From 45ca66ee73bfe04a7ac17e2086f2e5d20bfa93e9 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Sat, 17 Nov 2012 23:51:39 +0200 Subject: 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 --- src/lx_exa.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file 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); } -- cgit v1.2.3