]> Pileus Git - ~andy/gtk/blob - gtk/gtkimage.c
c92f7c69d7e844b7f78528275578e094e6fc52e0
[~andy/gtk] / gtk / gtkimage.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28 #include <math.h>
29 #include <string.h>
30
31 #include "gtkcontainer.h"
32 #include "gtkimage.h"
33 #include "gtkiconfactory.h"
34 #include "gtkstock.h"
35 #include "gtkicontheme.h"
36 #include "gtkintl.h"
37 #include "gtkprivate.h"
38 #include "gtkalias.h"
39
40 /**
41  * SECTION:gtkimage
42  * @Short_description: A widget displaying an image
43  * @Title: GtkImage
44  * @See_also:#GdkPixbuf
45  *
46  * The #GtkImage widget displays an image. Various kinds of object
47  * can be displayed as an image; most typically, you would load a
48  * #GdkPixbuf ("pixel buffer") from a file, and then display that.
49  * There's a convenience function to do this, gtk_image_new_from_file(),
50  * used as follows:
51  * <informalexample><programlisting>
52  *   GtkWidget *image;
53  *   image = gtk_image_new_from_file ("myfile.png");
54  * </programlisting></informalexample>
55  * If the file isn't loaded successfully, the image will contain a
56  * "broken image" icon similar to that used in many web browsers.
57  * If you want to handle errors in loading the file yourself,
58  * for example by displaying an error message, then load the image with
59  * gdk_pixbuf_new_from_file(), then create the #GtkImage with
60  * gtk_image_new_from_pixbuf().
61  *
62  * The image file may contain an animation, if so the #GtkImage will
63  * display an animation (#GdkPixbufAnimation) instead of a static image.
64  *
65  * #GtkImage is a subclass of #GtkMisc, which implies that you can
66  * align it (center, left, right) and add padding to it, using
67  * #GtkMisc methods.
68  *
69  * #GtkImage is a "no window" widget (has no #GdkWindow of its own),
70  * so by default does not receive events. If you want to receive events
71  * on the image, such as button clicks, place the image inside a
72  * #GtkEventBox, then connect to the event signals on the event box.
73  * <example>
74  * <title>Handling button press events on a
75  * <structname>GtkImage</structname>.</title>
76  * <programlisting>
77  *   static gboolean
78  *   button_press_callback (GtkWidget      *event_box,
79  *                          GdkEventButton *event,
80  *                          gpointer        data)
81  *   {
82  *     g_print ("Event box clicked at coordinates &percnt;f,&percnt;f\n",
83  *              event->x, event->y);
84  *
85  *     /<!---->* Returning TRUE means we handled the event, so the signal
86  *      * emission should be stopped (don't call any further
87  *      * callbacks that may be connected). Return FALSE
88  *      * to continue invoking callbacks.
89  *      *<!---->/
90  *     return TRUE;
91  *   }
92  *
93  *   static GtkWidget*
94  *   create_image (void)
95  *   {
96  *     GtkWidget *image;
97  *     GtkWidget *event_box;
98  *
99  *     image = gtk_image_new_from_file ("myfile.png");
100  *
101  *     event_box = gtk_event_box_new (<!-- -->);
102  *
103  *     gtk_container_add (GTK_CONTAINER (event_box), image);
104  *
105  *     g_signal_connect (G_OBJECT (event_box),
106  *                       "button_press_event",
107  *                       G_CALLBACK (button_press_callback),
108  *                       image);
109  *
110  *     return image;
111  *   }
112  * </programlisting>
113  * </example>
114  *
115  * When handling events on the event box, keep in mind that coordinates
116  * in the image may be different from event box coordinates due to
117  * the alignment and padding settings on the image (see #GtkMisc).
118  * The simplest way to solve this is to set the alignment to 0.0
119  * (left/top), and set the padding to zero. Then the origin of
120  * the image will be the same as the origin of the event box.
121  *
122  * Sometimes an application will want to avoid depending on external data
123  * files, such as image files. GTK+ comes with a program to avoid this,
124  * called <application>gdk-pixbuf-csource</application>. This program
125  * allows you to convert an image into a C variable declaration, which
126  * can then be loaded into a #GdkPixbuf using
127  * gdk_pixbuf_new_from_inline().
128  */
129
130 typedef struct _GtkImagePrivate GtkImagePrivate;
131
132 struct _GtkImagePrivate
133 {
134   /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
135   gchar *filename;
136
137   gint pixel_size;
138   guint need_calc_size : 1;
139 };
140
141 #define GTK_IMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_IMAGE, GtkImagePrivate))
142
143
144 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
145 static gint gtk_image_expose       (GtkWidget      *widget,
146                                     GdkEventExpose *event);
147 static void gtk_image_unmap        (GtkWidget      *widget);
148 static void gtk_image_unrealize    (GtkWidget      *widget);
149 static void gtk_image_size_request (GtkWidget      *widget,
150                                     GtkRequisition *requisition);
151 static void gtk_image_style_set    (GtkWidget      *widget,
152                                     GtkStyle       *prev_style);
153 static void gtk_image_screen_changed (GtkWidget    *widget,
154                                       GdkScreen    *prev_screen);
155 static void gtk_image_destroy      (GtkObject      *object);
156 static void gtk_image_reset        (GtkImage       *image);
157 static void gtk_image_calc_size    (GtkImage       *image);
158
159 static void gtk_image_update_size  (GtkImage       *image,
160                                     gint            image_width,
161                                     gint            image_height);
162
163 static void gtk_image_set_property      (GObject          *object,
164                                          guint             prop_id,
165                                          const GValue     *value,
166                                          GParamSpec       *pspec);
167 static void gtk_image_get_property      (GObject          *object,
168                                          guint             prop_id,
169                                          GValue           *value,
170                                          GParamSpec       *pspec);
171
172 static void icon_theme_changed          (GtkImage         *image);
173
174 enum
175 {
176   PROP_0,
177   PROP_PIXBUF,
178   PROP_PIXMAP,
179   PROP_IMAGE,
180   PROP_MASK,
181   PROP_FILE,
182   PROP_STOCK,
183   PROP_ICON_SET,
184   PROP_ICON_SIZE,
185   PROP_PIXEL_SIZE,
186   PROP_PIXBUF_ANIMATION,
187   PROP_ICON_NAME,
188   PROP_STORAGE_TYPE,
189   PROP_GICON
190 };
191
192 G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_MISC)
193
194 static void
195 gtk_image_class_init (GtkImageClass *class)
196 {
197   GObjectClass *gobject_class;
198   GtkObjectClass *object_class;
199   GtkWidgetClass *widget_class;
200
201   gobject_class = G_OBJECT_CLASS (class);
202   
203   gobject_class->set_property = gtk_image_set_property;
204   gobject_class->get_property = gtk_image_get_property;
205   
206   object_class = GTK_OBJECT_CLASS (class);
207   
208   object_class->destroy = gtk_image_destroy;
209
210   widget_class = GTK_WIDGET_CLASS (class);
211   
212   widget_class->expose_event = gtk_image_expose;
213   widget_class->size_request = gtk_image_size_request;
214   widget_class->unmap = gtk_image_unmap;
215   widget_class->unrealize = gtk_image_unrealize;
216   widget_class->style_set = gtk_image_style_set;
217   widget_class->screen_changed = gtk_image_screen_changed;
218   
219   g_object_class_install_property (gobject_class,
220                                    PROP_PIXBUF,
221                                    g_param_spec_object ("pixbuf",
222                                                         P_("Pixbuf"),
223                                                         P_("A GdkPixbuf to display"),
224                                                         GDK_TYPE_PIXBUF,
225                                                         GTK_PARAM_READWRITE));
226
227   g_object_class_install_property (gobject_class,
228                                    PROP_PIXMAP,
229                                    g_param_spec_object ("pixmap",
230                                                         P_("Pixmap"),
231                                                         P_("A GdkPixmap to display"),
232                                                         GDK_TYPE_PIXMAP,
233                                                         GTK_PARAM_READWRITE));
234
235   g_object_class_install_property (gobject_class,
236                                    PROP_IMAGE,
237                                    g_param_spec_object ("image",
238                                                         P_("Image"),
239                                                         P_("A GdkImage to display"),
240                                                         GDK_TYPE_IMAGE,
241                                                         GTK_PARAM_READWRITE));
242
243   g_object_class_install_property (gobject_class,
244                                    PROP_MASK,
245                                    g_param_spec_object ("mask",
246                                                         P_("Mask"),
247                                                         P_("Mask bitmap to use with GdkImage or GdkPixmap"),
248                                                         GDK_TYPE_PIXMAP,
249                                                         GTK_PARAM_READWRITE));
250   
251   g_object_class_install_property (gobject_class,
252                                    PROP_FILE,
253                                    g_param_spec_string ("file",
254                                                         P_("Filename"),
255                                                         P_("Filename to load and display"),
256                                                         NULL,
257                                                         GTK_PARAM_READWRITE));
258   
259
260   g_object_class_install_property (gobject_class,
261                                    PROP_STOCK,
262                                    g_param_spec_string ("stock",
263                                                         P_("Stock ID"),
264                                                         P_("Stock ID for a stock image to display"),
265                                                         NULL,
266                                                         GTK_PARAM_READWRITE));
267   
268   g_object_class_install_property (gobject_class,
269                                    PROP_ICON_SET,
270                                    g_param_spec_boxed ("icon-set",
271                                                        P_("Icon set"),
272                                                        P_("Icon set to display"),
273                                                        GTK_TYPE_ICON_SET,
274                                                        GTK_PARAM_READWRITE));
275   
276   g_object_class_install_property (gobject_class,
277                                    PROP_ICON_SIZE,
278                                    g_param_spec_int ("icon-size",
279                                                      P_("Icon size"),
280                                                      P_("Symbolic size to use for stock icon, icon set or named icon"),
281                                                      0, G_MAXINT,
282                                                      DEFAULT_ICON_SIZE,
283                                                      GTK_PARAM_READWRITE));
284   /**
285    * GtkImage:pixel-size:
286    *
287    * The "pixel-size" property can be used to specify a fixed size
288    * overriding the #GtkImage:icon-size property for images of type 
289    * %GTK_IMAGE_ICON_NAME. 
290    *
291    * Since: 2.6
292    */
293   g_object_class_install_property (gobject_class,
294                                    PROP_PIXEL_SIZE,
295                                    g_param_spec_int ("pixel-size",
296                                                      P_("Pixel size"),
297                                                      P_("Pixel size to use for named icon"),
298                                                      -1, G_MAXINT,
299                                                      -1,
300                                                      GTK_PARAM_READWRITE));
301   
302   g_object_class_install_property (gobject_class,
303                                    PROP_PIXBUF_ANIMATION,
304                                    g_param_spec_object ("pixbuf-animation",
305                                                         P_("Animation"),
306                                                         P_("GdkPixbufAnimation to display"),
307                                                         GDK_TYPE_PIXBUF_ANIMATION,
308                                                         GTK_PARAM_READWRITE));
309
310   /**
311    * GtkImage:icon-name:
312    *
313    * The name of the icon in the icon theme. If the icon theme is
314    * changed, the image will be updated automatically.
315    *
316    * Since: 2.6
317    */
318   g_object_class_install_property (gobject_class,
319                                    PROP_ICON_NAME,
320                                    g_param_spec_string ("icon-name",
321                                                         P_("Icon Name"),
322                                                         P_("The name of the icon from the icon theme"),
323                                                         NULL,
324                                                         GTK_PARAM_READWRITE));
325   
326   /**
327    * GtkImage:gicon:
328    *
329    * The GIcon displayed in the GtkImage. For themed icons,
330    * If the icon theme is changed, the image will be updated
331    * automatically.
332    *
333    * Since: 2.14
334    */
335   g_object_class_install_property (gobject_class,
336                                    PROP_GICON,
337                                    g_param_spec_object ("gicon",
338                                                         P_("Icon"),
339                                                         P_("The GIcon being displayed"),
340                                                         G_TYPE_ICON,
341                                                         GTK_PARAM_READWRITE));
342   
343   g_object_class_install_property (gobject_class,
344                                    PROP_STORAGE_TYPE,
345                                    g_param_spec_enum ("storage-type",
346                                                       P_("Storage type"),
347                                                       P_("The representation being used for image data"),
348                                                       GTK_TYPE_IMAGE_TYPE,
349                                                       GTK_IMAGE_EMPTY,
350                                                       GTK_PARAM_READABLE));
351
352   g_type_class_add_private (object_class, sizeof (GtkImagePrivate));
353 }
354
355 static void
356 gtk_image_init (GtkImage *image)
357 {
358   GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image);
359
360   GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
361
362   image->storage_type = GTK_IMAGE_EMPTY;
363   image->icon_size = DEFAULT_ICON_SIZE;
364   image->mask = NULL;
365
366   priv->pixel_size = -1;
367
368   priv->filename = NULL;
369 }
370
371 static void
372 gtk_image_destroy (GtkObject *object)
373 {
374   GtkImage *image = GTK_IMAGE (object);
375
376   gtk_image_reset (image);
377   
378   GTK_OBJECT_CLASS (gtk_image_parent_class)->destroy (object);
379 }
380
381 static void 
382 gtk_image_set_property (GObject      *object,
383                         guint         prop_id,
384                         const GValue *value,
385                         GParamSpec   *pspec)
386 {
387   GtkImage *image;
388
389   image = GTK_IMAGE (object);
390   
391   switch (prop_id)
392     {
393     case PROP_PIXBUF:
394       gtk_image_set_from_pixbuf (image,
395                                  g_value_get_object (value));
396       break;
397     case PROP_PIXMAP:
398       gtk_image_set_from_pixmap (image,
399                                  g_value_get_object (value),
400                                  image->mask);
401       break;
402     case PROP_IMAGE:
403       gtk_image_set_from_image (image,
404                                 g_value_get_object (value),
405                                 image->mask);
406       break;
407     case PROP_MASK:
408       if (image->storage_type == GTK_IMAGE_PIXMAP)
409         gtk_image_set_from_pixmap (image,
410                                    image->data.pixmap.pixmap,
411                                    g_value_get_object (value));
412       else if (image->storage_type == GTK_IMAGE_IMAGE)
413         gtk_image_set_from_image (image,
414                                   image->data.image.image,
415                                   g_value_get_object (value));
416       else
417         {
418           GdkBitmap *mask;
419
420           mask = g_value_get_object (value);
421
422           if (mask)
423             g_object_ref (mask);
424           
425           gtk_image_clear (image);
426
427           image->mask = mask;
428         }
429       break;
430     case PROP_FILE:
431       gtk_image_set_from_file (image, g_value_get_string (value));
432       break;
433     case PROP_STOCK:
434       gtk_image_set_from_stock (image, g_value_get_string (value),
435                                 image->icon_size);
436       break;
437     case PROP_ICON_SET:
438       gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
439                                    image->icon_size);
440       break;
441     case PROP_ICON_SIZE:
442       if (image->storage_type == GTK_IMAGE_STOCK)
443         gtk_image_set_from_stock (image,
444                                   image->data.stock.stock_id,
445                                   g_value_get_int (value));
446       else if (image->storage_type == GTK_IMAGE_ICON_SET)
447         gtk_image_set_from_icon_set (image,
448                                      image->data.icon_set.icon_set,
449                                      g_value_get_int (value));
450       else if (image->storage_type == GTK_IMAGE_ICON_NAME)
451         gtk_image_set_from_icon_name (image,
452                                       image->data.name.icon_name,
453                                       g_value_get_int (value));
454       else if (image->storage_type == GTK_IMAGE_GICON)
455         gtk_image_set_from_gicon (image,
456                                   image->data.gicon.icon,
457                                   g_value_get_int (value));
458       else
459         /* Save to be used when STOCK, ICON_SET, ICON_NAME or GICON property comes in */
460         image->icon_size = g_value_get_int (value);
461       break;
462     case PROP_PIXEL_SIZE:
463       gtk_image_set_pixel_size (image, g_value_get_int (value));
464       break;
465     case PROP_PIXBUF_ANIMATION:
466       gtk_image_set_from_animation (image,
467                                     g_value_get_object (value));
468       break;
469     case PROP_ICON_NAME:
470       gtk_image_set_from_icon_name (image, g_value_get_string (value),
471                                     image->icon_size);
472       break;
473     case PROP_GICON:
474       gtk_image_set_from_gicon (image, g_value_get_object (value),
475                                 image->icon_size);
476       break;
477
478     default:
479       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
480       break;
481     }
482 }
483
484 static void 
485 gtk_image_get_property (GObject     *object,
486                         guint        prop_id,
487                         GValue      *value,
488                         GParamSpec  *pspec)
489 {
490   GtkImage *image;
491   GtkImagePrivate *priv;
492
493   image = GTK_IMAGE (object);
494   priv = GTK_IMAGE_GET_PRIVATE (image);
495
496   /* The "getter" functions whine if you try to get the wrong
497    * storage type. This function is instead robust against that,
498    * so that GUI builders don't have to jump through hoops
499    * to avoid g_warning
500    */
501   
502   switch (prop_id)
503     {
504     case PROP_PIXBUF:
505       if (image->storage_type != GTK_IMAGE_PIXBUF)
506         g_value_set_object (value, NULL);
507       else
508         g_value_set_object (value,
509                             gtk_image_get_pixbuf (image));
510       break;
511     case PROP_PIXMAP:
512       if (image->storage_type != GTK_IMAGE_PIXMAP)
513         g_value_set_object (value, NULL);
514       else
515         g_value_set_object (value,
516                             image->data.pixmap.pixmap);
517       break;
518     case PROP_MASK:
519       g_value_set_object (value, image->mask);
520       break;
521     case PROP_IMAGE:
522       if (image->storage_type != GTK_IMAGE_IMAGE)
523         g_value_set_object (value, NULL);
524       else
525         g_value_set_object (value,
526                             image->data.image.image);
527       break;
528     case PROP_FILE:
529       g_value_set_string (value, priv->filename);
530       break;
531     case PROP_STOCK:
532       if (image->storage_type != GTK_IMAGE_STOCK)
533         g_value_set_string (value, NULL);
534       else
535         g_value_set_string (value,
536                             image->data.stock.stock_id);
537       break;
538     case PROP_ICON_SET:
539       if (image->storage_type != GTK_IMAGE_ICON_SET)
540         g_value_set_boxed (value, NULL);
541       else
542         g_value_set_boxed (value,
543                            image->data.icon_set.icon_set);
544       break;      
545     case PROP_ICON_SIZE:
546       g_value_set_int (value, image->icon_size);
547       break;
548     case PROP_PIXEL_SIZE:
549       g_value_set_int (value, priv->pixel_size);
550       break;
551     case PROP_PIXBUF_ANIMATION:
552       if (image->storage_type != GTK_IMAGE_ANIMATION)
553         g_value_set_object (value, NULL);
554       else
555         g_value_set_object (value,
556                             image->data.anim.anim);
557       break;
558     case PROP_ICON_NAME:
559       if (image->storage_type != GTK_IMAGE_ICON_NAME)
560         g_value_set_string (value, NULL);
561       else
562         g_value_set_string (value,
563                             image->data.name.icon_name);
564       break;
565     case PROP_GICON:
566       if (image->storage_type != GTK_IMAGE_GICON)
567         g_value_set_object (value, NULL);
568       else
569         g_value_set_object (value,
570                             image->data.gicon.icon);
571       break;
572     case PROP_STORAGE_TYPE:
573       g_value_set_enum (value, image->storage_type);
574       break;
575       
576     default:
577       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
578       break;
579     }
580 }
581
582
583 /**
584  * gtk_image_new_from_pixmap:
585  * @pixmap: (allow-none): a #GdkPixmap, or %NULL
586  * @mask: (allow-none): a #GdkBitmap, or %NULL
587  *
588  * Creates a #GtkImage widget displaying @pixmap with a @mask.
589  * A #GdkPixmap is a server-side image buffer in the pixel format of the
590  * current display. The #GtkImage does not assume a reference to the
591  * pixmap or mask; you still need to unref them if you own references.
592  * #GtkImage will add its own reference rather than adopting yours.
593  * 
594  * Return value: a new #GtkImage
595  **/
596 GtkWidget*
597 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
598                            GdkBitmap *mask)
599 {
600   GtkImage *image;
601
602   image = g_object_new (GTK_TYPE_IMAGE, NULL);
603
604   gtk_image_set_from_pixmap (image, pixmap, mask);
605
606   return GTK_WIDGET (image);
607 }
608
609 /**
610  * gtk_image_new_from_image:
611  * @image: (allow-none): a #GdkImage, or %NULL
612  * @mask: (allow-none): a #GdkBitmap, or %NULL
613  *
614  * Creates a #GtkImage widget displaying a @image with a @mask.
615  * A #GdkImage is a client-side image buffer in the pixel format of the
616  * current display. The #GtkImage does not assume a reference to the
617  * image or mask; you still need to unref them if you own references.
618  * #GtkImage will add its own reference rather than adopting yours.
619  * 
620  * Return value: a new #GtkImage
621  **/
622 GtkWidget*
623 gtk_image_new_from_image  (GdkImage  *gdk_image,
624                            GdkBitmap *mask)
625 {
626   GtkImage *image;
627
628   image = g_object_new (GTK_TYPE_IMAGE, NULL);
629
630   gtk_image_set_from_image (image, gdk_image, mask);
631
632   return GTK_WIDGET (image);
633 }
634
635 /**
636  * gtk_image_new_from_file:
637  * @filename: a filename
638  * 
639  * Creates a new #GtkImage displaying the file @filename. If the file
640  * isn't found or can't be loaded, the resulting #GtkImage will
641  * display a "broken image" icon. This function never returns %NULL,
642  * it always returns a valid #GtkImage widget.
643  *
644  * If the file contains an animation, the image will contain an
645  * animation.
646  *
647  * If you need to detect failures to load the file, use
648  * gdk_pixbuf_new_from_file() to load the file yourself, then create
649  * the #GtkImage from the pixbuf. (Or for animations, use
650  * gdk_pixbuf_animation_new_from_file()).
651  *
652  * The storage type (gtk_image_get_storage_type()) of the returned
653  * image is not defined, it will be whatever is appropriate for
654  * displaying the file.
655  * 
656  * Return value: a new #GtkImage
657  **/
658 GtkWidget*
659 gtk_image_new_from_file   (const gchar *filename)
660 {
661   GtkImage *image;
662
663   image = g_object_new (GTK_TYPE_IMAGE, NULL);
664
665   gtk_image_set_from_file (image, filename);
666
667   return GTK_WIDGET (image);
668 }
669
670 /**
671  * gtk_image_new_from_pixbuf:
672  * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
673  *
674  * Creates a new #GtkImage displaying @pixbuf.
675  * The #GtkImage does not assume a reference to the
676  * pixbuf; you still need to unref it if you own references.
677  * #GtkImage will add its own reference rather than adopting yours.
678  * 
679  * Note that this function just creates an #GtkImage from the pixbuf. The
680  * #GtkImage created will not react to state changes. Should you want that, 
681  * you should use gtk_image_new_from_icon_set().
682  * 
683  * Return value: a new #GtkImage
684  **/
685 GtkWidget*
686 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
687 {
688   GtkImage *image;
689
690   image = g_object_new (GTK_TYPE_IMAGE, NULL);
691
692   gtk_image_set_from_pixbuf (image, pixbuf);
693
694   return GTK_WIDGET (image);  
695 }
696
697 /**
698  * gtk_image_new_from_stock:
699  * @stock_id: a stock icon name
700  * @size: (type int): a stock icon size
701  * 
702  * Creates a #GtkImage displaying a stock icon. Sample stock icon
703  * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes
704  * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
705  * icon name isn't known, the image will be empty.
706  * You can register your own stock icon names, see
707  * gtk_icon_factory_add_default() and gtk_icon_factory_add().
708  * 
709  * Return value: a new #GtkImage displaying the stock icon
710  **/
711 GtkWidget*
712 gtk_image_new_from_stock (const gchar    *stock_id,
713                           GtkIconSize     size)
714 {
715   GtkImage *image;
716
717   image = g_object_new (GTK_TYPE_IMAGE, NULL);
718
719   gtk_image_set_from_stock (image, stock_id, size);
720
721   return GTK_WIDGET (image);
722 }
723
724 /**
725  * gtk_image_new_from_icon_set:
726  * @icon_set: a #GtkIconSet
727  * @size: (type int): a stock icon size
728  *
729  * Creates a #GtkImage displaying an icon set. Sample stock sizes are
730  * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
731  * this function, usually it's better to create a #GtkIconFactory, put
732  * your icon sets in the icon factory, add the icon factory to the
733  * list of default factories with gtk_icon_factory_add_default(), and
734  * then use gtk_image_new_from_stock(). This will allow themes to
735  * override the icon you ship with your application.
736  *
737  * The #GtkImage does not assume a reference to the
738  * icon set; you still need to unref it if you own references.
739  * #GtkImage will add its own reference rather than adopting yours.
740  * 
741  * Return value: a new #GtkImage
742  **/
743 GtkWidget*
744 gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
745                              GtkIconSize     size)
746 {
747   GtkImage *image;
748
749   image = g_object_new (GTK_TYPE_IMAGE, NULL);
750
751   gtk_image_set_from_icon_set (image, icon_set, size);
752
753   return GTK_WIDGET (image);
754 }
755
756 /**
757  * gtk_image_new_from_animation:
758  * @animation: an animation
759  * 
760  * Creates a #GtkImage displaying the given animation.
761  * The #GtkImage does not assume a reference to the
762  * animation; you still need to unref it if you own references.
763  * #GtkImage will add its own reference rather than adopting yours.
764  *
765  * Note that the animation frames are shown using a timeout with
766  * #G_PRIORITY_DEFAULT. When using animations to indicate busyness,
767  * keep in mind that the animation will only be shown if the main loop
768  * is not busy with something that has a higher priority.
769  *
770  * Return value: a new #GtkImage widget
771  **/
772 GtkWidget*
773 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
774 {
775   GtkImage *image;
776
777   g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
778   
779   image = g_object_new (GTK_TYPE_IMAGE, NULL);
780
781   gtk_image_set_from_animation (image, animation);
782
783   return GTK_WIDGET (image);
784 }
785
786 /**
787  * gtk_image_new_from_icon_name:
788  * @icon_name: an icon name
789  * @size: (type int): a stock icon size
790  * 
791  * Creates a #GtkImage displaying an icon from the current icon theme.
792  * If the icon name isn't known, a "broken image" icon will be
793  * displayed instead.  If the current icon theme is changed, the icon
794  * will be updated appropriately.
795  * 
796  * Return value: a new #GtkImage displaying the themed icon
797  *
798  * Since: 2.6
799  **/
800 GtkWidget*
801 gtk_image_new_from_icon_name (const gchar    *icon_name,
802                               GtkIconSize     size)
803 {
804   GtkImage *image;
805
806   image = g_object_new (GTK_TYPE_IMAGE, NULL);
807
808   gtk_image_set_from_icon_name (image, icon_name, size);
809
810   return GTK_WIDGET (image);
811 }
812
813 /**
814  * gtk_image_new_from_gicon:
815  * @icon: an icon
816  * @size: (type int): a stock icon size
817  * 
818  * Creates a #GtkImage displaying an icon from the current icon theme.
819  * If the icon name isn't known, a "broken image" icon will be
820  * displayed instead.  If the current icon theme is changed, the icon
821  * will be updated appropriately.
822  * 
823  * Return value: a new #GtkImage displaying the themed icon
824  *
825  * Since: 2.14
826  **/
827 GtkWidget*
828 gtk_image_new_from_gicon (GIcon *icon,
829                           GtkIconSize     size)
830 {
831   GtkImage *image;
832
833   image = g_object_new (GTK_TYPE_IMAGE, NULL);
834
835   gtk_image_set_from_gicon (image, icon, size);
836
837   return GTK_WIDGET (image);
838 }
839
840 /**
841  * gtk_image_set_from_pixmap:
842  * @image: a #GtkImage
843  * @pixmap: (allow-none): a #GdkPixmap or %NULL
844  * @mask: (allow-none): a #GdkBitmap or %NULL
845  *
846  * See gtk_image_new_from_pixmap() for details.
847  **/
848 void
849 gtk_image_set_from_pixmap (GtkImage  *image,
850                            GdkPixmap *pixmap,
851                            GdkBitmap *mask)
852 {
853   g_return_if_fail (GTK_IS_IMAGE (image));
854   g_return_if_fail (pixmap == NULL ||
855                     GDK_IS_PIXMAP (pixmap));
856   g_return_if_fail (mask == NULL ||
857                     GDK_IS_PIXMAP (mask));
858
859   g_object_freeze_notify (G_OBJECT (image));
860   
861   if (pixmap)
862     g_object_ref (pixmap);
863
864   if (mask)
865     g_object_ref (mask);
866
867   gtk_image_clear (image);
868
869   image->mask = mask;
870   
871   if (pixmap)
872     {
873       int width;
874       int height;
875       
876       image->storage_type = GTK_IMAGE_PIXMAP;
877
878       image->data.pixmap.pixmap = pixmap;
879
880       gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
881
882       gtk_image_update_size (image, width, height);
883     }
884
885   g_object_notify (G_OBJECT (image), "pixmap");
886   g_object_notify (G_OBJECT (image), "mask");
887   
888   g_object_thaw_notify (G_OBJECT (image));
889 }
890
891 /**
892  * gtk_image_set_from_image:
893  * @image: a #GtkImage
894  * @gdk_image: (allow-none): a #GdkImage or %NULL
895  * @mask:  (allow-none): a #GdkBitmap or %NULL
896  *
897  * See gtk_image_new_from_image() for details.
898  **/
899 void
900 gtk_image_set_from_image  (GtkImage  *image,
901                            GdkImage  *gdk_image,
902                            GdkBitmap *mask)
903 {
904   g_return_if_fail (GTK_IS_IMAGE (image));
905   g_return_if_fail (gdk_image == NULL ||
906                     GDK_IS_IMAGE (gdk_image));
907   g_return_if_fail (mask == NULL ||
908                     GDK_IS_PIXMAP (mask));
909
910   g_object_freeze_notify (G_OBJECT (image));
911   
912   if (gdk_image)
913     g_object_ref (gdk_image);
914
915   if (mask)
916     g_object_ref (mask);
917
918   gtk_image_clear (image);
919
920   if (gdk_image)
921     {
922       image->storage_type = GTK_IMAGE_IMAGE;
923
924       image->data.image.image = gdk_image;
925       image->mask = mask;
926
927       gtk_image_update_size (image, gdk_image->width, gdk_image->height);
928     }
929   else
930     {
931       /* Clean up the mask if gdk_image was NULL */
932       if (mask)
933         g_object_unref (mask);
934     }
935
936   g_object_notify (G_OBJECT (image), "image");
937   g_object_notify (G_OBJECT (image), "mask");
938   
939   g_object_thaw_notify (G_OBJECT (image));
940 }
941
942 /**
943  * gtk_image_set_from_file:
944  * @image: a #GtkImage
945  * @filename: (allow-none): a filename or %NULL
946  *
947  * See gtk_image_new_from_file() for details.
948  **/
949 void
950 gtk_image_set_from_file   (GtkImage    *image,
951                            const gchar *filename)
952 {
953   GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image);
954   GdkPixbufAnimation *anim;
955   
956   g_return_if_fail (GTK_IS_IMAGE (image));
957
958   g_object_freeze_notify (G_OBJECT (image));
959   
960   gtk_image_clear (image);
961
962   if (filename == NULL)
963     {
964       priv->filename = NULL;
965       g_object_thaw_notify (G_OBJECT (image));
966       return;
967     }
968
969   anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
970
971   if (anim == NULL)
972     {
973       gtk_image_set_from_stock (image,
974                                 GTK_STOCK_MISSING_IMAGE,
975                                 GTK_ICON_SIZE_BUTTON);
976       g_object_thaw_notify (G_OBJECT (image));
977       return;
978     }
979
980   /* We could just unconditionally set_from_animation,
981    * but it's nicer for memory if we toss the animation
982    * if it's just a single pixbuf
983    */
984
985   if (gdk_pixbuf_animation_is_static_image (anim))
986     gtk_image_set_from_pixbuf (image,
987                                gdk_pixbuf_animation_get_static_image (anim));
988   else
989     gtk_image_set_from_animation (image, anim);
990
991   g_object_unref (anim);
992
993   priv->filename = g_strdup (filename);
994   
995   g_object_thaw_notify (G_OBJECT (image));
996 }
997
998 /**
999  * gtk_image_set_from_pixbuf:
1000  * @image: a #GtkImage
1001  * @pixbuf: (allow-none): a #GdkPixbuf or %NULL
1002  *
1003  * See gtk_image_new_from_pixbuf() for details.
1004  **/
1005 void
1006 gtk_image_set_from_pixbuf (GtkImage  *image,
1007                            GdkPixbuf *pixbuf)
1008 {
1009   g_return_if_fail (GTK_IS_IMAGE (image));
1010   g_return_if_fail (pixbuf == NULL ||
1011                     GDK_IS_PIXBUF (pixbuf));
1012
1013   g_object_freeze_notify (G_OBJECT (image));
1014   
1015   if (pixbuf)
1016     g_object_ref (pixbuf);
1017
1018   gtk_image_clear (image);
1019
1020   if (pixbuf != NULL)
1021     {
1022       image->storage_type = GTK_IMAGE_PIXBUF;
1023
1024       image->data.pixbuf.pixbuf = pixbuf;
1025
1026       gtk_image_update_size (image,
1027                              gdk_pixbuf_get_width (pixbuf),
1028                              gdk_pixbuf_get_height (pixbuf));
1029     }
1030
1031   g_object_notify (G_OBJECT (image), "pixbuf");
1032   
1033   g_object_thaw_notify (G_OBJECT (image));
1034 }
1035
1036 /**
1037  * gtk_image_set_from_stock:
1038  * @image: a #GtkImage
1039  * @stock_id: a stock icon name
1040  * @size: (type int): a stock icon size
1041  *
1042  * See gtk_image_new_from_stock() for details.
1043  **/
1044 void
1045 gtk_image_set_from_stock  (GtkImage       *image,
1046                            const gchar    *stock_id,
1047                            GtkIconSize     size)
1048 {
1049   gchar *new_id;
1050   
1051   g_return_if_fail (GTK_IS_IMAGE (image));
1052
1053   g_object_freeze_notify (G_OBJECT (image));
1054
1055   /* in case stock_id == image->data.stock.stock_id */
1056   new_id = g_strdup (stock_id);
1057   
1058   gtk_image_clear (image);
1059
1060   if (new_id)
1061     {
1062       image->storage_type = GTK_IMAGE_STOCK;
1063       
1064       image->data.stock.stock_id = new_id;
1065       image->icon_size = size;
1066
1067       /* Size is demand-computed in size request method
1068        * if we're a stock image, since changing the
1069        * style impacts the size request
1070        */
1071     }
1072
1073   g_object_notify (G_OBJECT (image), "stock");
1074   g_object_notify (G_OBJECT (image), "icon-size");
1075   
1076   g_object_thaw_notify (G_OBJECT (image));
1077 }
1078
1079 /**
1080  * gtk_image_set_from_icon_set:
1081  * @image: a #GtkImage
1082  * @icon_set: a #GtkIconSet
1083  * @size: (type int): a stock icon size
1084  *
1085  * See gtk_image_new_from_icon_set() for details.
1086  **/
1087 void
1088 gtk_image_set_from_icon_set  (GtkImage       *image,
1089                               GtkIconSet     *icon_set,
1090                               GtkIconSize     size)
1091 {
1092   g_return_if_fail (GTK_IS_IMAGE (image));
1093
1094   g_object_freeze_notify (G_OBJECT (image));
1095   
1096   if (icon_set)
1097     gtk_icon_set_ref (icon_set);
1098   
1099   gtk_image_clear (image);
1100
1101   if (icon_set)
1102     {      
1103       image->storage_type = GTK_IMAGE_ICON_SET;
1104       
1105       image->data.icon_set.icon_set = icon_set;
1106       image->icon_size = size;
1107
1108       /* Size is demand-computed in size request method
1109        * if we're an icon set
1110        */
1111     }
1112   
1113   g_object_notify (G_OBJECT (image), "icon-set");
1114   g_object_notify (G_OBJECT (image), "icon-size");
1115   
1116   g_object_thaw_notify (G_OBJECT (image));
1117 }
1118
1119 /**
1120  * gtk_image_set_from_animation:
1121  * @image: a #GtkImage
1122  * @animation: the #GdkPixbufAnimation
1123  * 
1124  * Causes the #GtkImage to display the given animation (or display
1125  * nothing, if you set the animation to %NULL).
1126  **/
1127 void
1128 gtk_image_set_from_animation (GtkImage           *image,
1129                               GdkPixbufAnimation *animation)
1130 {
1131   g_return_if_fail (GTK_IS_IMAGE (image));
1132   g_return_if_fail (animation == NULL ||
1133                     GDK_IS_PIXBUF_ANIMATION (animation));
1134
1135   g_object_freeze_notify (G_OBJECT (image));
1136   
1137   if (animation)
1138     g_object_ref (animation);
1139
1140   gtk_image_clear (image);
1141
1142   if (animation != NULL)
1143     {
1144       image->storage_type = GTK_IMAGE_ANIMATION;
1145
1146       image->data.anim.anim = animation;
1147       image->data.anim.frame_timeout = 0;
1148       image->data.anim.iter = NULL;
1149       
1150       gtk_image_update_size (image,
1151                              gdk_pixbuf_animation_get_width (animation),
1152                              gdk_pixbuf_animation_get_height (animation));
1153     }
1154
1155   g_object_notify (G_OBJECT (image), "pixbuf-animation");
1156   
1157   g_object_thaw_notify (G_OBJECT (image));
1158 }
1159
1160 /**
1161  * gtk_image_set_from_icon_name:
1162  * @image: a #GtkImage
1163  * @icon_name: an icon name
1164  * @size: (type int): an icon size
1165  *
1166  * See gtk_image_new_from_icon_name() for details.
1167  * 
1168  * Since: 2.6
1169  **/
1170 void
1171 gtk_image_set_from_icon_name  (GtkImage       *image,
1172                                const gchar    *icon_name,
1173                                GtkIconSize     size)
1174 {
1175   gchar *new_name;
1176   
1177   g_return_if_fail (GTK_IS_IMAGE (image));
1178
1179   g_object_freeze_notify (G_OBJECT (image));
1180
1181   /* in case icon_name == image->data.name.icon_name */
1182   new_name = g_strdup (icon_name);
1183   
1184   gtk_image_clear (image);
1185
1186   if (new_name)
1187     {
1188       image->storage_type = GTK_IMAGE_ICON_NAME;
1189       
1190       image->data.name.icon_name = new_name;
1191       image->icon_size = size;
1192
1193       /* Size is demand-computed in size request method
1194        * if we're a icon theme image, since changing the
1195        * style impacts the size request
1196        */
1197     }
1198
1199   g_object_notify (G_OBJECT (image), "icon-name");
1200   g_object_notify (G_OBJECT (image), "icon-size");
1201   
1202   g_object_thaw_notify (G_OBJECT (image));
1203 }
1204
1205 /**
1206  * gtk_image_set_from_gicon:
1207  * @image: a #GtkImage
1208  * @icon: an icon
1209  * @size: (type int): an icon size
1210  *
1211  * See gtk_image_new_from_gicon() for details.
1212  * 
1213  * Since: 2.14
1214  **/
1215 void
1216 gtk_image_set_from_gicon  (GtkImage       *image,
1217                            GIcon          *icon,
1218                            GtkIconSize     size)
1219 {
1220   g_return_if_fail (GTK_IS_IMAGE (image));
1221
1222   g_object_freeze_notify (G_OBJECT (image));
1223
1224   /* in case icon == image->data.gicon.icon */
1225   if (icon)
1226     g_object_ref (icon);
1227   
1228   gtk_image_clear (image);
1229
1230   if (icon)
1231     {
1232       image->storage_type = GTK_IMAGE_GICON;
1233       
1234       image->data.gicon.icon = icon;
1235       image->icon_size = size;
1236
1237       /* Size is demand-computed in size request method
1238        * if we're a icon theme image, since changing the
1239        * style impacts the size request
1240        */
1241     }
1242
1243   g_object_notify (G_OBJECT (image), "gicon");
1244   g_object_notify (G_OBJECT (image), "icon-size");
1245   
1246   g_object_thaw_notify (G_OBJECT (image));
1247 }
1248
1249 /**
1250  * gtk_image_get_storage_type:
1251  * @image: a #GtkImage
1252  * 
1253  * Gets the type of representation being used by the #GtkImage
1254  * to store image data. If the #GtkImage has no image data,
1255  * the return value will be %GTK_IMAGE_EMPTY.
1256  * 
1257  * Return value: image representation being used
1258  **/
1259 GtkImageType
1260 gtk_image_get_storage_type (GtkImage *image)
1261 {
1262   g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
1263
1264   return image->storage_type;
1265 }
1266
1267 /**
1268  * gtk_image_get_pixmap:
1269  * @image: a #GtkImage
1270  * @pixmap: (out) (transfer none) (allow-none): location to store the
1271  *     pixmap, or %NULL
1272  * @mask: (out) (transfer none) (allow-none): location to store the
1273  *     mask, or %NULL
1274  *
1275  * Gets the pixmap and mask being displayed by the #GtkImage.
1276  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1277  * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
1278  * The caller of this function does not own a reference to the
1279  * returned pixmap and mask.
1280  **/
1281 void
1282 gtk_image_get_pixmap (GtkImage   *image,
1283                       GdkPixmap **pixmap,
1284                       GdkBitmap **mask)
1285 {
1286   g_return_if_fail (GTK_IS_IMAGE (image)); 
1287   g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
1288                     image->storage_type == GTK_IMAGE_EMPTY);
1289   
1290   if (pixmap)
1291     *pixmap = image->data.pixmap.pixmap;
1292   
1293   if (mask)
1294     *mask = image->mask;
1295 }
1296
1297 /**
1298  * gtk_image_get_image:
1299  * @image: a #GtkImage
1300  * @gdk_image: (out) (transfer none) (allow-none): return location for
1301  *     a #GtkImage, or %NULL
1302  * @mask: (out) (transfer none) (allow-none): return location for a
1303  *     #GdkBitmap, or %NULL
1304  * 
1305  * Gets the #GdkImage and mask being displayed by the #GtkImage.
1306  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1307  * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
1308  * The caller of this function does not own a reference to the
1309  * returned image and mask.
1310  **/
1311 void
1312 gtk_image_get_image  (GtkImage   *image,
1313                       GdkImage  **gdk_image,
1314                       GdkBitmap **mask)
1315 {
1316   g_return_if_fail (GTK_IS_IMAGE (image));
1317   g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
1318                     image->storage_type == GTK_IMAGE_EMPTY);
1319
1320   if (gdk_image)
1321     *gdk_image = image->data.image.image;
1322   
1323   if (mask)
1324     *mask = image->mask;
1325 }
1326
1327 /**
1328  * gtk_image_get_pixbuf:
1329  * @image: a #GtkImage
1330  *
1331  * Gets the #GdkPixbuf being displayed by the #GtkImage.
1332  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1333  * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1334  * The caller of this function does not own a reference to the
1335  * returned pixbuf.
1336  * 
1337  * Return value: (transfer none): the displayed pixbuf, or %NULL if
1338  * the image is empty
1339  **/
1340 GdkPixbuf*
1341 gtk_image_get_pixbuf (GtkImage *image)
1342 {
1343   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1344   g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1345                         image->storage_type == GTK_IMAGE_EMPTY, NULL);
1346
1347   if (image->storage_type == GTK_IMAGE_EMPTY)
1348     image->data.pixbuf.pixbuf = NULL;
1349   
1350   return image->data.pixbuf.pixbuf;
1351 }
1352
1353 /**
1354  * gtk_image_get_stock:
1355  * @image: a #GtkImage
1356  * @stock_id: (out) (transfer none) (allow-none): place to store a
1357  *     stock icon name, or %NULL
1358  * @size: (out) (allow-none) (type int): place to store a stock icon
1359  *     size, or %NULL
1360  *
1361  * Gets the stock icon name and size being displayed by the #GtkImage.
1362  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1363  * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1364  * The returned string is owned by the #GtkImage and should not
1365  * be freed.
1366  **/
1367 void
1368 gtk_image_get_stock  (GtkImage        *image,
1369                       gchar          **stock_id,
1370                       GtkIconSize     *size)
1371 {
1372   g_return_if_fail (GTK_IS_IMAGE (image));
1373   g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1374                     image->storage_type == GTK_IMAGE_EMPTY);
1375
1376   if (image->storage_type == GTK_IMAGE_EMPTY)
1377     image->data.stock.stock_id = NULL;
1378   
1379   if (stock_id)
1380     *stock_id = image->data.stock.stock_id;
1381
1382   if (size)
1383     *size = image->icon_size;
1384 }
1385
1386 /**
1387  * gtk_image_get_icon_set:
1388  * @image: a #GtkImage
1389  * @icon_set: (out) (transfer none) (allow-none): location to store a
1390  *     #GtkIconSet, or %NULL
1391  * @size: (out) (allow-none) (type int): location to store a stock
1392  *     icon size, or %NULL
1393  *
1394  * Gets the icon set and size being displayed by the #GtkImage.
1395  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1396  * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1397  **/
1398 void
1399 gtk_image_get_icon_set  (GtkImage        *image,
1400                          GtkIconSet     **icon_set,
1401                          GtkIconSize     *size)
1402 {
1403   g_return_if_fail (GTK_IS_IMAGE (image));
1404   g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1405                     image->storage_type == GTK_IMAGE_EMPTY);
1406       
1407   if (icon_set)    
1408     *icon_set = image->data.icon_set.icon_set;
1409
1410   if (size)
1411     *size = image->icon_size;
1412 }
1413
1414 /**
1415  * gtk_image_get_animation:
1416  * @image: a #GtkImage
1417  *
1418  * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1419  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1420  * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1421  * The caller of this function does not own a reference to the
1422  * returned animation.
1423  * 
1424  * Return value: (transfer none): the displayed animation, or %NULL if
1425  * the image is empty
1426  **/
1427 GdkPixbufAnimation*
1428 gtk_image_get_animation (GtkImage *image)
1429 {
1430   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1431   g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1432                         image->storage_type == GTK_IMAGE_EMPTY,
1433                         NULL);
1434
1435   if (image->storage_type == GTK_IMAGE_EMPTY)
1436     image->data.anim.anim = NULL;
1437   
1438   return image->data.anim.anim;
1439 }
1440
1441 /**
1442  * gtk_image_get_icon_name:
1443  * @image: a #GtkImage
1444  * @icon_name: (out) (transfer none) (allow-none): place to store an
1445  *     icon name, or %NULL
1446  * @size: (out) (allow-none) (type int): place to store an icon size,
1447  *     or %NULL
1448  *
1449  * Gets the icon name and size being displayed by the #GtkImage.
1450  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1451  * %GTK_IMAGE_ICON_NAME (see gtk_image_get_storage_type()).
1452  * The returned string is owned by the #GtkImage and should not
1453  * be freed.
1454  * 
1455  * Since: 2.6
1456  **/
1457 void
1458 gtk_image_get_icon_name  (GtkImage              *image,
1459                           G_CONST_RETURN gchar **icon_name,
1460                           GtkIconSize           *size)
1461 {
1462   g_return_if_fail (GTK_IS_IMAGE (image));
1463   g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME ||
1464                     image->storage_type == GTK_IMAGE_EMPTY);
1465
1466   if (image->storage_type == GTK_IMAGE_EMPTY)
1467     image->data.name.icon_name = NULL;
1468   
1469   if (icon_name)
1470     *icon_name = image->data.name.icon_name;
1471
1472   if (size)
1473     *size = image->icon_size;
1474 }
1475
1476 /**
1477  * gtk_image_get_gicon:
1478  * @image: a #GtkImage
1479  * @gicon: (out) (transfer none) (allow-none): place to store a
1480  *     #GIcon, or %NULL
1481  * @size: (out) (allow-none) (type int): place to store an icon size,
1482  *     or %NULL
1483  *
1484  * Gets the #GIcon and size being displayed by the #GtkImage.
1485  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1486  * %GTK_IMAGE_GICON (see gtk_image_get_storage_type()).
1487  * The caller of this function does not own a reference to the
1488  * returned #GIcon.
1489  * 
1490  * Since: 2.14
1491  **/
1492 void
1493 gtk_image_get_gicon (GtkImage     *image,
1494                      GIcon       **gicon,
1495                      GtkIconSize  *size)
1496 {
1497   g_return_if_fail (GTK_IS_IMAGE (image));
1498   g_return_if_fail (image->storage_type == GTK_IMAGE_GICON ||
1499                     image->storage_type == GTK_IMAGE_EMPTY);
1500
1501   if (image->storage_type == GTK_IMAGE_EMPTY)
1502     image->data.gicon.icon = NULL;
1503   
1504   if (gicon)
1505     *gicon = image->data.gicon.icon;
1506
1507   if (size)
1508     *size = image->icon_size;
1509 }
1510
1511 /**
1512  * gtk_image_new:
1513  * 
1514  * Creates a new empty #GtkImage widget.
1515  * 
1516  * Return value: a newly created #GtkImage widget. 
1517  **/
1518 GtkWidget*
1519 gtk_image_new (void)
1520 {
1521   return g_object_new (GTK_TYPE_IMAGE, NULL);
1522 }
1523
1524 /**
1525  * gtk_image_set:
1526  * @image: a #GtkImage
1527  * @val: a #GdkImage
1528  * @mask: a #GdkBitmap that indicates which parts of the image should be transparent.
1529  *
1530  * Sets the #GtkImage.
1531  *
1532  * Deprecated: 2.0: Use gtk_image_set_from_image() instead.
1533  */
1534 void
1535 gtk_image_set (GtkImage  *image,
1536                GdkImage  *val,
1537                GdkBitmap *mask)
1538 {
1539   g_return_if_fail (GTK_IS_IMAGE (image));
1540
1541   gtk_image_set_from_image (image, val, mask);
1542 }
1543
1544 /**
1545  * gtk_image_get:
1546  * @image: a #GtkImage
1547  * @val: return location for a #GdkImage
1548  * @mask: a #GdkBitmap that indicates which parts of the image should be transparent.
1549  *
1550  * Gets the #GtkImage.
1551  *
1552  * Deprecated: 2.0: Use gtk_image_get_image() instead.
1553  */
1554 void
1555 gtk_image_get (GtkImage   *image,
1556                GdkImage  **val,
1557                GdkBitmap **mask)
1558 {
1559   g_return_if_fail (GTK_IS_IMAGE (image));
1560
1561   gtk_image_get_image (image, val, mask);
1562 }
1563
1564 static void
1565 gtk_image_reset_anim_iter (GtkImage *image)
1566 {
1567   if (image->storage_type == GTK_IMAGE_ANIMATION)
1568     {
1569       /* Reset the animation */
1570       
1571       if (image->data.anim.frame_timeout)
1572         {
1573           g_source_remove (image->data.anim.frame_timeout);
1574           image->data.anim.frame_timeout = 0;
1575         }
1576
1577       if (image->data.anim.iter)
1578         {
1579           g_object_unref (image->data.anim.iter);
1580           image->data.anim.iter = NULL;
1581         }
1582     }
1583 }
1584
1585 static void
1586 gtk_image_unmap (GtkWidget *widget)
1587 {
1588   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1589
1590   GTK_WIDGET_CLASS (gtk_image_parent_class)->unmap (widget);
1591 }
1592
1593 static void
1594 gtk_image_unrealize (GtkWidget *widget)
1595 {
1596   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1597
1598   GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget);
1599 }
1600
1601 static gint
1602 animation_timeout (gpointer data)
1603 {
1604   GtkImage *image;
1605   int delay;
1606
1607   image = GTK_IMAGE (data);
1608   
1609   image->data.anim.frame_timeout = 0;
1610
1611   gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1612
1613   delay = gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter);
1614   if (delay >= 0)
1615     {
1616       image->data.anim.frame_timeout =
1617         gdk_threads_add_timeout (delay, animation_timeout, image);
1618
1619       gtk_widget_queue_draw (GTK_WIDGET (image));
1620
1621       if (gtk_widget_is_drawable (GTK_WIDGET (image)))
1622         gdk_window_process_updates (GTK_WIDGET (image)->window, TRUE);
1623     }
1624
1625   return FALSE;
1626 }
1627
1628 static void
1629 icon_theme_changed (GtkImage *image)
1630 {
1631   if (image->storage_type == GTK_IMAGE_ICON_NAME) 
1632     {
1633       if (image->data.name.pixbuf)
1634         g_object_unref (image->data.name.pixbuf);
1635       image->data.name.pixbuf = NULL;
1636
1637       gtk_widget_queue_draw (GTK_WIDGET (image));
1638     }
1639   if (image->storage_type == GTK_IMAGE_GICON) 
1640     {
1641       if (image->data.gicon.pixbuf)
1642         g_object_unref (image->data.gicon.pixbuf);
1643       image->data.gicon.pixbuf = NULL;
1644
1645       gtk_widget_queue_draw (GTK_WIDGET (image));
1646     }
1647 }
1648
1649 static void
1650 ensure_pixbuf_for_icon_name (GtkImage *image)
1651 {
1652   GtkImagePrivate *priv;
1653   GdkScreen *screen;
1654   GtkIconTheme *icon_theme;
1655   GtkSettings *settings;
1656   gint width, height;
1657   gint *sizes, *s, dist;
1658   GtkIconLookupFlags flags;
1659   GError *error = NULL;
1660
1661   g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME);
1662
1663   priv = GTK_IMAGE_GET_PRIVATE (image);
1664   screen = gtk_widget_get_screen (GTK_WIDGET (image));
1665   icon_theme = gtk_icon_theme_get_for_screen (screen);
1666   settings = gtk_settings_get_for_screen (screen);
1667   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
1668   if (image->data.name.pixbuf == NULL)
1669     {
1670       if (priv->pixel_size != -1)
1671         {
1672           width = height = priv->pixel_size;
1673           flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
1674         }
1675       else if (!gtk_icon_size_lookup_for_settings (settings,
1676                                                    image->icon_size,
1677                                                    &width, &height))
1678         {
1679           if (image->icon_size == -1)
1680             {
1681               /* Find an available size close to 48 */
1682               sizes = gtk_icon_theme_get_icon_sizes (icon_theme, image->data.name.icon_name);
1683               dist = 100;
1684               width = height = 48;
1685               for (s = sizes; *s; s++)
1686                 {
1687                   if (*s == -1)
1688                     {
1689                       width = height = 48;
1690                       break;
1691                     }
1692                   if (*s < 48)
1693                     {
1694                       if (48 - *s < dist)
1695                         {
1696                           width = height = *s;
1697                           dist = 48 - *s;
1698                         }
1699                     }
1700                   else
1701                     {
1702                       if (*s - 48 < dist)
1703                         {
1704                           width = height = *s;
1705                           dist = *s - 48;
1706                         }
1707                     }
1708                 }
1709               g_free (sizes);
1710             }
1711           else
1712             {
1713               g_warning ("Invalid icon size %d\n", image->icon_size);
1714               width = height = 24;
1715             }
1716         }
1717       image->data.name.pixbuf =
1718         gtk_icon_theme_load_icon (icon_theme,
1719                                   image->data.name.icon_name,
1720                                   MIN (width, height), flags, &error);
1721       if (image->data.name.pixbuf == NULL)
1722         {
1723           g_error_free (error);
1724           image->data.name.pixbuf =
1725             gtk_widget_render_icon (GTK_WIDGET (image),
1726                                     GTK_STOCK_MISSING_IMAGE,
1727                                     image->icon_size,
1728                                     NULL);
1729         }
1730     }
1731 }
1732
1733 static void
1734 ensure_pixbuf_for_gicon (GtkImage *image)
1735 {
1736   GtkImagePrivate *priv;
1737   GdkScreen *screen;
1738   GtkIconTheme *icon_theme;
1739   GtkSettings *settings;
1740   gint width, height;
1741   GtkIconInfo *info;
1742   GtkIconLookupFlags flags;
1743
1744   g_return_if_fail (image->storage_type == GTK_IMAGE_GICON);
1745
1746   priv = GTK_IMAGE_GET_PRIVATE (image);
1747   screen = gtk_widget_get_screen (GTK_WIDGET (image));
1748   icon_theme = gtk_icon_theme_get_for_screen (screen);
1749   settings = gtk_settings_get_for_screen (screen);
1750   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
1751   if (image->data.gicon.pixbuf == NULL)
1752     {
1753       if (priv->pixel_size != -1)
1754         {
1755           width = height = priv->pixel_size;
1756           flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
1757         }
1758       else if (!gtk_icon_size_lookup_for_settings (settings,
1759                                                    image->icon_size,
1760                                                    &width, &height))
1761         {
1762           if (image->icon_size == -1)
1763             width = height = 48;
1764           else
1765             {
1766               g_warning ("Invalid icon size %d\n", image->icon_size);
1767               width = height = 24;
1768             }
1769         }
1770
1771       info = gtk_icon_theme_lookup_by_gicon (icon_theme,
1772                                              image->data.gicon.icon,
1773                                              MIN (width, height), flags);
1774       if (info)
1775         {
1776           image->data.gicon.pixbuf = gtk_icon_info_load_icon (info, NULL);
1777           gtk_icon_info_free (info);
1778         }
1779
1780       if (image->data.gicon.pixbuf == NULL)
1781         {
1782           image->data.gicon.pixbuf =
1783             gtk_widget_render_icon (GTK_WIDGET (image),
1784                                     GTK_STOCK_MISSING_IMAGE,
1785                                     image->icon_size,
1786                                     NULL);
1787         }
1788     }
1789 }
1790
1791
1792 /*
1793  * Like gdk_rectangle_intersect (dest, src, dest), but make 
1794  * sure that the origin of dest is moved by an "even" offset. 
1795  * If necessary grow the intersection by one row or column 
1796  * to achieve this.
1797  *
1798  * This is necessary since we can't pass alignment information
1799  * for the pixelation pattern down to gdk_pixbuf_saturate_and_pixelate(), 
1800  * thus we have to makesure that the subimages are properly aligned.
1801  */
1802 static gboolean
1803 rectangle_intersect_even (GdkRectangle *src, 
1804                           GdkRectangle *dest)
1805 {
1806   gboolean isect;
1807   gint x, y;
1808
1809   x = dest->x;
1810   y = dest->y;
1811   isect = gdk_rectangle_intersect (dest, src, dest);
1812
1813   if ((dest->x - x + dest->y - y) % 2 != 0)
1814     {
1815       if (dest->x > x)
1816         {
1817           dest->x--;
1818           dest->width++;
1819         }
1820       else
1821         {
1822           dest->y--;
1823           dest->height++;
1824         }
1825     }
1826   
1827   return isect;
1828 }
1829
1830 static gint
1831 gtk_image_expose (GtkWidget      *widget,
1832                   GdkEventExpose *event)
1833 {
1834   g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1835   g_return_val_if_fail (event != NULL, FALSE);
1836   
1837   if (GTK_WIDGET_MAPPED (widget) &&
1838       GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1839     {
1840       GtkImage *image;
1841       GtkMisc *misc;
1842       GtkImagePrivate *priv;
1843       GdkRectangle area, image_bound;
1844       gfloat xalign;
1845       gint x, y, mask_x, mask_y;
1846       GdkBitmap *mask;
1847       GdkPixbuf *pixbuf;
1848       gboolean needs_state_transform;
1849
1850       image = GTK_IMAGE (widget);
1851       misc = GTK_MISC (widget);
1852       priv = GTK_IMAGE_GET_PRIVATE (image);
1853
1854       area = event->area;
1855
1856       /* For stock items and icon sets, we lazily calculate
1857        * the size; we might get here between a queue_resize()
1858        * and size_request() if something explicitely forces
1859        * a redraw.
1860        */
1861       if (priv->need_calc_size)
1862         gtk_image_calc_size (image);
1863       
1864       if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1865         return FALSE;
1866
1867       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1868         xalign = misc->xalign;
1869       else
1870         xalign = 1.0 - misc->xalign;
1871
1872       x = floor (widget->allocation.x + misc->xpad
1873                  + ((widget->allocation.width - widget->requisition.width) * xalign));
1874       y = floor (widget->allocation.y + misc->ypad 
1875                  + ((widget->allocation.height - widget->requisition.height) * misc->yalign));
1876       mask_x = x;
1877       mask_y = y;
1878       
1879       image_bound.x = x;
1880       image_bound.y = y;      
1881       image_bound.width = 0;
1882       image_bound.height = 0;      
1883
1884       mask = NULL;
1885       pixbuf = NULL;
1886       needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1887       
1888       switch (image->storage_type)
1889         {
1890         case GTK_IMAGE_PIXMAP:
1891           mask = image->mask;
1892           gdk_drawable_get_size (image->data.pixmap.pixmap,
1893                                  &image_bound.width,
1894                                  &image_bound.height);
1895           if (rectangle_intersect_even (&area, &image_bound) &&
1896               needs_state_transform)
1897             {
1898               pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1899                                                      image->data.pixmap.pixmap,
1900                                                      gtk_widget_get_colormap (widget),
1901                                                      image_bound.x - x, image_bound.y - y,
1902                                                      0, 0,
1903                                                      image_bound.width,
1904                                                      image_bound.height);
1905
1906               x = image_bound.x;
1907               y = image_bound.y;
1908             }
1909           
1910           break;
1911
1912         case GTK_IMAGE_IMAGE:
1913           mask = image->mask;
1914           image_bound.width = image->data.image.image->width;
1915           image_bound.height = image->data.image.image->height;
1916
1917           if (rectangle_intersect_even (&area, &image_bound) &&
1918               needs_state_transform)
1919             {
1920               pixbuf = gdk_pixbuf_get_from_image (NULL,
1921                                                   image->data.image.image,
1922                                                   gtk_widget_get_colormap (widget),
1923                                                   image_bound.x - x, image_bound.y - y,
1924                                                   0, 0,
1925                                                   image_bound.width,
1926                                                   image_bound.height);
1927
1928               x = image_bound.x;
1929               y = image_bound.y;
1930             }
1931           break;
1932
1933         case GTK_IMAGE_PIXBUF:
1934           image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1935           image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);            
1936
1937           if (rectangle_intersect_even (&area, &image_bound) &&
1938               needs_state_transform)
1939             {
1940               pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1941                                                  image_bound.x - x, image_bound.y - y,
1942                                                  image_bound.width, image_bound.height);
1943
1944               x = image_bound.x;
1945               y = image_bound.y;
1946             }
1947           else
1948             {
1949               pixbuf = image->data.pixbuf.pixbuf;
1950               g_object_ref (pixbuf);
1951             }
1952           break;
1953
1954         case GTK_IMAGE_STOCK:
1955           pixbuf = gtk_widget_render_icon (widget,
1956                                            image->data.stock.stock_id,
1957                                            image->icon_size,
1958                                            NULL);
1959           if (pixbuf)
1960             {              
1961               image_bound.width = gdk_pixbuf_get_width (pixbuf);
1962               image_bound.height = gdk_pixbuf_get_height (pixbuf);
1963             }
1964
1965           /* already done */
1966           needs_state_transform = FALSE;
1967           break;
1968
1969         case GTK_IMAGE_ICON_SET:
1970           pixbuf =
1971             gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1972                                       widget->style,
1973                                       gtk_widget_get_direction (widget),
1974                                       GTK_WIDGET_STATE (widget),
1975                                       image->icon_size,
1976                                       widget,
1977                                       NULL);
1978
1979           if (pixbuf)
1980             {
1981               image_bound.width = gdk_pixbuf_get_width (pixbuf);
1982               image_bound.height = gdk_pixbuf_get_height (pixbuf);
1983             }
1984
1985           /* already done */
1986           needs_state_transform = FALSE;
1987           break;
1988
1989         case GTK_IMAGE_ANIMATION:
1990           {
1991             if (image->data.anim.iter == NULL)
1992               {
1993                 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1994                 
1995                 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1996                   image->data.anim.frame_timeout =
1997                     gdk_threads_add_timeout (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1998                                    animation_timeout,
1999                                    image);
2000               }
2001
2002             image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
2003             image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
2004                   
2005             /* don't advance the anim iter here, or we could get frame changes between two
2006              * exposes of different areas.
2007              */
2008             
2009             pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
2010             g_object_ref (pixbuf);
2011           }
2012           break;
2013
2014         case GTK_IMAGE_ICON_NAME:
2015           ensure_pixbuf_for_icon_name (image);
2016           pixbuf = image->data.name.pixbuf;
2017           if (pixbuf)
2018             {
2019               g_object_ref (pixbuf);
2020               image_bound.width = gdk_pixbuf_get_width (pixbuf);
2021               image_bound.height = gdk_pixbuf_get_height (pixbuf);
2022             }
2023           break;
2024
2025         case GTK_IMAGE_GICON:
2026           ensure_pixbuf_for_gicon (image);
2027           pixbuf = image->data.gicon.pixbuf;
2028           if (pixbuf)
2029             {
2030               g_object_ref (pixbuf);
2031               image_bound.width = gdk_pixbuf_get_width (pixbuf);
2032               image_bound.height = gdk_pixbuf_get_height (pixbuf);
2033             }
2034           break;
2035           
2036         case GTK_IMAGE_EMPTY:
2037           g_assert_not_reached ();
2038           break;
2039         }
2040
2041       if (mask)
2042         {
2043           gdk_gc_set_clip_mask (widget->style->black_gc, mask);
2044           gdk_gc_set_clip_origin (widget->style->black_gc, mask_x, mask_y);
2045         }
2046
2047       if (rectangle_intersect_even (&area, &image_bound))
2048         {
2049           if (pixbuf)
2050             {
2051               if (needs_state_transform)
2052                 {
2053                   GtkIconSource *source;
2054                   GdkPixbuf *rendered;
2055
2056                   source = gtk_icon_source_new ();
2057                   gtk_icon_source_set_pixbuf (source, pixbuf);
2058                   /* The size here is arbitrary; since size isn't
2059                    * wildcarded in the souce, it isn't supposed to be
2060                    * scaled by the engine function
2061                    */
2062                   gtk_icon_source_set_size (source,
2063                                             GTK_ICON_SIZE_SMALL_TOOLBAR);
2064                   gtk_icon_source_set_size_wildcarded (source, FALSE);
2065                   
2066                   rendered = gtk_style_render_icon (widget->style,
2067                                                     source,
2068                                                     gtk_widget_get_direction (widget),
2069                                                     GTK_WIDGET_STATE (widget),
2070                                                     /* arbitrary */
2071                                                     (GtkIconSize)-1,
2072                                                     widget,
2073                                                     "gtk-image");
2074
2075                   gtk_icon_source_free (source);
2076
2077                   g_object_unref (pixbuf);
2078                   pixbuf = rendered;
2079                 }
2080
2081               if (pixbuf)
2082                 {
2083                   gdk_draw_pixbuf (widget->window,
2084                                    widget->style->black_gc,
2085                                    pixbuf,
2086                                    image_bound.x - x,
2087                                    image_bound.y - y,
2088                                    image_bound.x,
2089                                    image_bound.y,
2090                                    image_bound.width,
2091                                    image_bound.height,
2092                                    GDK_RGB_DITHER_NORMAL,
2093                                    0, 0);
2094                 }
2095             }
2096           else
2097             {
2098               switch (image->storage_type)
2099                 {
2100                 case GTK_IMAGE_PIXMAP:
2101                   gdk_draw_drawable (widget->window,
2102                                      widget->style->black_gc,
2103                                      image->data.pixmap.pixmap,
2104                                      image_bound.x - x, image_bound.y - y,
2105                                      image_bound.x, image_bound.y,
2106                                      image_bound.width, image_bound.height);
2107                   break;
2108               
2109                 case GTK_IMAGE_IMAGE:
2110                   gdk_draw_image (widget->window,
2111                                   widget->style->black_gc,
2112                                   image->data.image.image,
2113                                   image_bound.x - x, image_bound.y - y,
2114                                   image_bound.x, image_bound.y,
2115                                   image_bound.width, image_bound.height);
2116                   break;
2117
2118                 case GTK_IMAGE_PIXBUF:
2119                 case GTK_IMAGE_STOCK:
2120                 case GTK_IMAGE_ICON_SET:
2121                 case GTK_IMAGE_ANIMATION:
2122                 case GTK_IMAGE_ICON_NAME:
2123                 case GTK_IMAGE_EMPTY:
2124                 case GTK_IMAGE_GICON:
2125                   g_assert_not_reached ();
2126                   break;
2127                 }
2128             }
2129         } /* if rectangle intersects */      
2130
2131       if (mask)
2132         {
2133           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
2134           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
2135         }
2136       
2137       if (pixbuf)
2138         g_object_unref (pixbuf);
2139
2140     } /* if widget is drawable */
2141
2142   return FALSE;
2143 }
2144
2145 static void
2146 gtk_image_reset (GtkImage *image)
2147 {
2148   GtkImagePrivate *priv;
2149
2150   priv = GTK_IMAGE_GET_PRIVATE (image);
2151
2152   g_object_freeze_notify (G_OBJECT (image));
2153   
2154   if (image->storage_type != GTK_IMAGE_EMPTY)
2155     g_object_notify (G_OBJECT (image), "storage-type");
2156
2157   if (image->mask)
2158     {
2159       g_object_unref (image->mask);
2160       image->mask = NULL;
2161       g_object_notify (G_OBJECT (image), "mask");
2162     }
2163
2164   if (image->icon_size != DEFAULT_ICON_SIZE)
2165     {
2166       image->icon_size = DEFAULT_ICON_SIZE;
2167       g_object_notify (G_OBJECT (image), "icon-size");
2168     }
2169   
2170   switch (image->storage_type)
2171     {
2172     case GTK_IMAGE_PIXMAP:
2173
2174       if (image->data.pixmap.pixmap)
2175         g_object_unref (image->data.pixmap.pixmap);
2176       image->data.pixmap.pixmap = NULL;
2177       
2178       g_object_notify (G_OBJECT (image), "pixmap");
2179       
2180       break;
2181
2182     case GTK_IMAGE_IMAGE:
2183
2184       if (image->data.image.image)
2185         g_object_unref (image->data.image.image);
2186       image->data.image.image = NULL;
2187       
2188       g_object_notify (G_OBJECT (image), "image");
2189       
2190       break;
2191
2192     case GTK_IMAGE_PIXBUF:
2193
2194       if (image->data.pixbuf.pixbuf)
2195         g_object_unref (image->data.pixbuf.pixbuf);
2196
2197       g_object_notify (G_OBJECT (image), "pixbuf");
2198       
2199       break;
2200
2201     case GTK_IMAGE_STOCK:
2202
2203       g_free (image->data.stock.stock_id);
2204
2205       image->data.stock.stock_id = NULL;
2206       
2207       g_object_notify (G_OBJECT (image), "stock");      
2208       break;
2209
2210     case GTK_IMAGE_ICON_SET:
2211       if (image->data.icon_set.icon_set)
2212         gtk_icon_set_unref (image->data.icon_set.icon_set);
2213       image->data.icon_set.icon_set = NULL;
2214       
2215       g_object_notify (G_OBJECT (image), "icon-set");      
2216       break;
2217
2218     case GTK_IMAGE_ANIMATION:
2219       gtk_image_reset_anim_iter (image);
2220       
2221       if (image->data.anim.anim)
2222         g_object_unref (image->data.anim.anim);
2223       image->data.anim.anim = NULL;
2224       
2225       g_object_notify (G_OBJECT (image), "pixbuf-animation");
2226       
2227       break;
2228
2229     case GTK_IMAGE_ICON_NAME:
2230       g_free (image->data.name.icon_name);
2231       image->data.name.icon_name = NULL;
2232       if (image->data.name.pixbuf)
2233         g_object_unref (image->data.name.pixbuf);
2234       image->data.name.pixbuf = NULL;
2235
2236       g_object_notify (G_OBJECT (image), "icon-name");
2237
2238       break;
2239       
2240     case GTK_IMAGE_GICON:
2241       if (image->data.gicon.icon)
2242         g_object_unref (image->data.gicon.icon);
2243       image->data.gicon.icon = NULL;
2244       if (image->data.gicon.pixbuf)
2245         g_object_unref (image->data.gicon.pixbuf);
2246       image->data.gicon.pixbuf = NULL;
2247
2248       g_object_notify (G_OBJECT (image), "gicon");
2249
2250       break;
2251       
2252     case GTK_IMAGE_EMPTY:
2253     default:
2254       break;
2255       
2256     }
2257
2258   if (priv->filename)
2259     {
2260       g_free (priv->filename);
2261       priv->filename = NULL;
2262       g_object_notify (G_OBJECT (image), "file");
2263     }
2264
2265   image->storage_type = GTK_IMAGE_EMPTY;
2266
2267   memset (&image->data, '\0', sizeof (image->data));
2268
2269   g_object_thaw_notify (G_OBJECT (image));
2270 }
2271
2272 /**
2273  * gtk_image_clear:
2274  * @image: a #GtkImage
2275  *
2276  * Resets the image to be empty.
2277  *
2278  * Since: 2.8
2279  */
2280 void
2281 gtk_image_clear (GtkImage *image)
2282 {
2283   GtkImagePrivate *priv;
2284
2285   priv = GTK_IMAGE_GET_PRIVATE (image);
2286
2287   priv->need_calc_size = 1;
2288
2289   gtk_image_reset (image);
2290   gtk_image_update_size (image, 0, 0);
2291 }
2292
2293 static void
2294 gtk_image_calc_size (GtkImage *image)
2295 {
2296   GtkWidget *widget = GTK_WIDGET (image);
2297   GdkPixbuf *pixbuf = NULL;
2298   GtkImagePrivate *priv;
2299
2300   priv = GTK_IMAGE_GET_PRIVATE (image);
2301
2302   priv->need_calc_size = 0;
2303
2304   /* We update stock/icon set on every size request, because
2305    * the theme could have affected the size; for other kinds of
2306    * image, we just update the requisition when the image data
2307    * is set.
2308    */
2309   switch (image->storage_type)
2310     {
2311     case GTK_IMAGE_STOCK:
2312       pixbuf = gtk_widget_render_icon (widget,
2313                                        image->data.stock.stock_id,
2314                                        image->icon_size,
2315                                        NULL);
2316       break;
2317       
2318     case GTK_IMAGE_ICON_SET:
2319       pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
2320                                          widget->style,
2321                                          gtk_widget_get_direction (widget),
2322                                          GTK_WIDGET_STATE (widget),
2323                                          image->icon_size,
2324                                          widget,
2325                                          NULL);
2326       break;
2327     case GTK_IMAGE_ICON_NAME:
2328       ensure_pixbuf_for_icon_name (image);
2329       pixbuf = image->data.name.pixbuf;
2330       if (pixbuf) g_object_ref (pixbuf);
2331       break;
2332     case GTK_IMAGE_GICON:
2333       ensure_pixbuf_for_gicon (image);
2334       pixbuf = image->data.gicon.pixbuf;
2335       if (pixbuf)
2336         g_object_ref (pixbuf);
2337       break;
2338     default:
2339       break;
2340     }
2341
2342   if (pixbuf)
2343     {
2344       widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
2345       widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
2346
2347       g_object_unref (pixbuf);
2348     }
2349 }
2350
2351 static void
2352 gtk_image_size_request (GtkWidget      *widget,
2353                         GtkRequisition *requisition)
2354 {
2355   GtkImage *image;
2356   
2357   image = GTK_IMAGE (widget);
2358
2359   gtk_image_calc_size (image);
2360
2361   /* Chain up to default that simply reads current requisition */
2362   GTK_WIDGET_CLASS (gtk_image_parent_class)->size_request (widget, requisition);
2363 }
2364
2365 static void
2366 gtk_image_style_set (GtkWidget      *widget,
2367                      GtkStyle       *prev_style)
2368 {
2369   GtkImage *image;
2370
2371   image = GTK_IMAGE (widget);
2372
2373   GTK_WIDGET_CLASS (gtk_image_parent_class)->style_set (widget, prev_style);
2374
2375   icon_theme_changed (image);
2376 }
2377
2378 static void
2379 gtk_image_screen_changed (GtkWidget *widget,
2380                           GdkScreen *prev_screen)
2381 {
2382   GtkImage *image;
2383
2384   image = GTK_IMAGE (widget);
2385
2386   if (GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed)
2387     GTK_WIDGET_CLASS (gtk_image_parent_class)->screen_changed (widget, prev_screen);
2388
2389   icon_theme_changed (image);
2390 }
2391
2392
2393 static void
2394 gtk_image_update_size (GtkImage *image,
2395                        gint      image_width,
2396                        gint      image_height)
2397 {
2398   GtkWidget *widget = GTK_WIDGET (image);
2399
2400   widget->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
2401   widget->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
2402
2403   if (gtk_widget_get_visible (widget))
2404     gtk_widget_queue_resize (widget);
2405 }
2406
2407
2408 /**
2409  * gtk_image_set_pixel_size:
2410  * @image: a #GtkImage
2411  * @pixel_size: the new pixel size
2412  * 
2413  * Sets the pixel size to use for named icons. If the pixel size is set
2414  * to a value != -1, it is used instead of the icon size set by
2415  * gtk_image_set_from_icon_name().
2416  *
2417  * Since: 2.6
2418  */
2419 void 
2420 gtk_image_set_pixel_size (GtkImage *image,
2421                           gint      pixel_size)
2422 {
2423   GtkImagePrivate *priv;
2424
2425   g_return_if_fail (GTK_IS_IMAGE (image));
2426   
2427   priv = GTK_IMAGE_GET_PRIVATE (image);
2428
2429   if (priv->pixel_size != pixel_size)
2430     {
2431       priv->pixel_size = pixel_size;
2432       
2433       if (image->storage_type == GTK_IMAGE_ICON_NAME)
2434         {
2435           if (image->data.name.pixbuf)
2436             {
2437               g_object_unref (image->data.name.pixbuf);
2438               image->data.name.pixbuf = NULL;
2439             }
2440           
2441           gtk_image_update_size (image, pixel_size, pixel_size);
2442         }
2443       
2444       if (image->storage_type == GTK_IMAGE_GICON)
2445         {
2446           if (image->data.gicon.pixbuf)
2447             {
2448               g_object_unref (image->data.gicon.pixbuf);
2449               image->data.gicon.pixbuf = NULL;
2450             }
2451           
2452           gtk_image_update_size (image, pixel_size, pixel_size);
2453         }
2454       
2455       g_object_notify (G_OBJECT (image), "pixel-size");
2456     }
2457 }
2458
2459 /**
2460  * gtk_image_get_pixel_size:
2461  * @image: a #GtkImage
2462  * 
2463  * Gets the pixel size used for named icons.
2464  *
2465  * Returns: the pixel size used for named icons.
2466  *
2467  * Since: 2.6
2468  */
2469 gint
2470 gtk_image_get_pixel_size (GtkImage *image)
2471 {
2472   GtkImagePrivate *priv;
2473
2474   g_return_val_if_fail (GTK_IS_IMAGE (image), -1);
2475   
2476   priv = GTK_IMAGE_GET_PRIVATE (image);
2477
2478   return priv->pixel_size;
2479 }
2480
2481 #if defined (G_OS_WIN32) && !defined (_WIN64)
2482
2483 #undef gtk_image_new_from_file
2484
2485 GtkWidget*
2486 gtk_image_new_from_file   (const gchar *filename)
2487 {
2488   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
2489   GtkWidget *retval;
2490
2491   retval = gtk_image_new_from_file_utf8 (utf8_filename);
2492
2493   g_free (utf8_filename);
2494
2495   return retval;
2496 }
2497
2498 #undef gtk_image_set_from_file
2499
2500 void
2501 gtk_image_set_from_file   (GtkImage    *image,
2502                            const gchar *filename)
2503 {
2504   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
2505
2506   gtk_image_set_from_file_utf8 (image, utf8_filename);
2507
2508   g_free (utf8_filename);
2509 }
2510
2511 #endif
2512
2513 #define __GTK_IMAGE_C__
2514 #include "gtkaliasdef.c"