Bug 769103 - Get SVG masks working for HTML elements under CSS transforms. r=roc.

This commit is contained in:
Jonathan Watt 2012-06-28 23:59:05 +01:00
parent 53377817cd
commit 85c5167bf8
4 changed files with 101 additions and 7 deletions

View File

@ -0,0 +1,42 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test SVG masking of transformed HTML elements</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=769103 -->
<style type="text/css">
* { margin: 0; border: 0; padding: 0;}
div {
position: absolute;
left: 1px;
top: 1px;
width: 3px;
height: 3px;
-moz-transform: scale(100,100);
-moz-transform-origin: 0 0;
}
</style>
</head>
<body bgcolor="lime">
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"
style="display:block; position:absolute;">
<mask id="mask1" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.48" fill="white"/>
</mask>
<mask id="mask2" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5" fill="white"/>
</mask>
<circle cx="150" cy="150" r="147" fill="red"/>
</svg>
<div style="background: red; mask: url(#mask1);"/>
<div style="background: lime; mask: url(#mask2);"/>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test SVG masking of transformed HTML elements</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=769103 -->
<style type="text/css">
* { margin: 0; border: 0; padding: 0;}
div {
position: absolute;
left: 50px;
top: 50px;
width: 150px;
height: 150px;
-moz-transform: scale(2,2);
-moz-transform-origin: 0 0;
}
</style>
</head>
<body bgcolor="lime">
<svg xmlns="http://www.w3.org/2000/svg" width="350" height="350"
style="display:block; position:absolute;">
<mask id="mask1" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.48" fill="white"/>
</mask>
<mask id="mask2" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.50" fill="white"/>
</mask>
<circle cx="200" cy="200" r="147" fill="red"/>
</svg>
<div style="background: red; mask: url(#mask1);"/>
<div style="background: lime; mask: url(#mask2);"/>
</body>
</html>

View File

@ -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

View File

@ -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;
}