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