Bug 972041 - getCTM should account for CSS transform r=longsonr

We use nsSVGUtils::GetTransformMatrixInUserSpace to support
CSS transform in getCTM.

Differential Revision: https://phabricator.services.mozilla.com/D28969

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-27 08:42:51 +00:00
Родитель 6cfa928fe9
Коммит 92d63fc969
2 изменённых файлов: 34 добавлений и 5 удалений

Просмотреть файл

@ -19,11 +19,13 @@
#include "mozilla/SVGContextPaint.h" #include "mozilla/SVGContextPaint.h"
#include "mozilla/TextUtils.h" #include "mozilla/TextUtils.h"
#include "nsComputedDOMStyle.h" #include "nsComputedDOMStyle.h"
#include "nsContainerFrame.h"
#include "nsFontMetrics.h" #include "nsFontMetrics.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsMathUtils.h" #include "nsMathUtils.h"
#include "nsSVGUtils.h"
#include "nsWhitespaceTokenizer.h" #include "nsWhitespaceTokenizer.h"
#include "SVGAnimationElement.h" #include "SVGAnimationElement.h"
#include "SVGAnimatedPreserveAspectRatio.h" #include "SVGAnimatedPreserveAspectRatio.h"
@ -466,15 +468,37 @@ SVGViewportElement* SVGContentUtils::GetNearestViewportElement(
static gfx::Matrix GetCTMInternal(SVGElement* aElement, bool aScreenCTM, static gfx::Matrix GetCTMInternal(SVGElement* aElement, bool aScreenCTM,
bool aHaveRecursed) { bool aHaveRecursed) {
gfxMatrix matrix = aElement->PrependLocalTransformsTo( auto getLocalTransformHelper =
gfxMatrix(), aHaveRecursed ? eAllTransforms : eUserSpaceToParent); [](SVGElement const* e, bool shouldIncludeChildToUserSpace) -> gfxMatrix {
gfxMatrix ret;
if (auto* f = e->GetPrimaryFrame()) {
ret = nsSVGUtils::GetTransformMatrixInUserSpace(f, f->GetParent());
} else {
// FIXME: Ideally we should also return the correct matrix
// for display:none, but currently transform related code relies
// heavily on the present of a frame.
// For now we just fall back to |PrependLocalTransformsTo| which
// doesn't account for CSS transform.
ret = e->PrependLocalTransformsTo({}, eUserSpaceToParent);
}
if (shouldIncludeChildToUserSpace) {
ret = e->PrependLocalTransformsTo({}, eChildToUserSpace) * ret;
}
return ret;
};
gfxMatrix matrix = getLocalTransformHelper(aElement, aHaveRecursed);
SVGElement* element = aElement; SVGElement* element = aElement;
nsIContent* ancestor = aElement->GetFlattenedTreeParent(); nsIContent* ancestor = aElement->GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVGElement() && while (ancestor && ancestor->IsSVGElement() &&
!ancestor->IsSVGElement(nsGkAtoms::foreignObject)) { !ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
element = static_cast<SVGElement*>(ancestor); element = static_cast<SVGElement*>(ancestor);
matrix *= element->PrependLocalTransformsTo(gfxMatrix()); // i.e. *A*ppend matrix *= getLocalTransformHelper(element, true);
if (!aScreenCTM && SVGContentUtils::EstablishesViewport(element)) { if (!aScreenCTM && SVGContentUtils::EstablishesViewport(element)) {
if (!element->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG) && if (!element->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG) &&
!element->NodeInfo()->Equals(nsGkAtoms::symbol, kNameSpaceID_SVG)) { !element->NodeInfo()->Equals(nsGkAtoms::symbol, kNameSpaceID_SVG)) {
@ -501,7 +525,7 @@ static gfx::Matrix GetCTMInternal(SVGElement* aElement, bool aScreenCTM,
// transforms in this case since that's what we've been doing for // 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 // a while, and it keeps us consistent with WebKit and Opera (if not
// really with the ambiguous spec). // really with the ambiguous spec).
matrix = aElement->PrependLocalTransformsTo(gfxMatrix()); matrix = getLocalTransformHelper(aElement, true);
} }
if (auto* f = element->GetPrimaryFrame()) { if (auto* f = element->GetPrimaryFrame()) {

Просмотреть файл

@ -9,6 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366697
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style> <style>
#padsvg1 { padding-left: 27px; padding-top: 43px; } #padsvg1 { padding-left: 27px; padding-top: 43px; }
#transrect1 { transform: scale(2,3); }
</style> </style>
</head> </head>
<body> <body>
@ -19,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366697
<iframe id="svg" src="getCTM-helper.svg"></iframe> <iframe id="svg" src="getCTM-helper.svg"></iframe>
<svg id="padsvg1" width="100" height="100"> <svg id="padsvg1" width="100" height="100">
<rect width="10" height="10" /> <rect id="transrect1" width="10" height="10" />
</svg> </svg>
<pre id="test"> <pre id="test">
@ -34,6 +35,10 @@ function runTest() {
is(buggy.getCTM().e, 30, "buggy.getCTM().e"); is(buggy.getCTM().e, 30, "buggy.getCTM().e");
is(buggy.getCTM().f, 40, "buggy.getCTM().f"); is(buggy.getCTM().f, 40, "buggy.getCTM().f");
var transrect1 = document.getElementById("transrect1");
is(transrect1.getCTM().a, 2, "transrect1.getCTM().a");
is(transrect1.getCTM().d, 3, "transrect1.getCTM().d");
var padsvg1 = document.getElementById("padsvg1"); var padsvg1 = document.getElementById("padsvg1");
is(padsvg1.getScreenCTM().e - padsvg1.getBoundingClientRect().x, 27, "padsvg1.getScreenCTM().e"); is(padsvg1.getScreenCTM().e - padsvg1.getBoundingClientRect().x, 27, "padsvg1.getScreenCTM().e");
is(padsvg1.getScreenCTM().f - padsvg1.getBoundingClientRect().y, 43, "padsvg1.getScreenCTM().f"); is(padsvg1.getScreenCTM().f - padsvg1.getBoundingClientRect().y, 43, "padsvg1.getScreenCTM().f");