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/.
33 #include <pango/pangowin32.h>
35 #include "gdkscreen.h" /* gdk_screen_get_default() */
36 #include "gdkregion-generic.h"
37 #include "gdkprivate-win32.h"
39 #define ROP3_D 0x00AA0029
40 #define ROP3_DSna 0x00220326
41 #define ROP3_DSPDxax 0x00E20746
43 #define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
44 GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)
46 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
53 static void gdk_win32_draw_arc (GdkDrawable *drawable,
62 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
67 static void gdk_win32_draw_text (GdkDrawable *drawable,
74 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
81 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
90 static void gdk_win32_draw_points (GdkDrawable *drawable,
94 static void gdk_win32_draw_segments (GdkDrawable *drawable,
98 static void gdk_win32_draw_lines (GdkDrawable *drawable,
102 static void gdk_win32_draw_glyphs (GdkDrawable *drawable,
107 PangoGlyphString *glyphs);
108 static void gdk_win32_draw_image (GdkDrawable *drawable,
118 static void gdk_win32_set_colormap (GdkDrawable *drawable,
119 GdkColormap *colormap);
121 static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable);
123 static gint gdk_win32_get_depth (GdkDrawable *drawable);
125 static GdkScreen * gdk_win32_get_screen (GdkDrawable *drawable);
127 static GdkVisual* gdk_win32_get_visual (GdkDrawable *drawable);
129 static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass);
131 static void gdk_drawable_impl_win32_finalize (GObject *object);
133 static gpointer parent_class = NULL;
136 gdk_drawable_impl_win32_get_type (void)
138 static GType object_type = 0;
142 static const GTypeInfo object_info =
144 sizeof (GdkDrawableImplWin32Class),
145 (GBaseInitFunc) NULL,
146 (GBaseFinalizeFunc) NULL,
147 (GClassInitFunc) gdk_drawable_impl_win32_class_init,
148 NULL, /* class_finalize */
149 NULL, /* class_data */
150 sizeof (GdkDrawableImplWin32),
152 (GInstanceInitFunc) NULL,
155 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
156 "GdkDrawableImplWin32",
164 gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass)
166 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
167 GObjectClass *object_class = G_OBJECT_CLASS (klass);
169 parent_class = g_type_class_peek_parent (klass);
171 object_class->finalize = gdk_drawable_impl_win32_finalize;
173 drawable_class->create_gc = _gdk_win32_gc_new;
174 drawable_class->draw_rectangle = gdk_win32_draw_rectangle;
175 drawable_class->draw_arc = gdk_win32_draw_arc;
176 drawable_class->draw_polygon = gdk_win32_draw_polygon;
177 drawable_class->draw_text = gdk_win32_draw_text;
178 drawable_class->draw_text_wc = gdk_win32_draw_text_wc;
179 drawable_class->draw_drawable = gdk_win32_draw_drawable;
180 drawable_class->draw_points = gdk_win32_draw_points;
181 drawable_class->draw_segments = gdk_win32_draw_segments;
182 drawable_class->draw_lines = gdk_win32_draw_lines;
183 drawable_class->draw_glyphs = gdk_win32_draw_glyphs;
184 drawable_class->draw_image = gdk_win32_draw_image;
186 drawable_class->set_colormap = gdk_win32_set_colormap;
187 drawable_class->get_colormap = gdk_win32_get_colormap;
189 drawable_class->get_depth = gdk_win32_get_depth;
190 drawable_class->get_screen = gdk_win32_get_screen;
191 drawable_class->get_visual = gdk_win32_get_visual;
193 drawable_class->_copy_to_image = _gdk_win32_copy_to_image;
197 gdk_drawable_impl_win32_finalize (GObject *object)
199 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
201 G_OBJECT_CLASS (parent_class)->finalize (object);
204 /*****************************************************
205 * Win32 specific implementations of generic functions *
206 *****************************************************/
209 gdk_win32_get_colormap (GdkDrawable *drawable)
211 return GDK_DRAWABLE_IMPL_WIN32 (drawable)->colormap;
215 gdk_win32_set_colormap (GdkDrawable *drawable,
216 GdkColormap *colormap)
218 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
220 if (impl->colormap == colormap)
224 gdk_colormap_unref (impl->colormap);
225 impl->colormap = colormap;
227 gdk_colormap_ref (impl->colormap);
234 * Render a dashed line 'by hand' cause the Win9x GDI is
235 * too limited to do so
237 static inline gboolean
238 render_line_horizontal (HDC hdc,
248 for (n = 0; x1 < x2; n++)
250 int len = dashes[n % num_dashes];
255 if (!GDI_CALL (PatBlt, (hdc, x1, y - pen_width / 2,
260 x1 += dashes[n % num_dashes];
266 static inline gboolean
267 render_line_vertical (HDC hdc,
277 for (n = 0; y1 < y2; n++)
279 int len = dashes[n % num_dashes];
283 if (!GDI_CALL (PatBlt, (hdc, x - pen_width / 2, y1,
288 y1 += dashes[n % num_dashes];
295 draw_tiles_lowlevel (HDC dest,
309 GDK_NOTE (MISC, g_print ("draw_tiles_lowlevel: %p +%d+%d tile=%p:%dx%d@+%d+%d %dx%d\n",
312 tile, tile_width, tile_height,
313 tile_x_origin, tile_y_origin,
316 y = tile_y_origin % tile_height;
319 while (y < dest_y + height)
321 if (y + tile_height >= dest_y)
323 x = tile_x_origin % tile_width;
326 while (x < dest_x + width)
328 if (x + tile_width >= dest_x)
330 gint src_x = MAX (0, dest_x - x);
331 gint src_y = MAX (0, dest_y - y);
333 if (!GDI_CALL (BitBlt, (dest, x + src_x, y + src_y,
334 MIN (tile_width, dest_x + width - (x + src_x)),
335 MIN (tile_height, dest_y + height - (y + src_y)),
349 draw_tiles (GdkDrawable *drawable,
360 const GdkGCValuesMask mask = GDK_GC_FOREGROUND;
361 gint tile_width, tile_height;
363 HDC dest_hdc, tile_hdc;
365 gc_copy = gdk_gc_new (tile);
366 gdk_gc_copy (gc_copy, gc);
367 dest_hdc = gdk_win32_hdc_get (drawable, gc, mask);
368 tile_hdc = gdk_win32_hdc_get (tile, gc_copy, mask);
370 gdk_drawable_get_size (tile, &tile_width, &tile_height);
372 draw_tiles_lowlevel (dest_hdc, tile_hdc, rop3,
373 dest_x, dest_y, tile_x_origin, tile_y_origin,
374 width, height, tile_width, tile_height);
376 gdk_win32_hdc_release (drawable, gc, mask);
377 gdk_win32_hdc_release (tile, gc_copy, mask);
378 gdk_gc_unref (gc_copy);
382 rop2_to_rop3 (int rop2)
386 /* Oh, Microsoft's silly names for binary and ternary rops. */
387 #define CASE(rop2,rop3) case R2_##rop2: return rop3
388 CASE (BLACK, BLACKNESS);
389 CASE (NOTMERGEPEN, NOTSRCERASE);
390 CASE (MASKNOTPEN, 0x00220326);
391 CASE (NOTCOPYPEN, NOTSRCCOPY);
392 CASE (MASKPENNOT, SRCERASE);
393 CASE (NOT, DSTINVERT);
394 CASE (XORPEN, SRCINVERT);
395 CASE (NOTMASKPEN, 0x007700E6);
396 CASE (MASKPEN, SRCAND);
397 CASE (NOTXORPEN, 0x00990066);
398 CASE (NOP, 0x00AA0029);
399 CASE (MERGENOTPEN, MERGEPAINT);
400 CASE (COPYPEN, SRCCOPY);
401 CASE (MERGEPENNOT, 0x00DD0228);
402 CASE (MERGEPEN, SRCPAINT);
403 CASE (WHITE, WHITENESS);
405 default: return SRCCOPY;
410 generic_draw (GdkDrawable *drawable,
412 GdkGCValuesMask mask,
413 void (*function) (GdkGCWin32 *, HDC, gint, gint, va_list),
414 const GdkRegion *region,
417 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
418 GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc);
422 va_start (args, region);
424 /* If tiled or stippled, draw to a temp pixmap and do blitting magic.
427 if (gcwin32->values_mask & GDK_GC_FILL &&
428 ((gcwin32->fill_style == GDK_TILED &&
429 gcwin32->values_mask & GDK_GC_TILE &&
430 gcwin32->tile != NULL)
432 ((gcwin32->fill_style == GDK_OPAQUE_STIPPLED ||
433 gcwin32->fill_style == GDK_STIPPLED) &&
434 gcwin32->values_mask & GDK_GC_STIPPLE &&
435 gcwin32->stipple != NULL)))
437 const GdkGCValuesMask blitting_mask = 0;
438 GdkGCValuesMask drawing_mask = GDK_GC_FOREGROUND;
439 gint ts_x_origin = 0, ts_y_origin = 0;
441 gint width = region->extents.x2 - region->extents.x1;
442 gint height = region->extents.y2 - region->extents.y1;
444 GdkPixmap *mask_pixmap =
445 gdk_pixmap_new (drawable, width, height, 1);
446 GdkPixmap *tile_pixmap =
447 gdk_pixmap_new (drawable, width, height, -1);
448 GdkPixmap *stipple_bitmap = NULL;
451 GdkGC *mask_gc = gdk_gc_new (mask_pixmap);
452 GdkGC *tile_gc = gdk_gc_new (tile_pixmap);
457 HGDIOBJ old_mask_hbm;
458 HGDIOBJ old_tile_hbm;
460 GdkGCValues gcvalues;
462 hdc = gdk_win32_hdc_get (drawable, gc, blitting_mask);
463 tile_hdc = CreateCompatibleDC (hdc);
465 if (gcwin32->values_mask & GDK_GC_TS_X_ORIGIN)
466 ts_x_origin = gc->ts_x_origin;
467 if (gcwin32->values_mask & GDK_GC_TS_Y_ORIGIN)
468 ts_y_origin = gc->ts_y_origin;
470 ts_x_origin -= region->extents.x1;
471 ts_y_origin -= region->extents.y1;
473 /* Fill mask bitmap with zeros */
474 gdk_gc_set_function (mask_gc, GDK_CLEAR);
475 gdk_draw_rectangle (mask_pixmap, mask_gc, TRUE,
476 0, 0, width, height);
478 /* Paint into mask bitmap, drawing ones */
479 gdk_gc_set_function (mask_gc, GDK_COPY);
481 gdk_gc_set_foreground (mask_gc, &fg);
483 /* If the drawing function uses line attributes, set them as in
486 if (mask & LINE_ATTRIBUTES)
488 gdk_gc_get_values (gc, &gcvalues);
489 if (gcvalues.line_width != 0 ||
490 gcvalues.line_style != GDK_LINE_SOLID ||
491 gcvalues.cap_style != GDK_CAP_BUTT ||
492 gcvalues.join_style != GDK_JOIN_MITER)
493 gdk_gc_set_line_attributes (mask_gc,
497 gcvalues.join_style);
498 drawing_mask |= LINE_ATTRIBUTES;
501 /* Ditto, if the drawing function draws text, set up for that. */
502 if (mask & GDK_GC_FONT)
503 drawing_mask |= GDK_GC_FONT;
505 mask_hdc = gdk_win32_hdc_get (mask_pixmap, mask_gc, drawing_mask);
506 (*function) (GDK_GC_WIN32 (mask_gc), mask_hdc,
507 region->extents.x1, region->extents.y1, args);
508 gdk_win32_hdc_release (mask_pixmap, mask_gc, drawing_mask);
510 if (gcwin32->fill_style == GDK_TILED)
512 /* Tile pixmap with tile */
513 draw_tiles (tile_pixmap, tile_gc, SRCCOPY,
515 0, 0, ts_x_origin, ts_y_origin,
520 /* Tile with stipple */
523 stipple_bitmap = gdk_pixmap_new (NULL, width, height, 1);
524 stipple_gc = gdk_gc_new (stipple_bitmap);
526 /* Tile stipple bitmap */
527 draw_tiles (stipple_bitmap, stipple_gc, SRCCOPY,
529 0, 0, ts_x_origin, ts_y_origin,
532 if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
534 /* Fill tile pixmap with background */
535 fg.pixel = gcwin32->background;
536 gdk_gc_set_foreground (tile_gc, &fg);
537 gdk_draw_rectangle (tile_pixmap, tile_gc, TRUE,
538 0, 0, width, height);
540 gdk_gc_unref (stipple_gc);
543 gdk_gc_unref (mask_gc);
544 gdk_gc_unref (tile_gc);
546 mask_hdc = CreateCompatibleDC (hdc);
548 if ((old_mask_hbm = SelectObject (mask_hdc, GDK_PIXMAP_HBITMAP (mask_pixmap))) == NULL)
549 WIN32_GDI_FAILED ("SelectObject");
551 if ((old_tile_hbm = SelectObject (tile_hdc, GDK_PIXMAP_HBITMAP (tile_pixmap))) == NULL)
552 WIN32_GDI_FAILED ("SelectObject");
554 if (gcwin32->fill_style == GDK_STIPPLED ||
555 gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
558 HGDIOBJ old_stipple_hbm;
560 HGDIOBJ old_tile_brush;
562 if ((stipple_hdc = CreateCompatibleDC (hdc)) == NULL)
563 WIN32_GDI_FAILED ("CreateCompatibleDC");
565 if ((old_stipple_hbm =
566 SelectObject (stipple_hdc,
567 GDK_PIXMAP_HBITMAP (stipple_bitmap))) == NULL)
568 WIN32_GDI_FAILED ("SelectObject");
570 if ((fg_brush = CreateSolidBrush
571 (_gdk_win32_colormap_color (impl->colormap,
572 gcwin32->foreground))) == NULL)
573 WIN32_GDI_FAILED ("CreateSolidBrush");
575 if ((old_tile_brush = SelectObject (tile_hdc, fg_brush)) == NULL)
576 WIN32_GDI_FAILED ("SelectObject");
578 /* Paint tile with foreround where stipple is one
580 * Desired ternary ROP: (P=foreground, S=stipple, D=destination)
591 * Reading bottom-up: 11100010 = 0xE2. PSDK docs say this is
592 * known as DSPDxax, with hex value 0x00E20746.
594 GDI_CALL (BitBlt, (tile_hdc, 0, 0, width, height,
595 stipple_hdc, 0, 0, ROP3_DSPDxax));
597 if (gcwin32->fill_style == GDK_STIPPLED)
599 /* Punch holes in mask where stipple is zero */
600 GDI_CALL (BitBlt, (mask_hdc, 0, 0, width, height,
601 stipple_hdc, 0, 0, SRCAND));
604 GDI_CALL (SelectObject, (tile_hdc, old_tile_brush));
605 GDI_CALL (DeleteObject, (fg_brush));
606 GDI_CALL (SelectObject, (stipple_hdc, old_stipple_hbm));
607 GDI_CALL (DeleteDC, (stipple_hdc));
608 g_object_unref (stipple_bitmap);
611 /* Tile pixmap now contains the pattern that we should paint in
612 * the areas where mask is one. (It is filled with said pattern.)
617 GDI_CALL (MaskBlt, (hdc, region->extents.x1, region->extents.y1,
620 GDK_PIXMAP_HBITMAP (mask_pixmap), 0, 0,
621 MAKEROP4 (rop2_to_rop3 (gcwin32->rop2), ROP3_D)));
625 GdkPixmap *temp1_pixmap =
626 gdk_pixmap_new (drawable, width, height, -1);
627 GdkPixmap *temp2_pixmap =
628 gdk_pixmap_new (drawable, width, height, -1);
629 HDC temp1_hdc = CreateCompatibleDC (hdc);
630 HDC temp2_hdc = CreateCompatibleDC (hdc);
631 HGDIOBJ old_temp1_hbm =
632 SelectObject (temp1_hdc, GDK_PIXMAP_HBITMAP (temp1_pixmap));
633 HGDIOBJ old_temp2_hbm =
634 SelectObject (temp2_hdc, GDK_PIXMAP_HBITMAP (temp2_pixmap));
636 /* Grab copy of dest region to temp1 */
637 GDI_CALL (BitBlt,(temp1_hdc, 0, 0, width, height,
638 hdc, region->extents.x1, region->extents.y1, SRCCOPY));
640 /* Paint tile to temp1 using correct function */
641 GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height,
642 tile_hdc, 0, 0, rop2_to_rop3 (gcwin32->rop2)));
644 /* Mask out temp1 where function didn't paint */
645 GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height,
646 mask_hdc, 0, 0, SRCAND));
648 /* Grab another copy of dest region to temp2 */
649 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
650 hdc, region->extents.x1, region->extents.y1, SRCCOPY));
652 /* Mask out temp2 where function did paint */
653 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
654 mask_hdc, 0, 0, ROP3_DSna));
656 /* Combine temp1 with temp2 */
657 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
658 temp1_hdc, 0, 0, SRCPAINT));
661 GDI_CALL (BitBlt, (hdc, region->extents.x1, region->extents.y1, width, height,
662 temp2_hdc, 0, 0, SRCCOPY));
665 GDI_CALL (SelectObject, (temp1_hdc, old_temp1_hbm));
666 GDI_CALL (SelectObject, (temp2_hdc, old_temp2_hbm));
667 GDI_CALL (DeleteDC, (temp1_hdc));
668 GDI_CALL (DeleteDC, (temp2_hdc));
669 g_object_unref (temp1_pixmap);
670 g_object_unref (temp2_pixmap);
674 GDI_CALL (SelectObject, (mask_hdc, old_mask_hbm));
675 GDI_CALL (SelectObject, (tile_hdc, old_tile_hbm));
676 GDI_CALL (DeleteDC, (mask_hdc));
677 GDI_CALL (DeleteDC, (tile_hdc));
678 g_object_unref (mask_pixmap);
679 g_object_unref (tile_pixmap);
681 gdk_win32_hdc_release (drawable, gc, blitting_mask);
685 hdc = gdk_win32_hdc_get (drawable, gc, mask);
686 (*function) (gcwin32, hdc, 0, 0, args);
687 gdk_win32_hdc_release (drawable, gc, mask);
693 widen_bounds (GdkRectangle *bounds,
699 bounds->x -= pen_width;
700 bounds->y -= pen_width;
701 bounds->width += 2 * pen_width;
702 bounds->height += 2 * pen_width;
704 return gdk_region_rectangle (bounds);
708 draw_rectangle (GdkGCWin32 *gcwin32,
714 HGDIOBJ old_pen_or_brush;
721 filled = va_arg (args, gboolean);
722 x = va_arg (args, gint);
723 y = va_arg (args, gint);
724 width = va_arg (args, gint);
725 height = va_arg (args, gint);
730 if (!filled && gcwin32->pen_dashes && !IS_WIN_NT ())
732 render_line_vertical (hdc, x, y, y+height+1,
735 gcwin32->pen_num_dashes) &&
736 render_line_horizontal (hdc, x, x+width+1, y,
739 gcwin32->pen_num_dashes) &&
740 render_line_vertical (hdc, x+width+1, y, y+height+1,
743 gcwin32->pen_num_dashes) &&
744 render_line_horizontal (hdc, x, x+width+1, y+height+1,
747 gcwin32->pen_num_dashes);
752 old_pen_or_brush = SelectObject (hdc, GetStockObject (NULL_PEN));
754 old_pen_or_brush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
755 if (old_pen_or_brush == NULL)
756 WIN32_GDI_FAILED ("SelectObject");
758 GDI_CALL (Rectangle, (hdc, x, y, x+width+1, y+height+1));
760 if (old_pen_or_brush != NULL)
761 GDI_CALL (SelectObject, (hdc, old_pen_or_brush));
766 gdk_win32_draw_rectangle (GdkDrawable *drawable,
777 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@+%d+%d\n",
778 _gdk_win32_drawable_description (drawable),
780 (filled ? "fill " : ""),
781 width, height, x, y));
785 bounds.width = width;
786 bounds.height = height;
787 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
789 generic_draw (drawable, gc,
790 GDK_GC_FOREGROUND | (filled ? 0 : LINE_ATTRIBUTES),
791 draw_rectangle, region, filled, x, y, width, height);
793 gdk_region_destroy (region);
797 draw_arc (GdkGCWin32 *gcwin32,
808 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
810 filled = va_arg (args, gboolean);
811 x = va_arg (args, gint);
812 y = va_arg (args, gint);
813 width = va_arg (args, gint);
814 height = va_arg (args, gint);
815 angle1 = va_arg (args, gint);
816 angle2 = va_arg (args, gint);
821 if (angle2 >= 360*64)
823 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
827 nXStartArc = x + width/2 + width * cos(angle1/64.*2.*G_PI/360.);
828 nYStartArc = y + height/2 + -height * sin(angle1/64.*2.*G_PI/360.);
829 nXEndArc = x + width/2 + width * cos((angle1+angle2)/64.*2.*G_PI/360.);
830 nYEndArc = y + height/2 + -height * sin((angle1+angle2)/64.*2.*G_PI/360.);
834 nXEndArc = x + width/2 + width * cos(angle1/64.*2.*G_PI/360.);
835 nYEndArc = y + height/2 + -height * sin(angle1/64.*2.*G_PI/360.);
836 nXStartArc = x + width/2 + width * cos((angle1+angle2)/64.*2.*G_PI/360.);
837 nYStartArc = y + height/2 + -height * sin((angle1+angle2)/64.*2.*G_PI/360.);
842 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
843 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
844 x, y, x+width, y+height,
845 nXStartArc, nYStartArc,
846 nXEndArc, nYEndArc));
847 GDI_CALL (Pie, (hdc, x, y, x+width, y+height,
848 nXStartArc, nYStartArc, nXEndArc, nYEndArc));
849 GDI_CALL (SelectObject, (hdc, old_pen));
853 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
854 x, y, x+width, y+height,
855 nXStartArc, nYStartArc,
856 nXEndArc, nYEndArc));
857 GDI_CALL (Arc, (hdc, x, y, x+width, y+height,
858 nXStartArc, nYStartArc, nXEndArc, nYEndArc));
863 gdk_win32_draw_arc (GdkDrawable *drawable,
876 GDK_NOTE (MISC, g_print ("gdk_win32_draw_arc: %s %d,%d,%d,%d %d %d\n",
877 _gdk_win32_drawable_description (drawable),
878 x, y, width, height, angle1, angle2));
880 if (width <= 2 || height <= 2 || angle2 == 0)
885 bounds.width = width;
886 bounds.height = height;
887 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
889 generic_draw (drawable, gc,
890 GDK_GC_FOREGROUND | (filled ? 0 : LINE_ATTRIBUTES),
891 draw_arc, region, filled, x, y, width, height, angle1, angle2);
893 gdk_region_destroy (region);
897 draw_polygon (GdkGCWin32 *gcwin32,
909 filled = va_arg (args, gboolean);
910 pts = va_arg (args, POINT *);
911 npoints = va_arg (args, gint);
913 if (x_offset != 0 || y_offset != 0)
914 for (i = 0; i < npoints; i++)
916 pts[i].x -= x_offset;
917 pts[i].y -= y_offset;
922 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
924 WIN32_GDI_FAILED ("SelectObject");
925 GDI_CALL (Polygon, (hdc, pts, npoints));
927 GDI_CALL (SelectObject, (hdc, old_pen));
930 GDI_CALL (Polyline, (hdc, pts, npoints));
934 gdk_win32_draw_polygon (GdkDrawable *drawable,
945 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %s %d points\n",
946 _gdk_win32_drawable_description (drawable),
957 pts = g_new (POINT, npoints+1);
959 for (i = 0; i < npoints; i++)
961 bounds.x = MIN (bounds.x, points[i].x);
962 bounds.y = MIN (bounds.y, points[i].y);
963 pts[i].x = points[i].x;
964 pts[i].y = points[i].y;
967 for (i = 0; i < npoints; i++)
969 bounds.width = MAX (bounds.width, points[i].x - bounds.x);
970 bounds.height = MAX (bounds.height, points[i].y - bounds.y);
973 if (points[0].x != points[npoints-1].x ||
974 points[0].y != points[npoints-1].y)
976 pts[npoints].x = points[0].x;
977 pts[npoints].y = points[0].y;
981 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
983 generic_draw (drawable, gc,
984 GDK_GC_FOREGROUND | (filled ? 0 : LINE_ATTRIBUTES),
985 draw_polygon, region, filled, pts, npoints);
987 gdk_region_destroy (region);
998 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
999 const wchar_t *wcstr,
1005 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
1010 if ((oldfont = SelectObject (argp->hdc, singlefont->hfont)) == NULL)
1012 WIN32_GDI_FAILED ("SelectObject");
1016 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
1017 WIN32_GDI_FAILED ("TextOutW");
1018 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
1021 SelectObject (argp->hdc, oldfont);
1025 gdk_win32_draw_text (GdkDrawable *drawable,
1033 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
1036 gdk_draw_text_arg arg;
1038 if (text_length == 0)
1041 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1045 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
1047 GDK_NOTE (MISC, g_print ("gdk_win32_draw_text: %s (%d,%d) \"%.*s\" (len %d)\n",
1048 _gdk_win32_drawable_description (drawable),
1050 (text_length > 10 ? 10 : text_length),
1051 text, text_length));
1053 if (text_length == 1)
1055 /* For single characters, don't try to interpret as UTF-8. */
1056 wc = (guchar) text[0];
1057 _gdk_wchar_text_handle (font, &wc, 1, gdk_draw_text_handler, &arg);
1061 wcstr = g_utf8_to_utf16 (text, text_length, NULL, &wlen, NULL);
1062 _gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
1066 gdk_win32_hdc_release (drawable, gc, mask);
1070 gdk_win32_draw_text_wc (GdkDrawable *drawable,
1075 const GdkWChar *text,
1078 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
1081 gdk_draw_text_arg arg;
1083 if (text_length == 0)
1086 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1090 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
1092 GDK_NOTE (MISC, g_print ("gdk_win32_draw_text_wc: %s (%d,%d) len: %d\n",
1093 _gdk_win32_drawable_description (drawable),
1094 x, y, text_length));
1096 if (sizeof (wchar_t) != sizeof (GdkWChar))
1098 wcstr = g_new (wchar_t, text_length);
1099 for (i = 0; i < text_length; i++)
1103 wcstr = (wchar_t *) text;
1105 _gdk_wchar_text_handle (font, wcstr, text_length,
1106 gdk_draw_text_handler, &arg);
1108 if (sizeof (wchar_t) != sizeof (GdkWChar))
1111 gdk_win32_hdc_release (drawable, gc, mask);
1115 gdk_win32_draw_drawable (GdkDrawable *drawable,
1125 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1127 _gdk_win32_blit (FALSE, (GdkDrawableImplWin32 *) drawable,
1128 gc, src, xsrc, ysrc,
1129 xdest, ydest, width, height);
1133 gdk_win32_draw_points (GdkDrawable *drawable,
1142 hdc = gdk_win32_hdc_get (drawable, gc, GDK_GC_FOREGROUND);
1144 GDK_NOTE (MISC, g_print ("gdk_win32_draw_points: %s %d points\n",
1145 _gdk_win32_drawable_description (drawable),
1148 /* The X11 version uses XDrawPoint(), which doesn't use the fill
1149 * mode, so don't use generic_draw. But we should use the current
1150 * function, so we can't use SetPixel(). Draw single-pixel
1151 * rectangles (sigh).
1154 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
1155 for (i = 0; i < npoints; i++)
1156 Rectangle (hdc, points[i].x, points[i].y,
1157 points[i].x + 2, points[i].y + 2);
1159 SelectObject (hdc, old_pen);
1160 gdk_win32_hdc_release (drawable, gc, GDK_GC_FOREGROUND);
1164 draw_segments (GdkGCWin32 *gcwin32,
1174 segs = va_arg (args, GdkSegment *);
1175 nsegs = va_arg (args, gint);
1177 if (x_offset != 0 || y_offset != 0)
1179 /* must not modify in place, but could splice in the offset all below */
1180 segs = g_memdup (segs, nsegs * sizeof (GdkSegment));
1181 for (i = 0; i < nsegs; i++)
1183 segs[i].x1 -= x_offset;
1184 segs[i].y1 -= y_offset;
1185 segs[i].x2 -= x_offset;
1186 segs[i].y2 -= y_offset;
1190 if (gcwin32->pen_dashes && !IS_WIN_NT ())
1192 for (i = 0; i < nsegs; i++)
1194 if (segs[i].x1 == segs[i].x2)
1198 if (segs[i].y1 <= segs[i].y2)
1199 y1 = segs[i].y1, y2 = segs[i].y2;
1201 y1 = segs[i].y2, y2 = segs[i].y1;
1203 render_line_vertical (hdc,
1206 gcwin32->pen_dashes,
1207 gcwin32->pen_num_dashes);
1209 else if (segs[i].y1 == segs[i].y2)
1213 if (segs[i].x1 <= segs[i].x2)
1214 x1 = segs[i].x1, x2 = segs[i].x2;
1216 x1 = segs[i].x2, x2 = segs[i].x1;
1218 render_line_horizontal (hdc,
1221 gcwin32->pen_dashes,
1222 gcwin32->pen_num_dashes);
1225 GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
1226 GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
1232 for (i = 0; i < nsegs; i++)
1233 GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
1234 GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
1236 /* not drawing the end pixel does produce a crippled mask, look
1237 * e.g. at xpm icons produced with gdk_pixbuf_new_from_xpm_data trough
1238 * gdk_pixbuf_render_threshold_alpha (testgtk folder icon or
1239 * Dia's toolbox icons) but only on win9x ... --hb
1241 * Update : see bug #81895 and bug #126710 why this is finally
1242 * needed on any win32 platform ;-)
1244 if (gcwin32->pen_width <= 1)
1246 GdkSegment *ps = &segs[nsegs-1];
1249 if (ps->y2 == ps->y1 && ps->x2 == ps->x1)
1250 xc = 1; /* just a point */
1251 else if (ps->y2 == ps->y1)
1252 xc = (ps->x1 < ps->x2) ? 1 : -1; /* advance x only */
1253 else if (ps->x2 == ps->x1)
1254 yc = (ps->y1 < ps->y2) ? 1 : -1; /* advance y only */
1257 xc = (ps->x1 < ps->x2) ? 1 : -1;
1258 yc = (ps->y1 < ps->y2) ? 1 : -1;
1261 GDI_CALL (LineTo, (hdc, ps->x2 + xc, ps->y2 + yc));
1264 if (x_offset != 0 || y_offset != 0)
1269 gdk_win32_draw_segments (GdkDrawable *drawable,
1274 GdkRectangle bounds;
1278 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %s %d segs\n",
1279 _gdk_win32_drawable_description (drawable),
1282 bounds.x = G_MAXINT;
1283 bounds.y = G_MAXINT;
1287 for (i = 0; i < nsegs; i++)
1289 bounds.x = MIN (bounds.x, segs[i].x1);
1290 bounds.x = MIN (bounds.x, segs[i].x2);
1291 bounds.y = MIN (bounds.y, segs[i].y1);
1292 bounds.y = MIN (bounds.y, segs[i].y2);
1295 for (i = 0; i < nsegs; i++)
1297 bounds.width = MAX (bounds.width, segs[i].x1 - bounds.x);
1298 bounds.width = MAX (bounds.width, segs[i].x2 - bounds.x);
1299 bounds.height = MAX (bounds.height, segs[i].y1 - bounds.y);
1300 bounds.height = MAX (bounds.height, segs[i].y2 - bounds.y);
1303 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1305 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1306 draw_segments, region, segs, nsegs);
1308 gdk_region_destroy (region);
1312 draw_lines (GdkGCWin32 *gcwin32,
1322 pts = va_arg (args, POINT *);
1323 npoints = va_arg (args, gint);
1325 if (x_offset != 0 || y_offset != 0)
1326 for (i = 0; i < npoints; i++)
1328 pts[i].x -= x_offset;
1329 pts[i].y -= y_offset;
1332 if (gcwin32->pen_dashes && !IS_WIN_NT ())
1334 for (i = 0; i < npoints - 1; i++)
1336 if (pts[i].x == pts[i+1].x)
1339 if (pts[i].y > pts[i+1].y)
1340 y1 = pts[i+1].y, y2 = pts[i].y;
1342 y1 = pts[i].y, y2 = pts[i+1].y;
1344 render_line_vertical (hdc, pts[i].x, y1, y2,
1346 gcwin32->pen_dashes,
1347 gcwin32->pen_num_dashes);
1349 else if (pts[i].y == pts[i+1].y)
1352 if (pts[i].x > pts[i+1].x)
1353 x1 = pts[i+1].x, x2 = pts[i].x;
1355 x1 = pts[i].x, x2 = pts[i+1].x;
1357 render_line_horizontal (hdc, x1, x2, pts[i].y,
1359 gcwin32->pen_dashes,
1360 gcwin32->pen_num_dashes);
1363 GDI_CALL (MoveToEx, (hdc, pts[i].x, pts[i].y, NULL)) &&
1364 GDI_CALL (LineTo, (hdc, pts[i+1].x, pts[i+1].y));
1368 GDI_CALL (Polyline, (hdc, pts, npoints));
1372 gdk_win32_draw_lines (GdkDrawable *drawable,
1377 GdkRectangle bounds;
1382 GDK_NOTE (MISC, g_print ("gdk_win32_draw_lines: %s %d points\n",
1383 _gdk_win32_drawable_description (drawable),
1389 bounds.x = G_MAXINT;
1390 bounds.y = G_MAXINT;
1394 pts = g_new (POINT, npoints);
1396 for (i = 0; i < npoints; i++)
1398 bounds.x = MIN (bounds.x, points[i].x);
1399 bounds.y = MIN (bounds.y, points[i].y);
1400 pts[i].x = points[i].x;
1401 pts[i].y = points[i].y;
1404 for (i = 0; i < npoints; i++)
1406 bounds.width = MAX (bounds.width, points[i].x - bounds.x);
1407 bounds.height = MAX (bounds.height, points[i].y - bounds.y);
1410 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1412 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1413 draw_lines, region, pts, npoints);
1415 gdk_region_destroy (region);
1420 draw_glyphs (GdkGCWin32 *gcwin32,
1429 PangoGlyphString *glyphs;
1431 font = va_arg (args, PangoFont *);
1432 x = va_arg (args, gint);
1433 y = va_arg (args, gint);
1434 glyphs = va_arg (args, PangoGlyphString *);
1439 pango_win32_render (hdc, font, glyphs, x, y);
1443 gdk_win32_draw_glyphs (GdkDrawable *drawable,
1448 PangoGlyphString *glyphs)
1450 GdkRectangle bounds;
1452 PangoRectangle ink_rect;
1454 pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
1456 bounds.x = x + PANGO_PIXELS (ink_rect.x) - 1;
1457 bounds.y = y + PANGO_PIXELS (ink_rect.y) - 1;
1458 bounds.width = PANGO_PIXELS (ink_rect.width) + 2;
1459 bounds.height = PANGO_PIXELS (ink_rect.height) + 2;
1460 region = gdk_region_rectangle (&bounds);
1462 generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
1463 draw_glyphs, region, font, x, y, glyphs);
1465 gdk_region_destroy (region);
1469 blit_from_pixmap (gboolean use_fg_bg,
1470 GdkDrawableImplWin32 *dest,
1472 GdkPixmapImplWin32 *src,
1473 GdkGCWin32 *gcwin32,
1483 RGBQUAD oldtable[256], newtable[256];
1486 gint newtable_size = 0, oldtable_size = 0;
1489 GDK_NOTE (MISC, g_print ("blit_from_pixmap\n"));
1491 if (!(srcdc = CreateCompatibleDC (NULL)))
1493 WIN32_GDI_FAILED ("CreateCompatibleDC");
1497 if (!(holdbitmap = SelectObject (srcdc, ((GdkDrawableImplWin32 *) src)->handle)))
1498 WIN32_GDI_FAILED ("SelectObject");
1501 if (GDK_PIXMAP_OBJECT (src->parent_instance.wrapper)->depth <= 8)
1503 /* Blitting from a 1, 4 or 8-bit pixmap */
1505 if ((oldtable_size = GetDIBColorTable (srcdc, 0, 256, oldtable)) == 0)
1506 WIN32_GDI_FAILED ("GetDIBColorTable");
1507 else if (GDK_PIXMAP_OBJECT (src->parent_instance.wrapper)->depth == 1)
1509 /* Blitting from an 1-bit pixmap */
1515 bgix = gcwin32->background;
1516 fgix = gcwin32->foreground;
1524 if (GDK_IS_PIXMAP_IMPL_WIN32 (dest) &&
1525 GDK_PIXMAP_OBJECT (dest->wrapper)->depth <= 8)
1527 /* Destination is also pixmap, get fg and bg from
1528 * its palette. Either use the foreground and
1529 * background pixel values in the GC (only in the
1530 * case of gdk_image_put(), cf. XPutImage()), or 0
1531 * and 1 to index the palette.
1533 if (!GDI_CALL (GetDIBColorTable, (hdc, bgix, 1, newtable)) ||
1534 !GDI_CALL (GetDIBColorTable, (hdc, fgix, 1, newtable+1)))
1539 /* Destination is a window, get fg and bg from its
1543 bg = _gdk_win32_colormap_color (dest->colormap, bgix);
1544 fg = _gdk_win32_colormap_color (dest->colormap, fgix);
1545 newtable[0].rgbBlue = GetBValue (bg);
1546 newtable[0].rgbGreen = GetGValue (bg);
1547 newtable[0].rgbRed = GetRValue (bg);
1548 newtable[0].rgbReserved = 0;
1549 newtable[1].rgbBlue = GetBValue (fg);
1550 newtable[1].rgbGreen = GetGValue (fg);
1551 newtable[1].rgbRed = GetRValue (fg);
1552 newtable[1].rgbReserved = 0;
1555 GDK_NOTE (MISC, g_print ("bg: %02x %02x %02x "
1556 "fg: %02x %02x %02x\n",
1558 newtable[0].rgbGreen,
1559 newtable[0].rgbBlue,
1561 newtable[1].rgbGreen,
1562 newtable[1].rgbBlue));
1565 else if (GDK_IS_PIXMAP_IMPL_WIN32 (dest))
1567 /* Destination is pixmap, get its color table */
1569 if ((newtable_size = GetDIBColorTable (hdc, 0, 256, newtable)) == 0)
1570 WIN32_GDI_FAILED ("GetDIBColorTable"), ok = FALSE;
1573 /* If blitting between pixmaps, set source's color table */
1574 if (ok && newtable_size > 0)
1576 GDK_NOTE (MISC_OR_COLORMAP,
1577 g_print ("blit_from_pixmap: set color table"
1578 " hdc=%p count=%d\n",
1579 srcdc, newtable_size));
1580 if (!GDI_CALL (SetDIBColorTable, (srcdc, 0, newtable_size, newtable)))
1586 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1587 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1589 /* Restore source's color table if necessary */
1590 if (ok && newtable_size > 0 && oldtable_size > 0)
1592 GDK_NOTE (MISC_OR_COLORMAP,
1593 g_print ("blit_from_pixmap: reset color table"
1594 " hdc=%p count=%d\n",
1595 srcdc, oldtable_size));
1596 GDI_CALL (SetDIBColorTable, (srcdc, 0, oldtable_size, oldtable));
1599 GDI_CALL (SelectObject, (srcdc, holdbitmap));
1601 GDI_CALL (DeleteDC, (srcdc));
1605 blit_inside_window (HDC hdc,
1606 GdkGCWin32 *gcwin32,
1615 GDK_NOTE (MISC, g_print ("blit_inside_window\n"));
1617 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1618 hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1622 blit_from_window (HDC hdc,
1623 GdkGCWin32 *gcwin32,
1624 GdkDrawableImplWin32 *src,
1633 HPALETTE holdpal = NULL;
1634 GdkColormap *cmap = gdk_colormap_get_system ();
1636 GDK_NOTE (MISC, g_print ("blit_from_window\n"));
1638 if ((srcdc = GetDC (src->handle)) == NULL)
1640 WIN32_GDI_FAILED ("GetDC");
1644 if (cmap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
1645 cmap->visual->type == GDK_VISUAL_STATIC_COLOR)
1649 if (!(holdpal = SelectPalette (srcdc, GDK_WIN32_COLORMAP_DATA (cmap)->hpal, FALSE)))
1650 WIN32_GDI_FAILED ("SelectPalette");
1651 else if ((k = RealizePalette (srcdc)) == GDI_ERROR)
1652 WIN32_GDI_FAILED ("RealizePalette");
1654 GDK_NOTE (MISC_OR_COLORMAP,
1655 g_print ("blit_from_window: realized %d\n", k));
1658 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1659 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1661 if (holdpal != NULL)
1662 GDI_CALL (SelectPalette, (srcdc, holdpal, FALSE));
1664 GDI_CALL (ReleaseDC, (src->handle, srcdc));
1668 _gdk_win32_blit (gboolean use_fg_bg,
1669 GdkDrawableImplWin32 *drawable,
1680 HRGN src_rgn, draw_rgn, outside_rgn;
1682 GdkDrawableImplWin32 *draw_impl;
1683 GdkDrawableImplWin32 *src_impl = NULL;
1684 gint src_width, src_height;
1686 GDK_NOTE (MISC, g_print ("_gdk_win32_blit: src:%s %dx%d@+%d+%d\n"
1687 " dst:%s @+%d+%d use_fg_bg=%d\n",
1688 _gdk_win32_drawable_description (src),
1689 width, height, xsrc, ysrc,
1690 _gdk_win32_drawable_description ((GdkDrawable *) drawable),
1694 draw_impl = (GdkDrawableImplWin32 *) drawable;
1696 if (GDK_IS_DRAWABLE_IMPL_WIN32 (src))
1697 src_impl = (GdkDrawableImplWin32 *) src;
1698 else if (GDK_IS_WINDOW (src))
1699 src_impl = (GdkDrawableImplWin32 *) GDK_WINDOW_OBJECT (src)->impl;
1700 else if (GDK_IS_PIXMAP (src))
1701 src_impl = (GdkDrawableImplWin32 *) GDK_PIXMAP_OBJECT (src)->impl;
1703 g_assert_not_reached ();
1705 hdc = gdk_win32_hdc_get ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1707 gdk_drawable_get_size (src, &src_width, &src_height);
1709 if ((src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1)) == NULL)
1710 WIN32_GDI_FAILED ("CreateRectRgn");
1711 else if ((draw_rgn = CreateRectRgn (xsrc, ysrc,
1713 ysrc + height + 1)) == NULL)
1714 WIN32_GDI_FAILED ("CreateRectRgn");
1717 if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
1721 /* If we are drawing on a window, calculate the region that is
1722 * outside the source pixmap, and invalidate that, causing it to
1723 * be cleared. Not completely sure whether this is always needed. XXX
1726 outside_rgn = CreateRectRgnIndirect (&r);
1728 if ((comb = CombineRgn (outside_rgn,
1730 RGN_DIFF)) == ERROR)
1731 WIN32_GDI_FAILED ("CombineRgn");
1732 else if (comb != NULLREGION)
1734 OffsetRgn (outside_rgn, xdest, ydest);
1735 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
1736 g_print ("...calling InvalidateRgn, "
1737 "bbox: %ldx%ld@+%ld+%ld\n",
1738 r.right - r.left - 1, r.bottom - r.top - 1,
1740 InvalidateRgn (draw_impl->handle, outside_rgn, TRUE);
1742 GDI_CALL (DeleteObject, (outside_rgn));
1745 #if 1 /* Don't know if this is necessary XXX */
1746 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
1747 g_warning ("gdk_win32_blit: CombineRgn returned a COMPLEXREGION");
1749 GetRgnBox (draw_rgn, &r);
1750 if (r.left != xsrc || r.top != ysrc ||
1751 r.right != xsrc + width + 1 || r.bottom != ysrc + height + 1)
1753 xdest += r.left - xsrc;
1755 ydest += r.top - ysrc;
1757 width = r.right - xsrc - 1;
1758 height = r.bottom - ysrc - 1;
1760 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
1762 width, height, xsrc, ysrc,
1767 GDI_CALL (DeleteObject, (src_rgn));
1768 GDI_CALL (DeleteObject, (draw_rgn));
1771 if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
1772 blit_from_pixmap (use_fg_bg, draw_impl, hdc,
1773 (GdkPixmapImplWin32 *) src_impl, GDK_GC_WIN32 (gc),
1774 xsrc, ysrc, xdest, ydest, width, height);
1775 else if (draw_impl->handle == src_impl->handle)
1776 blit_inside_window (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
1778 blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
1779 gdk_win32_hdc_release ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1783 gdk_win32_draw_image (GdkDrawable *drawable,
1793 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1795 _gdk_win32_blit (TRUE, (GdkDrawableImplWin32 *) drawable,
1796 gc, (GdkPixmap *) image->windowing_data,
1797 xsrc, ysrc, xdest, ydest, width, height);
1801 gdk_win32_get_depth (GdkDrawable *drawable)
1803 /* This is a bit bogus but I'm not sure the other way is better */
1805 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1809 gdk_win32_get_screen (GdkDrawable *drawable)
1811 return gdk_screen_get_default ();
1815 gdk_win32_get_visual (GdkDrawable *drawable)
1817 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1821 gdk_win32_drawable_get_handle (GdkDrawable *drawable)
1823 return GDK_DRAWABLE_HANDLE (drawable);
1827 gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,