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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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-2000. 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/.
30 #include <pango/pangowin32.h>
32 #include "gdkinternals.h"
33 #include "gdkprivate-win32.h"
35 static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
42 static void gdk_win32_draw_arc (GdkDrawable *drawable,
51 static void gdk_win32_draw_polygon (GdkDrawable *drawable,
56 static void gdk_win32_draw_text (GdkDrawable *drawable,
63 static void gdk_win32_draw_text_wc (GdkDrawable *drawable,
70 static void gdk_win32_draw_drawable (GdkDrawable *drawable,
79 static void gdk_win32_draw_points (GdkDrawable *drawable,
83 static void gdk_win32_draw_segments (GdkDrawable *drawable,
87 static void gdk_win32_draw_lines (GdkDrawable *drawable,
91 static void gdk_win32_draw_glyphs (GdkDrawable *drawable,
96 PangoGlyphString *glyphs);
97 static void gdk_win32_draw_image (GdkDrawable *drawable,
107 static void gdk_win32_set_colormap (GdkDrawable *drawable,
108 GdkColormap *colormap);
110 static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable);
112 static gint gdk_win32_get_depth (GdkDrawable *drawable);
114 static GdkVisual* gdk_win32_get_visual (GdkDrawable *drawable);
116 static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass);
118 static gpointer parent_class = NULL;
121 gdk_drawable_impl_win32_get_type (void)
123 static GType object_type = 0;
127 static const GTypeInfo object_info =
129 sizeof (GdkDrawableImplWin32Class),
130 (GBaseInitFunc) NULL,
131 (GBaseFinalizeFunc) NULL,
132 (GClassInitFunc) gdk_drawable_impl_win32_class_init,
133 NULL, /* class_finalize */
134 NULL, /* class_data */
135 sizeof (GdkDrawableImplWin32),
137 (GInstanceInitFunc) NULL,
140 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
141 "GdkDrawableImplWin32",
149 gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass)
151 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
153 parent_class = g_type_class_peek_parent (klass);
155 drawable_class->create_gc = _gdk_win32_gc_new;
156 drawable_class->draw_rectangle = gdk_win32_draw_rectangle;
157 drawable_class->draw_arc = gdk_win32_draw_arc;
158 drawable_class->draw_polygon = gdk_win32_draw_polygon;
159 drawable_class->draw_text = gdk_win32_draw_text;
160 drawable_class->draw_text_wc = gdk_win32_draw_text_wc;
161 drawable_class->draw_drawable = gdk_win32_draw_drawable;
162 drawable_class->draw_points = gdk_win32_draw_points;
163 drawable_class->draw_segments = gdk_win32_draw_segments;
164 drawable_class->draw_lines = gdk_win32_draw_lines;
165 drawable_class->draw_glyphs = gdk_win32_draw_glyphs;
166 drawable_class->draw_image = gdk_win32_draw_image;
168 drawable_class->set_colormap = gdk_win32_set_colormap;
169 drawable_class->get_colormap = gdk_win32_get_colormap;
171 drawable_class->get_depth = gdk_win32_get_depth;
172 drawable_class->get_visual = gdk_win32_get_visual;
174 drawable_class->get_image = _gdk_win32_get_image;
177 /*****************************************************
178 * Win32 specific implementations of generic functions *
179 *****************************************************/
182 gdk_win32_get_colormap (GdkDrawable *drawable)
184 GdkDrawableImplWin32 *impl;
186 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
188 return impl->colormap;
192 gdk_win32_set_colormap (GdkDrawable *drawable,
193 GdkColormap *colormap)
195 GdkDrawableImplWin32 *impl;
197 g_return_if_fail (colormap != NULL);
199 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
201 if (impl->colormap == colormap)
205 gdk_colormap_unref (impl->colormap);
206 impl->colormap = colormap;
208 gdk_colormap_ref (impl->colormap);
215 gdk_win32_draw_rectangle (GdkDrawable *drawable,
223 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
224 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
226 HGDIOBJ old_pen_or_brush;
230 GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %#x (%p) %s%dx%d@+%d+%d\n",
231 (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
233 (filled ? "fill " : ""),
234 width, height, x, y));
236 hdc = gdk_win32_hdc_get (drawable, gc, mask);
240 HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
241 HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
244 GetObject (hbr, sizeof (lbr), &lbr);
245 GetObject (hpen, sizeof (lpen), &lpen);
247 g_print ("current brush: style = %s, color = 0x%.08x\n",
248 (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
250 g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
251 (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
257 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
259 if (!BeginPath (hdc))
260 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
262 /* Win9x doesn't support Rectangle calls in a path,
268 pts[1].x = x + width + 1;
270 pts[2].x = x + width + 1;
271 pts[2].y = y + height + 1;
273 pts[3].y = y + height + 1;
276 MoveToEx (hdc, x, y, NULL);
278 if (ok && !Polyline (hdc, pts, 4))
279 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
281 if (ok && !CloseFigure (hdc))
282 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
284 if (ok && !EndPath (hdc))
285 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
288 if (!WidenPath (hdc))
289 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
291 if (ok && !FillPath (hdc))
292 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
297 old_pen_or_brush = SelectObject (hdc, GetStockObject (NULL_PEN));
299 old_pen_or_brush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
301 if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
302 WIN32_GDI_FAILED ("Rectangle");
304 SelectObject (hdc, old_pen_or_brush);
307 gdk_win32_hdc_release (drawable, gc, mask);
311 gdk_win32_draw_arc (GdkDrawable *drawable,
321 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
323 int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
325 GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n",
326 (guint) GDK_DRAWABLE_HANDLE (drawable),
327 x, y, width, height, angle1, angle2));
329 /* Seems that drawing arcs with width or height <= 2 fails, at least
332 if (width <= 2 || height <= 2 || angle2 == 0)
335 hdc = gdk_win32_hdc_get (drawable, gc, mask);
337 if (angle2 >= 360*64)
339 nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
343 /* The 100. is just an arbitrary value */
344 nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
345 nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
346 nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
347 nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
351 nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
352 nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
353 nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
354 nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
357 /* GDK_OPAQUE_STIPPLED arcs not implemented. */
361 GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
362 x, y, x+width, y+height,
363 nXStartArc, nYStartArc,
364 nXEndArc, nYEndArc));
365 if (!Pie (hdc, x, y, x+width, y+height,
366 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
367 WIN32_GDI_FAILED ("Pie");
371 GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
372 x, y, x+width, y+height,
373 nXStartArc, nYStartArc,
374 nXEndArc, nYEndArc));
375 if (!Arc (hdc, x, y, x+width, y+height,
376 nXStartArc, nYStartArc, nXEndArc, nYEndArc))
377 WIN32_GDI_FAILED ("Arc");
379 gdk_win32_hdc_release (drawable, gc, mask);
383 gdk_win32_draw_polygon (GdkDrawable *drawable,
389 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
390 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
396 GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %#x (%p) %d\n",
397 (guint) GDK_DRAWABLE_HANDLE (drawable),
404 hdc = gdk_win32_hdc_get (drawable, gc, mask);
405 pts = g_new (POINT, npoints+1);
407 for (i = 0; i < npoints; i++)
409 pts[i].x = points[i].x;
410 pts[i].y = points[i].y;
413 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
415 if (!BeginPath (hdc))
416 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
419 MoveToEx (hdc, points[0].x, points[0].y, NULL);
421 if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y)
424 if (ok && !Polyline (hdc, pts, 4))
425 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
427 if (ok && !CloseFigure (hdc))
428 WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE;
430 if (ok && !EndPath (hdc))
431 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
434 if (!WidenPath (hdc))
435 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
437 if (ok && !FillPath (hdc))
438 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
442 if (points[0].x != points[npoints-1].x
443 || points[0].y != points[npoints-1].y)
445 pts[npoints].x = points[0].x;
446 pts[npoints].y = points[0].y;
452 if (!Polygon (hdc, pts, npoints))
453 WIN32_GDI_FAILED ("Polygon");
457 if (!Polyline (hdc, pts, npoints))
458 WIN32_GDI_FAILED ("Polyline");
462 gdk_win32_hdc_release (drawable, gc, mask);
472 gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
473 const wchar_t *wcstr,
479 gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
484 if ((oldfont = SelectObject (argp->hdc, singlefont->hfont)) == NULL)
486 WIN32_GDI_FAILED ("SelectObject");
490 if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
491 WIN32_GDI_FAILED ("TextOutW");
492 GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
495 SelectObject (argp->hdc, oldfont);
499 gdk_win32_draw_text (GdkDrawable *drawable,
507 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
510 gdk_draw_text_arg arg;
512 if (text_length == 0)
515 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
519 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
521 GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
522 (guint) GDK_DRAWABLE_HANDLE (drawable),
524 (text_length > 10 ? 10 : text_length),
527 if (text_length == 1)
529 /* For single characters, don't try to interpret as UTF-8. */
530 wc = (guchar) text[0];
531 gdk_wchar_text_handle (font, &wc, 1, gdk_draw_text_handler, &arg);
535 wcstr = g_new (wchar_t, text_length);
536 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
537 g_warning ("gdk_win32_draw_text: gdk_nmbstowchar_ts failed");
539 gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
544 gdk_win32_hdc_release (drawable, gc, mask);
548 gdk_win32_draw_text_wc (GdkDrawable *drawable,
553 const GdkWChar *text,
556 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
559 gdk_draw_text_arg arg;
561 if (text_length == 0)
564 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
568 arg.hdc = gdk_win32_hdc_get (drawable, gc, mask);
570 GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
571 (guint) GDK_DRAWABLE_HANDLE (drawable),
574 if (sizeof (wchar_t) != sizeof (GdkWChar))
576 wcstr = g_new (wchar_t, text_length);
577 for (i = 0; i < text_length; i++)
581 wcstr = (wchar_t *) text;
583 gdk_wchar_text_handle (font, wcstr, text_length,
584 gdk_draw_text_handler, &arg);
586 if (sizeof (wchar_t) != sizeof (GdkWChar))
589 gdk_win32_hdc_release (drawable, gc, mask);
593 gdk_win32_draw_drawable (GdkDrawable *drawable,
606 HRGN src_rgn, draw_rgn, outside_rgn;
608 gint src_width, src_height;
610 GdkDrawableImplWin32 *impl;
613 impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
614 if (GDK_IS_DRAWABLE_IMPL_WIN32(src))
615 src_handle = GDK_DRAWABLE_IMPL_WIN32 (src)->handle;
617 src_handle = GDK_DRAWABLE_HANDLE (src);
619 GDK_NOTE (MISC, g_print ("gdk_win32_draw_drawable: dest: %#x @+%d+%d"
620 " src: %#x %dx%d@+%d+%d\n",
621 (guint) impl->handle,
624 width, height, xsrc, ysrc));
626 hdc = gdk_win32_hdc_get (drawable, gc, 0);
628 gdk_drawable_get_size (src, &src_width, &src_height);
629 src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1);
630 draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
632 if (GDK_IS_WINDOW_IMPL_WIN32 (drawable))
634 /* If we are drawing on a window, calculate the region that is
635 * outside the source pixmap, and invalidate that, causing it to
639 outside_rgn = CreateRectRgnIndirect (&r);
640 if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
642 if (ERROR == OffsetRgn (outside_rgn, xdest, ydest))
643 WIN32_GDI_FAILED ("OffsetRgn");
644 GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
645 g_print ("...calling InvalidateRgn, "
646 "bbox: %ldx%ld@+%ld+%ld\n",
647 r.right - r.left - 1, r.bottom - r.top - 1,
649 if (!InvalidateRgn (impl->handle, outside_rgn, TRUE))
650 WIN32_GDI_FAILED ("InvalidateRgn");
652 if (!DeleteObject (outside_rgn))
653 WIN32_GDI_FAILED ("DeleteObject");
656 #if 1 /* Don't know if this is necessary */
657 if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
658 g_warning ("gdk_win32_draw_drawable: CombineRgn returned a COMPLEXREGION");
660 if (0 == GetRgnBox (draw_rgn, &r))
661 WIN32_GDI_FAILED("GetRgnBox");
664 || r.right != xsrc + width + 1
665 || r.bottom != ysrc + height + 1)
667 xdest += r.left - xsrc;
669 ydest += r.top - ysrc;
671 width = r.right - xsrc - 1;
672 height = r.bottom - ysrc - 1;
674 GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
676 width, height, xsrc, ysrc,
681 if (!DeleteObject (src_rgn))
682 WIN32_GDI_FAILED ("DeleteObject");
683 if (!DeleteObject (draw_rgn))
684 WIN32_GDI_FAILED ("DeleteObject");
686 /* This function is called also to bitblt from a window.
688 if (GDK_IS_PIXMAP_IMPL_WIN32 (src) || GDK_IS_PIXMAP(src))
690 if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
691 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
693 if (ok && (hgdiobj = SelectObject (srcdc, src_handle)) == NULL)
694 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
696 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
697 srcdc, xsrc, ysrc, SRCCOPY))
698 WIN32_GDI_FAILED ("BitBlt");
700 if (ok && (SelectObject (srcdc, hgdiobj) == NULL))
701 WIN32_GDI_FAILED ("SelectObject");
703 if (srcdc != NULL && !DeleteDC (srcdc))
704 WIN32_GDI_FAILED ("DeleteDC");
706 else if (impl->handle == src_handle)
708 /* Blitting inside a window, use ScrollDC */
709 RECT scrollRect, clipRect, emptyRect;
712 scrollRect.left = MIN (xsrc, xdest);
713 scrollRect.top = MIN (ysrc, ydest);
714 scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
715 scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
717 clipRect.left = xdest;
718 clipRect.top = ydest;
719 clipRect.right = xdest + width + 1;
720 clipRect.bottom = ydest + height + 1;
722 SetRectEmpty (&emptyRect);
723 updateRgn = CreateRectRgnIndirect (&emptyRect);
724 if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
725 &scrollRect, &clipRect,
727 WIN32_GDI_FAILED ("ScrollDC"), ok = FALSE;
728 if (ok && !InvalidateRgn (impl->handle, updateRgn, FALSE))
729 WIN32_GDI_FAILED ("InvalidateRgn"), ok = FALSE;
730 if (ok && !UpdateWindow (impl->handle))
731 WIN32_GDI_FAILED ("UpdateWindow");
732 if (!DeleteObject (updateRgn))
733 WIN32_GDI_FAILED ("DeleteObject");
737 if ((srcdc = GetDC (src_handle)) == NULL)
738 WIN32_GDI_FAILED ("GetDC"), ok = FALSE;
740 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
741 srcdc, xsrc, ysrc, SRCCOPY))
742 WIN32_GDI_FAILED ("BitBlt");
743 if (ok && !ReleaseDC (src_handle, srcdc))
744 WIN32_GDI_FAILED ("ReleaseDC");
746 gdk_win32_hdc_release (drawable, gc, 0);
750 gdk_win32_draw_points (GdkDrawable *drawable,
757 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
758 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
761 hdc = gdk_win32_hdc_get (drawable, gc, 0);
763 fg = gdk_colormap_color (impl->colormap, gc_private->foreground);
765 GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x %dx%.06x\n",
766 (guint) GDK_DRAWABLE_HANDLE (drawable),
767 npoints, (guint) fg));
769 for (i = 0; i < npoints; i++)
770 SetPixel (hdc, points[i].x, points[i].y, fg);
772 gdk_win32_hdc_release (drawable, gc, 0);
776 gdk_win32_draw_segments (GdkDrawable *drawable,
781 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
782 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
787 GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %#x nsegs: %d\n",
788 (guint) GDK_DRAWABLE_HANDLE (drawable), nsegs));
790 hdc = gdk_win32_hdc_get (drawable, gc, mask);
792 if (gc_private->fill_style == GDK_OPAQUE_STIPPLED)
794 if (!BeginPath (hdc))
795 WIN32_GDI_FAILED ("BeginPath"), ok = FALSE;
797 for (i = 0; ok && i < nsegs; i++)
799 if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
800 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
801 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
802 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
805 if (ok && gc_private->pen_width <= 1)
806 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
807 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
810 if (ok && !EndPath (hdc))
811 WIN32_GDI_FAILED ("EndPath"), ok = FALSE;
813 if (ok && !WidenPath (hdc))
814 WIN32_GDI_FAILED ("WidenPath"), ok = FALSE;
816 if (ok && !FillPath (hdc))
817 WIN32_GDI_FAILED ("FillPath"), ok = FALSE;
821 for (i = 0; ok && i < nsegs; i++)
823 if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
824 WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE;
825 if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2))
826 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
829 if (ok && gc_private->pen_width <= 1)
830 if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
831 WIN32_GDI_FAILED ("LineTo"), ok = FALSE;
834 gdk_win32_hdc_release (drawable, gc, mask);
838 gdk_win32_draw_lines (GdkDrawable *drawable,
843 GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc);
844 const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
853 hdc = gdk_win32_hdc_get (drawable, gc, mask);
855 pts = g_new (POINT, npoints);
857 for (i = 0; i < npoints; i++)
859 pts[i].x = points[i].x;
860 pts[i].y = points[i].y;
863 if (!Polyline (hdc, pts, npoints))
864 WIN32_GDI_FAILED ("Polyline"), ok = FALSE;
869 if (ok && gc_private->pen_width <= 1)
871 MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
872 if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
873 WIN32_GDI_FAILED ("LineTo");
875 gdk_win32_hdc_release (drawable, gc, mask);
879 gdk_win32_draw_glyphs (GdkDrawable *drawable,
884 PangoGlyphString *glyphs)
886 const GdkGCValuesMask mask = GDK_GC_FOREGROUND;
889 hdc = gdk_win32_hdc_get (drawable, gc, mask);
891 /* HB: Maybe there should be a GDK_GC_PANGO flag for hdc_get */
892 /* default write mode is transparent (leave background) */
893 if (SetBkMode (hdc, TRANSPARENT) == 0)
894 WIN32_GDI_FAILED ("SetBkMode");
896 if (GDI_ERROR == SetTextAlign (hdc, TA_LEFT|TA_BOTTOM|TA_NOUPDATECP))
897 WIN32_GDI_FAILED ("SetTextAlign");
899 pango_win32_render (hdc, font, glyphs, x, y);
901 gdk_win32_hdc_release (drawable, gc, mask);
905 gdk_win32_draw_image (GdkDrawable *drawable,
915 GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
916 GdkImagePrivateWin32 *image_private = IMAGE_PRIVATE_DATA (image);
917 GdkColormapPrivateWin32 *colormap_private = (GdkColormapPrivateWin32 *) impl->colormap;
922 BITMAPINFOHEADER bmiHeader;
923 WORD bmiIndices[256];
925 static gboolean bmi_inited = FALSE;
929 hdc = gdk_win32_hdc_get (drawable, gc, 0);
931 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR &&
932 colormap_private && colormap_private->xcolormap->rc_palette)
936 for (i = 0; i < 256; i++)
937 bmi.bmiIndices[i] = i;
941 if (GetObject (image_private->hbitmap, sizeof (DIBSECTION),
942 &ds) != sizeof (DIBSECTION))
943 WIN32_GDI_FAILED ("GetObject"), ok = FALSE;
945 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
946 xdest, ydest, xsrc, ysrc, width, height);
947 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
948 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
949 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
950 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
952 bmi.bmiHeader = ds.dsBmih;
953 /* I have spent hours on getting the parameters to
954 * SetDIBitsToDevice right. I wonder what drugs the guys in
955 * Redmond were on when they designed this API.
957 if (ok && SetDIBitsToDevice (hdc,
960 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
961 0, -ds.dsBmih.biHeight,
963 (CONST BITMAPINFO *) &bmi,
964 DIB_PAL_COLORS) == 0)
965 WIN32_GDI_FAILED ("SetDIBitsToDevice");
970 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
971 WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
973 if (ok && (oldbitmap = SelectObject (memdc, image_private->hbitmap)) == NULL)
974 WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
976 if (ok && !BitBlt (hdc, xdest, ydest, width, height,
977 memdc, xsrc, ysrc, SRCCOPY))
978 WIN32_GDI_FAILED ("BitBlt");
980 if (oldbitmap != NULL && SelectObject (memdc, oldbitmap) == NULL)
981 WIN32_GDI_FAILED ("SelectObject");
983 if (memdc != NULL && !DeleteDC (memdc))
984 WIN32_GDI_FAILED ("DeleteDC");
986 gdk_win32_hdc_release (drawable, gc, 0);
990 gdk_win32_get_depth (GdkDrawable *drawable)
992 /* This is a bit bogus but I'm not sure the other way is better */
994 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);
998 gdk_win32_get_visual (GdkDrawable *drawable)
1000 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper);