Re: GC graphics_exposures
Tor Lillqvist <[email protected]> Mon, 3 Feb 2003 00:54:09 +0000
| Newsgroups | gmane.comp.video.gimp.windows.devel |
|---|---|
| Message-ID | <[email protected]> |
I did some hacking on this, trying various more or less convoluted
ways of finding out if part of the source rectangle of the blit is
obscured, and the corresponding part of the destination rectangle thus
needs a GraphicsExpose-style event.
The solution below uses the only relatively recently documented
GetRandomRgn() API. I'm not 100% satisfied, there are certainly race
possibilities. But it's the best I could come up with. I tried to use
ScrollWindowEx(), but couldn't figure out what the returned hrgnUpdate
region really is supposed to indicate, and if it is of any use in
implementing a GraphicsExpose workalike...
As you see, there is debugging output still left in the code. Also, it
might be a good idea not to use InvalidateRgn(), but instead directly
generate a GDK expose event (which the InvalidateRgn() call eventually
would cause to be generated anyway).
Index: win32/gdkdrawable-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkdrawable-win32.c,v
retrieving revision 1.57
diff -u -2 -r1.57 gdkdrawable-win32.c
--- win32/gdkdrawable-win32.c 9 Dec 2002 00:43:42 -0000 1.57
+++ win32/gdkdrawable-win32.c 3 Feb 2003 00:34:51 -0000
@@ -1559,18 +1559,82 @@
static void
-blit_inside_window (HDC hdc,
- GdkGCWin32 *gcwin32,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height)
+dump_region (HRGN rgn)
+{
+ LPRGNDATA rgndata;
+ DWORD i, nbytes;
+
+ nbytes = GetRegionData (rgn, 0, NULL);
+
+ rgndata = g_malloc (nbytes);
+
+ GetRegionData (rgn, nbytes, rgndata);
+
+ if (rgndata->rdh.nCount == 0)
+ g_print ("EMPTY");
+
+ for (i = 0; i < rgndata->rdh.nCount; i++)
+ {
+ RECT *rect = ((RECT *) rgndata->Buffer) + i;
+ g_print ("(%ld,%ld)--(%ld,%ld) ", rect->left, rect->top, rect->right, rect->bottom);
+ }
+
+ g_free (rgndata);
+}
+
+static void
+blit_inside_window (GdkDrawableImplWin32 *drawable,
+ HDC hdc,
+ GdkGCWin32 *gcwin32,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
{
+ HRGN rgn0, rgn1 = NULL;
+ int rgn1_type = ERROR;
+
GDK_NOTE (MISC, g_print ("blit_inside_window\n"));
+ if (gcwin32->graphics_exposures)
+ {
+ /* Get visible region of window */
+ rgn0 = CreateRectRgn (0, 0, 0, 0);
+ GetRandomRgn (hdc, rgn0, SYSRGN);
+ if (IS_WIN_NT ())
+ {
+ POINT pt = {0, 0};
+ ClientToScreen (drawable->handle, &pt);
+ OffsetRgn (rgn0, -pt.x, -pt.y);
+ }
+ g_print ("rgn0: "), dump_region (rgn0), g_print ("\n");
+
+ /* Source rectangle region */
+ rgn1 = CreateRectRgn (xsrc, ysrc, xsrc + width, ysrc + height);
+ g_print ("rgn1: "), dump_region (rgn1), g_print ("\n");
+
+ /* Subtract visible client region from source. Result is
+ * obscured part of source rectangle.
+ */
+ rgn1_type = CombineRgn (rgn1, rgn1, rgn0, RGN_DIFF);
+ g_print ("rgn1: "), dump_region (rgn1), g_print ("\n");
+ }
+
GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
+
+ if (gcwin32->graphics_exposures)
+ {
+ if (rgn1_type != NULLREGION &&
+ rgn1_type != ERROR)
+ {
+ OffsetRgn (rgn1, xdest - xsrc, ydest - ysrc);
+ InvalidateRgn (drawable->handle, rgn1, FALSE);
+ }
+ DeleteObject (rgn0);
+ DeleteObject (rgn1);
+ }
}
@@ -1636,5 +1700,4 @@
HRGN src_rgn, draw_rgn, outside_rgn;
RECT r;
- GdkDrawableImplWin32 *draw_impl;
GdkDrawableImplWin32 *src_impl = NULL;
gint src_width, src_height;
@@ -1648,6 +1711,4 @@
use_fg_bg));
- draw_impl = (GdkDrawableImplWin32 *) drawable;
-
if (GDK_IS_DRAWABLE_IMPL_WIN32 (src))
src_impl = (GdkDrawableImplWin32 *) src;
@@ -1671,5 +1732,5 @@
else
{
- if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
+ if (GDK_IS_WINDOW_IMPL_WIN32 (drawable))
{
int comb;
@@ -1694,5 +1755,5 @@
r.right - r.left - 1, r.bottom - r.top - 1,
r.left, r.top)));
- InvalidateRgn (draw_impl->handle, outside_rgn, TRUE);
+ InvalidateRgn (drawable->handle, outside_rgn, TRUE);
}
GDI_CALL (DeleteObject, (outside_rgn));
@@ -1726,9 +1787,9 @@
if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
- blit_from_pixmap (use_fg_bg, draw_impl, hdc,
+ blit_from_pixmap (use_fg_bg, drawable, hdc,
(GdkPixmapImplWin32 *) src_impl, GDK_GC_WIN32 (gc),
xsrc, ysrc, xdest, ydest, width, height);
- else if (draw_impl->handle == src_impl->handle)
- blit_inside_window (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
+ else if (drawable->handle == src_impl->handle)
+ blit_inside_window (drawable, hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
else
blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
Index: win32/gdkgc-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkgc-win32.c,v
retrieving revision 1.55
diff -u -2 -r1.55 gdkgc-win32.c
--- win32/gdkgc-win32.c 17 Dec 2002 01:39:11 -0000 1.55
+++ win32/gdkgc-win32.c 3 Feb 2003 00:34:52 -0000
@@ -455,6 +455,8 @@
win32_gc->tile = NULL;
win32_gc->stipple = NULL;
- win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
+ win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN;
+ win32_gc->graphics_exposures = TRUE;
win32_gc->pen_width = 0;
+ win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
win32_gc->pen_dashes = NULL;
win32_gc->pen_num_dashes = 0;
To Post a message, send it to: [email protected]
To Unsubscribe, send a blank message to: [email protected]
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/