]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdrawable-win32.c
Win32 version of GDK source files and resource files (cursors and icons).
[~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 #include "gdk.h"
31 #include "gdkprivate.h"
32
33 #ifndef M_TWOPI
34 #define M_TWOPI         (2.0 * 3.14159265358979323846)
35 #endif
36
37 void
38 gdk_draw_point (GdkDrawable *drawable,
39                 GdkGC       *gc,
40                 gint         x,
41                 gint         y)
42 {
43   GdkWindowPrivate *drawable_private;
44   GdkGCPrivate *gc_private;
45   HDC hdc;
46   HBRUSH hbr;
47   RECT rect;
48
49   g_return_if_fail (drawable != NULL);
50   g_return_if_fail (gc != NULL);
51
52   drawable_private = (GdkWindowPrivate*) drawable;
53   if (drawable_private->destroyed)
54     return;
55   gc_private = (GdkGCPrivate*) gc;
56
57   hdc = gdk_gc_predraw (drawable_private, gc_private);
58   hbr = GetCurrentObject (hdc, OBJ_BRUSH);
59   /* We use FillRect because SetPixel wants the COLORREF directly,
60    * and doesn't use the current brush, which is what we want.
61    */
62   rect.left = x;
63   rect.top = y;
64   rect.right = rect.left + 1;
65   rect.bottom = rect.top + 1;
66   FillRect (hdc, &rect, hbr);
67   
68   gdk_gc_postdraw (drawable_private, gc_private);
69 }
70
71 void
72 gdk_draw_line (GdkDrawable *drawable,
73                GdkGC       *gc,
74                gint         x1,
75                gint         y1,
76                gint         x2,
77                gint         y2)
78 {
79   GdkWindowPrivate *drawable_private;
80   GdkGCPrivate *gc_private;
81   HDC hdc;
82
83   g_return_if_fail (drawable != NULL);
84   g_return_if_fail (gc != NULL);
85
86   drawable_private = (GdkWindowPrivate*) drawable;
87   if (drawable_private->destroyed)
88     return;
89   gc_private = (GdkGCPrivate*) gc;
90
91   hdc = gdk_gc_predraw (drawable_private, gc_private);
92     
93   GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n",
94                            drawable_private->xwindow, gc_private,
95                            x1, y1, x2, y2));
96   
97   MoveToEx (hdc, x1, y1, NULL);
98   if (!LineTo (hdc, x2, y2))
99     g_warning ("gdk_draw_line: LineTo #1 failed");
100   /* LineTo doesn't draw the last point, so if we have a pen width of 1,
101    * we draw the end pixel separately... With wider pens it hopefully
102    * doesn't matter?
103    */
104   if (gc_private->pen_width == 1)
105     if (!LineTo (hdc, x2 + 1, y2))
106       g_warning ("gdk_draw_line: LineTo #2 failed");
107   gdk_gc_postdraw (drawable_private, gc_private);
108 }
109
110 void
111 gdk_draw_rectangle (GdkDrawable *drawable,
112                     GdkGC       *gc,
113                     gint         filled,
114                     gint         x,
115                     gint         y,
116                     gint         width,
117                     gint         height)
118 {
119   GdkWindowPrivate *drawable_private;
120   GdkGCPrivate *gc_private;
121   HDC hdc;
122   LOGBRUSH lb;
123   HPEN hpen;
124   HBRUSH hbr;
125   HGDIOBJ oldpen, oldbrush;
126
127   g_return_if_fail (drawable != NULL);
128   g_return_if_fail (gc != NULL);
129
130   drawable_private = (GdkWindowPrivate*) drawable;
131   if (drawable_private->destroyed)
132     return;
133   gc_private = (GdkGCPrivate*) gc;
134
135   if (width == -1)
136     width = drawable_private->width;
137   if (height == -1)
138     height = drawable_private->height;
139
140   hdc = gdk_gc_predraw (drawable_private, gc_private);
141
142   GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
143                            drawable_private->xwindow,
144                            gc_private,
145                            (filled ? "fill " : ""),
146                            width, height, x, y));
147     
148 #if 0
149   {
150     HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
151     HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
152     LOGBRUSH lbr;
153     LOGPEN lpen;
154     GetObject (hbr, sizeof (lbr), &lbr);
155     GetObject (hpen, sizeof (lpen), &lpen);
156     
157     g_print ("current brush: style = %s, color = 0x%.08x\n",
158              (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
159              lbr.lbColor);
160     g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
161              (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
162              lpen.lopnWidth,
163              lpen.lopnColor);
164   }
165 #endif
166
167   if (filled)
168     oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
169   else
170     oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
171   
172   if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
173     g_warning ("gdk_draw_rectangle: Rectangle failed");
174   
175   if (filled)
176     SelectObject (hdc, oldpen);
177   else
178     SelectObject (hdc, oldbrush);
179
180   gdk_gc_postdraw (drawable_private, gc_private);
181 }
182
183 void
184 gdk_draw_arc (GdkDrawable *drawable,
185               GdkGC       *gc,
186               gint         filled,
187               gint         x,
188               gint         y,
189               gint         width,
190               gint         height,
191               gint         angle1,
192               gint         angle2)
193 {
194   GdkWindowPrivate *drawable_private;
195   GdkGCPrivate *gc_private;
196   HDC hdc;
197   int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
198
199   g_return_if_fail (drawable != NULL);
200   g_return_if_fail (gc != NULL);
201
202   drawable_private = (GdkWindowPrivate*) drawable;
203   if (drawable_private->destroyed)
204     return;
205   gc_private = (GdkGCPrivate*) gc;
206
207   if (width == -1)
208     width = drawable_private->width;
209   if (height == -1)
210     height = drawable_private->height;
211
212   hdc = gdk_gc_predraw (drawable_private, gc_private);
213
214   nXStartArc = x + width/2 + (int) (sin(angle1/64.*M_TWOPI)*width);
215   nYStartArc = y + height/2 + (int) (cos(angle1/64.*M_TWOPI)*height);
216   nXEndArc = x + width/2 + (int) (sin(angle2/64.*M_TWOPI)*width);
217   nYEndArc = y + height/2 + (int) (cos(angle2/64.*M_TWOPI)*height);
218
219   if (filled)
220     {
221       if (!Pie (hdc, x, y, x+width, y+height,
222                 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
223         g_warning ("gdk_draw_arc: Pie failed");
224     }
225   else
226     {
227       if (!Arc (hdc, x, y, x+width, y+height,
228                 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
229         g_warning ("gdk_draw_arc: Arc failed");
230     }
231   gdk_gc_postdraw (drawable_private, gc_private);
232 }
233
234 void
235 gdk_draw_polygon (GdkDrawable *drawable,
236                   GdkGC       *gc,
237                   gint         filled,
238                   GdkPoint    *points,
239                   gint         npoints)
240 {
241   GdkWindowPrivate *drawable_private;
242   GdkGCPrivate *gc_private;
243   HDC hdc;
244   POINT *pts;
245   int i;
246
247   g_return_if_fail (drawable != NULL);
248   g_return_if_fail (gc != NULL);
249
250   drawable_private = (GdkWindowPrivate*) drawable;
251   if (drawable_private->destroyed)
252     return;
253   gc_private = (GdkGCPrivate*) gc;
254
255   hdc = gdk_gc_predraw (drawable_private, gc_private);
256   pts = g_malloc ((npoints+1) * sizeof (POINT));
257
258   GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n",
259                            drawable_private->xwindow, gc_private,
260                            npoints));
261
262   for (i = 0; i < npoints; i++)
263     {
264       pts[i].x = points[i].x;
265       pts[i].y = points[i].y;
266     }
267   
268   if ((points[0].x != points[npoints-1].x) ||
269       (points[0].y != points[npoints-1].y)) 
270     {
271       pts[npoints].x = points[0].x;
272       pts[npoints].y = points[0].y;
273       npoints++;
274     }
275   if (filled)
276     {
277       if (!Polygon (hdc, pts, npoints))
278         g_warning ("gdk_draw_polygon: Polygon failed");
279     }
280   else
281     {
282       if (!Polyline (hdc, pts, npoints))
283         g_warning ("gdk_draw_polygon: Polyline failed");
284     }
285   g_free (pts);
286   gdk_gc_postdraw (drawable_private, gc_private);
287 }
288
289 /* gdk_draw_string
290  */
291 void
292 gdk_draw_string (GdkDrawable *drawable,
293                  GdkFont     *font,
294                  GdkGC       *gc,
295                  gint         x,
296                  gint         y,
297                  const gchar *string)
298 {
299   gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
300 }
301
302 /* gdk_draw_text
303  *
304  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
305  *
306  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
307  */
308 void
309 gdk_draw_text (GdkDrawable *drawable,
310                GdkFont     *font,
311                GdkGC       *gc,
312                gint         x,
313                gint         y,
314                const gchar *text,
315                gint         text_length)
316 {
317   GdkWindowPrivate *drawable_private;
318   GdkFontPrivate *font_private;
319   GdkGCPrivate *gc_private;
320   HDC hdc;
321   HFONT xfont;
322   HGDIOBJ oldfont;
323
324   g_return_if_fail (drawable != NULL);
325   g_return_if_fail (font != NULL);
326   g_return_if_fail (gc != NULL);
327   g_return_if_fail (text != NULL);
328
329   drawable_private = (GdkWindowPrivate*) drawable;
330   if (drawable_private->destroyed)
331     return;
332   gc_private = (GdkGCPrivate*) gc;
333   font_private = (GdkFontPrivate*) font;
334
335   if (font->type == GDK_FONT_FONT)
336     {
337       hdc = gdk_gc_predraw (drawable_private, gc_private);
338       xfont = (HFONT) font_private->xfont;
339
340       GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
341                                "+%d+%d font: %#x \"%.*s\" length: %d\n",
342                                drawable_private->xwindow,
343                                gc_private, gc_private->xgc,
344                                x, y, xfont,
345                                (text_length > 10 ? 10 : text_length),
346                                text, text_length));
347       
348       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
349         g_warning ("gdk_draw_text: SelectObject failed");
350       if (!TextOutA (hdc, x, y, text, text_length))
351         g_warning ("gdk_draw_text: TextOutA failed");
352       SelectObject (hdc, oldfont);
353       gdk_gc_postdraw (drawable_private, gc_private);
354     }
355   else
356     g_error ("undefined font type");
357 }
358
359 void
360 gdk_draw_text_wc (GdkDrawable    *drawable,
361                   GdkFont        *font,
362                   GdkGC          *gc,
363                   gint            x,
364                   gint            y,
365                   const GdkWChar *text,
366                   gint            text_length)
367 {
368   GdkWindowPrivate *drawable_private;
369   GdkFontPrivate *font_private;
370   GdkGCPrivate *gc_private;
371   gint i;
372   wchar_t *wcstr;
373
374   g_return_if_fail (drawable != NULL);
375   g_return_if_fail (font != NULL);
376   g_return_if_fail (gc != NULL);
377   g_return_if_fail (text != NULL);
378
379   drawable_private = (GdkWindowPrivate*) drawable;
380   if (drawable_private->destroyed)
381     return;
382   gc_private = (GdkGCPrivate*) gc;
383   font_private = (GdkFontPrivate*) font;
384
385   if (font->type == GDK_FONT_FONT)
386     {
387       HDC hdc;
388       HFONT xfont;
389       HGDIOBJ oldfont;
390
391       hdc = gdk_gc_predraw (drawable_private, gc_private);
392       xfont = (HFONT) font_private->xfont;
393
394       GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
395                                "+%d+%d font: %#x length: %d\n",
396                                drawable_private->xwindow,
397                                gc_private, gc_private->xgc,
398                                x, y, xfont,
399                                text_length));
400       
401       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
402         g_warning ("gdk_draw_text: SelectObject failed");
403       wcstr = g_new (wchar_t, text_length);
404       for (i = 0; i < text_length; i++)
405         wcstr[i] = text[i];
406       if (!TextOutW (hdc, x, y, wcstr, text_length))
407         g_warning ("gdk_draw_text: TextOutW failed");
408       g_free (wcstr);
409       SelectObject (hdc, oldfont);
410       gdk_gc_postdraw (drawable_private, gc_private);
411     }
412   else
413     g_error ("undefined font type");
414 }
415
416 void
417 gdk_draw_pixmap (GdkDrawable *drawable,
418                  GdkGC       *gc,
419                  GdkPixmap   *src,
420                  gint         xsrc,
421                  gint         ysrc,
422                  gint         xdest,
423                  gint         ydest,
424                  gint         width,
425                  gint         height)
426 {
427   GdkWindowPrivate *drawable_private;
428   GdkWindowPrivate *src_private;
429   GdkGCPrivate *gc_private;
430   HDC hdc;
431   HDC srcdc;
432   HGDIOBJ hgdiobj;
433
434   g_return_if_fail (drawable != NULL);
435   g_return_if_fail (src != NULL);
436   g_return_if_fail (gc != NULL);
437
438   drawable_private = (GdkWindowPrivate*) drawable;
439   src_private = (GdkWindowPrivate*) src;
440   if (drawable_private->destroyed || src_private->destroyed)
441     return;
442   gc_private = (GdkGCPrivate*) gc;
443
444   if (width == -1)
445     width = src_private->width;
446   if (height == -1)
447     height = src_private->height;
448
449   hdc = gdk_gc_predraw (drawable_private, gc_private);
450
451   GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x destdc: (%d) %#x "
452                            "src: %#x %dx%d@+%d+%d\n",
453                            drawable_private->xwindow, gc_private, hdc,
454                            src_private->xwindow,
455                            width, height, xdest, ydest));
456
457   /* Strangely enough, this function is called also to bitblt
458    * from a window.
459    */
460   if (src_private->window_type == GDK_WINDOW_PIXMAP)
461     {
462       if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
463         g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
464       
465       if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
466         g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
467       
468       if (!BitBlt (hdc, xdest, ydest, width, height,
469                    srcdc, xsrc, ysrc, SRCCOPY))
470         g_warning ("gdk_draw_pixmap: BitBlt failed");
471       
472       if ((SelectObject (srcdc, hgdiobj) == NULL))
473         g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
474       
475       if (!DeleteDC (srcdc))
476         g_warning ("gdk_draw_pixmap: DeleteDC failed");
477     }
478   else
479     {
480       if ((srcdc = GetDC (src_private->xwindow)) == NULL)
481         g_warning ("gdk_draw_pixmap: GetDC failed");
482       
483       if (!BitBlt (hdc, xdest, ydest, width, height,
484                    srcdc, xsrc, ysrc, SRCCOPY))
485         g_warning ("gdk_draw_pixmap: BitBlt failed");
486       
487       ReleaseDC (src_private->xwindow, srcdc);
488     }
489   gdk_gc_postdraw (drawable_private, gc_private);
490 }
491
492 void
493 gdk_draw_image (GdkDrawable *drawable,
494                 GdkGC       *gc,
495                 GdkImage    *image,
496                 gint         xsrc,
497                 gint         ysrc,
498                 gint         xdest,
499                 gint         ydest,
500                 gint         width,
501                 gint         height)
502 {
503   GdkImagePrivate *image_private;
504
505   g_return_if_fail (drawable != NULL);
506   g_return_if_fail (image != NULL);
507   g_return_if_fail (gc != NULL);
508
509   image_private = (GdkImagePrivate*) image;
510
511   g_return_if_fail (image_private->image_put != NULL);
512
513   if (width == -1)
514     width = image->width;
515   if (height == -1)
516     height = image->height;
517
518   (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
519                                 xdest, ydest, width, height);
520 }
521
522 void
523 gdk_draw_points (GdkDrawable *drawable,
524                  GdkGC       *gc,
525                  GdkPoint    *points,
526                  gint         npoints)
527 {
528   GdkWindowPrivate *drawable_private;
529   GdkGCPrivate *gc_private;
530   HDC hdc;
531   HBRUSH hbr;
532   int i;
533
534   g_return_if_fail (drawable != NULL);
535   g_return_if_fail ((points != NULL) && (npoints > 0));
536   g_return_if_fail (gc != NULL);
537
538   drawable_private = (GdkWindowPrivate*) drawable;
539   if (drawable_private->destroyed)
540     return;
541   gc_private = (GdkGCPrivate*) gc;
542
543   hdc = gdk_gc_predraw (drawable_private, gc_private);
544   hbr = GetCurrentObject (hdc, OBJ_BRUSH);
545   
546   for (i = 0; i < npoints; i++)
547     {
548       RECT rect;
549       
550       rect.left = points[i].x;
551       rect.top = points[i].y;
552       rect.right = rect.left + 1;
553       rect.bottom = rect.top + 1;
554       if (!FillRect (hdc, &rect, hbr))
555         g_warning ("gdk_draw_points: FillRect failed");
556     }
557   gdk_gc_postdraw (drawable_private, gc_private);
558 }
559
560 void
561 gdk_draw_segments (GdkDrawable *drawable,
562                    GdkGC       *gc,
563                    GdkSegment  *segs,
564                    gint         nsegs)
565 {
566   GdkWindowPrivate *drawable_private;
567   GdkGCPrivate *gc_private;
568   HDC hdc;
569   int i;
570
571   if (nsegs <= 0)
572     return;
573
574   g_return_if_fail (drawable != NULL);
575   g_return_if_fail (segs != NULL);
576   g_return_if_fail (gc != NULL);
577
578   drawable_private = (GdkWindowPrivate*) drawable;
579   if (drawable_private->destroyed)
580     return;
581   gc_private = (GdkGCPrivate*) gc;
582
583   hdc = gdk_gc_predraw (drawable_private, gc_private);
584
585   for (i = 0; i < nsegs; i++)
586     {
587       MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL);
588       if (!LineTo (hdc, segs[i].x2, segs[i].y2))
589         g_warning ("gdk_draw_segments: LineTo #1 failed");
590       
591       /* Draw end pixel */
592       if (gc_private->pen_width == 1)
593         if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
594           g_warning ("gdk_draw_segments: LineTo #2 failed");
595     }
596   gdk_gc_postdraw (drawable_private, gc_private);
597 }
598
599 void
600 gdk_draw_lines (GdkDrawable *drawable,
601                 GdkGC       *gc,
602                 GdkPoint    *points,
603                 gint         npoints)
604 {
605   GdkWindowPrivate *drawable_private;
606   GdkGCPrivate *gc_private;
607   HDC hdc;
608   POINT *pts;
609   int i;
610
611   if (npoints <= 0)
612     return;
613
614   g_return_if_fail (drawable != NULL);
615   g_return_if_fail (points != NULL);
616   g_return_if_fail (gc != NULL);
617
618   drawable_private = (GdkWindowPrivate*) drawable;
619   gc_private = (GdkGCPrivate*) gc;
620
621   hdc = gdk_gc_predraw (drawable_private, gc_private);
622 #if 1
623   pts = g_malloc (npoints * sizeof (POINT));
624
625   for (i = 0; i < npoints; i++)
626     {
627       pts[i].x = points[i].x;
628       pts[i].y = points[i].y;
629     }
630   
631   if (!Polyline (hdc, pts, npoints))
632     g_warning ("gdk_draw_lines: Polyline failed");
633   
634   g_free (pts);
635   
636   /* Draw end pixel */
637   if (gc_private->pen_width == 1)
638     {
639       MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
640       if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
641         g_warning ("gdk_draw_lines: LineTo failed");
642     }
643 #else
644   MoveToEx (hdc, points[0].x, points[0].y, NULL);
645   for (i = 1; i < npoints; i++)
646     if (!LineTo (hdc, points[i].x, points[i].y))
647       g_warning ("gdk_draw_lines: LineTo #1 failed");
648   
649   /* Draw end pixel */
650   if (gc_private->pen_width == 1)
651     if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
652       g_warning ("gdk_draw_lines: LineTo #2 failed");
653 #endif  
654   gdk_gc_postdraw (drawable_private, gc_private);
655 }