From 85c5167bf81e0a9d9975ce975fe58834c4a166ea Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Thu, 28 Jun 2012 23:59:05 +0100 Subject: [PATCH] Bug 769103 - Get SVG masks working for HTML elements under CSS transforms. r=roc. --- .../mask-transformed-html-01.xhtml | 42 +++++++++++++++++++ .../mask-transformed-html-02.xhtml | 42 +++++++++++++++++++ .../reftests/svg/svg-integration/reftest.list | 4 ++ layout/svg/base/src/nsSVGMaskFrame.cpp | 20 +++++---- 4 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 layout/reftests/svg/svg-integration/mask-transformed-html-01.xhtml create mode 100644 layout/reftests/svg/svg-integration/mask-transformed-html-02.xhtml diff --git a/layout/reftests/svg/svg-integration/mask-transformed-html-01.xhtml b/layout/reftests/svg/svg-integration/mask-transformed-html-01.xhtml new file mode 100644 index 00000000000..25d0ad22685 --- /dev/null +++ b/layout/reftests/svg/svg-integration/mask-transformed-html-01.xhtml @@ -0,0 +1,42 @@ + + + + Test SVG masking of transformed HTML elements + + + + + + + + + + + + + + + +
+
+ + + diff --git a/layout/reftests/svg/svg-integration/mask-transformed-html-02.xhtml b/layout/reftests/svg/svg-integration/mask-transformed-html-02.xhtml new file mode 100644 index 00000000000..c614291a684 --- /dev/null +++ b/layout/reftests/svg/svg-integration/mask-transformed-html-02.xhtml @@ -0,0 +1,42 @@ + + + + Test SVG masking of transformed HTML elements + + + + + + + + + + + + + + + +
+
+ + + diff --git a/layout/reftests/svg/svg-integration/reftest.list b/layout/reftests/svg/svg-integration/reftest.list index ca65ac1f445..b0a262fe221 100644 --- a/layout/reftests/svg/svg-integration/reftest.list +++ b/layout/reftests/svg/svg-integration/reftest.list @@ -25,3 +25,7 @@ == mask-html-01-extref-02.xhtml mask-html-01-ref.svg == mask-html-zoomed-01.xhtml mask-html-01-ref.svg == mask-html-xbl-bound-01.html mask-html-01-ref.svg +== mask-transformed-html-01.xhtml ../pass.svg +== mask-transformed-html-02.xhtml ../pass.svg + + diff --git a/layout/svg/base/src/nsSVGMaskFrame.cpp b/layout/svg/base/src/nsSVGMaskFrame.cpp index 4775852c956..d9016408264 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.cpp +++ b/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -53,18 +53,14 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext, gfxContext *gfx = aContext->ThebesContext(); + // Get the clip extents in device space: gfx->Save(); nsSVGUtils::SetClipRect(gfx, aMatrix, maskArea); + gfx->IdentityMatrix(); gfxRect clipExtents = gfx->GetClipExtents(); clipExtents.RoundOut(); gfx->Restore(); -#ifdef DEBUG_tor - fprintf(stderr, "clip extent: %f,%f %fx%f\n", - clipExtents.X(), clipExtents.Y(), - clipExtents.Width(), clipExtents.Height()); -#endif - bool resultOverflows; gfxIntSize surfaceSize = nsSVGUtils::ConvertToSurfaceSize(gfxSize(clipExtents.Width(), @@ -82,10 +78,19 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext, new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32); if (!image || image->CairoStatus()) return nsnull; - image->SetDeviceOffset(-clipExtents.TopLeft()); + + // We would like to use gfxImageSurface::SetDeviceOffset() to position + // 'image'. However, we need to set the same matrix on the temporary context + // and pattern that we create below as is currently set on 'gfx'. + // Unfortunately, any device offset set by SetDeviceOffset() is affected by + // the transform passed to the SetMatrix() calls, so to avoid that we account + // for the device offset in the transform rather than use SetDeviceOffset(). + gfxMatrix matrix = + gfx->CurrentMatrix() * gfxMatrix().Translate(-clipExtents.TopLeft()); nsRenderingContext tmpCtx; tmpCtx.Init(this->PresContext()->DeviceContext(), image); + tmpCtx.ThebesContext()->SetMatrix(matrix); mMaskParent = aParent; if (mMaskParentMatrix) { @@ -132,6 +137,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext, } gfxPattern *retval = new gfxPattern(image); + retval->SetMatrix(matrix); NS_IF_ADDREF(retval); return retval; }