2 * Copyright (C) 1998-2000 Red Hat, Inc.
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.
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.
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.
19 * Written by Owen Taylor <otaylor@redhat.com>, based on code by
20 * Carsten Haitzler <raster@rasterman.com>
23 #include "pixmap_theme.h"
27 match_theme_image(GtkStyle *style,
28 ThemeMatchData *match_data)
32 tmp_list = ((ThemeData *)style->engine_data)->img_list;
37 ThemeImage *image = tmp_list->data;
38 tmp_list = tmp_list->next;
40 if (match_data->function != image->match_data.function)
43 flags = match_data->flags & image->match_data.flags;
45 if (flags != image->match_data.flags) /* Required components not present */
48 if ((flags & THEME_MATCH_STATE) &&
49 match_data->state != image->match_data.state)
52 if ((flags & THEME_MATCH_SHADOW) &&
53 match_data->shadow != image->match_data.shadow)
56 if ((flags & THEME_MATCH_ARROW_DIRECTION) &&
57 match_data->arrow_direction != image->match_data.arrow_direction)
60 if ((flags & THEME_MATCH_ORIENTATION) &&
61 match_data->orientation != image->match_data.orientation)
64 if ((flags & THEME_MATCH_GAP_SIDE) &&
65 match_data->gap_side != image->match_data.gap_side)
68 if (image->match_data.detail &&
69 (!image->match_data.detail ||
70 strcmp (match_data->detail, image->match_data.detail) != 0))
80 draw_simple_image(GtkStyle *style,
84 ThemeMatchData *match_data,
93 gboolean setbg = FALSE;
95 if ((width == -1) && (height == -1))
97 gdk_window_get_size(window, &width, &height);
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);
106 if (!(match_data->flags & THEME_MATCH_ORIENTATION))
108 match_data->flags |= THEME_MATCH_ORIENTATION;
111 match_data->orientation = GTK_ORIENTATION_VERTICAL;
113 match_data->orientation = GTK_ORIENTATION_HORIZONTAL;
116 image = match_theme_image(style, match_data);
119 if (image->background)
121 GdkBitmap *mask = NULL;
123 if (image->background->stretch && setbg &&
124 gdk_window_get_type (window) != GDK_WINDOW_PIXMAP)
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);
131 theme_pixbuf_render (image->background,
133 draw_center ? COMPONENT_ALL : COMPONENT_ALL | COMPONENT_CENTER,
135 x, y, width, height);
139 gdk_window_shape_combine_mask (window, mask, 0, 0);
140 gdk_pixmap_unref (mask);
144 if (image->overlay && draw_center)
145 theme_pixbuf_render (image->overlay,
146 window, NULL, area, COMPONENT_ALL,
148 x, y, width, height);
153 draw_gap_image(GtkStyle *style,
157 ThemeMatchData *match_data,
158 gboolean draw_center,
163 GtkPositionType gap_side,
168 gboolean setbg = FALSE;
170 if ((width == -1) && (height == -1))
172 gdk_window_get_size(window, &width, &height);
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);
180 if (!(match_data->flags & THEME_MATCH_ORIENTATION))
182 match_data->flags |= THEME_MATCH_ORIENTATION;
185 match_data->orientation = GTK_ORIENTATION_VERTICAL;
187 match_data->orientation = GTK_ORIENTATION_HORIZONTAL;
190 match_data->flags |= THEME_MATCH_GAP_SIDE;
191 match_data->gap_side = gap_side;
193 image = match_theme_image(style, match_data);
197 GdkRectangle r1, r2, r3;
198 GdkPixbuf *pixbuf = NULL;
199 guint components = COMPONENT_ALL;
202 components |= COMPONENT_CENTER;
204 if (image->gap_start)
205 pixbuf = theme_pixbuf_get_pixbuf (image->gap_start);
211 thickness = pixbuf->art_pixbuf->height;
213 thickness = style->klass->ythickness;
216 components |= COMPONENT_NORTH_WEST | COMPONENT_NORTH | COMPONENT_NORTH_EAST;
221 r1.height = thickness;
224 r2.width = gap_width;
225 r2.height = thickness;
226 r3.x = x + gap_x + gap_width;
228 r3.width = width - (gap_x + gap_width);
229 r3.height = thickness;
234 thickness = pixbuf->art_pixbuf->height;
236 thickness = style->klass->ythickness;
239 components |= COMPONENT_SOUTH_WEST | COMPONENT_SOUTH | COMPONENT_SOUTH_EAST;
242 r1.y = y + height - thickness;
244 r1.height = thickness;
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;
257 thickness = pixbuf->art_pixbuf->width;
259 thickness = style->klass->xthickness;
262 components |= COMPONENT_NORTH_WEST | COMPONENT_WEST | COMPONENT_SOUTH_WEST;
266 r1.width = thickness;
270 r2.width = thickness;
271 r2.height = gap_width;
273 r3.y = y + gap_x + gap_width;
274 r3.width = thickness;
275 r3.height = height - (gap_x + gap_width);
280 thickness = pixbuf->art_pixbuf->width;
282 thickness = style->klass->xthickness;
285 components |= COMPONENT_NORTH_EAST | COMPONENT_EAST | COMPONENT_SOUTH_EAST;
287 r1.x = x + width - thickness;
289 r1.width = thickness;
291 r2.x = x + width - thickness;
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);
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);
311 theme_pixbuf_render (image->gap,
312 window, NULL, area, COMPONENT_ALL, FALSE,
313 r2.x, r2.y, r2.width, r2.height);
315 theme_pixbuf_render (image->gap_end,
316 window, NULL, area, COMPONENT_ALL, FALSE,
317 r3.x, r3.y, r3.width, r3.height);
322 draw_hline(GtkStyle * style,
333 ThemeMatchData match_data;
335 g_return_if_fail(style != NULL);
336 g_return_if_fail(window != NULL);
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;
344 image = match_theme_image(style, &match_data);
347 if (image->background)
348 theme_pixbuf_render (image->background,
349 window, NULL, area, COMPONENT_ALL, FALSE,
350 x1, y, (x2 - x1) + 1, 2);
355 draw_vline(GtkStyle * style,
366 ThemeMatchData match_data;
368 g_return_if_fail (style != NULL);
369 g_return_if_fail (window != NULL);
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;
377 image = match_theme_image(style, &match_data);
380 if (image->background)
381 theme_pixbuf_render (image->background,
382 window, NULL, area, COMPONENT_ALL, FALSE,
383 x, y1, 2, (y2 - y1) + 1);
388 draw_shadow(GtkStyle * style,
391 GtkShadowType shadow,
400 ThemeMatchData match_data;
402 g_return_if_fail(style != NULL);
403 g_return_if_fail(window != NULL);
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;
411 draw_simple_image (style, window, area, widget, &match_data, FALSE, FALSE,
412 x, y, width, height);
416 draw_polygon(GtkStyle * style,
419 GtkShadowType shadow,
428 #define M_PI 3.14159265358979323846
431 #define M_PI_4 0.78539816339744830962
434 static const gdouble pi_over_4 = M_PI_4;
435 static const gdouble pi_3_over_4 = M_PI_4 * 3;
442 g_return_if_fail(style != NULL);
443 g_return_if_fail(window != NULL);
444 g_return_if_fail(points != NULL);
449 gc3 = style->light_gc[state];
450 gc4 = style->black_gc;
453 gc3 = style->black_gc;
454 gc4 = style->light_gc[state];
462 gdk_gc_set_clip_rectangle(gc3, area);
463 gdk_gc_set_clip_rectangle(gc4, area);
466 gdk_draw_polygon(window, style->bg_gc[state], TRUE, points, npoints);
470 for (i = 0; i < npoints; i++)
472 if ((points[i].x == points[i + 1].x) &&
473 (points[i].y == points[i + 1].y))
476 angle = atan2(points[i + 1].y - points[i].y,
477 points[i + 1].x - points[i].x);
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);
484 gdk_draw_line(window, gc4,
485 points[i].x, points[i].y,
486 points[i + 1].x, points[i + 1].y);
490 gdk_gc_set_clip_rectangle(gc3, NULL);
491 gdk_gc_set_clip_rectangle(gc4, NULL);
496 draw_arrow(GtkStyle * style,
499 GtkShadowType shadow,
503 GtkArrowType arrow_direction,
510 ThemeMatchData match_data;
512 g_return_if_fail(style != NULL);
513 g_return_if_fail(window != NULL);
515 match_data.function = TOKEN_D_ARROW;
516 match_data.detail = detail;
517 match_data.flags = (THEME_MATCH_SHADOW |
519 THEME_MATCH_ARROW_DIRECTION);
520 match_data.shadow = shadow;
521 match_data.state = state;
522 match_data.arrow_direction = arrow_direction;
524 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
525 x, y, width, height);
529 draw_diamond(GtkStyle * style,
532 GtkShadowType shadow,
541 ThemeMatchData match_data;
543 g_return_if_fail(style != NULL);
544 g_return_if_fail(window != NULL);
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;
552 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
553 x, y, width, height);
557 draw_oval(GtkStyle * style,
560 GtkShadowType shadow,
569 ThemeMatchData match_data;
571 g_return_if_fail(style != NULL);
572 g_return_if_fail(window != NULL);
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;
580 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
581 x, y, width, height);
585 draw_string(GtkStyle * style,
593 const gchar * string)
595 g_return_if_fail(style != NULL);
596 g_return_if_fail(window != NULL);
598 if (state == GTK_STATE_INSENSITIVE)
602 gdk_gc_set_clip_rectangle(style->white_gc, area);
603 gdk_gc_set_clip_rectangle(style->fg_gc[state], area);
606 gdk_draw_string(window, style->font, style->fg_gc[state], x, y, string);
610 gdk_gc_set_clip_rectangle(style->white_gc, NULL);
611 gdk_gc_set_clip_rectangle(style->fg_gc[state], NULL);
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);
623 draw_box(GtkStyle * style,
626 GtkShadowType shadow,
635 ThemeMatchData match_data;
637 g_return_if_fail(style != NULL);
638 g_return_if_fail(window != NULL);
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;
646 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
647 x, y, width, height);
651 draw_flat_box(GtkStyle * style,
654 GtkShadowType shadow,
663 ThemeMatchData match_data;
665 g_return_if_fail(style != NULL);
666 g_return_if_fail(window != NULL);
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;
674 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
675 x, y, width, height);
679 draw_check(GtkStyle * style,
682 GtkShadowType shadow,
691 ThemeMatchData match_data;
693 g_return_if_fail(style != NULL);
694 g_return_if_fail(window != NULL);
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;
702 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
703 x, y, width, height);
707 draw_option(GtkStyle * style,
710 GtkShadowType shadow,
719 ThemeMatchData match_data;
721 g_return_if_fail(style != NULL);
722 g_return_if_fail(window != NULL);
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;
730 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
731 x, y, width, height);
735 draw_cross(GtkStyle * style,
738 GtkShadowType shadow,
747 ThemeMatchData match_data;
749 g_return_if_fail(style != NULL);
750 g_return_if_fail(window != NULL);
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;
758 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
759 x, y, width, height);
763 draw_ramp(GtkStyle * style,
766 GtkShadowType shadow,
770 GtkArrowType arrow_direction,
776 ThemeMatchData match_data;
778 g_return_if_fail(style != NULL);
779 g_return_if_fail(window != NULL);
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;
787 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
788 x, y, width, height);
792 draw_tab(GtkStyle * style,
795 GtkShadowType shadow,
804 ThemeMatchData match_data;
806 g_return_if_fail(style != NULL);
807 g_return_if_fail(window != NULL);
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;
815 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
816 x, y, width, height);
820 draw_shadow_gap(GtkStyle * style,
823 GtkShadowType shadow,
831 GtkPositionType gap_side,
835 ThemeMatchData match_data;
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 |
842 THEME_MATCH_ORIENTATION);
843 match_data.shadow = shadow;
844 match_data.state = state;
846 draw_gap_image (style, window, area, widget, &match_data, FALSE,
847 x, y, width, height, gap_side, gap_x, gap_width);
851 draw_box_gap(GtkStyle * style,
854 GtkShadowType shadow,
862 GtkPositionType gap_side,
866 ThemeMatchData match_data;
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 |
873 THEME_MATCH_ORIENTATION);
874 match_data.shadow = shadow;
875 match_data.state = state;
877 draw_gap_image (style, window, area, widget, &match_data, TRUE,
878 x, y, width, height, gap_side, gap_x, gap_width);
882 draw_extension(GtkStyle * style,
885 GtkShadowType shadow,
893 GtkPositionType gap_side)
895 ThemeMatchData match_data;
897 g_return_if_fail(style != NULL);
898 g_return_if_fail(window != NULL);
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;
913 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
914 x, y, width, height);
918 draw_focus(GtkStyle * style,
928 ThemeMatchData match_data;
930 g_return_if_fail(style != NULL);
931 g_return_if_fail(window != NULL);
939 match_data.function = TOKEN_D_FOCUS;
940 match_data.detail = detail;
941 match_data.flags = 0;
943 draw_simple_image (style, window, area, widget, &match_data, TRUE, FALSE,
944 x, y, width, height);
948 draw_slider(GtkStyle * style,
951 GtkShadowType shadow,
959 GtkOrientation orientation)
961 ThemeMatchData match_data;
963 g_return_if_fail(style != NULL);
964 g_return_if_fail(window != NULL);
966 match_data.function = TOKEN_D_SLIDER;
967 match_data.detail = detail;
968 match_data.flags = (THEME_MATCH_SHADOW |
970 THEME_MATCH_ORIENTATION);
971 match_data.shadow = shadow;
972 match_data.state = state;
973 match_data.orientation = orientation;
975 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
976 x, y, width, height);}
980 draw_handle(GtkStyle * style,
983 GtkShadowType shadow,
991 GtkOrientation orientation)
993 ThemeMatchData match_data;
995 g_return_if_fail (style != NULL);
996 g_return_if_fail (window != NULL);
998 match_data.function = TOKEN_D_HANDLE;
999 match_data.detail = detail;
1000 match_data.flags = (THEME_MATCH_SHADOW |
1002 THEME_MATCH_ORIENTATION);
1003 match_data.shadow = shadow;
1004 match_data.state = state;
1005 match_data.orientation = orientation;
1007 draw_simple_image (style, window, area, widget, &match_data, TRUE, TRUE,
1008 x, y, width, height);
1011 GtkStyleClass pixmap_default_class =