]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdrawable-win32.c
Corresponding changes as in X11 backend.
[~andy/gtk] / gdk / win32 / gdkdrawable-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "config.h"
28
29 #include <math.h>
30
31 #include "gdkdrawable.h"
32 #include "gdkprivate.h"
33 #include "gdkwindow.h"
34 #include "gdkx.h"
35
36 #ifndef G_PI
37 #define G_PI 3.14159265358979323846
38 #endif
39
40 /* Manipulation of drawables
41  */
42 void          
43 gdk_drawable_set_data (GdkDrawable   *drawable,
44                        const gchar   *key,
45                        gpointer       data,
46                        GDestroyNotify destroy_func)
47 {
48   g_dataset_set_data_full (drawable, key, data, destroy_func);
49 }
50
51 void          
52 gdk_drawable_get_data (GdkDrawable   *drawable,
53                        const gchar   *key)
54 {
55   g_dataset_get_data (drawable, key);
56 }
57
58 GdkDrawableType
59 gdk_drawable_get_type (GdkDrawable *drawable)
60 {
61   g_return_val_if_fail (drawable != NULL, (GdkDrawableType) -1);
62   
63   return GDK_DRAWABLE_TYPE (drawable);
64 }
65
66 void
67 gdk_drawable_get_size (GdkDrawable *drawable,
68                        gint        *width,
69                        gint        *height)
70 {
71   GdkDrawablePrivate *drawable_private;
72   
73   g_return_if_fail (drawable != NULL);
74   
75   drawable_private = (GdkDrawablePrivate*) drawable;
76   
77   if (width)
78     *width = drawable_private->width;
79   if (height)
80     *height = drawable_private->height;
81 }
82
83 void
84 gdk_drawable_set_colormap (GdkDrawable *drawable,
85                            GdkColormap *colormap)
86 {
87   GdkDrawablePrivate *drawable_private;
88   GdkColormapPrivate *colormap_private;
89   
90   g_return_if_fail (drawable != NULL);
91   g_return_if_fail (colormap != NULL);
92   
93   drawable_private = (GdkDrawablePrivate*) drawable;
94   colormap_private = (GdkColormapPrivate*) colormap;
95   
96   if (!GDK_DRAWABLE_DESTROYED (drawable))
97     {
98       if (GDK_IS_WINDOW (drawable))
99         {
100           g_return_if_fail (colormap_private->visual !=
101                             ((GdkColormapPrivate*)(drawable_private->colormap))->visual);
102           /* XXX ??? */
103           GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n",
104                                    GDK_DRAWABLE_XID (drawable),
105                                    colormap_private->xcolormap));
106         }
107       if (drawable_private->colormap)
108         gdk_colormap_unref (drawable_private->colormap);
109       drawable_private->colormap = colormap;
110       gdk_colormap_ref (drawable_private->colormap);
111       
112       if (GDK_IS_WINDOW (drawable) &&
113           drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
114         gdk_window_add_colormap_windows (drawable);
115     }
116 }
117
118 GdkColormap*
119 gdk_drawable_get_colormap (GdkDrawable *drawable)
120 {
121   GdkDrawablePrivate *drawable_private;
122   
123   g_return_val_if_fail (drawable != NULL, NULL);
124   drawable_private = (GdkDrawablePrivate*) drawable;
125
126   if (!GDK_DRAWABLE_DESTROYED (drawable))
127     {
128       if (drawable_private->colormap == NULL)
129         return gdk_colormap_get_system (); /* XXX ??? */
130       else
131         return drawable_private->colormap;
132     }
133   
134   return NULL;
135 }
136
137 GdkVisual*
138 gdk_drawable_get_visual (GdkDrawable *drawable)
139 {
140   GdkColormap *colormap;
141
142   g_return_val_if_fail (drawable != NULL, NULL);
143
144   colormap = gdk_drawable_get_colormap (drawable);
145   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
146 }
147
148 void
149 gdk_draw_point (GdkDrawable *drawable,
150                 GdkGC       *gc,
151                 gint         x,
152                 gint         y)
153 {
154   GdkDrawablePrivate *drawable_private;
155   GdkGCPrivate *gc_private;
156   HDC hdc;
157
158   g_return_if_fail (drawable != NULL);
159   g_return_if_fail (gc != NULL);
160
161   if (GDK_DRAWABLE_DESTROYED (drawable))
162     return;
163   drawable_private = (GdkDrawablePrivate*) drawable;
164   gc_private = (GdkGCPrivate*) gc;
165
166   hdc = gdk_gc_predraw (drawable_private, gc_private);
167
168   /* We use LineTo because SetPixel wants the COLORREF directly,
169    * and doesn't use the current pen, which is what we want.
170    */
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");
175   
176   gdk_gc_postdraw (drawable_private, gc_private);
177 }
178
179 void
180 gdk_draw_line (GdkDrawable *drawable,
181                GdkGC       *gc,
182                gint         x1,
183                gint         y1,
184                gint         x2,
185                gint         y2)
186 {
187   GdkDrawablePrivate *drawable_private;
188   GdkGCPrivate *gc_private;
189   HDC hdc;
190
191   g_return_if_fail (drawable != NULL);
192   g_return_if_fail (gc != NULL);
193
194   if (GDK_DRAWABLE_DESTROYED (drawable))
195     return;
196   drawable_private = (GdkDrawablePrivate*) drawable;
197   gc_private = (GdkGCPrivate*) gc;
198
199   hdc = gdk_gc_predraw (drawable_private, gc_private);
200     
201   GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n",
202                            drawable_private->xwindow, gc_private,
203                            x1, y1, x2, y2));
204   
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 ...
211    */
212   if (gc_private->pen_width == 1
213       && GetVersion () > 0x80000000)
214     if (!LineTo (hdc, x2 + 1, y2))
215       g_warning ("gdk_draw_line: LineTo #2 failed");
216   gdk_gc_postdraw (drawable_private, gc_private);
217 }
218
219 void
220 gdk_draw_rectangle (GdkDrawable *drawable,
221                     GdkGC       *gc,
222                     gint         filled,
223                     gint         x,
224                     gint         y,
225                     gint         width,
226                     gint         height)
227 {
228   GdkDrawablePrivate *drawable_private;
229   GdkGCPrivate *gc_private;
230   HDC hdc;
231   HGDIOBJ oldpen, oldbrush;
232
233   g_return_if_fail (drawable != NULL);
234   g_return_if_fail (gc != NULL);
235
236   if (GDK_DRAWABLE_DESTROYED (drawable))
237     return;
238   drawable_private = (GdkDrawablePrivate*) drawable;
239   gc_private = (GdkGCPrivate*) gc;
240
241   if (width == -1)
242     width = drawable_private->width;
243   if (height == -1)
244     height = drawable_private->height;
245
246   hdc = gdk_gc_predraw (drawable_private, gc_private);
247
248   GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
249                            drawable_private->xwindow,
250                            gc_private,
251                            (filled ? "fill " : ""),
252                            width, height, x, y));
253     
254 #if 0
255   {
256     HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
257     HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
258     LOGBRUSH lbr;
259     LOGPEN lpen;
260     GetObject (hbr, sizeof (lbr), &lbr);
261     GetObject (hpen, sizeof (lpen), &lpen);
262     
263     g_print ("current brush: style = %s, color = 0x%.08x\n",
264              (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
265              lbr.lbColor);
266     g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
267              (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
268              lpen.lopnWidth,
269              lpen.lopnColor);
270   }
271 #endif
272
273   if (filled)
274     oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
275   else
276     oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
277   
278   if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
279     g_warning ("gdk_draw_rectangle: Rectangle failed");
280   
281   if (filled)
282     SelectObject (hdc, oldpen);
283   else
284     SelectObject (hdc, oldbrush);
285
286   gdk_gc_postdraw (drawable_private, gc_private);
287 }
288
289 void
290 gdk_draw_arc (GdkDrawable *drawable,
291               GdkGC       *gc,
292               gint         filled,
293               gint         x,
294               gint         y,
295               gint         width,
296               gint         height,
297               gint         angle1,
298               gint         angle2)
299 {
300   GdkDrawablePrivate *drawable_private;
301   GdkGCPrivate *gc_private;
302   HDC hdc;
303   int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
304
305   g_return_if_fail (drawable != NULL);
306   g_return_if_fail (gc != NULL);
307
308   if (GDK_DRAWABLE_DESTROYED (drawable))
309     return;
310   drawable_private = (GdkDrawablePrivate*) drawable;
311   gc_private = (GdkGCPrivate*) gc;
312
313   if (width == -1)
314     width = drawable_private->width;
315   if (height == -1)
316     height = drawable_private->height;
317
318   GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x  %d,%d,%d,%d  %d %d\n",
319                            drawable_private->xwindow,
320                            x, y, width, height, angle1, angle2));
321
322   if (width != 0 && height != 0 && angle2 != 0)
323     {
324       hdc = gdk_gc_predraw (drawable_private, gc_private);
325
326       if (angle2 >= 360*64)
327         {
328           nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
329         }
330       else if (angle2 > 0)
331         {
332           /* The 100. is just an arbitrary value */
333           nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
334           nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
335           nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
336           nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
337         }
338       else
339         {
340           nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
341           nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
342           nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
343           nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
344         }
345
346       if (filled)
347         {
348           GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
349                                    x, y, x+width, y+height,
350                                    nXStartArc, nYStartArc,
351                                    nXEndArc, nYEndArc));
352           Pie (hdc, x, y, x+width, y+height,
353                nXStartArc, nYStartArc, nXEndArc, nYEndArc);
354         }
355       else
356         {
357           GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
358                                    x, y, x+width, y+height,
359                                    nXStartArc, nYStartArc,
360                                    nXEndArc, nYEndArc));
361           Arc (hdc, x, y, x+width, y+height,
362                nXStartArc, nYStartArc, nXEndArc, nYEndArc);
363         }
364       gdk_gc_postdraw (drawable_private, gc_private);
365     }
366 }
367
368 void
369 gdk_draw_polygon (GdkDrawable *drawable,
370                   GdkGC       *gc,
371                   gint         filled,
372                   GdkPoint    *points,
373                   gint         npoints)
374 {
375   GdkDrawablePrivate *drawable_private;
376   GdkGCPrivate *gc_private;
377   HDC hdc;
378   POINT *pts;
379   int i;
380
381   g_return_if_fail (drawable != NULL);
382   g_return_if_fail (gc != NULL);
383
384   if (GDK_DRAWABLE_DESTROYED (drawable))
385     return;
386   drawable_private = (GdkDrawablePrivate*) drawable;
387   gc_private = (GdkGCPrivate*) gc;
388
389   GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n",
390                            drawable_private->xwindow, gc_private,
391                            npoints));
392
393   if (npoints < 2)
394     return;
395
396   hdc = gdk_gc_predraw (drawable_private, gc_private);
397   pts = g_malloc ((npoints+1) * sizeof (POINT));
398
399   for (i = 0; i < npoints; i++)
400     {
401       pts[i].x = points[i].x;
402       pts[i].y = points[i].y;
403     }
404   
405   if ((points[0].x != points[npoints-1].x) ||
406       (points[0].y != points[npoints-1].y)) 
407     {
408       pts[npoints].x = points[0].x;
409       pts[npoints].y = points[0].y;
410       npoints++;
411     }
412   if (filled)
413     {
414       if (!Polygon (hdc, pts, npoints))
415         g_warning ("gdk_draw_polygon: Polygon failed");
416     }
417   else
418     {
419       if (!Polyline (hdc, pts, npoints))
420         g_warning ("gdk_draw_polygon: Polyline failed");
421     }
422   g_free (pts);
423   gdk_gc_postdraw (drawable_private, gc_private);
424 }
425
426 /* gdk_draw_string
427  */
428 void
429 gdk_draw_string (GdkDrawable *drawable,
430                  GdkFont     *font,
431                  GdkGC       *gc,
432                  gint         x,
433                  gint         y,
434                  const gchar *string)
435 {
436   gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
437 }
438
439 /* gdk_draw_text
440  *
441  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
442  *
443  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
444  */
445 void
446 gdk_draw_text (GdkDrawable *drawable,
447                GdkFont     *font,
448                GdkGC       *gc,
449                gint         x,
450                gint         y,
451                const gchar *text,
452                gint         text_length)
453 {
454   GdkDrawablePrivate *drawable_private;
455   GdkFontPrivate *font_private;
456   GdkGCPrivate *gc_private;
457   HDC hdc;
458   HFONT xfont;
459   HGDIOBJ oldfont;
460
461   g_return_if_fail (drawable != NULL);
462   g_return_if_fail (font != NULL);
463   g_return_if_fail (gc != NULL);
464   g_return_if_fail (text != NULL);
465
466   if (GDK_DRAWABLE_DESTROYED (drawable))
467     return;
468   drawable_private = (GdkDrawablePrivate*) drawable;
469   gc_private = (GdkGCPrivate*) gc;
470   font_private = (GdkFontPrivate*) font;
471
472   if (font->type == GDK_FONT_FONT)
473     {
474       hdc = gdk_gc_predraw (drawable_private, gc_private);
475       xfont = (HFONT) font_private->xfont;
476
477       GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
478                                "+%d+%d font: %#x \"%.*s\" length: %d\n",
479                                drawable_private->xwindow,
480                                gc_private, gc_private->xgc,
481                                x, y, xfont,
482                                (text_length > 10 ? 10 : text_length),
483                                text, text_length));
484       
485       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
486         g_warning ("gdk_draw_text: SelectObject failed");
487       if (!TextOutA (hdc, x, y, text, text_length))
488         g_warning ("gdk_draw_text: TextOutA failed");
489       SelectObject (hdc, oldfont);
490       gdk_gc_postdraw (drawable_private, gc_private);
491     }
492   else
493     g_error ("undefined font type");
494 }
495
496 void
497 gdk_draw_text_wc (GdkDrawable    *drawable,
498                   GdkFont        *font,
499                   GdkGC          *gc,
500                   gint            x,
501                   gint            y,
502                   const GdkWChar *text,
503                   gint            text_length)
504 {
505   GdkDrawablePrivate *drawable_private;
506   GdkFontPrivate *font_private;
507   GdkGCPrivate *gc_private;
508   gint i;
509   wchar_t *wcstr;
510
511   g_return_if_fail (drawable != NULL);
512   g_return_if_fail (font != NULL);
513   g_return_if_fail (gc != NULL);
514   g_return_if_fail (text != NULL);
515
516   if (GDK_DRAWABLE_DESTROYED (drawable))
517     return;
518   drawable_private = (GdkDrawablePrivate*) drawable;
519   gc_private = (GdkGCPrivate*) gc;
520   font_private = (GdkFontPrivate*) font;
521
522   if (font->type == GDK_FONT_FONT)
523     {
524       HDC hdc;
525       HFONT xfont;
526       HGDIOBJ oldfont;
527
528       hdc = gdk_gc_predraw (drawable_private, gc_private);
529       xfont = (HFONT) font_private->xfont;
530
531       GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
532                                "+%d+%d font: %#x length: %d\n",
533                                drawable_private->xwindow,
534                                gc_private, gc_private->xgc,
535                                x, y, xfont,
536                                text_length));
537       
538       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
539         g_warning ("gdk_draw_text: SelectObject failed");
540       wcstr = g_new (wchar_t, text_length);
541       for (i = 0; i < text_length; i++)
542         wcstr[i] = text[i];
543       if (!TextOutW (hdc, x, y, wcstr, text_length))
544         g_warning ("gdk_draw_text: TextOutW failed");
545       g_free (wcstr);
546       SelectObject (hdc, oldfont);
547       gdk_gc_postdraw (drawable_private, gc_private);
548     }
549   else
550     g_error ("undefined font type");
551 }
552
553 void
554 gdk_draw_pixmap (GdkDrawable *drawable,
555                  GdkGC       *gc,
556                  GdkPixmap   *src,
557                  gint         xsrc,
558                  gint         ysrc,
559                  gint         xdest,
560                  gint         ydest,
561                  gint         width,
562                  gint         height)
563 {
564   GdkDrawablePrivate *drawable_private;
565   GdkDrawablePrivate *src_private;
566   GdkGCPrivate *gc_private;
567   HDC hdc;
568   HDC srcdc;
569   HGDIOBJ hgdiobj;
570   HRGN src_rgn, draw_rgn, outside_rgn;
571   RECT r;
572
573   g_return_if_fail (drawable != NULL);
574   g_return_if_fail (src != NULL);
575   g_return_if_fail (gc != NULL);
576
577   if (GDK_DRAWABLE_DESTROYED (drawable) || GDK_DRAWABLE_DESTROYED (src))
578     return;
579   drawable_private = (GdkDrawablePrivate*) drawable;
580   src_private = (GdkDrawablePrivate*) src;
581   gc_private = (GdkGCPrivate*) gc;
582
583   if (width == -1)
584     width = src_private->width; /* Or should we subtract xsrc? */
585   if (height == -1)
586     height = src_private->height; /* Ditto? */
587
588   GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
589                            "src: %#x %dx%d@+%d+%d"
590                            " dest: %#x @+%d+%d\n",
591                            drawable_private->xwindow,
592                            src_private->xwindow,
593                            width, height, xsrc, ysrc,
594                            drawable_private->xwindow, xdest, ydest));
595
596   hdc = gdk_gc_predraw (drawable_private, gc_private);
597
598   src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
599   draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
600   SetRectEmpty (&r);
601   outside_rgn = CreateRectRgnIndirect (&r);
602   
603   if (drawable_private->window_type != GDK_DRAWABLE_PIXMAP)
604     {
605       /* If we are drawing on a window, calculate the region that is
606        * outside the source pixmap, and invalidate that, causing it to
607        * be cleared. XXX
608        */
609       if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
610         {
611           OffsetRgn (outside_rgn, xdest, ydest);
612           GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
613                            g_print ("...calling InvalidateRgn, "
614                                     "bbox: %dx%d@+%d+%d\n",
615                                     r.right - r.left - 1, r.bottom - r.top - 1,
616                                     r.left, r.top)));
617           InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE);
618         }
619     }
620
621 #if 1 /* Don't know if this is necessary  */
622   if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
623     g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
624
625   GetRgnBox (draw_rgn, &r);
626   if (r.left != xsrc
627       || r.top != ysrc
628       || r.right != xsrc + width + 1
629       || r.bottom != ysrc + height + 1)
630     {
631       xdest += r.left - xsrc;
632       xsrc = r.left;
633       ydest += r.top - ysrc;
634       ysrc = r.top;
635       width = r.right - xsrc - 1;
636       height = r.bottom - ysrc - 1;
637       
638       GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
639                                "dest: @+%d+%d\n",
640                                width, height, xsrc, ysrc,
641                                xdest, ydest));
642     }
643 #endif
644
645   DeleteObject (src_rgn);
646   DeleteObject (draw_rgn);
647   DeleteObject (outside_rgn);
648
649   /* Strangely enough, this function is called also to bitblt
650    * from a window.
651    */
652   if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
653     {
654       if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
655         g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
656       
657       if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
658         g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
659       
660       if (!BitBlt (hdc, xdest, ydest, width, height,
661                    srcdc, xsrc, ysrc, SRCCOPY))
662         g_warning ("gdk_draw_pixmap: BitBlt failed");
663       
664       if ((SelectObject (srcdc, hgdiobj) == NULL))
665         g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
666       
667       if (!DeleteDC (srcdc))
668         g_warning ("gdk_draw_pixmap: DeleteDC failed");
669     }
670   else
671     {
672       if (drawable_private->xwindow == src_private->xwindow)
673         {
674           /* Blitting inside a window, use ScrollDC */
675           RECT scrollRect, clipRect, emptyRect;
676           HRGN updateRgn;
677
678           scrollRect.left = MIN (xsrc, xdest);
679           scrollRect.top = MIN (ysrc, ydest);
680           scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
681           scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
682
683           clipRect.left = xdest;
684           clipRect.top = ydest;
685           clipRect.right = xdest + width + 1;
686           clipRect.bottom = ydest + height + 1;
687
688           SetRectEmpty (&emptyRect);
689           updateRgn = CreateRectRgnIndirect (&emptyRect);
690           if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
691                          &scrollRect, &clipRect,
692                          updateRgn, NULL))
693             g_warning ("gdk_draw_pixmap: ScrollDC failed");
694           if (!InvalidateRgn (drawable_private->xwindow, updateRgn, FALSE))
695             g_warning ("gdk_draw_pixmap: InvalidateRgn failed");
696           if (!UpdateWindow (drawable_private->xwindow))
697             g_warning ("gdk_draw_pixmap: UpdateWindow failed");
698         }
699       else
700         {
701           if ((srcdc = GetDC (src_private->xwindow)) == NULL)
702             g_warning ("gdk_draw_pixmap: GetDC failed");
703           
704           if (!BitBlt (hdc, xdest, ydest, width, height,
705                        srcdc, xsrc, ysrc, SRCCOPY))
706             g_warning ("gdk_draw_pixmap: BitBlt failed");
707           ReleaseDC (src_private->xwindow, srcdc);
708         }
709     }
710   gdk_gc_postdraw (drawable_private, gc_private);
711 }
712
713 void
714 gdk_draw_image (GdkDrawable *drawable,
715                 GdkGC       *gc,
716                 GdkImage    *image,
717                 gint         xsrc,
718                 gint         ysrc,
719                 gint         xdest,
720                 gint         ydest,
721                 gint         width,
722                 gint         height)
723 {
724   GdkImagePrivate *image_private;
725
726   g_return_if_fail (drawable != NULL);
727   g_return_if_fail (image != NULL);
728   g_return_if_fail (gc != NULL);
729
730   image_private = (GdkImagePrivate*) image;
731
732   g_return_if_fail (image_private->image_put != NULL);
733
734   if (width == -1)
735     width = image->width;
736   if (height == -1)
737     height = image->height;
738
739   (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
740                                 xdest, ydest, width, height);
741 }
742
743 void
744 gdk_draw_points (GdkDrawable *drawable,
745                  GdkGC       *gc,
746                  GdkPoint    *points,
747                  gint         npoints)
748 {
749   GdkDrawablePrivate *drawable_private;
750   GdkGCPrivate *gc_private;
751   HDC hdc;
752   int i;
753
754   g_return_if_fail (drawable != NULL);
755   g_return_if_fail ((points != NULL) && (npoints > 0));
756   g_return_if_fail (gc != NULL);
757
758   if (GDK_DRAWABLE_DESTROYED (drawable))
759     return;
760   drawable_private = (GdkDrawablePrivate*) drawable;
761   gc_private = (GdkGCPrivate*) gc;
762
763   hdc = gdk_gc_predraw (drawable_private, gc_private);
764   
765   GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x "
766                            "npoints: %d\n",
767                            drawable_private->xwindow, gc_private, hdc,
768                            npoints));
769
770   for (i = 0; i < npoints; i++)
771     {
772       if (!MoveToEx (hdc, points[i].x, points[i].y, NULL))
773         g_warning ("gdk_draw_points: MoveToEx failed");
774       if (!LineTo (hdc, points[i].x + 1, points[i].y))
775         g_warning ("gdk_draw_points: LineTo failed");
776     }
777   gdk_gc_postdraw (drawable_private, gc_private);
778 }
779
780 void
781 gdk_draw_segments (GdkDrawable *drawable,
782                    GdkGC       *gc,
783                    GdkSegment  *segs,
784                    gint         nsegs)
785 {
786   GdkDrawablePrivate *drawable_private;
787   GdkGCPrivate *gc_private;
788   HDC hdc;
789   int i;
790
791   if (nsegs <= 0)
792     return;
793
794   g_return_if_fail (drawable != NULL);
795   g_return_if_fail (segs != NULL);
796   g_return_if_fail (gc != NULL);
797
798   if (GDK_DRAWABLE_DESTROYED (drawable))
799     return;
800   drawable_private = (GdkDrawablePrivate*) drawable;
801   gc_private = (GdkGCPrivate*) gc;
802
803   hdc = gdk_gc_predraw (drawable_private, gc_private);
804
805   for (i = 0; i < nsegs; i++)
806     {
807       if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
808         g_warning ("gdk_draw_segments: MoveToEx failed");
809       if (!LineTo (hdc, segs[i].x2, segs[i].y2))
810         g_warning ("gdk_draw_segments: LineTo #1 failed");
811       
812       /* Draw end pixel */
813       if (gc_private->pen_width == 1)
814         if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
815           g_warning ("gdk_draw_segments: LineTo #2 failed");
816     }
817   gdk_gc_postdraw (drawable_private, gc_private);
818 }
819
820 void
821 gdk_draw_lines (GdkDrawable *drawable,
822                 GdkGC       *gc,
823                 GdkPoint    *points,
824                 gint         npoints)
825 {
826   GdkDrawablePrivate *drawable_private;
827   GdkGCPrivate *gc_private;
828   HDC hdc;
829   POINT *pts;
830   int i;
831
832   if (npoints < 2)
833     return;
834
835   g_return_if_fail (drawable != NULL);
836   g_return_if_fail (points != NULL);
837   g_return_if_fail (gc != NULL);
838
839   if (GDK_DRAWABLE_DESTROYED (drawable))
840     return;
841   drawable_private = (GdkDrawablePrivate*) drawable;
842   gc_private = (GdkGCPrivate*) gc;
843
844   hdc = gdk_gc_predraw (drawable_private, gc_private);
845 #if 1
846   pts = g_malloc (npoints * sizeof (POINT));
847
848   for (i = 0; i < npoints; i++)
849     {
850       pts[i].x = points[i].x;
851       pts[i].y = points[i].y;
852     }
853   
854   if (!Polyline (hdc, pts, npoints))
855     g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints);
856   
857   g_free (pts);
858   
859   /* Draw end pixel */
860   if (gc_private->pen_width == 1)
861     {
862       MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
863       if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
864         g_warning ("gdk_draw_lines: LineTo failed");
865     }
866 #else
867   MoveToEx (hdc, points[0].x, points[0].y, NULL);
868   for (i = 1; i < npoints; i++)
869     if (!LineTo (hdc, points[i].x, points[i].y))
870       g_warning ("gdk_draw_lines: LineTo #1 failed");
871   
872   /* Draw end pixel */
873   if (gc_private->pen_width == 1)
874     if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
875       g_warning ("gdk_draw_lines: LineTo #2 failed");
876 #endif  
877   gdk_gc_postdraw (drawable_private, gc_private);
878 }