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_new (wchar_t, text_length);
1062 if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
1063 g_warning ("gdk_win32_draw_text: _gdk_utf8_to_ucs2 failed");
1065 _gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
1070 gdk_win32_hdc_release (drawable, gc, mask);
1074 gdk_win32_draw_text_wc (GdkDrawable *drawable,
1079 const GdkWChar *text,
1082 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
1085 gdk_draw_text_arg arg;
1087 if (text_length == 0)
1090 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1094 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
1096 GDK_NOTE (MISC, g_print ("gdk_win32_draw_text_wc: %s (%d,%d) len: %d\n",
1097 _gdk_win32_drawable_description (drawable),
1098 x, y, text_length));
1100 if (sizeof (wchar_t) != sizeof (GdkWChar))
1102 wcstr = g_new (wchar_t, text_length);
1103 for (i = 0; i < text_length; i++)
1107 wcstr = (wchar_t *) text;
1109 _gdk_wchar_text_handle (font, wcstr, text_length,
1110 gdk_draw_text_handler, &arg);
1112 if (sizeof (wchar_t) != sizeof (GdkWChar))
1115 gdk_win32_hdc_release (drawable, gc, mask);
1119 gdk_win32_draw_drawable (GdkDrawable *drawable,
1129 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1131 _gdk_win32_blit (FALSE, (GdkDrawableImplWin32 *) drawable,
1132 gc, src, xsrc, ysrc,
1133 xdest, ydest, width, height);
1137 gdk_win32_draw_points (GdkDrawable *drawable,
1146 hdc = gdk_win32_hdc_get (drawable, gc, GDK_GC_FOREGROUND);
1148 GDK_NOTE (MISC, g_print ("gdk_win32_draw_points: %s %d points\n",
1149 _gdk_win32_drawable_description (drawable),
1152 /* The X11 version uses XDrawPoint(), which doesn't use the fill
1153 * mode, so don't use generic_draw. But we should use the current
1154 * function, so we can't use SetPixel(). Draw single-pixel
1155 * rectangles (sigh).
1158 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
1159 for (i = 0; i < npoints; i++)
1160 Rectangle (hdc, points[i].x, points[i].y,
1161 points[i].x + 2, points[i].y + 2);
1163 SelectObject (hdc, old_pen);
1164 gdk_win32_hdc_release (drawable, gc, GDK_GC_FOREGROUND);
1168 draw_segments (GdkGCWin32 *gcwin32,
1178 segs = va_arg (args, GdkSegment *);
1179 nsegs = va_arg (args, gint);
1181 if (x_offset != 0 || y_offset != 0)
1182 for (i = 0; i < nsegs; i++)
1184 segs[i].x1 -= x_offset;
1185 segs[i].y1 -= y_offset;
1186 segs[i].x2 -= x_offset;
1187 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 if (gcwin32->pen_width <= 1 && !IS_WIN_NT())
1243 GdkSegment *ps = &segs[nsegs-1];
1244 int xc = (ps->y2 == ps->y1) ? 0 : ((ps->x1 < ps->x2) ? 1 : -1);
1245 int yc = (ps->x2 == ps->x1) ? 0 : ((ps->y1 < ps->y2) ? 1 : -1);
1246 /* don't forget single point lines */
1247 xc = (0 == xc && 0 == yc) ? 1 : xc;
1249 GDI_CALL (LineTo, (hdc, ps->x2 + xc, ps->y2 + yc));
1255 gdk_win32_draw_segments (GdkDrawable *drawable,
1260 GdkRectangle bounds;
1264 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %s %d segs\n",
1265 _gdk_win32_drawable_description (drawable),
1268 bounds.x = G_MAXINT;
1269 bounds.y = G_MAXINT;
1273 for (i = 0; i < nsegs; i++)
1275 bounds.x = MIN (bounds.x, segs[i].x1);
1276 bounds.x = MIN (bounds.x, segs[i].x2);
1277 bounds.y = MIN (bounds.y, segs[i].y1);
1278 bounds.y = MIN (bounds.y, segs[i].y2);
1281 for (i = 0; i < nsegs; i++)
1283 bounds.width = MAX (bounds.width, segs[i].x1 - bounds.x);
1284 bounds.width = MAX (bounds.width, segs[i].x2 - bounds.x);
1285 bounds.height = MAX (bounds.height, segs[i].y1 - bounds.y);
1286 bounds.height = MAX (bounds.height, segs[i].y2 - bounds.y);
1289 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1291 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1292 draw_segments, region, segs, nsegs);
1294 gdk_region_destroy (region);
1298 draw_lines (GdkGCWin32 *gcwin32,
1308 pts = va_arg (args, POINT *);
1309 npoints = va_arg (args, gint);
1311 if (x_offset != 0 || y_offset != 0)
1312 for (i = 0; i < npoints; i++)
1314 pts[i].x -= x_offset;
1315 pts[i].y -= y_offset;
1318 if (gcwin32->pen_dashes && !IS_WIN_NT ())
1320 for (i = 0; i < npoints - 1; i++)
1322 if (pts[i].x == pts[i+1].x)
1325 if (pts[i].y > pts[i+1].y)
1326 y1 = pts[i+1].y, y2 = pts[i].y;
1328 y1 = pts[i].y, y2 = pts[i+1].y;
1330 render_line_vertical (hdc, pts[i].x, y1, y2,
1332 gcwin32->pen_dashes,
1333 gcwin32->pen_num_dashes);
1335 else if (pts[i].y == pts[i+1].y)
1338 if (pts[i].x > pts[i+1].x)
1339 x1 = pts[i+1].x, x2 = pts[i].x;
1341 x1 = pts[i].x, x2 = pts[i+1].x;
1343 render_line_horizontal (hdc, x1, x2, pts[i].y,
1345 gcwin32->pen_dashes,
1346 gcwin32->pen_num_dashes);
1349 GDI_CALL (MoveToEx, (hdc, pts[i].x, pts[i].y, NULL)) &&
1350 GDI_CALL (LineTo, (hdc, pts[i+1].x, pts[i+1].y));
1354 GDI_CALL (Polyline, (hdc, pts, npoints));
1358 gdk_win32_draw_lines (GdkDrawable *drawable,
1363 GdkRectangle bounds;
1368 GDK_NOTE (MISC, g_print ("gdk_win32_draw_lines: %s %d points\n",
1369 _gdk_win32_drawable_description (drawable),
1375 bounds.x = G_MAXINT;
1376 bounds.y = G_MAXINT;
1380 pts = g_new (POINT, npoints);
1382 for (i = 0; i < npoints; i++)
1384 bounds.x = MIN (bounds.x, points[i].x);
1385 bounds.y = MIN (bounds.y, points[i].y);
1386 pts[i].x = points[i].x;
1387 pts[i].y = points[i].y;
1390 for (i = 0; i < npoints; i++)
1392 bounds.width = MAX (bounds.width, points[i].x - bounds.x);
1393 bounds.height = MAX (bounds.height, points[i].y - bounds.y);
1396 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1398 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1399 draw_lines, region, pts, npoints);
1401 gdk_region_destroy (region);
1406 draw_glyphs (GdkGCWin32 *gcwin32,
1415 PangoGlyphString *glyphs;
1417 font = va_arg (args, PangoFont *);
1418 x = va_arg (args, gint);
1419 y = va_arg (args, gint);
1420 glyphs = va_arg (args, PangoGlyphString *);
1425 pango_win32_render (hdc, font, glyphs, x, y);
1429 gdk_win32_draw_glyphs (GdkDrawable *drawable,
1434 PangoGlyphString *glyphs)
1436 GdkRectangle bounds;
1438 PangoRectangle ink_rect;
1440 pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
1442 bounds.x = x + PANGO_PIXELS (ink_rect.x) - 1;
1443 bounds.y = y + PANGO_PIXELS (ink_rect.y) - 1;
1444 bounds.width = PANGO_PIXELS (ink_rect.width) + 2;
1445 bounds.height = PANGO_PIXELS (ink_rect.height) + 2;
1446 region = gdk_region_rectangle (&bounds);
1448 generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
1449 draw_glyphs, region, font, x, y, glyphs);
1451 gdk_region_destroy (region);
1455 blit_from_pixmap (gboolean use_fg_bg,
1456 GdkDrawableImplWin32 *dest,
1458 GdkPixmapImplWin32 *src,
1459 GdkGCWin32 *gcwin32,
1469 RGBQUAD oldtable[256], newtable[256];
1472 gint newtable_size = 0, oldtable_size = 0;
1475 GDK_NOTE (MISC, g_print ("blit_from_pixmap\n"));
1477 if (!(srcdc = CreateCompatibleDC (NULL)))
1479 WIN32_GDI_FAILED ("CreateCompatibleDC");
1483 if (!(holdbitmap = SelectObject (srcdc, ((GdkDrawableImplWin32 *) src)->handle)))
1484 WIN32_GDI_FAILED ("SelectObject");
1487 if (GDK_PIXMAP_OBJECT (src->parent_instance.wrapper)->depth <= 8)
1489 /* Blitting from a 1, 4 or 8-bit pixmap */
1491 if ((oldtable_size = GetDIBColorTable (srcdc, 0, 256, oldtable)) == 0)
1492 WIN32_GDI_FAILED ("GetDIBColorTable");
1493 else if (GDK_PIXMAP_OBJECT (src->parent_instance.wrapper)->depth == 1)
1495 /* Blitting from an 1-bit pixmap */
1501 bgix = gcwin32->background;
1502 fgix = gcwin32->foreground;
1510 if (GDK_IS_PIXMAP_IMPL_WIN32 (dest) &&
1511 GDK_PIXMAP_OBJECT (dest->wrapper)->depth <= 8)
1513 /* Destination is also pixmap, get fg and bg from
1514 * its palette. Either use the foreground and
1515 * background pixel values in the GC (only in the
1516 * case of gdk_image_put(), cf. XPutImage()), or 0
1517 * and 1 to index the palette.
1519 if (!GDI_CALL (GetDIBColorTable, (hdc, bgix, 1, newtable)) ||
1520 !GDI_CALL (GetDIBColorTable, (hdc, fgix, 1, newtable+1)))
1525 /* Destination is a window, get fg and bg from its
1529 bg = _gdk_win32_colormap_color (dest->colormap, bgix);
1530 fg = _gdk_win32_colormap_color (dest->colormap, fgix);
1531 newtable[0].rgbBlue = GetBValue (bg);
1532 newtable[0].rgbGreen = GetGValue (bg);
1533 newtable[0].rgbRed = GetRValue (bg);
1534 newtable[0].rgbReserved = 0;
1535 newtable[1].rgbBlue = GetBValue (fg);
1536 newtable[1].rgbGreen = GetGValue (fg);
1537 newtable[1].rgbRed = GetRValue (fg);
1538 newtable[1].rgbReserved = 0;
1541 GDK_NOTE (MISC, g_print ("bg: %02x %02x %02x "
1542 "fg: %02x %02x %02x\n",
1544 newtable[0].rgbGreen,
1545 newtable[0].rgbBlue,
1547 newtable[1].rgbGreen,
1548 newtable[1].rgbBlue));
1551 else if (GDK_IS_PIXMAP_IMPL_WIN32 (dest))
1553 /* Destination is pixmap, get its color table */
1555 if ((newtable_size = GetDIBColorTable (hdc, 0, 256, newtable)) == 0)
1556 WIN32_GDI_FAILED ("GetDIBColorTable"), ok = FALSE;
1559 /* If blitting between pixmaps, set source's color table */
1560 if (ok && newtable_size > 0)
1562 GDK_NOTE (MISC_OR_COLORMAP,
1563 g_print ("blit_from_pixmap: set color table"
1564 " hdc=%p count=%d\n",
1565 srcdc, newtable_size));
1566 if (!GDI_CALL (SetDIBColorTable, (srcdc, 0, newtable_size, newtable)))
1572 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1573 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1575 /* Restore source's color table if necessary */
1576 if (ok && newtable_size > 0 && oldtable_size > 0)
1578 GDK_NOTE (MISC_OR_COLORMAP,
1579 g_print ("blit_from_pixmap: reset color table"
1580 " hdc=%p count=%d\n",
1581 srcdc, oldtable_size));
1582 GDI_CALL (SetDIBColorTable, (srcdc, 0, oldtable_size, oldtable));
1585 GDI_CALL (SelectObject, (srcdc, holdbitmap));
1587 GDI_CALL (DeleteDC, (srcdc));
1591 blit_inside_window (HDC hdc,
1592 GdkGCWin32 *gcwin32,
1601 GDK_NOTE (MISC, g_print ("blit_inside_window\n"));
1603 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1604 hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1608 blit_from_window (HDC hdc,
1609 GdkGCWin32 *gcwin32,
1610 GdkDrawableImplWin32 *src,
1619 HPALETTE holdpal = NULL;
1620 GdkColormap *cmap = gdk_colormap_get_system ();
1622 GDK_NOTE (MISC, g_print ("blit_from_window\n"));
1624 if ((srcdc = GetDC (src->handle)) == NULL)
1626 WIN32_GDI_FAILED ("GetDC");
1630 if (cmap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
1631 cmap->visual->type == GDK_VISUAL_STATIC_COLOR)
1635 if (!(holdpal = SelectPalette (srcdc, GDK_WIN32_COLORMAP_DATA (cmap)->hpal, FALSE)))
1636 WIN32_GDI_FAILED ("SelectPalette");
1637 else if ((k = RealizePalette (srcdc)) == GDI_ERROR)
1638 WIN32_GDI_FAILED ("RealizePalette");
1640 GDK_NOTE (MISC_OR_COLORMAP,
1641 g_print ("blit_from_window: realized %d\n", k));
1644 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1645 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1647 if (holdpal != NULL)
1648 GDI_CALL (SelectPalette, (srcdc, holdpal, FALSE));
1650 GDI_CALL (ReleaseDC, (src->handle, srcdc));
1654 _gdk_win32_blit (gboolean use_fg_bg,
1655 GdkDrawableImplWin32 *drawable,
1666 HRGN src_rgn, draw_rgn, outside_rgn;
1668 GdkDrawableImplWin32 *draw_impl;
1669 GdkDrawableImplWin32 *src_impl = NULL;
1670 gint src_width, src_height;
1672 GDK_NOTE (MISC, g_print ("_gdk_win32_blit: src:%s %dx%d@+%d+%d\n"
1673 " dst:%s @+%d+%d use_fg_bg=%d\n",
1674 _gdk_win32_drawable_description (src),
1675 width, height, xsrc, ysrc,
1676 _gdk_win32_drawable_description ((GdkDrawable *) drawable),
1680 draw_impl = (GdkDrawableImplWin32 *) drawable;
1682 if (GDK_IS_DRAWABLE_IMPL_WIN32 (src))
1683 src_impl = (GdkDrawableImplWin32 *) src;
1684 else if (GDK_IS_WINDOW (src))
1685 src_impl = (GdkDrawableImplWin32 *) GDK_WINDOW_OBJECT (src)->impl;
1686 else if (GDK_IS_PIXMAP (src))
1687 src_impl = (GdkDrawableImplWin32 *) GDK_PIXMAP_OBJECT (src)->impl;
1689 g_assert_not_reached ();
1691 hdc = gdk_win32_hdc_get ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1693 gdk_drawable_get_size (src, &src_width, &src_height);
1695 if ((src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1)) == NULL)
1696 WIN32_GDI_FAILED ("CreateRectRgn");
1697 else if ((draw_rgn = CreateRectRgn (xsrc, ysrc,
1699 ysrc + height + 1)) == NULL)
1700 WIN32_GDI_FAILED ("CreateRectRgn");
1703 if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
1707 /* If we are drawing on a window, calculate the region that is
1708 * outside the source pixmap, and invalidate that, causing it to
1709 * be cleared. Not completely sure whether this is always needed. XXX
1712 outside_rgn = CreateRectRgnIndirect (&r);
1714 if ((comb = CombineRgn (outside_rgn,
1716 RGN_DIFF)) == ERROR)
1717 WIN32_GDI_FAILED ("CombineRgn");
1718 else if (comb != NULLREGION)
1720 OffsetRgn (outside_rgn, xdest, ydest);
1721 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
1722 g_print ("...calling InvalidateRgn, "
1723 "bbox: %ldx%ld@+%ld+%ld\n",
1724 r.right - r.left - 1, r.bottom - r.top - 1,
1726 InvalidateRgn (draw_impl->handle, outside_rgn, TRUE);
1728 GDI_CALL (DeleteObject, (outside_rgn));
1731 #if 1 /* Don't know if this is necessary XXX */
1732 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
1733 g_warning ("gdk_win32_blit: CombineRgn returned a COMPLEXREGION");
1735 GetRgnBox (draw_rgn, &r);
1736 if (r.left != xsrc || r.top != ysrc ||
1737 r.right != xsrc + width + 1 || r.bottom != ysrc + height + 1)
1739 xdest += r.left - xsrc;
1741 ydest += r.top - ysrc;
1743 width = r.right - xsrc - 1;
1744 height = r.bottom - ysrc - 1;
1746 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
1748 width, height, xsrc, ysrc,
1753 GDI_CALL (DeleteObject, (src_rgn));
1754 GDI_CALL (DeleteObject, (draw_rgn));
1757 if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
1758 blit_from_pixmap (use_fg_bg, draw_impl, hdc,
1759 (GdkPixmapImplWin32 *) src_impl, GDK_GC_WIN32 (gc),
1760 xsrc, ysrc, xdest, ydest, width, height);
1761 else if (draw_impl->handle == src_impl->handle)
1762 blit_inside_window (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
1764 blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
1765 gdk_win32_hdc_release ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1769 gdk_win32_draw_image (GdkDrawable *drawable,
1779 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1781 _gdk_win32_blit (TRUE, (GdkDrawableImplWin32 *) drawable,
1782 gc, (GdkPixmap *) image->windowing_data,
1783 xsrc, ysrc, xdest, ydest, width, height);
1787 gdk_win32_get_depth (GdkDrawable *drawable)
1789 /* This is a bit bogus but I'm not sure the other way is better */
1791 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1795 gdk_win32_get_screen (GdkDrawable *drawable)
1797 return gdk_screen_get_default ();
1801 gdk_win32_get_visual (GdkDrawable *drawable)
1803 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1807 gdk_win32_drawable_get_handle (GdkDrawable *drawable)
1809 return GDK_DRAWABLE_HANDLE (drawable);