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