Code: bool LayoutSVGViewportContainer::calculateLocalTransform()
 {
     if (!m_needsTransformUpdate)
        return false;
 
     m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
     m_needsTransformUpdate = false;
    return true;
 }

Commit Message: Avoid using forced layout to trigger paint invalidation for SVG containers

Currently, SVG containers in the LayoutObject hierarchy force layout of
their children if the transform changes. The main reason for this is to
trigger paint invalidation of the subtree. In some cases - changes to the
scale factor - there are other reasons to trigger layout, like computing
a new scale factor for <text> or re-layout nodes with non-scaling stroke.

Compute a "scale-factor change" in addition to the "transform change"
already computed, then use this new signal to determine if layout should
be forced for the subtree. Trigger paint invalidation using the
LayoutObject flags instead.

The downside to this is that paint invalidation will walk into "hidden"
containers which rarely require repaint (since they are not technically
visible). This will hopefully be rectified in a follow-up CL.

For the testcase from 603850, this essentially eliminates the cost of
layout (from ~350ms to ~0ms on authors machine; layout cost is related
to text metrics recalculation), bumping frame rate significantly.

BUG=603956,603850

Review-Url: https://codereview.chromium.org/1996543002
Cr-Commit-Position: refs/heads/master@{#400950}
CWE ID: 
bool LayoutSVGViewportContainer::calculateLocalTransform()
void LayoutSVGViewportContainer::setNeedsTransformUpdate()
{
    setMayNeedPaintInvalidationSubtree();
    m_needsTransformUpdate = true;
}

static std::pair<double, double> scaleReference(const AffineTransform& transform)
{
    return std::make_pair(transform.xScaleSquared(), transform.yScaleSquared());
}

LayoutSVGContainer::TransformChange LayoutSVGViewportContainer::calculateLocalTransform()
 {
     if (!m_needsTransformUpdate)
        return TransformChange::None;
 
    std::pair<double, double> oldScale = scaleReference(m_localToParentTransform);
     m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
     m_needsTransformUpdate = false;
    return scaleReference(m_localToParentTransform) != oldScale
        ? TransformChange::Full : TransformChange::ScaleInvariant;
 }
