From 8c4a98ac365afb74ad418cb24a28322320801465 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Sun, 21 Jun 2015 12:08:15 +0000 Subject: Fix Fl_Pixmap (background) drawing to respect the clip region (STR #3206). STR title: (Re-)drawing artefacts with scheme plastic after STR 3059. It turned out that drawing a pixmap could enlarge the clip region if the intersection of the clip region and the pixmap was not a single rectangle. Hence drawing the background pixmap would draw outside the clip region and leave artefacts when a widget was drawn on top of it. See STR #3206. Thanks to Manolo who had the idea and provided a patch to draw into the individual rectangles of a multi-rectangle clip region. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10771 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_Pixmap.cxx | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index 62198cc97..160c88e85 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -32,6 +32,7 @@ // Implemented without using the xpm library (which I can't use because // it interferes with the color cube used by fl_draw_image). +#include #include #include #include @@ -40,6 +41,10 @@ #include #include +#if defined(USE_X11) +#include +#endif + #include #include "flstring.h" #include @@ -195,23 +200,38 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int H int X, Y, W, H; if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; if (pxm->mask_) { - // I can't figure out how to combine a mask with existing region, - // so cut the image down to a clipped rectangle: - int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); - cx += nx-X; X = nx; - cy += ny-Y; Y = ny; // make X use the bitmap as a mask: XSetClipMask(fl_display, fl_gc, pxm->mask_); - int ox = X-cx; if (ox < 0) ox += pxm->w(); - int oy = Y-cy; if (oy < 0) oy += pxm->h(); XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); - } - copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); - if (pxm->mask_) { + if (clip_region()) { + // At this point, XYWH is the bounding box of the intersection between + // the current clip region and the (portion of the) pixmap we have to draw. + // The current clip region is often a rectangle. But, when a window with rounded + // corners is moved above another window, expose events may create a complex clip + // region made of several (e.g., 10) rectangles. We have to draw only in the clip + // region, and also to mask out the transparent pixels of the image. This can't + // be done in a single Xlib call for a multi-rectangle clip region. Thus, we + // process each rectangle of the intersection between the clip region and XYWH. + // See also STR #3206. + Region r = XRectangleRegion(X,Y,W,H); + XIntersectRegion(r, clip_region(), r); + int X1, Y1, W1, H1; + for (int i = 0; i < r->numRects; i++) { + X1 = r->rects[i].x1; + Y1 = r->rects[i].y1; + W1 = r->rects[i].x2 - r->rects[i].x1; + H1 = r->rects[i].y2 - r->rects[i].y1; + copy_offscreen(X1, Y1, W1, H1, pxm->id_, cx + (X1 - X), cy + (Y1 - Y)); + } + XDestroyRegion(r); + } else { + copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); + } // put the old clip region back XSetClipOrigin(fl_display, fl_gc, 0, 0); - fl_restore_clip(); + restore_clip(); } + else copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); } //------------------------------------------------------------------------------ -- cgit v1.2.3