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