diff options
author | Tor Lillqvist <tml@src.gnome.org> | 2000-07-23 21:43:23 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2000-07-23 21:43:23 +0000 |
commit | 46587958172cf895cca524a2cc91344463f358aa (patch) | |
tree | 63d0c3f8e03ecca3c82514656ea2d663bf057032 /gdk/win32/gdkdrawable-win32.c | |
parent | 20b5d8ec2fc3ec4505ba7327ffae006a7bfa2e09 (diff) | |
download | gtk+-46587958172cf895cca524a2cc91344463f358aa.tar.gz |
More work on the Win32 backend. More files compile now.
Diffstat (limited to 'gdk/win32/gdkdrawable-win32.c')
-rw-r--r-- | gdk/win32/gdkdrawable-win32.c | 652 |
1 files changed, 379 insertions, 273 deletions
diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c index 37abf2db75..8a7466d419 100644 --- a/gdk/win32/gdkdrawable-win32.c +++ b/gdk/win32/gdkdrawable-win32.c @@ -24,19 +24,15 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include "config.h" - #include <math.h> #include <glib.h> -#ifndef G_PI -#define G_PI 3.14159265358979323846 -#endif +#include <pango/pangowin32.h> #include "gdkinternals.h" #include "gdkprivate-win32.h" - -static void gdk_win32_drawable_destroy (GdkDrawable *drawable); +#include "gdkdrawable-win32.h" +#include "gdkpixmap-win32.h" static void gdk_win32_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, @@ -94,86 +90,121 @@ static void gdk_win32_draw_lines (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints); +static void gdk_win32_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs); +static void gdk_win32_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height); + +static void gdk_win32_set_colormap (GdkDrawable *drawable, + GdkColormap *colormap); + +static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable); + +static gint gdk_win32_get_depth (GdkDrawable *drawable); + +static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass); + +static gpointer parent_class = NULL; + +GType +gdk_drawable_impl_win32_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDrawableImplWin32Class), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_drawable_impl_win32_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDrawableImplWin32), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_DRAWABLE, + "GdkDrawableImplWin32", + &object_info); + } + + return object_type; +} -GdkDrawableClass _gdk_win32_drawable_class = { - gdk_win32_drawable_destroy, - _gdk_win32_gc_new, - gdk_win32_draw_rectangle, - gdk_win32_draw_arc, - gdk_win32_draw_polygon, - gdk_win32_draw_text, - gdk_win32_draw_text_wc, - gdk_win32_draw_drawable, - gdk_win32_draw_points, - gdk_win32_draw_segments, - gdk_win32_draw_lines -}; +static void +gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass) +{ + GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + drawable_class->create_gc = _gdk_win32_gc_new; + drawable_class->draw_rectangle = gdk_win32_draw_rectangle; + drawable_class->draw_arc = gdk_win32_draw_arc; + drawable_class->draw_polygon = gdk_win32_draw_polygon; + drawable_class->draw_text = gdk_win32_draw_text; + drawable_class->draw_text_wc = gdk_win32_draw_text_wc; + drawable_class->draw_drawable = gdk_win32_draw_drawable; + drawable_class->draw_points = gdk_win32_draw_points; + drawable_class->draw_segments = gdk_win32_draw_segments; + drawable_class->draw_lines = gdk_win32_draw_lines; + drawable_class->draw_glyphs = gdk_win32_draw_glyphs; + drawable_class->draw_image = gdk_win32_draw_image; + + drawable_class->set_colormap = gdk_win32_set_colormap; + drawable_class->get_colormap = gdk_win32_get_colormap; + + drawable_class->get_depth = gdk_win32_get_depth; +} /***************************************************** * Win32 specific implementations of generic functions * *****************************************************/ -GdkColormap* -gdk_drawable_get_colormap (GdkDrawable *drawable) +static GdkColormap* +gdk_win32_get_colormap (GdkDrawable *drawable) { - GdkDrawablePrivate *drawable_private; - - g_return_val_if_fail (drawable != NULL, NULL); - drawable_private = (GdkDrawablePrivate*) drawable; - - if (!GDK_DRAWABLE_DESTROYED (drawable)) - { - if (drawable_private->colormap == NULL) - return gdk_colormap_get_system (); /* XXX ??? */ - else - return drawable_private->colormap; - } + GdkDrawableImplWin32 *impl; - return NULL; + return impl->colormap; } -void -gdk_drawable_set_colormap (GdkDrawable *drawable, - GdkColormap *colormap) +static void +gdk_win32_set_colormap (GdkDrawable *drawable, + GdkColormap *colormap) { - GdkDrawablePrivate *drawable_private; - GdkColormapPrivateWin32 *colormap_private; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (colormap != NULL); - - drawable_private = (GdkDrawablePrivate *) drawable; - colormap_private = (GdkColormapPrivateWin32 *) colormap; + GdkDrawableImplWin32 *impl; + + g_return_if_fail (colormap != NULL); + + impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); + + if (impl->colormap == colormap) + return; - if (!GDK_DRAWABLE_DESTROYED (drawable)) - { - if (GDK_IS_WINDOW (drawable)) - { - g_return_if_fail (colormap_private->base.visual != - ((GdkColormapPrivate *) (drawable_private->colormap))->visual); - /* XXX ??? */ - GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n", - GDK_DRAWABLE_XID (drawable), - colormap_private->xcolormap)); - } - if (drawable_private->colormap) - gdk_colormap_unref (drawable_private->colormap); - drawable_private->colormap = colormap; - gdk_colormap_ref (drawable_private->colormap); - - if (GDK_IS_WINDOW (drawable) - && drawable_private->window_type != GDK_WINDOW_TOPLEVEL) - gdk_window_add_colormap_windows (drawable); - } + if (impl->colormap) + gdk_colormap_unref (impl->colormap); + impl->colormap = colormap; + if (impl->colormap) + gdk_colormap_ref (impl->colormap); } /* Drawing */ -static void -gdk_win32_drawable_destroy (GdkDrawable *drawable) -{ - -} static void gdk_win32_draw_rectangle (GdkDrawable *drawable, @@ -184,8 +215,8 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, gint width, gint height) { - GdkGCPrivate *gc_private = (GdkGCPrivate*) gc; - GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; HDC hdc; HGDIOBJ oldpen, oldbrush; HBRUSH hbr = NULL; @@ -193,13 +224,12 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, gboolean ok = TRUE; GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n", - GDK_DRAWABLE_XID (drawable), + GDK_DRAWABLE_HANDLE (drawable), gc_private, (filled ? "fill " : ""), width, height, x, y)); - hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + hdc = gdk_gc_predraw (drawable, gc_private, mask); #if 0 { @@ -220,7 +250,7 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, } #endif - if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) + if (gc_private->fill_style == GDK_OPAQUE_STIPPLED) { if (!BeginPath (hdc)) WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; @@ -277,7 +307,7 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, SelectObject (hdc, oldbrush); } - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + gdk_gc_postdraw (drawable, gc_private, mask); } static void @@ -291,69 +321,66 @@ gdk_win32_draw_arc (GdkDrawable *drawable, gint angle1, gint angle2) { - GdkGCPrivate *gc_private; + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; HDC hdc; int nXStartArc, nYStartArc, nXEndArc, nYEndArc; - gc_private = (GdkGCPrivate*) gc; - GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n", - GDK_DRAWABLE_XID (drawable), + GDK_DRAWABLE_HANDLE (drawable), x, y, width, height, angle1, angle2)); /* Seems that drawing arcs with width or height <= 2 fails, at least * with my TNT card. */ - if (width > 2 && height > 2 && angle2 != 0) - { - hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); - - if (angle2 >= 360*64) - { - nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0; - } - else if (angle2 > 0) - { - /* The 100. is just an arbitrary value */ - nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); - nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); - nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); - nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); - } - else - { - nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); - nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); - nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); - nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); - } + if (width <= 2 || height <= 2 || angle2 == 0) + return; - /* GDK_OPAQUE_STIPPLED arcs not implemented. */ + hdc = gdk_gc_predraw (drawable, gc_private, mask); - if (filled) - { - GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", - x, y, x+width, y+height, - nXStartArc, nYStartArc, - nXEndArc, nYEndArc)); - if (!Pie (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc)) - WIN32_GDI_FAILED ("Pie"); - } - else - { - GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", - x, y, x+width, y+height, - nXStartArc, nYStartArc, - nXEndArc, nYEndArc)); - if (!Arc (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc)) - WIN32_GDI_FAILED ("Arc"); - } - gdk_gc_postdraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + if (angle2 >= 360*64) + { + nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0; } + else if (angle2 > 0) + { + /* The 100. is just an arbitrary value */ + nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); + nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); + nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); + nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); + } + else + { + nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); + nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); + nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); + nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); + } + + /* GDK_OPAQUE_STIPPLED arcs not implemented. */ + + if (filled) + { + GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", + x, y, x+width, y+height, + nXStartArc, nYStartArc, + nXEndArc, nYEndArc)); + if (!Pie (hdc, x, y, x+width, y+height, + nXStartArc, nYStartArc, nXEndArc, nYEndArc)) + WIN32_GDI_FAILED ("Pie"); + } + else + { + GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", + x, y, x+width, y+height, + nXStartArc, nYStartArc, + nXEndArc, nYEndArc)); + if (!Arc (hdc, x, y, x+width, y+height, + nXStartArc, nYStartArc, nXEndArc, nYEndArc)) + WIN32_GDI_FAILED ("Arc"); + } + gdk_gc_postdraw (drawable, gc_private, mask); } static void @@ -363,8 +390,8 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, GdkPoint *points, gint npoints) { - GdkGCPrivate *gc_private = (GdkGCPrivate*) gc; - GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; HDC hdc; HBRUSH hbr = NULL; POINT *pts; @@ -372,14 +399,13 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, int i; GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %#x (%d) %d\n", - GDK_DRAWABLE_XID (drawable), gc_private, + GDK_DRAWABLE_HANDLE (drawable), gc_private, npoints)); if (npoints < 2) return; - hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + hdc = gdk_gc_predraw (drawable, gc_private, mask); pts = g_new (POINT, npoints+1); for (i = 0; i < npoints; i++) @@ -388,12 +414,13 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, pts[i].y = points[i].y; } - if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) + if (gc_private->fill_style == GDK_OPAQUE_STIPPLED) { if (!BeginPath (hdc)) WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; - MoveToEx (hdc, points[0].x, points[0].y, NULL); + if (ok) + MoveToEx (hdc, points[0].x, points[0].y, NULL); if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y) npoints--; @@ -440,7 +467,7 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, } } g_free (pts); - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + gdk_gc_postdraw (drawable, gc_private, mask); } typedef struct @@ -462,7 +489,7 @@ gdk_draw_text_handler (GdkWin32SingleFont *singlefont, if (!singlefont) return; - if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL) + if ((oldfont = SelectObject (argp->hdc, singlefont->hfont)) == NULL) { WIN32_GDI_FAILED ("SelectObject"); return; @@ -485,51 +512,45 @@ gdk_win32_draw_text (GdkDrawable *drawable, const gchar *text, gint text_length) { - GdkGCPrivate *gc_private; - wchar_t *wcstr; + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT; + wchar_t *wcstr, wc; gint wlen; gdk_draw_text_arg arg; - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - if (text_length == 0) return; g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - gc_private = (GdkGCPrivate*) gc; - arg.x = x; arg.y = y; - arg.hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_FONT); + arg.hdc = gdk_gc_predraw (drawable, gc_private, mask); GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n", - GDK_DRAWABLE_XID (drawable), + GDK_DRAWABLE_HANDLE (drawable), x, y, (text_length > 10 ? 10 : text_length), text, text_length)); - wcstr = g_new (wchar_t, text_length); if (text_length == 1) { /* For single characters, don't try to interpret as UTF-8. */ - wcstr[0] = (guchar) text[0]; - gdk_wchar_text_handle (font, wcstr, 1, gdk_draw_text_handler, &arg); + wc = (guchar) text[0]; + gdk_wchar_text_handle (font, &wc, 1, gdk_draw_text_handler, &arg); } else { + wcstr = g_new (wchar_t, text_length); if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) g_warning ("gdk_win32_draw_text: gdk_nmbstowchar_ts failed"); else gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg); + g_free (wcstr); } - g_free (wcstr); - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); + gdk_gc_postdraw (drawable, gc_private, mask); } static void @@ -541,29 +562,23 @@ gdk_win32_draw_text_wc (GdkDrawable *drawable, const GdkWChar *text, gint text_length) { - GdkGCPrivate *gc_private; + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT; gint i, wlen; wchar_t *wcstr; gdk_draw_text_arg arg; - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - if (text_length == 0) return; g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - gc_private = (GdkGCPrivate*) gc; - arg.x = x; arg.y = y; - arg.hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_FONT); + arg.hdc = gdk_gc_predraw (drawable, gc_private, mask); GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n", - GDK_DRAWABLE_XID (drawable), + GDK_DRAWABLE_HANDLE (drawable), x, y, text_length)); if (sizeof (wchar_t) != sizeof (GdkWChar)) @@ -581,7 +596,7 @@ gdk_win32_draw_text_wc (GdkDrawable *drawable, if (sizeof (wchar_t) != sizeof (GdkWChar)) g_free (wcstr); - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); + gdk_gc_postdraw (drawable, gc_private, mask); } static void @@ -595,38 +610,36 @@ gdk_win32_draw_drawable (GdkDrawable *drawable, gint width, gint height) { - GdkDrawablePrivate *src_private; - GdkGCPrivate *gc_private; + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + GdkDrawableImplWin32 *src_impl = GDK_DRAWABLE_IMPL_WIN32 (src); HDC hdc; HDC srcdc; HGDIOBJ hgdiobj; HRGN src_rgn, draw_rgn, outside_rgn; RECT r; + gint src_width, src_height; + gboolean ok = TRUE; - src_private = (GdkDrawablePrivate*) src; - gc_private = (GdkGCPrivate*) gc; - - GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x " - "src: %#x %dx%d@+%d+%d" - " dest: %#x @+%d+%d\n", - GDK_DRAWABLE_XID (drawable), - GDK_DRAWABLE_XID (src), - width, height, xsrc, ysrc, - GDK_DRAWABLE_XID (drawable), xdest, ydest)); + GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x @+%d+%d" + "src: %#x %dx%d@+%d+%d\n", + GDK_DRAWABLE_HANDLE (drawable), xdest, ydest, + GDK_PIXMAP_HBITMAP (src), + width, height, xsrc, ysrc)); hdc = gdk_gc_predraw (drawable, gc_private, 0); - src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1); + gdk_drawable_get_size (src, &src_width, &src_height); + src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1); draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1); - SetRectEmpty (&r); - outside_rgn = CreateRectRgnIndirect (&r); - if (GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_PIXMAP) + if (!GDK_IS_PIXMAP (drawable)) { /* If we are drawing on a window, calculate the region that is * outside the source pixmap, and invalidate that, causing it to * be cleared. XXX */ + SetRectEmpty (&r); + outside_rgn = CreateRectRgnIndirect (&r); if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION) { OffsetRgn (outside_rgn, xdest, ydest); @@ -635,8 +648,9 @@ gdk_win32_draw_drawable (GdkDrawable *drawable, "bbox: %dx%d@+%d+%d\n", r.right - r.left - 1, r.bottom - r.top - 1, r.left, r.top))); - InvalidateRgn (GDK_DRAWABLE_XID (drawable), outside_rgn, TRUE); + InvalidateRgn (GDK_DRAWABLE_HANDLE (drawable), outside_rgn, TRUE); } + DeleteObject (outside_rgn); } #if 1 /* Don't know if this is necessary */ @@ -665,68 +679,64 @@ gdk_win32_draw_drawable (GdkDrawable *drawable, DeleteObject (src_rgn); DeleteObject (draw_rgn); - DeleteObject (outside_rgn); - /* Strangely enough, this function is called also to bitblt - * from a window. + /* This function is called also to bitblt from a window. */ - if (src_private->window_type == GDK_DRAWABLE_PIXMAP) + if (GDK_IS_PIXMAP (src)) { if ((srcdc = CreateCompatibleDC (hdc)) == NULL) - WIN32_GDI_FAILED ("CreateCompatibleDC"); + WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE; - if ((hgdiobj = SelectObject (srcdc, GDK_DRAWABLE_XID (src))) == NULL) - WIN32_GDI_FAILED ("SelectObject"); + if (ok && (hgdiobj = SelectObject (srcdc, GDK_PIXMAP_HBITMAP (src))) == NULL) + WIN32_GDI_FAILED ("SelectObject"), ok = FALSE; - if (!BitBlt (hdc, xdest, ydest, width, height, - srcdc, xsrc, ysrc, SRCCOPY)) + if (ok && !BitBlt (hdc, xdest, ydest, width, height, + srcdc, xsrc, ysrc, SRCCOPY)) WIN32_GDI_FAILED ("BitBlt"); - if ((SelectObject (srcdc, hgdiobj) == NULL)) + if (ok && (SelectObject (srcdc, hgdiobj) == NULL)) WIN32_GDI_FAILED ("SelectObject"); - if (!DeleteDC (srcdc)) + if (srcdc != NULL && !DeleteDC (srcdc)) WIN32_GDI_FAILED ("DeleteDC"); } + else if (GDK_DRAWABLE_HANDLE (drawable) == GDK_DRAWABLE_HANDLE (src)) + { + /* Blitting inside a window, use ScrollDC */ + RECT scrollRect, clipRect, emptyRect; + HRGN updateRgn; + + scrollRect.left = MIN (xsrc, xdest); + scrollRect.top = MIN (ysrc, ydest); + scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1); + scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1); + + clipRect.left = xdest; + clipRect.top = ydest; + clipRect.right = xdest + width + 1; + clipRect.bottom = ydest + height + 1; + + SetRectEmpty (&emptyRect); + updateRgn = CreateRectRgnIndirect (&emptyRect); + if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc, + &scrollRect, &clipRect, + updateRgn, NULL)) + WIN32_GDI_FAILED ("ScrollDC"), ok = FALSE; + if (ok && !InvalidateRgn (GDK_WINDOW_HWND (drawable), updateRgn, FALSE)) + WIN32_GDI_FAILED ("InvalidateRgn"), ok = FALSE; + if (ok && !UpdateWindow (GDK_WINDOW_HWND (drawable))) + WIN32_GDI_FAILED ("UpdateWindow"); + DeleteObject (updateRgn); + } else { - if (GDK_DRAWABLE_XID(drawable) == GDK_DRAWABLE_XID (src)) - { - /* Blitting inside a window, use ScrollDC */ - RECT scrollRect, clipRect, emptyRect; - HRGN updateRgn; - - scrollRect.left = MIN (xsrc, xdest); - scrollRect.top = MIN (ysrc, ydest); - scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1); - scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1); - - clipRect.left = xdest; - clipRect.top = ydest; - clipRect.right = xdest + width + 1; - clipRect.bottom = ydest + height + 1; - - SetRectEmpty (&emptyRect); - updateRgn = CreateRectRgnIndirect (&emptyRect); - if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc, - &scrollRect, &clipRect, - updateRgn, NULL)) - WIN32_GDI_FAILED ("ScrollDC"); - if (!InvalidateRgn (GDK_DRAWABLE_XID (drawable), updateRgn, FALSE)) - WIN32_GDI_FAILED ("InvalidateRgn"); - if (!UpdateWindow (GDK_DRAWABLE_XID (drawable))) - WIN32_GDI_FAILED ("UpdateWindow"); - } - else - { - if ((srcdc = GetDC (GDK_DRAWABLE_XID (src))) == NULL) - WIN32_GDI_FAILED ("GetDC"); - - if (!BitBlt (hdc, xdest, ydest, width, height, - srcdc, xsrc, ysrc, SRCCOPY)) - WIN32_GDI_FAILED ("BitBlt"); - ReleaseDC (GDK_DRAWABLE_XID (src), srcdc); - } + if ((srcdc = GetDC (GDK_WINDOW_HWND (src))) == NULL) + WIN32_GDI_FAILED ("GetDC"), ok = FALSE; + + if (ok && !BitBlt (hdc, xdest, ydest, width, height, + srcdc, xsrc, ysrc, SRCCOPY)) + WIN32_GDI_FAILED ("BitBlt"); + ReleaseDC (GDK_WINDOW_HWND (src), srcdc); } gdk_gc_postdraw (drawable, gc_private, 0); } @@ -739,16 +749,15 @@ gdk_win32_draw_points (GdkDrawable *drawable, { HDC hdc; COLORREF fg; - GdkGCPrivate *gc_private = (GdkGCPrivate*) gc; - GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private); - GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable; + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); GdkColormapPrivateWin32 *colormap_private = - (GdkColormapPrivateWin32 *) drawable_private->colormap; + (GdkColormapPrivateWin32 *) impl->colormap; int i; hdc = gdk_gc_predraw (drawable, gc_private, 0); - fg = gdk_colormap_color (colormap_private, gc_data->foreground); + fg = gdk_colormap_color (colormap_private, gc_private->foreground); GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x %dx%.06x\n", GDK_DRAWABLE_XID (drawable), npoints, fg)); @@ -765,25 +774,24 @@ gdk_win32_draw_segments (GdkDrawable *drawable, GdkSegment *segs, gint nsegs) { - GdkGCPrivate *gc_private = (GdkGCPrivate*) gc; - GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; HDC hdc; HBRUSH hbr = NULL; gboolean ok = TRUE; int i; GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %#x nsegs: %d\n", - GDK_DRAWABLE_XID (drawable), nsegs)); + GDK_DRAWABLE_HANDLE (drawable), nsegs)); - hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + hdc = gdk_gc_predraw (drawable, gc_private, mask); - if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) + if (gc_private->fill_style == GDK_OPAQUE_STIPPLED) { if (!BeginPath (hdc)) WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; - for (i = 0; i < nsegs; i++) + for (i = 0; ok && i < nsegs; i++) { if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; @@ -791,7 +799,7 @@ gdk_win32_draw_segments (GdkDrawable *drawable, WIN32_GDI_FAILED ("LineTo"), ok = FALSE; /* Draw end pixel */ - if (ok && gc_data->pen_width <= 1) + if (ok && gc_private->pen_width <= 1) if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) WIN32_GDI_FAILED ("LineTo"), ok = FALSE; } @@ -811,20 +819,20 @@ gdk_win32_draw_segments (GdkDrawable *drawable, } else { - for (i = 0; i < nsegs; i++) + for (i = 0; ok && i < nsegs; i++) { if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) - WIN32_GDI_FAILED ("MoveToEx"); - if (!LineTo (hdc, segs[i].x2, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"); + WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; + if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2)) + WIN32_GDI_FAILED ("LineTo"), ok = FALSE; /* Draw end pixel */ - if (gc_data->pen_width <= 1) + if (ok && gc_private->pen_width <= 1) if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"); + WIN32_GDI_FAILED ("LineTo"), ok = FALSE; } } - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + gdk_gc_postdraw (drawable, gc_private, mask); } static void @@ -833,18 +841,18 @@ gdk_win32_draw_lines (GdkDrawable *drawable, GdkPoint *points, gint npoints) { - GdkGCPrivate *gc_private = (GdkGCPrivate*) gc; - GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA (gc_private); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; HDC hdc; POINT *pts; int i; + gboolean ok = TRUE; if (npoints < 2) return; - hdc = gdk_gc_predraw (drawable, gc_private, - GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); -#if 1 + hdc = gdk_gc_predraw (drawable, gc_private, mask); + pts = g_new (POINT, npoints); for (i = 0; i < npoints; i++) @@ -854,31 +862,129 @@ gdk_win32_draw_lines (GdkDrawable *drawable, } if (!Polyline (hdc, pts, npoints)) - WIN32_GDI_FAILED ("Polyline"); + WIN32_GDI_FAILED ("Polyline"), ok = FALSE; g_free (pts); /* Draw end pixel */ - if (gc_data->pen_width <= 1) + if (ok && gc_private->pen_width <= 1) { MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL); if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y)) WIN32_GDI_FAILED ("LineTo"); } -#else - MoveToEx (hdc, points[0].x, points[0].y, NULL); - for (i = 1; i < npoints; i++) - if (!LineTo (hdc, points[i].x, points[i].y)) - WIN32_GDI_FAILED ("LineTo"); - - /* Draw end pixel */ - /* LineTo doesn't draw the last point, so if we have a pen width of 1, - * we draw the end pixel separately... With wider pens we don't care. - * //HB: But the NT developers don't read their API documentation ... - */ - if (gc_data->pen_width <= 1 && windows_version > 0x80000000) - if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y)) - WIN32_GDI_FAILED ("LineTo"); -#endif - gdk_gc_postdraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND); + gdk_gc_postdraw (drawable, gc_private, mask); +} + +static void +gdk_win32_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs) +{ + GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + const GdkGCValuesMask mask = GDK_GC_FOREGROUND; + HDC hdc; + + hdc = gdk_gc_predraw (drawable, gc_private, mask); + + pango_win32_render (hdc, font, glyphs, x, y); + + gdk_gc_postdraw (drawable, gc_private, mask); +} + +static void +gdk_win32_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); + GdkGCWin32 *gc_private = GDK_GC_WIN32 (gc); + GdkImagePrivateWin32 *image_private = (GdkImagePrivateWin32 *) image; + GdkColormapPrivateWin32 *colormap_private = (GdkColormapPrivateWin32 *) impl->colormap; + HDC hdc, memdc; + HGDIOBJ oldbitmap; + DIBSECTION ds; + static struct { + BITMAPINFOHEADER bmiHeader; + WORD bmiIndices[256]; + } bmi; + static gboolean bmi_inited = FALSE; + gboolean ok = TRUE; + int i; + + hdc = gdk_gc_predraw (drawable, gc_private, 0); + + if (colormap_private && colormap_private->xcolormap->rc_palette) + { + if (!bmi_inited) + { + for (i = 0; i < 256; i++) + bmi.bmiIndices[i] = i; + bmi_inited = TRUE; + } + + if (GetObject (image_private->hbitmap, sizeof (DIBSECTION), + &ds) != sizeof (DIBSECTION)) + WIN32_GDI_FAILED ("GetObject"), ok = FALSE; +#if 0 + g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n", + xdest, ydest, xsrc, ysrc, width, height); + g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n", + ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits); + g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n", + ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed); +#endif + bmi.bmiHeader = ds.dsBmih; + /* I have spent hours on getting the parameters to + * SetDIBitsToDevice right. I wonder what drugs the guys in + * Redmond were on when they designed this API. + */ + if (ok && SetDIBitsToDevice (hdc, + xdest, ydest, + width, height, + xsrc, (-ds.dsBmih.biHeight)-height-ysrc, + 0, -ds.dsBmih.biHeight, + ds.dsBm.bmBits, + (CONST BITMAPINFO *) &bmi, + DIB_PAL_COLORS) == 0) + WIN32_GDI_FAILED ("SetDIBitsToDevice"); + } + else + { + + if ((memdc = CreateCompatibleDC (hdc)) == NULL) + WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE; + + if (ok && (oldbitmap = SelectObject (memdc, image_private->hbitmap)) == NULL) + WIN32_GDI_FAILED ("SelectObject"), ok = FALSE; + + if (ok && !BitBlt (hdc, xdest, ydest, width, height, + memdc, xsrc, ysrc, SRCCOPY)) + WIN32_GDI_FAILED ("BitBlt"); + + if (oldbitmap != NULL && SelectObject (memdc, oldbitmap) == NULL) + WIN32_GDI_FAILED ("SelectObject"); + + if (memdc != NULL && !DeleteDC (memdc)) + WIN32_GDI_FAILED ("DeleteDC"); + } + gdk_gc_postdraw (drawable, gc_private, 0); +} + +static gint +gdk_win32_get_depth (GdkDrawable *drawable) +{ + /* This is a bit bogus but I'm not sure the other way is better */ + + return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper); } |