1 /* High Contrast - a cairo based GTK+ engine
2 * Copyright (C) 2003 Sun Microsystems Inc.
3 * Copyright (C) 2006 Andrew Johnson <acjgenius@earthlink.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Project contact: <gnome-themes-list@gnome.org>
20 *
21 *
22 * This file contains code from GTK+,
23 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, and Josh MacDonald,
24 * which is also available under the GNU LGPL 2.1 and later versions
25 *
26 */
27
28
29 #include "hc_gtk2_engine.h"
30 #include "hc_gtk2_support.h"
31 #include "hc_gtk2_drawing.h"
32
33 #include <gtk/gtk.h>
34
35 #include <math.h>
36 #include <string.h>
37
38 /* Standard Border Function */
39 void
hc_draw_shadow(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)40 hc_draw_shadow(GtkStyle * style,
41 GdkWindow * window,
42 GtkStateType state_type,
43 GtkShadowType shadow_type,
44 GdkRectangle * area,
45 GtkWidget * widget,
46 const gchar * detail,
47 gint x,
48 gint y,
49 gint width,
50 gint height)
51 {
52 /* Border Uses Foreground Color */
53 CairoColor foreground = HC_STYLE(style)->color_cube.fg[state_type];
54
55 gint line_width;
56 gint clip_x = x, clip_y = y, clip_width = width, clip_height = height;
57
58 cairo_t *canvas;
59
60 /***********************************************/
61 /* GTK Sanity Checks */
62 /***********************************************/
63 CHECK_ARGS
64 SANITIZE_SIZE
65
66
67 /***********************************************/
68 /* GTK Special Cases - adjust Size/Offset */
69 /***********************************************/
70 line_width = HC_STYLE(style)->edge_thickness;
71
72 if (CHECK_DETAIL (detail, "menubar") && ge_is_panel_widget_item(widget))
73 {
74 return;
75 }
76
77 /* Spin Button */
78 if ((CHECK_DETAIL(detail, "spinbutton_up")) || (CHECK_DETAIL(detail, "spinbutton_down")))
79 {
80 /* Overdraw Height By Half The Line Width -
81 Prevents Double line Between buttons */
82 height += floor(line_width / 2);
83
84
85 /* If Down Button Offset By Half Line Width */
86 if (CHECK_DETAIL(detail, "spinbutton_down"))
87 {
88 y -= floor(line_width / 2);
89 }
90
91
92 /* Overdraw Width By Line Width -
93 Prevents Double line Between Entry And Buttons */
94 width += line_width;
95
96
97 /* If LTR Offset X By Line Width */
98 if (ge_widget_is_ltr (widget))
99 {
100 x -= line_width;
101 }
102
103 /* Force Border To Use Foreground Widget State */
104 if (widget)
105 {
106 foreground = HC_STYLE(style)->color_cube.fg[widget->state];
107 }
108 }
109
110
111 /* Entry - Force Border To Use Foreground Matching Widget State */
112 if (CHECK_DETAIL(detail, "entry") && !ge_is_combo(widget))
113 {
114 foreground = HC_STYLE(style)->color_cube.fg[widget ? widget->state : GTK_STATE_NORMAL];
115 }
116
117
118 /* Combo Box Button's */
119 if (CHECK_DETAIL(detail, "button") && ge_is_in_combo_box(widget))
120 {
121 /* Overdraw Width By Line Width -
122 Prevents Double Line Between Entry and Button. */
123 width += line_width;
124
125
126 /* If LTR Offset X By Line Width */
127 if (ge_widget_is_ltr (widget))
128 {
129 x -= line_width;
130 }
131
132
133 /* Force Border To Use Foreground Matching Parent State */
134 if ((widget) && (widget->parent))
135 {
136 gtk_widget_ensure_style(widget->parent);
137 ge_gdk_color_to_cairo(&widget->parent->style->fg[GTK_WIDGET_STATE(widget)], &foreground);
138 }
139 }
140
141
142 /***********************************************/
143 /* Draw Border */
144 /***********************************************/
145 canvas = ge_gdk_drawable_to_cairo (window, area);
146
147 /* Clip Border Too Passed Size */
148 cairo_rectangle(canvas, clip_x, clip_y, clip_width, clip_height);
149 cairo_clip(canvas);
150
151 /* Set Line Style */
152 ge_cairo_set_color(canvas, &foreground);
153 cairo_set_line_cap(canvas, CAIRO_LINE_CAP_BUTT);
154
155 cairo_set_line_width (canvas, line_width);
156 ge_cairo_inner_rectangle (canvas, x, y, width, height);
157
158 cairo_stroke(canvas);
159
160 cairo_destroy(canvas);
161 }
162
163
164 /* Border Function For Frame && Notebook,
165 With Gap For Text and/or Tabs
166 */
167 void
hc_draw_shadow_gap(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side,gint gap_pos,gint gap_size)168 hc_draw_shadow_gap (GtkStyle *style,
169 GdkWindow *window,
170 GtkStateType state_type,
171 GtkShadowType shadow_type,
172 GdkRectangle *area,
173 GtkWidget *widget,
174 const gchar *detail,
175 gint x,
176 gint y,
177 gint width,
178 gint height,
179 GtkPositionType gap_side,
180 gint gap_pos,
181 gint gap_size)
182 {
183 /* Border Uses Foreground Color */
184 CairoColor *foreground = &HC_STYLE(style)->color_cube.fg[state_type];
185 gint line_width;
186 cairo_t *canvas;
187
188 /***********************************************/
189 /* GTK Sanity Checks */
190 /***********************************************/
191 CHECK_ARGS
192 SANITIZE_SIZE
193
194 if (shadow_type == GTK_SHADOW_NONE)
195 return;
196
197 /***********************************************/
198 /* GTK Special Cases - adjust Size/Offset */
199 /***********************************************/
200 line_width = HC_STYLE(style)->edge_thickness;
201
202 if (CHECK_DETAIL (detail, "notebook"))
203 {
204 gap_pos += line_width;
205 gap_size -= 2*line_width;
206 }
207
208 /***********************************************/
209 /* Draw Border */
210 /***********************************************/
211 canvas = ge_gdk_drawable_to_cairo (window, area);
212
213 /* Create And Clip Too Path To Ignore Gap */
214 hc_simple_border_gap_clip(canvas, line_width, x, y, width, height, gap_side, gap_pos, gap_size);
215
216
217 /* Set Line Style */
218 ge_cairo_set_color(canvas, foreground);
219 cairo_set_line_cap(canvas, CAIRO_LINE_CAP_BUTT);
220
221 cairo_set_line_width (canvas, line_width);
222 ge_cairo_inner_rectangle (canvas, x, y, width, height);
223
224 cairo_stroke(canvas);
225
226 cairo_destroy(canvas);
227 }
228
229
230 /* Border Function For Notebooks Tabs */
231 void
hc_draw_extension(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side)232 hc_draw_extension (GtkStyle *style,
233 GdkWindow *window,
234 GtkStateType state_type,
235 GtkShadowType shadow_type,
236 GdkRectangle *area,
237 GtkWidget *widget,
238 const gchar *detail,
239 gint x,
240 gint y,
241 gint width,
242 gint height,
243 GtkPositionType gap_side)
244 {
245 /* Fill Uses Background Color */
246 CairoColor *background = &HC_STYLE(style)->color_cube.bg[state_type];
247
248 /* Border Uses Foreground Color */
249 CairoColor *foreground = &HC_STYLE(style)->color_cube.fg[state_type];
250
251 gint line_width;
252
253 gint widget_x = 0, widget_y = 0, widget_width = 0, widget_height = 0;
254 gint clip_x = x, clip_y = y, clip_width = width, clip_height = height;
255
256 cairo_t *canvas;
257
258 /***********************************************/
259 /* GTK Sanity Checks */
260 /***********************************************/
261 CHECK_ARGS
262 SANITIZE_SIZE
263
264
265 /***********************************************/
266 /* GTK Special Cases - adjust Size/Offset */
267 /***********************************************/
268 line_width = HC_STYLE(style)->edge_thickness;
269
270 /* What all this is for -
271
272 GTK doesn't overlap Extensions and Notebooks,
273 but rather a tab is drawn with a "gap" side.
274
275 Instead of long draw cases per gap side,
276 perform a standard draw, but clipped to size,
277 and overdraw edge thickness + one on gap side.
278
279 To fake the apearance of overlap on edge aligned tabs
280 increase clip by edge thickness on gap side.
281 */
282 if (widget && (GE_IS_NOTEBOOK (widget)))
283 {
284 widget_x = (widget->allocation.x + GTK_CONTAINER (widget)->border_width);
285 widget_y = (widget->allocation.y + GTK_CONTAINER (widget)->border_width);
286 widget_width = (widget->allocation.width - 2*GTK_CONTAINER (widget)->border_width);
287 widget_height = (widget->allocation.height - 2*GTK_CONTAINER (widget)->border_width);
288 }
289
290 switch (gap_side)
291 {
292 case GTK_POS_TOP:
293 if (GTK_CHECK_VERSION(2,10,0) ||
294 ((widget && GE_IS_NOTEBOOK (widget)) &&
295 ((x==widget_x) ||
296 ((x + width) == (widget_x + widget_width)))))
297 {
298 clip_height += line_width;
299
300 if (!GTK_CHECK_VERSION(2,10,0))
301 {
302 height -= floor(line_width/2.0);
303 }
304 }
305
306 y -= (line_width + 1);
307 height += (line_width + 1);
308 break;
309
310 case GTK_POS_LEFT:
311 if (GTK_CHECK_VERSION(2,10,0) ||
312 ((widget && GE_IS_NOTEBOOK (widget)) &&
313 ((y==widget_y) ||
314 ((y + height) == (widget_y + widget_height)))))
315 {
316 clip_width += line_width;
317
318 if (!GTK_CHECK_VERSION(2,10,0))
319 {
320 x -= floor(line_width/2.0);
321 }
322 }
323
324 x -= (line_width + 1);
325 width += (line_width + 1);
326 break;
327
328 default:
329 case GTK_POS_BOTTOM:
330 height += (line_width + 1);
331 break;
332
333 case GTK_POS_RIGHT:
334 width += (line_width + 1);
335 break;
336 }
337
338
339 /***********************************************/
340 /* Draw Border */
341 /***********************************************/
342 canvas = ge_gdk_drawable_to_cairo (window, area);
343
344 /* Clip Too Size */
345 cairo_rectangle(canvas, clip_x, clip_y, clip_width, clip_height);
346 cairo_clip(canvas);
347
348
349 /* Set Fill Style */
350 ge_cairo_set_color(canvas, background);
351
352 /* Fill Rectangle */
353 cairo_rectangle (canvas, x, y, width, height);
354 cairo_fill(canvas);
355
356
357 /* Set Line Style */
358 ge_cairo_set_color(canvas, foreground);
359 cairo_set_line_cap(canvas, CAIRO_LINE_CAP_BUTT);
360
361 cairo_set_line_width (canvas, line_width);
362 ge_cairo_inner_rectangle (canvas, x, y, width, height);
363
364 cairo_stroke(canvas);
365
366 cairo_destroy(canvas);
367 }
368
369
370 /* Draw Function For Boxes Traditionally Either Without Borders,
371 or With A Single Pixel Line */
372 void
hc_draw_flat_box(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)373 hc_draw_flat_box (GtkStyle *style,
374 GdkWindow *window,
375 GtkStateType state_type,
376 GtkShadowType shadow_type,
377 GdkRectangle *area,
378 GtkWidget *widget,
379 const gchar *detail,
380 gint x,
381 gint y,
382 gint width,
383 gint height)
384 {
385 if (detail && !strcmp ("tooltip", detail))
386 {
387 hc_draw_box (style, window, state_type, shadow_type, area,
388 widget, detail, x, y, width, height);
389 }
390 else
391 {
392 GtkStyleClass *hc_parent_class;
393 hc_parent_class = GTK_STYLE_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS(style)));
394 hc_parent_class->draw_flat_box (style, window, state_type, shadow_type, area,
395 widget, detail, x, y, width, height);
396 }
397 }
398
399
400 /* Draw Function For Standard Boxes (Most Widgets)
401 Ensures Fill And Border */
402 void
hc_draw_box(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)403 hc_draw_box (GtkStyle *style,
404 GdkWindow *window,
405 GtkStateType state_type,
406 GtkShadowType shadow_type,
407 GdkRectangle *area,
408 GtkWidget *widget,
409 const gchar *detail,
410 gint x,
411 gint y,
412 gint width,
413 gint height)
414 {
415 /***********************************************/
416 /* GTK Sanity Checks */
417 /***********************************************/
418 CHECK_ARGS
419 SANITIZE_SIZE
420
421
422 /***********************************************/
423 /* GTK Special Cases - adjust Size/Offset */
424 /***********************************************/
425
426 /* Add Menu Shell Hack For Menu Bar Item Prelight */
427 if (GE_IS_MENU_SHELL(widget))
428 {
429 hc_gtk2_engine_hack_menu_shell_setup_signals(widget);
430 }
431
432
433 /***********************************************/
434 /* Draw Fill */
435 /***********************************************/
436 gtk_style_apply_default_background (style, window,
437 widget && !GTK_WIDGET_NO_WINDOW (widget),
438 state_type, area, x, y, width, height);
439
440
441 /***********************************************/
442 /* Draw Border */
443 /***********************************************/
444 hc_draw_shadow (style, window, state_type, shadow_type, area, widget, detail,
445 x, y, width, height);
446 }
447
448
449 /* Draw Function For Boxes With Gap
450
451 Primarily For Frames With Text
452 And Notebooks With Tabs.
453 */
454 void
hc_draw_box_gap(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side,gint gap_pos,gint gap_size)455 hc_draw_box_gap (GtkStyle *style,
456 GdkWindow *window,
457 GtkStateType state_type,
458 GtkShadowType shadow_type,
459 GdkRectangle *area,
460 GtkWidget *widget,
461 const gchar *detail,
462 gint x,
463 gint y,
464 gint width,
465 gint height,
466 GtkPositionType gap_side,
467 gint gap_pos,
468 gint gap_size)
469 {
470 /***********************************************/
471 /* GTK Sanity Checks */
472 /***********************************************/
473 CHECK_ARGS
474 SANITIZE_SIZE
475
476
477 /***********************************************/
478 /* Draw Fill */
479 /***********************************************/
480 gtk_style_apply_default_background (style, window,
481 widget && !GTK_WIDGET_NO_WINDOW (widget),
482 state_type, area, x, y, width, height);
483
484
485 /***********************************************/
486 /* Draw Border */
487 /***********************************************/
488 hc_draw_shadow_gap (style, window, state_type, shadow_type, area, widget, detail,
489 x, y, width, height, gap_side, gap_pos, gap_size);
490 }
491
492
493 /* Draw Function For Boxes Commonly Needing Grips
494
495 Primarily For -
496 Paned Handles
497 Toolbar Handles
498 */
499 void
hc_draw_handle(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkOrientation orientation)500 hc_draw_handle (GtkStyle *style,
501 GdkWindow *window,
502 GtkStateType state_type,
503 GtkShadowType shadow_type,
504 GdkRectangle *area,
505 GtkWidget *widget,
506 const gchar *detail,
507 gint x,
508 gint y,
509 gint width,
510 gint height,
511 GtkOrientation orientation)
512 {
513 gint clip_x = x, clip_y = y, clip_width = width, clip_height = height;
514 gint xthick, ythick;
515
516 HcStyle *hc_style;
517 gdouble xx, yy;
518 CairoColor *light, *dark;
519 cairo_t *canvas;
520
521 /***********************************************/
522 /* GTK Sanity Checks */
523 /***********************************************/
524 CHECK_ARGS
525 SANITIZE_SIZE
526
527
528 /***********************************************/
529 /* GTK Special Cases - adjust Size/Offset */
530 /***********************************************/
531 xthick = style->xthickness;
532 ythick = style->ythickness;
533
534 if (CHECK_DETAIL(detail, "paned"))
535 {
536 /* we want to ignore the shadow border in paned widgets */
537 xthick = 0;
538 ythick = 0;
539 }
540
541 clip_x = x + xthick;
542 clip_y = y + ythick;
543 clip_width = width - (xthick * 2);
544 clip_height = height - (ythick * 2);
545
546
547 /***********************************************/
548 /* Draw Box */
549 /***********************************************/
550 hc_draw_box (style, window, state_type, shadow_type, area, widget,
551 detail, x, y, width, height);
552
553
554 /***********************************************/
555 /* Draw Grip */
556 /***********************************************/
557 hc_style = HC_STYLE (style);
558
559 light = &hc_style->color_cube.light[state_type];
560 dark = &hc_style->color_cube.dark[state_type];
561
562 canvas = ge_gdk_drawable_to_cairo (window, area);
563
564 /* Clip Too Size */
565 cairo_rectangle(canvas, clip_x, clip_y, clip_width, clip_height);
566 cairo_clip(canvas);
567
568 if (CHECK_DETAIL (detail, "paned"))
569 {
570 if (orientation == GTK_ORIENTATION_HORIZONTAL)
571 {
572 for (xx = x + width/2.0 - 15; xx <= x + width/2.0 + 15; xx += 5)
573 do_hc_draw_dot (canvas, light, dark, xx, y + height/2.0);
574 }
575 else
576 {
577 for (yy = y + height/2 - 15; yy <= y + height/2.0 + 15; yy += 5)
578 {
579 do_hc_draw_dot (canvas, light, dark, x + width/2.0, yy);
580 }
581 }
582 }
583 else
584 {
585 if (orientation == GTK_ORIENTATION_HORIZONTAL)
586 {
587 for (xx = x + xthick + (width/2 - xthick) % 5; xx <= x + width - xthick*2; xx += 5)
588 do_hc_draw_dot (canvas, light, dark, xx + 2, y + height/2);
589 }
590 else
591 {
592 for (yy = y + ythick + (height/2 - ythick) % 5; yy <= y + height - ythick*2; yy += 5)
593 do_hc_draw_dot (canvas, light, dark, x + width/2, yy + 2);
594 }
595 }
596
597 cairo_destroy(canvas);
598 }
599
600
601 void
hc_draw_slider(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkOrientation orientation)602 hc_draw_slider (GtkStyle * style,
603 GdkWindow * window,
604 GtkStateType state_type,
605 GtkShadowType shadow_type,
606 GdkRectangle * area,
607 GtkWidget * widget,
608 const gchar * detail,
609 gint x,
610 gint y,
611 gint width,
612 gint height,
613 GtkOrientation orientation)
614 {
615 cairo_t *canvas;
616 gint line_width;
617
618 CHECK_ARGS
619 SANITIZE_SIZE
620
621 canvas = ge_gdk_drawable_to_cairo (window, area);
622
623 /***********************************************/
624 /* Draw Box */
625 /***********************************************/
626 line_width = HC_STYLE(style)->edge_thickness;
627
628 hc_draw_box (style, window, state_type, shadow_type, area, widget,
629 detail, x, y, width, height);
630
631 if (GE_IS_SCALE(widget))
632 {
633 if (orientation == GTK_ORIENTATION_HORIZONTAL)
634 {
635 do_hc_draw_line (canvas, &HC_STYLE(style)->color_cube.fg[state_type],
636 line_width /2,
637 x + ceil(width/2.0) + 0.5,
638 y + line_width,
639 x + ceil(width/2.0) + 0.5,
640 y + height - line_width);
641 }
642 else
643 {
644 do_hc_draw_line (canvas, &HC_STYLE(style)->color_cube.fg[state_type],
645 line_width /2,
646 x + line_width,
647 y + ceil(height/2.0) + 0.5,
648 x + width - line_width,
649 y + ceil(height/2.0) + 0.5);
650 }
651 }
652
653 cairo_destroy(canvas);
654 }
655
656 /* Draw Check Buttons Check & Border */
657 void
hc_draw_check(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)658 hc_draw_check (GtkStyle *style,
659 GdkWindow *window,
660 GtkStateType state_type,
661 GtkShadowType shadow_type,
662 GdkRectangle *area,
663 GtkWidget *widget,
664 const gchar *detail,
665 gint x,
666 gint y,
667 gint width,
668 gint height)
669 {
670 HcStyle *hc_style = HC_STYLE (style);
671 gboolean inconsistent;
672 gint line_width;
673 cairo_t *cr;
674
675 CHECK_ARGS
676 SANITIZE_SIZE
677
678 /* Bug #351764 */
679 if ((!GTK_CHECK_VERSION(2,12,0)) &&
680 CHECK_DETAIL(detail, "cellcheck"))
681 {
682 x += (width - HC_STYLE(style)->cell_indicator_size)/2;
683 y += (height - HC_STYLE(style)->cell_indicator_size)/2;
684 width = HC_STYLE(style)->cell_indicator_size;
685 height = HC_STYLE(style)->cell_indicator_size;
686 }
687
688 inconsistent = (shadow_type == GTK_SHADOW_ETCHED_IN);
689
690 line_width = ceil(HC_STYLE(style)->edge_thickness/2.0);
691 cr = ge_gdk_drawable_to_cairo (window, area);
692
693 cairo_save(cr);
694
695 ge_cairo_set_color(cr, &hc_style->color_cube.base[state_type]);
696
697 cairo_rectangle (cr, x, y, width, height);
698
699 cairo_fill(cr);
700
701 /* Set Line Style */
702 ge_cairo_set_color(cr, &hc_style->color_cube.fg[state_type]);
703 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
704
705 cairo_set_line_width (cr, line_width);
706
707 /* Stroke Rectangle */
708 ge_cairo_stroke_rectangle (cr, x + line_width/2.0, y + line_width/2.0, width - line_width, height - line_width);
709
710 cairo_restore(cr);
711
712 if ((shadow_type == GTK_SHADOW_IN) || inconsistent)
713 {
714 cairo_save (cr);
715 /* Clip to the inner area. */
716 cairo_rectangle (cr, x + line_width, y + line_width, width - 2*line_width, height - 2*line_width);
717 cairo_clip (cr);
718
719 ge_cairo_set_color(cr, &hc_style->color_cube.fg[state_type]);
720
721 line_width = ceil(MIN(width,height)/5.0);
722
723 if (inconsistent)
724 {
725 cairo_set_line_width (cr, line_width);
726
727 cairo_move_to(cr, x, y + floor(height/2.0) + (line_width%2)/2.0);
728 cairo_line_to(cr, x + width, y + floor(height/2.0) + (line_width%2)/2.0);
729 }
730 else
731 {
732 cairo_set_line_width (cr, line_width);
733
734 /* Backward Diagonal */
735 cairo_move_to(cr, x, y);
736 cairo_line_to(cr, x + width, y + height);
737
738 /* Forward Diagonal */
739 cairo_move_to(cr, x, y + height);
740 cairo_line_to(cr, x + width, y);
741 }
742
743 cairo_stroke (cr);
744
745 cairo_restore (cr);
746 }
747
748 cairo_destroy(cr);
749 }
750
751 /* Draw Radio Button AKA Option Button Check & Border */
752 void
hc_draw_option(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)753 hc_draw_option (GtkStyle *style,
754 GdkWindow *window,
755 GtkStateType state_type,
756 GtkShadowType shadow_type,
757 GdkRectangle *area,
758 GtkWidget *widget,
759 const gchar *detail,
760 gint x,
761 gint y,
762 gint width,
763 gint height)
764 {
765 HcStyle *hc_style = HC_STYLE (style);
766 cairo_t *cr;
767
768 gint centerX;
769 gint centerY;
770 gint radius;
771 gboolean inconsistent;
772
773 CHECK_ARGS
774 SANITIZE_SIZE
775
776 /* Bug #351764 */
777 if ((!GTK_CHECK_VERSION(2,12,0)) &&
778 CHECK_DETAIL(detail, "cellradio"))
779 {
780 x += (width - HC_STYLE(style)->cell_indicator_size)/2;
781 y += (height - HC_STYLE(style)->cell_indicator_size)/2;
782 width = HC_STYLE(style)->cell_indicator_size;
783 height = HC_STYLE(style)->cell_indicator_size;
784 }
785
786 cr = ge_gdk_drawable_to_cairo (window, area);
787
788 centerX = x + floor(width/2);
789 centerY = y + floor(height/2);
790 radius = floor(MIN(width,height)/2.0);
791
792 cairo_set_line_width (cr, radius*0.30);
793 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
794
795 cairo_arc(cr, centerX, centerY, radius, 0 , 2 * G_PI);
796 ge_cairo_set_color(cr, &hc_style->color_cube.bg[state_type]);
797 cairo_fill (cr);
798
799 cairo_arc(cr, centerX, centerY, radius, 0 , 2 * G_PI);
800 ge_cairo_set_color(cr, &hc_style->color_cube.fg[state_type]);
801 cairo_stroke (cr);
802
803 inconsistent = (shadow_type == GTK_SHADOW_ETCHED_IN);
804
805 ge_cairo_set_color(cr, &hc_style->color_cube.text[state_type]);
806
807 if (shadow_type == GTK_SHADOW_IN)
808 {
809 cairo_arc(cr, centerX, centerY, radius*0.38, 0, 2 * G_PI);
810 cairo_fill(cr);
811 cairo_arc(cr, centerX, centerY, radius*0.38, 0, 2 * G_PI);
812 cairo_stroke(cr);
813 }
814 else if (inconsistent)
815 {
816 int line_width = ceil(radius*0.68);
817
818 /* Force Thickness Even */
819 line_width -= (line_width % 2);
820
821 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
822 cairo_set_line_width (cr, line_width);
823
824 cairo_move_to(cr, centerX - radius*0.38, centerY);
825 cairo_line_to(cr, centerX + radius*0.38, centerY);
826
827 cairo_stroke (cr);
828 }
829
830 cairo_destroy(cr);
831 }
832
833 void
hc_draw_tab(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)834 hc_draw_tab (GtkStyle *style,
835 GdkWindow *window,
836 GtkStateType state_type,
837 GtkShadowType shadow_type,
838 GdkRectangle *area,
839 GtkWidget *widget,
840 const gchar *detail,
841 gint x,
842 gint y,
843 gint width,
844 gint height)
845 {
846 GtkRequisition indicator_size;
847 GtkBorder indicator_spacing;
848
849 HcStyle *hc_style = HC_STYLE (style);
850 cairo_t *cr;
851
852 ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing);
853
854 indicator_size.width += 2;
855 indicator_size.height += 2;
856
857 if (ge_widget_is_ltr (widget))
858 {
859 x += width - indicator_size.width;
860 }
861
862 y += ((height - indicator_size.height) / 2) + 1;
863
864 width = indicator_size.width;
865 height = indicator_size.height;
866
867 cr = ge_gdk_drawable_to_cairo(window, area);
868
869 do_hc_draw_arrow (cr, &hc_style->color_cube.fg[state_type],
870 GTK_ARROW_DOWN,TRUE, x, y,
871 width, height);
872
873
874 cairo_destroy(cr);
875 }
876
877 void
hc_draw_layout(GtkStyle * style,GdkWindow * window,GtkStateType state_type,gboolean use_text,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,PangoLayout * layout)878 hc_draw_layout (GtkStyle *style,
879 GdkWindow *window,
880 GtkStateType state_type,
881 gboolean use_text,
882 GdkRectangle *area,
883 GtkWidget *widget,
884 const gchar *detail,
885 gint x,
886 gint y,
887 PangoLayout *layout)
888 {
889 GdkGC *gc;
890
891 CHECK_ARGS
892
893 gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
894
895 if (area)
896 gdk_gc_set_clip_rectangle (gc, area);
897
898 gdk_draw_layout (window, gc, x, y, layout);
899
900 if (area)
901 gdk_gc_set_clip_rectangle (gc, NULL);
902 }
903
904 void
hc_draw_arrow(GtkStyle * style,GdkWindow * window,GtkStateType state,GtkShadowType shadow,GdkRectangle * area,GtkWidget * widget,const gchar * detail,GtkArrowType arrow_type,gboolean fill,gint x,gint y,gint width,gint height)905 hc_draw_arrow (GtkStyle *style,
906 GdkWindow *window,
907 GtkStateType state,
908 GtkShadowType shadow,
909 GdkRectangle *area,
910 GtkWidget *widget,
911 const gchar *detail,
912 GtkArrowType arrow_type,
913 gboolean fill,
914 gint x,
915 gint y,
916 gint width,
917 gint height)
918 {
919 gint line_width;
920 HcStyle *hc_style;
921 cairo_t *cr;
922
923 /***********************************************/
924 /* GTK Sanity Checks */
925 /***********************************************/
926 CHECK_ARGS
927 SANITIZE_SIZE
928
929 /***********************************************/
930 /* GTK Arrow Special Cases - adjust Size/Offset*/
931 /***********************************************/
932 line_width = HC_STYLE(style)->edge_thickness;
933
934 if (ge_is_combo_box_entry (widget))
935 {
936 x -= 1;
937
938 if (ge_widget_is_ltr (widget))
939 {
940 x -= (line_width/2);
941 }
942 else
943 {
944 x += (line_width/2);
945 }
946 }
947 else if (ge_is_combo_box(widget, FALSE))
948 {
949 if (ge_widget_is_ltr (widget))
950 {
951 x -= 2;
952 }
953 }
954
955
956 if (ge_is_combo(widget))
957 {
958 y += 1;
959 width -= 2;
960 height -= 2;
961
962 if (ge_widget_is_ltr (widget))
963 {
964 x -= ((width%2)?0:1);
965 }
966 else
967 {
968 x += floor(line_width/2) + ((width%2)?1:0);
969 }
970 }
971
972 if (CHECK_DETAIL(detail, "menuitem"))
973 {
974 x -= 1;
975 }
976
977 if (CHECK_DETAIL (detail, "arrow"))
978 {
979 x += (width%2)?0:1;
980 }
981
982 /***********************************************/
983 /* Draw Arrow */
984 /***********************************************/
985 hc_style = HC_STYLE (style);
986 cr = ge_gdk_drawable_to_cairo(window, area);
987
988 do_hc_draw_arrow (cr, &hc_style->color_cube.fg[state], arrow_type, TRUE,
989 x, y, width+1, height+1);
990
991 cairo_destroy(cr);
992 }
993
994 void
hc_draw_hline(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x1,gint x2,gint y)995 hc_draw_hline (GtkStyle *style,
996 GdkWindow *window,
997 GtkStateType state_type,
998 GdkRectangle *area,
999 GtkWidget *widget,
1000 const gchar *detail,
1001 gint x1,
1002 gint x2,
1003 gint y)
1004 {
1005 HcStyle *hc_style = HC_STYLE (style);
1006 cairo_t *cr;
1007 gint line_width;
1008
1009 CHECK_ARGS
1010
1011 cr = ge_gdk_drawable_to_cairo (window, area);
1012
1013 line_width = style->ythickness/2;
1014
1015 do_hc_draw_line (cr, &hc_style->color_cube.fg[state_type], (CHECK_DETAIL(detail, "label"))?1:2*line_width - 1,
1016 x1 + line_width + 2, y + style->ythickness/2 + 0.5,
1017 x2 - line_width - 1, y + style->ythickness/2 + 0.5);
1018
1019 cairo_destroy(cr);
1020 }
1021
1022 void
hc_draw_vline(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint y1,gint y2,gint x)1023 hc_draw_vline (GtkStyle *style,
1024 GdkWindow *window,
1025 GtkStateType state_type,
1026 GdkRectangle *area,
1027 GtkWidget *widget,
1028 const gchar *detail,
1029 gint y1,
1030 gint y2,
1031 gint x)
1032 {
1033 HcStyle *hc_style = HC_STYLE (style);
1034 cairo_t *cr;
1035 gint line_width;
1036
1037 CHECK_ARGS
1038
1039 cr = ge_gdk_drawable_to_cairo (window, area);
1040
1041 line_width = style->xthickness/2;
1042
1043 do_hc_draw_line (cr, &hc_style->color_cube.fg[state_type], (CHECK_DETAIL(detail, "label"))?1:2*line_width - 1,
1044 x + style->xthickness/2 + 0.5, y1,
1045 x + style->xthickness/2 + 0.5, y2);
1046
1047 cairo_destroy(cr);
1048 }
1049
1050 void
hc_draw_expander(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,GtkExpanderStyle expander_style)1051 hc_draw_expander (GtkStyle *style,
1052 GdkWindow *window,
1053 GtkStateType state_type,
1054 GdkRectangle *area,
1055 GtkWidget *widget,
1056 const gchar *detail,
1057 gint x,
1058 gint y,
1059 GtkExpanderStyle expander_style)
1060 {
1061 #define DEFAULT_EXPANDER_SIZE 12
1062
1063 HcStyle *hc_style = HC_STYLE (style);
1064
1065 gint expander_size;
1066 gint line_width;
1067 double vertical_overshoot;
1068 int diameter;
1069 double radius;
1070 double interp; /* interpolation factor for center position */
1071 double x_double_horz, y_double_horz;
1072 double x_double_vert, y_double_vert;
1073 double x_double, y_double;
1074 gint degrees = 0;
1075 cairo_t *cr;
1076
1077 CHECK_ARGS
1078
1079 cr = ge_gdk_drawable_to_cairo (window, area);
1080
1081 if (widget &&
1082 gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
1083 "expander-size"))
1084 {
1085 gtk_widget_style_get (widget,
1086 "expander-size", &expander_size,
1087 NULL);
1088 }
1089 else
1090 expander_size = DEFAULT_EXPANDER_SIZE;
1091
1092 line_width = MAX (1, expander_size/9);
1093
1094 switch (expander_style)
1095 {
1096 case GTK_EXPANDER_COLLAPSED:
1097 degrees = (ge_widget_is_ltr(widget)) ? 0 : 180;
1098 interp = 0.0;
1099 break;
1100 case GTK_EXPANDER_SEMI_COLLAPSED:
1101 degrees = (ge_widget_is_ltr(widget)) ? 30 : 150;
1102 interp = 0.25;
1103 break;
1104 case GTK_EXPANDER_SEMI_EXPANDED:
1105 degrees = (ge_widget_is_ltr(widget)) ? 60 : 120;
1106 interp = 0.75;
1107 break;
1108 case GTK_EXPANDER_EXPANDED:
1109 degrees = 90;
1110 interp = 1.0;
1111 break;
1112 default:
1113 g_assert_not_reached ();
1114 }
1115
1116 /* Compute distance that the stroke extends beyonds the end
1117 * of the triangle we draw.
1118 */
1119 vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
1120
1121 /* For odd line widths, we end the vertical line of the triangle
1122 * at a half pixel, so we round differently.
1123 */
1124 if (line_width % 2 == 1)
1125 vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
1126 else
1127 vertical_overshoot = ceil (vertical_overshoot);
1128
1129 /* Adjust the size of the triangle we draw so that the entire stroke fits
1130 */
1131 diameter = MAX (3, expander_size - 2 * vertical_overshoot);
1132
1133 /* If the line width is odd, we want the diameter to be even,
1134 * and vice versa, so force the sum to be odd. This relationship
1135 * makes the point of the triangle look right.
1136 */
1137 diameter -= (1 - (diameter + line_width) % 2);
1138
1139 radius = diameter / 2.;
1140
1141 /* Adjust the center so that the stroke is properly aligned with
1142 * the pixel grid. The center adjustment is different for the
1143 * horizontal and vertical orientations. For intermediate positions
1144 * we interpolate between the two.
1145 */
1146 x_double_vert = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
1147 y_double_vert = y - 0.5;
1148
1149 x_double_horz = x - 0.5;
1150 y_double_horz = floor (y - (radius + line_width) / 2.) + (radius + line_width) / 2.;
1151
1152 x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
1153 y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
1154
1155 cairo_translate (cr, x_double, y_double);
1156 cairo_rotate (cr, degrees * G_PI / 180);
1157
1158 cairo_move_to (cr, - radius / 2., - radius);
1159 cairo_line_to (cr, radius / 2., 0);
1160 cairo_line_to (cr, - radius / 2., radius);
1161 cairo_close_path (cr);
1162
1163 cairo_set_line_width (cr, line_width);
1164
1165 ge_cairo_set_color (cr, &hc_style->color_cube.base[state_type]);
1166
1167 cairo_fill_preserve (cr);
1168
1169 ge_cairo_set_color (cr, &hc_style->color_cube.text[state_type]);
1170 cairo_stroke (cr);
1171
1172 cairo_destroy (cr);
1173 }
1174
1175 void
hc_draw_diamond(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)1176 hc_draw_diamond (GtkStyle *style,
1177 GdkWindow *window,
1178 GtkStateType state_type,
1179 GtkShadowType shadow_type,
1180 GdkRectangle *area,
1181 GtkWidget *widget,
1182 const gchar *detail,
1183 gint x,
1184 gint y,
1185 gint width,
1186 gint height)
1187 {
1188 HcStyle *hc_style = HC_STYLE (style);
1189
1190 int half_width;
1191 int half_height;
1192 cairo_t *cr;
1193
1194 CHECK_ARGS
1195 SANITIZE_SIZE
1196
1197 half_width = width / 2;
1198 half_height = height / 2;
1199
1200 cr = ge_gdk_drawable_to_cairo (window, area);
1201
1202 switch (shadow_type) {
1203 case GTK_SHADOW_IN:
1204 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1205 x + 2, y + half_height,
1206 x + half_width, y + height - 2);
1207 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1208 x + half_width, y + height - 2,
1209 x + width - 2, y + half_height);
1210 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1211 x + 1, y + half_height,
1212 x + half_width, y + height - 1);
1213 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1214 x + half_width, y + height - 1,
1215 x + width - 1, y + half_height);
1216 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1217 x, y + half_height,
1218 x + half_width, y + height);
1219 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1220 x + half_width, y + height,
1221 x + width, y + half_height);
1222
1223 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1224 x + 2, y + half_height,
1225 x + half_width, y + 2);
1226 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1227 x + half_width, y + 2,
1228 x + width - 2, y + half_height);
1229 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1230 x + 1, y + half_height,
1231 x + half_width, y + 1);
1232 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1233 x + half_width, y + 1,
1234 x + width - 1, y + half_height);
1235 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1236 x, y + half_height,
1237 x + half_width, y);
1238 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1239 x + half_width, y,
1240 x + width, y + half_height);
1241 break;
1242 case GTK_SHADOW_OUT:
1243 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1244 x + 2, y + half_height,
1245 x + half_width, y + height - 2);
1246 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1247 x + half_width, y + height - 2,
1248 x + width - 2, y + half_height);
1249 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1250 x + 1, y + half_height,
1251 x + half_width, y + height - 1);
1252 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1253 x + half_width, y + height - 1,
1254 x + width - 1, y + half_height);
1255 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1256 x, y + half_height,
1257 x + half_width, y + height);
1258 ge_cairo_line(cr, &hc_style->color_cube.dark[state_type],
1259 x + half_width, y + height,
1260 x + width, y + half_height);
1261
1262 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1263 x + 2, y + half_height,
1264 x + half_width, y + 2);
1265 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1266 x + half_width, y + 2,
1267 x + width - 2, y + half_height);
1268 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1269 x + 1, y + half_height,
1270 x + half_width, y + 1);
1271 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1272 x + half_width, y + 1,
1273 x + width - 1, y + half_height);
1274 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1275 x, y + half_height,
1276 x + half_width, y);
1277 ge_cairo_line(cr, &hc_style->color_cube.light[state_type],
1278 x + half_width, y,
1279 x + width, y + half_height);
1280 break;
1281 default:
1282 break;
1283 }
1284
1285 cairo_destroy(cr);
1286 }
1287
1288 void
hc_draw_polygon(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,GdkPoint * points,gint npoints,gboolean fill)1289 hc_draw_polygon (GtkStyle *style,
1290 GdkWindow *window,
1291 GtkStateType state_type,
1292 GtkShadowType shadow_type,
1293 GdkRectangle *area,
1294 GtkWidget *widget,
1295 const gchar *detail,
1296 GdkPoint *points,
1297 gint npoints,
1298 gboolean fill)
1299 {
1300 HcStyle *hc_style = HC_STYLE (style);
1301
1302 static const gdouble pi_over_4 = G_PI_4;
1303 static const gdouble pi_3_over_4 = G_PI_4 * 3;
1304
1305 CairoColor *color1;
1306 CairoColor *color2;
1307 CairoColor *color3;
1308 CairoColor *color4;
1309 gdouble angle;
1310 int xadjust;
1311 int yadjust;
1312 int i;
1313 cairo_t *cr;
1314
1315 g_return_if_fail(style != NULL);
1316 g_return_if_fail(window != NULL);
1317 g_return_if_fail(points != NULL);
1318
1319 switch (shadow_type) {
1320 case GTK_SHADOW_IN:
1321 color1 = &hc_style->color_cube.light[state_type];
1322 color2 = &hc_style->color_cube.dark[state_type];
1323 color3 = &hc_style->color_cube.light[state_type];
1324 color4 = &hc_style->color_cube.dark[state_type];
1325 break;
1326 case GTK_SHADOW_ETCHED_IN:
1327 color1 = &hc_style->color_cube.light[state_type];
1328 color2 = &hc_style->color_cube.dark[state_type];
1329 color3 = &hc_style->color_cube.dark[state_type];
1330 color4 = &hc_style->color_cube.light[state_type];
1331 break;
1332 case GTK_SHADOW_OUT:
1333 color1 = &hc_style->color_cube.dark[state_type];
1334 color2 = &hc_style->color_cube.light[state_type];
1335 color3 = &hc_style->color_cube.dark[state_type];
1336 color4 = &hc_style->color_cube.light[state_type];
1337 break;
1338 case GTK_SHADOW_ETCHED_OUT:
1339 color1 = &hc_style->color_cube.dark[state_type];
1340 color2 = &hc_style->color_cube.light[state_type];
1341 color3 = &hc_style->color_cube.light[state_type];
1342 color4 = &hc_style->color_cube.dark[state_type];
1343 break;
1344 default:
1345 return;
1346 }
1347
1348 cr = ge_gdk_drawable_to_cairo (window, area);
1349
1350 if (fill)
1351 ge_cairo_polygon(cr, &hc_style->color_cube.bg[state_type], points, npoints);
1352
1353 npoints--;
1354
1355 for (i = 0; i < npoints; i++) {
1356 if ((points[i].x == points[i + 1].x) &&
1357 (points[i].y == points[i + 1].y)) {
1358 angle = 0;
1359 } else {
1360 angle = atan2(points[i + 1].y - points[i].y,
1361 points[i + 1].x - points[i].x);
1362 }
1363
1364 if ((angle > -pi_3_over_4) && (angle < pi_over_4)) {
1365 if (angle > -pi_over_4) {
1366 xadjust = 0;
1367 yadjust = 1;
1368 } else {
1369 xadjust = 1;
1370 yadjust = 0;
1371 }
1372
1373 ge_cairo_line(cr, color1,
1374 points[i].x - xadjust,
1375 points[i].y - yadjust,
1376 points[i + 1].x - xadjust,
1377 points[i + 1].y - yadjust);
1378 ge_cairo_line(cr, color3,
1379 points[i].x, points[i].y,
1380 points[i + 1].x, points[i + 1].y);
1381 }
1382 else {
1383 if ((angle < -pi_3_over_4) || (angle > pi_3_over_4)) {
1384 xadjust = 0;
1385 yadjust = 1;
1386 } else {
1387 xadjust = 1;
1388 yadjust = 0;
1389 }
1390
1391 ge_cairo_line(cr, color4,
1392 points[i].x + xadjust,
1393 points[i].y + yadjust,
1394 points[i + 1].x + xadjust,
1395 points[i + 1].y + yadjust);
1396 ge_cairo_line(cr, color2,
1397 points[i].x, points[i].y,
1398 points[i + 1].x, points[i + 1].y);
1399 }
1400 }
1401
1402 cairo_destroy(cr);
1403 }
1404