Only create a single display transform for SVG frames with single child transforms.

This improves performance on repeated scaling of vectors.
This commit is contained in:
wolfbeast
2017-06-28 21:47:18 +02:00
parent 10494e1b7d
commit de11930c3f
2 changed files with 37 additions and 14 deletions
+34 -12
View File
@@ -979,21 +979,43 @@ nsSVGOuterSVGAnonChildFrame::GetType() const
}
bool
nsSVGOuterSVGAnonChildFrame::HasChildrenOnlyTransform(gfx::Matrix *aTransform) const
nsSVGOuterSVGAnonChildFrame::IsSVGTransformed(Matrix* aOwnTransform,
Matrix* aFromParentTransform) const
{
// We must claim our nsSVGOuterSVGFrame's children-only transforms as our own
// so that the children we are used to wrap are transformed properly.
// Our elements 'transform' attribute is applied to our nsSVGOuterSVGFrame
// 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*>(mContent);
SVGSVGElement* content = static_cast<SVGSVGElement*>(mContent);
bool hasTransform = content->HasChildrenOnlyTransform();
if (hasTransform && aTransform) {
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
gfxMatrix identity;
*aTransform = gfx::ToMatrix(
content->PrependLocalTransformsTo(identity, eChildToUserSpace));
if (!content->HasChildrenOnlyTransform()) {
return false;
}
return hasTransform;
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
gfxMatrix ownMatrix =
content->PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace);
if (ownMatrix.IsIdentity()) {
return false;
}
if (aOwnTransform) {
if (ownMatrix.HasNonTranslation()) {
// Note: viewBox, currentScale and currentTranslate should only
// produce a rectilinear transform.
// 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.
CSSPoint pos = CSSPixel::FromAppUnits(GetPosition());
CSSPoint scaledPos = CSSPoint(ownMatrix._11 * pos.x, ownMatrix._22 * pos.y);
CSSPoint deltaPos = scaledPos - pos;
ownMatrix *= gfxMatrix::Translation(-deltaPos.x, -deltaPos.y);
}
*aOwnTransform = gfx::ToMatrix(ownMatrix);
}
return true;
}
+3 -2
View File
@@ -263,6 +263,9 @@ public:
*/
virtual nsIAtom* GetType() const override;
bool IsSVGTransformed(Matrix *aOwnTransform,
Matrix *aFromParentTransform) const override;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM() override {
// GetCanvasTM returns the transform from an SVG frame to the frame's
@@ -270,8 +273,6 @@ public:
// set on us for any CSS border or padding on our nsSVGOuterSVGFrame.
return static_cast<nsSVGOuterSVGFrame*>(GetParent())->GetCanvasTM();
}
virtual bool HasChildrenOnlyTransform(Matrix *aTransform) const override;
};
#endif