]> Pileus Git - ~andy/gtk/blob - gtk/gtkimage.c
Don't try to use render if we can't get a picture for the drawable. (Fixes
[~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 <math.h>
28 #include "gtkcontainer.h"
29 #include "gtkimage.h"
30 #include "gtkiconfactory.h"
31 #include "gtkstock.h"
32 #include "gtkintl.h"
33 #include <string.h>
34
35 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
36
37 static void gtk_image_class_init   (GtkImageClass  *klass);
38 static void gtk_image_init         (GtkImage       *image);
39 static gint gtk_image_expose       (GtkWidget      *widget,
40                                     GdkEventExpose *event);
41 static void gtk_image_unmap        (GtkWidget      *widget);
42 static void gtk_image_unrealize    (GtkWidget      *widget);
43 static void gtk_image_size_request (GtkWidget      *widget,
44                                     GtkRequisition *requisition);
45 static void gtk_image_destroy      (GtkObject      *object);
46 static void gtk_image_clear        (GtkImage       *image);
47 static void gtk_image_reset        (GtkImage       *image);
48 static void gtk_image_calc_size    (GtkImage       *image);
49
50 static void gtk_image_update_size  (GtkImage       *image,
51                                     gint            image_width,
52                                     gint            image_height);
53
54 static void gtk_image_set_property      (GObject          *object,
55                                          guint             prop_id,
56                                          const GValue     *value,
57                                          GParamSpec       *pspec);
58 static void gtk_image_get_property      (GObject          *object,
59                                          guint             prop_id,
60                                          GValue           *value,
61                                          GParamSpec       *pspec);
62
63 static gpointer parent_class;
64
65 enum
66 {
67   PROP_0,
68   PROP_PIXBUF,
69   PROP_PIXMAP,
70   PROP_IMAGE,
71   PROP_MASK,
72   PROP_FILE,
73   PROP_STOCK,
74   PROP_ICON_SET,
75   PROP_ICON_SIZE,
76   PROP_PIXBUF_ANIMATION,
77   PROP_STORAGE_TYPE
78 };
79
80 GType
81 gtk_image_get_type (void)
82 {
83   static GType image_type = 0;
84
85   if (!image_type)
86     {
87       static const GTypeInfo image_info =
88       {
89         sizeof (GtkImageClass),
90         NULL,           /* base_init */
91         NULL,           /* base_finalize */
92         (GClassInitFunc) gtk_image_class_init,
93         NULL,           /* class_finalize */
94         NULL,           /* class_data */
95         sizeof (GtkImage),
96         0,              /* n_preallocs */
97         (GInstanceInitFunc) gtk_image_init,
98       };
99
100       image_type = g_type_register_static (GTK_TYPE_MISC, "GtkImage",
101                                            &image_info, 0);
102     }
103
104   return image_type;
105 }
106
107 static void
108 gtk_image_class_init (GtkImageClass *class)
109 {
110   GObjectClass *gobject_class;
111   GtkObjectClass *object_class;
112   GtkWidgetClass *widget_class;
113
114   parent_class = g_type_class_peek_parent (class);
115
116   gobject_class = G_OBJECT_CLASS (class);
117   
118   gobject_class->set_property = gtk_image_set_property;
119   gobject_class->get_property = gtk_image_get_property;
120   
121   object_class = GTK_OBJECT_CLASS (class);
122   
123   object_class->destroy = gtk_image_destroy;
124
125   widget_class = GTK_WIDGET_CLASS (class);
126   
127   widget_class->expose_event = gtk_image_expose;
128   widget_class->size_request = gtk_image_size_request;
129   widget_class->unmap = gtk_image_unmap;
130   widget_class->unrealize = gtk_image_unrealize;
131   
132   g_object_class_install_property (gobject_class,
133                                    PROP_PIXBUF,
134                                    g_param_spec_object ("pixbuf",
135                                                         _("Pixbuf"),
136                                                         _("A GdkPixbuf to display"),
137                                                         GDK_TYPE_PIXBUF,
138                                                         G_PARAM_READWRITE));
139
140   g_object_class_install_property (gobject_class,
141                                    PROP_PIXMAP,
142                                    g_param_spec_object ("pixmap",
143                                                         _("Pixmap"),
144                                                         _("A GdkPixmap to display"),
145                                                         GDK_TYPE_PIXMAP,
146                                                         G_PARAM_READWRITE));
147
148   g_object_class_install_property (gobject_class,
149                                    PROP_IMAGE,
150                                    g_param_spec_object ("image",
151                                                         _("Image"),
152                                                         _("A GdkImage to display"),
153                                                         GDK_TYPE_IMAGE,
154                                                         G_PARAM_READWRITE));
155
156   g_object_class_install_property (gobject_class,
157                                    PROP_MASK,
158                                    g_param_spec_object ("mask",
159                                                         _("Mask"),
160                                                         _("Mask bitmap to use with GdkImage or GdkPixmap"),
161                                                         GDK_TYPE_PIXMAP,
162                                                         G_PARAM_READWRITE));
163   
164   g_object_class_install_property (gobject_class,
165                                    PROP_FILE,
166                                    g_param_spec_string ("file",
167                                                         _("Filename"),
168                                                         _("Filename to load and display"),
169                                                         NULL,
170                                                         G_PARAM_WRITABLE));
171   
172
173   g_object_class_install_property (gobject_class,
174                                    PROP_STOCK,
175                                    g_param_spec_string ("stock",
176                                                         _("Stock ID"),
177                                                         _("Stock ID for a stock image to display"),
178                                                         NULL,
179                                                         G_PARAM_READWRITE));
180   
181   g_object_class_install_property (gobject_class,
182                                    PROP_ICON_SET,
183                                    g_param_spec_boxed ("icon_set",
184                                                        _("Icon set"),
185                                                        _("Icon set to display"),
186                                                        GTK_TYPE_ICON_SET,
187                                                        G_PARAM_READWRITE));
188   
189   g_object_class_install_property (gobject_class,
190                                    PROP_ICON_SIZE,
191                                    g_param_spec_int ("icon_size",
192                                                      _("Icon size"),
193                                                      _("Size to use for stock icon or icon set"),
194                                                      0, G_MAXINT,
195                                                      DEFAULT_ICON_SIZE,
196                                                      G_PARAM_READWRITE));
197
198   g_object_class_install_property (gobject_class,
199                                    PROP_PIXBUF_ANIMATION,
200                                    g_param_spec_object ("pixbuf_animation",
201                                                         _("Animation"),
202                                                         _("GdkPixbufAnimation to display"),
203                                                         GDK_TYPE_PIXBUF_ANIMATION,
204                                                         G_PARAM_READWRITE));
205   
206   g_object_class_install_property (gobject_class,
207                                    PROP_STORAGE_TYPE,
208                                    g_param_spec_enum ("storage_type",
209                                                       _("Storage type"),
210                                                       _("The representation being used for image data"),
211                                                       GTK_TYPE_IMAGE_TYPE,
212                                                       GTK_IMAGE_EMPTY,
213                                                       G_PARAM_READABLE));
214 }
215
216 static void
217 gtk_image_init (GtkImage *image)
218 {
219   GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
220
221   image->storage_type = GTK_IMAGE_EMPTY;
222   image->icon_size = DEFAULT_ICON_SIZE;
223   image->mask = NULL;
224 }
225
226 static void
227 gtk_image_destroy (GtkObject *object)
228 {
229   GtkImage *image = GTK_IMAGE (object);
230
231   gtk_image_clear (image);
232   
233   GTK_OBJECT_CLASS (parent_class)->destroy (object);
234 }
235
236 static void 
237 gtk_image_set_property (GObject      *object,
238                         guint         prop_id,
239                         const GValue *value,
240                         GParamSpec   *pspec)
241 {
242   GtkImage *image;
243
244   image = GTK_IMAGE (object);
245   
246   switch (prop_id)
247     {
248     case PROP_PIXBUF:
249       gtk_image_set_from_pixbuf (image,
250                                  g_value_get_object (value));
251       break;
252     case PROP_PIXMAP:
253       gtk_image_set_from_pixmap (image,
254                                  g_value_get_object (value),
255                                  image->mask);
256       break;
257     case PROP_IMAGE:
258       gtk_image_set_from_image (image,
259                                 g_value_get_object (value),
260                                 image->mask);
261       break;
262     case PROP_MASK:
263       if (image->storage_type == GTK_IMAGE_PIXMAP)
264         gtk_image_set_from_pixmap (image,
265                                    image->data.pixmap.pixmap,
266                                    g_value_get_object (value));
267       else if (image->storage_type == GTK_IMAGE_IMAGE)
268         gtk_image_set_from_image (image,
269                                   image->data.image.image,
270                                   g_value_get_object (value));
271       else
272         {
273           GdkBitmap *mask;
274
275           mask = g_value_get_object (value);
276
277           if (mask)
278             g_object_ref (mask);
279           
280           gtk_image_reset (image);
281
282           image->mask = mask;
283         }
284       break;
285     case PROP_FILE:
286       gtk_image_set_from_file (image,
287                                g_value_get_string (value));
288       break;
289     case PROP_STOCK:
290       gtk_image_set_from_stock (image, g_value_get_string (value),
291                                 image->icon_size);
292       break;
293     case PROP_ICON_SET:
294       gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
295                                    image->icon_size);
296       break;
297     case PROP_ICON_SIZE:
298       if (image->storage_type == GTK_IMAGE_STOCK)
299         gtk_image_set_from_stock (image,
300                                   image->data.stock.stock_id,
301                                   g_value_get_int (value));
302       else if (image->storage_type == GTK_IMAGE_ICON_SET)
303         gtk_image_set_from_icon_set (image,
304                                      image->data.icon_set.icon_set,
305                                      g_value_get_int (value));
306       else
307         /* Save to be used when STOCK or ICON_SET property comes in */
308         image->icon_size = g_value_get_int (value);
309       break;
310     case PROP_PIXBUF_ANIMATION:
311       gtk_image_set_from_animation (image,
312                                     g_value_get_object (value));
313       break;
314       
315     default:
316       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
317       break;
318     }
319 }
320
321 static void 
322 gtk_image_get_property (GObject     *object,
323                         guint        prop_id,
324                         GValue      *value,
325                         GParamSpec  *pspec)
326 {
327   GtkImage *image;
328
329   image = GTK_IMAGE (object);
330
331   /* The "getter" functions whine if you try to get the wrong
332    * storage type. This function is instead robust against that,
333    * so that GUI builders don't have to jump through hoops
334    * to avoid g_warning
335    */
336   
337   switch (prop_id)
338     {
339     case PROP_PIXBUF:
340       if (image->storage_type != GTK_IMAGE_PIXBUF)
341         g_value_set_object (value, NULL);
342       else
343         g_value_set_object (value,
344                             gtk_image_get_pixbuf (image));
345       break;
346     case PROP_PIXMAP:
347       if (image->storage_type != GTK_IMAGE_PIXMAP)
348         g_value_set_object (value, NULL);
349       else
350         g_value_set_object (value,
351                             image->data.pixmap.pixmap);
352       break;
353     case PROP_MASK:
354       g_value_set_object (value, image->mask);
355       break;
356     case PROP_IMAGE:
357       if (image->storage_type != GTK_IMAGE_IMAGE)
358         g_value_set_object (value, NULL);
359       else
360         g_value_set_object (value,
361                             image->data.image.image);
362       break;
363     case PROP_STOCK:
364       if (image->storage_type != GTK_IMAGE_STOCK)
365         g_value_set_string (value, NULL);
366       else
367         g_value_set_string (value,
368                             image->data.stock.stock_id);
369       break;
370     case PROP_ICON_SET:
371       if (image->storage_type != GTK_IMAGE_ICON_SET)
372         g_value_set_boxed (value, NULL);
373       else
374         g_value_set_boxed (value,
375                            image->data.icon_set.icon_set);
376       break;      
377     case PROP_ICON_SIZE:
378       g_value_set_int (value, image->icon_size);
379       break;
380     case PROP_PIXBUF_ANIMATION:
381       if (image->storage_type != GTK_IMAGE_ANIMATION)
382         g_value_set_object (value, NULL);
383       else
384         g_value_set_object (value,
385                             image->data.anim.anim);
386       break;
387     case PROP_STORAGE_TYPE:
388       g_value_set_enum (value, image->storage_type);
389       break;
390       
391     default:
392       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393       break;
394     }
395 }
396
397
398 /**
399  * gtk_image_new_from_pixmap:
400  * @pixmap: a #GdkPixmap, or %NULL
401  * @mask: a #GdkBitmap, or %NULL
402  * 
403  * Creates a #GtkImage widget displaying @pixmap with a @mask.
404  * A #GdkImage is a server-side image buffer in the pixel format of the
405  * current display. The #GtkImage does not assume a reference to the
406  * pixmap or mask; you still need to unref them if you own references.
407  * #GtkImage will add its own reference rather than adopting yours.
408  * 
409  * Return value: a new #GtkImage
410  **/
411 GtkWidget*
412 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
413                            GdkBitmap *mask)
414 {
415   GtkImage *image;
416
417   image = g_object_new (GTK_TYPE_IMAGE, NULL);
418
419   gtk_image_set_from_pixmap (image, pixmap, mask);
420
421   return GTK_WIDGET (image);
422 }
423
424 /**
425  * gtk_image_new_from_image:
426  * @image: a #GdkImage, or %NULL
427  * @mask: a #GdkBitmap, or %NULL 
428  * 
429  * Creates a #GtkImage widget displaying a @image with a @mask.
430  * A #GdkImage is a client-side image buffer in the pixel format of the
431  * current display.
432  * The #GtkImage does not assume a reference to the
433  * image or mask; you still need to unref them if you own references.
434  * #GtkImage will add its own reference rather than adopting yours.
435  * 
436  * Return value: a new #GtkImage
437  **/
438 GtkWidget*
439 gtk_image_new_from_image  (GdkImage  *gdk_image,
440                            GdkBitmap *mask)
441 {
442   GtkImage *image;
443
444   image = g_object_new (GTK_TYPE_IMAGE, NULL);
445
446   gtk_image_set_from_image (image, gdk_image, mask);
447
448   return GTK_WIDGET (image);
449 }
450
451 /**
452  * gtk_image_new_from_file:
453  * @filename: a filename
454  * 
455  * Creates a new #GtkImage displaying the file @filename. If the file
456  * isn't found or can't be loaded, the resulting #GtkImage will
457  * display a "broken image" icon. This function never returns %NULL,
458  * it always returns a valid #GtkImage widget.
459  *
460  * If the file contains an animation, the image will contain an
461  * animation.
462  *
463  * If you need to detect failures to load the file, use
464  * gdk_pixbuf_new_from_file() to load the file yourself, then create
465  * the #GtkImage from the pixbuf. (Or for animations, use
466  * gdk_pixbuf_animation_new_from_file()).
467  *
468  * The storage type (gtk_image_get_storage_type()) of the returned
469  * image is not defined, it will be whatever is appropriate for
470  * displaying the file.
471  * 
472  * Return value: a new #GtkImage
473  **/
474 GtkWidget*
475 gtk_image_new_from_file   (const gchar *filename)
476 {
477   GtkImage *image;
478
479   image = g_object_new (GTK_TYPE_IMAGE, NULL);
480
481   gtk_image_set_from_file (image, filename);
482
483   return GTK_WIDGET (image);
484 }
485
486 /**
487  * gtk_image_new_from_pixbuf:
488  * @pixbuf: a #GdkPixbuf, or %NULL
489  * 
490  * Creates a new #GtkImage displaying @pixbuf.
491  * The #GtkImage does not assume a reference to the
492  * pixbuf; you still need to unref it if you own references.
493  * #GtkImage will add its own reference rather than adopting yours.
494  * 
495  * Note that this function just creates an #GtkImage from the pixbuf.  The
496  * #GtkImage created will not react to state changes.  Should you want that, you
497  * should use gtk_image_new_from_icon_set().
498  * 
499  * Return value: a new #GtkImage
500  **/
501 GtkWidget*
502 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
503 {
504   GtkImage *image;
505
506   image = g_object_new (GTK_TYPE_IMAGE, NULL);
507
508   gtk_image_set_from_pixbuf (image, pixbuf);
509
510   return GTK_WIDGET (image);  
511 }
512
513 /**
514  * gtk_image_new_from_stock:
515  * @stock_id: a stock icon name
516  * @size: a stock icon size
517  * 
518  * Creates a #GtkImage displaying a stock icon. Sample stock icon
519  * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
520  * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
521  * icon name isn't known, a "broken image" icon will be displayed instead.
522  * You can register your own stock icon names, see
523  * gtk_icon_factory_add_default() and gtk_icon_factory_add().
524  * 
525  * Return value: a new #GtkImage displaying the stock icon
526  **/
527 GtkWidget*
528 gtk_image_new_from_stock (const gchar    *stock_id,
529                           GtkIconSize     size)
530 {
531   GtkImage *image;
532
533   image = g_object_new (GTK_TYPE_IMAGE, NULL);
534
535   gtk_image_set_from_stock (image, stock_id, size);
536
537   return GTK_WIDGET (image);
538 }
539
540 /**
541  * gtk_image_new_from_icon_set:
542  * @icon_set: a #GtkIconSet
543  * @size: a stock icon size
544  *
545  * Creates a #GtkImage displaying an icon set. Sample stock sizes are
546  * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
547  * this function, usually it's better to create a #GtkIconFactory, put
548  * your icon sets in the icon factory, add the icon factory to the
549  * list of default factories with gtk_icon_factory_add_default(), and
550  * then use gtk_image_new_from_stock(). This will allow themes to
551  * override the icon you ship with your application.
552  *
553  * The #GtkImage does not assume a reference to the
554  * icon set; you still need to unref it if you own references.
555  * #GtkImage will add its own reference rather than adopting yours.
556  * 
557  * 
558  * Return value: a new #GtkImage
559  **/
560 GtkWidget*
561 gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
562                              GtkIconSize     size)
563 {
564   GtkImage *image;
565
566   image = g_object_new (GTK_TYPE_IMAGE, NULL);
567
568   gtk_image_set_from_icon_set (image, icon_set, size);
569
570   return GTK_WIDGET (image);
571 }
572
573 /**
574  * gtk_image_new_from_animation:
575  * @animation: an animation
576  * 
577  * Creates a #GtkImage displaying the given animation.
578  * The #GtkImage does not assume a reference to the
579  * animation; you still need to unref it if you own references.
580  * #GtkImage will add its own reference rather than adopting yours.
581  * 
582  * Return value: a new #GtkImage widget
583  **/
584 GtkWidget*
585 gtk_image_new_from_animation (GdkPixbufAnimation *animation)
586 {
587   GtkImage *image;
588
589   g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
590   
591   image = g_object_new (GTK_TYPE_IMAGE, NULL);
592
593   gtk_image_set_from_animation (image, animation);
594
595   return GTK_WIDGET (image);
596 }
597
598 /**
599  * gtk_image_set_from_pixmap:
600  * @image: a #GtkImage
601  * @pixmap: a #GdkPixmap or %NULL
602  * @mask: a #GdkBitmap or %NULL
603  *
604  * See gtk_image_new_from_pixmap() for details.
605  * 
606  **/
607 void
608 gtk_image_set_from_pixmap (GtkImage  *image,
609                            GdkPixmap *pixmap,
610                            GdkBitmap *mask)
611 {
612   g_return_if_fail (GTK_IS_IMAGE (image));
613   g_return_if_fail (pixmap == NULL ||
614                     GDK_IS_PIXMAP (pixmap));
615   g_return_if_fail (mask == NULL ||
616                     GDK_IS_PIXMAP (mask));
617
618   g_object_freeze_notify (G_OBJECT (image));
619   
620   if (pixmap)
621     g_object_ref (pixmap);
622
623   if (mask)
624     g_object_ref (mask);
625
626   gtk_image_reset (image);
627
628   image->mask = mask;
629   
630   if (pixmap)
631     {
632       int width;
633       int height;
634       
635       image->storage_type = GTK_IMAGE_PIXMAP;
636
637       image->data.pixmap.pixmap = pixmap;
638
639       gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
640
641       gtk_image_update_size (image, width, height);
642     }
643
644   g_object_notify (G_OBJECT (image), "pixmap");
645   g_object_notify (G_OBJECT (image), "mask");
646   
647   g_object_thaw_notify (G_OBJECT (image));
648 }
649
650 /**
651  * gtk_image_set_from_image:
652  * @image: a #GtkImage
653  * @gdk_image: a #GdkImage or %NULL
654  * @mask: a #GdkBitmap or %NULL
655  *
656  * See gtk_image_new_from_image() for details.
657  * 
658  **/
659 void
660 gtk_image_set_from_image  (GtkImage  *image,
661                            GdkImage  *gdk_image,
662                            GdkBitmap *mask)
663 {
664   g_return_if_fail (GTK_IS_IMAGE (image));
665   g_return_if_fail (gdk_image == NULL ||
666                     GDK_IS_IMAGE (gdk_image));
667   g_return_if_fail (mask == NULL ||
668                     GDK_IS_PIXMAP (mask));
669
670   g_object_freeze_notify (G_OBJECT (image));
671   
672   if (gdk_image)
673     g_object_ref (gdk_image);
674
675   if (mask)
676     g_object_ref (mask);
677
678   gtk_image_reset (image);
679
680   if (gdk_image)
681     {
682       image->storage_type = GTK_IMAGE_IMAGE;
683
684       image->data.image.image = gdk_image;
685       image->mask = mask;
686
687       gtk_image_update_size (image, gdk_image->width, gdk_image->height);
688     }
689   else
690     {
691       /* Clean up the mask if gdk_image was NULL */
692       if (mask)
693         g_object_unref (mask);
694     }
695
696   g_object_notify (G_OBJECT (image), "image");
697   g_object_notify (G_OBJECT (image), "mask");
698   
699   g_object_thaw_notify (G_OBJECT (image));
700 }
701
702 /**
703  * gtk_image_set_from_file:
704  * @image: a #GtkImage
705  * @filename: a filename or %NULL
706  *
707  * See gtk_image_new_from_file() for details.
708  * 
709  **/
710 void
711 gtk_image_set_from_file   (GtkImage    *image,
712                            const gchar *filename)
713 {
714   GdkPixbufAnimation *anim;
715   
716   g_return_if_fail (GTK_IS_IMAGE (image));
717
718   g_object_freeze_notify (G_OBJECT (image));
719   
720   gtk_image_reset (image);
721
722   if (filename == NULL)
723     {
724       g_object_thaw_notify (G_OBJECT (image));
725       return;
726     }
727   
728   anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
729
730   if (anim == NULL)
731     {
732       gtk_image_set_from_stock (image,
733                                 GTK_STOCK_MISSING_IMAGE,
734                                 GTK_ICON_SIZE_BUTTON);
735       g_object_thaw_notify (G_OBJECT (image));
736       return;
737     }
738
739   /* We could just unconditionally set_from_animation,
740    * but it's nicer for memory if we toss the animation
741    * if it's just a single pixbuf
742    */
743
744   if (gdk_pixbuf_animation_is_static_image (anim))
745     {
746       gtk_image_set_from_pixbuf (image,
747                                  gdk_pixbuf_animation_get_static_image (anim));
748     }
749   else
750     {
751       gtk_image_set_from_animation (image, anim);
752     }
753
754   g_object_unref (anim);
755
756   g_object_thaw_notify (G_OBJECT (image));
757 }
758
759 /**
760  * gtk_image_set_from_pixbuf:
761  * @image: a #GtkImage
762  * @pixbuf: a #GdkPixbuf or %NULL
763  *
764  * See gtk_image_new_from_pixbuf() for details. 
765  * 
766  **/
767 void
768 gtk_image_set_from_pixbuf (GtkImage  *image,
769                            GdkPixbuf *pixbuf)
770 {
771   g_return_if_fail (GTK_IS_IMAGE (image));
772   g_return_if_fail (pixbuf == NULL ||
773                     GDK_IS_PIXBUF (pixbuf));
774
775   g_object_freeze_notify (G_OBJECT (image));
776   
777   if (pixbuf)
778     g_object_ref (pixbuf);
779
780   gtk_image_reset (image);
781
782   if (pixbuf != NULL)
783     {
784       image->storage_type = GTK_IMAGE_PIXBUF;
785
786       image->data.pixbuf.pixbuf = pixbuf;
787
788       gtk_image_update_size (image,
789                              gdk_pixbuf_get_width (pixbuf),
790                              gdk_pixbuf_get_height (pixbuf));
791     }
792
793   g_object_notify (G_OBJECT (image), "pixbuf");
794   
795   g_object_thaw_notify (G_OBJECT (image));
796 }
797
798 /**
799  * gtk_image_set_from_stock:
800  * @image: a #GtkImage
801  * @stock_id: a stock icon name
802  * @size: a stock icon size
803  *
804  * See gtk_image_new_from_stock() for details.
805  * 
806  **/
807 void
808 gtk_image_set_from_stock  (GtkImage       *image,
809                            const gchar    *stock_id,
810                            GtkIconSize     size)
811 {
812   gchar *new_id;
813   
814   g_return_if_fail (GTK_IS_IMAGE (image));
815
816   g_object_freeze_notify (G_OBJECT (image));
817
818   /* in case stock_id == image->data.stock.stock_id */
819   new_id = g_strdup (stock_id);
820   
821   gtk_image_reset (image);
822
823   if (new_id)
824     {
825       image->storage_type = GTK_IMAGE_STOCK;
826       
827       image->data.stock.stock_id = new_id;
828       image->icon_size = size;
829
830       /* Size is demand-computed in size request method
831        * if we're a stock image, since changing the
832        * style impacts the size request
833        */
834     }
835
836   g_object_notify (G_OBJECT (image), "stock");
837   g_object_notify (G_OBJECT (image), "icon_size");
838   
839   g_object_thaw_notify (G_OBJECT (image));
840 }
841
842 /**
843  * gtk_image_set_from_icon_set:
844  * @image: a #GtkImage
845  * @icon_set: a #GtkIconSet
846  * @size: a stock icon size
847  *
848  * See gtk_image_new_from_icon_set() for details.
849  * 
850  **/
851 void
852 gtk_image_set_from_icon_set  (GtkImage       *image,
853                               GtkIconSet     *icon_set,
854                               GtkIconSize     size)
855 {
856   g_return_if_fail (GTK_IS_IMAGE (image));
857
858   g_object_freeze_notify (G_OBJECT (image));
859   
860   if (icon_set)
861     gtk_icon_set_ref (icon_set);
862   
863   gtk_image_reset (image);
864
865   if (icon_set)
866     {      
867       image->storage_type = GTK_IMAGE_ICON_SET;
868       
869       image->data.icon_set.icon_set = icon_set;
870       image->icon_size = size;
871
872       /* Size is demand-computed in size request method
873        * if we're an icon set
874        */
875     }
876   
877   g_object_notify (G_OBJECT (image), "icon_set");
878   g_object_notify (G_OBJECT (image), "icon_size");
879   
880   g_object_thaw_notify (G_OBJECT (image));
881 }
882
883 /**
884  * gtk_image_set_from_animation:
885  * @image: a #GtkImage
886  * @animation: the #GdkPixbufAnimation
887  * 
888  * Causes the #GtkImage to display the given animation (or display
889  * nothing, if you set the animation to %NULL).
890  **/
891 void
892 gtk_image_set_from_animation (GtkImage           *image,
893                               GdkPixbufAnimation *animation)
894 {
895   g_return_if_fail (GTK_IS_IMAGE (image));
896   g_return_if_fail (animation == NULL ||
897                     GDK_IS_PIXBUF_ANIMATION (animation));
898
899   g_object_freeze_notify (G_OBJECT (image));
900   
901   if (animation)
902     g_object_ref (animation);
903
904   gtk_image_reset (image);
905
906   if (animation != NULL)
907     {
908       image->storage_type = GTK_IMAGE_ANIMATION;
909
910       image->data.anim.anim = animation;
911       image->data.anim.frame_timeout = 0;
912       image->data.anim.iter = NULL;
913       
914       gtk_image_update_size (image,
915                              gdk_pixbuf_animation_get_width (animation),
916                              gdk_pixbuf_animation_get_height (animation));
917     }
918
919   g_object_notify (G_OBJECT (image), "pixbuf_animation");
920   
921   g_object_thaw_notify (G_OBJECT (image));
922 }
923
924 /**
925  * gtk_image_get_storage_type:
926  * @image: a #GtkImage
927  * 
928  * Gets the type of representation being used by the #GtkImage
929  * to store image data. If the #GtkImage has no image data,
930  * the return value will be %GTK_IMAGE_EMPTY.
931  * 
932  * Return value: image representation being used
933  **/
934 GtkImageType
935 gtk_image_get_storage_type (GtkImage *image)
936 {
937   g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
938
939   return image->storage_type;
940 }
941
942 /**
943  * gtk_image_get_pixmap:
944  * @image: a #GtkImage
945  * @pixmap: location to store the pixmap, or %NULL
946  * @mask: location to store the mask, or %NULL
947  *
948  * Gets the pixmap and mask being displayed by the #GtkImage.
949  * The storage type of the image must be %GTK_IMAGE_EMPTY or
950  * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
951  * The caller of this function does not own a reference to the
952  * returned pixmap and mask.
953  * 
954  **/
955 void
956 gtk_image_get_pixmap (GtkImage   *image,
957                       GdkPixmap **pixmap,
958                       GdkBitmap **mask)
959 {
960   g_return_if_fail (GTK_IS_IMAGE (image)); 
961   g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
962                     image->storage_type == GTK_IMAGE_EMPTY);
963   
964   if (pixmap)
965     *pixmap = image->data.pixmap.pixmap;
966   
967   if (mask)
968     *mask = image->mask;
969 }
970
971 /**
972  * gtk_image_get_image:
973  * @image: a #GtkImage
974  * @gdk_image: return location for a #GtkImage
975  * @mask: return location for a #GdkBitmap
976  * 
977  * Gets the #GdkImage and mask being displayed by the #GtkImage.
978  * The storage type of the image must be %GTK_IMAGE_EMPTY or
979  * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
980  * The caller of this function does not own a reference to the
981  * returned image and mask.
982  **/
983 void
984 gtk_image_get_image  (GtkImage   *image,
985                       GdkImage  **gdk_image,
986                       GdkBitmap **mask)
987 {
988   g_return_if_fail (GTK_IS_IMAGE (image));
989   g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
990                     image->storage_type == GTK_IMAGE_EMPTY);
991
992   if (gdk_image)
993     *gdk_image = image->data.image.image;
994   
995   if (mask)
996     *mask = image->mask;
997 }
998
999 /**
1000  * gtk_image_get_pixbuf:
1001  * @image: a #GtkImage
1002  *
1003  *
1004  * Gets the #GdkPixbuf being displayed by the #GtkImage.
1005  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1006  * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
1007  * The caller of this function does not own a reference to the
1008  * returned pixbuf.
1009  * 
1010  * Return value: the displayed pixbuf, or %NULL if the image is empty
1011  **/
1012 GdkPixbuf*
1013 gtk_image_get_pixbuf (GtkImage *image)
1014 {
1015   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1016   g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
1017                         image->storage_type == GTK_IMAGE_EMPTY, NULL);
1018
1019   if (image->storage_type == GTK_IMAGE_EMPTY)
1020     image->data.pixbuf.pixbuf = NULL;
1021   
1022   return image->data.pixbuf.pixbuf;
1023 }
1024
1025 /**
1026  * gtk_image_get_stock:
1027  * @image: a #GtkImage
1028  * @stock_id: place to store a stock icon name
1029  * @size: place to store a stock icon size
1030  *
1031  * Gets the stock icon name and size being displayed by the #GtkImage.
1032  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1033  * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1034  * The returned string is owned by the #GtkImage and should not
1035  * be freed.
1036  * 
1037  **/
1038 void
1039 gtk_image_get_stock  (GtkImage        *image,
1040                       gchar          **stock_id,
1041                       GtkIconSize     *size)
1042 {
1043   g_return_if_fail (GTK_IS_IMAGE (image));
1044   g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
1045                     image->storage_type == GTK_IMAGE_EMPTY);
1046
1047   if (image->storage_type == GTK_IMAGE_EMPTY)
1048     image->data.stock.stock_id = NULL;
1049   
1050   if (stock_id)
1051     *stock_id = image->data.stock.stock_id;
1052
1053   if (size)
1054     *size = image->icon_size;
1055 }
1056
1057 /**
1058  * gtk_image_get_icon_set:
1059  * @image: a #GtkImage
1060  * @icon_set: location to store a #GtkIconSet
1061  * @size: location to store a stock icon size
1062  *
1063  * Gets the icon set and size being displayed by the #GtkImage.
1064  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1065  * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
1066  * 
1067  **/
1068 void
1069 gtk_image_get_icon_set  (GtkImage        *image,
1070                          GtkIconSet     **icon_set,
1071                          GtkIconSize     *size)
1072 {
1073   g_return_if_fail (GTK_IS_IMAGE (image));
1074   g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
1075                     image->storage_type == GTK_IMAGE_EMPTY);
1076       
1077   if (icon_set)    
1078     *icon_set = image->data.icon_set.icon_set;
1079
1080   if (size)
1081     *size = image->icon_size;
1082 }
1083
1084 /**
1085  * gtk_image_get_animation:
1086  * @image: a #GtkImage
1087  *
1088  *
1089  * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
1090  * The storage type of the image must be %GTK_IMAGE_EMPTY or
1091  * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
1092  * The caller of this function does not own a reference to the
1093  * returned animation.
1094  * 
1095  * Return value: the displayed animation, or %NULL if the image is empty
1096  **/
1097 GdkPixbufAnimation*
1098 gtk_image_get_animation (GtkImage *image)
1099 {
1100   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
1101   g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
1102                         image->storage_type == GTK_IMAGE_EMPTY,
1103                         NULL);
1104
1105   if (image->storage_type == GTK_IMAGE_EMPTY)
1106     image->data.anim.anim = NULL;
1107   
1108   return image->data.anim.anim;
1109 }
1110
1111 /**
1112  * gtk_image_new:
1113  * 
1114  * Creates a new empty #GtkImage widget.
1115  * 
1116  * Return value: a newly created #GtkImage widget. 
1117  **/
1118 GtkWidget*
1119 gtk_image_new (void)
1120 {
1121   return g_object_new (GTK_TYPE_IMAGE, NULL);
1122 }
1123
1124 void
1125 gtk_image_set (GtkImage  *image,
1126                GdkImage  *val,
1127                GdkBitmap *mask)
1128 {
1129   g_return_if_fail (GTK_IS_IMAGE (image));
1130
1131   gtk_image_set_from_image (image, val, mask);
1132 }
1133
1134 void
1135 gtk_image_get (GtkImage   *image,
1136                GdkImage  **val,
1137                GdkBitmap **mask)
1138 {
1139   g_return_if_fail (GTK_IS_IMAGE (image));
1140
1141   gtk_image_get_image (image, val, mask);
1142 }
1143
1144 static void
1145 gtk_image_reset_anim_iter (GtkImage *image)
1146 {
1147   if (image->storage_type == GTK_IMAGE_ANIMATION)
1148     {
1149       /* Reset the animation */
1150       
1151       if (image->data.anim.frame_timeout)
1152         {
1153           g_source_remove (image->data.anim.frame_timeout);
1154           image->data.anim.frame_timeout = 0;
1155         }
1156
1157       if (image->data.anim.iter)
1158         {
1159           g_object_unref (image->data.anim.iter);
1160           image->data.anim.iter = NULL;
1161         }
1162     }
1163 }
1164
1165 static void
1166 gtk_image_unmap (GtkWidget *widget)
1167 {
1168   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1169
1170   if (GTK_WIDGET_CLASS (parent_class)->unmap)
1171     GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1172 }
1173
1174 static void
1175 gtk_image_unrealize (GtkWidget *widget)
1176 {
1177   gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1178
1179   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1180     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
1181 }
1182
1183 static gint
1184 animation_timeout (gpointer data)
1185 {
1186   GtkImage *image;
1187
1188   GDK_THREADS_ENTER ();
1189
1190   image = GTK_IMAGE (data);
1191   
1192   image->data.anim.frame_timeout = 0;
1193
1194   gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);
1195
1196   if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1197     image->data.anim.frame_timeout =
1198       g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1199                      animation_timeout,
1200                      image);
1201   
1202   gtk_widget_queue_draw (GTK_WIDGET (image));
1203
1204   GDK_THREADS_LEAVE ();
1205
1206   return FALSE;
1207 }
1208
1209 static gint
1210 gtk_image_expose (GtkWidget      *widget,
1211                   GdkEventExpose *event)
1212 {
1213   g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
1214   g_return_val_if_fail (event != NULL, FALSE);
1215   
1216   if (GTK_WIDGET_MAPPED (widget) &&
1217       GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
1218     {
1219       GtkImage *image;
1220       GtkMisc *misc;
1221       GdkRectangle area, image_bound;
1222       gfloat xalign;
1223       gint x, y;
1224       GdkBitmap *mask;
1225       GdkPixbuf *pixbuf;
1226       gboolean needs_state_transform;
1227       
1228       image = GTK_IMAGE (widget);
1229       misc = GTK_MISC (widget);
1230
1231       area = event->area;
1232
1233       /* For stock items and icon sets, we lazily calculate
1234        * the size; we might get here between a queue_resize()
1235        * and size_request() if something explicitely forces
1236        * a redraw.
1237        */
1238       if (widget->requisition.width == 0 && widget->requisition.height == 0)
1239         gtk_image_calc_size (image);
1240       
1241       if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
1242         return FALSE;
1243
1244       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1245         xalign = misc->xalign;
1246       else
1247         xalign = 1.0 - misc->xalign;
1248   
1249       x = floor (widget->allocation.x + misc->xpad
1250                  + ((widget->allocation.width - widget->requisition.width) * xalign)
1251                  + 0.5);
1252       y = floor (widget->allocation.y + misc->ypad 
1253                  + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
1254                  + 0.5);
1255       
1256       image_bound.x = x;
1257       image_bound.y = y;      
1258       image_bound.width = 0;
1259       image_bound.height = 0;      
1260
1261       mask = NULL;
1262       pixbuf = NULL;
1263       needs_state_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
1264       
1265       switch (image->storage_type)
1266         {
1267         case GTK_IMAGE_PIXMAP:
1268           mask = image->mask;
1269           gdk_drawable_get_size (image->data.pixmap.pixmap,
1270                                  &image_bound.width,
1271                                  &image_bound.height);
1272
1273           if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1274               needs_state_transform)
1275             {
1276               pixbuf = gdk_pixbuf_get_from_drawable (NULL,
1277                                                      image->data.pixmap.pixmap,
1278                                                      gtk_widget_get_colormap (widget),
1279                                                      image_bound.x - x, image_bound.y - y,
1280                                                      0, 0,
1281                                                      image_bound.width,
1282                                                      image_bound.height);
1283
1284               x = image_bound.x;
1285               y = image_bound.y;
1286             }
1287           
1288           break;
1289
1290         case GTK_IMAGE_IMAGE:
1291           mask = image->mask;
1292           image_bound.width = image->data.image.image->width;
1293           image_bound.height = image->data.image.image->height;
1294
1295           if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1296               needs_state_transform)
1297             {
1298               pixbuf = gdk_pixbuf_get_from_image (NULL,
1299                                                   image->data.image.image,
1300                                                   gtk_widget_get_colormap (widget),
1301                                                   image_bound.x - x, image_bound.y - y,
1302                                                   0, 0,
1303                                                   image_bound.width,
1304                                                   image_bound.height);
1305
1306               x = image_bound.x;
1307               y = image_bound.y;
1308             }
1309           break;
1310
1311         case GTK_IMAGE_PIXBUF:
1312           image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
1313           image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);          
1314
1315           if (gdk_rectangle_intersect (&image_bound, &area, &image_bound) &&
1316               needs_state_transform)
1317             {
1318               pixbuf = gdk_pixbuf_new_subpixbuf (image->data.pixbuf.pixbuf,
1319                                                  image_bound.x - x, image_bound.y - y,
1320                                                  image_bound.width, image_bound.height);
1321
1322               x = image_bound.x;
1323               y = image_bound.y;
1324             }
1325           else
1326             {
1327               pixbuf = image->data.pixbuf.pixbuf;
1328               g_object_ref (pixbuf);
1329             }
1330           break;
1331
1332         case GTK_IMAGE_STOCK:
1333           pixbuf = gtk_widget_render_icon (widget,
1334                                            image->data.stock.stock_id,
1335                                            image->icon_size,
1336                                            NULL);
1337           if (pixbuf)
1338             {              
1339               image_bound.width = gdk_pixbuf_get_width (pixbuf);
1340               image_bound.height = gdk_pixbuf_get_height (pixbuf);
1341             }
1342
1343           /* already done */
1344           needs_state_transform = FALSE;
1345           break;
1346
1347         case GTK_IMAGE_ICON_SET:
1348           pixbuf =
1349             gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1350                                       widget->style,
1351                                       gtk_widget_get_direction (widget),
1352                                       GTK_WIDGET_STATE (widget),
1353                                       image->icon_size,
1354                                       widget,
1355                                       NULL);
1356
1357           if (pixbuf)
1358             {
1359               image_bound.width = gdk_pixbuf_get_width (pixbuf);
1360               image_bound.height = gdk_pixbuf_get_height (pixbuf);
1361             }
1362
1363           /* already done */
1364           needs_state_transform = FALSE;
1365           break;
1366
1367         case GTK_IMAGE_ANIMATION:
1368           {
1369             if (image->data.anim.iter == NULL)
1370               {
1371                 image->data.anim.iter = gdk_pixbuf_animation_get_iter (image->data.anim.anim, NULL);
1372                 
1373                 if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
1374                   image->data.anim.frame_timeout =
1375                     g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
1376                                    animation_timeout,
1377                                    image);
1378               }
1379
1380             image_bound.width = gdk_pixbuf_animation_get_width (image->data.anim.anim);
1381             image_bound.height = gdk_pixbuf_animation_get_height (image->data.anim.anim);
1382                   
1383             /* don't advance the anim iter here, or we could get frame changes between two
1384              * exposes of different areas.
1385              */
1386             
1387             pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->data.anim.iter);
1388             g_object_ref (pixbuf);
1389           }
1390           break;
1391
1392         case GTK_IMAGE_EMPTY:
1393           g_assert_not_reached ();
1394           break;
1395         }
1396
1397       if (mask)
1398         {
1399           gdk_gc_set_clip_mask (widget->style->black_gc, mask);
1400           gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
1401         }
1402
1403       if (gdk_rectangle_intersect (&image_bound, &area, &image_bound))
1404         {
1405           if (pixbuf)
1406             {
1407               if (needs_state_transform)
1408                 {
1409                   GtkIconSource *source;
1410                   GdkPixbuf *rendered;
1411
1412                   source = gtk_icon_source_new ();
1413                   gtk_icon_source_set_pixbuf (source, pixbuf);
1414                   /* The size here is arbitrary; since size isn't
1415                    * wildcarded in the souce, it isn't supposed to be
1416                    * scaled by the engine function
1417                    */
1418                   gtk_icon_source_set_size (source,
1419                                             GTK_ICON_SIZE_SMALL_TOOLBAR);
1420                   gtk_icon_source_set_size_wildcarded (source, FALSE);
1421                   
1422                   rendered = gtk_style_render_icon (widget->style,
1423                                                     source,
1424                                                     gtk_widget_get_direction (widget),
1425                                                     GTK_WIDGET_STATE (widget),
1426                                                     /* arbitrary */
1427                                                     (GtkIconSize)-1,
1428                                                     widget,
1429                                                     "gtk-image");
1430
1431                   gtk_icon_source_free (source);
1432
1433                   g_object_unref (pixbuf);
1434                   pixbuf = rendered;
1435                 }
1436
1437               if (pixbuf)
1438                 {
1439                   gdk_draw_pixbuf (widget->window,
1440                                    widget->style->black_gc,
1441                                    pixbuf,
1442                                    image_bound.x - x,
1443                                    image_bound.y - y,
1444                                    image_bound.x,
1445                                    image_bound.y,
1446                                    image_bound.width,
1447                                    image_bound.height,
1448                                    GDK_RGB_DITHER_NORMAL,
1449                                    0, 0);
1450
1451                   g_object_unref (pixbuf);
1452                   pixbuf = NULL;
1453                 }
1454             }
1455           else
1456             {
1457               switch (image->storage_type)
1458                 {
1459                 case GTK_IMAGE_PIXMAP:
1460                   gdk_draw_drawable (widget->window,
1461                                      widget->style->black_gc,
1462                                      image->data.pixmap.pixmap,
1463                                      image_bound.x - x, image_bound.y - y,
1464                                      image_bound.x, image_bound.y,
1465                                      image_bound.width, image_bound.height);
1466                   break;
1467               
1468                 case GTK_IMAGE_IMAGE:
1469                   gdk_draw_image (widget->window,
1470                                   widget->style->black_gc,
1471                                   image->data.image.image,
1472                                   image_bound.x - x, image_bound.y - y,
1473                                   image_bound.x, image_bound.y,
1474                                   image_bound.width, image_bound.height);
1475                   break;
1476
1477                 case GTK_IMAGE_PIXBUF:
1478                 case GTK_IMAGE_STOCK:
1479                 case GTK_IMAGE_ICON_SET:
1480                 case GTK_IMAGE_ANIMATION:
1481                 case GTK_IMAGE_EMPTY:
1482                   g_assert_not_reached ();
1483                   break;
1484                 }
1485             }
1486         } /* if rectangle intersects */      
1487
1488       if (mask)
1489         {
1490           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
1491           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
1492         }
1493       
1494     } /* if widget is drawable */
1495
1496   return FALSE;
1497 }
1498
1499 static void
1500 gtk_image_clear (GtkImage *image)
1501 {
1502   g_object_freeze_notify (G_OBJECT (image));
1503   
1504   if (image->storage_type != GTK_IMAGE_EMPTY)
1505     g_object_notify (G_OBJECT (image), "storage_type");
1506
1507   if (image->mask)
1508     {
1509       g_object_unref (image->mask);
1510       image->mask = NULL;
1511       g_object_notify (G_OBJECT (image), "mask");
1512     }
1513
1514   if (image->icon_size != DEFAULT_ICON_SIZE)
1515     {
1516       image->icon_size = DEFAULT_ICON_SIZE;
1517       g_object_notify (G_OBJECT (image), "icon_size");
1518     }
1519   
1520   switch (image->storage_type)
1521     {
1522     case GTK_IMAGE_PIXMAP:
1523
1524       if (image->data.pixmap.pixmap)
1525         g_object_unref (image->data.pixmap.pixmap);
1526       image->data.pixmap.pixmap = NULL;
1527       
1528       g_object_notify (G_OBJECT (image), "pixmap");
1529       
1530       break;
1531
1532     case GTK_IMAGE_IMAGE:
1533
1534       if (image->data.image.image)
1535         g_object_unref (image->data.image.image);
1536       image->data.image.image = NULL;
1537       
1538       g_object_notify (G_OBJECT (image), "image");
1539       
1540       break;
1541
1542     case GTK_IMAGE_PIXBUF:
1543
1544       if (image->data.pixbuf.pixbuf)
1545         g_object_unref (image->data.pixbuf.pixbuf);
1546
1547       g_object_notify (G_OBJECT (image), "pixbuf");
1548       
1549       break;
1550
1551     case GTK_IMAGE_STOCK:
1552
1553       g_free (image->data.stock.stock_id);
1554
1555       image->data.stock.stock_id = NULL;
1556       
1557       g_object_notify (G_OBJECT (image), "stock");      
1558       break;
1559
1560     case GTK_IMAGE_ICON_SET:
1561       if (image->data.icon_set.icon_set)
1562         gtk_icon_set_unref (image->data.icon_set.icon_set);
1563       image->data.icon_set.icon_set = NULL;
1564       
1565       g_object_notify (G_OBJECT (image), "icon_set");      
1566       break;
1567
1568     case GTK_IMAGE_ANIMATION:
1569       if (image->data.anim.frame_timeout)
1570         g_source_remove (image->data.anim.frame_timeout);
1571       
1572       if (image->data.anim.anim)
1573         g_object_unref (image->data.anim.anim);
1574
1575       image->data.anim.frame_timeout = 0;
1576       image->data.anim.anim = NULL;
1577       
1578       g_object_notify (G_OBJECT (image), "pixbuf_animation");
1579       
1580       break;
1581       
1582     case GTK_IMAGE_EMPTY:
1583     default:
1584       break;
1585       
1586     }
1587
1588   image->storage_type = GTK_IMAGE_EMPTY;
1589
1590   memset (&image->data, '\0', sizeof (image->data));
1591
1592   g_object_thaw_notify (G_OBJECT (image));
1593 }
1594
1595 static void
1596 gtk_image_reset (GtkImage *image)
1597 {
1598   gtk_image_clear (image);
1599
1600   gtk_image_update_size (image, 0, 0);
1601 }
1602
1603 static void
1604 gtk_image_calc_size (GtkImage *image)
1605 {
1606   GtkWidget *widget = GTK_WIDGET (image);
1607   GdkPixbuf *pixbuf = NULL;
1608   
1609   /* We update stock/icon set on every size request, because
1610    * the theme could have affected the size; for other kinds of
1611    * image, we just update the requisition when the image data
1612    * is set.
1613    */
1614   switch (image->storage_type)
1615     {
1616     case GTK_IMAGE_STOCK:
1617       pixbuf = gtk_widget_render_icon (widget,
1618                                        image->data.stock.stock_id,
1619                                        image->icon_size,
1620                                        NULL);
1621       break;
1622       
1623     case GTK_IMAGE_ICON_SET:
1624       pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
1625                                          widget->style,
1626                                          gtk_widget_get_direction (widget),
1627                                          GTK_WIDGET_STATE (widget),
1628                                          image->icon_size,
1629                                          widget,
1630                                          NULL);
1631       break;
1632       
1633     default:
1634       break;
1635     }
1636
1637   if (pixbuf)
1638     {
1639       widget->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2;
1640       widget->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2;
1641
1642       g_object_unref (pixbuf);
1643     }
1644 }
1645
1646 static void
1647 gtk_image_size_request (GtkWidget      *widget,
1648                         GtkRequisition *requisition)
1649 {
1650   GtkImage *image;
1651   
1652   image = GTK_IMAGE (widget);
1653
1654   gtk_image_calc_size (image);
1655
1656   /* Chain up to default that simply reads current requisition */
1657   GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1658 }
1659
1660 static void
1661 gtk_image_update_size (GtkImage *image,
1662                        gint      image_width,
1663                        gint      image_height)
1664 {
1665   GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
1666   GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
1667
1668   if (GTK_WIDGET_VISIBLE (image))
1669     gtk_widget_queue_resize (GTK_WIDGET (image));
1670 }