Bug 489151 - Masking and clipping with objectBoundingBox and non-trivial transforms is broken. r=jwatt

This commit is contained in:
Ryo Onodera 2009-04-24 03:10:22 +09:00
parent 0c31d2c87a
commit e70f2603e4
7 changed files with 64 additions and 43 deletions

View File

@ -48,6 +48,7 @@
#include "nsIDOMSVGPoint.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
#include "nsIDOMSVGRect.h"
//----------------------------------------------------------------------
// nsISupports methods
@ -96,14 +97,8 @@ NS_IMETHODIMP nsSVGGraphicElement::GetBBox(nsIDOMSVGRect **_retval)
nsISVGChildFrame* svgframe = do_QueryFrame(frame);
NS_ASSERTION(svgframe, "wrong frame type");
if (svgframe) {
svgframe->SetMatrixPropagation(PR_FALSE);
svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
nsresult rv = svgframe->GetBBox(_retval);
svgframe->SetMatrixPropagation(PR_TRUE);
svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
return rv;
*_retval = nsSVGUtils::GetBBox(frame).get();
return NS_OK;
}
return NS_ERROR_FAILURE;
}

View File

@ -750,14 +750,8 @@ nsSVGSVGElement::GetBBox(nsIDOMSVGRect **_retval)
nsISVGChildFrame* svgframe = do_QueryFrame(frame);
if (svgframe) {
svgframe->SetMatrixPropagation(PR_FALSE);
svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
nsresult rv = svgframe->GetBBox(_retval);
svgframe->SetMatrixPropagation(PR_TRUE);
svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
return rv;
*_retval = nsSVGUtils::GetBBox(frame).get();
return NS_OK;
} else {
// XXX: outer svg
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -0,0 +1,25 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=489151 -->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Test objectBoundingBox clip-path on element with ancestor transform</title>
<desc>
This test checks that the bbox calculation for an objectBoundingBox
clip-path is correctly getting the bbox in the userspace of the
clipped element, and not it's bbox in an ancestor userspace or rootspace.
</desc>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<rect x="0.5" width="0.5" height="1"/>
</clipPath>
<rect width="100%" height="100%" fill="lime"/>
<rect x="100" width="100" height="100" fill="red"/>
<g transform="translate(-100,0)">
<g clip-path="url(#clip)">
<rect x="100" width="100" height="100" fill="red"/>
<rect x="200" width="100" height="100" fill="lime"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 972 B

View File

@ -0,0 +1,25 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=489151 -->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Test objectBoundingBox mask on element with ancestor transform</title>
<desc>
This test checks that the bbox calculation for an objectBoundingBox
mask is correctly getting the bbox in the userspace of the masked
element, and not it's bbox in an ancestor userspace or rootspace.
</desc>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect x="0.5" width="0.5" height="1" fill="white"/>
</mask>
<rect width="100%" height="100%" fill="lime"/>
<rect x="100" width="100" height="100" fill="red"/>
<g transform="translate(-100,0)">
<g mask="url(#mask)">
<rect x="100" width="100" height="100" fill="red"/>
<rect x="200" width="100" height="100" fill="lime"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 994 B

View File

@ -78,6 +78,8 @@ fails == inline-in-xul-basic-01.xul pass.svg
# Bug 456323
# == mask-transformed-01.svg mask-transformed-01-ref.svg
== nested-viewBox-01.svg pass.svg
== objectBoundingBox-and-clipPath.svg pass.svg
== objectBoundingBox-and-mask.svg pass.svg
== objectBoundingBox-and-pattern-01a.svg objectBoundingBox-and-pattern-01-ref.svg
== objectBoundingBox-and-pattern-01b.svg objectBoundingBox-and-pattern-01-ref.svg
== objectBoundingBox-and-pattern-01c.svg objectBoundingBox-and-pattern-01-ref.svg

View File

@ -640,22 +640,12 @@ nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
if (!aContent)
return NS_ERROR_FAILURE;
// Get the calling geometry's bounding box. This
// will be in *device coordinates*
nsISVGChildFrame *callerSVGFrame;
if (callerType == nsGkAtoms::svgGlyphFrame)
callerSVGFrame = do_QueryFrame(aSource->GetParent());
else
callerSVGFrame = do_QueryFrame(aSource);
callerSVGFrame->SetMatrixPropagation(PR_FALSE);
callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED );
callerSVGFrame->GetBBox(aBBox);
callerSVGFrame->SetMatrixPropagation(PR_TRUE);
callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
if (callerType == nsGkAtoms::svgGlyphFrame) {
*aBBox = nsSVGUtils::GetBBox(aSource->GetParent()).get();
} else {
*aBBox = nsSVGUtils::GetBBox(aSource).get();
}
// Sanity check
PRUint16 type = GetPatternUnits();
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {

View File

@ -1402,23 +1402,13 @@ nsSVGUtils::AdjustMatrixForUnits(nsIDOMSVGMatrix *aMatrix,
PRBool gotRect = PR_FALSE;
if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
nsCOMPtr<nsIDOMSVGRect> rect;
svgFrame->GetBBox(getter_AddRefs(rect));
nsCOMPtr<nsIDOMSVGRect> rect = GetBBox(aFrame);
if (rect) {
gotRect = PR_TRUE;
rect->GetX(&minx);
rect->GetY(&miny);
rect->GetWidth(&width);
rect->GetHeight(&height);
// Correct for scaling in outersvg CTM
nsPresContext *presCtx = aFrame->PresContext();
float scaleInv =
presCtx->AppUnitsToGfxUnits(presCtx->AppUnitsPerCSSPixel());
minx /= scaleInv;
miny /= scaleInv;
width /= scaleInv;
height /= scaleInv;
}
} else {
gotRect = PR_TRUE;