]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererpixbuf.c
Support named icons in cells by adding a icon-name property. (#165777,
[~andy/gtk] / gtk / gtkcellrendererpixbuf.c
1 /* gtkcellrendererpixbuf.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 #include <config.h>
21 #include <stdlib.h>
22 #include "gtkcellrendererpixbuf.h"
23 #include "gtkiconfactory.h"
24 #include "gtkicontheme.h"
25 #include "gtkintl.h"
26 #include "gtkprivate.h"
27 #include "gtkalias.h"
28
29 static void gtk_cell_renderer_pixbuf_get_property  (GObject                    *object,
30                                                     guint                       param_id,
31                                                     GValue                     *value,
32                                                     GParamSpec                 *pspec);
33 static void gtk_cell_renderer_pixbuf_set_property  (GObject                    *object,
34                                                     guint                       param_id,
35                                                     const GValue               *value,
36                                                     GParamSpec                 *pspec);
37 static void gtk_cell_renderer_pixbuf_init       (GtkCellRendererPixbuf      *celltext);
38 static void gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class);
39 static void gtk_cell_renderer_pixbuf_finalize   (GObject                    *object);
40 static void gtk_cell_renderer_pixbuf_create_stock_pixbuf (GtkCellRendererPixbuf *cellpixbuf,
41                                                           GtkWidget             *widget);
42 static void gtk_cell_renderer_pixbuf_create_named_icon_pixbuf (GtkCellRendererPixbuf *cellpixbuf,
43                                                                GtkWidget             *widget);
44 static void gtk_cell_renderer_pixbuf_get_size   (GtkCellRenderer            *cell,
45                                                  GtkWidget                  *widget,
46                                                  GdkRectangle               *rectangle,
47                                                  gint                       *x_offset,
48                                                  gint                       *y_offset,
49                                                  gint                       *width,
50                                                  gint                       *height);
51 static void gtk_cell_renderer_pixbuf_render     (GtkCellRenderer            *cell,
52                                                  GdkDrawable                *window,
53                                                  GtkWidget                  *widget,
54                                                  GdkRectangle               *background_area,
55                                                  GdkRectangle               *cell_area,
56                                                  GdkRectangle               *expose_area,
57                                                  GtkCellRendererState        flags);
58
59
60 enum {
61         PROP_ZERO,
62         PROP_PIXBUF,
63         PROP_PIXBUF_EXPANDER_OPEN,
64         PROP_PIXBUF_EXPANDER_CLOSED,
65         PROP_STOCK_ID,
66         PROP_STOCK_SIZE,
67         PROP_STOCK_DETAIL,
68         PROP_FOLLOW_STATE,
69         PROP_ICON_NAME
70 };
71
72 static gpointer parent_class;
73
74
75 #define GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_RENDERER_PIXBUF, GtkCellRendererPixbufPrivate))
76
77 typedef struct _GtkCellRendererPixbufPrivate GtkCellRendererPixbufPrivate;
78 struct _GtkCellRendererPixbufPrivate
79 {
80   gchar *stock_id;
81   GtkIconSize stock_size;
82   gchar *stock_detail;
83   gboolean follow_state;
84
85   gchar *icon_name;
86 };
87
88
89 GType
90 gtk_cell_renderer_pixbuf_get_type (void)
91 {
92   static GType cell_pixbuf_type = 0;
93
94   if (!cell_pixbuf_type)
95     {
96       static const GTypeInfo cell_pixbuf_info =
97       {
98         sizeof (GtkCellRendererPixbufClass),
99         NULL,           /* base_init */
100         NULL,           /* base_finalize */
101         (GClassInitFunc) gtk_cell_renderer_pixbuf_class_init,
102         NULL,           /* class_finalize */
103         NULL,           /* class_data */
104         sizeof (GtkCellRendererPixbuf),
105         0,              /* n_preallocs */
106         (GInstanceInitFunc) gtk_cell_renderer_pixbuf_init,
107       };
108
109       cell_pixbuf_type =
110         g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererPixbuf",
111                                 &cell_pixbuf_info, 0);
112     }
113
114   return cell_pixbuf_type;
115 }
116
117 static void
118 gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *cellpixbuf)
119 {
120   GtkCellRendererPixbufPrivate *priv;
121
122   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cellpixbuf);
123   priv->stock_size = GTK_ICON_SIZE_MENU;
124 }
125
126 static void
127 gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
128 {
129   GObjectClass *object_class = G_OBJECT_CLASS (class);
130   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
131
132   parent_class = g_type_class_peek_parent (class);
133
134   object_class->finalize = gtk_cell_renderer_pixbuf_finalize;
135
136   object_class->get_property = gtk_cell_renderer_pixbuf_get_property;
137   object_class->set_property = gtk_cell_renderer_pixbuf_set_property;
138
139   cell_class->get_size = gtk_cell_renderer_pixbuf_get_size;
140   cell_class->render = gtk_cell_renderer_pixbuf_render;
141
142   g_object_class_install_property (object_class,
143                                    PROP_PIXBUF,
144                                    g_param_spec_object ("pixbuf",
145                                                         P_("Pixbuf Object"),
146                                                         P_("The pixbuf to render"),
147                                                         GDK_TYPE_PIXBUF,
148                                                         GTK_PARAM_READWRITE));
149
150   g_object_class_install_property (object_class,
151                                    PROP_PIXBUF_EXPANDER_OPEN,
152                                    g_param_spec_object ("pixbuf-expander-open",
153                                                         P_("Pixbuf Expander Open"),
154                                                         P_("Pixbuf for open expander"),
155                                                         GDK_TYPE_PIXBUF,
156                                                         GTK_PARAM_READWRITE));
157
158   g_object_class_install_property (object_class,
159                                    PROP_PIXBUF_EXPANDER_CLOSED,
160                                    g_param_spec_object ("pixbuf-expander-closed",
161                                                         P_("Pixbuf Expander Closed"),
162                                                         P_("Pixbuf for closed expander"),
163                                                         GDK_TYPE_PIXBUF,
164                                                         GTK_PARAM_READWRITE));
165
166   g_object_class_install_property (object_class,
167                                    PROP_STOCK_ID,
168                                    g_param_spec_string ("stock-id",
169                                                         P_("Stock ID"),
170                                                         P_("The stock ID of the stock icon to render"),
171                                                         NULL,
172                                                         GTK_PARAM_READWRITE));
173
174   g_object_class_install_property (object_class,
175                                    PROP_STOCK_SIZE,
176                                    g_param_spec_uint ("stock-size",
177                                                       P_("Size"),
178                                                       P_("The GtkIconSize value that specifies the size of the rendered icon"),
179                                                       0,
180                                                       G_MAXUINT,
181                                                       GTK_ICON_SIZE_MENU,
182                                                       GTK_PARAM_READWRITE));
183
184   g_object_class_install_property (object_class,
185                                    PROP_STOCK_DETAIL,
186                                    g_param_spec_string ("stock-detail",
187                                                         P_("Detail"),
188                                                         P_("Render detail to pass to the theme engine"),
189                                                         NULL,
190                                                         GTK_PARAM_READWRITE));
191
192   
193   /**
194    * GtkCellRendererPixbuf:icon-name:
195    *
196    * The name of the themed icon to display.
197    * This property only has an effect if not overridden by "stock_id" 
198    * or "pixbuf" properties.
199    *
200    * Since: 2.8 
201    */
202   g_object_class_install_property (object_class,
203                                    PROP_ICON_NAME,
204                                    g_param_spec_string ("icon-name",
205                                                         P_("Icon Name"),
206                                                         P_("The name of the icon from the icon theme"),
207                                                         NULL,
208                                                         GTK_PARAM_READWRITE));
209
210   /**
211    * GtkCellRendererPixbuf:follow-state:
212    *
213    * Specifies whether the rendered pixbuf should be colorized
214    * according to the #GtkCellRendererState.
215    *
216    * Since: 2.8
217    */
218   g_object_class_install_property (object_class,
219                                    PROP_FOLLOW_STATE,
220                                    g_param_spec_boolean ("follow-state",
221                                                          P_("Follow State"),
222                                                          P_("Whether the rendered pixbuf should be "
223                                                             "colorized according to the state"),
224                                                          FALSE,
225                                                          GTK_PARAM_READWRITE));
226
227
228   g_type_class_add_private (object_class, sizeof (GtkCellRendererPixbufPrivate));
229 }
230
231 static void
232 gtk_cell_renderer_pixbuf_finalize (GObject *object)
233 {
234   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
235   GtkCellRendererPixbufPrivate *priv;
236
237   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (object);
238   
239   if (cellpixbuf->pixbuf)
240     g_object_unref (cellpixbuf->pixbuf);
241
242   g_free (priv->stock_id);
243   g_free (priv->stock_detail);
244   g_free (priv->icon_name);
245
246   (* G_OBJECT_CLASS (parent_class)->finalize) (object);
247 }
248
249 static void
250 gtk_cell_renderer_pixbuf_get_property (GObject        *object,
251                                        guint           param_id,
252                                        GValue         *value,
253                                        GParamSpec     *pspec)
254 {
255   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
256   GtkCellRendererPixbufPrivate *priv;
257
258   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (object);
259   
260   switch (param_id)
261     {
262     case PROP_PIXBUF:
263       g_value_set_object (value,
264                           cellpixbuf->pixbuf ? G_OBJECT (cellpixbuf->pixbuf) : NULL);
265       break;
266     case PROP_PIXBUF_EXPANDER_OPEN:
267       g_value_set_object (value,
268                           cellpixbuf->pixbuf_expander_open ? G_OBJECT (cellpixbuf->pixbuf_expander_open) : NULL);
269       break;
270     case PROP_PIXBUF_EXPANDER_CLOSED:
271       g_value_set_object (value,
272                           cellpixbuf->pixbuf_expander_closed ? G_OBJECT (cellpixbuf->pixbuf_expander_closed) : NULL);
273       break;
274     case PROP_STOCK_ID:
275       g_value_set_string (value, priv->stock_id);
276       break;
277     case PROP_STOCK_SIZE:
278       g_value_set_uint (value, priv->stock_size);
279       break;
280     case PROP_STOCK_DETAIL:
281       g_value_set_string (value, priv->stock_detail);
282       break;
283     case PROP_FOLLOW_STATE:
284       g_value_set_boolean (value, priv->follow_state);
285       break;
286     case PROP_ICON_NAME:
287       g_value_set_string (value, priv->icon_name);
288       break;
289     default:
290       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
291       break;
292     }
293 }
294
295
296 static void
297 gtk_cell_renderer_pixbuf_set_property (GObject      *object,
298                                        guint         param_id,
299                                        const GValue *value,
300                                        GParamSpec   *pspec)
301 {
302   GdkPixbuf *pixbuf;
303   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
304   GtkCellRendererPixbufPrivate *priv;
305
306   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (object);
307   
308   switch (param_id)
309     {
310     case PROP_PIXBUF:
311       pixbuf = (GdkPixbuf*) g_value_get_object (value);
312       if (pixbuf)
313         g_object_ref (pixbuf);
314       if (cellpixbuf->pixbuf)
315         g_object_unref (cellpixbuf->pixbuf);
316       cellpixbuf->pixbuf = pixbuf;
317       break;
318     case PROP_PIXBUF_EXPANDER_OPEN:
319       pixbuf = (GdkPixbuf*) g_value_get_object (value);
320       if (pixbuf)
321         g_object_ref (pixbuf);
322       if (cellpixbuf->pixbuf_expander_open)
323         g_object_unref (cellpixbuf->pixbuf_expander_open);
324       cellpixbuf->pixbuf_expander_open = pixbuf;
325       break;
326     case PROP_PIXBUF_EXPANDER_CLOSED:
327       pixbuf = (GdkPixbuf*) g_value_get_object (value);
328       if (pixbuf)
329         g_object_ref (pixbuf);
330       if (cellpixbuf->pixbuf_expander_closed)
331         g_object_unref (cellpixbuf->pixbuf_expander_closed);
332       cellpixbuf->pixbuf_expander_closed = pixbuf;
333       break;
334     case PROP_STOCK_ID:
335       if (priv->stock_id)
336         {
337           if (cellpixbuf->pixbuf)
338             {
339               g_object_unref (cellpixbuf->pixbuf);
340               cellpixbuf->pixbuf = NULL;
341             }
342           g_free (priv->stock_id);
343           g_free (priv->icon_name);
344           priv->icon_name = NULL;
345         }
346       priv->stock_id = g_strdup (g_value_get_string (value));
347       break;
348     case PROP_STOCK_SIZE:
349       priv->stock_size = g_value_get_uint (value);
350       break;
351     case PROP_STOCK_DETAIL:
352       if (priv->stock_detail)
353         g_free (priv->stock_detail);
354       priv->stock_detail = g_strdup (g_value_get_string (value));
355       break;
356     case PROP_ICON_NAME:
357       if (priv->icon_name)
358         {
359           if (cellpixbuf->pixbuf)
360             {
361               g_object_unref (cellpixbuf->pixbuf);
362               cellpixbuf->pixbuf = NULL;
363             }
364           g_free (priv->stock_id);
365           g_free (priv->icon_name);
366         }
367       priv->icon_name = g_strdup (g_value_get_string (value));
368       break;
369     case PROP_FOLLOW_STATE:
370       priv->follow_state = g_value_get_boolean (value);
371       break;
372     default:
373       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
374       break;
375     }
376
377   if (cellpixbuf->pixbuf && priv->stock_id)
378     {
379       g_object_unref (cellpixbuf->pixbuf);
380       cellpixbuf->pixbuf = NULL;
381     }
382 }
383
384 /**
385  * gtk_cell_renderer_pixbuf_new:
386  * 
387  * Creates a new #GtkCellRendererPixbuf. Adjust rendering
388  * parameters using object properties. Object properties can be set
389  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
390  * can bind a property to a value in a #GtkTreeModel. For example, you
391  * can bind the "pixbuf" property on the cell renderer to a pixbuf value
392  * in the model, thus rendering a different image in each row of the
393  * #GtkTreeView.
394  * 
395  * Return value: the new cell renderer
396  **/
397 GtkCellRenderer *
398 gtk_cell_renderer_pixbuf_new (void)
399 {
400   return g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF, NULL);
401 }
402
403 static void
404 gtk_cell_renderer_pixbuf_create_stock_pixbuf (GtkCellRendererPixbuf *cellpixbuf,
405                                               GtkWidget             *widget)
406 {
407   GtkCellRendererPixbufPrivate *priv;
408
409   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cellpixbuf);
410
411   if (cellpixbuf->pixbuf)
412     g_object_unref (cellpixbuf->pixbuf);
413
414   cellpixbuf->pixbuf = gtk_widget_render_icon (widget,
415                                                priv->stock_id,
416                                                priv->stock_size,
417                                                priv->stock_detail);
418 }
419
420 static void 
421 gtk_cell_renderer_pixbuf_create_named_icon_pixbuf (GtkCellRendererPixbuf *cellpixbuf,
422                                                    GtkWidget             *widget)
423 {
424   GtkCellRendererPixbufPrivate *priv;
425   GdkScreen *screen;
426   GtkIconTheme *icon_theme;
427   GtkSettings *settings;
428   gint width, height;
429   GError *error = NULL;
430
431   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cellpixbuf);
432
433   if (cellpixbuf->pixbuf)
434     g_object_unref (cellpixbuf->pixbuf);
435
436   screen = gtk_widget_get_screen (GTK_WIDGET (widget));
437   icon_theme = gtk_icon_theme_get_for_screen (screen);
438   settings = gtk_settings_get_for_screen (screen);
439
440   if (!gtk_icon_size_lookup_for_settings (settings,
441                                           priv->stock_size,
442                                           &width, &height))
443     {
444       g_warning ("Invalid icon size %d\n", priv->stock_size);
445       width = height = 24;
446     }
447
448   cellpixbuf->pixbuf =
449     gtk_icon_theme_load_icon (icon_theme,
450                               priv->icon_name,
451                               MIN (width, height), 0, &error);
452   if (!cellpixbuf->pixbuf) 
453     {
454       g_warning ("could not load image: %s\n", error->message);
455       g_error_free (error);
456     }
457 }
458
459 static GdkPixbuf *
460 create_colorized_pixbuf (GdkPixbuf *src, 
461                          GdkColor  *new_color)
462 {
463   gint i, j;
464   gint width, height, has_alpha, src_row_stride, dst_row_stride;
465   gint red_value, green_value, blue_value;
466   guchar *target_pixels;
467   guchar *original_pixels;
468   guchar *pixsrc;
469   guchar *pixdest;
470   GdkPixbuf *dest;
471   
472   red_value = new_color->red / 255.0;
473   green_value = new_color->green / 255.0;
474   blue_value = new_color->blue / 255.0;
475   
476   dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
477                          gdk_pixbuf_get_has_alpha (src),
478                          gdk_pixbuf_get_bits_per_sample (src),
479                          gdk_pixbuf_get_width (src),
480                          gdk_pixbuf_get_height (src));
481   
482   has_alpha = gdk_pixbuf_get_has_alpha (src);
483   width = gdk_pixbuf_get_width (src);
484   height = gdk_pixbuf_get_height (src);
485   src_row_stride = gdk_pixbuf_get_rowstride (src);
486   dst_row_stride = gdk_pixbuf_get_rowstride (dest);
487   target_pixels = gdk_pixbuf_get_pixels (dest);
488   original_pixels = gdk_pixbuf_get_pixels (src);
489   
490   for (i = 0; i < height; i++) {
491     pixdest = target_pixels + i*dst_row_stride;
492     pixsrc = original_pixels + i*src_row_stride;
493     for (j = 0; j < width; j++) {               
494       *pixdest++ = (*pixsrc++ * red_value) >> 8;
495       *pixdest++ = (*pixsrc++ * green_value) >> 8;
496       *pixdest++ = (*pixsrc++ * blue_value) >> 8;
497       if (has_alpha) {
498         *pixdest++ = *pixsrc++;
499       }
500     }
501   }
502   return dest;
503 }
504
505
506 static void
507 gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
508                                    GtkWidget       *widget,
509                                    GdkRectangle    *cell_area,
510                                    gint            *x_offset,
511                                    gint            *y_offset,
512                                    gint            *width,
513                                    gint            *height)
514 {
515   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
516   GtkCellRendererPixbufPrivate *priv;
517   gint pixbuf_width  = 0;
518   gint pixbuf_height = 0;
519   gint calc_width;
520   gint calc_height;
521
522   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cell);
523
524   if (!cellpixbuf->pixbuf)
525     {
526       if (priv->stock_id)
527         gtk_cell_renderer_pixbuf_create_stock_pixbuf (cellpixbuf, widget);
528       else if (priv->icon_name)
529         gtk_cell_renderer_pixbuf_create_named_icon_pixbuf (cellpixbuf, widget);
530     }
531   
532   if (cellpixbuf->pixbuf)
533     {
534       pixbuf_width  = gdk_pixbuf_get_width (cellpixbuf->pixbuf);
535       pixbuf_height = gdk_pixbuf_get_height (cellpixbuf->pixbuf);
536     }
537   if (cellpixbuf->pixbuf_expander_open)
538     {
539       pixbuf_width  = MAX (pixbuf_width, gdk_pixbuf_get_width (cellpixbuf->pixbuf_expander_open));
540       pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (cellpixbuf->pixbuf_expander_open));
541     }
542   if (cellpixbuf->pixbuf_expander_closed)
543     {
544       pixbuf_width  = MAX (pixbuf_width, gdk_pixbuf_get_width (cellpixbuf->pixbuf_expander_closed));
545       pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (cellpixbuf->pixbuf_expander_closed));
546     }
547   
548   calc_width  = (gint) cell->xpad * 2 + pixbuf_width;
549   calc_height = (gint) cell->ypad * 2 + pixbuf_height;
550   
551   if (x_offset) *x_offset = 0;
552   if (y_offset) *y_offset = 0;
553
554   if (cell_area && pixbuf_width > 0 && pixbuf_height > 0)
555     {
556       if (x_offset)
557         {
558           *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
559                         1.0 - cell->xalign : cell->xalign) * 
560                        (cell_area->width - calc_width - 2 * cell->xpad));
561           *x_offset = MAX (*x_offset, 0) + cell->xpad;
562         }
563       if (y_offset)
564         {
565           *y_offset = (cell->yalign *
566                        (cell_area->height - calc_height - 2 * cell->ypad));
567           *y_offset = MAX (*y_offset, 0) + cell->ypad;
568         }
569     }
570
571   if (width)
572     *width = calc_width;
573   
574   if (height)
575     *height = calc_height;
576 }
577
578 static void
579 gtk_cell_renderer_pixbuf_render (GtkCellRenderer      *cell,
580                                  GdkWindow            *window,
581                                  GtkWidget            *widget,
582                                  GdkRectangle         *background_area,
583                                  GdkRectangle         *cell_area,
584                                  GdkRectangle         *expose_area,
585                                  GtkCellRendererState  flags)
586
587 {
588   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
589   GtkCellRendererPixbufPrivate *priv;
590   GdkPixbuf *pixbuf;
591   GdkPixbuf *invisible = NULL;
592   GdkPixbuf *colorized = NULL;
593   GdkRectangle pix_rect;
594   GdkRectangle draw_rect;
595   cairo_t *cr;
596
597   priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cell);
598
599   gtk_cell_renderer_pixbuf_get_size (cell, widget, cell_area,
600                                      &pix_rect.x,
601                                      &pix_rect.y,
602                                      &pix_rect.width,
603                                      &pix_rect.height);
604
605   pix_rect.x += cell_area->x;
606   pix_rect.y += cell_area->y;
607   pix_rect.width  -= cell->xpad * 2;
608   pix_rect.height -= cell->ypad * 2;
609
610   if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) ||
611       !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect))
612     return;
613
614   pixbuf = cellpixbuf->pixbuf;
615
616   if (cell->is_expander)
617     {
618       if (cell->is_expanded &&
619           cellpixbuf->pixbuf_expander_open != NULL)
620         pixbuf = cellpixbuf->pixbuf_expander_open;
621       else if (!cell->is_expanded &&
622                cellpixbuf->pixbuf_expander_closed != NULL)
623         pixbuf = cellpixbuf->pixbuf_expander_closed;
624     }
625
626   if (!pixbuf)
627     return;
628
629   if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE || !cell->sensitive)
630     {
631       GtkIconSource *source;
632       
633       source = gtk_icon_source_new ();
634       gtk_icon_source_set_pixbuf (source, pixbuf);
635       /* The size here is arbitrary; since size isn't
636        * wildcarded in the source, it isn't supposed to be
637        * scaled by the engine function
638        */
639       gtk_icon_source_set_size (source, GTK_ICON_SIZE_SMALL_TOOLBAR);
640       gtk_icon_source_set_size_wildcarded (source, FALSE);
641       
642      invisible = gtk_style_render_icon (widget->style,
643                                         source,
644                                         gtk_widget_get_direction (widget),
645                                         GTK_STATE_INSENSITIVE,
646                                         /* arbitrary */
647                                         (GtkIconSize)-1,
648                                         widget,
649                                         "gtkcellrendererpixbuf");
650      
651      gtk_icon_source_free (source);
652      
653      pixbuf = invisible;
654     }
655   else if (priv->follow_state && 
656            (flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_PRELIT)) != 0)
657     {
658       GtkStateType state;
659
660       if ((flags & GTK_CELL_RENDERER_SELECTED) != 0)
661         {
662           if (GTK_WIDGET_HAS_FOCUS (widget))
663             state = GTK_STATE_SELECTED;
664           else
665             state = GTK_STATE_ACTIVE;
666         }
667       else
668         state = GTK_STATE_PRELIGHT;
669
670       colorized = create_colorized_pixbuf (pixbuf,
671                                            &widget->style->base[state]);
672
673       pixbuf = colorized;
674     }
675
676   cr = gdk_cairo_create (window);
677   
678   gdk_cairo_set_source_pixbuf (cr, pixbuf, pix_rect.x, pix_rect.y);
679   gdk_cairo_rectangle (cr, &draw_rect);
680   cairo_fill (cr);
681
682   cairo_destroy (cr);
683   
684   if (invisible)
685     g_object_unref (invisible);
686
687   if (colorized)
688     g_object_unref (colorized);
689 }
690
691 #define __GTK_CELL_RENDERER_PIXBUF_C__
692 #include "gtkaliasdef.c"