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