1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdkpixmap.h"
34 #include "gdkregion-generic.h"
35 #include "gdkinternals.h"
36 #include "gdkprivate-win32.h"
38 static void gdk_win32_gc_get_values (GdkGC *gc,
40 static void gdk_win32_gc_set_values (GdkGC *gc,
42 GdkGCValuesMask values_mask);
43 static void gdk_win32_gc_set_dashes (GdkGC *gc,
48 static void gdk_gc_win32_class_init (GdkGCWin32Class *klass);
49 static void gdk_gc_win32_finalize (GObject *object);
51 static gpointer parent_class = NULL;
54 gdk_gc_win32_get_type (void)
56 static GType object_type = 0;
60 static const GTypeInfo object_info =
62 sizeof (GdkGCWin32Class),
64 (GBaseFinalizeFunc) NULL,
65 (GClassInitFunc) gdk_gc_win32_class_init,
66 NULL, /* class_finalize */
67 NULL, /* class_data */
70 (GInstanceInitFunc) NULL,
73 object_type = g_type_register_static (GDK_TYPE_GC,
82 gdk_gc_win32_class_init (GdkGCWin32Class *klass)
84 GObjectClass *object_class = G_OBJECT_CLASS (klass);
85 GdkGCClass *gc_class = GDK_GC_CLASS (klass);
87 parent_class = g_type_class_peek_parent (klass);
89 object_class->finalize = gdk_gc_win32_finalize;
91 gc_class->get_values = gdk_win32_gc_get_values;
92 gc_class->set_values = gdk_win32_gc_set_values;
93 gc_class->set_dashes = gdk_win32_gc_set_dashes;
97 gdk_gc_win32_finalize (GObject *object)
99 GdkGCWin32 *win32_gc = GDK_GC_WIN32 (object);
101 if (win32_gc->clip_region)
102 gdk_region_destroy (win32_gc->clip_region);
104 if (win32_gc->values_mask & GDK_GC_FONT)
105 gdk_font_unref (win32_gc->font);
107 if (win32_gc->values_mask & GDK_GC_TILE)
108 gdk_drawable_unref (win32_gc->tile);
110 if (win32_gc->values_mask & GDK_GC_STIPPLE)
111 gdk_drawable_unref (win32_gc->stipple);
113 G_OBJECT_CLASS (parent_class)->finalize (object);
117 gdk_win32_gc_values_to_win32values (GdkGCValues *values,
118 GdkGCValuesMask mask,
119 GdkGCWin32 *win32_gc)
124 GDK_NOTE (MISC, g_print ("{"));
126 if (mask & GDK_GC_FOREGROUND)
128 win32_gc->foreground = values->foreground.pixel;
129 win32_gc->values_mask |= GDK_GC_FOREGROUND;
130 GDK_NOTE (MISC, (g_print ("fg=%.06lx", win32_gc->foreground),
134 if (mask & GDK_GC_BACKGROUND)
136 win32_gc->background = values->background.pixel;
137 win32_gc->values_mask |= GDK_GC_BACKGROUND;
138 GDK_NOTE (MISC, (g_print ("%sbg=%.06lx", s, win32_gc->background),
142 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
143 || values->font->type == GDK_FONT_FONTSET))
145 if (win32_gc->font != NULL)
146 gdk_font_unref (win32_gc->font);
147 win32_gc->font = values->font;
148 if (win32_gc->font != NULL)
152 gdk_font_ref (win32_gc->font);
153 win32_gc->values_mask |= GDK_GC_FONT;
154 GDK_NOTE (MISC, (xlfd = gdk_font_full_name_get (win32_gc->font),
155 g_print ("%sfont=%s", s, xlfd),
157 gdk_font_full_name_free (xlfd)));
161 win32_gc->values_mask &= ~GDK_GC_FONT;
162 GDK_NOTE (MISC, (g_print ("%sfont=NULL", s),
167 if (mask & GDK_GC_FUNCTION)
169 GDK_NOTE (MISC, (g_print ("%srop2=", s),
171 switch (values->function)
174 win32_gc->rop2 = R2_COPYPEN;
175 GDK_NOTE (MISC, g_print ("COPYPEN"));
178 win32_gc->rop2 = R2_NOT;
179 GDK_NOTE (MISC, g_print ("NOT"));
182 win32_gc->rop2 = R2_XORPEN;
183 GDK_NOTE (MISC, g_print ("XORPEN"));
186 win32_gc->rop2 = R2_BLACK;
187 GDK_NOTE (MISC, g_print ("BLACK"));
190 win32_gc->rop2 = R2_MASKPEN;
191 GDK_NOTE (MISC, g_print ("MASKPEN"));
193 case GDK_AND_REVERSE:
194 win32_gc->rop2 = R2_MASKPENNOT;
195 GDK_NOTE (MISC, g_print ("MASKPENNOT"));
198 win32_gc->rop2 = R2_MASKNOTPEN;
199 GDK_NOTE (MISC, g_print ("MASKNOTPEN"));
202 win32_gc->rop2 = R2_NOP;
203 GDK_NOTE (MISC, g_print ("NOP"));
206 win32_gc->rop2 = R2_MERGEPEN;
207 GDK_NOTE (MISC, g_print ("MERGEPEN"));
210 win32_gc->rop2 = R2_NOTXORPEN;
211 GDK_NOTE (MISC, g_print ("NOTXORPEN"));
214 win32_gc->rop2 = R2_MERGEPENNOT;
215 GDK_NOTE (MISC, g_print ("MERGEPENNOT"));
217 case GDK_COPY_INVERT:
218 win32_gc->rop2 = R2_NOTCOPYPEN;
219 GDK_NOTE (MISC, g_print ("NOTCOPYPEN"));
222 win32_gc->rop2 = R2_MERGENOTPEN;
223 GDK_NOTE (MISC, g_print ("MERGENOTPEN"));
226 win32_gc->rop2 = R2_NOTMASKPEN;
227 GDK_NOTE (MISC, g_print ("NOTMASKPEN"));
230 win32_gc->rop2 = R2_NOTMERGEPEN;
231 GDK_NOTE (MISC, g_print ("NOTMERGEPEN"));
234 win32_gc->rop2 = R2_WHITE;
235 GDK_NOTE (MISC, g_print ("WHITE"));
238 win32_gc->values_mask |= GDK_GC_FUNCTION;
241 if (mask & GDK_GC_FILL)
243 win32_gc->fill_style = values->fill;
244 win32_gc->values_mask |= GDK_GC_FILL;
245 GDK_NOTE (MISC, (g_print ("%sfill=%d", s, win32_gc->fill_style),
249 if (mask & GDK_GC_TILE)
251 if (win32_gc->tile != NULL)
252 gdk_drawable_unref (win32_gc->tile);
253 win32_gc->tile = values->tile;
254 if (win32_gc->tile != NULL)
256 gdk_drawable_ref (win32_gc->tile);
257 win32_gc->values_mask |= GDK_GC_TILE;
259 (g_print ("%stile=%#x", s,
260 (guint) GDK_PIXMAP_HBITMAP (win32_gc->tile)),
265 win32_gc->values_mask &= ~GDK_GC_TILE;
266 GDK_NOTE (MISC, (g_print ("%stile=NULL", s),
271 if (mask & GDK_GC_STIPPLE)
273 if (win32_gc->stipple != NULL)
274 gdk_drawable_unref (win32_gc->stipple);
275 win32_gc->stipple = values->stipple;
276 if (win32_gc->stipple != NULL)
278 gdk_drawable_get_size (win32_gc->stipple, &sw, &sh);
280 if (sw != 8 || sh != 8)
282 /* It seems that it *must* be 8x8, at least on my machine.
283 * Thus, tile an 8x8 bitmap with the stipple in case it is
284 * smaller, or simply use just the top left 8x8 in case it is
288 GdkPixmap *bm = gdk_bitmap_create_from_data (NULL, dummy, 8, 8);
289 GdkGC *gc = gdk_gc_new (bm);
298 gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
303 win32_gc->stipple = bm;
307 gdk_drawable_ref (win32_gc->stipple);
308 win32_gc->values_mask |= GDK_GC_STIPPLE;
310 (g_print ("%sstipple=%#x", s,
311 (guint) GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
316 win32_gc->values_mask &= ~GDK_GC_STIPPLE;
317 GDK_NOTE (MISC, (g_print ("%sstipple=NULL", s),
322 if (mask & GDK_GC_CLIP_MASK)
324 if (win32_gc->clip_region != NULL)
326 gdk_region_destroy (win32_gc->clip_region);
327 win32_gc->clip_region = NULL;
330 if (win32_gc->hcliprgn != NULL)
332 DeleteObject (win32_gc->hcliprgn);
333 win32_gc->hcliprgn = NULL;
336 if (values->clip_mask != NULL)
339 BitmapToRegion ((HBITMAP) GDK_PIXMAP_HBITMAP (values->clip_mask));
340 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
344 win32_gc->hcliprgn = NULL;
345 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
347 GDK_NOTE (MISC, (g_print ("%sclip=%#x", s, (guint) win32_gc->hcliprgn),
351 if (mask & GDK_GC_SUBWINDOW)
353 win32_gc->subwindow_mode = values->subwindow_mode;
354 win32_gc->values_mask |= GDK_GC_SUBWINDOW;
355 GDK_NOTE (MISC, (g_print ("%ssubw=%d", s, win32_gc->subwindow_mode),
359 if (mask & GDK_GC_TS_X_ORIGIN)
361 win32_gc->values_mask |= GDK_GC_TS_X_ORIGIN;
362 GDK_NOTE (MISC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
366 if (mask & GDK_GC_TS_Y_ORIGIN)
368 win32_gc->values_mask |= GDK_GC_TS_Y_ORIGIN;
369 GDK_NOTE (MISC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
373 if (mask & GDK_GC_CLIP_X_ORIGIN)
375 win32_gc->values_mask |= GDK_GC_CLIP_X_ORIGIN;
376 GDK_NOTE (MISC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
380 if (mask & GDK_GC_CLIP_Y_ORIGIN)
382 win32_gc->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
383 GDK_NOTE (MISC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
387 if (mask & GDK_GC_EXPOSURES)
389 win32_gc->graphics_exposures = values->graphics_exposures;
390 win32_gc->values_mask |= GDK_GC_EXPOSURES;
391 GDK_NOTE (MISC, (g_print ("%sexp=%d", s, win32_gc->graphics_exposures),
395 if (mask & GDK_GC_LINE_WIDTH)
397 win32_gc->pen_width = values->line_width;
398 win32_gc->values_mask |= GDK_GC_LINE_WIDTH;
399 GDK_NOTE (MISC, (g_print ("%spw=%d", s, win32_gc->pen_width),
403 if (mask & GDK_GC_LINE_STYLE)
405 win32_gc->pen_style &= ~(PS_STYLE_MASK);
406 GDK_NOTE (MISC, (g_print ("%sps|=", s),
408 switch (values->line_style)
411 GDK_NOTE (MISC, g_print ("LINE_SOLID"));
412 win32_gc->pen_style |= PS_SOLID;
414 case GDK_LINE_ON_OFF_DASH:
415 case GDK_LINE_DOUBLE_DASH: /* ??? */
416 GDK_NOTE (MISC, g_print ("DASH"));
417 win32_gc->pen_style |= PS_DASH;
420 win32_gc->values_mask |= GDK_GC_LINE_STYLE;
423 if (mask & GDK_GC_CAP_STYLE)
425 win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
426 GDK_NOTE (MISC, (g_print ("%sps|=", s),
428 switch (values->cap_style)
430 case GDK_CAP_NOT_LAST: /* ??? */
432 GDK_NOTE (MISC, g_print ("ENDCAP_FLAT"));
433 win32_gc->pen_style |= PS_ENDCAP_FLAT;
436 GDK_NOTE (MISC, g_print ("ENDCAP_ROUND"));
437 win32_gc->pen_style |= PS_ENDCAP_ROUND;
439 case GDK_CAP_PROJECTING:
440 GDK_NOTE (MISC, g_print ("ENDCAP_SQUARE"));
441 win32_gc->pen_style |= PS_ENDCAP_SQUARE;
444 win32_gc->values_mask |= GDK_GC_CAP_STYLE;
447 if (mask & GDK_GC_JOIN_STYLE)
449 win32_gc->pen_style &= ~(PS_JOIN_MASK);
450 GDK_NOTE (MISC, (g_print ("%sps|=", s),
452 switch (values->join_style)
455 GDK_NOTE (MISC, g_print ("JOIN_MITER"));
456 win32_gc->pen_style |= PS_JOIN_MITER;
459 GDK_NOTE (MISC, g_print ("JOIN_ROUND"));
460 win32_gc->pen_style |= PS_JOIN_ROUND;
463 GDK_NOTE (MISC, g_print ("JOIN_BEVEL"));
464 win32_gc->pen_style |= PS_JOIN_BEVEL;
467 win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
469 GDK_NOTE (MISC, g_print ("}\n"));
473 _gdk_win32_gc_new (GdkDrawable *drawable,
475 GdkGCValuesMask mask)
478 GdkGCWin32 *win32_gc;
480 /* NOTICE that the drawable here has to be the impl drawable,
481 * not the publically-visible drawables.
483 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
485 gc = g_object_new (gdk_gc_win32_get_type (), NULL);
486 win32_gc = GDK_GC_WIN32 (gc);
488 win32_gc->hdc = NULL;
489 win32_gc->clip_region = NULL;
490 win32_gc->hcliprgn = NULL;
492 /* Use the same default values as X11 does, even if they don't make
493 * sense per se. But apps always set fg and bg anyway.
495 win32_gc->foreground = 0;
496 win32_gc->background = 1;
497 win32_gc->font = NULL;
498 win32_gc->rop2 = R2_COPYPEN;
499 win32_gc->fill_style = GDK_SOLID;
500 win32_gc->tile = NULL;
501 win32_gc->stipple = NULL;
502 win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
503 win32_gc->pen_width = 0;
505 win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
507 GDK_NOTE (MISC, g_print ("_gdk_win32_gc_new: "));
508 gdk_win32_gc_values_to_win32values (values, mask, win32_gc);
510 win32_gc->hwnd = NULL;
512 GDK_NOTE (MISC, g_print (" = %p\n", gc));
518 gdk_win32_gc_get_values (GdkGC *gc,
521 GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
523 values->foreground.pixel = win32_gc->foreground;
524 values->background.pixel = win32_gc->background;
525 values->font = win32_gc->font;
527 switch (win32_gc->rop2)
530 values->function = GDK_COPY; break;
532 values->function = GDK_INVERT; break;
534 values->function = GDK_XOR; break;
536 values->function = GDK_CLEAR; break;
538 values->function = GDK_AND; break;
540 values->function = GDK_AND_REVERSE; break;
542 values->function = GDK_AND_INVERT; break;
544 values->function = GDK_NOOP; break;
546 values->function = GDK_OR; break;
548 values->function = GDK_EQUIV; break;
550 values->function = GDK_OR_REVERSE; break;
552 values->function = GDK_COPY_INVERT; break;
554 values->function = GDK_OR_INVERT; break;
556 values->function = GDK_NAND; break;
558 values->function = GDK_NOR; break;
560 values->function = GDK_SET; break;
563 values->fill = win32_gc->fill_style;
565 values->tile = win32_gc->tile;
566 values->stipple = win32_gc->stipple;
568 /* Also the X11 backend always returns a NULL clip_mask */
569 values->clip_mask = NULL;
571 values->subwindow_mode = win32_gc->subwindow_mode;
572 values->ts_x_origin = win32_gc->parent_instance.ts_x_origin;
573 values->ts_y_origin = win32_gc->parent_instance.ts_y_origin;
574 values->clip_x_origin = win32_gc->parent_instance.clip_x_origin;
575 values->clip_y_origin = win32_gc->parent_instance.clip_y_origin;
576 values->graphics_exposures = win32_gc->graphics_exposures;
577 values->line_width = win32_gc->pen_width;
579 if (win32_gc->pen_style & PS_SOLID)
580 values->line_style = GDK_LINE_SOLID;
581 else if (win32_gc->pen_style & PS_DASH)
582 values->line_style = GDK_LINE_ON_OFF_DASH;
584 values->line_style = GDK_LINE_SOLID;
586 /* PS_ENDCAP_ROUND is zero */
587 if (win32_gc->pen_style & PS_ENDCAP_FLAT)
588 values->cap_style = GDK_CAP_BUTT;
589 else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
590 values->cap_style = GDK_CAP_PROJECTING;
592 values->cap_style = GDK_CAP_ROUND;
594 /* PS_JOIN_ROUND is zero */
595 if (win32_gc->pen_style & PS_JOIN_MITER)
596 values->join_style = GDK_JOIN_MITER;
597 else if (win32_gc->pen_style & PS_JOIN_BEVEL)
598 values->join_style = GDK_JOIN_BEVEL;
600 values->join_style = GDK_JOIN_ROUND;
604 gdk_win32_gc_set_values (GdkGC *gc,
606 GdkGCValuesMask mask)
608 g_return_if_fail (GDK_IS_GC (gc));
610 GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_values: "));
612 gdk_win32_gc_values_to_win32values (values, mask, GDK_GC_WIN32 (gc));
616 gdk_win32_gc_set_dashes (GdkGC *gc,
621 GdkGCWin32 *win32_gc;
623 g_return_if_fail (GDK_IS_GC (gc));
624 g_return_if_fail (dash_list != NULL);
626 win32_gc = GDK_GC_WIN32 (gc);
628 win32_gc->pen_style &= ~(PS_STYLE_MASK);
629 win32_gc->pen_style |= PS_DASH;
632 * Set the extended line style. This could be done by
633 * PS_USERSTYLE and ExtCreatePen; but ONLY on WinNT,
634 * so let's make a guess (based on the implementation
635 * in DIA). On Win9x this does only work for lines
638 * More workarounds for Win9x descibed at:
639 * http://www.codeguru.com/gdi/dashed.shtml
641 if (!IS_WIN_NT () && win32_gc->pen_width > 1)
643 GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_dashes: not fully supported\n"));
644 win32_gc->pen_style |= PS_SOLID;
648 win32_gc->pen_style = PS_COSMETIC; /* ??? */
651 if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2))
653 win32_gc->pen_style |= PS_DASH;
654 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n",
655 dash_list[0], dash_list[1]));
659 win32_gc->pen_style |= PS_DOT;
660 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DOT (%d,%d)\n",
661 dash_list[0], dash_list[1]));
666 win32_gc->pen_style |= PS_DASHDOT;
667 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOT (%d,%d,%d,%d)\n",
668 dash_list[0], dash_list[1],
669 dash_list[2], dash_list[3]));
673 win32_gc->pen_style |= PS_DASHDOTDOT;
674 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOTDOT (%d,%d,%d,%d,%d,%d)\n",
675 dash_list[0], dash_list[1],
676 dash_list[2], dash_list[3],
677 dash_list[4], dash_list[5]));
681 win32_gc->pen_style |= PS_DASH;
682 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: no guess for %d dashes\n", n));
687 gdk_gc_set_clip_rectangle (GdkGC *gc,
688 GdkRectangle *rectangle)
690 GdkGCWin32 *win32_gc;
692 g_return_if_fail (GDK_IS_GC (gc));
694 win32_gc = GDK_GC_WIN32 (gc);
696 if (win32_gc->hcliprgn)
698 DeleteObject (win32_gc->hcliprgn);
699 win32_gc->hcliprgn = NULL;
702 if (win32_gc->clip_region)
703 gdk_region_destroy (win32_gc->clip_region);
708 g_print ("gdk_gc_set_clip_rectangle: %dx%d@+%d+%d\n",
709 rectangle->width, rectangle->height,
710 rectangle->x, rectangle->y));
711 win32_gc->clip_region = gdk_region_rectangle (rectangle);
712 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
716 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));
718 win32_gc->clip_region = NULL;
719 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
721 win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
725 gdk_gc_set_clip_region (GdkGC *gc,
728 GdkGCWin32 *win32_gc;
730 g_return_if_fail (GDK_IS_GC (gc));
732 win32_gc = GDK_GC_WIN32 (gc);
734 if (win32_gc->clip_region)
735 gdk_region_destroy (win32_gc->clip_region);
739 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: %dx%d+%d+%d\n",
740 region->extents.x2 - region->extents.x1,
741 region->extents.y2 - region->extents.y1,
742 region->extents.x1, region->extents.y1));
744 win32_gc->clip_region = gdk_region_copy (region);
745 win32_gc->values_mask |= GDK_GC_CLIP_MASK;
749 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: NULL\n"));
751 win32_gc->clip_region = NULL;
752 win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
755 gc->clip_x_origin = 0;
756 gc->clip_y_origin = 0;
758 win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
762 gdk_gc_copy (GdkGC *dst_gc,
765 GdkGCWin32 *dst_win32_gc;
766 GdkGCWin32 *src_win32_gc;
768 g_return_if_fail (GDK_IS_GC_WIN32 (dst_gc));
769 g_return_if_fail (GDK_IS_GC_WIN32 (src_gc));
771 dst_win32_gc = GDK_GC_WIN32 (dst_gc);
772 src_win32_gc = GDK_GC_WIN32 (src_gc);
774 if (dst_win32_gc->font != NULL)
775 gdk_font_unref (dst_win32_gc->font);
776 if (dst_win32_gc->tile != NULL)
777 gdk_drawable_unref (dst_win32_gc->tile);
778 if (dst_win32_gc->stipple != NULL)
779 gdk_drawable_unref (dst_win32_gc->stipple);
780 if (dst_win32_gc->clip_region != NULL)
781 gdk_region_destroy (dst_win32_gc->clip_region);
782 if (dst_win32_gc->hcliprgn != NULL)
783 DeleteObject (dst_win32_gc->hcliprgn);
785 *dst_win32_gc = *src_win32_gc;
787 if (dst_win32_gc->hcliprgn)
789 /* create a new region, to copy to */
790 dst_win32_gc->hcliprgn = CreateRectRgn(0,0,1,1);
791 /* overwrite from source */
792 CombineRgn (dst_win32_gc->hcliprgn, src_win32_gc->hcliprgn,
795 if (dst_win32_gc->clip_region != NULL)
796 dst_win32_gc->clip_region = gdk_region_copy (dst_win32_gc->clip_region);
797 if (dst_win32_gc->font != NULL)
798 gdk_font_ref (dst_win32_gc->font);
799 if (dst_win32_gc->tile != NULL)
800 gdk_drawable_ref (dst_win32_gc->tile);
801 if (dst_win32_gc->stipple != NULL)
802 gdk_drawable_ref (dst_win32_gc->stipple);
805 static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
808 gdk_colormap_color (GdkColormap *colormap,
811 const GdkVisual *visual;
812 GdkColormapPrivateWin32 *colormap_private;
815 if (colormap == NULL)
816 return PALETTEINDEX (pixel);
818 colormap_private = GDK_COLORMAP_PRIVATE_DATA (colormap);
820 g_return_val_if_fail(colormap_private != NULL, RGB (0,0,0));
822 if (colormap_private->xcolormap->rc_palette)
823 return PALETTEINDEX (pixel);
825 visual = colormap->visual;
826 r = (pixel & visual->red_mask) >> visual->red_shift;
827 r = (r * 255) / bitmask[visual->red_prec];
828 g = (pixel & visual->green_mask) >> visual->green_shift;
829 g = (g * 255) / bitmask[visual->green_prec];
830 b = (pixel & visual->blue_mask) >> visual->blue_shift;
831 b = (b * 255) / bitmask[visual->blue_prec];
833 return RGB (r, g, b);
837 predraw_set_foreground (GdkGC *gc,
838 GdkColormap *colormap,
841 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
842 GdkColormapPrivateWin32 *colormap_private;
848 if (colormap == NULL)
850 /* A 1 bit deep bitmap */
855 PALETTEENTRY palPalEntry[2];
857 static HPALETTE hpal = NULL;
861 /* Create a b&w palette */
862 logpal.palVersion = 0x300;
863 logpal.palNumEntries = 2;
864 logpal.palPalEntry[0].peRed =
865 logpal.palPalEntry[0].peGreen =
866 logpal.palPalEntry[0].peBlue = 0x00;
867 logpal.palPalEntry[0].peFlags = 0x00;
868 logpal.palPalEntry[1].peRed =
869 logpal.palPalEntry[1].peGreen =
870 logpal.palPalEntry[1].peBlue = 0xFF;
871 logpal.palPalEntry[1].peFlags = 0x00;
872 if ((hpal = CreatePalette ((LOGPALETTE *) &logpal)) == NULL)
873 WIN32_GDI_FAILED ("CreatePalette"), *ok = FALSE;
875 SelectPalette (win32_gc->hdc, hpal, FALSE);
876 RealizePalette (win32_gc->hdc);
877 fg = PALETTEINDEX (win32_gc->foreground);
881 colormap_private = GDK_COLORMAP_PRIVATE_DATA (colormap);
882 /* maybe this should bail out with g_return_if_fail
883 * (colormap_private != NULL) ?
885 if (colormap_private && colormap_private->xcolormap->rc_palette)
888 if (SelectPalette (win32_gc->hdc, colormap_private->xcolormap->palette,
890 WIN32_GDI_FAILED ("SelectPalette"), *ok = FALSE;
891 if (TRUE || colormap_private->xcolormap->stale)
893 if ((k = RealizePalette (win32_gc->hdc)) == GDI_ERROR)
894 WIN32_GDI_FAILED ("RealizePalette"), *ok = FALSE;
895 colormap_private->xcolormap->stale = FALSE;
898 g_print ("Selected palette %#x for gc %#x, realized %d colors\n",
899 colormap_private->xcolormap->palette, win32_gc->hdc, k);
904 fg = gdk_colormap_color (colormap, win32_gc->foreground);
906 if (SetTextColor (win32_gc->hdc, fg) == CLR_INVALID)
907 WIN32_GDI_FAILED ("SetTextColor"), *ok = FALSE;
909 /* Create and select pen and brush. */
911 logbrush.lbStyle = BS_SOLID;
912 logbrush.lbColor = fg;
914 if (*ok && (hpen = ExtCreatePen (win32_gc->pen_style,
915 (win32_gc->pen_width > 0 ? win32_gc->pen_width : 1),
916 &logbrush, 0, NULL)) == NULL)
917 WIN32_GDI_FAILED ("ExtCreatePen");
919 if (SelectObject (win32_gc->hdc, hpen) == NULL)
920 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
922 switch (win32_gc->fill_style)
924 case GDK_OPAQUE_STIPPLED:
925 if (*ok && (hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (win32_gc->stipple))) == NULL)
926 WIN32_GDI_FAILED ("CreatePatternBrush"), *ok = FALSE;
928 if (*ok && !SetBrushOrgEx(win32_gc->hdc, gc->ts_x_origin,
929 gc->ts_y_origin, NULL))
930 WIN32_GDI_FAILED ("SetBrushOrgEx"), *ok = FALSE;
935 if (*ok && (hbr = CreateSolidBrush (fg)) == NULL)
936 WIN32_GDI_FAILED ("CreateSolidBrush"), *ok = FALSE;
939 if (*ok && SelectObject (win32_gc->hdc, hbr) == NULL)
940 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
944 predraw_set_background (GdkGC *gc,
945 GdkColormap *colormap,
948 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
950 if (win32_gc->values_mask & GDK_GC_BACKGROUND)
952 COLORREF bg = gdk_colormap_color (colormap, win32_gc->background);
954 if (SetBkColor (win32_gc->hdc, bg) == CLR_INVALID)
955 WIN32_GDI_FAILED ("SetBkColor"), *ok = FALSE;
959 if (0 == SetBkMode (win32_gc->hdc, TRANSPARENT))
960 WIN32_GDI_FAILED ("SetBkMode"), *ok = FALSE;
965 gdk_win32_hdc_get (GdkDrawable *drawable,
967 GdkGCValuesMask usage)
969 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
970 GdkDrawableImplWin32 *impl;
974 g_assert (win32_gc->hdc == NULL);
976 if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
977 impl = GDK_DRAWABLE_IMPL_WIN32(drawable);
978 else if (GDK_IS_WINDOW (drawable))
979 impl = ((GdkWindowObject *) drawable)->impl;
980 else if (GDK_IS_PIXMAP (drawable))
981 impl = ((GdkPixmapObject *) drawable)->impl;
983 win32_gc->hwnd = impl->handle;
985 if (GDK_IS_PIXMAP_IMPL_WIN32 (impl))
987 if ((win32_gc->hdc = CreateCompatibleDC (NULL)) == NULL)
988 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
990 if (ok && (win32_gc->saved_dc = SaveDC (win32_gc->hdc)) == 0)
991 WIN32_GDI_FAILED ("SaveDC"), ok = FALSE;
993 if (ok && SelectObject (win32_gc->hdc, win32_gc->hwnd) == NULL)
994 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
998 if ((win32_gc->hdc = GetDC (win32_gc->hwnd)) == NULL)
999 WIN32_GDI_FAILED ("GetDC");
1001 if (ok && (win32_gc->saved_dc = SaveDC (win32_gc->hdc)) == 0)
1002 WIN32_GDI_FAILED ("SaveDC");
1005 if (ok && (usage & GDK_GC_FOREGROUND))
1006 predraw_set_foreground (gc, impl->colormap, &ok);
1009 && (usage & GDK_GC_BACKGROUND)
1010 /* && (win32_gc->values_mask & GDK_GC_BACKGROUND) */)
1011 predraw_set_background (gc, impl->colormap, &ok);
1013 if (ok && (usage & GDK_GC_FONT))
1015 if (SetBkMode (win32_gc->hdc, TRANSPARENT) == 0)
1016 WIN32_GDI_FAILED ("SetBkMode"), ok = FALSE;
1018 if (ok && SetTextAlign (win32_gc->hdc, TA_BASELINE) == GDI_ERROR)
1019 WIN32_GDI_FAILED ("SetTextAlign"), ok = FALSE;
1022 if (ok && (win32_gc->values_mask & GDK_GC_FUNCTION))
1023 if (SetROP2 (win32_gc->hdc, win32_gc->rop2) == 0)
1024 WIN32_GDI_FAILED ("SetROP2"), ok = FALSE;
1026 if (win32_gc->values_mask & GDK_GC_CLIP_MASK)
1027 g_assert ((win32_gc->clip_region != NULL) != (win32_gc->hcliprgn != NULL));
1030 && (win32_gc->values_mask & GDK_GC_CLIP_MASK)
1031 && win32_gc->clip_region != NULL)
1036 GdkRegionBox *boxes = win32_gc->clip_region->rects;
1038 sizeof (RGNDATAHEADER) + (sizeof (RECT) * win32_gc->clip_region->numRects);
1041 rgndata = g_malloc (nbytes);
1042 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
1043 rgndata->rdh.iType = RDH_RECTANGLES;
1044 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
1045 SetRect (&rgndata->rdh.rcBound,
1046 G_MAXSHORT, G_MAXSHORT, G_MINSHORT, G_MINSHORT);
1048 for (i = 0; i < win32_gc->clip_region->numRects; i++)
1050 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
1052 rect->left = CLAMP (boxes[i].x1 + gc->clip_x_origin,
1053 G_MINSHORT, G_MAXSHORT);
1054 rect->right = CLAMP (boxes[i].x2 + gc->clip_x_origin,
1055 G_MINSHORT, G_MAXSHORT);
1056 rect->top = CLAMP (boxes[i].y1 + gc->clip_y_origin,
1057 G_MINSHORT, G_MAXSHORT);
1058 rect->bottom = CLAMP (boxes[i].y2 + gc->clip_y_origin,
1059 G_MINSHORT, G_MAXSHORT);
1061 GDK_NOTE (MISC, g_print ("clip rgn box %d: %ldx%ld@+%ld+%ld\n",
1063 rect->right-rect->left,
1064 rect->bottom-rect->top,
1065 rect->left, rect->top));
1067 if (rect->left < rgndata->rdh.rcBound.left)
1068 rgndata->rdh.rcBound.left = rect->left;
1069 if (rect->right > rgndata->rdh.rcBound.right)
1070 rgndata->rdh.rcBound.right = rect->right;
1071 if (rect->top < rgndata->rdh.rcBound.top)
1072 rgndata->rdh.rcBound.top = rect->top;
1073 if (rect->bottom > rgndata->rdh.rcBound.bottom)
1074 rgndata->rdh.rcBound.bottom = rect->bottom;
1076 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
1077 WIN32_API_FAILED ("ExtCreateRegion"), ok = FALSE;
1079 if (ok && SelectClipRgn (win32_gc->hdc, hrgn) == ERROR)
1080 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
1083 DeleteObject (hrgn);
1086 && (win32_gc->values_mask & GDK_GC_CLIP_MASK)
1087 && win32_gc->hcliprgn != NULL)
1089 if (SelectClipRgn (win32_gc->hdc, win32_gc->hcliprgn) == ERROR)
1090 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
1091 if (ok && !OffsetClipRgn (win32_gc->hdc,
1092 win32_gc->values_mask & GDK_GC_CLIP_X_ORIGIN ? gc->clip_x_origin : 0,
1093 win32_gc->values_mask & GDK_GC_CLIP_Y_ORIGIN ? gc->clip_y_origin : 0))
1094 WIN32_API_FAILED ("OffsetClipRgn"), ok = FALSE;
1097 if (gdk_debug_flags & GDK_DEBUG_MISC)
1101 EXTLOGPEN extlogpen;
1105 g_print ("gdk_win32_hdc_get: %#x\n", (guint) win32_gc->hdc);
1106 obj = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH);
1107 GetObject (obj, sizeof (LOGBRUSH), &logbrush);
1108 g_print ("brush: style: %s color: %.06lx hatch: %#lx\n",
1109 (logbrush.lbStyle == BS_HOLLOW ? "HOLLOW" :
1110 (logbrush.lbStyle == BS_PATTERN ? "PATTERN" :
1111 (logbrush.lbStyle == BS_SOLID ? "SOLID" :
1115 obj = GetCurrentObject (win32_gc->hdc, OBJ_PEN);
1116 GetObject (obj, sizeof (EXTLOGPEN), &extlogpen);
1117 g_print ("pen: type: %s style: %s endcap: %s join: %s width: %d brush: %s\n",
1118 ((extlogpen.elpPenStyle & PS_TYPE_MASK) ==
1119 PS_GEOMETRIC ? "GEOMETRIC" : "COSMETIC"),
1120 ((extlogpen.elpPenStyle & PS_STYLE_MASK) ==
1122 ((extlogpen.elpPenStyle & PS_STYLE_MASK) ==
1123 PS_SOLID ? "SOLID" : "???")),
1124 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1125 PS_ENDCAP_FLAT ? "FLAT" :
1126 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1127 PS_ENDCAP_ROUND ? "ROUND" :
1128 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1129 PS_ENDCAP_SQUARE ? "ROUND" :
1130 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1131 PS_ENDCAP_SQUARE ? "ROUND" : "???")))),
1132 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1133 PS_JOIN_BEVEL ? "BEVEL" :
1134 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1135 PS_JOIN_MITER ? "MITER" :
1136 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1137 PS_JOIN_ROUND ? "ROUND" : "???"))),
1139 (extlogpen.elpBrushStyle == BS_DIBPATTERN ? "DIBPATTERN" :
1140 (extlogpen.elpBrushStyle == BS_DIBPATTERNPT ? "DIBPATTERNPT" :
1141 (extlogpen.elpBrushStyle == BS_HATCHED ? "HATCHED" :
1142 (extlogpen.elpBrushStyle == BS_HOLLOW ? "HOLLOW" :
1143 (extlogpen.elpBrushStyle == BS_PATTERN ? "PATTERN" :
1144 (extlogpen.elpBrushStyle == BS_SOLID ? "SOLID" : "???")))))));
1145 hrgn = CreateRectRgn (0, 0, 0, 0);
1146 if ((flag = GetClipRgn (win32_gc->hdc, hrgn)) == -1)
1147 WIN32_API_FAILED ("GetClipRgn");
1149 g_print ("no clip region\n");
1152 GetRgnBox (hrgn, &rect);
1153 g_print ("clip region bbox: %ldx%ld@+%ld+%ld\n",
1154 rect.right - rect.left,
1155 rect.bottom - rect.top,
1156 rect.left, rect.top);
1160 return win32_gc->hdc;
1164 gdk_win32_hdc_release (GdkDrawable *drawable,
1166 GdkGCValuesMask usage)
1168 GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
1169 GdkDrawableImplWin32 *impl;
1170 HGDIOBJ hpen = NULL;
1173 if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
1174 impl = GDK_DRAWABLE_IMPL_WIN32(drawable);
1175 else if (GDK_IS_WINDOW (drawable))
1176 impl = ((GdkWindowObject *) drawable)->impl;
1177 else if (GDK_IS_PIXMAP (drawable))
1178 impl = ((GdkPixmapObject *) drawable)->impl;
1180 if (usage & GDK_GC_FOREGROUND)
1182 if ((hpen = GetCurrentObject (win32_gc->hdc, OBJ_PEN)) == NULL)
1183 WIN32_GDI_FAILED ("GetCurrentObject");
1185 if ((hbr = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH)) == NULL)
1186 WIN32_GDI_FAILED ("GetCurrentObject");
1189 if (!RestoreDC (win32_gc->hdc, win32_gc->saved_dc))
1190 WIN32_GDI_FAILED ("RestoreDC");
1192 if (colormap_private != NULL
1193 && colormap_private->xcolormap->rc_palette
1194 && colormap_private->xcolormap->stale)
1196 SelectPalette (win32_gc->hdc, GetStockObject (DEFAULT_PALETTE), FALSE);
1197 if (!UnrealizeObject (colormap_private->xcolormap->palette))
1198 WIN32_GDI_FAILED ("UnrealizeObject");
1201 if (GDK_IS_PIXMAP_IMPL_WIN32 (impl))
1203 if (!DeleteDC (win32_gc->hdc))
1204 WIN32_GDI_FAILED ("DeleteDC");
1208 ReleaseDC (win32_gc->hwnd, win32_gc->hdc);
1212 if (!DeleteObject (hpen))
1213 WIN32_GDI_FAILED ("DeleteObject");
1216 if (!DeleteObject (hbr))
1217 WIN32_GDI_FAILED ("DeleteObject");
1219 win32_gc->hdc = NULL;
1222 /* This function originally from Jean-Edouard Lachand-Robert, and
1223 * available at www.codeguru.com. Simplified for our needs, now
1224 * handles just one-bit deep bitmaps (in Window parlance, ie those
1225 * that GDK calls bitmaps (and not pixmaps), with zero pixels being
1230 * BitmapToRegion : Create a region from the "non-transparent" pixels of
1232 * Author : Jean-Edouard Lachand-Robert
1233 * (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
1237 BitmapToRegion (HBITMAP hBmp)
1245 BITMAPINFOHEADER bmiHeader;
1249 RGBQUAD bmiColors[2];
1258 PALETTEENTRY palPalEntry[2];
1260 static HPALETTE bwPalette = NULL;
1273 /* Create a B&W palette */
1274 if (bwPalette == NULL)
1276 /* Create a b&w palette */
1277 logpal.palVersion = 0x300;
1278 logpal.palNumEntries = 2;
1279 logpal.palPalEntry[0].peRed =
1280 logpal.palPalEntry[0].peGreen =
1281 logpal.palPalEntry[0].peBlue = 0;
1282 logpal.palPalEntry[0].peFlags = 0;
1283 logpal.palPalEntry[1].peRed =
1284 logpal.palPalEntry[1].peGreen =
1285 logpal.palPalEntry[1].peBlue = 0xFF;
1286 logpal.palPalEntry[1].peFlags = 0;
1287 if ((bwPalette = CreatePalette ((LOGPALETTE *) &logpal)) == NULL)
1288 WIN32_GDI_FAILED ("CreatePalette");
1291 /* Create a memory DC inside which we will scan the bitmap content */
1292 hMemDC = CreateCompatibleDC (NULL);
1295 WIN32_GDI_FAILED ("CreateCompatibleDC");
1299 SelectPalette (hMemDC, bwPalette, FALSE);
1300 RealizePalette (hMemDC);
1302 /* Get bitmap size */
1303 GetObject(hBmp, sizeof(bm), &bm);
1305 /* Create a 8 bits depth bitmap and select it into the memory DC */
1306 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
1307 bmi.bmiHeader.biWidth = bm.bmWidth;
1308 bmi.bmiHeader.biHeight = bm.bmHeight;
1309 bmi.bmiHeader.biPlanes = 1;
1310 bmi.bmiHeader.biBitCount = 8;
1311 bmi.bmiHeader.biCompression = BI_RGB;
1312 bmi.bmiHeader.biSizeImage = 0;
1313 bmi.bmiHeader.biXPelsPerMeter = 0;
1314 bmi.bmiHeader.biYPelsPerMeter = 0;
1315 bmi.bmiHeader.biClrUsed = 2;
1316 bmi.bmiHeader.biClrImportant = 2;
1318 bmi.bmiColors[0] = 0;
1319 bmi.bmiColors[1] = 1;
1320 hbm8 = CreateDIBSection (hMemDC, (BITMAPINFO *)&bmi,
1321 DIB_PAL_COLORS, &pbits8, NULL, 0);
1323 bmi.bmiColors[0].rgbBlue =
1324 bmi.bmiColors[0].rgbGreen =
1325 bmi.bmiColors[0].rgbRed = 0x00;
1326 bmi.bmiColors[0].rgbReserved = 0x00;
1328 bmi.bmiColors[1].rgbBlue =
1329 bmi.bmiColors[1].rgbGreen =
1330 bmi.bmiColors[1].rgbRed = 0xFF;
1331 bmi.bmiColors[0].rgbReserved = 0x00;
1333 hbm8 = CreateDIBSection (hMemDC, (BITMAPINFO *)&bmi,
1334 DIB_RGB_COLORS, &pbits8, NULL, 0);
1338 WIN32_GDI_FAILED ("CreateDIBSection");
1343 holdBmp = (HBITMAP) SelectObject (hMemDC, hbm8);
1345 /* Create a DC just to copy the bitmap into the memory DC*/
1346 hDC = CreateCompatibleDC (hMemDC);
1349 WIN32_GDI_FAILED ("CreateCompatibleDC");
1350 SelectObject (hMemDC, holdBmp);
1351 DeleteObject (hbm8);
1356 /* Get how many bytes per row we have for the bitmap bits */
1357 GetObject (hbm8, sizeof (bm8), &bm8);
1359 /* Hans Breuer found a fix to the long-standing erroneous behaviour
1360 * on NT 4.0: There seems to be a bug in Win NT 4.0 GDI: scanlines
1361 * in bitmaps are dword aligned on both Win95 and NT. In the case of
1362 * a bitmap with 22 bytes worth of width, GetObject above returns
1363 * with bmWidth == 22. On Win95 bmWidthBytes == 24, as it should be,
1364 * but on NT is it 22. We need to correct this here.
1366 bm8.bmWidthBytes = (((bm8.bmWidthBytes-1)/4)+1)*4; /* dword aligned!! */
1368 /* Copy the bitmap into the memory DC*/
1369 holdBmp2 = (HBITMAP) SelectObject (hDC, hBmp);
1371 if (!BitBlt (hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY))
1373 WIN32_GDI_FAILED ("BitBlt");
1374 SelectObject (hDC, holdBmp2);
1375 SelectObject (hMemDC, holdBmp);
1376 DeleteObject (hbm8);
1380 SelectObject (hDC, holdBmp2);
1383 /* For better performances, we will use the ExtCreateRegion()
1384 * function to create the region. This function take a RGNDATA
1385 * structure on entry. We will add rectangles by amount of
1386 * ALLOC_UNIT number in this structure.
1388 #define ALLOC_UNIT 100
1389 maxRects = ALLOC_UNIT;
1391 pData = g_malloc (sizeof (RGNDATAHEADER) + (sizeof (RECT) * maxRects));
1392 pData->rdh.dwSize = sizeof (RGNDATAHEADER);
1393 pData->rdh.iType = RDH_RECTANGLES;
1394 pData->rdh.nCount = pData->rdh.nRgnSize = 0;
1395 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1397 /* Scan each bitmap from bottom to top (the bitmap is inverted vertically)*/
1398 p8 = (BYTE *) pbits8 + (bm8.bmHeight - 1) * bm8.bmWidthBytes;
1399 for (y = 0; y < bm.bmHeight; y++)
1401 /* Scan each bitmap row from left to right*/
1402 for (x = 0; x < bm.bmWidth; x++)
1404 /* Search for a continuous range of "non transparent pixels"*/
1407 while (x < bm.bmWidth)
1410 /* This pixel is "transparent"*/
1419 /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
1422 if (pData->rdh.nCount >= maxRects)
1424 maxRects += ALLOC_UNIT;
1425 pData = g_realloc (pData, sizeof(RGNDATAHEADER)
1426 + (sizeof(RECT) * maxRects));
1428 pr = (RECT *) &pData->Buffer;
1429 SetRect (&pr[pData->rdh.nCount], x0, y, x, y+1);
1430 if (x0 < pData->rdh.rcBound.left)
1431 pData->rdh.rcBound.left = x0;
1432 if (y < pData->rdh.rcBound.top)
1433 pData->rdh.rcBound.top = y;
1434 if (x > pData->rdh.rcBound.right)
1435 pData->rdh.rcBound.right = x;
1436 if (y+1 > pData->rdh.rcBound.bottom)
1437 pData->rdh.rcBound.bottom = y+1;
1438 pData->rdh.nCount++;
1440 /* On Windows98, ExtCreateRegion() may fail if the
1441 * number of rectangles is too large (ie: >
1442 * 4000). Therefore, we have to create the region by
1445 if (pData->rdh.nCount == 2000)
1447 HRGN h = ExtCreateRegion (NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
1450 CombineRgn(hRgn, hRgn, h, RGN_OR);
1455 pData->rdh.nCount = 0;
1456 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1461 /* Go to next row (remember, the bitmap is inverted vertically)*/
1462 p8 -= bm8.bmWidthBytes;
1465 /* Create or extend the region with the remaining rectangles*/
1466 h = ExtCreateRegion (NULL, sizeof (RGNDATAHEADER)
1467 + (sizeof (RECT) * maxRects), pData);
1470 CombineRgn (hRgn, hRgn, h, RGN_OR);
1478 SelectObject(hMemDC, holdBmp);
1479 DeleteObject (hbm8);
1485 #ifdef G_ENABLE_DEBUG
1488 gdk_win32_cap_style_to_string (GdkCapStyle cap_style)
1492 #define CASE(x) case x: return #x + strlen ("GDK_CAP_")
1493 CASE (GDK_CAP_NOT_LAST);
1494 CASE (GDK_CAP_BUTT);
1495 CASE (GDK_CAP_ROUND);
1496 CASE (GDK_CAP_PROJECTING);
1498 default: return ("illegal GdkCapStyle value");
1505 gdk_win32_fill_style_to_string (GdkFill fill)
1509 #define CASE(x) case x: return #x + strlen ("GDK_")
1512 CASE (GDK_STIPPLED);
1513 CASE (GDK_OPAQUE_STIPPLED);
1515 default: return ("illegal GdkFill value");
1522 gdk_win32_function_to_string (GdkFunction function)
1526 #define CASE(x) case x: return #x + strlen ("GDK_")
1532 CASE (GDK_AND_REVERSE);
1533 CASE (GDK_AND_INVERT);
1537 CASE (GDK_OR_REVERSE);
1538 CASE (GDK_COPY_INVERT);
1539 CASE (GDK_OR_INVERT);
1543 default: return ("illegal GdkFunction value");
1550 gdk_win32_join_style_to_string (GdkJoinStyle join_style)
1554 #define CASE(x) case x: return #x + strlen ("GDK_JOIN_")
1555 CASE (GDK_JOIN_MITER);
1556 CASE (GDK_JOIN_ROUND);
1557 CASE (GDK_JOIN_BEVEL);
1559 default: return ("illegal GdkJoinStyle value");
1566 gdk_win32_line_style_to_string (GdkLineStyle line_style)
1570 #define CASE(x) case x: return #x + strlen ("GDK_LINE_")
1571 CASE(GDK_LINE_SOLID);
1572 CASE(GDK_LINE_ON_OFF_DASH);
1573 CASE(GDK_LINE_DOUBLE_DASH);
1575 default: return ("illegal GdkLineStyle value");