1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #define G_PI 3.14159265358979323846
36 #include "gdkinternals.h"
37 #include "gdkprivate-win32.h"
39 static void gdk_win32_drawable_destroy (GdkDrawable *drawable);
41 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
48 static void gdk_win32_draw_arc (GdkDrawable *drawable,
57 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
62 static void gdk_win32_draw_text (GdkDrawable *drawable,
69 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
76 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
85 static void gdk_win32_draw_points (GdkDrawable *drawable,
89 static void gdk_win32_draw_segments (GdkDrawable *drawable,
93 static void gdk_win32_draw_lines (GdkDrawable *drawable,
98 GdkDrawableClass _gdk_win32_drawable_class = {
99 gdk_win32_drawable_destroy,
101 gdk_win32_draw_rectangle,
103 gdk_win32_draw_polygon,
105 gdk_win32_draw_text_wc,
106 gdk_win32_draw_drawable,
107 gdk_win32_draw_points,
108 gdk_win32_draw_segments,
112 /*****************************************************
113 * Win32 specific implementations of generic functions *
114 *****************************************************/
117 gdk_drawable_get_colormap (GdkDrawable *drawable)
119 GdkDrawablePrivate *drawable_private;
121 g_return_val_if_fail (drawable != NULL, NULL);
122 drawable_private = (GdkDrawablePrivate*) drawable;
124 if (!GDK_DRAWABLE_DESTROYED (drawable))
126 if (drawable_private->colormap == NULL)
127 return gdk_colormap_get_system (); /* XXX ??? */
129 return drawable_private->colormap;
136 gdk_drawable_set_colormap (GdkDrawable *drawable,
137 GdkColormap *colormap)
139 GdkDrawablePrivate *drawable_private;
140 GdkColormapPrivateWin32 *colormap_private;
142 g_return_if_fail (drawable != NULL);
143 g_return_if_fail (colormap != NULL);
145 drawable_private = (GdkDrawablePrivate *) drawable;
146 colormap_private = (GdkColormapPrivateWin32 *) colormap;
148 if (!GDK_DRAWABLE_DESTROYED (drawable))
150 if (GDK_IS_WINDOW (drawable))
152 g_return_if_fail (colormap_private->base.visual !=
153 ((GdkColormapPrivate *) (drawable_private->colormap))->visual);
155 GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n",
156 GDK_DRAWABLE_XID (drawable),
157 colormap_private->xcolormap));
159 if (drawable_private->colormap)
160 gdk_colormap_unref (drawable_private->colormap);
161 drawable_private->colormap = colormap;
162 gdk_colormap_ref (drawable_private->colormap);
164 if (GDK_IS_WINDOW (drawable)
165 && drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
166 gdk_window_add_colormap_windows (drawable);
173 gdk_win32_drawable_destroy (GdkDrawable *drawable)
179 gdk_win32_draw_rectangle (GdkDrawable *drawable,
187 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
188 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
190 HGDIOBJ oldpen, oldbrush;
195 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
196 GDK_DRAWABLE_XID (drawable),
198 (filled ? "fill " : ""),
199 width, height, x, y));
201 hdc = gdk_gc_predraw (drawable, gc_private,
202 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
206 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
207 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
210 GetObject (hbr, sizeof (lbr), &lbr);
211 GetObject (hpen, sizeof (lpen), &lpen);
213 g_print ("current brush: style = %s, color = 0x%.08x\n",
214 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
216 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
217 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
223 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
225 if (!BeginPath (hdc))
226 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
228 /* Win9x doesn't support Rectangle calls in a path,
234 pts[1].x = x + width + 1;
236 pts[2].x = x + width + 1;
237 pts[2].y = y + height + 1;
239 pts[3].y = y + height + 1;
242 MoveToEx (hdc, x, y, NULL);
244 if (ok && !Polyline (hdc, pts, 4))
245 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
247 if (ok && !CloseFigure (hdc))
248 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
250 if (ok && !EndPath (hdc))
251 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
254 if (!WidenPath (hdc))
255 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
257 if (ok && !FillPath (hdc))
258 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
261 if (!DeleteObject (hbr))
262 WIN32_GDI_FAILED ("DeleteObject");
267 oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
269 oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
271 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
272 WIN32_GDI_FAILED ("Rectangle");
275 SelectObject (hdc, oldpen);
277 SelectObject (hdc, oldbrush);
280 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
284 gdk_win32_draw_arc (GdkDrawable *drawable,
294 GdkGCPrivate *gc_private;
296 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
298 gc_private = (GdkGCPrivate*) gc;
300 GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n",
301 GDK_DRAWABLE_XID (drawable),
302 x, y, width, height, angle1, angle2));
304 if (width != 0 && height != 0 && angle2 != 0)
306 hdc = gdk_gc_predraw (drawable, gc_private,
307 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
309 if (angle2 >= 360*64)
311 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
315 /* The 100. is just an arbitrary value */
316 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
317 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
318 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
319 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
323 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
324 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
325 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
326 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
329 /* GDK_OPAQUE_STIPPLED arcs not implemented. */
333 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
334 x, y, x+width, y+height,
335 nXStartArc, nYStartArc,
336 nXEndArc, nYEndArc));
337 if (!Pie (hdc, x, y, x+width, y+height,
338 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
339 WIN32_GDI_FAILED ("Pie");
343 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
344 x, y, x+width, y+height,
345 nXStartArc, nYStartArc,
346 nXEndArc, nYEndArc));
347 if (!Arc (hdc, x, y, x+width, y+height,
348 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
349 WIN32_GDI_FAILED ("Arc");
351 gdk_gc_postdraw (drawable, gc_private,
352 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
357 gdk_win32_draw_polygon (GdkDrawable *drawable,
363 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
364 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
371 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %#x (%d) %d\n",
372 GDK_DRAWABLE_XID (drawable), gc_private,
378 hdc = gdk_gc_predraw (drawable, gc_private,
379 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
380 pts = g_new (POINT, npoints+1);
382 for (i = 0; i < npoints; i++)
384 pts[i].x = points[i].x;
385 pts[i].y = points[i].y;
388 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
390 if (!BeginPath (hdc))
391 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
393 MoveToEx (hdc, points[0].x, points[0].y, NULL);
395 if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y)
398 if (ok && !Polyline (hdc, pts, 4))
399 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
401 if (ok && !CloseFigure (hdc))
402 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
404 if (ok && !EndPath (hdc))
405 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
408 if (!WidenPath (hdc))
409 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
411 if (ok && !FillPath (hdc))
412 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
415 if (!DeleteObject (hbr))
416 WIN32_GDI_FAILED ("DeleteObject");
420 if (points[0].x != points[npoints-1].x
421 || points[0].y != points[npoints-1].y)
423 pts[npoints].x = points[0].x;
424 pts[npoints].y = points[0].y;
430 if (!Polygon (hdc, pts, npoints))
431 WIN32_GDI_FAILED ("Polygon");
435 if (!Polyline (hdc, pts, npoints))
436 WIN32_GDI_FAILED ("Polyline");
440 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
450 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
451 const wchar_t *wcstr,
457 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
462 if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL)
464 WIN32_GDI_FAILED ("SelectObject");
468 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
469 WIN32_GDI_FAILED ("TextOutW");
470 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
473 SelectObject (argp->hdc, oldfont);
477 gdk_win32_draw_text (GdkDrawable *drawable,
485 GdkGCPrivate *gc_private;
488 gdk_draw_text_arg arg;
491 if (GDK_DRAWABLE_DESTROYED (drawable))
494 if (text_length == 0)
497 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
499 gc_private = (GdkGCPrivate*) gc;
503 arg.hdc = gdk_gc_predraw (drawable, gc_private,
504 GDK_GC_FOREGROUND|GDK_GC_FONT);
506 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
507 GDK_DRAWABLE_XID (drawable),
509 (text_length > 10 ? 10 : text_length),
512 wcstr = g_new (wchar_t, text_length);
513 if (text_length == 1)
515 /* For single characters, don't try to interpret as UTF-8. */
516 wcstr[0] = (guchar) text[0];
517 gdk_wchar_text_handle (font, wcstr, 1, gdk_draw_text_handler, &arg);
521 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
522 g_warning ("gdk_win32_draw_text: gdk_nmbstowchar_ts failed");
524 gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
529 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT);
533 gdk_win32_draw_text_wc (GdkDrawable *drawable,
538 const GdkWChar *text,
541 GdkGCPrivate *gc_private;
544 gdk_draw_text_arg arg;
547 if (GDK_DRAWABLE_DESTROYED (drawable))
550 if (text_length == 0)
553 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
555 gc_private = (GdkGCPrivate*) gc;
559 arg.hdc = gdk_gc_predraw (drawable, gc_private,
560 GDK_GC_FOREGROUND|GDK_GC_FONT);
562 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
563 GDK_DRAWABLE_XID (drawable),
566 if (sizeof (wchar_t) != sizeof (GdkWChar))
568 wcstr = g_new (wchar_t, text_length);
569 for (i = 0; i < text_length; i++)
573 wcstr = (wchar_t *) text;
575 gdk_wchar_text_handle (font, wcstr, text_length,
576 gdk_draw_text_handler, &arg);
578 if (sizeof (wchar_t) != sizeof (GdkWChar))
581 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT);
585 gdk_win32_draw_drawable (GdkDrawable *drawable,
595 GdkDrawablePrivate *src_private;
596 GdkGCPrivate *gc_private;
600 HRGN src_rgn, draw_rgn, outside_rgn;
603 src_private = (GdkDrawablePrivate*) src;
604 gc_private = (GdkGCPrivate*) gc;
606 GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
607 "src: %#x %dx%d@+%d+%d"
608 " dest: %#x @+%d+%d\n",
609 GDK_DRAWABLE_XID (drawable),
610 GDK_DRAWABLE_XID (src),
611 width, height, xsrc, ysrc,
612 GDK_DRAWABLE_XID (drawable), xdest, ydest));
614 hdc = gdk_gc_predraw (drawable, gc_private, 0);
616 src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
617 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
619 outside_rgn = CreateRectRgnIndirect (&r);
621 if (GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_PIXMAP)
623 /* If we are drawing on a window, calculate the region that is
624 * outside the source pixmap, and invalidate that, causing it to
627 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
629 OffsetRgn (outside_rgn, xdest, ydest);
630 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
631 g_print ("...calling InvalidateRgn, "
632 "bbox: %dx%d@+%d+%d\n",
633 r.right - r.left - 1, r.bottom - r.top - 1,
635 InvalidateRgn (GDK_DRAWABLE_XID (drawable), outside_rgn, TRUE);
639 #if 1 /* Don't know if this is necessary */
640 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
641 g_warning ("gdk_win32_draw_drawable: CombineRgn returned a COMPLEXREGION");
643 GetRgnBox (draw_rgn, &r);
646 || r.right != xsrc + width + 1
647 || r.bottom != ysrc + height + 1)
649 xdest += r.left - xsrc;
651 ydest += r.top - ysrc;
653 width = r.right - xsrc - 1;
654 height = r.bottom - ysrc - 1;
656 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
658 width, height, xsrc, ysrc,
663 DeleteObject (src_rgn);
664 DeleteObject (draw_rgn);
665 DeleteObject (outside_rgn);
667 /* Strangely enough, this function is called also to bitblt
670 if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
672 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
673 WIN32_GDI_FAILED ("CreateCompatibleDC");
675 if ((hgdiobj = SelectObject (srcdc, GDK_DRAWABLE_XID (src))) == NULL)
676 WIN32_GDI_FAILED ("SelectObject");
678 if (!BitBlt (hdc, xdest, ydest, width, height,
679 srcdc, xsrc, ysrc, SRCCOPY))
680 WIN32_GDI_FAILED ("BitBlt");
682 if ((SelectObject (srcdc, hgdiobj) == NULL))
683 WIN32_GDI_FAILED ("SelectObject");
685 if (!DeleteDC (srcdc))
686 WIN32_GDI_FAILED ("DeleteDC");
690 if (GDK_DRAWABLE_XID(drawable) == GDK_DRAWABLE_XID (src))
692 /* Blitting inside a window, use ScrollDC */
693 RECT scrollRect, clipRect, emptyRect;
696 scrollRect.left = MIN (xsrc, xdest);
697 scrollRect.top = MIN (ysrc, ydest);
698 scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
699 scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
701 clipRect.left = xdest;
702 clipRect.top = ydest;
703 clipRect.right = xdest + width + 1;
704 clipRect.bottom = ydest + height + 1;
706 SetRectEmpty (&emptyRect);
707 updateRgn = CreateRectRgnIndirect (&emptyRect);
708 if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
709 &scrollRect, &clipRect,
711 WIN32_GDI_FAILED ("ScrollDC");
712 if (!InvalidateRgn (GDK_DRAWABLE_XID (drawable), updateRgn, FALSE))
713 WIN32_GDI_FAILED ("InvalidateRgn");
714 if (!UpdateWindow (GDK_DRAWABLE_XID (drawable)))
715 WIN32_GDI_FAILED ("UpdateWindow");
719 if ((srcdc = GetDC (GDK_DRAWABLE_XID (src))) == NULL)
720 WIN32_GDI_FAILED ("GetDC");
722 if (!BitBlt (hdc, xdest, ydest, width, height,
723 srcdc, xsrc, ysrc, SRCCOPY))
724 WIN32_GDI_FAILED ("BitBlt");
725 ReleaseDC (GDK_DRAWABLE_XID (src), srcdc);
728 gdk_gc_postdraw (drawable, gc_private, 0);
732 gdk_win32_draw_points (GdkDrawable *drawable,
739 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
740 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
741 GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
742 GdkColormapPrivateWin32 *colormap_private =
743 (GdkColormapPrivateWin32 *) drawable_private->colormap;
746 hdc = gdk_gc_predraw (drawable, gc_private, 0);
748 fg = gdk_colormap_color (colormap_private, gc_data->foreground);
750 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x %dx%.06x\n",
751 GDK_DRAWABLE_XID (drawable), npoints, fg));
753 for (i = 0; i < npoints; i++)
754 SetPixel (hdc, points[i].x, points[i].y, fg);
756 gdk_gc_postdraw (drawable, gc_private, 0);
760 gdk_win32_draw_segments (GdkDrawable *drawable,
765 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
766 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
772 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %#x nsegs: %d\n",
773 GDK_DRAWABLE_XID (drawable), nsegs));
775 hdc = gdk_gc_predraw (drawable, gc_private,
776 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
778 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
780 if (!BeginPath (hdc))
781 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
783 for (i = 0; i < nsegs; i++)
785 if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
786 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
787 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
788 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
791 if (ok && gc_data->pen_width == 1)
792 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
793 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
796 if (ok && !EndPath (hdc))
797 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
799 if (ok && !WidenPath (hdc))
800 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
802 if (ok && !FillPath (hdc))
803 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
806 if (!DeleteObject (hbr))
807 WIN32_GDI_FAILED ("DeleteObject");
811 for (i = 0; i < nsegs; i++)
813 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
814 WIN32_GDI_FAILED ("MoveToEx");
815 if (!LineTo (hdc, segs[i].x2, segs[i].y2))
816 WIN32_GDI_FAILED ("LineTo");
819 if (gc_data->pen_width == 1)
820 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
821 WIN32_GDI_FAILED ("LineTo");
824 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
828 gdk_win32_draw_lines (GdkDrawable *drawable,
833 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
834 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
842 hdc = gdk_gc_predraw (drawable, gc_private,
843 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
845 pts = g_new (POINT, npoints);
847 for (i = 0; i < npoints; i++)
849 pts[i].x = points[i].x;
850 pts[i].y = points[i].y;
853 if (!Polyline (hdc, pts, npoints))
854 WIN32_GDI_FAILED ("Polyline");
859 if (gc_data->pen_width == 1)
861 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
862 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
863 WIN32_GDI_FAILED ("LineTo");
866 MoveToEx (hdc, points[0].x, points[0].y, NULL);
867 for (i = 1; i < npoints; i++)
868 if (!LineTo (hdc, points[i].x, points[i].y))
869 WIN32_GDI_FAILED ("LineTo");
872 /* LineTo doesn't draw the last point, so if we have a pen width of 1,
873 * we draw the end pixel separately... With wider pens we don't care.
874 * //HB: But the NT developers don't read their API documentation ...
876 if (gc_data->pen_width == 1 && windows_version > 0x80000000)
877 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
878 WIN32_GDI_FAILED ("LineTo");
880 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);