diff options
author | Mart Raudsepp <leio@gentoo.org> | 2012-11-17 23:51:39 +0200 |
---|---|---|
committer | Mart Raudsepp <leio@gentoo.org> | 2012-11-20 08:06:15 +0200 |
commit | 45ca66ee73bfe04a7ac17e2086f2e5d20bfa93e9 (patch) | |
tree | 25396883f4f734a501997e0781b6aab64e2f541e | |
parent | a46486b05f4674fc17f36947c97bc281c1d00d26 (diff) |
lx_exa: Improvements to negative srcX/Y PictOpSrc/Over operations
Adds handling of negative srcX or srcY coordinates, which is used by gtk3
GtkTrayIcon implementation via cairo for centering icons on top of the
destination area.
For now just handle the drawing within source pixmap bounds in these
cases, as full handling of the out of bound zero-vector for PictOpSrc
seems to require bigger refactoring, which is not suitable for the
impending stable release.
The approach implemented here should result in correct rendering for
PictOpOver (as out of bounds with non-repeat mode ends up meaning
transparency). For PictOpSrc no black borders are rendered where
appropriate, but before this approach, no source pixmap would even be
rendered at all, so it should be a net improvement for the upcoming
release, while fixing the gtk3 icons in GNOME3 fallback.
The completely out of bounds special case check didn't work correctly for
negative srcX or srcY because exaScratch.srcWidth/Height are unsigned
types, so the negative srcX or srcY got casted to unsigned, which resulted
in a big number, so srcX >= 0 was always true (but GCC managed to not warn
of the implicit signedness cast).
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=51360
-rw-r--r-- | src/lx_exa.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/src/lx_exa.c b/src/lx_exa.c index 8f3cb68..2e0cd48 100644 --- a/src/lx_exa.c +++ b/src/lx_exa.c @@ -1303,8 +1303,8 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, if (exaScratch.type == COMP_TYPE_ONEPASS) { /* This is the condition srcX or/and srcY is/are out of source * region */ - if (((srcX >= 0 && srcY >= exaScratch.srcHeight) - || (srcX >= exaScratch.srcWidth && srcY >= 0)) && + if (((srcY >= 0 && srcY >= exaScratch.srcHeight) + || (srcX >= 0 && srcX >= exaScratch.srcWidth)) && (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { if (exaScratch.repeat == 1) { opWidth = width; @@ -1345,8 +1345,29 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, opHeight = height; } else { - /* Have not met this condition till now */ - return; + /* FIXME: We can't support negative srcX/Y for all corner cases in + * a sane way without a bit bigger refactoring. So as to avoid + * gross misrenderings (e.g missing tray icons) in current real-world + * applications, just shift destination appropriately for now and + * ignore out of bounds source pixmap zero-vector handling. This is + * actually correct for PictOpOver, but PictOpSrc out of bounds regions + * should be blacked out, but aren't - without this workaround however + * it'd be simply all black instead, which is probably worse till a full + * clean solution solves it for all cases. */ + if (srcX < 0) { + opX -= srcX; + srcX = 0; + } + + if (srcY < 0) { + opY -= srcY; + srcY = 0; + } + + /* EXA has taken care of adjusting srcWidth if it gets cut on the right */ + width = opWidth = exaScratch.srcWidth; + /* EXA has taken care of adjusting srcHeight if it gets cut on the bottom */ + height = opHeight = exaScratch.srcHeight; } } else { @@ -1470,6 +1491,17 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, } /* All black out of the source */ if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS)) { + /* FIXME: We black out the source here, so that any further regions + * in the loop get handled as a source that's a zero-vector (as + * defined for out-of-bounds from source pixmap for RepeatModeNone), + * but this will likely interfere with cases where srcX and/or srcY + * is negative - as opposed to e.g width being larger than srcWidth, + * which is exercised in rendercheck (always rectangle in top-left + * corner). + * Additionally it forces the drawing into tiles of srcWidth/srcHeight + * for non-repeat modes too, where we don't really need to tile it like + * this and could draw the out of bound regions all at once (or at most + * in 4 operations without the big loop). */ lx_composite_all_black(srcOffset, exaScratch.srcWidth, exaScratch.srcHeight); } |