]> Pileus Git - ~andy/gtk/blob - modules/engines/pixbuf/pixbuf-draw.c
Silence the compiler.
[~andy/gtk] / modules / engines / pixbuf / pixbuf-draw.c
1 /* GTK+ Pixbuf Engine
2  * Copyright (C) 1998-2000 Red Hat, Inc.
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  * Written by Owen Taylor <otaylor@redhat.com>, based on code by
20  * Carsten Haitzler <raster@rasterman.com>
21  */
22
23 #include <math.h>
24 #include <string.h>
25
26 #undef GDK_DISABLE_DEPRECATED
27
28 #include "pixbuf.h"
29 #include "pixbuf-rc-style.h"
30 #include "pixbuf-style.h"
31
32 static void pixbuf_style_init       (PixbufStyle      *style);
33 static void pixbuf_style_class_init (PixbufStyleClass *klass);
34
35 static GtkStyleClass *parent_class = NULL;
36
37 static ThemeImage *
38 match_theme_image (GtkStyle       *style,
39                    ThemeMatchData *match_data)
40 {
41   GList *tmp_list;
42
43   tmp_list = PIXBUF_RC_STYLE (style->rc_style)->img_list;
44   
45   while (tmp_list)
46     {
47       guint flags;
48       ThemeImage *image = tmp_list->data;
49       tmp_list = tmp_list->next;
50
51       if (match_data->function != image->match_data.function)
52         continue;
53
54       flags = match_data->flags & image->match_data.flags;
55       
56       if (flags != image->match_data.flags) /* Required components not present */
57         continue;
58
59       if ((flags & THEME_MATCH_STATE) &&
60           match_data->state != image->match_data.state)
61         continue;
62
63       if ((flags & THEME_MATCH_SHADOW) &&
64           match_data->shadow != image->match_data.shadow)
65         continue;
66       
67       if ((flags & THEME_MATCH_ARROW_DIRECTION) &&
68           match_data->arrow_direction != image->match_data.arrow_direction)
69         continue;
70
71       if ((flags & THEME_MATCH_ORIENTATION) &&
72           match_data->orientation != image->match_data.orientation)
73         continue;
74
75       if ((flags & THEME_MATCH_GAP_SIDE) &&
76           match_data->gap_side != image->match_data.gap_side)
77         continue;
78
79       if (image->match_data.detail &&
80           (!match_data->detail ||
81            strcmp (match_data->detail, image->match_data.detail) != 0))
82       continue;
83
84       return image;
85     }
86   
87   return NULL;
88 }
89
90 static gboolean
91 draw_simple_image(GtkStyle       *style,
92                   GdkWindow      *window,
93                   GdkRectangle   *area,
94                   GtkWidget      *widget,
95                   ThemeMatchData *match_data,
96                   gboolean        draw_center,
97                   gboolean        allow_setbg,
98                   gint            x,
99                   gint            y,
100                   gint            width,
101                   gint            height)
102 {
103   ThemeImage *image;
104   gboolean setbg = FALSE;
105   
106   if ((width == -1) && (height == -1))
107     {
108       gdk_drawable_get_size(window, &width, &height);
109       if (allow_setbg)
110         setbg = TRUE;
111     }
112   else if (width == -1)
113     gdk_drawable_get_size(window, &width, NULL);
114   else if (height == -1)
115     gdk_drawable_get_size(window, NULL, &height);
116
117   if (!(match_data->flags & THEME_MATCH_ORIENTATION))
118     {
119       match_data->flags |= THEME_MATCH_ORIENTATION;
120       
121       if (height > width)
122         match_data->orientation = GTK_ORIENTATION_VERTICAL;
123       else
124         match_data->orientation = GTK_ORIENTATION_HORIZONTAL;
125     }
126     
127   image = match_theme_image (style, match_data);
128   if (image)
129     {
130       if (image->background)
131         {
132           theme_pixbuf_render (image->background,
133                                window, NULL, area,
134                                draw_center ? COMPONENT_ALL : COMPONENT_ALL | COMPONENT_CENTER,
135                                FALSE,
136                                x, y, width, height);
137         }
138       
139       if (image->overlay && draw_center)
140         theme_pixbuf_render (image->overlay,
141                              window, NULL, area, COMPONENT_ALL,
142                              TRUE, 
143                              x, y, width, height);
144
145       return TRUE;
146     }
147   else
148     return FALSE;
149 }
150
151 static gboolean
152 draw_gap_image(GtkStyle       *style,
153                GdkWindow      *window,
154                GdkRectangle   *area,
155                GtkWidget      *widget,
156                ThemeMatchData *match_data,
157                gboolean        draw_center,
158                gint            x,
159                gint            y,
160                gint            width,
161                gint            height,
162                GtkPositionType gap_side,
163                gint            gap_x,
164                gint            gap_width)
165 {
166   ThemeImage *image;
167   gboolean setbg = FALSE;
168   
169   if ((width == -1) && (height == -1))
170     {
171       gdk_drawable_get_size(window, &width, &height);
172       setbg = TRUE;
173     }
174   else if (width == -1)
175     gdk_drawable_get_size(window, &width, NULL);
176   else if (height == -1)
177     gdk_drawable_get_size(window, NULL, &height);
178
179   if (!(match_data->flags & THEME_MATCH_ORIENTATION))
180     {
181       match_data->flags |= THEME_MATCH_ORIENTATION;
182       
183       if (height > width)
184         match_data->orientation = GTK_ORIENTATION_VERTICAL;
185       else
186         match_data->orientation = GTK_ORIENTATION_HORIZONTAL;
187     }
188
189   match_data->flags |= THEME_MATCH_GAP_SIDE;
190   match_data->gap_side = gap_side;
191     
192   image = match_theme_image (style, match_data);
193   if (image)
194     {
195       gint thickness;
196       GdkRectangle r1, r2, r3;
197       GdkPixbuf *pixbuf = NULL;
198       guint components = COMPONENT_ALL;
199
200       if (!draw_center)
201         components |= COMPONENT_CENTER;
202
203       if (image->gap_start)
204         pixbuf = theme_pixbuf_get_pixbuf (image->gap_start);
205
206       switch (gap_side)
207         {
208         case GTK_POS_TOP:
209           if (pixbuf)
210             thickness = gdk_pixbuf_get_height (pixbuf);
211           else
212             thickness = style->ythickness;
213           
214           if (!draw_center)
215             components |= COMPONENT_NORTH_WEST | COMPONENT_NORTH | COMPONENT_NORTH_EAST;
216
217           r1.x      = x;
218           r1.y      = y;
219           r1.width  = gap_x;
220           r1.height = thickness;
221           r2.x      = x + gap_x;
222           r2.y      = y;
223           r2.width  = gap_width;
224           r2.height = thickness;
225           r3.x      = x + gap_x + gap_width;
226           r3.y      = y;
227           r3.width  = width - (gap_x + gap_width);
228           r3.height = thickness;
229           break;
230           
231         case GTK_POS_BOTTOM:
232           if (pixbuf)
233             thickness = gdk_pixbuf_get_height (pixbuf);
234           else
235             thickness = style->ythickness;
236
237           if (!draw_center)
238             components |= COMPONENT_SOUTH_WEST | COMPONENT_SOUTH | COMPONENT_SOUTH_EAST;
239
240           r1.x      = x;
241           r1.y      = y + height - thickness;
242           r1.width  = gap_x;
243           r1.height = thickness;
244           r2.x      = x + gap_x;
245           r2.y      = y + height - thickness;
246           r2.width  = gap_width;
247           r2.height = thickness;
248           r3.x      = x + gap_x + gap_width;
249           r3.y      = y + height - thickness;
250           r3.width  = width - (gap_x + gap_width);
251           r3.height = thickness;
252           break;
253           
254         case GTK_POS_LEFT:
255           if (pixbuf)
256             thickness = gdk_pixbuf_get_width (pixbuf);
257           else
258             thickness = style->xthickness;
259
260           if (!draw_center)
261             components |= COMPONENT_NORTH_WEST | COMPONENT_WEST | COMPONENT_SOUTH_WEST;
262
263           r1.x      = x;
264           r1.y      = y;
265           r1.width  = thickness;
266           r1.height = gap_x;
267           r2.x      = x;
268           r2.y      = y + gap_x;
269           r2.width  = thickness;
270           r2.height = gap_width;
271           r3.x      = x;
272           r3.y      = y + gap_x + gap_width;
273           r3.width  = thickness;
274           r3.height = height - (gap_x + gap_width);
275           break;
276           
277         case GTK_POS_RIGHT:
278           if (pixbuf)
279             thickness = gdk_pixbuf_get_width (pixbuf);
280           else
281             thickness = style->xthickness;
282
283           if (!draw_center)
284             components |= COMPONENT_NORTH_EAST | COMPONENT_EAST | COMPONENT_SOUTH_EAST;
285
286           r1.x      = x + width - thickness;
287           r1.y      = y;
288           r1.width  = thickness;
289           r1.height = gap_x;
290           r2.x      = x + width - thickness;
291           r2.y      = y + gap_x;
292           r2.width  = thickness;
293           r2.height = gap_width;
294           r3.x      = x + width - thickness;
295           r3.y      = y + gap_x + gap_width;
296           r3.width  = thickness;
297           r3.height = height - (gap_x + gap_width);
298           break;
299
300         default:
301           g_assert_not_reached ();
302         }
303
304       if (image->background)
305         theme_pixbuf_render (image->background,
306                              window, NULL, area, components, FALSE,
307                              x, y, width, height);
308       if (image->gap_start)
309         theme_pixbuf_render (image->gap_start,
310                              window, NULL, area, COMPONENT_ALL, FALSE,
311                              r1.x, r1.y, r1.width, r1.height);
312       if (image->gap)
313         theme_pixbuf_render (image->gap,
314                              window, NULL, area, COMPONENT_ALL, FALSE,
315                              r2.x, r2.y, r2.width, r2.height);
316       if (image->gap_end)
317         theme_pixbuf_render (image->gap_end,
318                              window, NULL, area, COMPONENT_ALL, FALSE,
319                              r3.x, r3.y, r3.width, r3.height);
320
321       return TRUE;
322     }
323   else
324     return FALSE;
325 }
326
327 static void
328 draw_hline (GtkStyle     *style,
329             GdkWindow    *window,
330             GtkStateType  state,
331             GdkRectangle *area,
332             GtkWidget    *widget,
333             const gchar  *detail,
334             gint          x1,
335             gint          x2,
336             gint          y)
337 {
338   ThemeImage *image;
339   ThemeMatchData   match_data;
340   
341   g_return_if_fail(style != NULL);
342   g_return_if_fail(window != NULL);
343
344   match_data.function = TOKEN_D_HLINE;
345   match_data.detail = (gchar *)detail;
346   match_data.flags = THEME_MATCH_ORIENTATION | THEME_MATCH_STATE;
347   match_data.state = state;
348   match_data.orientation = GTK_ORIENTATION_HORIZONTAL;
349   
350   image = match_theme_image (style, &match_data);
351   if (image)
352     {
353       if (image->background)
354         theme_pixbuf_render (image->background,
355                              window, NULL, area, COMPONENT_ALL, FALSE,
356                              x1, y, (x2 - x1) + 1, 2);
357     }
358   else
359     parent_class->draw_hline (style, window, state, area, widget, detail,
360                               x1, x2, y);
361 }
362
363 static void
364 draw_vline (GtkStyle     *style,
365             GdkWindow    *window,
366             GtkStateType  state,
367             GdkRectangle *area,
368             GtkWidget    *widget,
369             const gchar  *detail,
370             gint          y1,
371             gint          y2,
372             gint          x)
373 {
374   ThemeImage    *image;
375   ThemeMatchData match_data;
376   
377   g_return_if_fail (style != NULL);
378   g_return_if_fail (window != NULL);
379
380   match_data.function = TOKEN_D_VLINE;
381   match_data.detail = (gchar *)detail;
382   match_data.flags = THEME_MATCH_ORIENTATION | THEME_MATCH_STATE;
383   match_data.state = state;
384   match_data.orientation = GTK_ORIENTATION_VERTICAL;
385   
386   image = match_theme_image (style, &match_data);
387   if (image)
388     {
389       if (image->background)
390         theme_pixbuf_render (image->background,
391                              window, NULL, area, COMPONENT_ALL, FALSE,
392                              x, y1, 2, (y2 - y1) + 1);
393     }
394   else
395     parent_class->draw_vline (style, window, state, area, widget, detail,
396                               y1, y2, x);
397 }
398
399 static void
400 draw_shadow(GtkStyle     *style,
401             GdkWindow    *window,
402             GtkStateType  state,
403             GtkShadowType shadow,
404             GdkRectangle *area,
405             GtkWidget    *widget,
406             const gchar  *detail,
407             gint          x,
408             gint          y,
409             gint          width,
410             gint          height)
411 {
412   ThemeMatchData match_data;
413   
414   g_return_if_fail(style != NULL);
415   g_return_if_fail(window != NULL);
416
417   match_data.function = TOKEN_D_SHADOW;
418   match_data.detail = (gchar *)detail;
419   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
420   match_data.shadow = shadow;
421   match_data.state = state;
422
423   if (!draw_simple_image (style, window, area, widget, &match_data, FALSE, FALSE,
424                           x, y, width, height))
425     parent_class->draw_shadow (style, window, state, shadow, area, widget, detail,
426                                x, y, width, height);
427 }
428
429 /* This function makes up for some brokeness in gtkrange.c
430  * where we never get the full arrow of the stepper button
431  * and the type of button in a single drawing function.
432  *
433  * It doesn't work correctly when the scrollbar is squished
434  * to the point we don't have room for full-sized steppers.
435  */
436 static void
437 reverse_engineer_stepper_box (GtkWidget    *range,
438                               GtkArrowType  arrow_type,
439                               gint         *x,
440                               gint         *y,
441                               gint         *width,
442                               gint         *height)
443 {
444   gint slider_width = 14, stepper_size = 14;
445   gint box_width;
446   gint box_height;
447   
448   if (range)
449     {
450       gtk_widget_style_get (range,
451                             "slider_width", &slider_width,
452                             "stepper_size", &stepper_size,
453                             NULL);
454     }
455         
456   if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
457     {
458       box_width = slider_width;
459       box_height = stepper_size;
460     }
461   else
462     {
463       box_width = stepper_size;
464       box_height = slider_width;
465     }
466
467   *x = *x - (box_width - *width) / 2;
468   *y = *y - (box_height - *height) / 2;
469   *width = box_width;
470   *height = box_height;
471 }
472
473 static void
474 draw_arrow (GtkStyle     *style,
475             GdkWindow    *window,
476             GtkStateType  state,
477             GtkShadowType shadow,
478             GdkRectangle *area,
479             GtkWidget    *widget,
480             const gchar  *detail,
481             GtkArrowType  arrow_direction,
482             gint          fill,
483             gint          x,
484             gint          y,
485             gint          width,
486             gint          height)
487 {
488   ThemeMatchData match_data;
489   
490   g_return_if_fail(style != NULL);
491   g_return_if_fail(window != NULL);
492
493   if (detail &&
494       (strcmp (detail, "hscrollbar") == 0 || strcmp (detail, "vscrollbar") == 0))
495     {
496       /* This is a hack to work around the fact that scrollbar steppers are drawn
497        * as a box + arrow, so we never have
498        *
499        *   The full bounding box of the scrollbar 
500        *   The arrow direction
501        *
502        * At the same time. We simulate an extra paint function, "STEPPER", by doing
503        * nothing for the box, and then here, reverse engineering the box that
504        * was passed to draw box and using that
505        */
506       gint box_x = x;
507       gint box_y = y;
508       gint box_width = width;
509       gint box_height = height;
510
511       reverse_engineer_stepper_box (widget, arrow_direction,
512                                     &box_x, &box_y, &box_width, &box_height);
513
514       match_data.function = TOKEN_D_STEPPER;
515       match_data.detail = (gchar *)detail;
516       match_data.flags = (THEME_MATCH_SHADOW | 
517                           THEME_MATCH_STATE | 
518                           THEME_MATCH_ARROW_DIRECTION);
519       match_data.shadow = shadow;
520       match_data.state = state;
521       match_data.arrow_direction = arrow_direction;
522       
523       if (draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
524                              box_x, box_y, box_width, box_height))
525         {
526           /* The theme included stepper images, we're done */
527           return;
528         }
529
530       /* Otherwise, draw the full box, and fall through to draw the arrow
531        */
532       match_data.function = TOKEN_D_BOX;
533       match_data.detail = (gchar *)detail;
534       match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
535       match_data.shadow = shadow;
536       match_data.state = state;
537       
538       if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
539                               box_x, box_y, box_width, box_height))
540         parent_class->draw_box (style, window, state, shadow, area, widget, detail,
541                                 box_x, box_y, box_width, box_height);
542     }
543
544
545   match_data.function = TOKEN_D_ARROW;
546   match_data.detail = (gchar *)detail;
547   match_data.flags = (THEME_MATCH_SHADOW | 
548                       THEME_MATCH_STATE | 
549                       THEME_MATCH_ARROW_DIRECTION);
550   match_data.shadow = shadow;
551   match_data.state = state;
552   match_data.arrow_direction = arrow_direction;
553   
554   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
555                           x, y, width, height))
556     parent_class->draw_arrow (style, window, state, shadow, area, widget, detail,
557                               arrow_direction, fill, x, y, width, height);
558 }
559
560 static void
561 draw_diamond (GtkStyle     *style,
562               GdkWindow    *window,
563               GtkStateType  state,
564               GtkShadowType shadow,
565               GdkRectangle *area,
566               GtkWidget    *widget,
567               const gchar  *detail,
568               gint          x,
569               gint          y,
570               gint          width,
571               gint          height)
572 {
573   ThemeMatchData match_data;
574   
575   g_return_if_fail(style != NULL);
576   g_return_if_fail(window != NULL);
577
578   match_data.function = TOKEN_D_DIAMOND;
579   match_data.detail = (gchar *)detail;
580   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
581   match_data.shadow = shadow;
582   match_data.state = state;
583   
584   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
585                           x, y, width, height))
586     parent_class->draw_diamond (style, window, state, shadow, area, widget, detail,
587                                 x, y, width, height);
588 }
589
590 static void
591 draw_string (GtkStyle * style,
592              GdkWindow * window,
593              GtkStateType state,
594              GdkRectangle * area,
595              GtkWidget * widget,
596              const gchar *detail,
597              gint x,
598              gint y,
599              const gchar * string)
600 {
601   g_return_if_fail(style != NULL);
602   g_return_if_fail(window != NULL);
603
604   if (state == GTK_STATE_INSENSITIVE)
605     {
606       if (area)
607         {
608           gdk_gc_set_clip_rectangle(style->white_gc, area);
609           gdk_gc_set_clip_rectangle(style->fg_gc[state], area);
610         }
611
612       gdk_draw_string(window, gtk_style_get_font (style), style->fg_gc[state], x, y, string);
613       
614       if (area)
615         {
616           gdk_gc_set_clip_rectangle(style->white_gc, NULL);
617           gdk_gc_set_clip_rectangle(style->fg_gc[state], NULL);
618         }
619     }
620   else
621     {
622       gdk_gc_set_clip_rectangle(style->fg_gc[state], area);
623       gdk_draw_string(window, gtk_style_get_font (style), style->fg_gc[state], x, y, string);
624       gdk_gc_set_clip_rectangle(style->fg_gc[state], NULL);
625     }
626 }
627
628 static void
629 draw_box (GtkStyle     *style,
630           GdkWindow    *window,
631           GtkStateType  state,
632           GtkShadowType shadow,
633           GdkRectangle *area,
634           GtkWidget    *widget,
635           const gchar  *detail,
636           gint          x,
637           gint          y,
638           gint          width,
639           gint          height)
640 {
641   ThemeMatchData match_data;
642
643   g_return_if_fail(style != NULL);
644   g_return_if_fail(window != NULL);
645
646   if (detail &&
647       (strcmp (detail, "hscrollbar") == 0 || strcmp (detail, "vscrollbar") == 0))
648     {
649       /* We handle this in draw_arrow */
650       return;
651     }
652
653   match_data.function = TOKEN_D_BOX;
654   match_data.detail = (gchar *)detail;
655   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
656   match_data.shadow = shadow;
657   match_data.state = state;
658
659   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
660                           x, y, width, height)) {
661     parent_class->draw_box (style, window, state, shadow, area, widget, detail,
662                             x, y, width, height);
663   }
664 }
665
666 static void
667 draw_flat_box (GtkStyle     *style,
668                GdkWindow    *window,
669                GtkStateType  state,
670                GtkShadowType shadow,
671                GdkRectangle *area,
672                GtkWidget    *widget,
673                const gchar  *detail,
674                gint          x,
675                gint          y,
676                gint          width,
677                gint          height)
678 {
679   ThemeMatchData match_data;
680   
681   g_return_if_fail(style != NULL);
682   g_return_if_fail(window != NULL);
683
684   match_data.function = TOKEN_D_FLAT_BOX;
685   match_data.detail = (gchar *)detail;
686   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
687   match_data.shadow = shadow;
688   match_data.state = state;
689
690   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
691                           x, y, width, height))
692     parent_class->draw_flat_box (style, window, state, shadow, area, widget, detail,
693                                  x, y, width, height);
694 }
695
696 static void
697 draw_check (GtkStyle     *style,
698             GdkWindow    *window,
699             GtkStateType  state,
700             GtkShadowType shadow,
701             GdkRectangle *area,
702             GtkWidget    *widget,
703             const gchar  *detail,
704             gint          x,
705             gint          y,
706             gint          width,
707             gint          height)
708 {
709   ThemeMatchData match_data;
710   
711   g_return_if_fail(style != NULL);
712   g_return_if_fail(window != NULL);
713
714   match_data.function = TOKEN_D_CHECK;
715   match_data.detail = (gchar *)detail;
716   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
717   match_data.shadow = shadow;
718   match_data.state = state;
719   
720   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
721                           x, y, width, height))
722     parent_class->draw_check (style, window, state, shadow, area, widget, detail,
723                               x, y, width, height);
724 }
725
726 static void
727 draw_option (GtkStyle      *style,
728              GdkWindow     *window,
729              GtkStateType  state,
730              GtkShadowType shadow,
731              GdkRectangle *area,
732              GtkWidget    *widget,
733              const gchar  *detail,
734              gint          x,
735              gint          y,
736              gint          width,
737              gint          height)
738 {
739   ThemeMatchData match_data;
740   
741   g_return_if_fail(style != NULL);
742   g_return_if_fail(window != NULL);
743
744   match_data.function = TOKEN_D_OPTION;
745   match_data.detail = (gchar *)detail;
746   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
747   match_data.shadow = shadow;
748   match_data.state = state;
749   
750   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
751                           x, y, width, height))
752     parent_class->draw_option (style, window, state, shadow, area, widget, detail,
753                                x, y, width, height);
754 }
755
756 static void
757 draw_tab (GtkStyle     *style,
758           GdkWindow    *window,
759           GtkStateType  state,
760           GtkShadowType shadow,
761           GdkRectangle *area,
762           GtkWidget    *widget,
763           const gchar  *detail,
764           gint          x,
765           gint          y,
766           gint          width,
767           gint          height)
768 {
769   ThemeMatchData match_data;
770   
771   g_return_if_fail(style != NULL);
772   g_return_if_fail(window != NULL);
773
774   match_data.function = TOKEN_D_TAB;
775   match_data.detail = (gchar *)detail;
776   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
777   match_data.shadow = shadow;
778   match_data.state = state;
779   
780   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
781                           x, y, width, height))
782     parent_class->draw_tab (style, window, state, shadow, area, widget, detail,
783                             x, y, width, height);
784 }
785
786 static void
787 draw_shadow_gap (GtkStyle       *style,
788                  GdkWindow      *window,
789                  GtkStateType    state,
790                  GtkShadowType   shadow,
791                  GdkRectangle   *area,
792                  GtkWidget      *widget,
793                  const gchar    *detail,
794                  gint            x,
795                  gint            y,
796                  gint            width,
797                  gint            height,
798                  GtkPositionType gap_side,
799                  gint            gap_x,
800                  gint            gap_width)
801 {
802   ThemeMatchData match_data;
803   
804   match_data.function = TOKEN_D_SHADOW_GAP;
805   match_data.detail = (gchar *)detail;
806   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
807   match_data.flags = (THEME_MATCH_SHADOW | 
808                       THEME_MATCH_STATE | 
809                       THEME_MATCH_ORIENTATION);
810   match_data.shadow = shadow;
811   match_data.state = state;
812   
813   if (!draw_gap_image (style, window, area, widget, &match_data, FALSE,
814                        x, y, width, height, gap_side, gap_x, gap_width))
815     parent_class->draw_shadow_gap (style, window, state, shadow, area, widget, detail,
816                                    x, y, width, height, gap_side, gap_x, gap_width);
817 }
818
819 static void
820 draw_box_gap (GtkStyle       *style,
821               GdkWindow      *window,
822               GtkStateType    state,
823               GtkShadowType   shadow,
824               GdkRectangle   *area,
825               GtkWidget      *widget,
826               const gchar    *detail,
827               gint            x,
828               gint            y,
829               gint            width,
830               gint            height,
831               GtkPositionType gap_side,
832               gint            gap_x,
833               gint            gap_width)
834 {
835   ThemeMatchData match_data;
836   
837   match_data.function = TOKEN_D_BOX_GAP;
838   match_data.detail = (gchar *)detail;
839   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE;
840   match_data.flags = (THEME_MATCH_SHADOW | 
841                       THEME_MATCH_STATE | 
842                       THEME_MATCH_ORIENTATION);
843   match_data.shadow = shadow;
844   match_data.state = state;
845   
846   if (!draw_gap_image (style, window, area, widget, &match_data, TRUE,
847                        x, y, width, height, gap_side, gap_x, gap_width))
848     parent_class->draw_box_gap (style, window, state, shadow, area, widget, detail,
849                                 x, y, width, height, gap_side, gap_x, gap_width);
850 }
851
852 static void
853 draw_extension (GtkStyle       *style,
854                 GdkWindow      *window,
855                 GtkStateType    state,
856                 GtkShadowType   shadow,
857                 GdkRectangle   *area,
858                 GtkWidget      *widget,
859                 const gchar    *detail,
860                 gint            x,
861                 gint            y,
862                 gint            width,
863                 gint            height,
864                 GtkPositionType gap_side)
865 {
866   ThemeMatchData match_data;
867   
868   g_return_if_fail(style != NULL);
869   g_return_if_fail(window != NULL);
870
871   /* Why? */
872   if (width >=0)
873     width++;
874   if (height >=0)
875     height++;
876   
877   match_data.function = TOKEN_D_EXTENSION;
878   match_data.detail = (gchar *)detail;
879   match_data.flags = THEME_MATCH_SHADOW | THEME_MATCH_STATE | THEME_MATCH_GAP_SIDE;
880   match_data.shadow = shadow;
881   match_data.state = state;
882   match_data.gap_side = gap_side;
883
884   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
885                           x, y, width, height))
886     parent_class->draw_extension (style, window, state, shadow, area, widget, detail,
887                                   x, y, width, height, gap_side);
888 }
889
890 static void
891 draw_focus (GtkStyle     *style,
892             GdkWindow    *window,
893             GtkStateType  state_type,
894             GdkRectangle *area,
895             GtkWidget    *widget,
896             const gchar  *detail,
897             gint          x,
898             gint          y,
899             gint          width,
900             gint          height)
901 {
902   ThemeMatchData match_data;
903   
904   g_return_if_fail(style != NULL);
905   g_return_if_fail(window != NULL);
906
907   match_data.function = TOKEN_D_FOCUS;
908   match_data.detail = (gchar *)detail;
909   match_data.flags = 0;
910   
911   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, FALSE,
912                           x, y, width, height))
913     parent_class->draw_focus (style, window, state_type, area, widget, detail,
914                               x, y, width, height);
915 }
916
917 static void
918 draw_slider (GtkStyle      *style,
919              GdkWindow     *window,
920              GtkStateType   state,
921              GtkShadowType  shadow,
922              GdkRectangle  *area,
923              GtkWidget     *widget,
924              const gchar   *detail,
925              gint           x,
926              gint           y,
927              gint           width,
928              gint           height,
929              GtkOrientation orientation)
930 {
931   ThemeMatchData           match_data;
932   
933   g_return_if_fail(style != NULL);
934   g_return_if_fail(window != NULL);
935
936   match_data.function = TOKEN_D_SLIDER;
937   match_data.detail = (gchar *)detail;
938   match_data.flags = (THEME_MATCH_SHADOW | 
939                       THEME_MATCH_STATE | 
940                       THEME_MATCH_ORIENTATION);
941   match_data.shadow = shadow;
942   match_data.state = state;
943   match_data.orientation = orientation;
944
945   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
946                           x, y, width, height))
947     parent_class->draw_slider (style, window, state, shadow, area, widget, detail,
948                                x, y, width, height, orientation);
949 }
950
951
952 static void
953 draw_handle (GtkStyle      *style,
954              GdkWindow     *window,
955              GtkStateType   state,
956              GtkShadowType  shadow,
957              GdkRectangle  *area,
958              GtkWidget     *widget,
959              const gchar   *detail,
960              gint           x,
961              gint           y,
962              gint           width,
963              gint           height,
964              GtkOrientation orientation)
965 {
966   ThemeMatchData match_data;
967   
968   g_return_if_fail (style != NULL);
969   g_return_if_fail (window != NULL);
970
971   match_data.function = TOKEN_D_HANDLE;
972   match_data.detail = (gchar *)detail;
973   match_data.flags = (THEME_MATCH_SHADOW | 
974                       THEME_MATCH_STATE | 
975                       THEME_MATCH_ORIENTATION);
976   match_data.shadow = shadow;
977   match_data.state = state;
978   match_data.orientation = orientation;
979
980   if (!draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
981                           x, y, width, height))
982     parent_class->draw_handle (style, window, state, shadow, area, widget, detail,
983                                x, y, width, height, orientation);
984 }
985
986 GType pixbuf_type_style = 0;
987
988 void
989 pixbuf_style_register_type (GTypeModule *module)
990 {
991   static const GTypeInfo object_info =
992   {
993     sizeof (PixbufStyleClass),
994     (GBaseInitFunc) NULL,
995     (GBaseFinalizeFunc) NULL,
996     (GClassInitFunc) pixbuf_style_class_init,
997     NULL,           /* class_finalize */
998     NULL,           /* class_data */
999     sizeof (PixbufStyle),
1000     0,              /* n_preallocs */
1001     (GInstanceInitFunc) pixbuf_style_init,
1002   };
1003   
1004   pixbuf_type_style = g_type_module_register_type (module,
1005                                                    GTK_TYPE_STYLE,
1006                                                    "PixbufStyle",
1007                                                    &object_info, 0);
1008 }
1009
1010 static void
1011 pixbuf_style_init (PixbufStyle *style)
1012 {
1013 }
1014
1015 static void
1016 pixbuf_style_class_init (PixbufStyleClass *klass)
1017 {
1018   GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
1019
1020   parent_class = g_type_class_peek_parent (klass);
1021
1022   style_class->draw_hline = draw_hline;
1023   style_class->draw_vline = draw_vline;
1024   style_class->draw_shadow = draw_shadow;
1025   style_class->draw_arrow = draw_arrow;
1026   style_class->draw_diamond = draw_diamond;
1027   style_class->draw_string = draw_string;
1028   style_class->draw_box = draw_box;
1029   style_class->draw_flat_box = draw_flat_box;
1030   style_class->draw_check = draw_check;
1031   style_class->draw_option = draw_option;
1032   style_class->draw_tab = draw_tab;
1033   style_class->draw_shadow_gap = draw_shadow_gap;
1034   style_class->draw_box_gap = draw_box_gap;
1035   style_class->draw_extension = draw_extension;
1036   style_class->draw_focus = draw_focus;
1037   style_class->draw_slider = draw_slider;
1038   style_class->draw_handle = draw_handle;
1039 }