diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2015-06-21 12:08:15 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2015-06-21 12:08:15 +0000 |
| commit | 8c4a98ac365afb74ad418cb24a28322320801465 (patch) | |
| tree | d44478119a90ffe710fde0ac8b8294fa3fe2bc61 | |
| parent | c0b97d86d4a5b62949dbd90a0e28891d95c7076e (diff) | |
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
| -rw-r--r-- | src/Fl_Pixmap.cxx | 42 |
1 files changed, 31 insertions, 11 deletions
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 <config.h> #include <FL/Fl.H> #include <FL/fl_draw.H> #include <FL/x.H> @@ -40,6 +41,10 @@ #include <FL/Fl_Pixmap.H> #include <FL/Fl_Printer.H> +#if defined(USE_X11) +#include <X11/Xregion.h> +#endif + #include <stdio.h> #include "flstring.h" #include <ctype.h> @@ -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); } //------------------------------------------------------------------------------ |
