1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
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 of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include "gdkpixmap.h"
33 #include "gdkregion-generic.h"
34 #include "gdkprivate-win32.h"
36 static void gdk_win32_gc_get_values (GdkGC *gc,
38 static void gdk_win32_gc_set_values (GdkGC *gc,
40 GdkGCValuesMask values_mask);
41 static void gdk_win32_gc_set_dashes (GdkGC *gc,
46 static void gdk_gc_win32_class_init (GdkGCWin32Class *klass);
47 static void gdk_gc_win32_finalize (GObject *object);
49 static gpointer parent_class = NULL;
52 _gdk_gc_win32_get_type (void)
54 static GType object_type = 0;
58 static const GTypeInfo object_info =
60 sizeof (GdkGCWin32Class),
62 (GBaseFinalizeFunc) NULL,
63 (GClassInitFunc) gdk_gc_win32_class_init,
64 NULL, /* class_finalize */
65 NULL, /* class_data */
68 (GInstanceInitFunc) NULL,
71 object_type = g_type_register_static (GDK_TYPE_GC,
80 gdk_gc_win32_class_init (GdkGCWin32Class *klass)
82 GObjectClass *object_class = G_OBJECT_CLASS (klass);
83 GdkGCClass *gc_class = GDK_GC_CLASS (klass);
85 parent_class = g_type_class_peek_parent (klass);
87 object_class->finalize = gdk_gc_win32_finalize;
89 gc_class->get_values = gdk_win32_gc_get_values;
90 gc_class->set_values = gdk_win32_gc_set_values;
91 gc_class->set_dashes = gdk_win32_gc_set_dashes;
95 gdk_gc_win32_finalize (GObject *object)
97 GdkGCWin32 *win32_gc = GDK_GC_WIN32 (object);
99 if (win32_gc->clip_region)
100 gdk_region_destroy (win32_gc->clip_region);
102 if (win32_gc->values_mask & GDK_GC_FONT)
103 gdk_font_unref (win32_gc->font);
105 if (win32_gc->values_mask & GDK_GC_TILE)
106 gdk_drawable_unref (win32_gc->tile);
108 if (win32_gc->values_mask & GDK_GC_STIPPLE)
109 gdk_drawable_unref (win32_gc->stipple);
111 G_OBJECT_CLASS (parent_class)->finalize (object);
115 gdk_win32_gc_values_to_win32values (GdkGCValues *values,
116 GdkGCValuesMask mask,
117 GdkGCWin32 *win32_gc)
122 GDK_NOTE (GC, g_print ("{"));
124 if (mask & GDK_GC_FOREGROUND)
126 win32_gc->foreground = values->foreground.pixel;
127 win32_gc->values_mask |= GDK_GC_FOREGROUND;
128 GDK_NOTE (GC, (g_print ("fg=%.06lx", win32_gc->foreground),
132 if (mask & GDK_GC_BACKGROUND)
134 win32_gc->background = values->background.pixel;
135 win32_gc->values_mask |= GDK_GC_BACKGROUND;
136 GDK_NOTE (GC, (g_print ("%sbg=%.06lx", s, win32_gc->background),
140 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
141 || values->font->type == GDK_FONT_FONTSET))
143 if (win32_gc->font != NULL)
144 gdk_font_unref (win32_gc->font);
145 win32_gc->font = values->font;
146 if (win32_gc->font != NULL)
150 gdk_font_ref (win32_gc->font);
151 win32_gc->values_mask |= GDK_GC_FONT;
152 GDK_NOTE (GC, (xlfd = gdk_font_full_name_get (win32_gc->font),
153 g_print ("%sfont=%s", s, xlfd),
155 gdk_font_full_name_free (xlfd)));
159 win32_gc->values_mask &= ~GDK_GC_FONT;
160 GDK_NOTE (GC, (g_print ("%sfont=NULL", s),
165 if (mask & GDK_GC_FUNCTION)
167 GDK_NOTE (GC, (g_print ("%srop2=", s),
169 switch (values->function)
171 #define CASE(x,y) case GDK_##x: win32_gc->rop2 = R2_##y; GDK_NOTE (GC, g_print (#y)); break
172 CASE (COPY, COPYPEN);
177 CASE (AND_REVERSE, MASKPENNOT);
178 CASE (AND_INVERT, MASKNOTPEN);
181 CASE (EQUIV, NOTXORPEN);
182 CASE (OR_REVERSE, MERGEPENNOT);
183 CASE (COPY_INVERT, NOTCOPYPEN);
184 CASE (OR_INVERT, MERGENOTPEN);
185 CASE (NAND, NOTMASKPEN);
186 CASE (NOR, NOTMERGEPEN);
190 win32_gc->values_mask |= GDK_GC_FUNCTION;
193 if (mask & GDK_GC_FILL)
195 win32_gc->fill_style = values->fill;
196 win32_gc->values_mask |= GDK_GC_FILL;
197 GDK_NOTE (GC, (g_print ("%sfill=%d", s, win32_gc->fill_style),
201 if (mask & GDK_GC_TILE)
203 if (win32_gc->tile != NULL)
204 gdk_drawable_unref (win32_gc->tile);
205 win32_gc->tile = values->tile;
206 if (win32_gc->tile != NULL)
208 gdk_drawable_ref (win32_gc->tile);
209 win32_gc->values_mask |= GDK_GC_TILE;
211 (g_print ("%stile=%p", s,
212 GDK_PIXMAP_HBITMAP (win32_gc->tile)),
217 win32_gc->values_mask &= ~GDK_GC_TILE;
218 GDK_NOTE (GC, (g_print ("%stile=NULL", s),
223 if (mask & GDK_GC_STIPPLE)
225 if (win32_gc->stipple != NULL)
226 gdk_drawable_unref (win32_gc->stipple);
227 win32_gc->stipple = values->stipple;
228 if (win32_gc->stipple != NULL)
230 gdk_drawable_get_size (win32_gc->stipple, &sw, &sh);
232 #if 0 /* HB: this size limitation is disabled to make radio and check
233 * buttons work. I got the impression from the API docs, that
234 * it shouldn't be necessary at all, but win9x would do the clipping
236 if ( (sw != 8 || sh != 8)
237 && !IS_WIN_NT ()) /* HB: the MSDN says it's a Win95 limitation */
239 /* It seems that it *must* be 8x8, at least on my machine.
240 * Thus, tile an 8x8 bitmap with the stipple in case it is
241 * smaller, or simply use just the top left 8x8 in case it is
245 GdkPixmap *bm = gdk_bitmap_create_from_data (NULL, dummy, 8, 8);
246 GdkGC *gc = gdk_gc_new (bm);
255 gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
260 win32_gc->stipple = bm;
265 gdk_drawable_ref (win32_gc->stipple);
266 win32_gc->values_mask |= GDK_GC_STIPPLE;
268 (g_print ("%sstipple=%p", s,
269 GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
274 win32_gc->values_mask &= ~GDK_GC_STIPPLE;
275 GDK_NOTE (GC, (g_print ("%sstipple=NULL", s),
280 if (mask & GDK_GC_CLIP_MASK)
282 if (win32_gc->clip_region != NULL)
284 gdk_region_destroy (win32_gc->clip_region);
285 win32_gc->clip_region = NULL;
288 if (win32_gc->hcliprgn != NULL)
290 DeleteObject (win32_gc->hcliprgn);
291 win32_gc->hcliprgn = NULL;
294 if (values->clip_mask != NULL)
297 _gdk_win32_bitmap_to_region (values->clip_mask);
298 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
302 win32_gc->hcliprgn = NULL;
303 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
305 GDK_NOTE (GC, (g_print ("%sclip=%p", s, win32_gc->hcliprgn),
309 if (mask & GDK_GC_SUBWINDOW)
311 win32_gc->subwindow_mode = values->subwindow_mode;
312 win32_gc->values_mask |= GDK_GC_SUBWINDOW;
313 GDK_NOTE (GC, (g_print ("%ssubw=%d", s, win32_gc->subwindow_mode),
317 if (mask & GDK_GC_TS_X_ORIGIN)
319 win32_gc->values_mask |= GDK_GC_TS_X_ORIGIN;
320 GDK_NOTE (GC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
324 if (mask & GDK_GC_TS_Y_ORIGIN)
326 win32_gc->values_mask |= GDK_GC_TS_Y_ORIGIN;
327 GDK_NOTE (GC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
331 if (mask & GDK_GC_CLIP_X_ORIGIN)
333 win32_gc->values_mask |= GDK_GC_CLIP_X_ORIGIN;
334 GDK_NOTE (GC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
338 if (mask & GDK_GC_CLIP_Y_ORIGIN)
340 win32_gc->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
341 GDK_NOTE (GC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
345 if (mask & GDK_GC_EXPOSURES)
347 win32_gc->graphics_exposures = values->graphics_exposures;
348 win32_gc->values_mask |= GDK_GC_EXPOSURES;
349 GDK_NOTE (GC, (g_print ("%sexp=%d", s, win32_gc->graphics_exposures),
353 if (mask & GDK_GC_LINE_WIDTH)
355 win32_gc->pen_width = values->line_width;
356 win32_gc->values_mask |= GDK_GC_LINE_WIDTH;
357 GDK_NOTE (GC, (g_print ("%spw=%d", s, win32_gc->pen_width),
361 if (mask & GDK_GC_LINE_STYLE)
363 switch (values->line_style)
366 win32_gc->pen_style &= ~(PS_STYLE_MASK);
367 GDK_NOTE (GC, (g_print ("%sps|=LINE_SOLID", s),
369 win32_gc->pen_style |= PS_SOLID;
371 case GDK_LINE_ON_OFF_DASH:
372 case GDK_LINE_DOUBLE_DASH: /* ??? */
373 /* Only set the linestyle here, if it isn't already set
374 * gdk_win32_gc_set_dashes () knows better
376 if (0 == (win32_gc->values_mask & GDK_GC_LINE_STYLE))
378 win32_gc->pen_style &= ~(PS_STYLE_MASK);
379 GDK_NOTE (GC, (g_print ("%sps|=DASH", s),
381 win32_gc->pen_style |= PS_DASH;
385 win32_gc->values_mask |= GDK_GC_LINE_STYLE;
388 if (mask & GDK_GC_CAP_STYLE)
390 win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
391 switch (values->cap_style)
393 case GDK_CAP_NOT_LAST: /* ??? */
395 GDK_NOTE (GC, (g_print ("%sps|=ENDCAP_FLAT", s),
397 win32_gc->pen_style |= PS_ENDCAP_FLAT;
400 GDK_NOTE (GC, (g_print ("%sps|=ENDCAP_ROUND", s),
402 win32_gc->pen_style |= PS_ENDCAP_ROUND;
404 case GDK_CAP_PROJECTING:
405 GDK_NOTE (GC, (g_print ("%sps|=ENDCAP_SQUARE", s),
407 win32_gc->pen_style |= PS_ENDCAP_SQUARE;
410 win32_gc->values_mask |= GDK_GC_CAP_STYLE;
413 if (mask & GDK_GC_JOIN_STYLE)
415 win32_gc->pen_style &= ~(PS_JOIN_MASK);
416 switch (values->join_style)
419 GDK_NOTE (GC, (g_print ("%sps|=JOIN_MITER", s),
421 win32_gc->pen_style |= PS_JOIN_MITER;
424 GDK_NOTE (GC, (g_print ("%sps|=JOIN_ROUND", s),
426 win32_gc->pen_style |= PS_JOIN_ROUND;
429 GDK_NOTE (GC, (g_print ("%sps|=JOIN_BEVEL", s),
431 win32_gc->pen_style |= PS_JOIN_BEVEL;
434 win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
436 GDK_NOTE (GC, g_print ("}\n"));
440 _gdk_win32_gc_new (GdkDrawable *drawable,
442 GdkGCValuesMask mask)
445 GdkGCWin32 *win32_gc;
447 /* NOTICE that the drawable here has to be the impl drawable,
448 * not the publically-visible drawables.
450 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
452 gc = g_object_new (_gdk_gc_win32_get_type (), NULL);
453 win32_gc = GDK_GC_WIN32 (gc);
455 win32_gc->hdc = NULL;
456 win32_gc->clip_region = NULL;
457 win32_gc->hcliprgn = NULL;
459 /* Use the same default values as X11 does, even if they don't make
460 * sense per se. But apps always set fg and bg anyway.
462 win32_gc->foreground = 0;
463 win32_gc->background = 1;
464 win32_gc->font = NULL;
465 win32_gc->rop2 = R2_COPYPEN;
466 win32_gc->fill_style = GDK_SOLID;
467 win32_gc->tile = NULL;
468 win32_gc->stipple = NULL;
469 win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
470 win32_gc->pen_width = 0;
472 win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
474 GDK_NOTE (GC, g_print ("_gdk_win32_gc_new: "));
475 gdk_win32_gc_values_to_win32values (values, mask, win32_gc);
477 win32_gc->hwnd = NULL;
479 GDK_NOTE (GC, g_print (" = %p\n", gc));
485 gdk_win32_gc_get_values (GdkGC *gc,
488 GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
490 values->foreground.pixel = win32_gc->foreground;
491 values->background.pixel = win32_gc->background;
492 values->font = win32_gc->font;
494 switch (win32_gc->rop2)
497 values->function = GDK_COPY; break;
499 values->function = GDK_INVERT; break;
501 values->function = GDK_XOR; break;
503 values->function = GDK_CLEAR; break;
505 values->function = GDK_AND; break;
507 values->function = GDK_AND_REVERSE; break;
509 values->function = GDK_AND_INVERT; break;
511 values->function = GDK_NOOP; break;
513 values->function = GDK_OR; break;
515 values->function = GDK_EQUIV; break;
517 values->function = GDK_OR_REVERSE; break;
519 values->function = GDK_COPY_INVERT; break;
521 values->function = GDK_OR_INVERT; break;
523 values->function = GDK_NAND; break;
525 values->function = GDK_NOR; break;
527 values->function = GDK_SET; break;
530 values->fill = win32_gc->fill_style;
532 values->tile = win32_gc->tile;
533 values->stipple = win32_gc->stipple;
535 /* Also the X11 backend always returns a NULL clip_mask */
536 values->clip_mask = NULL;
538 values->subwindow_mode = win32_gc->subwindow_mode;
539 values->ts_x_origin = win32_gc->parent_instance.ts_x_origin;
540 values->ts_y_origin = win32_gc->parent_instance.ts_y_origin;
541 values->clip_x_origin = win32_gc->parent_instance.clip_x_origin;
542 values->clip_y_origin = win32_gc->parent_instance.clip_y_origin;
543 values->graphics_exposures = win32_gc->graphics_exposures;
544 values->line_width = win32_gc->pen_width;
546 if (win32_gc->pen_style & PS_SOLID)
547 values->line_style = GDK_LINE_SOLID;
548 else if (win32_gc->pen_style & PS_DASH)
549 values->line_style = GDK_LINE_ON_OFF_DASH;
551 values->line_style = GDK_LINE_SOLID;
553 /* PS_ENDCAP_ROUND is zero */
554 if (win32_gc->pen_style & PS_ENDCAP_FLAT)
555 values->cap_style = GDK_CAP_BUTT;
556 else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
557 values->cap_style = GDK_CAP_PROJECTING;
559 values->cap_style = GDK_CAP_ROUND;
561 /* PS_JOIN_ROUND is zero */
562 if (win32_gc->pen_style & PS_JOIN_MITER)
563 values->join_style = GDK_JOIN_MITER;
564 else if (win32_gc->pen_style & PS_JOIN_BEVEL)
565 values->join_style = GDK_JOIN_BEVEL;
567 values->join_style = GDK_JOIN_ROUND;
571 gdk_win32_gc_set_values (GdkGC *gc,
573 GdkGCValuesMask mask)
575 g_return_if_fail (GDK_IS_GC (gc));
577 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_values: "));
579 gdk_win32_gc_values_to_win32values (values, mask, GDK_GC_WIN32 (gc));
583 gdk_win32_gc_set_dashes (GdkGC *gc,
588 GdkGCWin32 *win32_gc;
590 g_return_if_fail (GDK_IS_GC (gc));
591 g_return_if_fail (dash_list != NULL);
593 win32_gc = GDK_GC_WIN32 (gc);
595 /* mark as set, see gdk_win32_gc_values_to_win32values () for the reason */
596 win32_gc->values_mask |= GDK_GC_LINE_STYLE;
598 win32_gc->pen_style &= ~(PS_STYLE_MASK);
601 * Set the extended line style. This could be done by
602 * PS_USERSTYLE and ExtCreatePen; but ONLY on WinNT,
603 * so let's make a guess (based on the implementation
604 * in DIA). On Win9x this does only work for lines
607 * More workarounds for Win9x descibed at:
608 * http://www.codeguru.com/gdi/dashed.shtml
610 if (!IS_WIN_NT () && win32_gc->pen_width > 1)
612 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: not fully supported\n"));
613 win32_gc->pen_style |= PS_SOLID;
617 win32_gc->pen_style = PS_COSMETIC; /* ??? */
621 if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2))
623 win32_gc->pen_style |= PS_DASH;
624 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n",
625 dash_list[0], dash_list[1]));
629 win32_gc->pen_style |= PS_DOT;
630 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: PS_DOT (%d,%d)\n",
631 dash_list[0], dash_list[1]));
636 win32_gc->pen_style |= PS_DASHDOT;
637 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: PS_DASHDOT (%d,%d,%d,%d)\n",
638 dash_list[0], dash_list[1],
639 dash_list[2], dash_list[3]));
643 win32_gc->pen_style |= PS_DASHDOTDOT;
644 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: PS_DASHDOTDOT (%d,%d,%d,%d,%d,%d)\n",
645 dash_list[0], dash_list[1],
646 dash_list[2], dash_list[3],
647 dash_list[4], dash_list[5]));
651 win32_gc->pen_style |= PS_DASH;
652 GDK_NOTE (GC, g_print ("gdk_win32_gc_set_dashes: no guess for %d dashes\n", n));
658 gdk_gc_set_clip_rectangle (GdkGC *gc,
659 GdkRectangle *rectangle)
661 GdkGCWin32 *win32_gc;
663 g_return_if_fail (GDK_IS_GC (gc));
665 win32_gc = GDK_GC_WIN32 (gc);
667 if (win32_gc->hcliprgn)
669 DeleteObject (win32_gc->hcliprgn);
670 win32_gc->hcliprgn = NULL;
673 if (win32_gc->clip_region)
674 gdk_region_destroy (win32_gc->clip_region);
679 g_print ("gdk_gc_set_clip_rectangle: %dx%d@+%d+%d\n",
680 rectangle->width, rectangle->height,
681 rectangle->x, rectangle->y));
682 win32_gc->clip_region = gdk_region_rectangle (rectangle);
683 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
687 GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));
689 win32_gc->clip_region = NULL;
690 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
692 win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
696 gdk_gc_set_clip_region (GdkGC *gc,
699 GdkGCWin32 *win32_gc;
701 g_return_if_fail (GDK_IS_GC (gc));
703 win32_gc = GDK_GC_WIN32 (gc);
705 if (win32_gc->clip_region)
706 gdk_region_destroy (win32_gc->clip_region);
710 GDK_NOTE (GC, g_print ("gdk_gc_set_clip_region: %dx%d+%d+%d\n",
711 region->extents.x2 - region->extents.x1,
712 region->extents.y2 - region->extents.y1,
713 region->extents.x1, region->extents.y1));
715 win32_gc->clip_region = gdk_region_copy (region);
716 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
720 GDK_NOTE (GC, g_print ("gdk_gc_set_clip_region: NULL\n"));
722 win32_gc->clip_region = NULL;
723 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
726 gc->clip_x_origin = 0;
727 gc->clip_y_origin = 0;
729 win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
733 gdk_gc_copy (GdkGC *dst_gc,
736 GdkGCWin32 *dst_win32_gc;
737 GdkGCWin32 *src_win32_gc;
739 g_return_if_fail (GDK_IS_GC_WIN32 (dst_gc));
740 g_return_if_fail (GDK_IS_GC_WIN32 (src_gc));
742 dst_win32_gc = GDK_GC_WIN32 (dst_gc);
743 src_win32_gc = GDK_GC_WIN32 (src_gc);
745 if (dst_win32_gc->font != NULL)
746 gdk_font_unref (dst_win32_gc->font);
747 if (dst_win32_gc->tile != NULL)
748 gdk_drawable_unref (dst_win32_gc->tile);
749 if (dst_win32_gc->stipple != NULL)
750 gdk_drawable_unref (dst_win32_gc->stipple);
751 if (dst_win32_gc->clip_region != NULL)
752 gdk_region_destroy (dst_win32_gc->clip_region);
753 if (dst_win32_gc->hcliprgn != NULL)
754 DeleteObject (dst_win32_gc->hcliprgn);
756 *dst_win32_gc = *src_win32_gc;
758 if (dst_win32_gc->hcliprgn)
760 /* create a new region, to copy to */
761 dst_win32_gc->hcliprgn = CreateRectRgn (0,0,1,1);
762 /* overwrite from source */
763 CombineRgn (dst_win32_gc->hcliprgn, src_win32_gc->hcliprgn,
766 if (dst_win32_gc->clip_region != NULL)
767 dst_win32_gc->clip_region = gdk_region_copy (dst_win32_gc->clip_region);
768 if (dst_win32_gc->font != NULL)
769 gdk_font_ref (dst_win32_gc->font);
770 if (dst_win32_gc->tile != NULL)
771 gdk_drawable_ref (dst_win32_gc->tile);
772 if (dst_win32_gc->stipple != NULL)
773 gdk_drawable_ref (dst_win32_gc->stipple);
776 static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
779 _gdk_win32_colormap_color (GdkColormap *colormap,
782 const GdkVisual *visual;
783 GdkColormapPrivateWin32 *colormap_private;
786 if (colormap == NULL)
787 return DIBINDEX (pixel);
789 colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
791 g_assert (colormap_private != NULL);
793 visual = colormap->visual;
794 switch (visual->type)
796 case GDK_VISUAL_GRAYSCALE:
797 case GDK_VISUAL_PSEUDO_COLOR:
798 case GDK_VISUAL_STATIC_COLOR:
799 return PALETTEINDEX (pixel);
801 case GDK_VISUAL_TRUE_COLOR:
802 r = (pixel & visual->red_mask) >> visual->red_shift;
803 r = (r * 255) / bitmask[visual->red_prec];
804 g = (pixel & visual->green_mask) >> visual->green_shift;
805 g = (g * 255) / bitmask[visual->green_prec];
806 b = (pixel & visual->blue_mask) >> visual->blue_shift;
807 b = (b * 255) / bitmask[visual->blue_prec];
808 return RGB (r, g, b);
811 g_assert_not_reached ();
817 predraw_set_foreground (GdkGC *gc,
818 GdkColormap *colormap,
825 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
826 GdkColormapPrivateWin32 *colormap_private;
830 (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
831 colormap->visual->type == GDK_VISUAL_STATIC_COLOR))
833 colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
835 g_assert (colormap_private != NULL);
837 if (!(win32_gc->holdpal = SelectPalette (win32_gc->hdc, colormap_private->hpal, FALSE)))
838 WIN32_GDI_FAILED ("SelectPalette"), *ok = FALSE;
839 else if ((k = RealizePalette (win32_gc->hdc)) == GDI_ERROR)
840 WIN32_GDI_FAILED ("RealizePalette"), *ok = FALSE;
842 GDK_NOTE (COLORMAP, g_print ("predraw_set_foreground: realized %p: %d colors\n",
843 colormap_private->hpal, k));
846 fg = _gdk_win32_colormap_color (colormap, win32_gc->foreground);
848 GDK_NOTE (GC, g_print ("predraw_set_foreground: fg=%06lx\n", fg));
850 if (SetTextColor (win32_gc->hdc, fg) == CLR_INVALID)
851 WIN32_GDI_FAILED ("SetTextColor"), *ok = FALSE;
853 /* Create and select pen and brush. */
855 logbrush.lbStyle = BS_SOLID;
856 logbrush.lbColor = fg;
857 logbrush.lbHatch = 0;
859 if (*ok && (hpen = ExtCreatePen (win32_gc->pen_style,
860 (win32_gc->pen_width > 0 ? win32_gc->pen_width : 1),
861 &logbrush, 0, NULL)) == NULL)
862 WIN32_GDI_FAILED ("ExtCreatePen"), *ok = FALSE;
864 if (*ok && SelectObject (win32_gc->hdc, hpen) == NULL)
865 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
867 switch (win32_gc->fill_style)
869 case GDK_OPAQUE_STIPPLED:
870 if (*ok && (hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (win32_gc->stipple))) == NULL)
871 WIN32_GDI_FAILED ("CreatePatternBrush"), *ok = FALSE;
872 if (*ok && !SetBrushOrgEx(win32_gc->hdc, gc->ts_x_origin,
873 gc->ts_y_origin, NULL))
874 WIN32_GDI_FAILED ("SetBrushOrgEx"), *ok = FALSE;
880 if (*ok && (hbr = CreateSolidBrush (fg)) == NULL)
881 WIN32_GDI_FAILED ("CreateSolidBrush"), *ok = FALSE;
886 HBRUSH old_hbr = SelectObject (win32_gc->hdc, hbr);
888 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
893 predraw_set_background (GdkGC *gc,
894 GdkColormap *colormap,
897 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
899 if (win32_gc->values_mask & GDK_GC_BACKGROUND)
901 COLORREF bg = _gdk_win32_colormap_color (colormap, win32_gc->background);
903 if (SetBkColor (win32_gc->hdc, bg) == CLR_INVALID)
904 WIN32_GDI_FAILED ("SetBkColor"), *ok = FALSE;
908 if (!SetBkMode (win32_gc->hdc, TRANSPARENT))
909 WIN32_GDI_FAILED ("SetBkMode"), *ok = FALSE;
914 gdk_win32_hdc_get (GdkDrawable *drawable,
916 GdkGCValuesMask usage)
918 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
919 GdkDrawableImplWin32 *impl = NULL;
923 g_assert (win32_gc->hdc == NULL);
925 if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
926 impl = GDK_DRAWABLE_IMPL_WIN32(drawable);
927 else if (GDK_IS_WINDOW (drawable))
928 impl = GDK_DRAWABLE_IMPL_WIN32 ((GDK_WINDOW_OBJECT (drawable))->impl);
929 else if (GDK_IS_PIXMAP (drawable))
930 impl = GDK_DRAWABLE_IMPL_WIN32 ((GDK_PIXMAP_OBJECT (drawable))->impl);
932 g_assert_not_reached ();
934 win32_gc->hwnd = impl->handle;
936 if (GDK_IS_PIXMAP_IMPL_WIN32 (impl))
938 if ((win32_gc->hdc = CreateCompatibleDC (NULL)) == NULL)
939 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
941 if (ok && (win32_gc->saved_dc = SaveDC (win32_gc->hdc)) == 0)
942 WIN32_GDI_FAILED ("SaveDC"), ok = FALSE;
944 if (ok && SelectObject (win32_gc->hdc, win32_gc->hwnd) == NULL)
945 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
949 if ((win32_gc->hdc = GetDC (win32_gc->hwnd)) == NULL)
950 WIN32_GDI_FAILED ("GetDC");
952 if (ok && (win32_gc->saved_dc = SaveDC (win32_gc->hdc)) == 0)
953 WIN32_GDI_FAILED ("SaveDC");
956 if (ok && (usage & GDK_GC_FOREGROUND))
957 predraw_set_foreground (gc, impl->colormap, &ok);
959 if (ok && (usage & GDK_GC_BACKGROUND))
960 predraw_set_background (gc, impl->colormap, &ok);
962 if (ok && (usage & GDK_GC_FONT))
964 if (SetBkMode (win32_gc->hdc, TRANSPARENT) == 0)
965 WIN32_GDI_FAILED ("SetBkMode"), ok = FALSE;
967 if (ok && SetTextAlign (win32_gc->hdc, TA_BASELINE) == GDI_ERROR)
968 WIN32_GDI_FAILED ("SetTextAlign"), ok = FALSE;
971 if (ok && (win32_gc->values_mask & GDK_GC_FUNCTION))
972 if (SetROP2 (win32_gc->hdc, win32_gc->rop2) == 0)
973 WIN32_GDI_FAILED ("SetROP2"), ok = FALSE;
975 if (win32_gc->values_mask & GDK_GC_CLIP_MASK)
976 g_assert ((win32_gc->clip_region != NULL) != (win32_gc->hcliprgn != NULL));
979 && (win32_gc->values_mask & GDK_GC_CLIP_MASK)
980 && win32_gc->clip_region != NULL)
985 GdkRegionBox *boxes = win32_gc->clip_region->rects;
987 sizeof (RGNDATAHEADER) + (sizeof (RECT) * win32_gc->clip_region->numRects);
990 rgndata = g_malloc (nbytes);
991 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
992 rgndata->rdh.iType = RDH_RECTANGLES;
993 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
994 SetRect (&rgndata->rdh.rcBound,
995 G_MAXSHORT, G_MAXSHORT, G_MINSHORT, G_MINSHORT);
997 for (i = 0; i < win32_gc->clip_region->numRects; i++)
999 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
1001 rect->left = CLAMP (boxes[i].x1 + gc->clip_x_origin,
1002 G_MINSHORT, G_MAXSHORT);
1003 rect->right = CLAMP (boxes[i].x2 + gc->clip_x_origin,
1004 G_MINSHORT, G_MAXSHORT);
1005 rect->top = CLAMP (boxes[i].y1 + gc->clip_y_origin,
1006 G_MINSHORT, G_MAXSHORT);
1007 rect->bottom = CLAMP (boxes[i].y2 + gc->clip_y_origin,
1008 G_MINSHORT, G_MAXSHORT);
1010 GDK_NOTE (GC, g_print ("clip rgn box %d: %ldx%ld@+%ld+%ld\n",
1012 rect->right-rect->left,
1013 rect->bottom-rect->top,
1014 rect->left, rect->top));
1016 if (rect->left < rgndata->rdh.rcBound.left)
1017 rgndata->rdh.rcBound.left = rect->left;
1018 if (rect->right > rgndata->rdh.rcBound.right)
1019 rgndata->rdh.rcBound.right = rect->right;
1020 if (rect->top < rgndata->rdh.rcBound.top)
1021 rgndata->rdh.rcBound.top = rect->top;
1022 if (rect->bottom > rgndata->rdh.rcBound.bottom)
1023 rgndata->rdh.rcBound.bottom = rect->bottom;
1025 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
1026 WIN32_API_FAILED ("ExtCreateRegion"), ok = FALSE;
1029 * XXX: combine the fillmode-stipple with the clip region possibly
1030 * this needs to be done with the hcliprgn below as well, but
1031 * the test case here were check boxes and radio buttons ...
1033 if ( (win32_gc->values_mask & GDK_GC_STIPPLE)
1034 && (win32_gc->values_mask & GDK_GC_FILL) && (win32_gc->fill_style == GDK_STIPPLED))
1036 HRGN hstipplergn = _gdk_win32_bitmap_to_region (win32_gc->stipple);
1038 if (OffsetRgn (hstipplergn,
1039 win32_gc->values_mask & GDK_GC_TS_X_ORIGIN ? gc->ts_x_origin : 0,
1040 win32_gc->values_mask & GDK_GC_TS_Y_ORIGIN ? gc->ts_y_origin : 0) == ERROR)
1041 WIN32_API_FAILED ("OffsetRgn"), ok = FALSE;
1042 if (CombineRgn (hrgn, hrgn, hstipplergn, RGN_AND) == ERROR)
1043 WIN32_API_FAILED ("CombineRgn"), ok = FALSE;
1044 if (!DeleteObject (hstipplergn))
1045 WIN32_API_FAILED ("DeleteObject");
1047 if (ok && SelectClipRgn (win32_gc->hdc, hrgn) == ERROR)
1048 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
1051 DeleteObject (hrgn);
1054 && (win32_gc->values_mask & GDK_GC_CLIP_MASK)
1055 && win32_gc->hcliprgn != NULL)
1057 if (SelectClipRgn (win32_gc->hdc, win32_gc->hcliprgn) == ERROR)
1058 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
1059 if (ok && !OffsetClipRgn (win32_gc->hdc,
1060 win32_gc->values_mask & GDK_GC_CLIP_X_ORIGIN ? gc->clip_x_origin : 0,
1061 win32_gc->values_mask & GDK_GC_CLIP_Y_ORIGIN ? gc->clip_y_origin : 0))
1062 WIN32_API_FAILED ("OffsetClipRgn"), ok = FALSE;
1064 #ifdef G_ENABLE_DEBUG
1065 if (_gdk_debug_flags & GDK_DEBUG_GC)
1069 EXTLOGPEN extlogpen;
1073 g_print ("gdk_win32_hdc_get: %p\n", win32_gc->hdc);
1074 obj = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH);
1075 GetObject (obj, sizeof (LOGBRUSH), &logbrush);
1076 g_print ("brush: style: %s color: %06lx hatch: %#lx\n",
1077 (logbrush.lbStyle == BS_HOLLOW ? "HOLLOW" :
1078 (logbrush.lbStyle == BS_PATTERN ? "PATTERN" :
1079 (logbrush.lbStyle == BS_SOLID ? "SOLID" :
1083 obj = GetCurrentObject (win32_gc->hdc, OBJ_PEN);
1084 GetObject (obj, sizeof (EXTLOGPEN), &extlogpen);
1085 g_print ("pen: type: %s style: %s endcap: %s join: %s width: %d brush: %s\n",
1086 ((extlogpen.elpPenStyle & PS_TYPE_MASK) ==
1087 PS_GEOMETRIC ? "GEOMETRIC" : "COSMETIC"),
1088 ((extlogpen.elpPenStyle & PS_STYLE_MASK) ==
1090 ((extlogpen.elpPenStyle & PS_STYLE_MASK) == PS_SOLID ? "SOLID" :
1091 ((extlogpen.elpPenStyle & PS_STYLE_MASK) == PS_DOT ? "DOT" :
1092 ((extlogpen.elpPenStyle & PS_STYLE_MASK) == PS_DASH ? "DASH" :
1094 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1095 PS_ENDCAP_FLAT ? "FLAT" :
1096 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1097 PS_ENDCAP_ROUND ? "ROUND" :
1098 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1099 PS_ENDCAP_SQUARE ? "ROUND" :
1100 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1101 PS_ENDCAP_SQUARE ? "ROUND" : "???")))),
1102 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1103 PS_JOIN_BEVEL ? "BEVEL" :
1104 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1105 PS_JOIN_MITER ? "MITER" :
1106 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1107 PS_JOIN_ROUND ? "ROUND" : "???"))),
1109 (extlogpen.elpBrushStyle == BS_DIBPATTERN ? "DIBPATTERN" :
1110 (extlogpen.elpBrushStyle == BS_DIBPATTERNPT ? "DIBPATTERNPT" :
1111 (extlogpen.elpBrushStyle == BS_HATCHED ? "HATCHED" :
1112 (extlogpen.elpBrushStyle == BS_HOLLOW ? "HOLLOW" :
1113 (extlogpen.elpBrushStyle == BS_PATTERN ? "PATTERN" :
1114 (extlogpen.elpBrushStyle == BS_SOLID ? "SOLID" : "???")))))));
1115 hrgn = CreateRectRgn (0, 0, 0, 0);
1116 if ((flag = GetClipRgn (win32_gc->hdc, hrgn)) == -1)
1117 WIN32_API_FAILED ("GetClipRgn");
1119 g_print ("no clip region\n");
1122 GetRgnBox (hrgn, &rect);
1123 g_print ("clip region bbox: %ldx%ld@+%ld+%ld\n",
1124 rect.right - rect.left,
1125 rect.bottom - rect.top,
1126 rect.left, rect.top);
1128 DeleteObject (hrgn);
1131 return win32_gc->hdc;
1135 gdk_win32_hdc_release (GdkDrawable *drawable,
1137 GdkGCValuesMask usage)
1139 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
1140 GdkDrawableImplWin32 *impl = NULL;
1141 HGDIOBJ hpen = NULL;
1144 GDK_NOTE (GC, g_print ("gdk_win32_hdc_release: %p\n", win32_gc->hdc));
1146 if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
1147 impl = GDK_DRAWABLE_IMPL_WIN32(drawable);
1148 else if (GDK_IS_WINDOW (drawable))
1149 impl = GDK_DRAWABLE_IMPL_WIN32 ((GDK_WINDOW_OBJECT (drawable))->impl);
1150 else if (GDK_IS_PIXMAP (drawable))
1151 impl = GDK_DRAWABLE_IMPL_WIN32 ((GDK_PIXMAP_OBJECT (drawable))->impl);
1153 g_assert_not_reached ();
1155 if (win32_gc->holdpal != NULL)
1159 if (!SelectPalette (win32_gc->hdc, win32_gc->holdpal, FALSE))
1160 WIN32_GDI_FAILED ("SelectPalette");
1161 else if ((k = RealizePalette (win32_gc->hdc)) == GDI_ERROR)
1162 WIN32_GDI_FAILED ("RealizePalette");
1164 GDK_NOTE (COLORMAP, g_print ("gdk_win32_hdc_release: realized %p: %d colors\n",
1165 win32_gc->holdpal, k));
1166 win32_gc->holdpal = NULL;
1169 if (usage & GDK_GC_FOREGROUND)
1171 if ((hpen = GetCurrentObject (win32_gc->hdc, OBJ_PEN)) == NULL)
1172 WIN32_GDI_FAILED ("GetCurrentObject");
1174 if ((hbr = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH)) == NULL)
1175 WIN32_GDI_FAILED ("GetCurrentObject");
1178 if (!RestoreDC (win32_gc->hdc, win32_gc->saved_dc))
1179 WIN32_GDI_FAILED ("RestoreDC");
1181 if (GDK_IS_PIXMAP_IMPL_WIN32 (impl))
1183 if (!DeleteDC (win32_gc->hdc))
1184 WIN32_GDI_FAILED ("DeleteDC");
1188 if (!ReleaseDC (win32_gc->hwnd, win32_gc->hdc))
1189 WIN32_GDI_FAILED ("ReleaseDC");
1193 if (!DeleteObject (hpen))
1194 WIN32_GDI_FAILED ("DeleteObject");
1197 if (!DeleteObject (hbr))
1198 WIN32_GDI_FAILED ("DeleteObject");
1200 win32_gc->hdc = NULL;
1203 /* This function originally from Jean-Edouard Lachand-Robert, and
1204 * available at www.codeguru.com. Simplified for our needs, not sure
1205 * how much of the original code left any longer. Now handles just
1206 * one-bit deep bitmaps (in Window parlance, ie those that GDK calls
1207 * bitmaps (and not pixmaps), with zero pixels being transparent.
1210 /* _gdk_win32_bitmap_to_region : Create a region from the
1211 * "non-transparent" pixels of a bitmap.
1215 _gdk_win32_bitmap_to_region (GdkPixmap *pixmap)
1225 image = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl)->image;
1226 g_assert (image->depth == 1);
1228 /* For better performances, we will use the ExtCreateRegion()
1229 * function to create the region. This function take a RGNDATA
1230 * structure on entry. We will add rectangles by amount of
1231 * ALLOC_UNIT number in this structure.
1233 #define ALLOC_UNIT 100
1234 maxRects = ALLOC_UNIT;
1236 pData = g_malloc (sizeof (RGNDATAHEADER) + (sizeof (RECT) * maxRects));
1237 pData->rdh.dwSize = sizeof (RGNDATAHEADER);
1238 pData->rdh.iType = RDH_RECTANGLES;
1239 pData->rdh.nCount = pData->rdh.nRgnSize = 0;
1240 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1242 for (y = 0; y < image->height; y++)
1244 /* Scan each bitmap row from left to right*/
1245 p = (guchar *) image->mem + y * image->bpl;
1246 for (x = 0; x < image->width; x++)
1248 /* Search for a continuous range of "non transparent pixels"*/
1250 while (x < image->width)
1252 if ((((p[x/8])>>(7-(x%8)))&1) == 0)
1253 /* This pixel is "transparent"*/
1261 /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
1264 if (pData->rdh.nCount >= maxRects)
1266 maxRects += ALLOC_UNIT;
1267 pData = g_realloc (pData, sizeof(RGNDATAHEADER)
1268 + (sizeof(RECT) * maxRects));
1270 pr = (RECT *) &pData->Buffer;
1271 SetRect (&pr[pData->rdh.nCount], x0, y, x, y+1);
1272 if (x0 < pData->rdh.rcBound.left)
1273 pData->rdh.rcBound.left = x0;
1274 if (y < pData->rdh.rcBound.top)
1275 pData->rdh.rcBound.top = y;
1276 if (x > pData->rdh.rcBound.right)
1277 pData->rdh.rcBound.right = x;
1278 if (y+1 > pData->rdh.rcBound.bottom)
1279 pData->rdh.rcBound.bottom = y+1;
1280 pData->rdh.nCount++;
1282 /* On Windows98, ExtCreateRegion() may fail if the
1283 * number of rectangles is too large (ie: >
1284 * 4000). Therefore, we have to create the region by
1287 if (pData->rdh.nCount == 2000)
1289 HRGN h = ExtCreateRegion (NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
1292 CombineRgn(hRgn, hRgn, h, RGN_OR);
1297 pData->rdh.nCount = 0;
1298 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1304 /* Create or extend the region with the remaining rectangles*/
1305 h = ExtCreateRegion (NULL, sizeof (RGNDATAHEADER)
1306 + (sizeof (RECT) * maxRects), pData);
1309 CombineRgn (hRgn, hRgn, h, RGN_OR);
1321 #ifdef G_ENABLE_DEBUG
1324 gdk_win32_cap_style_to_string (GdkCapStyle cap_style)
1328 #define CASE(x) case x: return #x + strlen ("GDK_CAP_")
1329 CASE (GDK_CAP_NOT_LAST);
1330 CASE (GDK_CAP_BUTT);
1331 CASE (GDK_CAP_ROUND);
1332 CASE (GDK_CAP_PROJECTING);
1334 default: return ("illegal GdkCapStyle value");
1341 gdk_win32_fill_style_to_string (GdkFill fill)
1345 #define CASE(x) case x: return #x + strlen ("GDK_")
1348 CASE (GDK_STIPPLED);
1349 CASE (GDK_OPAQUE_STIPPLED);
1351 default: return ("illegal GdkFill value");
1358 gdk_win32_function_to_string (GdkFunction function)
1362 #define CASE(x) case x: return #x + strlen ("GDK_")
1368 CASE (GDK_AND_REVERSE);
1369 CASE (GDK_AND_INVERT);
1373 CASE (GDK_OR_REVERSE);
1374 CASE (GDK_COPY_INVERT);
1375 CASE (GDK_OR_INVERT);
1379 default: return ("illegal GdkFunction value");
1386 gdk_win32_join_style_to_string (GdkJoinStyle join_style)
1390 #define CASE(x) case x: return #x + strlen ("GDK_JOIN_")
1391 CASE (GDK_JOIN_MITER);
1392 CASE (GDK_JOIN_ROUND);
1393 CASE (GDK_JOIN_BEVEL);
1395 default: return ("illegal GdkJoinStyle value");
1402 gdk_win32_line_style_to_string (GdkLineStyle line_style)
1406 #define CASE(x) case x: return #x + strlen ("GDK_LINE_")
1407 CASE(GDK_LINE_SOLID);
1408 CASE(GDK_LINE_ON_OFF_DASH);
1409 CASE(GDK_LINE_DOUBLE_DASH);
1411 default: return ("illegal GdkLineStyle value");