1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include <pango/pangowin32.h>
34 #include "gdkscreen.h" /* gdk_screen_get_default() */
35 #include "gdkregion-generic.h"
36 #include "gdkprivate-win32.h"
38 #define ROP3_D 0x00AA0029
39 #define ROP3_DPSao 0x00EA02E9
40 #define ROP3_DSna 0x00220326
42 #define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
43 GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)
45 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
52 static void gdk_win32_draw_arc (GdkDrawable *drawable,
61 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
66 static void gdk_win32_draw_text (GdkDrawable *drawable,
73 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
80 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
89 static void gdk_win32_draw_points (GdkDrawable *drawable,
93 static void gdk_win32_draw_segments (GdkDrawable *drawable,
97 static void gdk_win32_draw_lines (GdkDrawable *drawable,
101 static void gdk_win32_draw_glyphs (GdkDrawable *drawable,
106 PangoGlyphString *glyphs);
107 static void gdk_win32_draw_image (GdkDrawable *drawable,
117 static void gdk_win32_set_colormap (GdkDrawable *drawable,
118 GdkColormap *colormap);
120 static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable);
122 static gint gdk_win32_get_depth (GdkDrawable *drawable);
124 static GdkScreen * gdk_win32_get_screen (GdkDrawable *drawable);
126 static GdkVisual* gdk_win32_get_visual (GdkDrawable *drawable);
128 static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass);
130 static void gdk_drawable_impl_win32_finalize (GObject *object);
132 static gpointer parent_class = NULL;
135 gdk_drawable_impl_win32_get_type (void)
137 static GType object_type = 0;
141 static const GTypeInfo object_info =
143 sizeof (GdkDrawableImplWin32Class),
144 (GBaseInitFunc) NULL,
145 (GBaseFinalizeFunc) NULL,
146 (GClassInitFunc) gdk_drawable_impl_win32_class_init,
147 NULL, /* class_finalize */
148 NULL, /* class_data */
149 sizeof (GdkDrawableImplWin32),
151 (GInstanceInitFunc) NULL,
154 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
155 "GdkDrawableImplWin32",
163 gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass)
165 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
166 GObjectClass *object_class = G_OBJECT_CLASS (klass);
168 parent_class = g_type_class_peek_parent (klass);
170 object_class->finalize = gdk_drawable_impl_win32_finalize;
172 drawable_class->create_gc = _gdk_win32_gc_new;
173 drawable_class->draw_rectangle = gdk_win32_draw_rectangle;
174 drawable_class->draw_arc = gdk_win32_draw_arc;
175 drawable_class->draw_polygon = gdk_win32_draw_polygon;
176 drawable_class->draw_text = gdk_win32_draw_text;
177 drawable_class->draw_text_wc = gdk_win32_draw_text_wc;
178 drawable_class->draw_drawable = gdk_win32_draw_drawable;
179 drawable_class->draw_points = gdk_win32_draw_points;
180 drawable_class->draw_segments = gdk_win32_draw_segments;
181 drawable_class->draw_lines = gdk_win32_draw_lines;
182 drawable_class->draw_glyphs = gdk_win32_draw_glyphs;
183 drawable_class->draw_image = gdk_win32_draw_image;
185 drawable_class->set_colormap = gdk_win32_set_colormap;
186 drawable_class->get_colormap = gdk_win32_get_colormap;
188 drawable_class->get_depth = gdk_win32_get_depth;
189 drawable_class->get_screen = gdk_win32_get_screen;
190 drawable_class->get_visual = gdk_win32_get_visual;
192 drawable_class->_copy_to_image = _gdk_win32_copy_to_image;
196 gdk_drawable_impl_win32_finalize (GObject *object)
198 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
200 G_OBJECT_CLASS (parent_class)->finalize (object);
203 /*****************************************************
204 * Win32 specific implementations of generic functions *
205 *****************************************************/
208 gdk_win32_get_colormap (GdkDrawable *drawable)
210 return GDK_DRAWABLE_IMPL_WIN32 (drawable)->colormap;
214 gdk_win32_set_colormap (GdkDrawable *drawable,
215 GdkColormap *colormap)
217 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
219 if (impl->colormap == colormap)
223 gdk_colormap_unref (impl->colormap);
224 impl->colormap = colormap;
226 gdk_colormap_ref (impl->colormap);
233 * Render a dashed line 'by hand' cause the Win9x GDI is
234 * too limited to do so
236 static inline gboolean
237 render_line_horizontal (HDC hdc,
247 for (n = 0; x1 < x2; n++)
249 int len = dashes[n % num_dashes];
254 if (!GDI_CALL (PatBlt, (hdc, x1, y - pen_width / 2,
259 x1 += dashes[n % num_dashes];
265 static inline gboolean
266 render_line_vertical (HDC hdc,
276 for (n = 0; y1 < y2; n++)
278 int len = dashes[n % num_dashes];
282 if (!GDI_CALL (PatBlt, (hdc, x - pen_width / 2, y1,
287 y1 += dashes[n % num_dashes];
294 draw_tiles_lowlevel (HDC dest,
308 GDK_NOTE (MISC, g_print ("draw_tiles_lowlevel: %p +%d+%d tile=%p:%dx%d@+%d+%d %dx%d\n",
311 tile, tile_width, tile_height,
312 tile_x_origin, tile_y_origin,
315 y = tile_y_origin % tile_height;
318 while (y < dest_y + height)
320 if (y + tile_height >= dest_y)
322 x = tile_x_origin % tile_width;
325 while (x < dest_x + width)
327 if (x + tile_width >= dest_x)
329 gint src_x = MAX (0, dest_x - x);
330 gint src_y = MAX (0, dest_y - y);
332 if (!GDI_CALL (BitBlt, (dest, x + src_x, y + src_y,
333 MIN (tile_width, dest_x + width - (x + src_x)),
334 MIN (tile_height, dest_y + height - (y + src_y)),
348 draw_tiles (GdkDrawable *drawable,
359 const GdkGCValuesMask mask = GDK_GC_FOREGROUND;
360 gint tile_width, tile_height;
362 HDC dest_hdc, tile_hdc;
364 gc_copy = gdk_gc_new (tile);
365 gdk_gc_copy (gc_copy, gc);
366 dest_hdc = gdk_win32_hdc_get (drawable, gc, mask);
367 tile_hdc = gdk_win32_hdc_get (tile, gc_copy, mask);
369 gdk_drawable_get_size (tile, &tile_width, &tile_height);
371 draw_tiles_lowlevel (dest_hdc, tile_hdc, rop3,
372 dest_x, dest_y, tile_x_origin, tile_y_origin,
373 width, height, tile_width, tile_height);
375 gdk_win32_hdc_release (drawable, gc, mask);
376 gdk_win32_hdc_release (tile, gc_copy, mask);
377 gdk_gc_unref (gc_copy);
381 rop2_to_rop3 (int rop2)
385 /* Oh, Microsoft's silly names for binary and ternary rops. */
386 #define CASE(rop2,rop3) case R2_##rop2: return rop3
387 CASE (BLACK, BLACKNESS);
388 CASE (NOTMERGEPEN, NOTSRCERASE);
389 CASE (MASKNOTPEN, 0x00220326);
390 CASE (NOTCOPYPEN, NOTSRCCOPY);
391 CASE (MASKPENNOT, SRCERASE);
392 CASE (NOT, DSTINVERT);
393 CASE (XORPEN, SRCINVERT);
394 CASE (NOTMASKPEN, 0x007700E6);
395 CASE (MASKPEN, SRCAND);
396 CASE (NOTXORPEN, 0x00990066);
397 CASE (NOP, 0x00AA0029);
398 CASE (MERGENOTPEN, MERGEPAINT);
399 CASE (COPYPEN, SRCCOPY);
400 CASE (MERGEPENNOT, 0x00DD0228);
401 CASE (MERGEPEN, SRCPAINT);
402 CASE (WHITE, WHITENESS);
404 default: return SRCCOPY;
409 generic_draw (GdkDrawable *drawable,
411 GdkGCValuesMask mask,
412 void (*function) (GdkGCWin32 *, HDC, gint, gint, va_list),
413 const GdkRegion *region,
416 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
417 GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc);
421 va_start (args, region);
423 /* If tiled or stippled, draw to a temp pixmap and do blitting magic.
426 if (gcwin32->values_mask & GDK_GC_FILL &&
427 ((gcwin32->fill_style == GDK_TILED &&
428 gcwin32->values_mask & GDK_GC_TILE &&
429 gcwin32->tile != NULL)
431 ((gcwin32->fill_style == GDK_OPAQUE_STIPPLED ||
432 gcwin32->fill_style == GDK_STIPPLED) &&
433 gcwin32->values_mask & GDK_GC_STIPPLE &&
434 gcwin32->stipple != NULL)))
436 const GdkGCValuesMask blitting_mask = 0;
437 GdkGCValuesMask drawing_mask = GDK_GC_FOREGROUND;
438 gint ts_x_origin = 0, ts_y_origin = 0;
440 gint width = region->extents.x2 - region->extents.x1;
441 gint height = region->extents.y2 - region->extents.y1;
443 GdkPixmap *mask_pixmap =
444 gdk_pixmap_new (drawable, width, height, 1);
445 GdkPixmap *tile_pixmap =
446 gdk_pixmap_new (drawable, width, height, -1);
447 GdkPixmap *stipple_bitmap = NULL;
450 GdkGC *mask_gc = gdk_gc_new (mask_pixmap);
451 GdkGC *tile_gc = gdk_gc_new (tile_pixmap);
456 HGDIOBJ old_mask_hbm;
457 HGDIOBJ old_tile_hbm;
459 GdkGCValues gcvalues;
461 hdc = gdk_win32_hdc_get (drawable, gc, blitting_mask);
462 tile_hdc = CreateCompatibleDC (hdc);
464 if (gcwin32->values_mask & GDK_GC_TS_X_ORIGIN)
465 ts_x_origin = gc->ts_x_origin;
466 if (gcwin32->values_mask & GDK_GC_TS_Y_ORIGIN)
467 ts_y_origin = gc->ts_y_origin;
469 ts_x_origin -= region->extents.x1;
470 ts_y_origin -= region->extents.y1;
472 /* Fill mask bitmap with zeros */
473 gdk_gc_set_function (mask_gc, GDK_CLEAR);
474 gdk_draw_rectangle (mask_pixmap, mask_gc, TRUE,
475 0, 0, width, height);
477 /* Paint into mask bitmap, drawing ones */
478 gdk_gc_set_function (mask_gc, GDK_COPY);
480 gdk_gc_set_foreground (mask_gc, &fg);
482 /* If the drawing function uses line attributes, set them as in
485 if (mask & LINE_ATTRIBUTES)
487 gdk_gc_get_values (gc, &gcvalues);
488 if (gcvalues.line_width != 0 ||
489 gcvalues.line_style != GDK_LINE_SOLID ||
490 gcvalues.cap_style != GDK_CAP_BUTT ||
491 gcvalues.join_style != GDK_JOIN_MITER)
492 gdk_gc_set_line_attributes (mask_gc,
496 gcvalues.join_style);
497 drawing_mask |= LINE_ATTRIBUTES;
500 /* Ditto, if the drawing function draws text, set up for that. */
501 if (mask & GDK_GC_FONT)
502 drawing_mask |= GDK_GC_FONT;
504 mask_hdc = gdk_win32_hdc_get (mask_pixmap, mask_gc, drawing_mask);
505 (*function) (GDK_GC_WIN32 (mask_gc), mask_hdc,
506 region->extents.x1, region->extents.y1, args);
507 gdk_win32_hdc_release (mask_pixmap, mask_gc, drawing_mask);
509 if (gcwin32->fill_style == GDK_TILED)
511 /* Tile pixmap with tile */
512 draw_tiles (tile_pixmap, tile_gc, SRCCOPY,
514 0, 0, ts_x_origin, ts_y_origin,
519 /* Tile with stipple */
522 stipple_bitmap = gdk_pixmap_new (NULL, width, height, 1);
523 stipple_gc = gdk_gc_new (stipple_bitmap);
525 /* Tile stipple bitmap */
526 draw_tiles (stipple_bitmap, stipple_gc, SRCCOPY,
528 0, 0, ts_x_origin, ts_y_origin,
531 if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
533 /* Fill tile pixmap with background */
534 fg.pixel = gcwin32->background;
535 gdk_gc_set_foreground (tile_gc, &fg);
536 gdk_draw_rectangle (tile_pixmap, tile_gc, TRUE,
537 0, 0, width, height);
541 gdk_gc_unref (mask_gc);
542 gdk_gc_unref (tile_gc);
544 mask_hdc = CreateCompatibleDC (hdc);
546 if ((old_mask_hbm = SelectObject (mask_hdc, GDK_PIXMAP_HBITMAP (mask_pixmap))) == NULL)
547 WIN32_GDI_FAILED ("SelectObject");
549 if ((old_tile_hbm = SelectObject (tile_hdc, GDK_PIXMAP_HBITMAP (tile_pixmap))) == NULL)
550 WIN32_GDI_FAILED ("SelectObject");
552 if (gcwin32->fill_style == GDK_STIPPLED ||
553 gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
555 HDC stipple_hdc = CreateCompatibleDC (hdc);
556 HGDIOBJ old_stipple_hbm = SelectObject (stipple_hdc, GDK_PIXMAP_HBITMAP (stipple_bitmap));
557 HBRUSH fg_brush = CreateSolidBrush
558 (_gdk_win32_colormap_color (impl->colormap, gcwin32->foreground));
559 HGDIOBJ old_tile_brush = SelectObject (tile_hdc, fg_brush);
561 /* Paint tile with foreround where stipple is one */
562 GDI_CALL (BitBlt, (tile_hdc, 0, 0, width, height,
563 stipple_hdc, 0, 0, ROP3_DPSao));
565 if (gcwin32->fill_style == GDK_STIPPLED)
567 /* Punch holes in mask where stipple bitmap is zero */
568 GDI_CALL (BitBlt, (mask_hdc, 0, 0, width, height,
569 stipple_hdc, 0, 0, SRCAND));
572 GDI_CALL (SelectObject, (tile_hdc, old_tile_brush));
573 GDI_CALL (DeleteObject, (fg_brush));
574 GDI_CALL (SelectObject, (stipple_hdc, old_stipple_hbm));
575 GDI_CALL (DeleteDC, (stipple_hdc));
576 gdk_drawable_unref (stipple_bitmap);
579 /* Tile pixmap now contains the pattern that we should paint in
580 * the areas where mask is one. (It is filled with said pattern.)
585 GDI_CALL (MaskBlt, (hdc, region->extents.x1, region->extents.y1,
588 GDK_PIXMAP_HBITMAP (mask_pixmap), 0, 0,
589 MAKEROP4 (rop2_to_rop3 (gcwin32->rop2), ROP3_D)));
593 GdkPixmap *temp1_pixmap =
594 gdk_pixmap_new (drawable, width, height, -1);
595 GdkPixmap *temp2_pixmap =
596 gdk_pixmap_new (drawable, width, height, -1);
597 HDC temp1_hdc = CreateCompatibleDC (hdc);
598 HDC temp2_hdc = CreateCompatibleDC (hdc);
599 HGDIOBJ old_temp1_hbm =
600 SelectObject (temp1_hdc, GDK_PIXMAP_HBITMAP (temp1_pixmap));
601 HGDIOBJ old_temp2_hbm =
602 SelectObject (temp2_hdc, GDK_PIXMAP_HBITMAP (temp2_pixmap));
604 /* Grab copy of dest region to temp1 */
605 GDI_CALL (BitBlt,(temp1_hdc, 0, 0, width, height,
606 hdc, region->extents.x1, region->extents.y1, SRCCOPY));
608 /* Paint tile to temp1 using correct function */
609 GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height,
610 tile_hdc, 0, 0, rop2_to_rop3 (gcwin32->rop2)));
612 /* Mask out temp1 where function didn't paint */
613 GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height,
614 mask_hdc, 0, 0, SRCAND));
616 /* Grab another copy of dest region to temp2 */
617 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
618 hdc, region->extents.x1, region->extents.y1, SRCCOPY));
620 /* Mask out temp2 where function did paint */
621 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
622 mask_hdc, 0, 0, ROP3_DSna));
624 /* Combine temp1 with temp2 */
625 GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height,
626 temp1_hdc, 0, 0, SRCPAINT));
629 GDI_CALL (BitBlt, (hdc, region->extents.x1, region->extents.y1, width, height,
630 temp2_hdc, 0, 0, SRCCOPY));
633 GDI_CALL (SelectObject, (temp1_hdc, old_temp1_hbm));
634 GDI_CALL (SelectObject, (temp2_hdc, old_temp2_hbm));
635 GDI_CALL (DeleteDC, (temp1_hdc));
636 GDI_CALL (DeleteDC, (temp2_hdc));
637 gdk_drawable_unref (temp1_pixmap);
638 gdk_drawable_unref (temp2_pixmap);
642 GDI_CALL (SelectObject, (mask_hdc, old_mask_hbm));
643 GDI_CALL (SelectObject, (tile_hdc, old_tile_hbm));
644 GDI_CALL (DeleteDC, (mask_hdc));
645 GDI_CALL (DeleteDC, (tile_hdc));
646 gdk_drawable_unref (mask_pixmap);
647 gdk_drawable_unref (tile_pixmap);
649 gdk_win32_hdc_release (drawable, gc, blitting_mask);
653 hdc = gdk_win32_hdc_get (drawable, gc, mask);
654 (*function) (gcwin32, hdc, 0, 0, args);
655 gdk_win32_hdc_release (drawable, gc, mask);
661 widen_bounds (GdkRectangle *bounds,
667 bounds->x -= pen_width;
668 bounds->y -= pen_width;
669 bounds->width += 2 * pen_width;
670 bounds->height += 2 * pen_width;
672 return gdk_region_rectangle (bounds);
676 draw_rectangle (GdkGCWin32 *gcwin32,
682 HGDIOBJ old_pen_or_brush;
689 filled = va_arg (args, gboolean);
690 x = va_arg (args, gint);
691 y = va_arg (args, gint);
692 width = va_arg (args, gint);
693 height = va_arg (args, gint);
698 if (!filled && gcwin32->pen_dashes && !IS_WIN_NT ())
700 render_line_vertical (hdc, x, y, y+height+1,
703 gcwin32->pen_num_dashes) &&
704 render_line_horizontal (hdc, x, x+width+1, y,
707 gcwin32->pen_num_dashes) &&
708 render_line_vertical (hdc, x+width+1, y, y+height+1,
711 gcwin32->pen_num_dashes) &&
712 render_line_horizontal (hdc, x, x+width+1, y+height+1,
715 gcwin32->pen_num_dashes);
720 old_pen_or_brush = SelectObject (hdc, GetStockObject (NULL_PEN));
722 old_pen_or_brush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
723 if (old_pen_or_brush == NULL)
724 WIN32_GDI_FAILED ("SelectObject");
726 GDI_CALL (Rectangle, (hdc, x, y, x+width+1, y+height+1));
728 if (old_pen_or_brush != NULL)
729 GDI_CALL (SelectObject, (hdc, old_pen_or_brush));
734 gdk_win32_draw_rectangle (GdkDrawable *drawable,
745 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@+%d+%d\n",
746 _gdk_win32_drawable_description (drawable),
748 (filled ? "fill " : ""),
749 width, height, x, y));
753 bounds.width = width;
754 bounds.height = height;
755 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
757 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
758 draw_rectangle, region, filled, x, y, width, height);
760 gdk_region_destroy (region);
764 draw_arc (GdkGCWin32 *gcwin32,
778 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
780 filled = va_arg (args, gboolean);
781 x = va_arg (args, gint);
782 y = va_arg (args, gint);
783 width = va_arg (args, gint);
784 height = va_arg (args, gint);
785 angle1 = va_arg (args, gint);
786 angle2 = va_arg (args, gint);
791 if (angle2 >= 360*64)
793 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
797 /* The 100. is just an arbitrary value */
798 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
799 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
800 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
801 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
805 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
806 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
807 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
808 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
813 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
814 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
815 x, y, x+width, y+height,
816 nXStartArc, nYStartArc,
817 nXEndArc, nYEndArc));
818 GDI_CALL (Pie, (hdc, x, y, x+width, y+height,
819 nXStartArc, nYStartArc, nXEndArc, nYEndArc));
820 GDI_CALL (SelectObject, (hdc, old_pen));
824 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
825 x, y, x+width, y+height,
826 nXStartArc, nYStartArc,
827 nXEndArc, nYEndArc));
828 GDI_CALL (Arc, (hdc, x, y, x+width, y+height,
829 nXStartArc, nYStartArc, nXEndArc, nYEndArc));
834 gdk_win32_draw_arc (GdkDrawable *drawable,
847 GDK_NOTE (MISC, g_print ("gdk_win32_draw_arc: %s %d,%d,%d,%d %d %d\n",
848 _gdk_win32_drawable_description (drawable),
849 x, y, width, height, angle1, angle2));
851 if (width <= 2 || height <= 2 || angle2 == 0)
856 bounds.width = width;
857 bounds.height = height;
858 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
860 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
861 draw_arc, region, filled, x, y, width, height, angle1, angle2);
863 gdk_region_destroy (region);
867 draw_polygon (GdkGCWin32 *gcwin32,
878 filled = va_arg (args, gboolean);
879 pts = va_arg (args, POINT *);
880 npoints = va_arg (args, gint);
882 if (x_offset != 0 || y_offset != 0)
883 for (i = 0; i < npoints; i++)
885 pts[i].x -= x_offset;
886 pts[i].y -= y_offset;
890 GDI_CALL (Polygon, (hdc, pts, npoints));
892 GDI_CALL (Polyline, (hdc, pts, npoints));
896 gdk_win32_draw_polygon (GdkDrawable *drawable,
907 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %s %d points\n",
908 _gdk_win32_drawable_description (drawable),
919 pts = g_new (POINT, npoints+1);
921 for (i = 0; i < npoints; i++)
923 bounds.x = MIN (bounds.x, points[i].x);
924 bounds.y = MIN (bounds.y, points[i].y);
925 bounds.width = MAX (bounds.width, points[i].x - bounds.x);
926 bounds.height = MAX (bounds.height, points[i].y - bounds.y);
927 pts[i].x = points[i].x;
928 pts[i].y = points[i].y;
931 if (points[0].x != points[npoints-1].x ||
932 points[0].y != points[npoints-1].y)
934 pts[npoints].x = points[0].x;
935 pts[npoints].y = points[0].y;
939 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
941 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
942 draw_polygon, region, filled, pts, npoints);
944 gdk_region_destroy (region);
955 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
956 const wchar_t *wcstr,
962 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
967 if ((oldfont = SelectObject (argp->hdc, singlefont->hfont)) == NULL)
969 WIN32_GDI_FAILED ("SelectObject");
973 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
974 WIN32_GDI_FAILED ("TextOutW");
975 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
978 SelectObject (argp->hdc, oldfont);
982 gdk_win32_draw_text (GdkDrawable *drawable,
990 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
993 gdk_draw_text_arg arg;
995 if (text_length == 0)
998 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1002 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
1004 GDK_NOTE (MISC, g_print ("gdk_win32_draw_text: %s (%d,%d) \"%.*s\" (len %d)\n",
1005 _gdk_win32_drawable_description (drawable),
1007 (text_length > 10 ? 10 : text_length),
1008 text, text_length));
1010 if (text_length == 1)
1012 /* For single characters, don't try to interpret as UTF-8. */
1013 wc = (guchar) text[0];
1014 _gdk_wchar_text_handle (font, &wc, 1, gdk_draw_text_handler, &arg);
1018 wcstr = g_new (wchar_t, text_length);
1019 if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
1020 g_warning ("gdk_win32_draw_text: _gdk_utf8_to_ucs2 failed");
1022 _gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
1027 gdk_win32_hdc_release (drawable, gc, mask);
1031 gdk_win32_draw_text_wc (GdkDrawable *drawable,
1036 const GdkWChar *text,
1039 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
1042 gdk_draw_text_arg arg;
1044 if (text_length == 0)
1047 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1051 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
1053 GDK_NOTE (MISC, g_print ("gdk_win32_draw_text_wc: %s (%d,%d) len: %d\n",
1054 _gdk_win32_drawable_description (drawable),
1055 x, y, text_length));
1057 if (sizeof (wchar_t) != sizeof (GdkWChar))
1059 wcstr = g_new (wchar_t, text_length);
1060 for (i = 0; i < text_length; i++)
1064 wcstr = (wchar_t *) text;
1066 _gdk_wchar_text_handle (font, wcstr, text_length,
1067 gdk_draw_text_handler, &arg);
1069 if (sizeof (wchar_t) != sizeof (GdkWChar))
1072 gdk_win32_hdc_release (drawable, gc, mask);
1076 gdk_win32_draw_drawable (GdkDrawable *drawable,
1086 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1088 _gdk_win32_blit (FALSE, (GdkDrawableImplWin32 *) drawable,
1089 gc, src, xsrc, ysrc,
1090 xdest, ydest, width, height);
1094 gdk_win32_draw_points (GdkDrawable *drawable,
1103 hdc = gdk_win32_hdc_get (drawable, gc, GDK_GC_FOREGROUND);
1105 GDK_NOTE (MISC, g_print ("gdk_win32_draw_points: %s %d points\n",
1106 _gdk_win32_drawable_description (drawable),
1109 /* The X11 version uses XDrawPoint(), which doesn't use the fill
1110 * mode, so don't use generic_draw. But we should use the current
1111 * function, so we can't use SetPixel(). Draw single-pixel
1112 * rectangles (sigh).
1115 old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
1116 for (i = 0; i < npoints; i++)
1117 Rectangle (hdc, points[i].x, points[i].y,
1118 points[i].x + 2, points[i].y + 2);
1120 SelectObject (hdc, old_pen);
1121 gdk_win32_hdc_release (drawable, gc, GDK_GC_FOREGROUND);
1125 draw_segments (GdkGCWin32 *gcwin32,
1135 segs = va_arg (args, GdkSegment *);
1136 nsegs = va_arg (args, gint);
1138 if (x_offset != 0 || y_offset != 0)
1139 for (i = 0; i < nsegs; i++)
1141 segs[i].x1 -= x_offset;
1142 segs[i].y1 -= y_offset;
1143 segs[i].x2 -= x_offset;
1144 segs[i].y2 -= y_offset;
1147 if (gcwin32->pen_dashes && !IS_WIN_NT ())
1149 for (i = 0; i < nsegs; i++)
1151 if (segs[i].x1 == segs[i].x2)
1155 if (segs[i].y1 <= segs[i].y2)
1156 y1 = segs[i].y1, y2 = segs[i].y2;
1158 y1 = segs[i].y2, y2 = segs[i].y1;
1160 render_line_vertical (hdc,
1163 gcwin32->pen_dashes,
1164 gcwin32->pen_num_dashes);
1166 else if (segs[i].y1 == segs[i].y2)
1170 if (segs[i].x1 <= segs[i].x2)
1171 x1 = segs[i].x1, x2 = segs[i].x2;
1173 x1 = segs[i].x2, x2 = segs[i].x1;
1175 render_line_horizontal (hdc,
1178 gcwin32->pen_dashes,
1179 gcwin32->pen_num_dashes);
1182 GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
1183 GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)) &&
1184 (gcwin32->pen_width <= 1 &&
1185 GDI_CALL (LineTo, (hdc, segs[i].x2 + 1, segs[i].y2 + 1)));
1190 for (i = 0; i < nsegs; i++)
1191 GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
1192 GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)) &&
1193 (gcwin32->pen_width <= 1 &&
1194 GDI_CALL (LineTo, (hdc, segs[i].x2 + 1, segs[i].y2 + 1)));
1199 gdk_win32_draw_segments (GdkDrawable *drawable,
1204 GdkRectangle bounds;
1208 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %s %d segs\n",
1209 _gdk_win32_drawable_description (drawable),
1212 bounds.x = G_MAXINT;
1213 bounds.y = G_MAXINT;
1217 for (i = 0; i < nsegs; i++)
1219 bounds.x = MIN (bounds.x, segs[i].x1);
1220 bounds.x = MIN (bounds.x, segs[i].x2);
1221 bounds.y = MIN (bounds.y, segs[i].y1);
1222 bounds.y = MIN (bounds.y, segs[i].y2);
1223 bounds.width = MAX (bounds.width, segs[i].x1 - bounds.x);
1224 bounds.width = MAX (bounds.width, segs[i].x2 - bounds.x);
1225 bounds.height = MAX (bounds.height, segs[i].y1 - bounds.y);
1226 bounds.height = MAX (bounds.height, segs[i].y2 - bounds.y);
1229 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1231 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1232 draw_segments, region, segs, nsegs);
1234 gdk_region_destroy (region);
1238 draw_lines (GdkGCWin32 *gcwin32,
1248 pts = va_arg (args, POINT *);
1249 npoints = va_arg (args, gint);
1251 if (x_offset != 0 || y_offset != 0)
1252 for (i = 0; i < npoints; i++)
1254 pts[i].x -= x_offset;
1255 pts[i].y -= y_offset;
1258 if (gcwin32->pen_dashes && !IS_WIN_NT ())
1260 for (i = 0; i < npoints - 1; i++)
1262 if (pts[i].x == pts[i+1].x)
1265 if (pts[i].y > pts[i+1].y)
1266 y1 = pts[i+1].y, y2 = pts[i].y;
1268 y1 = pts[i].y, y2 = pts[i+1].y;
1270 render_line_vertical (hdc, pts[i].x, y1, y2,
1272 gcwin32->pen_dashes,
1273 gcwin32->pen_num_dashes);
1275 else if (pts[i].y == pts[i+1].y)
1278 if (pts[i].x > pts[i+1].x)
1279 x1 = pts[i+1].x, x2 = pts[i].x;
1281 x1 = pts[i].x, x2 = pts[i+1].x;
1283 render_line_horizontal (hdc, x1, x2, pts[i].y,
1285 gcwin32->pen_dashes,
1286 gcwin32->pen_num_dashes);
1289 GDI_CALL (MoveToEx, (hdc, pts[i].x, pts[i].y, NULL)) &&
1290 GDI_CALL (LineTo, (hdc, pts[i+1].x, pts[i+1].y));
1294 GDI_CALL (Polyline, (hdc, pts, npoints));
1298 gdk_win32_draw_lines (GdkDrawable *drawable,
1303 GdkRectangle bounds;
1308 GDK_NOTE (MISC, g_print ("gdk_win32_draw_lines: %s %d points\n",
1309 _gdk_win32_drawable_description (drawable),
1315 bounds.x = G_MAXINT;
1316 bounds.y = G_MAXINT;
1320 pts = g_new (POINT, npoints);
1322 for (i = 0; i < npoints; i++)
1324 bounds.x = MIN (bounds.x, points[i].x);
1325 bounds.y = MIN (bounds.y, points[i].y);
1326 bounds.width = MAX (bounds.width, points[i].x - bounds.x);
1327 bounds.height = MAX (bounds.height, points[i].y - bounds.y);
1328 pts[i].x = points[i].x;
1329 pts[i].y = points[i].y;
1332 region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
1334 generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES,
1335 draw_lines, region, pts, npoints);
1337 gdk_region_destroy (region);
1342 draw_glyphs (GdkGCWin32 *gcwin32,
1351 PangoGlyphString *glyphs;
1353 font = va_arg (args, PangoFont *);
1354 x = va_arg (args, gint);
1355 y = va_arg (args, gint);
1356 glyphs = va_arg (args, PangoGlyphString *);
1361 pango_win32_render (hdc, font, glyphs, x, y);
1365 gdk_win32_draw_glyphs (GdkDrawable *drawable,
1370 PangoGlyphString *glyphs)
1372 GdkRectangle bounds;
1374 PangoRectangle ink_rect;
1376 pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
1378 bounds.x = x + PANGO_PIXELS (ink_rect.x) - 1;
1379 bounds.y = y + PANGO_PIXELS (ink_rect.y) - 1;
1380 bounds.width = PANGO_PIXELS (ink_rect.width) + 2;
1381 bounds.height = PANGO_PIXELS (ink_rect.height) + 2;
1382 region = gdk_region_rectangle (&bounds);
1384 generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT,
1385 draw_glyphs, region, font, x, y, glyphs);
1387 gdk_region_destroy (region);
1391 blit_from_pixmap (gboolean use_fg_bg,
1392 GdkDrawableImplWin32 *dest,
1394 GdkPixmapImplWin32 *src,
1395 GdkGCWin32 *gcwin32,
1405 RGBQUAD oldtable[256], newtable[256];
1408 gint newtable_size = 0, oldtable_size = 0;
1411 GDK_NOTE (MISC, g_print ("blit_from_pixmap\n"));
1413 if (!(srcdc = CreateCompatibleDC (NULL)))
1415 WIN32_GDI_FAILED ("CreateCompatibleDC");
1419 if (!(holdbitmap = SelectObject (srcdc, ((GdkDrawableImplWin32 *) src)->handle)))
1420 WIN32_GDI_FAILED ("SelectObject");
1423 if (src->image->depth <= 8)
1425 /* Blitting from a 1, 4 or 8-bit pixmap */
1427 if ((oldtable_size = GetDIBColorTable (srcdc, 0, 256, oldtable)) == 0)
1428 WIN32_GDI_FAILED ("GetDIBColorTable");
1429 else if (src->image->depth == 1)
1431 /* Blitting from an 1-bit pixmap */
1437 bgix = gcwin32->background;
1438 fgix = gcwin32->foreground;
1446 if (GDK_IS_PIXMAP_IMPL_WIN32 (dest) &&
1447 ((GdkPixmapImplWin32 *) dest)->image->depth <= 8)
1449 /* Destination is also pixmap, get fg and bg from
1450 * its palette. Either use the foreground and
1451 * background pixel values in the GC (only in the
1452 * case of gdk_image_put(), cf. XPutImage()), or 0
1453 * and 1 to index the palette.
1455 if (!GDI_CALL (GetDIBColorTable, (hdc, bgix, 1, newtable)) ||
1456 !GDI_CALL (GetDIBColorTable, (hdc, fgix, 1, newtable+1)))
1461 /* Destination is a window, get fg and bg from its
1465 bg = _gdk_win32_colormap_color (dest->colormap, bgix);
1466 fg = _gdk_win32_colormap_color (dest->colormap, fgix);
1467 newtable[0].rgbBlue = GetBValue (bg);
1468 newtable[0].rgbGreen = GetGValue (bg);
1469 newtable[0].rgbRed = GetRValue (bg);
1470 newtable[0].rgbReserved = 0;
1471 newtable[1].rgbBlue = GetBValue (fg);
1472 newtable[1].rgbGreen = GetGValue (fg);
1473 newtable[1].rgbRed = GetRValue (fg);
1474 newtable[1].rgbReserved = 0;
1477 GDK_NOTE (MISC, g_print ("bg: %02x %02x %02x "
1478 "fg: %02x %02x %02x\n",
1480 newtable[0].rgbGreen,
1481 newtable[0].rgbBlue,
1483 newtable[1].rgbGreen,
1484 newtable[1].rgbBlue));
1487 else if (GDK_IS_PIXMAP_IMPL_WIN32 (dest))
1489 /* Destination is pixmap, get its color table */
1491 if ((newtable_size = GetDIBColorTable (hdc, 0, 256, newtable)) == 0)
1492 WIN32_GDI_FAILED ("GetDIBColorTable"), ok = FALSE;
1495 /* If blitting between pixmaps, set source's color table */
1496 if (ok && newtable_size > 0)
1498 GDK_NOTE (MISC_OR_COLORMAP,
1499 g_print ("blit_from_pixmap: set color table"
1500 " hdc=%p count=%d\n",
1501 srcdc, newtable_size));
1502 if (!GDI_CALL (SetDIBColorTable, (srcdc, 0, newtable_size, newtable)))
1508 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1509 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1511 /* Restore source's color table if necessary */
1512 if (ok && newtable_size > 0 && oldtable_size > 0)
1514 GDK_NOTE (MISC_OR_COLORMAP,
1515 g_print ("blit_from_pixmap: reset color table"
1516 " hdc=%p count=%d\n",
1517 srcdc, oldtable_size));
1518 GDI_CALL (SetDIBColorTable, (srcdc, 0, oldtable_size, oldtable));
1521 GDI_CALL (SelectObject, (srcdc, holdbitmap));
1523 GDI_CALL (DeleteDC, (srcdc));
1527 blit_inside_window (HDC hdc,
1528 GdkGCWin32 *gcwin32,
1537 GDK_NOTE (MISC, g_print ("blit_inside_window\n"));
1539 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1540 hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1544 blit_from_window (HDC hdc,
1545 GdkGCWin32 *gcwin32,
1546 GdkDrawableImplWin32 *src,
1555 HPALETTE holdpal = NULL;
1556 GdkColormap *cmap = gdk_colormap_get_system ();
1558 GDK_NOTE (MISC, g_print ("blit_from_window\n"));
1560 if ((srcdc = GetDC (src->handle)) == NULL)
1562 WIN32_GDI_FAILED ("GetDC");
1566 if (cmap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
1567 cmap->visual->type == GDK_VISUAL_STATIC_COLOR)
1571 if (!(holdpal = SelectPalette (srcdc, GDK_WIN32_COLORMAP_DATA (cmap)->hpal, FALSE)))
1572 WIN32_GDI_FAILED ("SelectPalette");
1573 else if ((k = RealizePalette (srcdc)) == GDI_ERROR)
1574 WIN32_GDI_FAILED ("RealizePalette");
1576 GDK_NOTE (MISC_OR_COLORMAP,
1577 g_print ("blit_from_window: realized %d\n", k));
1580 GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
1581 srcdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
1583 if (holdpal != NULL)
1584 GDI_CALL (SelectPalette, (srcdc, holdpal, FALSE));
1586 GDI_CALL (ReleaseDC, (src->handle, srcdc));
1590 _gdk_win32_blit (gboolean use_fg_bg,
1591 GdkDrawableImplWin32 *drawable,
1602 HRGN src_rgn, draw_rgn, outside_rgn;
1604 GdkDrawableImplWin32 *draw_impl;
1605 GdkDrawableImplWin32 *src_impl = NULL;
1606 gint src_width, src_height;
1608 GDK_NOTE (MISC, g_print ("_gdk_win32_blit: src:%s %dx%d@+%d+%d\n"
1609 " dst:%s @+%d+%d use_fg_bg=%d\n",
1610 _gdk_win32_drawable_description (src),
1611 width, height, xsrc, ysrc,
1612 _gdk_win32_drawable_description ((GdkDrawable *) drawable),
1616 draw_impl = (GdkDrawableImplWin32 *) drawable;
1618 if (GDK_IS_DRAWABLE_IMPL_WIN32 (src))
1619 src_impl = (GdkDrawableImplWin32 *) src;
1620 else if (GDK_IS_WINDOW (src))
1621 src_impl = (GdkDrawableImplWin32 *) GDK_WINDOW_OBJECT (src)->impl;
1622 else if (GDK_IS_PIXMAP (src))
1623 src_impl = (GdkDrawableImplWin32 *) GDK_PIXMAP_OBJECT (src)->impl;
1625 g_assert_not_reached ();
1627 hdc = gdk_win32_hdc_get ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1629 gdk_drawable_get_size (src, &src_width, &src_height);
1631 if ((src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1)) == NULL)
1632 WIN32_GDI_FAILED ("CreateRectRgn");
1633 else if ((draw_rgn = CreateRectRgn (xsrc, ysrc,
1635 ysrc + height + 1)) == NULL)
1636 WIN32_GDI_FAILED ("CreateRectRgn");
1639 if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
1643 /* If we are drawing on a window, calculate the region that is
1644 * outside the source pixmap, and invalidate that, causing it to
1645 * be cleared. Not completely sure whether this is always needed. XXX
1648 outside_rgn = CreateRectRgnIndirect (&r);
1650 if ((comb = CombineRgn (outside_rgn,
1652 RGN_DIFF)) == ERROR)
1653 WIN32_GDI_FAILED ("CombineRgn");
1654 else if (comb != NULLREGION)
1656 OffsetRgn (outside_rgn, xdest, ydest);
1657 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
1658 g_print ("...calling InvalidateRgn, "
1659 "bbox: %ldx%ld@+%ld+%ld\n",
1660 r.right - r.left - 1, r.bottom - r.top - 1,
1662 InvalidateRgn (draw_impl->handle, outside_rgn, TRUE);
1664 GDI_CALL (DeleteObject, (outside_rgn));
1667 #if 1 /* Don't know if this is necessary XXX */
1668 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
1669 g_warning ("gdk_win32_blit: CombineRgn returned a COMPLEXREGION");
1671 GetRgnBox (draw_rgn, &r);
1672 if (r.left != xsrc || r.top != ysrc ||
1673 r.right != xsrc + width + 1 || r.bottom != ysrc + height + 1)
1675 xdest += r.left - xsrc;
1677 ydest += r.top - ysrc;
1679 width = r.right - xsrc - 1;
1680 height = r.bottom - ysrc - 1;
1682 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
1684 width, height, xsrc, ysrc,
1689 GDI_CALL (DeleteObject, (src_rgn));
1690 GDI_CALL (DeleteObject, (draw_rgn));
1693 if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
1694 blit_from_pixmap (use_fg_bg, draw_impl, hdc,
1695 (GdkPixmapImplWin32 *) src_impl, GDK_GC_WIN32 (gc),
1696 xsrc, ysrc, xdest, ydest, width, height);
1697 else if (draw_impl->handle == src_impl->handle)
1698 blit_inside_window (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
1700 blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
1701 gdk_win32_hdc_release ((GdkDrawable *) drawable, gc, GDK_GC_FOREGROUND);
1705 gdk_win32_draw_image (GdkDrawable *drawable,
1715 g_assert (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable));
1717 _gdk_win32_blit (TRUE, (GdkDrawableImplWin32 *) drawable,
1718 gc, (GdkPixmap *) image->windowing_data,
1719 xsrc, ysrc, xdest, ydest, width, height);
1723 gdk_win32_get_depth (GdkDrawable *drawable)
1725 /* This is a bit bogus but I'm not sure the other way is better */
1727 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1731 gdk_win32_get_screen (GdkDrawable *drawable)
1733 return gdk_screen_get_default ();
1737 gdk_win32_get_visual (GdkDrawable *drawable)
1739 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1743 gdk_win32_drawable_get_handle (GdkDrawable *drawable)
1745 return GDK_DRAWABLE_HANDLE (drawable);