]> Pileus Git - ~andy/gtk/blob - gtk/gtkimage.c
Switch to using an enum with registration for icon sizes, instead of
[~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 "gtkcontainer.h"
28 #include "gtkimage.h"
29 #include "gtkiconfactory.h"
30 #include "gtkstock.h"
31
32 static void gtk_image_class_init   (GtkImageClass  *klass);
33 static void gtk_image_init         (GtkImage       *image);
34 static gint gtk_image_expose       (GtkWidget      *widget,
35                                     GdkEventExpose *event);
36 static void gtk_image_size_request (GtkWidget      *widget,
37                                     GtkRequisition *requisition);
38 static void gtk_image_destroy      (GtkObject      *object);
39 static void gtk_image_clear        (GtkImage       *image);
40 static void gtk_image_reset        (GtkImage       *image);
41 static void gtk_image_update_size  (GtkImage       *image,
42                                     gint            image_width,
43                                     gint            image_height);
44
45 static gpointer parent_class;
46
47 GtkType
48 gtk_image_get_type (void)
49 {
50   static GtkType image_type = 0;
51
52   if (!image_type)
53     {
54       static const GtkTypeInfo image_info =
55       {
56         "GtkImage",
57         sizeof (GtkImage),
58         sizeof (GtkImageClass),
59         (GtkClassInitFunc) gtk_image_class_init,
60         (GtkObjectInitFunc) gtk_image_init,
61         /* reserved_1 */ NULL,
62         /* reserved_2 */ NULL,
63         (GtkClassInitFunc) NULL,
64       };
65
66       image_type = gtk_type_unique (GTK_TYPE_MISC, &image_info);
67     }
68
69   return image_type;
70 }
71
72 static void
73 gtk_image_class_init (GtkImageClass *class)
74 {
75   GtkObjectClass *object_class;
76   GtkWidgetClass *widget_class;
77
78   parent_class = g_type_class_peek_parent (class);
79
80   object_class = (GtkObjectClass *) class;
81   
82   object_class->destroy = gtk_image_destroy;
83
84   widget_class = (GtkWidgetClass*) class;
85
86   widget_class->expose_event = gtk_image_expose;
87   widget_class->size_request = gtk_image_size_request;
88 }
89
90 static void
91 gtk_image_init (GtkImage *image)
92 {
93   GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
94
95   image->storage_type = GTK_IMAGE_EMPTY;
96 }
97
98 static void
99 gtk_image_destroy (GtkObject *object)
100 {
101   GtkImage *image = GTK_IMAGE (object);
102
103   gtk_image_clear (image);
104   
105   GTK_OBJECT_CLASS (parent_class)->destroy (object);
106 }
107
108
109 /**
110  * gtk_image_new_from_pixmap:
111  * @pixmap: a #GdkPixmap, or %NULL
112  * @mask: a #GdkBitmap, or %NULL
113  * 
114  * Creates a #GtkImage widget displaying @pixmap with a @mask.
115  * A #GdkImage is a server-side image buffer in the pixel format of the
116  * current display. The #GtkImage does not assume a reference to the
117  * pixmap or mask; you still need to unref them if you own references.
118  * #GtkImage will add its own reference rather than adopting yours.
119  * 
120  * Return value: a new #GtkImage
121  **/
122 GtkWidget*
123 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
124                            GdkBitmap *mask)
125 {
126   GtkImage *image;
127
128   image = gtk_type_new (GTK_TYPE_IMAGE);
129
130   gtk_image_set_from_pixmap (image, pixmap, mask);
131
132   return GTK_WIDGET (image);
133 }
134
135 /**
136  * gtk_image_new_from_image:
137  * @image: a #GdkImage, or %NULL
138  * @mask: a #GdkBitmap, or %NULL 
139  * 
140  * Creates a #GtkImage widget displaying a @image with a @mask.
141  * A #GdkImage is a client-side image buffer in the pixel format of the
142  * current display.
143  * The #GtkImage does not assume a reference to the
144  * image or mask; you still need to unref them if you own references.
145  * #GtkImage will add its own reference rather than adopting yours.
146  * 
147  * Return value: a new #GtkImage
148  **/
149 GtkWidget*
150 gtk_image_new_from_image  (GdkImage  *gdk_image,
151                            GdkBitmap *mask)
152 {
153   GtkImage *image;
154
155   image = gtk_type_new (GTK_TYPE_IMAGE);
156
157   gtk_image_set_from_image (image, gdk_image, mask);
158
159   return GTK_WIDGET (image);
160 }
161
162 /**
163  * gtk_image_new_from_file:
164  * @filename: a filename
165  * 
166  * Creates a new #GtkImage displaying the file @filename. If the
167  * file isn't found or can't be loaded, the #GtkImage will display
168  * a "broken image" icon. If you need to detect failures to load
169  * the file, use gdk_pixbuf_new_from_file() to load the file yourself,
170  * then create the #GtkImage from the pixbuf.
171  * 
172  * Return value: a new #GtkImage
173  **/
174 GtkWidget*
175 gtk_image_new_from_file   (const gchar *filename)
176 {
177   GtkImage *image;
178
179   image = gtk_type_new (GTK_TYPE_IMAGE);
180
181   gtk_image_set_from_file (image, filename);
182
183   return GTK_WIDGET (image);
184 }
185
186 /**
187  * gtk_image_new_from_pixbuf:
188  * @pixbuf: a #GdkPixbuf, or %NULL
189  * 
190  * Creates a new #GtkImage displaying @pixbuf.
191  * The #GtkImage does not assume a reference to the
192  * pixbuf; you still need to unref it if you own references.
193  * #GtkImage will add its own reference rather than adopting yours.
194  * 
195  * Note that this function just creates an #GtkImage from the pixbuf.  The
196  * #GtkImage created will not react to state changes.  Should you want that, you
197  * should use @gtk_image_new_from_icon_set.
198  * 
199  * Return value: a new #GtkImage
200  **/
201 GtkWidget*
202 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
203 {
204   GtkImage *image;
205
206   image = gtk_type_new (GTK_TYPE_IMAGE);
207
208   gtk_image_set_from_pixbuf (image, pixbuf);
209
210   return GTK_WIDGET (image);  
211 }
212
213 /**
214  * gtk_image_new_from_stock:
215  * @stock_id: a stock icon name
216  * @size: a stock icon size
217  * 
218  * Creates a #GtkImage displaying a stock icon. Sample stock icon
219  * names are #GTK_STOCK_ICON_OPEN, #GTK_STOCK_ICON_EXIT. Sample stock sizes
220  * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
221  * icon name isn't known, a "broken image" icon will be displayed instead.
222  * 
223  * Return value: a new #GtkImage displaying the stock icon
224  **/
225 GtkWidget*
226 gtk_image_new_from_stock (const gchar    *stock_id,
227                           GtkIconSize     size)
228 {
229   GtkImage *image;
230
231   image = gtk_type_new (GTK_TYPE_IMAGE);
232
233   gtk_image_set_from_stock (image, stock_id, size);
234
235   return GTK_WIDGET (image);
236 }
237
238 /**
239  * gtk_image_new_from_icon_set:
240  * @icon_set: a #GtkIconSet
241  * @size: a stock icon size
242  *
243  * Creates a #GtkImage displaying an icon set. Sample stock sizes are
244  * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
245  * this function, usually it's better to create a #GtkIconFactory, put
246  * your icon sets in the icon factory, add the icon factory to the
247  * list of default factories with gtk_icon_factory_add_default(), and
248  * then use gtk_image_new_from_stock(). This will allow themes to
249  * override the icon you ship with your application.
250  *
251  * The #GtkImage does not assume a reference to the
252  * icon set; you still need to unref it if you own references.
253  * #GtkImage will add its own reference rather than adopting yours.
254  * 
255  * 
256  * Return value: a new #GtkImage
257  **/
258 GtkWidget*
259 gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
260                              GtkIconSize     size)
261 {
262   GtkImage *image;
263
264   image = gtk_type_new (GTK_TYPE_IMAGE);
265
266   gtk_image_set_from_icon_set (image, icon_set, size);
267
268   return GTK_WIDGET (image);
269 }
270
271 /**
272  * gtk_image_set_from_pixmap:
273  * @image: a #GtkImage
274  * @pixmap: a #GdkPixmap or %NULL
275  * @mask: a #GdkBitmap or %NULL
276  *
277  * See gtk_image_new_from_pixmap() for details.
278  * 
279  **/
280 void
281 gtk_image_set_from_pixmap (GtkImage  *image,
282                            GdkPixmap *pixmap,
283                            GdkBitmap *mask)
284 {
285   g_return_if_fail (GTK_IS_IMAGE (image));
286   g_return_if_fail (pixmap == NULL ||
287                     GDK_IS_PIXMAP (pixmap));
288   g_return_if_fail (mask == NULL ||
289                     GDK_IS_PIXMAP (mask));
290   
291   if (pixmap)
292     g_object_ref (G_OBJECT (pixmap));
293
294   if (mask)
295     g_object_ref (G_OBJECT (mask));
296
297   gtk_image_reset (image);
298
299   if (pixmap)
300     {
301       int width;
302       int height;
303       
304       image->storage_type = GTK_IMAGE_PIXMAP;
305
306       image->data.pixmap.pixmap = pixmap;
307       image->data.pixmap.mask = mask;
308
309       gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
310
311       gtk_image_update_size (image, width, height);
312     }
313   else
314     {
315       /* Clean up the mask if pixmap was NULL */
316       if (mask)
317         g_object_unref (G_OBJECT (mask));
318     }
319 }
320
321 /**
322  * gtk_image_set_from_image:
323  * @image: a #GtkImage
324  * @gdk_image: a #GdkImage or %NULL
325  * @mask: a #GdkBitmap or %NULL
326  *
327  * See gtk_image_new_from_image() for details.
328  * 
329  **/
330 void
331 gtk_image_set_from_image  (GtkImage  *image,
332                            GdkImage  *gdk_image,
333                            GdkBitmap *mask)
334 {
335   g_return_if_fail (GTK_IS_IMAGE (image));
336   g_return_if_fail (gdk_image == NULL ||
337                     GDK_IS_IMAGE (gdk_image));
338   g_return_if_fail (mask == NULL ||
339                     GDK_IS_PIXMAP (mask));
340
341   
342   if (gdk_image)
343     g_object_ref (G_OBJECT (gdk_image));
344
345   if (mask)
346     g_object_ref (G_OBJECT (mask));
347
348   gtk_image_reset (image);
349
350   if (gdk_image)
351     {
352       image->storage_type = GTK_IMAGE_IMAGE;
353
354       image->data.image.image = gdk_image;
355       image->data.image.mask = mask;
356
357       gtk_image_update_size (image, gdk_image->width, gdk_image->height);
358     }
359   else
360     {
361       /* Clean up the mask if gdk_image was NULL */
362       if (mask)
363         g_object_unref (G_OBJECT (mask));
364     }
365 }
366
367 /**
368  * gtk_image_set_from_file:
369  * @image: a #GtkImage
370  * @filename: a filename or %NULL
371  *
372  * See gtk_image_new_from_file() for details.
373  * 
374  **/
375 void
376 gtk_image_set_from_file   (GtkImage    *image,
377                            const gchar *filename)
378 {
379   GdkPixbuf *pixbuf;
380   
381   g_return_if_fail (GTK_IS_IMAGE (image));
382   g_return_if_fail (filename != NULL);
383   
384   gtk_image_reset (image);
385
386   if (filename == NULL)
387     return;
388   
389   pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
390
391   if (pixbuf == NULL)
392     {
393       gtk_image_set_from_stock (image,
394                                 GTK_STOCK_MISSING_IMAGE,
395                                 GTK_ICON_SIZE_BUTTON);
396       return;
397     }
398
399   gtk_image_set_from_pixbuf (image, pixbuf);
400
401   g_object_unref (G_OBJECT (pixbuf));
402 }
403
404 /**
405  * gtk_image_set_from_pixbuf:
406  * @image: a #GtkImage
407  * @pixbuf: a #GdkPixbuf or %NULL
408  *
409  * See gtk_image_new_from_pixbuf() for details. 
410  * 
411  **/
412 void
413 gtk_image_set_from_pixbuf (GtkImage  *image,
414                            GdkPixbuf *pixbuf)
415 {
416   g_return_if_fail (GTK_IS_IMAGE (image));
417   g_return_if_fail (pixbuf == NULL ||
418                     GDK_IS_PIXBUF (pixbuf));
419   
420   if (pixbuf)
421     g_object_ref (G_OBJECT (pixbuf));
422
423   gtk_image_reset (image);
424
425   if (pixbuf != NULL)
426     {
427       image->storage_type = GTK_IMAGE_PIXBUF;
428
429       image->data.pixbuf.pixbuf = pixbuf;
430
431       gtk_image_update_size (image,
432                              gdk_pixbuf_get_width (pixbuf),
433                              gdk_pixbuf_get_height (pixbuf));
434     }
435 }
436
437 /**
438  * gtk_image_set_from_stock:
439  * @image: a #GtkImage
440  * @stock_id: a stock icon name
441  * @size: a stock icon size
442  *
443  * See gtk_image_new_from_stock for details.
444  * 
445  **/
446 void
447 gtk_image_set_from_stock  (GtkImage       *image,
448                            const gchar    *stock_id,
449                            GtkIconSize     size)
450 {
451   g_return_if_fail (GTK_IS_IMAGE (image));
452   
453   gtk_image_reset (image);
454
455   if (stock_id)
456     {      
457       image->storage_type = GTK_IMAGE_STOCK;
458       
459       image->data.stock.stock_id = g_strdup (stock_id);
460       image->data.stock.size = size;
461
462       /* Size is demand-computed in size request method
463        * if we're a stock image, since changing the
464        * style impacts the size request
465        */
466     }
467 }
468
469 /**
470  * gtk_image_set_from_icon_set:
471  * @image: a #GtkImage
472  * @icon_set: a #GtkIconSet
473  * @size: a stock icon size
474  *
475  * See gtk_image_new_from_icon_set() for details.
476  * 
477  **/
478 void
479 gtk_image_set_from_icon_set  (GtkImage       *image,
480                               GtkIconSet     *icon_set,
481                               GtkIconSize     size)
482 {
483   g_return_if_fail (GTK_IS_IMAGE (image));
484
485   if (icon_set)
486     gtk_icon_set_ref (icon_set);
487   
488   gtk_image_reset (image);
489
490   if (icon_set)
491     {      
492       image->storage_type = GTK_IMAGE_ICON_SET;
493       
494       image->data.icon_set.icon_set = icon_set;
495       image->data.icon_set.size = size;
496
497       /* Size is demand-computed in size request method
498        * if we're an icon set
499        */
500     }
501 }
502
503 /**
504  * gtk_image_get_storage_type:
505  * @image: a #GtkImage
506  * 
507  * Gets the type of representation being used by the #GtkImage
508  * to store image data. If the #GtkImage has no image data,
509  * the return value will be %GTK_IMAGE_EMPTY.
510  * 
511  * Return value: image representation being used
512  **/
513 GtkImageType
514 gtk_image_get_storage_type (GtkImage *image)
515 {
516   g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
517
518   return image->storage_type;
519 }
520
521 /**
522  * gtk_image_get_pixmap:
523  * @image: a #GtkImage
524  * @pixmap: location to store the pixmap, or %NULL
525  * @mask: location to store the mask, or %NULL
526  *
527  * Gets the pixmap and mask being displayed by the #GtkImage.
528  * The storage type of the image must be %GTK_IMAGE_EMPTY or
529  * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
530  * The caller of this function does not own a reference to the
531  * returned pixmap and mask.
532  * 
533  **/
534 void
535 gtk_image_get_pixmap (GtkImage   *image,
536                       GdkPixmap **pixmap,
537                       GdkBitmap **mask)
538 {
539   g_return_if_fail (GTK_IS_IMAGE (image)); 
540   g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
541                     image->storage_type == GTK_IMAGE_EMPTY);
542   
543   if (pixmap)
544     *pixmap = image->data.pixmap.pixmap;
545   
546   if (mask)
547     *mask = image->data.pixmap.mask;
548 }
549
550 /**
551  * gtk_image_get_image:
552  * @image: a #GtkImage
553  * @gdk_image: return location for a #GtkImage
554  * @mask: return location for a #GdkBitmap
555  * 
556  * Gets the #GdkImage and mask being displayed by the #GtkImage.
557  * The storage type of the image must be %GTK_IMAGE_EMPTY or
558  * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
559  * The caller of this function does not own a reference to the
560  * returned image and mask.
561  **/
562 void
563 gtk_image_get_image  (GtkImage   *image,
564                       GdkImage  **gdk_image,
565                       GdkBitmap **mask)
566 {
567   g_return_if_fail (GTK_IS_IMAGE (image));
568   g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
569                     image->storage_type == GTK_IMAGE_EMPTY);
570
571   if (gdk_image)
572     *gdk_image = image->data.image.image;
573   
574   if (mask)
575     *mask = image->data.image.mask;
576 }
577
578 /**
579  * gtk_image_get_pixbuf:
580  * @image: a #GtkImage
581  *
582  *
583  * Gets the #GdkPixbuf being displayed by the #GtkImage.
584  * The storage type of the image must be %GTK_IMAGE_EMPTY or
585  * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
586  * The caller of this function does not own a reference to the
587  * returned pixbuf.
588  * 
589  * Return value: the displayed pixbuf, or %NULL if the image is empty
590  **/
591 GdkPixbuf*
592 gtk_image_get_pixbuf (GtkImage *image)
593 {
594   g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
595   g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
596                         image->storage_type == GTK_IMAGE_EMPTY, NULL);
597
598   if (image->storage_type == GTK_IMAGE_EMPTY)
599     image->data.pixbuf.pixbuf = NULL;
600   
601   return image->data.pixbuf.pixbuf;
602 }
603
604 /**
605  * gtk_image_get_stock:
606  * @image: a #GtkImage
607  * @stock_id: place to store a stock icon name
608  * @size: place to store a stock icon size
609  *
610  * Gets the stock icon name and size being displayed by the #GtkImage.
611  * The storage type of the image must be %GTK_IMAGE_EMPTY or
612  * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
613  * The returned string is owned by the #GtkImage and should not
614  * be freed.
615  * 
616  **/
617 void
618 gtk_image_get_stock  (GtkImage        *image,
619                       gchar          **stock_id,
620                       GtkIconSize     *size)
621 {
622   g_return_if_fail (GTK_IS_IMAGE (image));
623   g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
624                     image->storage_type == GTK_IMAGE_EMPTY);
625
626   if (image->storage_type == GTK_IMAGE_EMPTY)
627     image->data.stock.stock_id = NULL;
628   
629   if (stock_id)
630     *stock_id = image->data.stock.stock_id;
631
632   if (size)
633     *size = image->data.stock.size;
634 }
635
636 /**
637  * gtk_image_get_icon_set:
638  * @image: a #GtkImage
639  * @icon_set: location to store a #GtkIconSet
640  * @size: location to store a stock icon size
641  *
642  * Gets the icon set and size being displayed by the #GtkImage.
643  * The storage type of the image must be %GTK_IMAGE_EMPTY or
644  * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
645  * 
646  **/
647 void
648 gtk_image_get_icon_set  (GtkImage        *image,
649                          GtkIconSet     **icon_set,
650                          GtkIconSize     *size)
651 {
652   g_return_if_fail (GTK_IS_IMAGE (image));
653   g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
654                     image->storage_type == GTK_IMAGE_EMPTY);
655       
656   if (icon_set)    
657     *icon_set = image->data.icon_set.icon_set;
658
659   if (size)
660     *size = image->data.icon_set.size;
661 }
662
663 GtkWidget*
664 gtk_image_new (GdkImage  *val,
665                GdkBitmap *mask)
666 {
667   GtkImage *image;
668
669   g_return_val_if_fail (val != NULL, NULL);
670
671   image = gtk_type_new (GTK_TYPE_IMAGE);
672
673   gtk_image_set (image, val, mask);
674
675   return GTK_WIDGET (image);
676 }
677
678 void
679 gtk_image_set (GtkImage  *image,
680                GdkImage  *val,
681                GdkBitmap *mask)
682 {
683   g_return_if_fail (GTK_IS_IMAGE (image));
684
685   gtk_image_set_from_image (image, val, mask);
686 }
687
688 void
689 gtk_image_get (GtkImage   *image,
690                GdkImage  **val,
691                GdkBitmap **mask)
692 {
693   g_return_if_fail (GTK_IS_IMAGE (image));
694
695   gtk_image_get_image (image, val, mask);
696 }
697
698
699 static gint
700 gtk_image_expose (GtkWidget      *widget,
701                   GdkEventExpose *event)
702 {
703   g_return_val_if_fail (widget != NULL, FALSE);
704   g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
705   g_return_val_if_fail (event != NULL, FALSE);
706   
707   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
708       GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
709     {
710       GtkImage *image;
711       GtkMisc *misc;
712       GdkRectangle area, image_bound, intersection;
713       gint x, y;
714       GdkBitmap *mask = NULL;
715       GdkPixbuf *stock_pixbuf = NULL;
716       
717       image = GTK_IMAGE (widget);
718       misc = GTK_MISC (widget);
719
720       x = (widget->allocation.x * (1.0 - misc->xalign) +
721            (widget->allocation.x + widget->allocation.width
722             - (widget->requisition.width - misc->xpad * 2)) *
723            misc->xalign) + 0.5;
724       y = (widget->allocation.y * (1.0 - misc->yalign) +
725            (widget->allocation.y + widget->allocation.height
726             - (widget->requisition.height - misc->ypad * 2)) *
727            misc->yalign) + 0.5;
728
729       image_bound.x = x;
730       image_bound.y = y;      
731
732       switch (image->storage_type)
733         {
734         case GTK_IMAGE_PIXMAP:
735           mask = image->data.pixmap.mask;
736           gdk_drawable_get_size (image->data.pixmap.pixmap,
737                                  &image_bound.width,
738                                  &image_bound.height);
739           break;
740
741         case GTK_IMAGE_IMAGE:
742           mask = image->data.image.mask;
743           image_bound.width = image->data.image.image->width;
744           image_bound.height = image->data.image.image->height;
745           break;
746
747         case GTK_IMAGE_PIXBUF:
748           image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
749           image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
750           break;
751
752         case GTK_IMAGE_STOCK:
753           stock_pixbuf = gtk_widget_render_icon (widget,
754                                                  image->data.stock.stock_id,
755                                                  image->data.stock.size,
756                                                  NULL);
757           if (stock_pixbuf)
758             {              
759               image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
760               image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
761             }
762           break;
763
764         case GTK_IMAGE_ICON_SET:
765           stock_pixbuf =
766             gtk_icon_set_render_icon (image->data.icon_set.icon_set,
767                                       widget->style,
768                                       gtk_widget_get_direction (widget),
769                                       GTK_WIDGET_STATE (widget),
770                                       image->data.icon_set.size,
771                                       widget,
772                                       NULL);
773
774           if (stock_pixbuf)
775             {
776               image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
777               image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
778             }
779           break;
780           
781         default:
782           break;
783         }
784
785       if (mask)
786         {
787           gdk_gc_set_clip_mask (widget->style->black_gc, mask);
788           gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
789         }
790
791       area = event->area;
792       
793       if (gdk_rectangle_intersect (&image_bound, &area, &intersection))
794         {
795
796           switch (image->storage_type)
797             {
798             case GTK_IMAGE_PIXMAP:
799               gdk_draw_drawable (widget->window,
800                                  widget->style->black_gc,
801                                  image->data.pixmap.pixmap,
802                                  image_bound.x - x, image_bound.y - y,
803                                  image_bound.x, image_bound.y,
804                                  image_bound.width, image_bound.height);
805               break;
806               
807             case GTK_IMAGE_IMAGE:
808               gdk_draw_image (widget->window,
809                               widget->style->black_gc,
810                               image->data.image.image,
811                               image_bound.x - x, image_bound.y - y,
812                               image_bound.x, image_bound.y,
813                               image_bound.width, image_bound.height);
814               break;
815
816             case GTK_IMAGE_PIXBUF:
817               gdk_pixbuf_render_to_drawable_alpha (image->data.pixbuf.pixbuf,
818                                                    widget->window,
819                                                    image_bound.x - x,
820                                                    image_bound.y - y,
821                                                    image_bound.x,
822                                                    image_bound.y,
823                                                    image_bound.width,
824                                                    image_bound.height,
825                                                    GDK_PIXBUF_ALPHA_FULL,
826                                                    128,
827                                                    GDK_RGB_DITHER_NORMAL,
828                                                    0, 0);
829               break;
830
831             case GTK_IMAGE_STOCK: /* fall thru */
832             case GTK_IMAGE_ICON_SET:
833               if (stock_pixbuf)
834                 {
835                   gdk_pixbuf_render_to_drawable_alpha (stock_pixbuf,
836                                                        widget->window,
837                                                        image_bound.x - x,
838                                                        image_bound.y - y,
839                                                        image_bound.x,
840                                                        image_bound.y,
841                                                        image_bound.width,
842                                                        image_bound.height,
843                                                        GDK_PIXBUF_ALPHA_FULL,
844                                                        128,
845                                                        GDK_RGB_DITHER_NORMAL,
846                                                        0, 0);
847                   
848                   g_object_unref (G_OBJECT (stock_pixbuf));
849                 }
850               break;
851
852             default:
853               break;
854             }
855         } /* if rectangle intersects */      
856       if (mask)
857         {
858           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
859           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
860         }
861     } /* if widget is drawable */
862
863   return FALSE;
864 }
865
866 static void
867 gtk_image_clear (GtkImage *image)
868 {
869   switch (image->storage_type)
870     {
871     case GTK_IMAGE_PIXMAP:
872
873       if (image->data.pixmap.pixmap)
874         g_object_unref (G_OBJECT (image->data.pixmap.pixmap));
875
876       if (image->data.pixmap.mask)
877         g_object_unref (G_OBJECT (image->data.pixmap.mask));
878
879       image->data.pixmap.pixmap = NULL;
880       image->data.pixmap.mask = NULL;
881
882       break;
883
884     case GTK_IMAGE_IMAGE:
885
886       if (image->data.image.image)
887         g_object_unref (G_OBJECT (image->data.image.image));
888
889       if (image->data.image.mask)
890         g_object_unref (G_OBJECT (image->data.image.mask));
891
892       image->data.image.image = NULL;
893       image->data.image.mask = NULL;
894
895       break;
896
897     case GTK_IMAGE_PIXBUF:
898
899       if (image->data.pixbuf.pixbuf)
900         g_object_unref (G_OBJECT (image->data.pixbuf.pixbuf));
901
902       image->data.pixbuf.pixbuf = NULL;
903
904       break;
905
906     case GTK_IMAGE_STOCK:
907
908       g_free (image->data.stock.stock_id);
909
910       image->data.stock.stock_id = NULL;
911       image->data.stock.size = 0;
912       
913       break;
914
915     case GTK_IMAGE_ICON_SET:
916       if (image->data.icon_set.icon_set)
917         gtk_icon_set_unref (image->data.icon_set.icon_set);
918
919       image->data.icon_set.size = 0;
920       image->data.icon_set.icon_set = NULL;
921       
922       break;
923       
924     case GTK_IMAGE_EMPTY:
925     default:
926       break;
927       
928     }
929
930   image->storage_type = GTK_IMAGE_EMPTY;
931 }
932
933 static void
934 gtk_image_reset (GtkImage *image)
935 {
936   gtk_image_clear (image);
937   
938   GTK_WIDGET (image)->requisition.width = 0;
939   GTK_WIDGET (image)->requisition.height = 0;
940   
941   if (GTK_WIDGET_VISIBLE (image))
942     gtk_widget_queue_resize (GTK_WIDGET (image));
943 }
944
945 static void
946 gtk_image_size_request (GtkWidget      *widget,
947                         GtkRequisition *requisition)
948 {
949   GtkImage *image;
950   GdkPixbuf *pixbuf = NULL;
951   
952   image = GTK_IMAGE (widget);
953
954   switch (image->storage_type)
955     {
956     case GTK_IMAGE_STOCK:
957       pixbuf = gtk_widget_render_icon (GTK_WIDGET (image),
958                                        image->data.stock.stock_id,
959                                        image->data.stock.size,
960                                        NULL);
961       break;
962
963     case GTK_IMAGE_ICON_SET:
964       pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
965                                          widget->style,
966                                          gtk_widget_get_direction (widget),
967                                          GTK_WIDGET_STATE (widget),
968                                          image->data.icon_set.size,
969                                          widget,
970                                          NULL);
971       break;
972       
973     default:
974       break;
975     }
976
977   if (pixbuf)
978     {
979       gtk_image_update_size (image,
980                              gdk_pixbuf_get_width (pixbuf),
981                              gdk_pixbuf_get_height (pixbuf));
982       g_object_unref (G_OBJECT (pixbuf));
983     }
984
985   /* Chain up to default that simply reads current requisition */
986   GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
987 }
988
989 static void
990 gtk_image_update_size (GtkImage *image,
991                        gint      image_width,
992                        gint      image_height)
993 {
994   GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
995   GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;
996 }
997
998