Bug 762411 - getScreenCTM scaling broken on inline outer svg elements. r=jwatt

This commit is contained in:
Robert Longson 2012-06-13 14:32:23 +01:00
parent 359b2d608d
commit aff81fb50f
4 changed files with 26 additions and 15 deletions

View File

@ -681,16 +681,7 @@ nsSVGSVGElement::GetCTM(nsIDOMSVGMatrix * *aCTM)
NS_IMETHODIMP
nsSVGSVGElement::GetScreenCTM(nsIDOMSVGMatrix **aCTM)
{
gfxMatrix m;
if (IsRoot()) {
// Consistency with other elements would have us return only the
// eFromUserSpace transforms, but this is what we've been doing for
// a while, and it keeps us consistent with WebKit and Opera (if not
// really with the ambiguous spec).
m = PrependLocalTransformsTo(m);
} else {
m = nsSVGUtils::GetCTM(this, true);
}
gfxMatrix m = nsSVGUtils::GetCTM(this, true);
*aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
NS_IF_ADDREF(*aCTM);
return NS_OK;

View File

@ -27,6 +27,12 @@
<g id="g2" transform="translate(600, 700)"/>
</svg>
</foreignObject>
<foreignObject x="30" y="40" width="100" height="100" transform="translate(1, 1)">
<html xmlns="http://www.w3.org/1999/xhtml" style="width: 100%; height: 100%">
<svg xmlns="http://www.w3.org/2000/svg" id="outer2"
width="100" height="100" viewBox="100 100 200 200"/>
</html>
</foreignObject>
<!-- something invalid -->
<foreignObject>
<g id="g3"/>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -32,6 +32,7 @@ function runTest()
var inner = doc.getElementById("inner");
var g1 = doc.getElementById("g1");
var outer = doc.getElementById("outer");
var outer2 = doc.getElementById("outer2");
var g2 = doc.getElementById("g2");
var g3 = doc.getElementById("g3");
var g4 = doc.getElementById("g4");
@ -82,6 +83,9 @@ function runTest()
// outer.farthestViewportElement == null (but actually == root)
is((function(){try{return outer.getScreenCTM().e}catch(e){return e}})(), 46, "outer.getScreenCTM().e");
is((function(){try{return outer.getScreenCTM().f}catch(e){return e}})(), 69, "outer.getScreenCTM().f");
// outer.farthestViewportElement == null (but actually == root)
is((function(){try{return outer2.getScreenCTM().e}catch(e){return e}})(), -19, "outer2.getScreenCTM().e");
is((function(){try{return outer2.getScreenCTM().f}catch(e){return e}})(), -8, "outer2.getScreenCTM().f");
// g2.farthestViewportElement == outer (but actually == root)
is((function(){try{return g2.getScreenCTM().e}catch(e){return e}})(), 646, "g2.getScreenCTM().e");
is((function(){try{return g2.getScreenCTM().f}catch(e){return e}})(), 769, "g2.getScreenCTM().f");

View File

@ -485,8 +485,6 @@ nsSVGUtils::GetNearestViewportElement(nsIContent *aContent)
static gfxMatrix
GetCTMInternal(nsSVGElement *aElement, bool aScreenCTM, bool aHaveRecursed)
{
nsIDocument* currentDoc = aElement->GetCurrentDoc();
gfxMatrix matrix = aElement->PrependLocalTransformsTo(gfxMatrix(),
aHaveRecursed ? nsSVGElement::eAllTransforms : nsSVGElement::eUserSpaceToParent);
nsSVGElement *element = aElement;
@ -511,18 +509,30 @@ GetCTMInternal(nsSVGElement *aElement, bool aScreenCTM, bool aHaveRecursed)
// didn't find a nearestViewportElement
return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
}
if (element->Tag() != nsGkAtoms::svg) {
// Not a valid SVG fragment
return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
}
if (element == aElement && !aHaveRecursed) {
// We get here when getScreenCTM() is called on an outer-<svg>.
// Consistency with other elements would have us include only the
// eFromUserSpace transforms, but we include the eAllTransforms
// transforms in this case since that's what we've been doing for
// a while, and it keeps us consistent with WebKit and Opera (if not
// really with the ambiguous spec).
matrix = aElement->PrependLocalTransformsTo(gfxMatrix());
}
if (!ancestor || !ancestor->IsElement()) {
return matrix;
}
if (ancestor->IsSVG()) {
if (element->Tag() != nsGkAtoms::svg) {
return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
}
return
matrix * GetCTMInternal(static_cast<nsSVGElement*>(ancestor), true, true);
}
// XXX this does not take into account CSS transform, or that the non-SVG
// content that we've hit may itself be inside an SVG foreignObject higher up
nsIDocument* currentDoc = aElement->GetCurrentDoc();
float x = 0.0f, y = 0.0f;
if (currentDoc && element->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
nsIPresShell *presShell = currentDoc->GetShell();