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 "gdkprivate.h"
34 #define M_TWOPI (2.0 * 3.14159265358979323846)
38 gdk_draw_point (GdkDrawable *drawable,
43 GdkWindowPrivate *drawable_private;
44 GdkGCPrivate *gc_private;
47 g_return_if_fail (drawable != NULL);
48 g_return_if_fail (gc != NULL);
50 drawable_private = (GdkWindowPrivate*) drawable;
51 if (drawable_private->destroyed)
53 gc_private = (GdkGCPrivate*) gc;
55 hdc = gdk_gc_predraw (drawable_private, gc_private);
57 /* We use LineTo because SetPixel wants the COLORREF directly,
58 * and doesn't use the current pen, which is what we want.
60 if (!MoveToEx (hdc, x, y, NULL))
61 g_warning ("gdk_draw_point: MoveToEx failed");
62 if (!LineTo (hdc, x + 1, y))
63 g_warning ("gdk_draw_point: LineTo failed");
65 gdk_gc_postdraw (drawable_private, gc_private);
69 gdk_draw_line (GdkDrawable *drawable,
76 GdkWindowPrivate *drawable_private;
77 GdkGCPrivate *gc_private;
80 g_return_if_fail (drawable != NULL);
81 g_return_if_fail (gc != NULL);
83 drawable_private = (GdkWindowPrivate*) drawable;
84 if (drawable_private->destroyed)
86 gc_private = (GdkGCPrivate*) gc;
88 hdc = gdk_gc_predraw (drawable_private, gc_private);
90 GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n",
91 drawable_private->xwindow, gc_private,
94 MoveToEx (hdc, x1, y1, NULL);
95 if (!LineTo (hdc, x2, y2))
96 g_warning ("gdk_draw_line: LineTo #1 failed");
97 /* LineTo doesn't draw the last point, so if we have a pen width of 1,
98 * we draw the end pixel separately... With wider pens it hopefully
101 if (gc_private->pen_width == 1)
102 if (!LineTo (hdc, x2 + 1, y2))
103 g_warning ("gdk_draw_line: LineTo #2 failed");
104 gdk_gc_postdraw (drawable_private, gc_private);
108 gdk_draw_rectangle (GdkDrawable *drawable,
116 GdkWindowPrivate *drawable_private;
117 GdkGCPrivate *gc_private;
119 HGDIOBJ oldpen, oldbrush;
121 g_return_if_fail (drawable != NULL);
122 g_return_if_fail (gc != NULL);
124 drawable_private = (GdkWindowPrivate*) drawable;
125 if (drawable_private->destroyed)
127 gc_private = (GdkGCPrivate*) gc;
130 width = drawable_private->width;
132 height = drawable_private->height;
134 hdc = gdk_gc_predraw (drawable_private, gc_private);
136 GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
137 drawable_private->xwindow,
139 (filled ? "fill " : ""),
140 width, height, x, y));
144 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
145 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
148 GetObject (hbr, sizeof (lbr), &lbr);
149 GetObject (hpen, sizeof (lpen), &lpen);
151 g_print ("current brush: style = %s, color = 0x%.08x\n",
152 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
154 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
155 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
162 oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
164 oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
166 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
167 g_warning ("gdk_draw_rectangle: Rectangle failed");
170 SelectObject (hdc, oldpen);
172 SelectObject (hdc, oldbrush);
174 gdk_gc_postdraw (drawable_private, gc_private);
178 gdk_draw_arc (GdkDrawable *drawable,
188 GdkWindowPrivate *drawable_private;
189 GdkGCPrivate *gc_private;
191 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
193 g_return_if_fail (drawable != NULL);
194 g_return_if_fail (gc != NULL);
196 drawable_private = (GdkWindowPrivate*) drawable;
197 if (drawable_private->destroyed)
199 gc_private = (GdkGCPrivate*) gc;
202 width = drawable_private->width;
204 height = drawable_private->height;
206 if (width != 0 && height != 0)
208 hdc = gdk_gc_predraw (drawable_private, gc_private);
210 nXStartArc = x + width/2 + (int) (sin(angle1/64.*M_TWOPI)*width);
211 nYStartArc = y + height/2 + (int) (cos(angle1/64.*M_TWOPI)*height);
212 nXEndArc = x + width/2 + (int) (sin(angle2/64.*M_TWOPI)*width);
213 nYEndArc = y + height/2 + (int) (cos(angle2/64.*M_TWOPI)*height);
217 Pie (hdc, x, y, x+width, y+height,
218 nXStartArc, nYStartArc, nXEndArc, nYEndArc);
222 Arc (hdc, x, y, x+width, y+height,
223 nXStartArc, nYStartArc, nXEndArc, nYEndArc);
225 gdk_gc_postdraw (drawable_private, gc_private);
230 gdk_draw_polygon (GdkDrawable *drawable,
236 GdkWindowPrivate *drawable_private;
237 GdkGCPrivate *gc_private;
242 g_return_if_fail (drawable != NULL);
243 g_return_if_fail (gc != NULL);
245 drawable_private = (GdkWindowPrivate*) drawable;
246 if (drawable_private->destroyed)
248 gc_private = (GdkGCPrivate*) gc;
250 GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n",
251 drawable_private->xwindow, gc_private,
257 hdc = gdk_gc_predraw (drawable_private, gc_private);
258 pts = g_malloc ((npoints+1) * sizeof (POINT));
260 for (i = 0; i < npoints; i++)
262 pts[i].x = points[i].x;
263 pts[i].y = points[i].y;
266 if ((points[0].x != points[npoints-1].x) ||
267 (points[0].y != points[npoints-1].y))
269 pts[npoints].x = points[0].x;
270 pts[npoints].y = points[0].y;
275 if (!Polygon (hdc, pts, npoints))
276 g_warning ("gdk_draw_polygon: Polygon failed");
280 if (!Polyline (hdc, pts, npoints))
281 g_warning ("gdk_draw_polygon: Polyline failed");
284 gdk_gc_postdraw (drawable_private, gc_private);
290 gdk_draw_string (GdkDrawable *drawable,
297 gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
302 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
304 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
307 gdk_draw_text (GdkDrawable *drawable,
315 GdkWindowPrivate *drawable_private;
316 GdkFontPrivate *font_private;
317 GdkGCPrivate *gc_private;
322 g_return_if_fail (drawable != NULL);
323 g_return_if_fail (font != NULL);
324 g_return_if_fail (gc != NULL);
325 g_return_if_fail (text != NULL);
327 drawable_private = (GdkWindowPrivate*) drawable;
328 if (drawable_private->destroyed)
330 gc_private = (GdkGCPrivate*) gc;
331 font_private = (GdkFontPrivate*) font;
333 if (font->type == GDK_FONT_FONT)
335 hdc = gdk_gc_predraw (drawable_private, gc_private);
336 xfont = (HFONT) font_private->xfont;
338 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
339 "+%d+%d font: %#x \"%.*s\" length: %d\n",
340 drawable_private->xwindow,
341 gc_private, gc_private->xgc,
343 (text_length > 10 ? 10 : text_length),
346 if ((oldfont = SelectObject (hdc, xfont)) == NULL)
347 g_warning ("gdk_draw_text: SelectObject failed");
348 if (!TextOutA (hdc, x, y, text, text_length))
349 g_warning ("gdk_draw_text: TextOutA failed");
350 SelectObject (hdc, oldfont);
351 gdk_gc_postdraw (drawable_private, gc_private);
354 g_error ("undefined font type");
358 gdk_draw_text_wc (GdkDrawable *drawable,
363 const GdkWChar *text,
366 GdkWindowPrivate *drawable_private;
367 GdkFontPrivate *font_private;
368 GdkGCPrivate *gc_private;
372 g_return_if_fail (drawable != NULL);
373 g_return_if_fail (font != NULL);
374 g_return_if_fail (gc != NULL);
375 g_return_if_fail (text != NULL);
377 drawable_private = (GdkWindowPrivate*) drawable;
378 if (drawable_private->destroyed)
380 gc_private = (GdkGCPrivate*) gc;
381 font_private = (GdkFontPrivate*) font;
383 if (font->type == GDK_FONT_FONT)
389 hdc = gdk_gc_predraw (drawable_private, gc_private);
390 xfont = (HFONT) font_private->xfont;
392 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
393 "+%d+%d font: %#x length: %d\n",
394 drawable_private->xwindow,
395 gc_private, gc_private->xgc,
399 if ((oldfont = SelectObject (hdc, xfont)) == NULL)
400 g_warning ("gdk_draw_text: SelectObject failed");
401 wcstr = g_new (wchar_t, text_length);
402 for (i = 0; i < text_length; i++)
404 if (!TextOutW (hdc, x, y, wcstr, text_length))
405 g_warning ("gdk_draw_text: TextOutW failed");
407 SelectObject (hdc, oldfont);
408 gdk_gc_postdraw (drawable_private, gc_private);
411 g_error ("undefined font type");
415 gdk_draw_pixmap (GdkDrawable *drawable,
425 GdkWindowPrivate *drawable_private;
426 GdkWindowPrivate *src_private;
427 GdkGCPrivate *gc_private;
431 HRGN src_rgn, draw_rgn, outside_rgn;
434 g_return_if_fail (drawable != NULL);
435 g_return_if_fail (src != NULL);
436 g_return_if_fail (gc != NULL);
438 drawable_private = (GdkWindowPrivate*) drawable;
439 src_private = (GdkWindowPrivate*) src;
440 if (drawable_private->destroyed || src_private->destroyed)
442 gc_private = (GdkGCPrivate*) gc;
445 width = src_private->width; /* Or should we subtract xsrc? */
447 height = src_private->height; /* Ditto? */
449 GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
450 "src: %#x %dx%d@+%d+%d"
451 " dest: %#x @+%d+%d\n",
452 drawable_private->xwindow,
453 src_private->xwindow,
454 width, height, xsrc, ysrc,
455 drawable_private->xwindow, xdest, ydest));
457 hdc = gdk_gc_predraw (drawable_private, gc_private);
459 src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
460 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
462 outside_rgn = CreateRectRgnIndirect (&r);
464 if (drawable_private->window_type != GDK_WINDOW_PIXMAP)
466 /* If we are drawing on a window, calculate the region that is
467 * outside the source pixmap, and invalidate that, causing it to
470 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
472 OffsetRgn (outside_rgn, xdest, ydest);
473 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
474 g_print ("...calling InvalidateRgn, "
475 "bbox: %dx%d@+%d+%d\n",
476 r.right - r.left - 1, r.bottom - r.top - 1,
478 InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE);
482 #if 1 /* Don't know if this is necessary */
483 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
484 g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
486 GetRgnBox (draw_rgn, &r);
489 || r.right != xsrc + width + 1
490 || r.bottom != ysrc + height + 1)
492 xdest += r.left - xsrc;
494 ydest += r.top - ysrc;
496 width = r.right - xsrc - 1;
497 height = r.bottom - ysrc - 1;
499 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
501 width, height, xsrc, ysrc,
506 DeleteObject (src_rgn);
507 DeleteObject (draw_rgn);
508 DeleteObject (outside_rgn);
510 /* Strangely enough, this function is called also to bitblt
513 if (src_private->window_type == GDK_WINDOW_PIXMAP)
515 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
516 g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
518 if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
519 g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
521 if (!BitBlt (hdc, xdest, ydest, width, height,
522 srcdc, xsrc, ysrc, SRCCOPY))
523 g_warning ("gdk_draw_pixmap: BitBlt failed");
525 if ((SelectObject (srcdc, hgdiobj) == NULL))
526 g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
528 if (!DeleteDC (srcdc))
529 g_warning ("gdk_draw_pixmap: DeleteDC failed");
533 if ((srcdc = GetDC (src_private->xwindow)) == NULL)
534 g_warning ("gdk_draw_pixmap: GetDC failed");
536 if (!BitBlt (hdc, xdest, ydest, width, height,
537 srcdc, xsrc, ysrc, SRCCOPY))
538 g_warning ("gdk_draw_pixmap: BitBlt failed");
540 ReleaseDC (src_private->xwindow, srcdc);
542 gdk_gc_postdraw (drawable_private, gc_private);
546 gdk_draw_image (GdkDrawable *drawable,
556 GdkImagePrivate *image_private;
558 g_return_if_fail (drawable != NULL);
559 g_return_if_fail (image != NULL);
560 g_return_if_fail (gc != NULL);
562 image_private = (GdkImagePrivate*) image;
564 g_return_if_fail (image_private->image_put != NULL);
567 width = image->width;
569 height = image->height;
571 (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
572 xdest, ydest, width, height);
576 gdk_draw_points (GdkDrawable *drawable,
581 GdkWindowPrivate *drawable_private;
582 GdkGCPrivate *gc_private;
586 g_return_if_fail (drawable != NULL);
587 g_return_if_fail ((points != NULL) && (npoints > 0));
588 g_return_if_fail (gc != NULL);
590 drawable_private = (GdkWindowPrivate*) drawable;
591 if (drawable_private->destroyed)
593 gc_private = (GdkGCPrivate*) gc;
595 hdc = gdk_gc_predraw (drawable_private, gc_private);
597 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x "
599 drawable_private->xwindow, gc_private, hdc,
602 for (i = 0; i < npoints; i++)
604 if (!MoveToEx (hdc, points[i].x, points[i].y, NULL))
605 g_warning ("gdk_draw_points: MoveToEx failed");
606 if (!LineTo (hdc, points[i].x + 1, points[i].y))
607 g_warning ("gdk_draw_points: LineTo failed");
609 gdk_gc_postdraw (drawable_private, gc_private);
613 gdk_draw_segments (GdkDrawable *drawable,
618 GdkWindowPrivate *drawable_private;
619 GdkGCPrivate *gc_private;
626 g_return_if_fail (drawable != NULL);
627 g_return_if_fail (segs != NULL);
628 g_return_if_fail (gc != NULL);
630 drawable_private = (GdkWindowPrivate*) drawable;
631 if (drawable_private->destroyed)
633 gc_private = (GdkGCPrivate*) gc;
635 hdc = gdk_gc_predraw (drawable_private, gc_private);
637 for (i = 0; i < nsegs; i++)
639 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
640 g_warning ("gdk_draw_segments: MoveToEx failed");
641 if (!LineTo (hdc, segs[i].x2, segs[i].y2))
642 g_warning ("gdk_draw_segments: LineTo #1 failed");
645 if (gc_private->pen_width == 1)
646 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
647 g_warning ("gdk_draw_segments: LineTo #2 failed");
649 gdk_gc_postdraw (drawable_private, gc_private);
653 gdk_draw_lines (GdkDrawable *drawable,
658 GdkWindowPrivate *drawable_private;
659 GdkGCPrivate *gc_private;
667 g_return_if_fail (drawable != NULL);
668 g_return_if_fail (points != NULL);
669 g_return_if_fail (gc != NULL);
671 drawable_private = (GdkWindowPrivate*) drawable;
672 gc_private = (GdkGCPrivate*) gc;
674 hdc = gdk_gc_predraw (drawable_private, gc_private);
676 pts = g_malloc (npoints * sizeof (POINT));
678 for (i = 0; i < npoints; i++)
680 pts[i].x = points[i].x;
681 pts[i].y = points[i].y;
684 if (!Polyline (hdc, pts, npoints))
685 g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints);
690 if (gc_private->pen_width == 1)
692 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
693 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
694 g_warning ("gdk_draw_lines: LineTo failed");
697 MoveToEx (hdc, points[0].x, points[0].y, NULL);
698 for (i = 1; i < npoints; i++)
699 if (!LineTo (hdc, points[i].x, points[i].y))
700 g_warning ("gdk_draw_lines: LineTo #1 failed");
703 if (gc_private->pen_width == 1)
704 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
705 g_warning ("gdk_draw_lines: LineTo #2 failed");
707 gdk_gc_postdraw (drawable_private, gc_private);