1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include <pango/pangowin32.h>
32 #include "gdkprivate-win32.h"
34 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
41 static void gdk_win32_draw_arc (GdkDrawable *drawable,
50 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
55 static void gdk_win32_draw_text (GdkDrawable *drawable,
62 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
69 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
78 static void gdk_win32_draw_points (GdkDrawable *drawable,
82 static void gdk_win32_draw_segments (GdkDrawable *drawable,
86 static void gdk_win32_draw_lines (GdkDrawable *drawable,
90 static void gdk_win32_draw_glyphs (GdkDrawable *drawable,
95 PangoGlyphString *glyphs);
96 static void gdk_win32_draw_image (GdkDrawable *drawable,
106 static void gdk_win32_set_colormap (GdkDrawable *drawable,
107 GdkColormap *colormap);
109 static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable);
111 static gint gdk_win32_get_depth (GdkDrawable *drawable);
113 static GdkVisual* gdk_win32_get_visual (GdkDrawable *drawable);
115 static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass);
117 static void gdk_drawable_impl_win32_finalize (GObject *object);
119 static gpointer parent_class = NULL;
122 gdk_drawable_impl_win32_get_type (void)
124 static GType object_type = 0;
128 static const GTypeInfo object_info =
130 sizeof (GdkDrawableImplWin32Class),
131 (GBaseInitFunc) NULL,
132 (GBaseFinalizeFunc) NULL,
133 (GClassInitFunc) gdk_drawable_impl_win32_class_init,
134 NULL, /* class_finalize */
135 NULL, /* class_data */
136 sizeof (GdkDrawableImplWin32),
138 (GInstanceInitFunc) NULL,
141 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
142 "GdkDrawableImplWin32",
150 gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass)
152 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
153 GObjectClass *object_class = G_OBJECT_CLASS (klass);
155 parent_class = g_type_class_peek_parent (klass);
157 object_class->finalize = gdk_drawable_impl_win32_finalize;
159 drawable_class->create_gc = _gdk_win32_gc_new;
160 drawable_class->draw_rectangle = gdk_win32_draw_rectangle;
161 drawable_class->draw_arc = gdk_win32_draw_arc;
162 drawable_class->draw_polygon = gdk_win32_draw_polygon;
163 drawable_class->draw_text = gdk_win32_draw_text;
164 drawable_class->draw_text_wc = gdk_win32_draw_text_wc;
165 drawable_class->draw_drawable = gdk_win32_draw_drawable;
166 drawable_class->draw_points = gdk_win32_draw_points;
167 drawable_class->draw_segments = gdk_win32_draw_segments;
168 drawable_class->draw_lines = gdk_win32_draw_lines;
169 drawable_class->draw_glyphs = gdk_win32_draw_glyphs;
170 drawable_class->draw_image = gdk_win32_draw_image;
172 drawable_class->set_colormap = gdk_win32_set_colormap;
173 drawable_class->get_colormap = gdk_win32_get_colormap;
175 drawable_class->get_depth = gdk_win32_get_depth;
176 drawable_class->get_visual = gdk_win32_get_visual;
178 drawable_class->get_image = _gdk_win32_get_image;
182 gdk_drawable_impl_win32_finalize (GObject *object)
184 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
186 G_OBJECT_CLASS (parent_class)->finalize (object);
189 /*****************************************************
190 * Win32 specific implementations of generic functions *
191 *****************************************************/
194 gdk_win32_get_colormap (GdkDrawable *drawable)
196 GdkDrawableImplWin32 *impl;
198 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
200 return impl->colormap;
204 gdk_win32_set_colormap (GdkDrawable *drawable,
205 GdkColormap *colormap)
207 GdkDrawableImplWin32 *impl;
209 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
211 if (impl->colormap == colormap)
215 gdk_colormap_unref (impl->colormap);
216 impl->colormap = colormap;
218 gdk_colormap_ref (impl->colormap);
225 gdk_win32_draw_rectangle (GdkDrawable *drawable,
233 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
234 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
236 HGDIOBJ old_pen_or_brush;
240 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %#x (%p) %s%dx%d@+%d+%d\n",
241 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
243 (filled ? "fill " : ""),
244 width, height, x, y));
247 && (gc_private->tile)
248 && (gc_private->values_mask & GDK_GC_TILE)
249 && (gc_private->values_mask & GDK_GC_FILL))
251 _gdk_win32_draw_tiles (drawable, gc, gc_private->tile, x, y, width, height);
255 hdc = gdk_win32_hdc_get (drawable, gc, mask);
259 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
260 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
263 GetObject (hbr, sizeof (lbr), &lbr);
264 GetObject (hpen, sizeof (lpen), &lpen);
266 g_print ("current brush: style = %s, color = 0x%.08x\n",
267 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
269 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
270 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
276 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
278 if (!BeginPath (hdc))
279 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
281 /* Win9x doesn't support Rectangle calls in a path,
287 pts[1].x = x + width + 1;
289 pts[2].x = x + width + 1;
290 pts[2].y = y + height + 1;
292 pts[3].y = y + height + 1;
295 MoveToEx (hdc, x, y, NULL);
297 if (ok && !Polyline (hdc, pts, 4))
298 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
300 if (ok && !CloseFigure (hdc))
301 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
303 if (ok && !EndPath (hdc))
304 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
307 if (!WidenPath (hdc))
308 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
310 if (ok && !FillPath (hdc))
311 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
316 old_pen_or_brush = SelectObject (hdc, GetStockObject (NULL_PEN));
318 old_pen_or_brush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
320 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
321 WIN32_GDI_FAILED ("Rectangle");
323 SelectObject (hdc, old_pen_or_brush);
326 gdk_win32_hdc_release (drawable, gc, mask);
330 gdk_win32_draw_arc (GdkDrawable *drawable,
340 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
342 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
344 GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n",
345 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
346 x, y, width, height, angle1, angle2));
348 /* Seems that drawing arcs with width or height <= 2 fails, at least
351 if (width <= 2 || height <= 2 || angle2 == 0)
354 hdc = gdk_win32_hdc_get (drawable, gc, mask);
356 if (angle2 >= 360*64)
358 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
362 /* The 100. is just an arbitrary value */
363 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
364 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
365 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
366 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
370 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
371 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
372 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
373 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
376 /* GDK_OPAQUE_STIPPLED arcs not implemented. */
380 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
381 x, y, x+width, y+height,
382 nXStartArc, nYStartArc,
383 nXEndArc, nYEndArc));
384 if (!Pie (hdc, x, y, x+width, y+height,
385 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
386 WIN32_GDI_FAILED ("Pie");
390 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
391 x, y, x+width, y+height,
392 nXStartArc, nYStartArc,
393 nXEndArc, nYEndArc));
394 if (!Arc (hdc, x, y, x+width, y+height,
395 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
396 WIN32_GDI_FAILED ("Arc");
398 gdk_win32_hdc_release (drawable, gc, mask);
402 gdk_win32_draw_polygon (GdkDrawable *drawable,
408 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
409 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
415 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %#x (%p) %d\n",
416 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
423 hdc = gdk_win32_hdc_get (drawable, gc, mask);
424 pts = g_new (POINT, npoints+1);
426 for (i = 0; i < npoints; i++)
428 pts[i].x = points[i].x;
429 pts[i].y = points[i].y;
432 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
434 if (!BeginPath (hdc))
435 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
438 MoveToEx (hdc, points[0].x, points[0].y, NULL);
440 if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y)
443 if (ok && !Polyline (hdc, pts, 4))
444 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
446 if (ok && !CloseFigure (hdc))
447 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
449 if (ok && !EndPath (hdc))
450 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
453 if (!WidenPath (hdc))
454 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
456 if (ok && !FillPath (hdc))
457 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
461 if (points[0].x != points[npoints-1].x
462 || points[0].y != points[npoints-1].y)
464 pts[npoints].x = points[0].x;
465 pts[npoints].y = points[0].y;
471 if (!Polygon (hdc, pts, npoints))
472 WIN32_GDI_FAILED ("Polygon");
476 if (!Polyline (hdc, pts, npoints))
477 WIN32_GDI_FAILED ("Polyline");
481 gdk_win32_hdc_release (drawable, gc, mask);
491 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
492 const wchar_t *wcstr,
498 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
503 if ((oldfont = SelectObject (argp->hdc, singlefont->hfont)) == NULL)
505 WIN32_GDI_FAILED ("SelectObject");
509 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
510 WIN32_GDI_FAILED ("TextOutW");
511 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
514 SelectObject (argp->hdc, oldfont);
518 gdk_win32_draw_text (GdkDrawable *drawable,
526 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
529 gdk_draw_text_arg arg;
531 if (text_length == 0)
534 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
538 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
540 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
541 (guint) GDK_DRAWABLE_HANDLE (drawable),
543 (text_length > 10 ? 10 : text_length),
546 if (text_length == 1)
548 /* For single characters, don't try to interpret as UTF-8. */
549 wc = (guchar) text[0];
550 _gdk_wchar_text_handle (font, &wc, 1, gdk_draw_text_handler, &arg);
554 wcstr = g_new (wchar_t, text_length);
555 if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
556 g_warning ("gdk_win32_draw_text: _gdk_win32_nmbstowchar_ts failed");
558 _gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
563 gdk_win32_hdc_release (drawable, gc, mask);
567 gdk_win32_draw_text_wc (GdkDrawable *drawable,
572 const GdkWChar *text,
575 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
578 gdk_draw_text_arg arg;
580 if (text_length == 0)
583 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
587 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
589 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
590 (guint) GDK_DRAWABLE_HANDLE (drawable),
593 if (sizeof (wchar_t) != sizeof (GdkWChar))
595 wcstr = g_new (wchar_t, text_length);
596 for (i = 0; i < text_length; i++)
600 wcstr = (wchar_t *) text;
602 _gdk_wchar_text_handle (font, wcstr, text_length,
603 gdk_draw_text_handler, &arg);
605 if (sizeof (wchar_t) != sizeof (GdkWChar))
608 gdk_win32_hdc_release (drawable, gc, mask);
612 gdk_win32_draw_drawable (GdkDrawable *drawable,
625 HRGN src_rgn, draw_rgn, outside_rgn;
627 gint src_width, src_height;
629 GdkDrawableImplWin32 *impl;
632 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
633 if (GDK_IS_DRAWABLE_IMPL_WIN32(src))
634 src_handle = GDK_DRAWABLE_IMPL_WIN32 (src)->handle;
636 src_handle = GDK_DRAWABLE_HANDLE (src);
638 GDK_NOTE (MISC, g_print ("gdk_win32_draw_drawable: dest: %#x @+%d+%d"
639 " src: %#x %dx%d@+%d+%d\n",
640 (guint) impl->handle,
643 width, height, xsrc, ysrc));
645 hdc = gdk_win32_hdc_get (drawable, gc, 0);
647 gdk_drawable_get_size (src, &src_width, &src_height);
648 src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1);
649 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
651 #if 0 /* HB: I dont't see reason to do this ... */
652 if (GDK_IS_WINDOW_IMPL_WIN32 (drawable))
654 /* If we are drawing on a window, calculate the region that is
655 * outside the source pixmap, and invalidate that, causing it to
659 outside_rgn = CreateRectRgnIndirect (&r);
660 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
662 if (ERROR == OffsetRgn (outside_rgn, xdest, ydest))
663 WIN32_GDI_FAILED ("OffsetRgn");
664 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
665 g_print ("...calling InvalidateRgn, "
666 "bbox: %ldx%ld@+%ld+%ld\n",
667 r.right - r.left - 1, r.bottom - r.top - 1,
669 if (!InvalidateRgn (impl->handle, outside_rgn, TRUE))
670 WIN32_GDI_FAILED ("InvalidateRgn");
672 if (!DeleteObject (outside_rgn))
673 WIN32_GDI_FAILED ("DeleteObject");
677 #if 1 /* Don't know if this is necessary */
678 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
679 g_warning ("gdk_win32_draw_drawable: CombineRgn returned a COMPLEXREGION");
681 if (0 == GetRgnBox (draw_rgn, &r))
682 WIN32_GDI_FAILED("GetRgnBox");
685 || r.right != xsrc + width + 1
686 || r.bottom != ysrc + height + 1)
688 xdest += r.left - xsrc;
690 ydest += r.top - ysrc;
692 width = r.right - xsrc - 1;
693 height = r.bottom - ysrc - 1;
695 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
697 width, height, xsrc, ysrc,
702 if (!DeleteObject (src_rgn))
703 WIN32_GDI_FAILED ("DeleteObject");
704 if (!DeleteObject (draw_rgn))
705 WIN32_GDI_FAILED ("DeleteObject");
707 /* This function is called also to bitblt from a window.
709 if (GDK_IS_PIXMAP_IMPL_WIN32 (src) || GDK_IS_PIXMAP(src))
711 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
712 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
714 if (ok && (hgdiobj = SelectObject (srcdc, src_handle)) == NULL)
715 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
717 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
718 srcdc, xsrc, ysrc, SRCCOPY))
719 WIN32_GDI_FAILED ("BitBlt");
721 if (ok && (SelectObject (srcdc, hgdiobj) == NULL))
722 WIN32_GDI_FAILED ("SelectObject");
724 if (srcdc != NULL && !DeleteDC (srcdc))
725 WIN32_GDI_FAILED ("DeleteDC");
727 else if (impl->handle == src_handle)
729 /* Blitting inside a window, use ScrollDC */
730 RECT scrollRect, clipRect, emptyRect;
733 scrollRect.left = MIN (xsrc, xdest);
734 scrollRect.top = MIN (ysrc, ydest);
735 scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
736 scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
738 clipRect.left = xdest;
739 clipRect.top = ydest;
740 clipRect.right = xdest + width + 1;
741 clipRect.bottom = ydest + height + 1;
743 SetRectEmpty (&emptyRect);
744 updateRgn = CreateRectRgnIndirect (&emptyRect);
745 if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
746 &scrollRect, &clipRect,
748 WIN32_GDI_FAILED ("ScrollDC"), ok = FALSE;
749 if (ok && !InvalidateRgn (impl->handle, updateRgn, FALSE))
750 WIN32_GDI_FAILED ("InvalidateRgn"), ok = FALSE;
751 if (ok && !UpdateWindow (impl->handle))
752 WIN32_GDI_FAILED ("UpdateWindow");
753 if (!DeleteObject (updateRgn))
754 WIN32_GDI_FAILED ("DeleteObject");
758 if ((srcdc = GetDC (src_handle)) == NULL)
759 WIN32_GDI_FAILED ("GetDC"), ok = FALSE;
761 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
762 srcdc, xsrc, ysrc, SRCCOPY))
763 WIN32_GDI_FAILED ("BitBlt");
764 if (ok && !ReleaseDC (src_handle, srcdc))
765 WIN32_GDI_FAILED ("ReleaseDC");
767 gdk_win32_hdc_release (drawable, gc, 0);
771 _gdk_win32_draw_tiles (GdkDrawable *drawable,
779 gint x = x_from, y = y_from;
780 gint tile_width, tile_height;
783 gdk_drawable_get_size (drawable, &width, &height);
784 gdk_drawable_get_size (tile, &tile_width, &tile_height);
786 width = MIN (width, max_width);
787 height = MIN (height, max_height);
789 tile_width = MIN (tile_width, max_width);
790 tile_height = MIN (tile_height, max_height);
797 gdk_win32_draw_drawable (drawable, gc, tile,
798 x % tile_width, /* xsrc */
799 y % tile_height, /* ysrc */
801 tile_width, tile_height);
809 gdk_win32_draw_points (GdkDrawable *drawable,
816 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
817 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
820 hdc = gdk_win32_hdc_get (drawable, gc, 0);
822 fg = _gdk_win32_colormap_color (impl->colormap, gc_private->foreground);
824 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x %dx%.06x\n",
825 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
826 npoints, (guint) fg));
828 for (i = 0; i < npoints; i++)
829 SetPixel (hdc, points[i].x, points[i].y, fg);
831 gdk_win32_hdc_release (drawable, gc, 0);
835 gdk_win32_draw_segments (GdkDrawable *drawable,
840 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
841 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
846 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %#x nsegs: %d\n",
847 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle, nsegs));
849 hdc = gdk_win32_hdc_get (drawable, gc, mask);
851 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
853 if (!BeginPath (hdc))
854 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
856 for (i = 0; ok && i < nsegs; i++)
858 if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
859 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
860 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
861 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
864 if (ok && gc_private->pen_width <= 1)
865 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
866 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
869 if (ok && !EndPath (hdc))
870 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
872 if (ok && !WidenPath (hdc))
873 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
875 if (ok && !FillPath (hdc))
876 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
880 const gboolean maybe_patblt =
881 gc_private->rop2 == R2_COPYPEN &&
882 gc_private->pen_width <= 1 &&
883 (gc_private->pen_style & PS_STYLE_MASK) == PS_SOLID;
885 for (i = 0; ok && i < nsegs; i++)
887 /* PatBlt() is much faster than LineTo(), says
888 * jpe@archaeopteryx.com. Hmm. Use it if we have a solid
889 * colour pen, then we know that the brush is also solid and
890 * of the same colour.
892 if (maybe_patblt && segs[i].x1 == segs[i].x2)
896 if (segs[i].y1 <= segs[i].y2)
897 y1 = segs[i].y1, y2 = segs[i].y2;
899 y1 = segs[i].y2, y2 = segs[i].y1;
901 if (!PatBlt (hdc, segs[i].x1, y1,
902 1, y2 - y1 + 1, PATCOPY))
903 WIN32_GDI_FAILED ("PatBlt"), ok = FALSE;
905 else if (maybe_patblt && segs[i].y1 == segs[i].y2)
909 if (segs[i].x1 <= segs[i].x2)
910 x1 = segs[i].x1, x2 = segs[i].x2;
912 x1 = segs[i].x2, x2 = segs[i].x1;
914 if (!PatBlt (hdc, x1, segs[i].y1,
915 x2 - x1 + 1, 1, PATCOPY))
916 WIN32_GDI_FAILED ("PatBlt"), ok = FALSE;
920 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
921 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
922 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
923 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
926 if (ok && gc_private->pen_width <= 1)
927 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
928 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
932 gdk_win32_hdc_release (drawable, gc, mask);
936 gdk_win32_draw_lines (GdkDrawable *drawable,
941 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
942 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
951 hdc = gdk_win32_hdc_get (drawable, gc, mask);
953 pts = g_new (POINT, npoints);
955 for (i = 0; i < npoints; i++)
957 pts[i].x = points[i].x;
958 pts[i].y = points[i].y;
961 if (!Polyline (hdc, pts, npoints))
962 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
967 if (ok && gc_private->pen_width <= 1)
969 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
970 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
971 WIN32_GDI_FAILED ("LineTo");
973 gdk_win32_hdc_release (drawable, gc, mask);
977 gdk_win32_draw_glyphs (GdkDrawable *drawable,
982 PangoGlyphString *glyphs)
984 const GdkGCValuesMask mask = GDK_GC_FOREGROUND;
987 hdc = gdk_win32_hdc_get (drawable, gc, mask);
989 /* HB: Maybe there should be a GDK_GC_PANGO flag for hdc_get */
990 /* default write mode is transparent (leave background) */
991 if (SetBkMode (hdc, TRANSPARENT) == 0)
992 WIN32_GDI_FAILED ("SetBkMode");
994 if (GDI_ERROR == SetTextAlign (hdc, TA_LEFT|TA_BASELINE|TA_NOUPDATECP))
995 WIN32_GDI_FAILED ("SetTextAlign");
997 pango_win32_render (hdc, font, glyphs, x, y);
999 gdk_win32_hdc_release (drawable, gc, mask);
1003 gdk_win32_draw_image (GdkDrawable *drawable,
1013 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
1014 GdkImagePrivateWin32 *image_private = IMAGE_PRIVATE_DATA (image);
1015 GdkColormapPrivateWin32 *colormap_private = (GdkColormapPrivateWin32 *) impl->colormap;
1020 BITMAPINFOHEADER bmiHeader;
1021 WORD bmiIndices[256];
1023 static gboolean bmi_inited = FALSE;
1027 hdc = gdk_win32_hdc_get (drawable, gc, 0);
1029 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR &&
1030 colormap_private && colormap_private->xcolormap->rc_palette)
1034 for (i = 0; i < 256; i++)
1035 bmi.bmiIndices[i] = i;
1039 if (GetObject (image_private->hbitmap, sizeof (DIBSECTION),
1040 &ds) != sizeof (DIBSECTION))
1041 WIN32_GDI_FAILED ("GetObject"), ok = FALSE;
1043 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
1044 xdest, ydest, xsrc, ysrc, width, height);
1045 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
1046 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
1047 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
1048 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
1050 bmi.bmiHeader = ds.dsBmih;
1051 /* I have spent hours on getting the parameters to
1052 * SetDIBitsToDevice right. I wonder what drugs the guys in
1053 * Redmond were on when they designed this API.
1055 if (ok && SetDIBitsToDevice (hdc,
1058 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
1059 0, -ds.dsBmih.biHeight,
1061 (CONST BITMAPINFO *) &bmi,
1062 DIB_PAL_COLORS) == 0)
1063 WIN32_GDI_FAILED ("SetDIBitsToDevice");
1068 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
1069 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
1071 if (ok && (oldbitmap = SelectObject (memdc, image_private->hbitmap)) == NULL)
1072 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
1074 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
1075 memdc, xsrc, ysrc, SRCCOPY))
1076 WIN32_GDI_FAILED ("BitBlt");
1078 if (oldbitmap != NULL && SelectObject (memdc, oldbitmap) == NULL)
1079 WIN32_GDI_FAILED ("SelectObject");
1081 if (memdc != NULL && !DeleteDC (memdc))
1082 WIN32_GDI_FAILED ("DeleteDC");
1084 gdk_win32_hdc_release (drawable, gc, 0);
1088 gdk_win32_get_depth (GdkDrawable *drawable)
1090 /* This is a bit bogus but I'm not sure the other way is better */
1092 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1096 gdk_win32_get_visual (GdkDrawable *drawable)
1098 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
1102 gdk_win32_drawable_get_handle (GdkDrawable *drawable)
1104 return GDK_DRAWABLE_HANDLE(drawable);