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/.
31 #include "gdkdrawable.h"
32 #include "gdkprivate.h"
33 #include "gdkwindow.h"
37 #define G_PI 3.14159265358979323846
40 /* Manipulation of drawables
43 gdk_drawable_set_data (GdkDrawable *drawable,
46 GDestroyNotify destroy_func)
48 g_dataset_set_data_full (drawable, key, data, destroy_func);
52 gdk_drawable_get_data (GdkDrawable *drawable,
55 g_dataset_get_data (drawable, key);
59 gdk_drawable_get_type (GdkDrawable *drawable)
61 g_return_val_if_fail (drawable != NULL, (GdkDrawableType) -1);
63 return GDK_DRAWABLE_TYPE (drawable);
67 gdk_drawable_get_size (GdkDrawable *drawable,
71 GdkDrawablePrivate *drawable_private;
73 g_return_if_fail (drawable != NULL);
75 drawable_private = (GdkDrawablePrivate*) drawable;
78 *width = drawable_private->width;
80 *height = drawable_private->height;
84 gdk_drawable_set_colormap (GdkDrawable *drawable,
85 GdkColormap *colormap)
87 GdkDrawablePrivate *drawable_private;
88 GdkColormapPrivate *colormap_private;
90 g_return_if_fail (drawable != NULL);
91 g_return_if_fail (colormap != NULL);
93 drawable_private = (GdkDrawablePrivate*) drawable;
94 colormap_private = (GdkColormapPrivate*) colormap;
96 if (!GDK_DRAWABLE_DESTROYED (drawable))
98 if (GDK_IS_WINDOW (drawable))
100 g_return_if_fail (colormap_private->visual !=
101 ((GdkColormapPrivate*)(drawable_private->colormap))->visual);
103 GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n",
104 GDK_DRAWABLE_XID (drawable),
105 colormap_private->xcolormap));
107 if (drawable_private->colormap)
108 gdk_colormap_unref (drawable_private->colormap);
109 drawable_private->colormap = colormap;
110 gdk_colormap_ref (drawable_private->colormap);
112 if (GDK_IS_WINDOW (drawable) &&
113 drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
114 gdk_window_add_colormap_windows (drawable);
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_get_visual (GdkDrawable *drawable)
140 GdkColormap *colormap;
142 g_return_val_if_fail (drawable != NULL, NULL);
144 colormap = gdk_drawable_get_colormap (drawable);
145 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
149 gdk_draw_point (GdkDrawable *drawable,
154 GdkDrawablePrivate *drawable_private;
155 GdkGCPrivate *gc_private;
158 g_return_if_fail (drawable != NULL);
159 g_return_if_fail (gc != NULL);
161 if (GDK_DRAWABLE_DESTROYED (drawable))
163 drawable_private = (GdkDrawablePrivate*) drawable;
164 gc_private = (GdkGCPrivate*) gc;
166 hdc = gdk_gc_predraw (drawable_private, gc_private);
168 /* We use LineTo because SetPixel wants the COLORREF directly,
169 * and doesn't use the current pen, which is what we want.
171 if (!MoveToEx (hdc, x, y, NULL))
172 g_warning ("gdk_draw_point: MoveToEx failed");
173 if (!LineTo (hdc, x + 1, y))
174 g_warning ("gdk_draw_point: LineTo failed");
176 gdk_gc_postdraw (drawable_private, gc_private);
180 gdk_draw_line (GdkDrawable *drawable,
187 GdkDrawablePrivate *drawable_private;
188 GdkGCPrivate *gc_private;
191 g_return_if_fail (drawable != NULL);
192 g_return_if_fail (gc != NULL);
194 if (GDK_DRAWABLE_DESTROYED (drawable))
196 drawable_private = (GdkDrawablePrivate*) drawable;
197 gc_private = (GdkGCPrivate*) gc;
199 hdc = gdk_gc_predraw (drawable_private, gc_private);
201 GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n",
202 drawable_private->xwindow, gc_private,
205 MoveToEx (hdc, x1, y1, NULL);
206 if (!LineTo (hdc, x2, y2))
207 g_warning ("gdk_draw_line: LineTo #1 failed");
208 /* LineTo doesn't draw the last point, so if we have a pen width of 1,
209 * we draw the end pixel separately... With wider pens we don't care.
210 * //HB: But the NT developers don't read their API documentation ...
212 if (gc_private->pen_width == 1 && windows_version > 0x80000000)
213 if (!LineTo (hdc, x2 + 1, y2))
214 g_warning ("gdk_draw_line: LineTo #2 failed");
215 gdk_gc_postdraw (drawable_private, gc_private);
219 gdk_draw_rectangle (GdkDrawable *drawable,
227 GdkDrawablePrivate *drawable_private;
228 GdkGCPrivate *gc_private;
230 HGDIOBJ oldpen, oldbrush;
232 g_return_if_fail (drawable != NULL);
233 g_return_if_fail (gc != NULL);
235 if (GDK_DRAWABLE_DESTROYED (drawable))
237 drawable_private = (GdkDrawablePrivate*) drawable;
238 gc_private = (GdkGCPrivate*) gc;
241 width = drawable_private->width;
243 height = drawable_private->height;
245 hdc = gdk_gc_predraw (drawable_private, gc_private);
247 GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
248 drawable_private->xwindow,
250 (filled ? "fill " : ""),
251 width, height, x, y));
255 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
256 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
259 GetObject (hbr, sizeof (lbr), &lbr);
260 GetObject (hpen, sizeof (lpen), &lpen);
262 g_print ("current brush: style = %s, color = 0x%.08x\n",
263 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
265 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
266 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
273 oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
275 oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
277 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
278 g_warning ("gdk_draw_rectangle: Rectangle failed");
281 SelectObject (hdc, oldpen);
283 SelectObject (hdc, oldbrush);
285 gdk_gc_postdraw (drawable_private, gc_private);
289 gdk_draw_arc (GdkDrawable *drawable,
299 GdkDrawablePrivate *drawable_private;
300 GdkGCPrivate *gc_private;
302 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
304 g_return_if_fail (drawable != NULL);
305 g_return_if_fail (gc != NULL);
307 if (GDK_DRAWABLE_DESTROYED (drawable))
309 drawable_private = (GdkDrawablePrivate*) drawable;
310 gc_private = (GdkGCPrivate*) gc;
313 width = drawable_private->width;
315 height = drawable_private->height;
317 GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n",
318 drawable_private->xwindow,
319 x, y, width, height, angle1, angle2));
321 if (width != 0 && height != 0 && angle2 != 0)
323 hdc = gdk_gc_predraw (drawable_private, gc_private);
325 if (angle2 >= 360*64)
327 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
331 /* The 100. is just an arbitrary value */
332 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
333 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
334 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
335 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
339 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
340 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
341 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
342 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
347 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
348 x, y, x+width, y+height,
349 nXStartArc, nYStartArc,
350 nXEndArc, nYEndArc));
351 Pie (hdc, x, y, x+width, y+height,
352 nXStartArc, nYStartArc, nXEndArc, nYEndArc);
356 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
357 x, y, x+width, y+height,
358 nXStartArc, nYStartArc,
359 nXEndArc, nYEndArc));
360 Arc (hdc, x, y, x+width, y+height,
361 nXStartArc, nYStartArc, nXEndArc, nYEndArc);
363 gdk_gc_postdraw (drawable_private, gc_private);
368 gdk_draw_polygon (GdkDrawable *drawable,
374 GdkDrawablePrivate *drawable_private;
375 GdkGCPrivate *gc_private;
380 g_return_if_fail (drawable != NULL);
381 g_return_if_fail (gc != NULL);
383 if (GDK_DRAWABLE_DESTROYED (drawable))
385 drawable_private = (GdkDrawablePrivate*) drawable;
386 gc_private = (GdkGCPrivate*) gc;
388 GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n",
389 drawable_private->xwindow, gc_private,
395 hdc = gdk_gc_predraw (drawable_private, gc_private);
396 pts = g_malloc ((npoints+1) * sizeof (POINT));
398 for (i = 0; i < npoints; i++)
400 pts[i].x = points[i].x;
401 pts[i].y = points[i].y;
404 if ((points[0].x != points[npoints-1].x) ||
405 (points[0].y != points[npoints-1].y))
407 pts[npoints].x = points[0].x;
408 pts[npoints].y = points[0].y;
413 if (!Polygon (hdc, pts, npoints))
414 g_warning ("gdk_draw_polygon: Polygon failed");
418 if (!Polyline (hdc, pts, npoints))
419 g_warning ("gdk_draw_polygon: Polyline failed");
422 gdk_gc_postdraw (drawable_private, gc_private);
434 gdk_draw_string (GdkDrawable *drawable,
441 gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
445 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
446 const wchar_t *wcstr,
452 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
457 if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL)
459 g_warning ("gdk_draw_text_handler: SelectObject failed");
463 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
464 g_warning ("gdk_draw_text_handler: TextOutW failed");
465 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
468 SelectObject (argp->hdc, oldfont);
475 gdk_draw_text (GdkDrawable *drawable,
483 GdkDrawablePrivate *drawable_private;
484 GdkGCPrivate *gc_private;
487 gdk_draw_text_arg arg;
489 g_return_if_fail (drawable != NULL);
490 g_return_if_fail (font != NULL);
491 g_return_if_fail (gc != NULL);
492 g_return_if_fail (text != NULL);
494 if (GDK_DRAWABLE_DESTROYED (drawable))
497 if (text_length == 0)
500 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
502 drawable_private = (GdkDrawablePrivate*) drawable;
503 gc_private = (GdkGCPrivate*) gc;
507 arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
509 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
510 drawable_private->xwindow,
512 (text_length > 10 ? 10 : text_length),
515 wcstr = g_new (wchar_t, text_length);
516 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
517 g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed");
519 gdk_wchar_text_handle (font, wcstr, wlen,
520 gdk_draw_text_handler, &arg);
524 gdk_gc_postdraw (drawable_private, gc_private);
528 gdk_draw_text_wc (GdkDrawable *drawable,
533 const GdkWChar *text,
536 GdkDrawablePrivate *drawable_private;
537 GdkGCPrivate *gc_private;
540 gdk_draw_text_arg arg;
542 g_return_if_fail (drawable != NULL);
543 g_return_if_fail (font != NULL);
544 g_return_if_fail (gc != NULL);
545 g_return_if_fail (text != NULL);
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 drawable_private = (GdkDrawablePrivate*) drawable;
556 gc_private = (GdkGCPrivate*) gc;
560 arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
562 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
563 drawable_private->xwindow,
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_private, gc_private);
585 gdk_draw_pixmap (GdkDrawable *drawable,
595 GdkDrawablePrivate *drawable_private;
596 GdkDrawablePrivate *src_private;
597 GdkGCPrivate *gc_private;
601 HRGN src_rgn, draw_rgn, outside_rgn;
604 g_return_if_fail (drawable != NULL);
605 g_return_if_fail (src != NULL);
606 g_return_if_fail (gc != NULL);
608 if (GDK_DRAWABLE_DESTROYED (drawable) || GDK_DRAWABLE_DESTROYED (src))
610 drawable_private = (GdkDrawablePrivate*) drawable;
611 src_private = (GdkDrawablePrivate*) src;
612 gc_private = (GdkGCPrivate*) gc;
615 width = src_private->width; /* Or should we subtract xsrc? */
617 height = src_private->height; /* Ditto? */
619 GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
620 "src: %#x %dx%d@+%d+%d"
621 " dest: %#x @+%d+%d\n",
622 drawable_private->xwindow,
623 src_private->xwindow,
624 width, height, xsrc, ysrc,
625 drawable_private->xwindow, xdest, ydest));
627 hdc = gdk_gc_predraw (drawable_private, gc_private);
629 src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
630 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
632 outside_rgn = CreateRectRgnIndirect (&r);
634 if (drawable_private->window_type != GDK_DRAWABLE_PIXMAP)
636 /* If we are drawing on a window, calculate the region that is
637 * outside the source pixmap, and invalidate that, causing it to
640 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
642 OffsetRgn (outside_rgn, xdest, ydest);
643 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
644 g_print ("...calling InvalidateRgn, "
645 "bbox: %dx%d@+%d+%d\n",
646 r.right - r.left - 1, r.bottom - r.top - 1,
648 InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE);
652 #if 1 /* Don't know if this is necessary */
653 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
654 g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
656 GetRgnBox (draw_rgn, &r);
659 || r.right != xsrc + width + 1
660 || r.bottom != ysrc + height + 1)
662 xdest += r.left - xsrc;
664 ydest += r.top - ysrc;
666 width = r.right - xsrc - 1;
667 height = r.bottom - ysrc - 1;
669 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
671 width, height, xsrc, ysrc,
676 DeleteObject (src_rgn);
677 DeleteObject (draw_rgn);
678 DeleteObject (outside_rgn);
680 /* Strangely enough, this function is called also to bitblt
683 if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
685 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
686 g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
688 if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
689 g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
691 if (!BitBlt (hdc, xdest, ydest, width, height,
692 srcdc, xsrc, ysrc, SRCCOPY))
693 g_warning ("gdk_draw_pixmap: BitBlt failed");
695 if ((SelectObject (srcdc, hgdiobj) == NULL))
696 g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
698 if (!DeleteDC (srcdc))
699 g_warning ("gdk_draw_pixmap: DeleteDC failed");
703 if (drawable_private->xwindow == src_private->xwindow)
705 /* Blitting inside a window, use ScrollDC */
706 RECT scrollRect, clipRect, emptyRect;
709 scrollRect.left = MIN (xsrc, xdest);
710 scrollRect.top = MIN (ysrc, ydest);
711 scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
712 scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
714 clipRect.left = xdest;
715 clipRect.top = ydest;
716 clipRect.right = xdest + width + 1;
717 clipRect.bottom = ydest + height + 1;
719 SetRectEmpty (&emptyRect);
720 updateRgn = CreateRectRgnIndirect (&emptyRect);
721 if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
722 &scrollRect, &clipRect,
724 g_warning ("gdk_draw_pixmap: ScrollDC failed");
725 if (!InvalidateRgn (drawable_private->xwindow, updateRgn, FALSE))
726 g_warning ("gdk_draw_pixmap: InvalidateRgn failed");
727 if (!UpdateWindow (drawable_private->xwindow))
728 g_warning ("gdk_draw_pixmap: UpdateWindow failed");
732 if ((srcdc = GetDC (src_private->xwindow)) == NULL)
733 g_warning ("gdk_draw_pixmap: GetDC failed");
735 if (!BitBlt (hdc, xdest, ydest, width, height,
736 srcdc, xsrc, ysrc, SRCCOPY))
737 g_warning ("gdk_draw_pixmap: BitBlt failed");
738 ReleaseDC (src_private->xwindow, srcdc);
741 gdk_gc_postdraw (drawable_private, gc_private);
745 gdk_draw_image (GdkDrawable *drawable,
755 GdkImagePrivate *image_private;
757 g_return_if_fail (drawable != NULL);
758 g_return_if_fail (image != NULL);
759 g_return_if_fail (gc != NULL);
761 image_private = (GdkImagePrivate*) image;
763 g_return_if_fail (image_private->image_put != NULL);
766 width = image->width;
768 height = image->height;
770 (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
771 xdest, ydest, width, height);
775 gdk_draw_points (GdkDrawable *drawable,
780 GdkDrawablePrivate *drawable_private;
781 GdkGCPrivate *gc_private;
785 g_return_if_fail (drawable != NULL);
786 g_return_if_fail ((points != NULL) && (npoints > 0));
787 g_return_if_fail (gc != NULL);
789 if (GDK_DRAWABLE_DESTROYED (drawable))
791 drawable_private = (GdkDrawablePrivate*) drawable;
792 gc_private = (GdkGCPrivate*) gc;
794 hdc = gdk_gc_predraw (drawable_private, gc_private);
796 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x "
798 drawable_private->xwindow, gc_private, hdc,
801 for (i = 0; i < npoints; i++)
803 if (!MoveToEx (hdc, points[i].x, points[i].y, NULL))
804 g_warning ("gdk_draw_points: MoveToEx failed");
805 if (!LineTo (hdc, points[i].x + 1, points[i].y))
806 g_warning ("gdk_draw_points: LineTo failed");
808 gdk_gc_postdraw (drawable_private, gc_private);
812 gdk_draw_segments (GdkDrawable *drawable,
817 GdkDrawablePrivate *drawable_private;
818 GdkGCPrivate *gc_private;
825 g_return_if_fail (drawable != NULL);
826 g_return_if_fail (segs != NULL);
827 g_return_if_fail (gc != NULL);
829 if (GDK_DRAWABLE_DESTROYED (drawable))
831 drawable_private = (GdkDrawablePrivate*) drawable;
832 gc_private = (GdkGCPrivate*) gc;
834 hdc = gdk_gc_predraw (drawable_private, gc_private);
836 for (i = 0; i < nsegs; i++)
838 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
839 g_warning ("gdk_draw_segments: MoveToEx failed");
840 if (!LineTo (hdc, segs[i].x2, segs[i].y2))
841 g_warning ("gdk_draw_segments: LineTo #1 failed");
844 if (gc_private->pen_width == 1)
845 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
846 g_warning ("gdk_draw_segments: LineTo #2 failed");
848 gdk_gc_postdraw (drawable_private, gc_private);
852 gdk_draw_lines (GdkDrawable *drawable,
857 GdkDrawablePrivate *drawable_private;
858 GdkGCPrivate *gc_private;
866 g_return_if_fail (drawable != NULL);
867 g_return_if_fail (points != NULL);
868 g_return_if_fail (gc != NULL);
870 if (GDK_DRAWABLE_DESTROYED (drawable))
872 drawable_private = (GdkDrawablePrivate*) drawable;
873 gc_private = (GdkGCPrivate*) gc;
875 hdc = gdk_gc_predraw (drawable_private, gc_private);
877 pts = g_malloc (npoints * sizeof (POINT));
879 for (i = 0; i < npoints; i++)
881 pts[i].x = points[i].x;
882 pts[i].y = points[i].y;
885 if (!Polyline (hdc, pts, npoints))
886 g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints);
891 if (gc_private->pen_width == 1)
893 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
894 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
895 g_warning ("gdk_draw_lines: LineTo failed");
898 MoveToEx (hdc, points[0].x, points[0].y, NULL);
899 for (i = 1; i < npoints; i++)
900 if (!LineTo (hdc, points[i].x, points[i].y))
901 g_warning ("gdk_draw_lines: LineTo #1 failed");
904 if (gc_private->pen_width == 1)
905 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
906 g_warning ("gdk_draw_lines: LineTo #2 failed");
908 gdk_gc_postdraw (drawable_private, gc_private);