Commit aa1a99e8 authored by pdr@chromium.org's avatar pdr@chromium.org

Devirtualize animatedLocalTransform() and rename it for clarity

This patch devirtualizes animatedLocalTransform and renames it
calculateAnimatedLocalTransform to emphasize that it is not cheap.

SVGGraphicsElement::animatedLocalTransform was virtual to support
SVGTextElement's special transform code. The text-specific
transform code is only in an infrequently-taken codepath
(style && style->hasTransform()) so we can actually improve performance
by devirtalizing and combining the two transform codepaths. The real
benefit is code simplification though.

Secondly, I've renamed this function to make it clear that it is not
a simple lookup.

BUG=429551

Review URL: https://codereview.chromium.org/693423002

git-svn-id: svn://svn.chromium.org/blink/trunk@184845 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2c9ab053
......@@ -84,7 +84,7 @@ void RenderSVGForeignObject::layout()
bool updateCachedBoundariesInParents = false;
if (m_needsTransformUpdate) {
m_localTransform = foreign->animatedLocalTransform();
m_localTransform = foreign->calculateAnimatedLocalTransform();
m_needsTransformUpdate = false;
updateCachedBoundariesInParents = true;
}
......
......@@ -123,7 +123,7 @@ void RenderSVGImage::layout()
bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundariesUpdate;
if (m_needsTransformUpdate) {
m_localTransform = toSVGImageElement(element())->animatedLocalTransform();
m_localTransform = toSVGImageElement(element())->calculateAnimatedLocalTransform();
m_needsTransformUpdate = false;
}
......
......@@ -149,7 +149,7 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
return false;
TemporaryChange<bool> inClipExpansionChange(m_inClipExpansion, true);
AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->animatedLocalTransform();
AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->calculateAnimatedLocalTransform();
// When drawing a clip for non-SVG elements, the CTM does not include the zoom factor.
// In this case, we need to apply the zoom scale explicitly - but only for clips with
// userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolved lengths).
......@@ -306,7 +306,7 @@ void RenderSVGResourceClipper::calculateClipContentPaintInvalidationRect()
continue;
m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->paintInvalidationRectInLocalCoordinates()));
}
m_clipBoundaries = toSVGClipPathElement(element())->animatedLocalTransform().mapRect(m_clipBoundaries);
m_clipBoundaries = toSVGClipPathElement(element())->calculateAnimatedLocalTransform().mapRect(m_clipBoundaries);
}
bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint)
......@@ -322,7 +322,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
point = transform.inverse().mapPoint(point);
}
AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->animatedLocalTransform();
AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->calculateAnimatedLocalTransform();
if (!animatedLocalTransform.isInvertible())
return false;
......
......@@ -123,7 +123,7 @@ void RenderSVGShape::layout()
}
if (m_needsTransformUpdate) {
m_localTransform = toSVGGraphicsElement(element())->animatedLocalTransform();
m_localTransform = toSVGGraphicsElement(element())->calculateAnimatedLocalTransform();
m_needsTransformUpdate = false;
updateCachedBoundariesInParents = true;
}
......
......@@ -326,7 +326,7 @@ void RenderSVGText::layout()
bool updateCachedBoundariesInParents = false;
if (m_needsTransformUpdate) {
m_localTransform = toSVGTextElement(node())->animatedLocalTransform();
m_localTransform = toSVGTextElement(node())->calculateAnimatedLocalTransform();
m_needsTransformUpdate = false;
updateCachedBoundariesInParents = true;
}
......
......@@ -58,7 +58,7 @@ Path RenderSVGTextPath::layoutPath() const
// the current 'text' element, including any adjustments to the current user coordinate
// system due to a possible transform attribute on the current 'text' element.
// http://www.w3.org/TR/SVG/text.html#TextPathElement
pathData.transform(pathElement.animatedLocalTransform());
pathData.transform(pathElement.calculateAnimatedLocalTransform());
return pathData;
}
......
......@@ -100,7 +100,7 @@ bool RenderSVGTransformableContainer::calculateLocalTransform()
if (!m_needsTransformUpdate)
return false;
m_localTransform = element->animatedLocalTransform();
m_localTransform = element->calculateAnimatedLocalTransform();
m_localTransform.translate(m_lastTranslation.width(), m_lastTranslation.height());
m_needsTransformUpdate = false;
return true;
......
......@@ -122,7 +122,7 @@ PassRefPtr<SVGMatrixTearOff> SVGGraphicsElement::getScreenCTMFromJavascript()
return SVGMatrixTearOff::create(getScreenCTM());
}
AffineTransform SVGGraphicsElement::animatedLocalTransform() const
AffineTransform SVGGraphicsElement::calculateAnimatedLocalTransform() const
{
AffineTransform matrix;
RenderStyle* style = renderer() ? renderer()->style() : 0;
......@@ -132,22 +132,28 @@ AffineTransform SVGGraphicsElement::animatedLocalTransform() const
TransformationMatrix transform;
float zoom = style->effectiveZoom();
// CSS transforms operate with pre-scaled lengths. To make this work with SVG
// (which applies the zoom factor globally, at the root level) we
//
// * pre-scale the bounding box (to bring it into the same space as the other CSS values)
// * invert the zoom factor (to effectively compute the CSS transform under a 1.0 zoom)
//
// Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath.
// See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/
if (zoom != 1) {
FloatRect scaledBBox = renderer()->objectBoundingBox();
scaledBBox.scale(zoom);
transform.scale(1 / zoom);
style->applyTransform(transform, scaledBBox);
transform.scale(zoom);
// SVGTextElements need special handling for the text positioning code.
if (isSVGTextElement(this)) {
// Do not take into account SVG's zoom rules, transform-origin, or percentage values.
style->applyTransform(transform, IntSize(0, 0), RenderStyle::ExcludeTransformOrigin);
} else {
style->applyTransform(transform, renderer()->objectBoundingBox());
// CSS transforms operate with pre-scaled lengths. To make this work with SVG
// (which applies the zoom factor globally, at the root level) we
//
// * pre-scale the bounding box (to bring it into the same space as the other CSS values)
// * invert the zoom factor (to effectively compute the CSS transform under a 1.0 zoom)
//
// Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath.
// See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/
if (zoom != 1) {
FloatRect scaledBBox = renderer()->objectBoundingBox();
scaledBBox.scale(zoom);
transform.scale(1 / zoom);
style->applyTransform(transform, scaledBBox);
transform.scale(zoom);
} else {
style->applyTransform(transform, renderer()->objectBoundingBox());
}
}
// Flatten any 3D transform.
......@@ -254,8 +260,7 @@ RenderObject* SVGGraphicsElement::createRenderer(RenderStyle*)
void SVGGraphicsElement::toClipPath(Path& path)
{
updatePathFromGraphicsElement(this, path);
// FIXME: How do we know the element has done a layout?
path.transform(animatedLocalTransform());
path.transform(calculateAnimatedLocalTransform());
}
}
......@@ -50,8 +50,8 @@ public:
SVGElement* nearestViewportElement() const;
SVGElement* farthestViewportElement() const;
virtual AffineTransform localCoordinateSpaceTransform(SVGElement::CTMScope) const override { return animatedLocalTransform(); }
virtual AffineTransform animatedLocalTransform() const;
virtual AffineTransform localCoordinateSpaceTransform(SVGElement::CTMScope) const override { return calculateAnimatedLocalTransform(); }
AffineTransform calculateAnimatedLocalTransform() const;
virtual AffineTransform* animateMotionTransform() override;
virtual FloatRect getBBox();
......
......@@ -32,31 +32,6 @@ inline SVGTextElement::SVGTextElement(Document& doc)
DEFINE_NODE_FACTORY(SVGTextElement)
// We override SVGGraphics::animatedLocalTransform() so that the transform-origin
// is not taken into account.
AffineTransform SVGTextElement::animatedLocalTransform() const
{
AffineTransform matrix;
RenderStyle* style = renderer() ? renderer()->style() : 0;
// if CSS property was set, use that, otherwise fallback to attribute (if set)
if (style && style->hasTransform()) {
TransformationMatrix t;
// For now, the transform-origin is not taken into account
// Also, any percentage values will not be taken into account
style->applyTransform(t, IntSize(0, 0), RenderStyle::ExcludeTransformOrigin);
// Flatten any 3D transform
matrix = t.toAffineTransform();
} else {
transform()->currentValue()->concatenate(matrix);
}
const AffineTransform* transform = const_cast<SVGTextElement*>(this)->animateMotionTransform();
if (transform)
return *transform * matrix;
return matrix;
}
RenderObject* SVGTextElement::createRenderer(RenderStyle*)
{
return new RenderSVGText(this);
......
......@@ -31,8 +31,6 @@ class SVGTextElement final : public SVGTextPositioningElement {
public:
DECLARE_NODE_FACTORY(SVGTextElement);
virtual AffineTransform animatedLocalTransform() const override;
private:
explicit SVGTextElement(Document&);
......
......@@ -434,7 +434,7 @@ void SVGUseElement::toClipPath(Path& path)
// FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
SVGLengthContext lengthContext(this);
path.translate(FloatSize(m_x->currentValue()->value(lengthContext), m_y->currentValue()->value(lengthContext)));
path.transform(animatedLocalTransform());
path.transform(calculateAnimatedLocalTransform());
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment