зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1915206 - Simplify SVG transforms a bit more. r=longsonr
We no longer need the concept of "local" transforms after bug 878346. Local transforms that we'd need in the future could be represented via attribute mapping. We still need the viewbox transform shenanigans which applies to children only, tho. Differential Revision: https://phabricator.services.mozilla.com/D220290
This commit is contained in:
Родитель
16e3fdbf40
Коммит
fe940af53e
|
@ -1626,7 +1626,7 @@ bool KeyframeEffect::CanAnimateTransformOnCompositor(
|
|||
|
||||
// Async 'transform' animations of aFrames with SVG transforms is not
|
||||
// supported. See bug 779599.
|
||||
if (primaryFrame->IsSVGTransformed()) {
|
||||
if (primaryFrame->GetParentSVGTransforms()) {
|
||||
aPerformanceWarning = AnimationPerformanceWarning::Type::TransformSVG;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/ComputedStyle.h"
|
||||
#include "SVGPathDataParser.h"
|
||||
#include "SVGOuterSVGFrame.h"
|
||||
#include "SVGPathData.h"
|
||||
#include "SVGPathElement.h"
|
||||
|
||||
|
@ -532,13 +532,10 @@ static gfx::Matrix GetCTMInternal(SVGElement* aElement, CTMType aCTMType,
|
|||
!ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
|
||||
element = static_cast<SVGElement*>(ancestor);
|
||||
if (aCTMType == CTMType::NonScalingStroke &&
|
||||
element->IsSVGElement(nsGkAtoms::svg) &&
|
||||
!static_cast<SVGSVGElement*>(element)->IsInner()) {
|
||||
auto* frame = element->GetPrimaryFrame();
|
||||
if (auto* anonKid =
|
||||
frame ? frame->PrincipalChildList().FirstChild() : nullptr) {
|
||||
element->IsSVGElement(nsGkAtoms::svg)) {
|
||||
if (SVGOuterSVGFrame* frame = do_QueryFrame(element->GetPrimaryFrame())) {
|
||||
Matrix childTransform;
|
||||
if (anonKid->IsSVGTransformed(&childTransform)) {
|
||||
if (frame->HasChildrenOnlyTransform(&childTransform)) {
|
||||
return gfx::ToMatrix(matrix) * childTransform;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,10 +72,8 @@ already_AddRefed<DOMSVGAnimatedLength> SVGForeignObjectElement::Height() {
|
|||
gfxMatrix SVGForeignObjectElement::PrependLocalTransformsTo(
|
||||
const gfxMatrix& aMatrix, SVGTransformTypes aWhich) const {
|
||||
// 'transform' attribute:
|
||||
gfxMatrix fromUserSpace =
|
||||
SVGGraphicsElement::PrependLocalTransformsTo(aMatrix, aWhich);
|
||||
if (aWhich == eUserSpaceToParent) {
|
||||
return fromUserSpace;
|
||||
return aMatrix;
|
||||
}
|
||||
// our 'x' and 'y' attributes:
|
||||
float x, y;
|
||||
|
@ -88,11 +86,9 @@ gfxMatrix SVGForeignObjectElement::PrependLocalTransformsTo(
|
|||
}
|
||||
|
||||
gfxMatrix toUserSpace = gfxMatrix::Translation(x, y);
|
||||
if (aWhich == eChildToUserSpace) {
|
||||
return toUserSpace * aMatrix;
|
||||
}
|
||||
MOZ_ASSERT(aWhich == eAllTransforms, "Unknown TransformTypes");
|
||||
return toUserSpace * fromUserSpace;
|
||||
MOZ_ASSERT(aWhich == eAllTransforms || aWhich == eChildToUserSpace,
|
||||
"Unknown TransformTypes");
|
||||
return toUserSpace * aMatrix;
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
|
|
|
@ -32,7 +32,7 @@ class SVGForeignObjectElement final : public SVGGraphicsElement {
|
|||
|
||||
public:
|
||||
// SVGElement specializations:
|
||||
virtual gfxMatrix PrependLocalTransformsTo(
|
||||
gfxMatrix PrependLocalTransformsTo(
|
||||
const gfxMatrix& aMatrix,
|
||||
SVGTransformTypes aWhich = eAllTransforms) const override;
|
||||
bool HasValidDimensions() const override;
|
||||
|
|
|
@ -112,11 +112,10 @@ inline float ComputeSynthesizedViewBoxDimension(
|
|||
// public helpers:
|
||||
|
||||
void SVGViewportElement::UpdateHasChildrenOnlyTransform() {
|
||||
bool hasChildrenOnlyTransform =
|
||||
mHasChildrenOnlyTransform =
|
||||
HasViewBoxOrSyntheticViewBox() ||
|
||||
(IsRootSVGSVGElement() &&
|
||||
static_cast<SVGSVGElement*>(this)->IsScaledOrTranslated());
|
||||
mHasChildrenOnlyTransform = hasChildrenOnlyTransform;
|
||||
}
|
||||
|
||||
void SVGViewportElement::ChildrenOnlyTransformChanged(uint32_t aFlags) {
|
||||
|
@ -253,7 +252,7 @@ gfxMatrix SVGViewportElement::PrependLocalTransformsTo(
|
|||
nullptr);
|
||||
childToUser = ThebesMatrix(GetViewBoxTransform().PostTranslate(x, y));
|
||||
} else if (IsRootSVGSVGElement()) {
|
||||
const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(this);
|
||||
const auto* svg = static_cast<const SVGSVGElement*>(this);
|
||||
const SVGPoint& translate = svg->GetCurrentTranslate();
|
||||
float scale = svg->CurrentScale();
|
||||
childToUser =
|
||||
|
|
|
@ -1693,10 +1693,10 @@ nsRect nsIFrame::GetMarginRectRelativeToSelf() const {
|
|||
bool nsIFrame::IsTransformed() const {
|
||||
if (!HasAnyStateBits(NS_FRAME_MAY_BE_TRANSFORMED)) {
|
||||
MOZ_ASSERT(!IsCSSTransformed());
|
||||
MOZ_ASSERT(!IsSVGTransformed());
|
||||
MOZ_ASSERT(!GetParentSVGTransforms());
|
||||
return false;
|
||||
}
|
||||
return IsCSSTransformed() || IsSVGTransformed();
|
||||
return IsCSSTransformed() || GetParentSVGTransforms();
|
||||
}
|
||||
|
||||
bool nsIFrame::IsCSSTransformed() const {
|
||||
|
@ -1741,10 +1741,7 @@ bool nsIFrame::HasOpacityInternal(float aThreshold,
|
|||
return HasAnimationOfOpacity(aEffectSet);
|
||||
}
|
||||
|
||||
bool nsIFrame::IsSVGTransformed(gfx::Matrix* aOwnTransforms,
|
||||
gfx::Matrix* aFromParentTransforms) const {
|
||||
return false;
|
||||
}
|
||||
bool nsIFrame::DoGetParentSVGTransforms(gfx::Matrix*) const { return false; }
|
||||
|
||||
bool nsIFrame::Extend3DContext(const nsStyleDisplay* aStyleDisplay,
|
||||
const nsStyleEffects* aStyleEffects,
|
||||
|
|
|
@ -2042,16 +2042,18 @@ class nsIFrame : public nsQueryFrame {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if this frame is an SVG frame that has SVG transforms applied
|
||||
* to it, or if its parent frame is an SVG frame that has children-only
|
||||
* Returns true if this frame's parent is an SVG frame that has children-only
|
||||
* transforms (e.g. an SVG viewBox attribute).
|
||||
* If aOwnTransforms is non-null and the frame has its own SVG transforms,
|
||||
* aOwnTransforms will be set to these transforms. If aFromParentTransforms
|
||||
* is non-null and the frame has an SVG parent with children-only transforms,
|
||||
* then aFromParentTransforms will be set to these transforms.
|
||||
* If aFromParentTransforms is non-null, then aFromParentTransforms will be
|
||||
* set to these transforms.
|
||||
*/
|
||||
virtual bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
|
||||
Matrix* aFromParentTransforms = nullptr) const;
|
||||
bool GetParentSVGTransforms(Matrix* aFromParentTransforms = nullptr) const {
|
||||
if (!HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
|
||||
return false;
|
||||
}
|
||||
return DoGetParentSVGTransforms(aFromParentTransforms);
|
||||
}
|
||||
virtual bool DoGetParentSVGTransforms(Matrix* = nullptr) const;
|
||||
|
||||
/**
|
||||
* Returns whether this frame will attempt to extend the 3d transforms of its
|
||||
|
|
|
@ -221,15 +221,14 @@ static void IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame,
|
|||
// This function is basically a simplified copy of
|
||||
// nsDisplayTransform::GetResultingTransformMatrixInternal.
|
||||
|
||||
Matrix svgTransform, parentsChildrenOnlyTransform;
|
||||
const bool hasSVGTransforms =
|
||||
aFrame->HasAnyStateBits(NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||
aFrame->IsSVGTransformed(&svgTransform, &parentsChildrenOnlyTransform);
|
||||
Matrix parentsChildrenOnlyTransform;
|
||||
const bool parentHasChildrenOnlyTransform =
|
||||
aFrame->GetParentSVGTransforms(&parentsChildrenOnlyTransform);
|
||||
|
||||
const nsStyleDisplay* display = aFrame->StyleDisplay();
|
||||
if (!aFrame->HasAnyStateBits(NS_FRAME_MAY_BE_TRANSFORMED) ||
|
||||
(!display->HasTransformProperty() && !display->HasIndividualTransform() &&
|
||||
display->mOffsetPath.IsNone() && !hasSVGTransforms)) {
|
||||
display->mOffsetPath.IsNone() && !parentHasChildrenOnlyTransform)) {
|
||||
if (aActivity->mPreviousTransformScale.isSome()) {
|
||||
// The transform was removed.
|
||||
aActivity->mPreviousTransformScale = Nothing();
|
||||
|
@ -249,12 +248,8 @@ static void IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame,
|
|||
transform = nsStyleTransformMatrix::ReadTransforms(
|
||||
display->mTranslate, display->mRotate, display->mScale, nullptr,
|
||||
display->mTransform, refBox, AppUnitsPerCSSPixel());
|
||||
} else if (hasSVGTransforms) {
|
||||
transform = Matrix4x4::From2D(svgTransform);
|
||||
}
|
||||
|
||||
const bool parentHasChildrenOnlyTransform =
|
||||
hasSVGTransforms && !parentsChildrenOnlyTransform.IsIdentity();
|
||||
if (parentHasChildrenOnlyTransform) {
|
||||
transform *= Matrix4x4::From2D(parentsChildrenOnlyTransform);
|
||||
}
|
||||
|
|
|
@ -6231,13 +6231,14 @@ Matrix4x4 nsDisplayTransform::GetResultingTransformMatrixInternal(
|
|||
|
||||
/* Get the matrix, then change its basis to factor in the origin. */
|
||||
Matrix4x4 result;
|
||||
// Call IsSVGTransformed() regardless of the value of
|
||||
// aProperties.HasTransform(), since we still need any
|
||||
// potential parentsChildrenOnlyTransform.
|
||||
Matrix svgTransform, parentsChildrenOnlyTransform;
|
||||
const bool hasSVGTransforms =
|
||||
|
||||
// See the comment for SVGContainerFrame::HasChildrenOnlyTransform for
|
||||
// an explanation of what children-only transforms are.
|
||||
Matrix parentsChildrenOnlyTransform;
|
||||
const bool parentHasChildrenOnlyTransform =
|
||||
frame && frame->HasAnyStateBits(NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||
frame->IsSVGTransformed(&svgTransform, &parentsChildrenOnlyTransform);
|
||||
frame->GetParentSVGTransforms(&parentsChildrenOnlyTransform) &&
|
||||
!parentsChildrenOnlyTransform.IsIdentity();
|
||||
bool shouldRound = nsLayoutUtils::ShouldSnapToGrid(frame);
|
||||
|
||||
/* Transformed frames always have a transform, or are preserving 3d (and might
|
||||
|
@ -6248,22 +6249,10 @@ Matrix4x4 nsDisplayTransform::GetResultingTransformMatrixInternal(
|
|||
aProperties.mMotion.ptrOr(nullptr), aProperties.mTransform, aRefBox,
|
||||
aAppUnitsPerPixel);
|
||||
}
|
||||
if (hasSVGTransforms) {
|
||||
// Correct the translation components for zoom:
|
||||
float pixelsPerCSSPx = AppUnitsPerCSSPixel() / aAppUnitsPerPixel;
|
||||
svgTransform._31 *= pixelsPerCSSPx;
|
||||
svgTransform._32 *= pixelsPerCSSPx;
|
||||
result *= Matrix4x4::From2D(svgTransform);
|
||||
}
|
||||
|
||||
// Apply any translation due to 'transform-origin' and/or 'transform-box':
|
||||
result.ChangeBasis(aProperties.mToTransformOrigin);
|
||||
|
||||
// See the comment for SVGContainerFrame::HasChildrenOnlyTransform for
|
||||
// an explanation of what children-only transforms are.
|
||||
const bool parentHasChildrenOnlyTransform =
|
||||
hasSVGTransforms && !parentsChildrenOnlyTransform.IsIdentity();
|
||||
|
||||
if (parentHasChildrenOnlyTransform) {
|
||||
float pixelsPerCSSPx = AppUnitsPerCSSPixel() / aAppUnitsPerPixel;
|
||||
parentsChildrenOnlyTransform._31 *= pixelsPerCSSPx;
|
||||
|
|
|
@ -395,11 +395,9 @@ void SVGClipPathFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
|||
gfxMatrix SVGClipPathFrame::GetCanvasTM() { return mMatrixForChildren; }
|
||||
|
||||
gfxMatrix SVGClipPathFrame::GetClipPathTransform(nsIFrame* aClippedFrame) {
|
||||
SVGClipPathElement* content = static_cast<SVGClipPathElement*>(GetContent());
|
||||
|
||||
gfxMatrix tm = content->PrependLocalTransformsTo({}, eChildToUserSpace) *
|
||||
SVGUtils::GetTransformMatrixInUserSpace(this);
|
||||
gfxMatrix tm = SVGUtils::GetTransformMatrixInUserSpace(this);
|
||||
|
||||
auto* content = static_cast<SVGClipPathElement*>(GetContent());
|
||||
SVGAnimatedEnumeration* clipPathUnits =
|
||||
&content->mEnumAttributes[SVGClipPathElement::CLIPPATHUNITS];
|
||||
|
||||
|
@ -455,20 +453,4 @@ SVGBBox SVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox& aBBox,
|
|||
return unionBBox;
|
||||
}
|
||||
|
||||
bool SVGClipPathFrame::IsSVGTransformed(Matrix* aOwnTransforms,
|
||||
Matrix* aFromParentTransforms) const {
|
||||
const auto* e = static_cast<SVGElement const*>(GetContent());
|
||||
Matrix m = ToMatrix(e->PrependLocalTransformsTo({}, eUserSpaceToParent));
|
||||
|
||||
if (m.IsIdentity()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aOwnTransforms) {
|
||||
*aOwnTransforms = m;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -47,9 +47,6 @@ class SVGClipPathFrame final : public SVGContainerFrame {
|
|||
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override {}
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransforms,
|
||||
Matrix* aFromParentTransforms) const override;
|
||||
|
||||
// SVGClipPathFrame methods:
|
||||
|
||||
/**
|
||||
|
|
|
@ -197,9 +197,9 @@ void SVGDisplayContainerFrame::RemoveFrame(DestroyContext& aContext,
|
|||
SVGContainerFrame::RemoveFrame(aContext, aListID, aOldFrame);
|
||||
}
|
||||
|
||||
bool SVGDisplayContainerFrame::IsSVGTransformed(
|
||||
gfx::Matrix* aOwnTransform, gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::IsSVGTransformed(this, aOwnTransform, aFromParentTransform);
|
||||
bool SVGDisplayContainerFrame::DoGetParentSVGTransforms(
|
||||
gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::GetParentSVGTransforms(this, aFromParentTransform);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -127,8 +127,7 @@ class SVGDisplayContainerFrame : public SVGContainerFrame,
|
|||
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransform = nullptr,
|
||||
Matrix* aFromParentTransform = nullptr) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override;
|
||||
|
||||
// ISVGDisplayableFrame interface:
|
||||
void PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
|
||||
|
|
|
@ -147,9 +147,9 @@ void SVGForeignObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
&newList);
|
||||
}
|
||||
|
||||
bool SVGForeignObjectFrame::IsSVGTransformed(
|
||||
Matrix* aOwnTransform, Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::IsSVGTransformed(this, aOwnTransform, aFromParentTransform);
|
||||
bool SVGForeignObjectFrame::DoGetParentSVGTransforms(
|
||||
Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::GetParentSVGTransforms(this, aFromParentTransform);
|
||||
}
|
||||
|
||||
void SVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
|
||||
|
|
|
@ -50,8 +50,7 @@ class SVGForeignObjectFrame final : public nsContainerFrame,
|
|||
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransform,
|
||||
Matrix* aFromParentTransform) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult GetFrameName(nsAString& aResult) const override {
|
||||
|
|
|
@ -122,9 +122,9 @@ void SVGGeometryFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SVGGeometryFrame::IsSVGTransformed(
|
||||
gfx::Matrix* aOwnTransform, gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::IsSVGTransformed(this, aOwnTransform, aFromParentTransform);
|
||||
bool SVGGeometryFrame::DoGetParentSVGTransforms(
|
||||
gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::GetParentSVGTransforms(this, aFromParentTransform);
|
||||
}
|
||||
|
||||
void SVGGeometryFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -70,8 +70,7 @@ class SVGGeometryFrame final : public nsIFrame, public ISVGDisplayableFrame {
|
|||
|
||||
void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
|
||||
Matrix* aFromParentTransforms = nullptr) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult GetFrameName(nsAString& aResult) const override {
|
||||
|
|
|
@ -170,9 +170,9 @@ void SVGImageFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
|
|||
// TODO(heycam): We should handle aspect-ratio, like nsImageFrame does.
|
||||
}
|
||||
|
||||
bool SVGImageFrame::IsSVGTransformed(gfx::Matrix* aOwnTransform,
|
||||
gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::IsSVGTransformed(this, aOwnTransform, aFromParentTransform);
|
||||
bool SVGImageFrame::DoGetParentSVGTransforms(
|
||||
gfx::Matrix* aFromParentTransform) const {
|
||||
return SVGUtils::GetParentSVGTransforms(this, aFromParentTransform);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -85,8 +85,7 @@ class SVGImageFrame final : public nsIFrame,
|
|||
|
||||
void DidSetComputedStyle(ComputedStyle* aOldStyle) final;
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
|
||||
Matrix* aFromParentTransforms = nullptr) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override;
|
||||
|
||||
bool GetIntrinsicImageDimensions(gfx::Size& aSize,
|
||||
AspectRatio& aAspectRatio) const;
|
||||
|
|
|
@ -526,14 +526,6 @@ nsresult SVGOuterSVGFrame::AttributeChanged(int32_t aNameSpaceID,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool SVGOuterSVGFrame::IsSVGTransformed(Matrix* aOwnTransform,
|
||||
Matrix* aFromParentTransform) const {
|
||||
// Our anonymous child's HasChildrenOnlyTransform() implementation makes sure
|
||||
// our children-only transforms are applied to our children. We only care
|
||||
// about transforms that transform our own frame here.
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// painting
|
||||
|
||||
|
@ -796,55 +788,50 @@ void SVGOuterSVGAnonChildFrame::BuildDisplayList(
|
|||
&newList);
|
||||
}
|
||||
|
||||
static Matrix ComputeOuterSVGAnonChildFrameTransform(
|
||||
const SVGOuterSVGAnonChildFrame* aFrame) {
|
||||
bool SVGOuterSVGFrame::HasChildrenOnlyTransform(Matrix* aTransform) const {
|
||||
// Our elements 'transform' attribute is applied to our SVGOuterSVGFrame
|
||||
// parent, and the element's children-only transforms are applied to us, the
|
||||
// anonymous child frame. Since we are the child frame, we apply the
|
||||
// children-only transforms as if they are our own transform.
|
||||
SVGSVGElement* content = static_cast<SVGSVGElement*>(aFrame->GetContent());
|
||||
|
||||
// anonymous child frame.
|
||||
auto* content = static_cast<SVGSVGElement*>(GetContent());
|
||||
if (!content->HasChildrenOnlyTransform()) {
|
||||
return Matrix();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
|
||||
gfxMatrix ownMatrix =
|
||||
content->PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace);
|
||||
|
||||
if (ownMatrix.HasNonTranslation()) {
|
||||
// viewBox, currentScale and currentTranslate should only produce a
|
||||
// rectilinear transform.
|
||||
MOZ_ASSERT(ownMatrix.IsRectilinear(),
|
||||
"Non-rectilinear transform will break the following logic");
|
||||
|
||||
// The nsDisplayTransform code will apply this transform to our frame,
|
||||
// including to our frame position. We don't want our frame position to
|
||||
// be scaled though, so we need to correct for that in the transform.
|
||||
// XXX Yeah, this is a bit hacky.
|
||||
CSSPoint pos = CSSPixel::FromAppUnits(aFrame->GetPosition());
|
||||
CSSPoint scaledPos = CSSPoint(ownMatrix._11 * pos.x, ownMatrix._22 * pos.y);
|
||||
CSSPoint deltaPos = scaledPos - pos;
|
||||
ownMatrix *= gfxMatrix::Translation(-deltaPos.x, -deltaPos.y);
|
||||
if (aTransform) {
|
||||
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
|
||||
*aTransform = gfx::ToMatrix(
|
||||
content->PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace));
|
||||
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
|
||||
// be scaled though, so we need to correct for that in the transform.
|
||||
// XXX Yeah, this is a bit hacky.
|
||||
// viewBox, currentScale and currentTranslate should only produce a
|
||||
// rectilinear transform.
|
||||
MOZ_ASSERT(aTransform->IsRectilinear(),
|
||||
"Non-rectilinear transform will break the following logic");
|
||||
CSSPoint pos =
|
||||
CSSPixel::FromAppUnits(GetContentRectRelativeToSelf().TopLeft());
|
||||
CSSPoint scaledPos =
|
||||
CSSPoint(aTransform->_11 * pos.x, aTransform->_22 * pos.y);
|
||||
CSSPoint deltaPos = scaledPos - pos;
|
||||
*aTransform *= Matrix::Translation(-deltaPos.x, -deltaPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
return gfx::ToMatrix(ownMatrix);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We want this frame to be a reference frame. An easy way to achieve that is
|
||||
// to always return true from this method, even for identity transforms.
|
||||
// This frame being a reference frame ensures that the offset between this
|
||||
// <svg> element and the parent reference frame is completely absorbed by the
|
||||
// nsDisplayTransform that's created for this frame, and that this offset does
|
||||
// not affect our descendants' transforms. Consequently, if the <svg> element
|
||||
// moves, e.g. during scrolling, the transform matrices of our contents are
|
||||
// unaffected. This simplifies invalidation.
|
||||
bool SVGOuterSVGAnonChildFrame::IsSVGTransformed(
|
||||
Matrix* aOwnTransform, Matrix* aFromParentTransform) const {
|
||||
if (aOwnTransform) {
|
||||
*aOwnTransform = ComputeOuterSVGAnonChildFrameTransform(this);
|
||||
}
|
||||
|
||||
bool SVGOuterSVGAnonChildFrame::DoGetParentSVGTransforms(
|
||||
Matrix* aFromParentTransform) const {
|
||||
// We want this frame to be a reference frame. An easy way to achieve that is
|
||||
// to always return true from this method, even for identity transforms.
|
||||
// This frame being a reference frame ensures that the offset between this
|
||||
// <svg> element and the parent reference frame is completely absorbed by the
|
||||
// nsDisplayTransform that's created for this frame, and that this offset does
|
||||
// not affect our descendants' transforms. Consequently, if the <svg> element
|
||||
// moves, e.g. during scrolling, the transform matrices of our contents are
|
||||
// unaffected. This simplifies invalidation.
|
||||
// TODO(emilio): Is the comment above true for WebRender nowadays?
|
||||
SVGUtils::GetParentSVGTransforms(this, aFromParentTransform);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,7 @@ class SVGOuterSVGFrame final : public SVGDisplayContainerFrame,
|
|||
return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
|
||||
}
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransform,
|
||||
Matrix* aFromParentTransform) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override { return false; };
|
||||
|
||||
// Return our anonymous box child.
|
||||
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
|
||||
|
@ -114,13 +113,7 @@ class SVGOuterSVGFrame final : public SVGDisplayContainerFrame,
|
|||
// SVGContainerFrame methods:
|
||||
gfxMatrix GetCanvasTM() override;
|
||||
|
||||
bool HasChildrenOnlyTransform(Matrix* aTransform) const override {
|
||||
// Our anonymous wrapper child must claim our children-only transforms as
|
||||
// its own so that our real children (the frames it wraps) are transformed
|
||||
// by them, and we must pretend we don't have any children-only transforms
|
||||
// so that our anonymous child is _not_ transformed by them.
|
||||
return false;
|
||||
}
|
||||
bool HasChildrenOnlyTransform(Matrix* aTransform) const override;
|
||||
|
||||
/**
|
||||
* Return true only if the height is unspecified (defaulting to 100%) or else
|
||||
|
@ -200,8 +193,7 @@ class SVGOuterSVGAnonChildFrame final : public SVGDisplayContainerFrame {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool IsSVGTransformed(Matrix* aOwnTransform,
|
||||
Matrix* aFromParentTransform) const override;
|
||||
bool DoGetParentSVGTransforms(Matrix*) const override;
|
||||
|
||||
// SVGContainerFrame methods:
|
||||
gfxMatrix GetCanvasTM() override {
|
||||
|
|
|
@ -350,18 +350,15 @@ gfxMatrix SVGUtils::GetCanvasTM(nsIFrame* aFrame) {
|
|||
return content->PrependLocalTransformsTo(parent->GetCanvasTM());
|
||||
}
|
||||
|
||||
bool SVGUtils::IsSVGTransformed(const nsIFrame* aFrame,
|
||||
gfx::Matrix* aOwnTransform,
|
||||
gfx::Matrix* aFromParentTransform) {
|
||||
bool SVGUtils::GetParentSVGTransforms(const nsIFrame* aFrame,
|
||||
gfx::Matrix* aFromParentTransform) {
|
||||
MOZ_ASSERT(aFrame->HasAllStateBits(NS_FRAME_SVG_LAYOUT |
|
||||
NS_FRAME_MAY_BE_TRANSFORMED),
|
||||
"Expecting an SVG frame that can be transformed");
|
||||
bool foundTransform = false;
|
||||
// Check if our parent has children-only transforms:
|
||||
if (SVGContainerFrame* parent = do_QueryFrame(aFrame->GetParent())) {
|
||||
foundTransform = parent->HasChildrenOnlyTransform(aFromParentTransform);
|
||||
return parent->HasChildrenOnlyTransform(aFromParentTransform);
|
||||
}
|
||||
return foundTransform;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SVGUtils::NotifyChildrenOfSVGChange(nsIFrame* aFrame, uint32_t aFlags) {
|
||||
|
@ -1525,9 +1522,6 @@ gfxMatrix SVGUtils::GetTransformMatrixInUserSpace(const nsIFrame* aFrame) {
|
|||
properties.mMotion.ptrOr(nullptr), properties.mTransform, refBox,
|
||||
AppUnitsPerCSSPixel());
|
||||
}
|
||||
if (aFrame->IsSVGTransformed(&svgTransform)) {
|
||||
trans *= Matrix4x4::From2D(svgTransform);
|
||||
}
|
||||
|
||||
trans.ChangeBasis(svgTransformOrigin);
|
||||
|
||||
|
|
|
@ -258,9 +258,8 @@ class SVGUtils final {
|
|||
/*
|
||||
* Returns whether the frame is transformed and what those transforms are.
|
||||
*/
|
||||
static bool IsSVGTransformed(const nsIFrame* aFrame,
|
||||
gfx::Matrix* aOwnTransform,
|
||||
gfx::Matrix* aFromParentTransform);
|
||||
static bool GetParentSVGTransforms(const nsIFrame* aFrame,
|
||||
gfx::Matrix* aFromParentTransform);
|
||||
|
||||
/**
|
||||
* Notify the descendants of aFrame of a change to one of their ancestors
|
||||
|
|
|
@ -239,16 +239,15 @@ void SVGViewportFrame::NotifyViewportOrTransformChanged(uint32_t aFlags) {
|
|||
// SVGContainerFrame methods:
|
||||
|
||||
bool SVGViewportFrame::HasChildrenOnlyTransform(gfx::Matrix* aTransform) const {
|
||||
SVGViewportElement* content = static_cast<SVGViewportElement*>(GetContent());
|
||||
|
||||
if (content->HasViewBoxOrSyntheticViewBox()) {
|
||||
// XXX Maybe return false if the transform is the identity transform?
|
||||
if (aTransform) {
|
||||
*aTransform = content->GetViewBoxTransform();
|
||||
}
|
||||
return true;
|
||||
auto* content = static_cast<SVGViewportElement*>(GetContent());
|
||||
if (!content->HasViewBoxOrSyntheticViewBox()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
// XXX Maybe return false if the transform is the identity transform?
|
||||
if (aTransform) {
|
||||
*aTransform = content->GetViewBoxTransform();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче