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 "gdkdrawable.h"
37 #include "gdkprivate.h"
38 #include "gdkwindow.h"
41 static void gdk_win32_drawable_destroy (GdkDrawable *drawable);
43 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
50 static void gdk_win32_draw_arc (GdkDrawable *drawable,
59 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
64 static void gdk_win32_draw_text (GdkDrawable *drawable,
71 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
78 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
87 static void gdk_win32_draw_points (GdkDrawable *drawable,
91 static void gdk_win32_draw_segments (GdkDrawable *drawable,
95 static void gdk_win32_draw_lines (GdkDrawable *drawable,
100 GdkDrawableClass _gdk_win32_drawable_class = {
101 gdk_win32_drawable_destroy,
103 gdk_win32_draw_rectangle,
105 gdk_win32_draw_polygon,
107 gdk_win32_draw_text_wc,
108 gdk_win32_draw_drawable,
109 gdk_win32_draw_points,
110 gdk_win32_draw_segments,
114 /*****************************************************
115 * Win32 specific implementations of generic functions *
116 *****************************************************/
119 gdk_drawable_get_colormap (GdkDrawable *drawable)
121 GdkDrawablePrivate *drawable_private;
123 g_return_val_if_fail (drawable != NULL, NULL);
124 drawable_private = (GdkDrawablePrivate*) drawable;
126 if (!GDK_DRAWABLE_DESTROYED (drawable))
128 if (drawable_private->colormap == NULL)
129 return gdk_colormap_get_system (); /* XXX ??? */
131 return drawable_private->colormap;
138 gdk_drawable_set_colormap (GdkDrawable *drawable,
139 GdkColormap *colormap)
141 GdkDrawablePrivate *drawable_private;
142 GdkColormapPrivateWin32 *colormap_private;
144 g_return_if_fail (drawable != NULL);
145 g_return_if_fail (colormap != NULL);
147 drawable_private = (GdkDrawablePrivate *) drawable;
148 colormap_private = (GdkColormapPrivateWin32 *) colormap;
150 if (!GDK_DRAWABLE_DESTROYED (drawable))
152 if (GDK_IS_WINDOW (drawable))
154 g_return_if_fail (colormap_private->base.visual !=
155 ((GdkColormapPrivate *) (drawable_private->colormap))->visual);
157 GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n",
158 GDK_DRAWABLE_XID (drawable),
159 colormap_private->xcolormap));
161 if (drawable_private->colormap)
162 gdk_colormap_unref (drawable_private->colormap);
163 drawable_private->colormap = colormap;
164 gdk_colormap_ref (drawable_private->colormap);
166 if (GDK_IS_WINDOW (drawable)
167 && drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
168 gdk_window_add_colormap_windows (drawable);
175 gdk_win32_drawable_destroy (GdkDrawable *drawable)
181 gdk_win32_draw_rectangle (GdkDrawable *drawable,
189 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
190 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
192 HGDIOBJ oldpen, oldbrush;
197 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
198 GDK_DRAWABLE_XID (drawable),
200 (filled ? "fill " : ""),
201 width, height, x, y));
203 hdc = gdk_gc_predraw (drawable, gc_private,
204 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
208 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
209 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
212 GetObject (hbr, sizeof (lbr), &lbr);
213 GetObject (hpen, sizeof (lpen), &lpen);
215 g_print ("current brush: style = %s, color = 0x%.08x\n",
216 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
218 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
219 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
225 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
227 if (!BeginPath (hdc))
228 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
230 /* Win9x doesn't support Rectangle calls in a path,
236 pts[1].x = x + width + 1;
238 pts[2].x = x + width + 1;
239 pts[2].y = y + height + 1;
241 pts[3].y = y + height + 1;
244 MoveToEx (hdc, x, y, NULL);
246 if (ok && !Polyline (hdc, pts, 4))
247 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
249 if (ok && !CloseFigure (hdc))
250 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
252 if (ok && !EndPath (hdc))
253 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
256 if (!WidenPath (hdc))
257 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
259 if (ok && !FillPath (hdc))
260 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
263 if (!DeleteObject (hbr))
264 WIN32_GDI_FAILED ("DeleteObject");
269 oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
271 oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
273 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
274 WIN32_GDI_FAILED ("Rectangle");
277 SelectObject (hdc, oldpen);
279 SelectObject (hdc, oldbrush);
282 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
286 gdk_win32_draw_arc (GdkDrawable *drawable,
296 GdkGCPrivate *gc_private;
298 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
300 gc_private = (GdkGCPrivate*) gc;
302 GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n",
303 GDK_DRAWABLE_XID (drawable),
304 x, y, width, height, angle1, angle2));
306 if (width != 0 && height != 0 && angle2 != 0)
308 hdc = gdk_gc_predraw (drawable, gc_private,
309 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
311 if (angle2 >= 360*64)
313 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
317 /* The 100. is just an arbitrary value */
318 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
319 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
320 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
321 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
325 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
326 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
327 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
328 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
331 /* GDK_OPAQUE_STIPPLED arcs not implemented. */
335 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
336 x, y, x+width, y+height,
337 nXStartArc, nYStartArc,
338 nXEndArc, nYEndArc));
339 if (!Pie (hdc, x, y, x+width, y+height,
340 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
341 WIN32_GDI_FAILED ("Pie");
345 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
346 x, y, x+width, y+height,
347 nXStartArc, nYStartArc,
348 nXEndArc, nYEndArc));
349 if (!Arc (hdc, x, y, x+width, y+height,
350 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
351 WIN32_GDI_FAILED ("Arc");
353 gdk_gc_postdraw (drawable, gc_private,
354 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
359 gdk_win32_draw_polygon (GdkDrawable *drawable,
365 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
366 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
373 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %#x (%d) %d\n",
374 GDK_DRAWABLE_XID (drawable), gc_private,
380 hdc = gdk_gc_predraw (drawable, gc_private,
381 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
382 pts = g_new (POINT, npoints+1);
384 for (i = 0; i < npoints; i++)
386 pts[i].x = points[i].x;
387 pts[i].y = points[i].y;
390 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
392 if (!BeginPath (hdc))
393 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
395 MoveToEx (hdc, points[0].x, points[0].y, NULL);
397 if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y)
400 if (ok && !Polyline (hdc, pts, 4))
401 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
403 if (ok && !CloseFigure (hdc))
404 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
406 if (ok && !EndPath (hdc))
407 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
410 if (!WidenPath (hdc))
411 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
413 if (ok && !FillPath (hdc))
414 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
417 if (!DeleteObject (hbr))
418 WIN32_GDI_FAILED ("DeleteObject");
422 if (points[0].x != points[npoints-1].x
423 || points[0].y != points[npoints-1].y)
425 pts[npoints].x = points[0].x;
426 pts[npoints].y = points[0].y;
432 if (!Polygon (hdc, pts, npoints))
433 WIN32_GDI_FAILED ("Polygon");
437 if (!Polyline (hdc, pts, npoints))
438 WIN32_GDI_FAILED ("Polyline");
442 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
452 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
453 const wchar_t *wcstr,
459 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
464 if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL)
466 WIN32_GDI_FAILED ("SelectObject");
470 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
471 WIN32_GDI_FAILED ("TextOutW");
472 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
475 SelectObject (argp->hdc, oldfont);
479 gdk_win32_draw_text (GdkDrawable *drawable,
487 GdkGCPrivate *gc_private;
490 gdk_draw_text_arg arg;
493 if (GDK_DRAWABLE_DESTROYED (drawable))
496 if (text_length == 0)
499 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
501 gc_private = (GdkGCPrivate*) gc;
505 arg.hdc = gdk_gc_predraw (drawable, gc_private,
506 GDK_GC_FOREGROUND|GDK_GC_FONT);
508 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
509 GDK_DRAWABLE_XID (drawable),
511 (text_length > 10 ? 10 : text_length),
514 wcstr = g_new (wchar_t, text_length);
515 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
516 g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed");
518 gdk_wchar_text_handle (font, wcstr, wlen,
519 gdk_draw_text_handler, &arg);
523 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT);
527 gdk_win32_draw_text_wc (GdkDrawable *drawable,
532 const GdkWChar *text,
535 GdkGCPrivate *gc_private;
538 gdk_draw_text_arg arg;
541 if (GDK_DRAWABLE_DESTROYED (drawable))
544 if (text_length == 0)
547 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
549 gc_private = (GdkGCPrivate*) gc;
553 arg.hdc = gdk_gc_predraw (drawable, gc_private,
554 GDK_GC_FOREGROUND|GDK_GC_FONT);
556 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
557 GDK_DRAWABLE_XID (drawable),
560 if (sizeof (wchar_t) != sizeof (GdkWChar))
562 wcstr = g_new (wchar_t, text_length);
563 for (i = 0; i < text_length; i++)
567 wcstr = (wchar_t *) text;
569 gdk_wchar_text_handle (font, wcstr, text_length,
570 gdk_draw_text_handler, &arg);
572 if (sizeof (wchar_t) != sizeof (GdkWChar))
575 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT);
579 gdk_win32_draw_drawable (GdkDrawable *drawable,
589 GdkDrawablePrivate *src_private;
590 GdkGCPrivate *gc_private;
594 HRGN src_rgn, draw_rgn, outside_rgn;
597 src_private = (GdkDrawablePrivate*) src;
598 gc_private = (GdkGCPrivate*) gc;
600 GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
601 "src: %#x %dx%d@+%d+%d"
602 " dest: %#x @+%d+%d\n",
603 GDK_DRAWABLE_XID (drawable),
604 GDK_DRAWABLE_XID (src),
605 width, height, xsrc, ysrc,
606 GDK_DRAWABLE_XID (drawable), xdest, ydest));
608 hdc = gdk_gc_predraw (drawable, gc_private, 0);
610 src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
611 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
613 outside_rgn = CreateRectRgnIndirect (&r);
615 if (GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_PIXMAP)
617 /* If we are drawing on a window, calculate the region that is
618 * outside the source pixmap, and invalidate that, causing it to
621 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
623 OffsetRgn (outside_rgn, xdest, ydest);
624 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
625 g_print ("...calling InvalidateRgn, "
626 "bbox: %dx%d@+%d+%d\n",
627 r.right - r.left - 1, r.bottom - r.top - 1,
629 InvalidateRgn (GDK_DRAWABLE_XID (drawable), outside_rgn, TRUE);
633 #if 1 /* Don't know if this is necessary */
634 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
635 g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
637 GetRgnBox (draw_rgn, &r);
640 || r.right != xsrc + width + 1
641 || r.bottom != ysrc + height + 1)
643 xdest += r.left - xsrc;
645 ydest += r.top - ysrc;
647 width = r.right - xsrc - 1;
648 height = r.bottom - ysrc - 1;
650 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
652 width, height, xsrc, ysrc,
657 DeleteObject (src_rgn);
658 DeleteObject (draw_rgn);
659 DeleteObject (outside_rgn);
661 /* Strangely enough, this function is called also to bitblt
664 if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
666 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
667 WIN32_GDI_FAILED ("CreateCompatibleDC");
669 if ((hgdiobj = SelectObject (srcdc, GDK_DRAWABLE_XID (src))) == NULL)
670 WIN32_GDI_FAILED ("SelectObject");
672 if (!BitBlt (hdc, xdest, ydest, width, height,
673 srcdc, xsrc, ysrc, SRCCOPY))
674 WIN32_GDI_FAILED ("BitBlt");
676 if ((SelectObject (srcdc, hgdiobj) == NULL))
677 WIN32_GDI_FAILED ("SelectObject");
679 if (!DeleteDC (srcdc))
680 WIN32_GDI_FAILED ("DeleteDC");
684 if (GDK_DRAWABLE_XID(drawable) == GDK_DRAWABLE_XID (src))
686 /* Blitting inside a window, use ScrollDC */
687 RECT scrollRect, clipRect, emptyRect;
690 scrollRect.left = MIN (xsrc, xdest);
691 scrollRect.top = MIN (ysrc, ydest);
692 scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
693 scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
695 clipRect.left = xdest;
696 clipRect.top = ydest;
697 clipRect.right = xdest + width + 1;
698 clipRect.bottom = ydest + height + 1;
700 SetRectEmpty (&emptyRect);
701 updateRgn = CreateRectRgnIndirect (&emptyRect);
702 if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
703 &scrollRect, &clipRect,
705 WIN32_GDI_FAILED ("ScrollDC");
706 if (!InvalidateRgn (GDK_DRAWABLE_XID (drawable), updateRgn, FALSE))
707 WIN32_GDI_FAILED ("InvalidateRgn");
708 if (!UpdateWindow (GDK_DRAWABLE_XID (drawable)))
709 WIN32_GDI_FAILED ("UpdateWindow");
713 if ((srcdc = GetDC (GDK_DRAWABLE_XID (src))) == NULL)
714 WIN32_GDI_FAILED ("GetDC");
716 if (!BitBlt (hdc, xdest, ydest, width, height,
717 srcdc, xsrc, ysrc, SRCCOPY))
718 WIN32_GDI_FAILED ("BitBlt");
719 ReleaseDC (GDK_DRAWABLE_XID (src), srcdc);
722 gdk_gc_postdraw (drawable, gc_private, 0);
726 gdk_win32_draw_points (GdkDrawable *drawable,
733 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
734 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
735 GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
736 GdkColormapPrivateWin32 *colormap_private =
737 (GdkColormapPrivateWin32 *) drawable_private->colormap;
740 hdc = gdk_gc_predraw (drawable, gc_private, 0);
742 fg = gdk_colormap_color (colormap_private, gc_data->foreground);
744 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x %dx%.06x\n",
745 GDK_DRAWABLE_XID (drawable), npoints, fg));
747 for (i = 0; i < npoints; i++)
748 SetPixel (hdc, points[i].x, points[i].y, fg);
750 gdk_gc_postdraw (drawable, gc_private, 0);
754 gdk_win32_draw_segments (GdkDrawable *drawable,
759 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
760 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
766 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %#x nsegs: %d\n",
767 GDK_DRAWABLE_XID (drawable), nsegs));
769 hdc = gdk_gc_predraw (drawable, gc_private,
770 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
772 if (gc_data->fill_style == GDK_OPAQUE_STIPPLED)
774 if (!BeginPath (hdc))
775 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
777 for (i = 0; i < nsegs; i++)
779 if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
780 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
781 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
782 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
785 if (ok && gc_data->pen_width == 1)
786 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
787 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
790 if (ok && !EndPath (hdc))
791 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
793 if (ok && !WidenPath (hdc))
794 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
796 if (ok && !FillPath (hdc))
797 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
800 if (!DeleteObject (hbr))
801 WIN32_GDI_FAILED ("DeleteObject");
805 for (i = 0; i < nsegs; i++)
807 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
808 WIN32_GDI_FAILED ("MoveToEx");
809 if (!LineTo (hdc, segs[i].x2, segs[i].y2))
810 WIN32_GDI_FAILED ("LineTo");
813 if (gc_data->pen_width == 1)
814 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
815 WIN32_GDI_FAILED ("LineTo");
818 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
822 gdk_win32_draw_lines (GdkDrawable *drawable,
827 GdkGCPrivate *gc_private = (GdkGCPrivate*) gc;
828 GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private);
836 hdc = gdk_gc_predraw (drawable, gc_private,
837 GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);
839 pts = g_new (POINT, npoints);
841 for (i = 0; i < npoints; i++)
843 pts[i].x = points[i].x;
844 pts[i].y = points[i].y;
847 if (!Polyline (hdc, pts, npoints))
848 WIN32_GDI_FAILED ("Polyline");
853 if (gc_data->pen_width == 1)
855 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
856 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
857 WIN32_GDI_FAILED ("LineTo");
860 MoveToEx (hdc, points[0].x, points[0].y, NULL);
861 for (i = 1; i < npoints; i++)
862 if (!LineTo (hdc, points[i].x, points[i].y))
863 WIN32_GDI_FAILED ("LineTo");
866 /* LineTo doesn't draw the last point, so if we have a pen width of 1,
867 * we draw the end pixel separately... With wider pens we don't care.
868 * //HB: But the NT developers don't read their API documentation ...
870 if (gc_data->pen_width == 1 && windows_version > 0x80000000)
871 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
872 WIN32_GDI_FAILED ("LineTo");
874 gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND);