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