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