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