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 Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. 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_destroy (GdkGC *gc);
39 static void gdk_win32_gc_get_values (GdkGC *gc,
41 static void gdk_win32_gc_set_values (GdkGC *gc,
43 GdkGCValuesMask values_mask);
44 static void gdk_win32_gc_set_dashes (GdkGC *gc,
49 static GdkGCClass gdk_win32_gc_class = {
51 gdk_win32_gc_get_values,
52 gdk_win32_gc_set_values,
53 gdk_win32_gc_set_dashes
57 gdk_win32_gc_values_to_win32values (GdkGCValues *values,
61 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc);
65 GDK_NOTE (MISC, g_print ("{"));
67 if (mask & GDK_GC_FOREGROUND)
69 data->foreground = values->foreground.pixel;
70 data->values_mask |= GDK_GC_FOREGROUND;
71 GDK_NOTE (MISC, (g_print ("fg=%.06x", data->foreground),
75 if (mask & GDK_GC_BACKGROUND)
77 data->background = values->background.pixel;
78 data->values_mask |= GDK_GC_BACKGROUND;
79 GDK_NOTE (MISC, (g_print ("%sbg=%.06x", s, data->background),
83 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
84 || values->font->type == GDK_FONT_FONTSET))
86 if (data->font != NULL)
87 gdk_font_unref (data->font);
88 data->font = values->font;
89 if (data->font != NULL)
93 gdk_font_ref (data->font);
94 data->values_mask |= GDK_GC_FONT;
95 GDK_NOTE (MISC, (xlfd = gdk_font_full_name_get (data->font),
96 g_print ("%sfont=%s", s, xlfd),
98 gdk_font_full_name_free (xlfd)));
102 data->values_mask &= ~GDK_GC_FONT;
103 GDK_NOTE (MISC, (g_print ("%sfont=NULL"),
108 if (mask & GDK_GC_FUNCTION)
110 GDK_NOTE (MISC, (g_print ("%srop2=", s),
112 switch (values->function)
115 data->rop2 = R2_COPYPEN;
116 GDK_NOTE (MISC, g_print ("COPYPEN"));
120 GDK_NOTE (MISC, g_print ("NOT"));
123 data->rop2 = R2_XORPEN;
124 GDK_NOTE (MISC, g_print ("XORPEN"));
127 data->rop2 = R2_BLACK;
128 GDK_NOTE (MISC, g_print ("BLACK"));
131 data->rop2 = R2_MASKPEN;
132 GDK_NOTE (MISC, g_print ("MASKPEN"));
134 case GDK_AND_REVERSE:
135 data->rop2 = R2_MASKPENNOT;
136 GDK_NOTE (MISC, g_print ("MASKPENNOT"));
139 data->rop2 = R2_MASKNOTPEN;
140 GDK_NOTE (MISC, g_print ("MASKNOTPEN"));
144 GDK_NOTE (MISC, g_print ("NOP"));
147 data->rop2 = R2_MERGEPEN;
148 GDK_NOTE (MISC, g_print ("MERGEPEN"));
151 data->rop2 = R2_NOTXORPEN;
152 GDK_NOTE (MISC, g_print ("NOTXORPEN"));
155 data->rop2 = R2_MERGEPENNOT;
156 GDK_NOTE (MISC, g_print ("MERGEPENNOT"));
158 case GDK_COPY_INVERT:
159 data->rop2 = R2_NOTCOPYPEN;
160 GDK_NOTE (MISC, g_print ("NOTCOPYPEN"));
163 data->rop2 = R2_MERGENOTPEN;
164 GDK_NOTE (MISC, g_print ("MERGENOTPEN"));
167 data->rop2 = R2_NOTMASKPEN;
168 GDK_NOTE (MISC, g_print ("NOTMASKPEN"));
171 data->rop2 = R2_WHITE;
172 GDK_NOTE (MISC, g_print ("WHITE"));
175 data->values_mask |= GDK_GC_FUNCTION;
178 if (mask & GDK_GC_FILL)
180 data->fill_style = values->fill;
181 data->values_mask |= GDK_GC_FILL;
182 GDK_NOTE (MISC, (g_print ("%sfill=%d", s, data->fill_style),
186 if (mask & GDK_GC_TILE)
188 if (data->tile != NULL)
189 gdk_drawable_unref (data->tile);
190 data->tile = values->tile;
191 if (data->tile != NULL)
193 gdk_drawable_ref (data->tile);
194 data->values_mask |= GDK_GC_TILE;
195 GDK_NOTE (MISC, (g_print ("%stile=%#x", s,
196 GDK_DRAWABLE_XID (data->tile)),
201 data->values_mask &= ~GDK_GC_TILE;
202 GDK_NOTE (MISC, (g_print ("%stile=NULL", s),
207 if (mask & GDK_GC_STIPPLE)
209 if (data->stipple != NULL)
210 gdk_drawable_unref (data->stipple);
211 data->stipple = values->stipple;
212 if (data->stipple != NULL)
214 gdk_drawable_get_size (data->stipple, &sw, &sh);
216 if (sw != 8 || sh != 8)
218 /* It seems that it *must* be 8x8, at least on my machine.
219 * Thus, tile an 8x8 bitmap with the stipple in case it is
220 * smaller, or simply use just the top left 8x8 in case it is
224 GdkPixmap *bm = gdk_bitmap_create_from_data (NULL, dummy, 8, 8);
225 GdkGC *gc = gdk_gc_new (bm);
234 gdk_draw_drawable (bm, gc, data->stipple, 0, 0, i, j, sw, sh);
243 gdk_drawable_ref (data->stipple);
244 data->values_mask |= GDK_GC_STIPPLE;
245 GDK_NOTE (MISC, (g_print ("%sstipple=%#x", s,
246 GDK_DRAWABLE_XID (data->stipple)),
251 data->values_mask &= ~GDK_GC_STIPPLE;
252 GDK_NOTE (MISC, (g_print ("%sstipple=NULL", s),
257 if (mask & GDK_GC_CLIP_MASK)
259 if (data->clip_region != NULL)
261 gdk_region_destroy (data->clip_region);
262 data->clip_region = NULL;
264 if (data->hcliprgn != NULL)
265 DeleteObject (data->hcliprgn);
267 if (values->clip_mask != NULL)
270 BitmapToRegion ((HBITMAP) GDK_DRAWABLE_XID (values->clip_mask));
271 data->values_mask |= GDK_GC_CLIP_MASK;
272 OffsetRgn (data->hcliprgn,
273 ((GdkGCPrivate *) gc)->clip_x_origin,
274 ((GdkGCPrivate *) gc)->clip_y_origin);
278 data->hcliprgn = NULL;
279 data->values_mask &= ~GDK_GC_CLIP_MASK;
281 GDK_NOTE (MISC, (g_print ("%sclip=%#x", s, data->hcliprgn),
285 if (mask & GDK_GC_SUBWINDOW)
287 data->subwindow_mode = values->subwindow_mode;
288 data->values_mask |= GDK_GC_SUBWINDOW;
289 GDK_NOTE (MISC, (g_print ("%ssubw=%d", s, data->subwindow_mode),
293 if (mask & GDK_GC_TS_X_ORIGIN)
295 data->values_mask |= GDK_GC_TS_X_ORIGIN;
296 GDK_NOTE (MISC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
300 if (mask & GDK_GC_TS_Y_ORIGIN)
302 data->values_mask |= GDK_GC_TS_Y_ORIGIN;
303 GDK_NOTE (MISC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
307 if (mask & GDK_GC_CLIP_X_ORIGIN)
309 data->values_mask |= GDK_GC_CLIP_X_ORIGIN;
310 GDK_NOTE (MISC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
314 if (mask & GDK_GC_CLIP_Y_ORIGIN)
316 data->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
317 GDK_NOTE (MISC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
321 if (mask & GDK_GC_EXPOSURES)
323 data->graphics_exposures = values->graphics_exposures;
324 data->values_mask |= GDK_GC_EXPOSURES;
325 GDK_NOTE (MISC, (g_print ("%sexp=%d", s, data->graphics_exposures),
329 if (mask & GDK_GC_LINE_WIDTH)
331 data->pen_width = values->line_width;
332 data->values_mask |= GDK_GC_LINE_WIDTH;
333 GDK_NOTE (MISC, (g_print ("%spw=%d", s, data->pen_width),
337 if (mask & GDK_GC_LINE_STYLE)
339 data->pen_style &= ~(PS_STYLE_MASK);
340 GDK_NOTE (MISC, (g_print ("%sps|=", s),
342 switch (values->line_style)
345 GDK_NOTE (MISC, g_print ("LINE_SOLID"));
346 data->pen_style |= PS_SOLID;
348 case GDK_LINE_ON_OFF_DASH:
349 case GDK_LINE_DOUBLE_DASH: /* ??? */
350 GDK_NOTE (MISC, g_print ("DASH"));
351 data->pen_style |= PS_DASH;
354 data->values_mask |= GDK_GC_LINE_STYLE;
357 if (mask & GDK_GC_CAP_STYLE)
359 data->pen_style &= ~(PS_ENDCAP_MASK);
360 GDK_NOTE (MISC, (g_print ("%sps|=", s),
362 switch (values->cap_style)
364 case GDK_CAP_NOT_LAST: /* ??? */
366 GDK_NOTE (MISC, g_print ("ENDCAP_FLAT"));
367 data->pen_style |= PS_ENDCAP_FLAT;
370 GDK_NOTE (MISC, g_print ("ENDCAP_ROUND"));
371 data->pen_style |= PS_ENDCAP_ROUND;
373 case GDK_CAP_PROJECTING:
374 GDK_NOTE (MISC, g_print ("ENDCAP_SQUARE"));
375 data->pen_style |= PS_ENDCAP_SQUARE;
378 data->values_mask |= GDK_GC_CAP_STYLE;
381 if (mask & GDK_GC_JOIN_STYLE)
383 data->pen_style &= ~(PS_JOIN_MASK);
384 GDK_NOTE (MISC, (g_print ("%sps|=", s),
386 switch (values->join_style)
389 GDK_NOTE (MISC, g_print ("JOIN_MITER"));
390 data->pen_style |= PS_JOIN_MITER;
393 GDK_NOTE (MISC, g_print ("JOIN_ROUND"));
394 data->pen_style |= PS_JOIN_ROUND;
397 GDK_NOTE (MISC, g_print ("JOIN_BEVEL"));
398 data->pen_style |= PS_JOIN_BEVEL;
401 data->values_mask |= GDK_GC_JOIN_STYLE;
403 GDK_NOTE (MISC, g_print ("}\n"));
407 _gdk_win32_gc_new (GdkDrawable *drawable,
409 GdkGCValuesMask mask)
412 GdkGCPrivate *private;
413 GdkGCWin32Data *data;
414 static GdkColor black;
415 static GdkColor white;
416 static gboolean beenhere = FALSE;
420 gdk_color_black (gdk_colormap_get_system (), &black);
421 gdk_color_white (gdk_colormap_get_system (), &white);
425 gc = gdk_gc_alloc ();
426 private = (GdkGCPrivate *)gc;
428 private->klass = &gdk_win32_gc_class;
429 private->klass_data = data = g_new (GdkGCWin32Data, 1);
431 data->clip_region = NULL;
433 data->foreground = black.pixel;
434 data->background = white.pixel;
436 data->rop2 = R2_COPYPEN;
437 data->fill_style = GDK_SOLID;
439 data->stipple = NULL;
440 data->pen_style = PS_GEOMETRIC;
443 data->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
445 GDK_NOTE (MISC, g_print ("_gdk_win32_gc_new: "));
446 gdk_win32_gc_values_to_win32values (values, mask, gc);
450 data->hcliprgn = NULL;
452 GDK_NOTE (MISC, g_print (" = %p\n", gc));
458 gdk_win32_gc_destroy (GdkGC *gc)
460 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc);
462 if (data->clip_region)
463 gdk_region_destroy (data->clip_region);
465 if (data->values_mask & GDK_GC_FONT)
466 gdk_font_unref (data->font);
468 if (data->values_mask & GDK_GC_TILE)
469 gdk_drawable_unref (data->tile);
471 if (data->values_mask & GDK_GC_STIPPLE)
472 gdk_drawable_unref (data->stipple);
474 g_free (GDK_GC_WIN32DATA (gc));
478 gdk_win32_gc_get_values (GdkGC *gc,
481 GdkGCPrivate *private = (GdkGCPrivate *) gc;
482 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc);
484 values->foreground.pixel = data->foreground;
485 values->background.pixel = data->background;
486 values->font = data->font;
491 values->function = GDK_COPY; break;
493 values->function = GDK_INVERT; break;
495 values->function = GDK_XOR; break;
497 values->function = GDK_CLEAR; break;
499 values->function = GDK_AND; break;
501 values->function = GDK_AND_REVERSE; break;
503 values->function = GDK_AND_INVERT; break;
505 values->function = GDK_NOOP; break;
507 values->function = GDK_OR; break;
509 values->function = GDK_EQUIV; break;
511 values->function = GDK_OR_REVERSE; break;
513 values->function = GDK_COPY_INVERT; break;
515 values->function = GDK_OR_INVERT; break;
517 values->function = GDK_NAND; break;
519 values->function = GDK_SET; break;
522 values->fill = data->fill_style;
524 values->tile = data->tile;
525 values->stipple = data->stipple;
527 /* Also the X11 backend always returns a NULL clip_mask */
528 values->clip_mask = NULL;
530 values->subwindow_mode = data->subwindow_mode;
531 values->ts_x_origin = private->ts_x_origin;
532 values->ts_y_origin = private->ts_y_origin;
533 values->clip_x_origin = private->clip_x_origin;
534 values->clip_y_origin = private->clip_y_origin;
535 values->graphics_exposures = data->graphics_exposures;
536 values->line_width = data->pen_width;
538 if (data->pen_style & PS_SOLID)
539 values->line_style = GDK_LINE_SOLID;
540 else if (data->pen_style & PS_DASH)
541 values->line_style = GDK_LINE_ON_OFF_DASH;
543 values->line_style = GDK_LINE_SOLID;
545 /* PS_ENDCAP_ROUND is zero */
546 if (data->pen_style & PS_ENDCAP_FLAT)
547 values->cap_style = GDK_CAP_BUTT;
548 else if (data->pen_style & PS_ENDCAP_SQUARE)
549 values->cap_style = GDK_CAP_PROJECTING;
551 values->cap_style = GDK_CAP_ROUND;
553 /* PS_JOIN_ROUND is zero */
554 if (data->pen_style & PS_JOIN_MITER)
555 values->join_style = GDK_JOIN_MITER;
556 else if (data->pen_style & PS_JOIN_BEVEL)
557 values->join_style = GDK_JOIN_BEVEL;
559 values->join_style = GDK_JOIN_ROUND;
563 gdk_win32_gc_set_values (GdkGC *gc,
565 GdkGCValuesMask mask)
567 GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_values: "));
568 gdk_win32_gc_values_to_win32values (values, mask, gc);
569 GDK_NOTE (MISC, g_print ("\n"));
573 gdk_win32_gc_set_dashes (GdkGC *gc,
578 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc);
580 data->pen_style &= ~(PS_STYLE_MASK);
581 data->pen_style |= PS_DASH;
584 * Set the extended line style. This could be done by
585 * PS_USERSTYLE and ExtCreatePen; but ONLY on WinNT,
586 * so let's make a guess (based on the implementation
587 * in DIA). On Win9x this does only work for lines
590 * More workarounds for Win9x descibed at:
591 * http://www.codeguru.com/gdi/dashed.shtml
593 if (!IS_WIN_NT (windows_version) && data->pen_width > 1)
595 GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_dashes: not fully supported\n"));
596 data->pen_style |= PS_SOLID;
600 /* data->pen_style = PS_COSMETIC; ??? */
603 if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2))
605 data->pen_style |= PS_DASH;
606 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n",
607 dash_list[0], dash_list[1]));
611 data->pen_style |= PS_DOT;
612 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DOT (%d,%d)\n",
613 dash_list[0], dash_list[1]));
618 data->pen_style |= PS_DASHDOT;
619 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOT (%d,%d,%d,%d)\n",
620 dash_list[0], dash_list[1],
621 dash_list[2], dash_list[3]));
625 data->pen_style |= PS_DASHDOTDOT;
626 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOTDOT (%d,%d,%d,%d,%d,%d)\n",
627 dash_list[0], dash_list[1],
628 dash_list[2], dash_list[3],
629 dash_list[4], dash_list[5]));
633 data->pen_style |= PS_DASH;
634 GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: no guess for %d dashes\n", n));
639 gdk_gc_set_clip_rectangle (GdkGC *gc,
640 GdkRectangle *rectangle)
642 GdkGCWin32Data *data;
644 g_return_if_fail (gc != NULL);
646 data = GDK_GC_WIN32DATA (gc);
648 if (data->clip_region)
649 gdk_region_destroy (data->clip_region);
654 g_print ("gdk_gc_set_clip_rectangle: (%d) %dx%d@+%d+%d\n",
656 rectangle->width, rectangle->height,
657 rectangle->x, rectangle->y));
658 data->clip_region = gdk_region_rectangle (rectangle);
659 data->values_mask |= GDK_GC_CLIP_MASK;
663 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_rectangle: (%d) NULL\n",
665 data->clip_region = NULL;
666 data->values_mask &= ~GDK_GC_CLIP_MASK;
668 data->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
672 gdk_gc_set_clip_region (GdkGC *gc,
675 GdkGCPrivate *private = (GdkGCPrivate *) gc;
676 GdkGCWin32Data *data;
678 g_return_if_fail (gc != NULL);
680 data = GDK_GC_WIN32DATA (gc);
682 if (data->clip_region)
683 gdk_region_destroy (data->clip_region);
687 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: %d %dx%d+%d+%d\n",
689 region->extents.x2 - region->extents.x1,
690 region->extents.y2 - region->extents.y1,
691 region->extents.x1, region->extents.y1));
692 data->clip_region = gdk_region_copy (region);
693 data->values_mask |= GDK_GC_CLIP_MASK;
697 GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: %d NULL\n",
699 data->clip_region = NULL;
700 data->values_mask &= ~GDK_GC_CLIP_MASK;
703 private->clip_x_origin = 0;
704 private->clip_y_origin = 0;
706 data->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
710 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
712 GdkGCWin32Data *dst_data = GDK_GC_WIN32DATA (dst_gc);
713 GdkGCWin32Data *src_data = GDK_GC_WIN32DATA (src_gc);
717 if (dst_data->font != NULL)
718 gdk_font_unref (dst_data->font);
719 if (dst_data->tile != NULL)
720 gdk_drawable_unref (dst_data->tile);
721 if (dst_data->stipple != NULL)
722 gdk_drawable_unref (dst_data->stipple);
723 if (dst_data->clip_region != NULL)
724 gdk_region_destroy (dst_data->clip_region);
726 *dst_data = *src_data;
728 if (dst_data->clip_region != NULL)
729 dst_data->clip_region = gdk_region_copy (dst_data->clip_region);
730 if (dst_data->font != NULL)
731 gdk_font_ref (dst_data->font);
732 if (dst_data->tile != NULL)
733 gdk_drawable_ref (dst_data->tile);
734 if (dst_data->stipple != NULL)
735 gdk_drawable_ref (dst_data->stipple);
738 static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
741 gdk_colormap_color (GdkColormapPrivateWin32 *colormap_private,
747 if (colormap_private == NULL || colormap_private->xcolormap->rc_palette)
748 return PALETTEINDEX (pixel);
751 visual = colormap_private->base.visual;
752 r = (pixel & visual->red_mask) >> visual->red_shift;
753 r = (r * 255) / bitmask[visual->red_prec];
754 g = (pixel & visual->green_mask) >> visual->green_shift;
755 g = (g * 255) / bitmask[visual->green_prec];
756 b = (pixel & visual->blue_mask) >> visual->blue_shift;
757 b = (b * 255) / bitmask[visual->blue_prec];
759 return RGB (r, g, b);
764 predraw_set_foreground (GdkGCPrivate *gc_private,
765 GdkColormapPrivateWin32 *colormap_private,
772 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc_private);
774 if (colormap_private == NULL)
776 /* A 1 bit deep bitmap */
781 PALETTEENTRY palPalEntry[2];
783 static HPALETTE hpal = NULL;
787 /* Create a b&w palette */
788 logpal.palVersion = 0x300;
789 logpal.palNumEntries = 2;
790 logpal.palPalEntry[0].peRed =
791 logpal.palPalEntry[0].peGreen =
792 logpal.palPalEntry[0].peBlue = 0x00;
793 logpal.palPalEntry[0].peFlags = 0x00;
794 logpal.palPalEntry[1].peRed =
795 logpal.palPalEntry[1].peGreen =
796 logpal.palPalEntry[1].peBlue = 0xFF;
797 logpal.palPalEntry[1].peFlags = 0x00;
798 if ((hpal = CreatePalette ((LOGPALETTE *) &logpal)) == NULL)
799 WIN32_GDI_FAILED ("CreatePalette"), *ok = FALSE;
801 SelectPalette (data->xgc, hpal, FALSE);
802 RealizePalette (data->xgc);
803 fg = PALETTEINDEX (data->foreground);
805 else if (colormap_private->xcolormap->rc_palette)
808 if (SelectPalette (data->xgc, colormap_private->xcolormap->palette,
810 WIN32_GDI_FAILED ("SelectPalette"), *ok = FALSE;
811 if (TRUE || colormap_private->xcolormap->stale)
813 if ((k = RealizePalette (data->xgc)) == GDI_ERROR)
814 WIN32_GDI_FAILED ("RealizePalette"), *ok = FALSE;
815 colormap_private->xcolormap->stale = FALSE;
818 g_print ("Selected palette %#x for gc %#x, realized %d colors\n",
819 colormap_private->xcolormap->palette, data->xgc, k);
823 fg = gdk_colormap_color (colormap_private, data->foreground);
825 if (SetTextColor (data->xgc, fg) == CLR_INVALID)
826 WIN32_GDI_FAILED ("SetTextColor"), *ok = FALSE;
828 /* Create and select pen and brush. */
830 logbrush.lbStyle = BS_SOLID;
831 logbrush.lbColor = fg;
833 if (*ok && (hpen = ExtCreatePen (data->pen_style, data->pen_width,
834 &logbrush, 0, NULL)) == NULL)
835 WIN32_GDI_FAILED ("ExtCreatePen");
837 if (SelectObject (data->xgc, hpen) == NULL)
838 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
840 switch (data->fill_style)
842 case GDK_OPAQUE_STIPPLED:
843 if (*ok && (hbr = CreatePatternBrush (GDK_DRAWABLE_XID (data->stipple))) == NULL)
844 WIN32_GDI_FAILED ("CreatePatternBrush"), *ok = FALSE;
846 if (*ok && !SetBrushOrgEx(data->xgc, gc_private->ts_x_origin,
847 gc_private->ts_y_origin, NULL))
848 WIN32_GDI_FAILED ("SetBrushOrgEx"), *ok = FALSE;
853 if (*ok && (hbr = CreateSolidBrush (fg)) == NULL)
854 WIN32_GDI_FAILED ("CreateSolidBrush"), *ok = FALSE;
857 if (*ok && SelectObject (data->xgc, hbr) == NULL)
858 WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE;
862 predraw_set_background (GdkGCWin32Data *data,
863 GdkColormapPrivateWin32 *colormap_private,
866 COLORREF bg = gdk_colormap_color (colormap_private, data->background);
868 if (SetBkColor (data->xgc, bg) == CLR_INVALID)
869 WIN32_GDI_FAILED ("SetBkColor"), *ok = FALSE;
873 gdk_gc_predraw (GdkDrawable *drawable,
874 GdkGCPrivate *gc_private,
875 GdkGCValuesMask usage)
877 GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
878 GdkColormapPrivateWin32 *colormap_private =
879 (GdkColormapPrivateWin32 *) drawable_private->colormap;
880 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc_private);
884 g_assert (data->xgc == NULL);
886 data->hwnd = GDK_DRAWABLE_XID (drawable);
888 if (GDK_DRAWABLE_TYPE (drawable) == GDK_DRAWABLE_PIXMAP)
890 if ((data->xgc = CreateCompatibleDC (NULL)) == NULL)
891 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
893 if (ok && (data->saved_dc = SaveDC (data->xgc)) == 0)
894 WIN32_GDI_FAILED ("SaveDC"), ok = FALSE;
896 if (ok && SelectObject (data->xgc, data->hwnd) == NULL)
897 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
901 if ((data->xgc = GetDC (data->hwnd)) == NULL)
902 WIN32_GDI_FAILED ("GetDC");
904 if (ok && (data->saved_dc = SaveDC (data->xgc)) == 0)
905 WIN32_GDI_FAILED ("SaveDC");
908 if (ok && (usage & GDK_GC_FOREGROUND))
909 predraw_set_foreground (gc_private, colormap_private, &ok);
912 && (usage & GDK_GC_BACKGROUND)
913 && (data->values_mask & GDK_GC_BACKGROUND))
914 predraw_set_background (data, colormap_private, &ok);
916 if (ok && (usage & GDK_GC_FONT))
918 if (SetBkMode (data->xgc, TRANSPARENT) == 0)
919 WIN32_GDI_FAILED ("SetBkMode"), ok = FALSE;
921 if (ok && SetTextAlign (data->xgc, TA_BASELINE) == GDI_ERROR)
922 WIN32_GDI_FAILED ("SetTextAlign"), ok = FALSE;
925 if (ok && (data->values_mask & GDK_GC_FUNCTION))
926 if (SetROP2 (data->xgc, data->rop2) == 0)
927 WIN32_GDI_FAILED ("SetROP2"), ok = FALSE;
929 if (data->values_mask & GDK_GC_CLIP_MASK)
930 g_assert ((data->clip_region != NULL) != (data->hcliprgn != NULL));
933 && (data->values_mask & GDK_GC_CLIP_MASK)
934 && data->clip_region != NULL)
939 GdkRegionBox *boxes = data->clip_region->rects;
941 sizeof (RGNDATAHEADER) + (sizeof (RECT) * data->clip_region->numRects);
944 rgndata = g_malloc (nbytes);
945 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
946 rgndata->rdh.iType = RDH_RECTANGLES;
947 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
948 SetRect (&rgndata->rdh.rcBound,
949 G_MAXSHORT, G_MAXSHORT, G_MINSHORT, G_MINSHORT);
951 for (i = 0; i < data->clip_region->numRects; i++)
953 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
955 rect->left = CLAMP (boxes[i].x1 + gc_private->clip_x_origin,
956 G_MINSHORT, G_MAXSHORT);
957 rect->right = CLAMP (boxes[i].x2 + gc_private->clip_x_origin,
958 G_MINSHORT, G_MAXSHORT);
959 rect->top = CLAMP (boxes[i].y1 + gc_private->clip_y_origin,
960 G_MINSHORT, G_MAXSHORT);
961 rect->bottom = CLAMP (boxes[i].y2 + gc_private->clip_y_origin,
962 G_MINSHORT, G_MAXSHORT);
964 GDK_NOTE (MISC, g_print ("clip rgn box %d: %dx%d@+%d+%d\n",
966 rect->right-rect->left,
967 rect->bottom-rect->top,
968 rect->left, rect->top));
970 if (rect->left < rgndata->rdh.rcBound.left)
971 rgndata->rdh.rcBound.left = rect->left;
972 if (rect->right > rgndata->rdh.rcBound.right)
973 rgndata->rdh.rcBound.right = rect->right;
974 if (rect->top < rgndata->rdh.rcBound.top)
975 rgndata->rdh.rcBound.top = rect->top;
976 if (rect->bottom > rgndata->rdh.rcBound.bottom)
977 rgndata->rdh.rcBound.bottom = rect->bottom;
979 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
980 WIN32_API_FAILED ("ExtCreateRegion"), ok = FALSE;
982 if (ok && SelectClipRgn (data->xgc, hrgn) == ERROR)
983 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
989 && (data->values_mask & GDK_GC_CLIP_MASK)
990 && data->hcliprgn != NULL)
992 if (SelectClipRgn (data->xgc, data->hcliprgn) == ERROR)
993 WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE;
996 if (gdk_debug_flags & GDK_DEBUG_MISC)
1000 EXTLOGPEN extlogpen;
1004 g_print ("gdk_gc_predraw: %d: %#x\n", data, data->xgc);
1005 obj = GetCurrentObject (data->xgc, OBJ_BRUSH);
1006 GetObject (obj, sizeof (LOGBRUSH), &logbrush);
1007 g_print ("brush: style: %s color: %.06x hatch: %#x\n",
1008 (logbrush.lbStyle == BS_HOLLOW ? "HOLLOW" :
1009 (logbrush.lbStyle == BS_PATTERN ? "PATTERN" :
1010 (logbrush.lbStyle == BS_SOLID ? "SOLID" :
1014 obj = GetCurrentObject (data->xgc, OBJ_PEN);
1015 GetObject (obj, sizeof (EXTLOGPEN), &extlogpen);
1016 g_print ("pen: type: %s style: %s endcap: %s join: %s width: %d brush: %s\n",
1017 ((extlogpen.elpPenStyle & PS_TYPE_MASK) ==
1018 PS_GEOMETRIC ? "GEOMETRIC" : "COSMETIC"),
1019 ((extlogpen.elpPenStyle & PS_STYLE_MASK) ==
1021 ((extlogpen.elpPenStyle & PS_STYLE_MASK) ==
1022 PS_SOLID ? "SOLID" : "???")),
1023 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1024 PS_ENDCAP_FLAT ? "FLAT" :
1025 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1026 PS_ENDCAP_ROUND ? "ROUND" :
1027 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1028 PS_ENDCAP_SQUARE ? "ROUND" :
1029 ((extlogpen.elpPenStyle & PS_ENDCAP_MASK) ==
1030 PS_ENDCAP_SQUARE ? "ROUND" : "???")))),
1031 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1032 PS_JOIN_BEVEL ? "BEVEL" :
1033 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1034 PS_JOIN_MITER ? "MITER" :
1035 ((extlogpen.elpPenStyle & PS_JOIN_MASK) ==
1036 PS_JOIN_ROUND ? "ROUND" : "???"))),
1038 (extlogpen.elpBrushStyle == BS_DIBPATTERN ? "DIBPATTERN" :
1039 (extlogpen.elpBrushStyle == BS_DIBPATTERNPT ? "DIBPATTERNPT" :
1040 (extlogpen.elpBrushStyle == BS_HATCHED ? "HATCHED" :
1041 (extlogpen.elpBrushStyle == BS_HOLLOW ? "HOLLOW" :
1042 (extlogpen.elpBrushStyle == BS_PATTERN ? "PATTERN" :
1043 (extlogpen.elpBrushStyle == BS_SOLID ? "SOLID" : "???")))))));
1044 hrgn = CreateRectRgn (0, 0, 0, 0);
1045 if ((flag = GetClipRgn (data->xgc, hrgn)) == -1)
1046 WIN32_API_FAILED ("GetClipRgn");
1048 g_print ("no clip region\n");
1051 GetRgnBox (hrgn, &rect);
1052 g_print ("clip region bbox: %dx%d@+%d+%d\n",
1053 rect.right - rect.left,
1054 rect.bottom - rect.top,
1055 rect.left, rect.top);
1063 gdk_gc_postdraw (GdkDrawable *drawable,
1064 GdkGCPrivate *gc_private,
1065 GdkGCValuesMask usage)
1067 GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
1068 GdkColormapPrivateWin32 *colormap_private =
1069 (GdkColormapPrivateWin32 *) drawable_private->colormap;
1070 GdkGCWin32Data *data = GDK_GC_WIN32DATA (gc_private);
1071 HGDIOBJ hpen = NULL;
1074 if (usage & GDK_GC_FOREGROUND)
1076 if ((hpen = GetCurrentObject (data->xgc, OBJ_PEN)) == NULL)
1077 WIN32_GDI_FAILED ("GetCurrentObject");
1079 if ((hbr = GetCurrentObject (data->xgc, OBJ_BRUSH)) == NULL)
1080 WIN32_GDI_FAILED ("GetCurrentObject");
1083 if (!RestoreDC (data->xgc, data->saved_dc))
1084 WIN32_GDI_FAILED ("RestoreDC");
1086 if (colormap_private != NULL
1087 && colormap_private->xcolormap->rc_palette
1088 && colormap_private->xcolormap->stale)
1090 SelectPalette (data->xgc, GetStockObject (DEFAULT_PALETTE), FALSE);
1091 if (!UnrealizeObject (colormap_private->xcolormap->palette))
1092 WIN32_GDI_FAILED ("UnrealizeObject");
1095 if (GDK_DRAWABLE_TYPE (drawable) == GDK_DRAWABLE_PIXMAP)
1097 if (!DeleteDC (data->xgc))
1098 WIN32_GDI_FAILED ("DeleteDC");
1102 ReleaseDC (data->hwnd, data->xgc);
1106 if (!DeleteObject (hpen))
1107 WIN32_GDI_FAILED ("DeleteObject");
1110 if (!DeleteObject (hbr))
1111 WIN32_GDI_FAILED ("DeleteObject");
1116 /* This function originally from Jean-Edouard Lachand-Robert, and
1117 * available at www.codeguru.com. Simplified for our needs, now
1118 * handles just one-bit deep bitmaps (in Window parlance, ie those
1119 * that GDK calls bitmaps (and not pixmaps), with zero pixels being
1124 * BitmapToRegion : Create a region from the "non-transparent" pixels of
1126 * Author : Jean-Edouard Lachand-Robert
1127 * (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
1131 BitmapToRegion (HBITMAP hBmp)
1139 BITMAPINFOHEADER bmiHeader;
1143 RGBQUAD bmiColors[2];
1152 PALETTEENTRY palPalEntry[2];
1154 static HPALETTE bwPalette = NULL;
1167 /* Create a B&W palette */
1168 if (bwPalette == NULL)
1170 /* Create a b&w palette */
1171 logpal.palVersion = 0x300;
1172 logpal.palNumEntries = 2;
1173 logpal.palPalEntry[0].peRed =
1174 logpal.palPalEntry[0].peGreen =
1175 logpal.palPalEntry[0].peBlue = 0;
1176 logpal.palPalEntry[0].peFlags = 0;
1177 logpal.palPalEntry[1].peRed =
1178 logpal.palPalEntry[1].peGreen =
1179 logpal.palPalEntry[1].peBlue = 0xFF;
1180 logpal.palPalEntry[1].peFlags = 0;
1181 if ((bwPalette = CreatePalette ((LOGPALETTE *) &logpal)) == NULL)
1182 WIN32_GDI_FAILED ("CreatePalette");
1185 /* Create a memory DC inside which we will scan the bitmap content */
1186 hMemDC = CreateCompatibleDC (NULL);
1189 WIN32_GDI_FAILED ("CreateCompatibleDC");
1193 SelectPalette (hMemDC, bwPalette, FALSE);
1194 RealizePalette (hMemDC);
1196 /* Get bitmap size */
1197 GetObject(hBmp, sizeof(bm), &bm);
1199 /* Create a 8 bits depth bitmap and select it into the memory DC */
1200 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
1201 bmi.bmiHeader.biWidth = bm.bmWidth;
1202 bmi.bmiHeader.biHeight = bm.bmHeight;
1203 bmi.bmiHeader.biPlanes = 1;
1204 bmi.bmiHeader.biBitCount = 8;
1205 bmi.bmiHeader.biCompression = BI_RGB;
1206 bmi.bmiHeader.biSizeImage = 0;
1207 bmi.bmiHeader.biXPelsPerMeter = 0;
1208 bmi.bmiHeader.biYPelsPerMeter = 0;
1209 bmi.bmiHeader.biClrUsed = 2;
1210 bmi.bmiHeader.biClrImportant = 2;
1212 bmi.bmiColors[0] = 0;
1213 bmi.bmiColors[1] = 1;
1214 hbm8 = CreateDIBSection (hMemDC, (BITMAPINFO *)&bmi,
1215 DIB_PAL_COLORS, &pbits8, NULL, 0);
1217 bmi.bmiColors[0].rgbBlue =
1218 bmi.bmiColors[0].rgbGreen =
1219 bmi.bmiColors[0].rgbRed = 0x00;
1220 bmi.bmiColors[0].rgbReserved = 0x00;
1222 bmi.bmiColors[1].rgbBlue =
1223 bmi.bmiColors[1].rgbGreen =
1224 bmi.bmiColors[1].rgbRed = 0xFF;
1225 bmi.bmiColors[0].rgbReserved = 0x00;
1227 hbm8 = CreateDIBSection (hMemDC, (BITMAPINFO *)&bmi,
1228 DIB_RGB_COLORS, &pbits8, NULL, 0);
1232 WIN32_GDI_FAILED ("CreateDIBSection");
1237 holdBmp = (HBITMAP) SelectObject (hMemDC, hbm8);
1239 /* Create a DC just to copy the bitmap into the memory DC*/
1240 hDC = CreateCompatibleDC (hMemDC);
1243 WIN32_GDI_FAILED ("CreateCompatibleDC");
1244 SelectObject (hMemDC, holdBmp);
1245 DeleteObject (hbm8);
1250 /* Get how many bytes per row we have for the bitmap bits */
1251 GetObject (hbm8, sizeof (bm8), &bm8);
1253 /* Hans Breuer found a fix to the long-standing erroneous behaviour
1254 * on NT 4.0: There seems to be a bug in Win NT 4.0 GDI: scanlines
1255 * in bitmaps are dword aligned on both Win95 and NT. In the case of
1256 * a bitmap with 22 bytes worth of width, GetObject above returns
1257 * with bmWidth == 22. On Win95 bmWidthBytes == 24, as it should be,
1258 * but on NT is it 22. We need to correct this here.
1260 bm8.bmWidthBytes = (((bm8.bmWidthBytes-1)/4)+1)*4; /* dword aligned!! */
1262 /* Copy the bitmap into the memory DC*/
1263 holdBmp2 = (HBITMAP) SelectObject (hDC, hBmp);
1265 if (!BitBlt (hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY))
1267 WIN32_GDI_FAILED ("BitBlt");
1268 SelectObject (hDC, holdBmp2);
1269 SelectObject (hMemDC, holdBmp);
1270 DeleteObject (hbm8);
1274 SelectObject (hDC, holdBmp2);
1277 /* For better performances, we will use the ExtCreateRegion()
1278 * function to create the region. This function take a RGNDATA
1279 * structure on entry. We will add rectangles by amount of
1280 * ALLOC_UNIT number in this structure.
1282 #define ALLOC_UNIT 100
1283 maxRects = ALLOC_UNIT;
1285 pData = g_malloc (sizeof (RGNDATAHEADER) + (sizeof (RECT) * maxRects));
1286 pData->rdh.dwSize = sizeof (RGNDATAHEADER);
1287 pData->rdh.iType = RDH_RECTANGLES;
1288 pData->rdh.nCount = pData->rdh.nRgnSize = 0;
1289 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1291 /* Scan each bitmap from bottom to top (the bitmap is inverted vertically)*/
1292 p8 = (BYTE *) pbits8 + (bm8.bmHeight - 1) * bm8.bmWidthBytes;
1293 for (y = 0; y < bm.bmHeight; y++)
1295 /* Scan each bitmap row from left to right*/
1296 for (x = 0; x < bm.bmWidth; x++)
1298 /* Search for a continuous range of "non transparent pixels"*/
1301 while (x < bm.bmWidth)
1304 /* This pixel is "transparent"*/
1313 /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
1316 if (pData->rdh.nCount >= maxRects)
1318 maxRects += ALLOC_UNIT;
1319 pData = g_realloc (pData, sizeof(RGNDATAHEADER)
1320 + (sizeof(RECT) * maxRects));
1322 pr = (RECT *) &pData->Buffer;
1323 SetRect (&pr[pData->rdh.nCount], x0, y, x, y+1);
1324 if (x0 < pData->rdh.rcBound.left)
1325 pData->rdh.rcBound.left = x0;
1326 if (y < pData->rdh.rcBound.top)
1327 pData->rdh.rcBound.top = y;
1328 if (x > pData->rdh.rcBound.right)
1329 pData->rdh.rcBound.right = x;
1330 if (y+1 > pData->rdh.rcBound.bottom)
1331 pData->rdh.rcBound.bottom = y+1;
1332 pData->rdh.nCount++;
1334 /* On Windows98, ExtCreateRegion() may fail if the
1335 * number of rectangles is too large (ie: >
1336 * 4000). Therefore, we have to create the region by
1339 if (pData->rdh.nCount == 2000)
1341 HRGN h = ExtCreateRegion (NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
1344 CombineRgn(hRgn, hRgn, h, RGN_OR);
1349 pData->rdh.nCount = 0;
1350 SetRect (&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
1355 /* Go to next row (remember, the bitmap is inverted vertically)*/
1356 p8 -= bm8.bmWidthBytes;
1359 /* Create or extend the region with the remaining rectangles*/
1360 h = ExtCreateRegion (NULL, sizeof (RGNDATAHEADER)
1361 + (sizeof (RECT) * maxRects), pData);
1364 CombineRgn (hRgn, hRgn, h, RGN_OR);
1371 SelectObject(hMemDC, holdBmp);
1372 DeleteObject (hbm8);