Bug 1915971 - Simplify PrependLocalTransformsTo. r=longsonr

Now that there's only one transform kind seems worth doing this.

Differential Revision: https://phabricator.services.mozilla.com/D220733
This commit is contained in:
Emilio Cobos Álvarez 2024-09-02 17:26:21 +00:00
Родитель 0d05060885
Коммит 8a62f66450
18 изменённых файлов: 49 добавлений и 124 удалений

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

@ -496,15 +496,12 @@ static gfx::Matrix GetCTMInternal(SVGElement* aElement, CTMType aCTMType,
auto getLocalTransformHelper =
[](SVGElement const* e, bool shouldIncludeChildToUserSpace) -> gfxMatrix {
gfxMatrix ret;
if (auto* f = e->GetPrimaryFrame()) {
ret = SVGUtils::GetTransformMatrixInUserSpace(f);
}
if (shouldIncludeChildToUserSpace) {
ret = e->PrependLocalTransformsTo({}, eChildToUserSpace) * ret;
ret = e->ChildToUserSpaceTransform() * ret;
}
return ret;
};

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

@ -41,26 +41,6 @@ class SVGViewportElement;
#define SVG_ZERO_LENGTH_PATH_FIX_FACTOR 512
/**
* SVGTransformTypes controls the transforms that PrependLocalTransformsTo
* applies.
*
* If aWhich is eAllTransforms, then all the transforms from the coordinate
* space established by this element for its children to the coordinate
* space established by this element's parent element for this element, are
* included.
*
* If aWhich is eChildToUserSpace, then only the transforms from the
* coordinate space established by this element for its childre to this
* elements userspace are included. This includes any offsets due to e.g.
* 'x'/'y' attributes, and any transform due to a 'viewBox' attribute, but
* does not include any transforms due to the 'transform' attribute.
*/
enum SVGTransformTypes {
eAllTransforms,
eChildToUserSpace
};
/**
* Functions generally used by SVG Content classes. Functions here
* should not generally depend on layout methods/classes e.g. SVGUtils

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

@ -1564,10 +1564,7 @@ SVGViewportElement* SVGElement::GetCtx() const {
}
/* virtual */
gfxMatrix SVGElement::PrependLocalTransformsTo(const gfxMatrix& aMatrix,
SVGTransformTypes aWhich) const {
return aMatrix;
}
gfxMatrix SVGElement::ChildToUserSpaceTransform() const { return {}; }
SVGElement::LengthAttributesInfo SVGElement::GetLengthInfo() {
return LengthAttributesInfo(nullptr, nullptr, 0);

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

@ -135,23 +135,12 @@ class SVGElement : public SVGElementBase // nsIContent
mozilla::dom::SVGViewportElement* GetCtx() const;
/**
* Returns aMatrix pre-multiplied by (explicit or implicit) transforms that
* are introduced by attributes on this element.
*
* If aWhich is eAllTransforms, then all the transforms from the coordinate
* space established by this element for its children to the coordinate
* space established by this element's parent element for this element, are
* included.
*
* If aWhich is eChildToUserSpace, then only the transforms from the
* coordinate space established by this element for its childre to this
* elements userspace are included. This includes any offsets due to e.g.
* 'x'/'y' attributes, and any transform due to a 'viewBox' attribute, but
* does not include any transforms due to the 'transform' attribute.
* Returns the transforms from the coordinate space established by this
* element for its children to this element's userspace. This includes any
* offsets due to e.g. 'x'/'y' attributes, and any transform due to a
* 'viewBox' attribute.
*/
virtual gfxMatrix PrependLocalTransformsTo(
const gfxMatrix& aMatrix,
SVGTransformTypes aWhich = eAllTransforms) const;
virtual gfxMatrix ChildToUserSpaceTransform() const;
// Setter for to set the current <animateMotion> transformation
// Only visible for SVGGraphicElement, so it's a no-op here, and that

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

@ -68,23 +68,16 @@ already_AddRefed<DOMSVGAnimatedLength> SVGForeignObjectElement::Height() {
//----------------------------------------------------------------------
// SVGElement methods
/* virtual */
gfxMatrix SVGForeignObjectElement::PrependLocalTransformsTo(
const gfxMatrix& aMatrix, SVGTransformTypes aWhich) const {
gfxMatrix SVGForeignObjectElement::ChildToUserSpaceTransform() const {
// our 'x' and 'y' attributes:
float x, y;
if (!SVGGeometryProperty::ResolveAll<SVGT::X, SVGT::Y>(this, &x, &y)) {
// This function might be called for element in display:none subtree
// (e.g. getScreenCTM), we fall back to use SVG attributes.
const_cast<SVGForeignObjectElement*>(this)->GetAnimatedLengthValues(
&x, &y, nullptr);
}
gfxMatrix toUserSpace = gfxMatrix::Translation(x, y);
MOZ_ASSERT(aWhich == eAllTransforms || aWhich == eChildToUserSpace,
"Unknown TransformTypes");
return toUserSpace * aMatrix;
return gfxMatrix::Translation(x, y);
}
/* virtual */

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

@ -32,9 +32,7 @@ class SVGForeignObjectElement final : public SVGGraphicsElement {
public:
// SVGElement specializations:
gfxMatrix PrependLocalTransformsTo(
const gfxMatrix& aMatrix,
SVGTransformTypes aWhich = eAllTransforms) const override;
gfxMatrix ChildToUserSpaceTransform() const override;
bool HasValidDimensions() const override;
// nsIContent interface

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

@ -9,6 +9,7 @@
#include "SVGAnimatedEnumeration.h"
#include "SVGViewportElement.h"
#include "mozilla/SVGImageContext.h"
nsresult NS_NewSVGSVGElement(
nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,

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

@ -604,18 +604,12 @@ void SVGUseElement::UnlinkSource() {
// SVGElement methods
/* virtual */
gfxMatrix SVGUseElement::PrependLocalTransformsTo(
const gfxMatrix& aMatrix, SVGTransformTypes aWhich) const {
// our 'x' and 'y' attributes:
gfxMatrix SVGUseElement::ChildToUserSpaceTransform() const {
float x, y;
if (!SVGGeometryProperty::ResolveAll<SVGT::X, SVGT::Y>(this, &x, &y)) {
const_cast<SVGUseElement*>(this)->GetAnimatedLengthValues(&x, &y, nullptr);
}
gfxMatrix childToUser = gfxMatrix::Translation(x, y);
MOZ_ASSERT(aWhich == eChildToUserSpace || aWhich == eAllTransforms,
"Unknown TransformTypes");
return childToUser * aMatrix;
return gfxMatrix::Translation(x, y);
}
/* virtual */

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

@ -64,9 +64,7 @@ class SVGUseElement final : public SVGUseElementBase,
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
// SVGElement specializations:
gfxMatrix PrependLocalTransformsTo(
const gfxMatrix& aMatrix,
SVGTransformTypes aWhich = eAllTransforms) const override;
gfxMatrix ChildToUserSpaceTransform() const override;
bool HasValidDimensions() const override;
// nsIContent interface

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

@ -237,31 +237,23 @@ float SVGViewportElement::GetLength(uint8_t aCtxType) const {
// SVGElement methods
/* virtual */
gfxMatrix SVGViewportElement::PrependLocalTransformsTo(
const gfxMatrix& aMatrix, SVGTransformTypes aWhich) const {
gfxMatrix childToUser;
gfxMatrix SVGViewportElement::ChildToUserSpaceTransform() const {
auto viewBox = GetViewBoxTransform();
if (IsInner()) {
float x, y;
const_cast<SVGViewportElement*>(this)->GetAnimatedLengthValues(&x, &y,
nullptr);
childToUser = ThebesMatrix(GetViewBoxTransform().PostTranslate(x, y));
} else if (IsRootSVGSVGElement()) {
return ThebesMatrix(viewBox.PostTranslate(x, y));
}
if (IsRootSVGSVGElement()) {
const auto* svg = static_cast<const SVGSVGElement*>(this);
const SVGPoint& translate = svg->GetCurrentTranslate();
float scale = svg->CurrentScale();
childToUser =
ThebesMatrix(GetViewBoxTransform()
.PostScale(scale, scale)
.PostTranslate(translate.GetX(), translate.GetY()));
} else {
// outer-<svg>, but inline in some other content:
childToUser = ThebesMatrix(GetViewBoxTransform());
return ThebesMatrix(viewBox.PostScale(scale, scale)
.PostTranslate(translate.GetX(), translate.GetY()));
}
MOZ_ASSERT(aWhich == eAllTransforms || aWhich == eChildToUserSpace,
"Unknown TransformTypes");
return childToUser * aMatrix;
// outer-<svg>, but inline in some other content:
return ThebesMatrix(viewBox);
}
/* virtual */

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

@ -8,9 +8,6 @@
#define DOM_SVG_SVGVIEWPORTELEMENT_H_
#include "mozilla/Attributes.h"
#include "mozilla/SVGImageContext.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/FromParser.h"
#include "nsIContentInlines.h"
#include "SVGAnimatedEnumeration.h"
#include "SVGAnimatedLength.h"
@ -45,9 +42,7 @@ class SVGViewportElement : public SVGGraphicsElement {
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
// SVGElement specializations:
gfxMatrix PrependLocalTransformsTo(
const gfxMatrix& aMatrix,
SVGTransformTypes aWhich = eAllTransforms) const override;
gfxMatrix ChildToUserSpaceTransform() const override;
bool HasValidDimensions() const override;

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

@ -125,7 +125,7 @@ class ISVGDisplayableFrame : public nsQueryFrame {
* SVG defines an element's bbox to be the element's fill bounds in the
* userspace established by that element. By allowing callers to pass in the
* transform from the userspace established by this element to the userspace
* established by an an ancestor, this method allows callers to obtain this
* established by an ancestor, this method allows callers to obtain this
* element's fill bounds in the userspace established by that ancestor
* instead. In that case, since we return the bounds in a different userspace
* (the ancestor's), the bounds we return are not this element's bbox, but

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

@ -217,7 +217,7 @@ void SVGDisplayContainerFrame::PaintSVG(gfxContext& aContext,
gfxMatrix matrix = aTransform;
if (auto* svg = SVGElement::FromNode(GetContent())) {
matrix = svg->PrependLocalTransformsTo(matrix, eChildToUserSpace);
matrix = svg->ChildToUserSpaceTransform() * matrix;
if (matrix.IsSingular()) {
return;
}
@ -250,7 +250,7 @@ nsIFrame* SVGDisplayContainerFrame::GetFrameForPoint(const gfxPoint& aPoint) {
// for its children (e.g. take account of any 'viewBox' attribute):
gfxPoint point = aPoint;
if (const auto* svg = SVGElement::FromNode(GetContent())) {
gfxMatrix m = svg->PrependLocalTransformsTo({}, eChildToUserSpace);
gfxMatrix m = svg->ChildToUserSpaceTransform();
if (!m.IsIdentity()) {
if (!m.Invert()) {
return nullptr;
@ -399,7 +399,7 @@ SVGBBox SVGDisplayContainerFrame::GetBBoxContribution(
}
gfxMatrix transform = gfx::ThebesMatrix(aToBBoxUserspace);
if (svg) {
transform = svg->PrependLocalTransformsTo({}, eChildToUserSpace) *
transform = svg->ChildToUserSpaceTransform() *
SVGUtils::GetTransformMatrixInUserSpace(kid) * transform;
}
// We need to include zero width/height vertical/horizontal lines, so we
@ -414,13 +414,10 @@ SVGBBox SVGDisplayContainerFrame::GetBBoxContribution(
gfxMatrix SVGDisplayContainerFrame::GetCanvasTM() {
if (!mCanvasTM) {
NS_ASSERTION(GetParent(), "null parent");
auto* parent = static_cast<SVGContainerFrame*>(GetParent());
auto* content = static_cast<SVGElement*>(GetContent());
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM());
mCanvasTM = MakeUnique<gfxMatrix>(tm);
mCanvasTM = MakeUnique<gfxMatrix>(content->ChildToUserSpaceTransform() *
parent->GetCanvasTM());
}
return *mCanvasTM;

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

@ -366,13 +366,10 @@ SVGBBox SVGForeignObjectFrame::GetBBoxContribution(
gfxMatrix SVGForeignObjectFrame::GetCanvasTM() {
if (!mCanvasTM) {
NS_ASSERTION(GetParent(), "null parent");
auto* parent = static_cast<SVGContainerFrame*>(GetParent());
auto* content = static_cast<SVGForeignObjectElement*>(GetContent());
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM());
mCanvasTM = MakeUnique<gfxMatrix>(tm);
mCanvasTM = MakeUnique<gfxMatrix>(content->ChildToUserSpaceTransform() *
parent->GetCanvasTM());
}
return *mCanvasTM;
}

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

@ -530,8 +530,7 @@ gfxMatrix SVGGeometryFrame::GetCanvasTM() {
auto* parent = static_cast<SVGContainerFrame*>(GetParent());
auto* content = static_cast<SVGGraphicsElement*>(GetContent());
return content->PrependLocalTransformsTo(parent->GetCanvasTM());
return content->ChildToUserSpaceTransform() * parent->GetCanvasTM();
}
void SVGGeometryFrame::Render(gfxContext* aContext, uint32_t aRenderComponents,

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

@ -634,7 +634,7 @@ SVGBBox SVGOuterSVGFrame::GetBBoxContribution(
!PrincipalChildList().FirstChild()->GetNextSibling(),
"We should have a single, anonymous, child");
// We must defer to our child so that we don't include our
// content->PrependLocalTransformsTo() transforms.
// content->ChildToUserSpaceTransform() transform.
auto* anonKid = static_cast<SVGOuterSVGAnonChildFrame*>(
PrincipalChildList().FirstChild());
return anonKid->GetBBoxContribution(aToBBoxUserspace, aFlags);
@ -649,8 +649,8 @@ gfxMatrix SVGOuterSVGFrame::GetCanvasTM() {
float devPxPerCSSPx = 1.0f / nsPresContext::AppUnitsToFloatCSSPixels(
PresContext()->AppUnitsPerDevPixel());
gfxMatrix tm = content->PrependLocalTransformsTo(
gfxMatrix::Scaling(devPxPerCSSPx, devPxPerCSSPx));
gfxMatrix tm = content->ChildToUserSpaceTransform().PostScale(
devPxPerCSSPx, devPxPerCSSPx);
mCanvasTM = MakeUnique<gfxMatrix>(tm);
}
return *mCanvasTM;
@ -797,9 +797,9 @@ bool SVGOuterSVGFrame::HasChildrenOnlyTransform(Matrix* aTransform) const {
return false;
}
if (aTransform) {
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
*aTransform = gfx::ToMatrix(
content->PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace));
// Outer-<svg> doesn't use x/y, so we can use the child-to-user-space
// transform here.
*aTransform = gfx::ToMatrix(content->ChildToUserSpaceTransform());
if (aTransform->HasNonTranslation()) {
// The nsDisplayTransform code will apply this transform to our inner kid,
// including to its frame position. We don't want our frame position to

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

@ -229,9 +229,9 @@ SVGBBox SVGSwitchFrame::GetBBoxContribution(const Matrix& aToBBoxUserspace,
nsIContent* content = kid->GetContent();
gfxMatrix transform = ThebesMatrix(aToBBoxUserspace);
if (content->IsSVGElement()) {
transform = static_cast<SVGElement*>(content)->PrependLocalTransformsTo(
{}, eChildToUserSpace) *
SVGUtils::GetTransformMatrixInUserSpace(kid) * transform;
transform =
static_cast<SVGElement*>(content)->ChildToUserSpaceTransform() *
SVGUtils::GetTransformMatrixInUserSpace(kid) * transform;
}
return svgKid->GetBBoxContribution(ToMatrix(transform), aFlags);
}
@ -241,7 +241,6 @@ SVGBBox SVGSwitchFrame::GetBBoxContribution(const Matrix& aToBBoxUserspace,
nsIFrame* SVGSwitchFrame::GetActiveChildFrame() {
auto* activeChild =
static_cast<dom::SVGSwitchElement*>(GetContent())->GetActiveChild();
return activeChild ? activeChild->GetPrimaryFrame() : nullptr;
}

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

@ -347,7 +347,7 @@ gfxMatrix SVGUtils::GetCanvasTM(nsIFrame* aFrame) {
auto* parent = static_cast<SVGContainerFrame*>(aFrame->GetParent());
auto* content = static_cast<SVGElement*>(aFrame->GetContent());
return content->PrependLocalTransformsTo(parent->GetCanvasTM());
return content->ChildToUserSpaceTransform() * parent->GetCanvasTM();
}
bool SVGUtils::GetParentSVGTransforms(const nsIFrame* aFrame,
@ -888,8 +888,8 @@ gfxRect SVGUtils::GetBBox(nsIFrame* aFrame, uint32_t aFlags,
// NOTE: When changing this to apply to other frame types, make sure to
// also update SVGUtils::FrameSpaceInCSSPxToUserSpaceOffset.
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "bad cast");
SVGElement* element = static_cast<SVGElement*>(aFrame->GetContent());
matrix = element->PrependLocalTransformsTo(matrix, eChildToUserSpace);
auto* element = static_cast<SVGElement*>(aFrame->GetContent());
matrix = element->ChildToUserSpaceTransform() * matrix;
}
gfxRect bbox =
svg->GetBBoxContribution(ToMatrix(matrix), aFlags).ToThebesRect();
@ -966,9 +966,8 @@ gfxPoint SVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(const nsIFrame* aFrame) {
// For foreignObject frames, SVGUtils::GetBBox applies their local
// transform, so we need to do the same here.
if (aFrame->IsSVGForeignObjectFrame()) {
gfxMatrix transform =
static_cast<SVGElement*>(aFrame->GetContent())
->PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace);
gfxMatrix transform = static_cast<SVGElement*>(aFrame->GetContent())
->ChildToUserSpaceTransform();
NS_ASSERTION(!transform.HasNonTranslation(),
"we're relying on this being an offset-only transform");
return transform.GetTranslation();
@ -1462,9 +1461,9 @@ bool SVGUtils::GetSVGGlyphExtents(const Element* aElement,
return false;
}
gfxMatrix transform(aSVGToAppSpace);
gfxMatrix transform = aSVGToAppSpace;
if (auto* svg = SVGElement::FromNode(frame->GetContent())) {
transform = svg->PrependLocalTransformsTo(aSVGToAppSpace);
transform = svg->ChildToUserSpaceTransform() * transform;
}
*aResult =