]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdrawable-win32.c
593c98cd80a9f21bfb73c72399829191834a1a2b
[~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  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
442  */
443 void
444 gdk_draw_text (GdkDrawable *drawable,
445                GdkFont     *font,
446                GdkGC       *gc,
447                gint         x,
448                gint         y,
449                const gchar *text,
450                gint         text_length)
451 {
452   GdkDrawablePrivate *drawable_private;
453   GdkFontPrivate *font_private;
454   GdkGCPrivate *gc_private;
455   HDC hdc;
456   HFONT xfont;
457   HGDIOBJ oldfont;
458   wchar_t *wcstr;
459   gint wlen;
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
469   if (text_length == 0)
470     return;
471
472   drawable_private = (GdkDrawablePrivate*) drawable;
473   gc_private = (GdkGCPrivate*) gc;
474   font_private = (GdkFontPrivate*) font;
475
476   if (font->type == GDK_FONT_FONT)
477     {
478       hdc = gdk_gc_predraw (drawable_private, gc_private);
479       xfont = (HFONT) font_private->xfont;
480
481       GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
482                                "+%d+%d font: %#x \"%.*s\" length: %d\n",
483                                drawable_private->xwindow,
484                                gc_private, gc_private->xgc,
485                                x, y, xfont,
486                                (text_length > 10 ? 10 : text_length),
487                                text, text_length));
488       
489       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
490         g_warning ("gdk_draw_text: SelectObject failed");
491       if (font_private->cpinfo.MaxCharSize > 1)
492         {
493           wcstr = g_new (wchar_t, text_length);
494           if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
495                                            text, text_length,
496                                            wcstr, text_length)) == 0)
497             g_warning ("gdk_draw_text: MultiByteToWideChar failed");
498           else if (!TextOutW (hdc, x, y, wcstr, wlen))
499             g_warning ("gdk_draw_text: TextOutW failed");
500           g_free (wcstr);
501         }
502       else
503         {
504           if (!TextOutA (hdc, x, y, text, text_length))
505             g_warning ("gdk_draw_text: TextOutA failed");
506         }
507       if (oldfont != NULL)
508         SelectObject (hdc, oldfont);
509       gdk_gc_postdraw (drawable_private, gc_private);
510     }
511   else
512     g_error ("undefined font type");
513 }
514
515 void
516 gdk_draw_text_wc (GdkDrawable    *drawable,
517                   GdkFont        *font,
518                   GdkGC          *gc,
519                   gint            x,
520                   gint            y,
521                   const GdkWChar *text,
522                   gint            text_length)
523 {
524   GdkDrawablePrivate *drawable_private;
525   GdkFontPrivate *font_private;
526   GdkGCPrivate *gc_private;
527   gint i, wlen;
528   wchar_t *wcstr;
529   guchar *str;
530
531   g_return_if_fail (drawable != NULL);
532   g_return_if_fail (font != NULL);
533   g_return_if_fail (gc != NULL);
534   g_return_if_fail (text != NULL);
535
536   if (GDK_DRAWABLE_DESTROYED (drawable))
537     return;
538
539   if (text_length == 0)
540     return;
541
542   drawable_private = (GdkDrawablePrivate*) drawable;
543   gc_private = (GdkGCPrivate*) gc;
544   font_private = (GdkFontPrivate*) font;
545
546   if (font->type == GDK_FONT_FONT)
547     {
548       HDC hdc;
549       HFONT xfont;
550       HGDIOBJ oldfont;
551
552       hdc = gdk_gc_predraw (drawable_private, gc_private);
553       xfont = (HFONT) font_private->xfont;
554
555       GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
556                                "+%d+%d font: %#x length: %d\n",
557                                drawable_private->xwindow,
558                                gc_private, gc_private->xgc,
559                                x, y, xfont,
560                                text_length));
561       
562       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
563           g_warning ("gdk_draw_text_wc: SelectObject failed");
564 #if 0 /* No. Don't use TextOutW directly. Compare to the X11 version,
565        * it uses plain XDrawString for GDK_FONT_FONT fonts, too.
566        * TextOutW by definition interprets the string as Unicode.
567        * We don't have that, but either chars from some single-byte codepage
568        * or from a DBCS.
569        */
570       wcstr = g_new (wchar_t, text_length);
571       for (i = 0; i < text_length; i++)
572         wcstr[i] = text[i];
573       if (!TextOutW (hdc, x, y, wcstr, text_length))
574         g_warning ("gdk_draw_text_wc: TextOutW failed");
575       g_free (wcstr);
576 #else
577       str = g_new (guchar, text_length);
578       for (i = 0; i < text_length; i++)
579         str[i] = text[i];
580       if (font_private->cpinfo.MaxCharSize > 1)
581         {
582           wcstr = g_new (wchar_t, text_length);
583           if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
584                                            str, text_length,
585                                            wcstr, text_length)) == 0)
586             g_warning ("gdk_draw_text: MultiByteToWideChar failed");
587           else if (!TextOutW (hdc, x, y, wcstr, wlen))
588             g_warning ("gdk_draw_text_wc: TextOutW failed");
589           g_free (wcstr);
590         }
591       else
592         {
593           if (!TextOutA (hdc, x, y, str, text_length))
594             g_warning ("gdk_draw_text_wc: TextOutA failed");
595         }
596       g_free (str);
597 #endif
598       if (oldfont != NULL)
599         SelectObject (hdc, oldfont);
600       gdk_gc_postdraw (drawable_private, gc_private);
601     }
602   else
603     g_error ("undefined font type");
604 }
605
606 void
607 gdk_draw_pixmap (GdkDrawable *drawable,
608                  GdkGC       *gc,
609                  GdkPixmap   *src,
610                  gint         xsrc,
611                  gint         ysrc,
612                  gint         xdest,
613                  gint         ydest,
614                  gint         width,
615                  gint         height)
616 {
617   GdkDrawablePrivate *drawable_private;
618   GdkDrawablePrivate *src_private;
619   GdkGCPrivate *gc_private;
620   HDC hdc;
621   HDC srcdc;
622   HGDIOBJ hgdiobj;
623   HRGN src_rgn, draw_rgn, outside_rgn;
624   RECT r;
625
626   g_return_if_fail (drawable != NULL);
627   g_return_if_fail (src != NULL);
628   g_return_if_fail (gc != NULL);
629
630   if (GDK_DRAWABLE_DESTROYED (drawable) || GDK_DRAWABLE_DESTROYED (src))
631     return;
632   drawable_private = (GdkDrawablePrivate*) drawable;
633   src_private = (GdkDrawablePrivate*) src;
634   gc_private = (GdkGCPrivate*) gc;
635
636   if (width == -1)
637     width = src_private->width; /* Or should we subtract xsrc? */
638   if (height == -1)
639     height = src_private->height; /* Ditto? */
640
641   GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
642                            "src: %#x %dx%d@+%d+%d"
643                            " dest: %#x @+%d+%d\n",
644                            drawable_private->xwindow,
645                            src_private->xwindow,
646                            width, height, xsrc, ysrc,
647                            drawable_private->xwindow, xdest, ydest));
648
649   hdc = gdk_gc_predraw (drawable_private, gc_private);
650
651   src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
652   draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
653   SetRectEmpty (&r);
654   outside_rgn = CreateRectRgnIndirect (&r);
655   
656   if (drawable_private->window_type != GDK_DRAWABLE_PIXMAP)
657     {
658       /* If we are drawing on a window, calculate the region that is
659        * outside the source pixmap, and invalidate that, causing it to
660        * be cleared. XXX
661        */
662       if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
663         {
664           OffsetRgn (outside_rgn, xdest, ydest);
665           GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
666                            g_print ("...calling InvalidateRgn, "
667                                     "bbox: %dx%d@+%d+%d\n",
668                                     r.right - r.left - 1, r.bottom - r.top - 1,
669                                     r.left, r.top)));
670           InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE);
671         }
672     }
673
674 #if 1 /* Don't know if this is necessary  */
675   if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
676     g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
677
678   GetRgnBox (draw_rgn, &r);
679   if (r.left != xsrc
680       || r.top != ysrc
681       || r.right != xsrc + width + 1
682       || r.bottom != ysrc + height + 1)
683     {
684       xdest += r.left - xsrc;
685       xsrc = r.left;
686       ydest += r.top - ysrc;
687       ysrc = r.top;
688       width = r.right - xsrc - 1;
689       height = r.bottom - ysrc - 1;
690       
691       GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
692                                "dest: @+%d+%d\n",
693                                width, height, xsrc, ysrc,
694                                xdest, ydest));
695     }
696 #endif
697
698   DeleteObject (src_rgn);
699   DeleteObject (draw_rgn);
700   DeleteObject (outside_rgn);
701
702   /* Strangely enough, this function is called also to bitblt
703    * from a window.
704    */
705   if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
706     {
707       if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
708         g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
709       
710       if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
711         g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
712       
713       if (!BitBlt (hdc, xdest, ydest, width, height,
714                    srcdc, xsrc, ysrc, SRCCOPY))
715         g_warning ("gdk_draw_pixmap: BitBlt failed");
716       
717       if ((SelectObject (srcdc, hgdiobj) == NULL))
718         g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
719       
720       if (!DeleteDC (srcdc))
721         g_warning ("gdk_draw_pixmap: DeleteDC failed");
722     }
723   else
724     {
725       if (drawable_private->xwindow == src_private->xwindow)
726         {
727           /* Blitting inside a window, use ScrollDC */
728           RECT scrollRect, clipRect, emptyRect;
729           HRGN updateRgn;
730
731           scrollRect.left = MIN (xsrc, xdest);
732           scrollRect.top = MIN (ysrc, ydest);
733           scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
734           scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
735
736           clipRect.left = xdest;
737           clipRect.top = ydest;
738           clipRect.right = xdest + width + 1;
739           clipRect.bottom = ydest + height + 1;
740
741           SetRectEmpty (&emptyRect);
742           updateRgn = CreateRectRgnIndirect (&emptyRect);
743           if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
744                          &scrollRect, &clipRect,
745                          updateRgn, NULL))
746             g_warning ("gdk_draw_pixmap: ScrollDC failed");
747           if (!InvalidateRgn (drawable_private->xwindow, updateRgn, FALSE))
748             g_warning ("gdk_draw_pixmap: InvalidateRgn failed");
749           if (!UpdateWindow (drawable_private->xwindow))
750             g_warning ("gdk_draw_pixmap: UpdateWindow failed");
751         }
752       else
753         {
754           if ((srcdc = GetDC (src_private->xwindow)) == NULL)
755             g_warning ("gdk_draw_pixmap: GetDC failed");
756           
757           if (!BitBlt (hdc, xdest, ydest, width, height,
758                        srcdc, xsrc, ysrc, SRCCOPY))
759             g_warning ("gdk_draw_pixmap: BitBlt failed");
760           ReleaseDC (src_private->xwindow, srcdc);
761         }
762     }
763   gdk_gc_postdraw (drawable_private, gc_private);
764 }
765
766 void
767 gdk_draw_image (GdkDrawable *drawable,
768                 GdkGC       *gc,
769                 GdkImage    *image,
770                 gint         xsrc,
771                 gint         ysrc,
772                 gint         xdest,
773                 gint         ydest,
774                 gint         width,
775                 gint         height)
776 {
777   GdkImagePrivate *image_private;
778
779   g_return_if_fail (drawable != NULL);
780   g_return_if_fail (image != NULL);
781   g_return_if_fail (gc != NULL);
782
783   image_private = (GdkImagePrivate*) image;
784
785   g_return_if_fail (image_private->image_put != NULL);
786
787   if (width == -1)
788     width = image->width;
789   if (height == -1)
790     height = image->height;
791
792   (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
793                                 xdest, ydest, width, height);
794 }
795
796 void
797 gdk_draw_points (GdkDrawable *drawable,
798                  GdkGC       *gc,
799                  GdkPoint    *points,
800                  gint         npoints)
801 {
802   GdkDrawablePrivate *drawable_private;
803   GdkGCPrivate *gc_private;
804   HDC hdc;
805   int i;
806
807   g_return_if_fail (drawable != NULL);
808   g_return_if_fail ((points != NULL) && (npoints > 0));
809   g_return_if_fail (gc != NULL);
810
811   if (GDK_DRAWABLE_DESTROYED (drawable))
812     return;
813   drawable_private = (GdkDrawablePrivate*) drawable;
814   gc_private = (GdkGCPrivate*) gc;
815
816   hdc = gdk_gc_predraw (drawable_private, gc_private);
817   
818   GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x "
819                            "npoints: %d\n",
820                            drawable_private->xwindow, gc_private, hdc,
821                            npoints));
822
823   for (i = 0; i < npoints; i++)
824     {
825       if (!MoveToEx (hdc, points[i].x, points[i].y, NULL))
826         g_warning ("gdk_draw_points: MoveToEx failed");
827       if (!LineTo (hdc, points[i].x + 1, points[i].y))
828         g_warning ("gdk_draw_points: LineTo failed");
829     }
830   gdk_gc_postdraw (drawable_private, gc_private);
831 }
832
833 void
834 gdk_draw_segments (GdkDrawable *drawable,
835                    GdkGC       *gc,
836                    GdkSegment  *segs,
837                    gint         nsegs)
838 {
839   GdkDrawablePrivate *drawable_private;
840   GdkGCPrivate *gc_private;
841   HDC hdc;
842   int i;
843
844   if (nsegs <= 0)
845     return;
846
847   g_return_if_fail (drawable != NULL);
848   g_return_if_fail (segs != NULL);
849   g_return_if_fail (gc != NULL);
850
851   if (GDK_DRAWABLE_DESTROYED (drawable))
852     return;
853   drawable_private = (GdkDrawablePrivate*) drawable;
854   gc_private = (GdkGCPrivate*) gc;
855
856   hdc = gdk_gc_predraw (drawable_private, gc_private);
857
858   for (i = 0; i < nsegs; i++)
859     {
860       if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
861         g_warning ("gdk_draw_segments: MoveToEx failed");
862       if (!LineTo (hdc, segs[i].x2, segs[i].y2))
863         g_warning ("gdk_draw_segments: LineTo #1 failed");
864       
865       /* Draw end pixel */
866       if (gc_private->pen_width == 1)
867         if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
868           g_warning ("gdk_draw_segments: LineTo #2 failed");
869     }
870   gdk_gc_postdraw (drawable_private, gc_private);
871 }
872
873 void
874 gdk_draw_lines (GdkDrawable *drawable,
875                 GdkGC       *gc,
876                 GdkPoint    *points,
877                 gint         npoints)
878 {
879   GdkDrawablePrivate *drawable_private;
880   GdkGCPrivate *gc_private;
881   HDC hdc;
882   POINT *pts;
883   int i;
884
885   if (npoints < 2)
886     return;
887
888   g_return_if_fail (drawable != NULL);
889   g_return_if_fail (points != NULL);
890   g_return_if_fail (gc != NULL);
891
892   if (GDK_DRAWABLE_DESTROYED (drawable))
893     return;
894   drawable_private = (GdkDrawablePrivate*) drawable;
895   gc_private = (GdkGCPrivate*) gc;
896
897   hdc = gdk_gc_predraw (drawable_private, gc_private);
898 #if 1
899   pts = g_malloc (npoints * sizeof (POINT));
900
901   for (i = 0; i < npoints; i++)
902     {
903       pts[i].x = points[i].x;
904       pts[i].y = points[i].y;
905     }
906   
907   if (!Polyline (hdc, pts, npoints))
908     g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints);
909   
910   g_free (pts);
911   
912   /* Draw end pixel */
913   if (gc_private->pen_width == 1)
914     {
915       MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
916       if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
917         g_warning ("gdk_draw_lines: LineTo failed");
918     }
919 #else
920   MoveToEx (hdc, points[0].x, points[0].y, NULL);
921   for (i = 1; i < npoints; i++)
922     if (!LineTo (hdc, points[i].x, points[i].y))
923       g_warning ("gdk_draw_lines: LineTo #1 failed");
924   
925   /* Draw end pixel */
926   if (gc_private->pen_width == 1)
927     if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
928       g_warning ("gdk_draw_lines: LineTo #2 failed");
929 #endif  
930   gdk_gc_postdraw (drawable_private, gc_private);
931 }