Skip to content
Permalink
Browse files
[LBSE] Transform update handling is unreliable
https://bugs.webkit.org/show_bug.cgi?id=247671

Reviewed by Rob Buis.

If a SVG renderer does not have a transformation and <animateMotion>
adds a non-identity supplementalTransform() no visual effect is observed.
Only when e.g. zooming in/out (-> style invalidation) the animation starts
to be visible.

If e.g. the 'transform' attribute changes SVG*Element::svgAttributeChanged()
needs to notify the renderer to re-evaluate the 'HasSVGTransform' and
'HasTransformRelatedProperty' flags, since the renderer might have gained
or lost a transformation due to the attribute change. Therefore explicitely
call updateHasSVGTransformFlags() instead of either updateFromStyle() or
updateFromElement(). This avoids unnecessary extra work, and will allow us
to handle transformation changes without performing relayouts, soon.

SVGAnimateMotionElement was lacking similar logic to communicate
transformation changes -- the aforementioned flags were out of sync,
and thus only if the element was already transformed one could observe
the animation -- that's fixed now in general.

Revisit all renderers to enforce that updateFromStyle() is only called
from one place (RenderLayerModelObject::styleDidChange) except for one
exception: RenderSVGRoot needs to forward updateFromStyle() calls to
its anonymous child, the RenderSVGViewportContainer. RenderSVGRoot
no longer stores a pointer to the RenderSVGViewportContainer, but instead
grabs it from the render tree hierarchy (firstChild()). This allows to
ink the anonymous RenderSVGViewportContainer to its owning RenderSVGRoot,
simplifying the render tree building (see RenderTreeBuilderSVG).
updateFromElement() is no longer needed for SVG.

Transform change handling is now handled consistenly for CSS transforms,
SVG transforms, SMIL transforms, SVG "generated" / "induced" transforms
such as viewBox, x/y translation for <use> elements, etc. share the same logic.

Covered by existing tests - 25 tests are fixed by this patch in LBSE.

* LayoutTests/platform/mac-ventura-wk2-lbse-text/TestExpectations:
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/custom/missing-xlink-expected.png: Removed.
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/repaint/mask-clip-target-transform-expected.txt:
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/page/zoom-hixie-mixed-008-expected.png:
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/page/zoom-hixie-mixed-009-expected.png:
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/page/zoom-hixie-rendering-model-004-expected.png: Removed.
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/page/zoom-svg-float-border-padding-expected.png:
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/text/zoom-hixie-mixed-008-expected.png: Removed.
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/text/zoom-hixie-rendering-model-004-expected.png: Removed.
* LayoutTests/platform/mac-ventura-wk2-lbse-text/svg/zoom/text/zoom-svg-float-border-padding-expected.png: Removed.
* Source/WebCore/rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::updateHasSVGTransformFlags):
* Source/WebCore/rendering/RenderLayerModelObject.h:
(WebCore::RenderLayerModelObject::needsHasSVGTransformFlags const):
(WebCore::RenderLayerModelObject::updateFromStyle):
* Source/WebCore/rendering/svg/RenderSVGBlock.cpp:
(WebCore::RenderSVGBlock::updateFromStyle):
(WebCore::RenderSVGBlock::needsHasSVGTransformFlags const):
* Source/WebCore/rendering/svg/RenderSVGBlock.h:
* Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp:
(WebCore::RenderSVGForeignObject::updateFromStyle):
* Source/WebCore/rendering/svg/RenderSVGForeignObject.h:
* Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h:
* Source/WebCore/rendering/svg/RenderSVGImage.cpp:
(WebCore::RenderSVGImage::needsHasSVGTransformFlags const):
* Source/WebCore/rendering/svg/RenderSVGImage.h:
* Source/WebCore/rendering/svg/RenderSVGInline.cpp:
(WebCore::RenderSVGInline::needsHasSVGTransformFlags const):
(WebCore::RenderSVGInline::updateFromStyle):
* Source/WebCore/rendering/svg/RenderSVGInline.h:
* Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:
(WebCore::RenderSVGModelObject::updateFromStyle):
* Source/WebCore/rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::viewportContainer const):
(WebCore::RenderSVGRoot::needsHasSVGTransformFlags const):
(WebCore::RenderSVGRoot::updateFromStyle):
(WebCore::RenderSVGRoot::setViewportContainer): Deleted.
(WebCore::RenderSVGRoot::updateFromElement): Deleted.
* Source/WebCore/rendering/svg/RenderSVGRoot.h:
* Source/WebCore/rendering/svg/RenderSVGShape.cpp:
(WebCore::RenderSVGShape::needsHasSVGTransformFlags const):
* Source/WebCore/rendering/svg/RenderSVGShape.h:
* Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp:
(WebCore::RenderSVGTransformableContainer::needsHasSVGTransformFlags const):
(WebCore::RenderSVGTransformableContainer::updateFromStyle): Deleted.
* Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h:
* Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp:
(WebCore::RenderSVGViewportContainer::RenderSVGViewportContainer):
(WebCore::RenderSVGViewportContainer::svgSVGElement const):
(WebCore::RenderSVGViewportContainer::needsHasSVGTransformFlags const):
(WebCore::RenderSVGViewportContainer::updateFromStyle):
(WebCore::RenderSVGViewportContainer::updateFromElement): Deleted.
(WebCore::RenderSVGViewportContainer::needsHasSVGTransformFlag const): Deleted.
* Source/WebCore/rendering/svg/RenderSVGViewportContainer.h:
* Source/WebCore/rendering/updating/RenderTreeBuilderSVG.cpp:
(WebCore::RenderTreeBuilder::SVG::attach):
(WebCore::RenderTreeBuilder::SVG::findOrCreateParentForChild):
* Source/WebCore/svg/SVGAnimateMotionElement.cpp:
(WebCore::SVGAnimateMotionElement::applyResultsToTarget):
* Source/WebCore/svg/SVGGraphicsElement.cpp:
(WebCore::SVGGraphicsElement::svgAttributeChanged):
* Source/WebCore/svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::updateCurrentTranslate):
(WebCore::SVGSVGElement::svgAttributeChanged):
(WebCore::SVGSVGElement::didAttachRenderers): Deleted.
* Source/WebCore/svg/SVGSVGElement.h:

Canonical link: https://commits.webkit.org/256787@main
  • Loading branch information
nikolaszimmermann committed Nov 17, 2022
1 parent e633ef2 commit 6b5b349b0390030413d11288faf13659fd76ec5d
Show file tree
Hide file tree
Showing 35 changed files with 145 additions and 143 deletions.
@@ -195,7 +195,6 @@ svg/as-background-image/background-image-preserveaspectRatio-support.html [ Imag
svg/as-image/img-preserveAspectRatio-support-1.html [ ImageOnlyFailure ]

# getBBox() / getBoundingClientRect() / getCTM() / getScreenCTM() / getIntersectionList / etc. return incorrect results
svg/animations/animate-mpath-insert.html [ Failure ]
svg/animations/fill-remove-support.html [ Failure ]
svg/custom/getBoundingClientRect.xhtml [ Failure ]
svg/custom/getClientRects.xhtml [ Failure ]
@@ -541,9 +540,6 @@ svg/text/select-x-list-with-tspans-3.svg [ Failure ]
svg/text/select-x-list-with-tspans-4.svg [ Failure ]
svg/text/selection-doubleclick.svg [ ImageOnlyFailure ]

# Text rendering placement issues (text renders at wrong location)
svg/carto.net/tabgroup.svg [ ImageOnlyFailure ]

# Transforming inner svg elements has issues
svg/transforms/svgsvgelement-transform.svg [ ImageOnlyFailure ]

@@ -586,33 +582,10 @@ svg/css/mix-blend-mode-background-root.svg [ ImageOnlyFailure ]
svg/css/mix-blend-mode-opacity-root.svg [ ImageOnlyFailure ]

# SMIL animation not correctly updastes (repainting issue only?)
svg/W3C-SVG-1.1/animate-elem-04-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-05-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-06-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-07-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-08-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-09-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-10-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-11-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-12-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-30-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-33-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-77-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-81-t.svg [ ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-82-t.svg [ ImageOnlyFailure ]
svg/animations/animateMotion-additive-1.svg [ ImageOnlyFailure ]
svg/animations/animateMotion-remove-freeze-use.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-by-scale-1.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-by-scale.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-rotate-around-point.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-skewX.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-skewY.svg [ ImageOnlyFailure ]
svg/animations/animateTransform-translate.svg [ ImageOnlyFailure ]
svg/animations/animated-string-href.svg [ ImageOnlyFailure ]
svg/animations/local-url-target-reference.html [ ImageOnlyFailure ]
svg/animations/mozilla/animateMotion-by-1.svg [ ImageOnlyFailure ]
svg/animations/mozilla/animateMotion-from-to-1.svg [ ImageOnlyFailure ]
svg/animations/multiple-animateTransform-additive-sum.svg [ ImageOnlyFailure ]
svg/animations/smil-multiple-animate-list.svg [ ImageOnlyFailure ]
svg/stroke/animated-non-scaling-stroke.html [ ImageOnlyFailure ]

@@ -664,6 +637,12 @@ svg/filters/feImage-target-reappend-to-document.svg [ Pass ImageOnlyFailure ]
# 3) SVG <image> flakiness
svg/as-image/image-preserveAspectRatio-all.svg [ Pass ImageOnlyFailure ]

# 4) Historical flakiness of SMIL animations, we don't pause them in these tests, that should
# finally be fixed to avoid this falkniess, even if it means adapting the SVG testsuite manually.
svg/W3C-SVG-1.1/animate-elem-04-t.svg [ Pass ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-17-t.svg [ Pass ImageOnlyFailure ]
svg/W3C-SVG-1.1/animate-elem-81-t.svg [ Pass ImageOnlyFailure ]

###############
# Crashes #
###############
Binary file not shown.
@@ -6,6 +6,8 @@ layer at (0,0) size 800x600
RenderSVGViewportContainer at (0,0) size 800x600
layer at (50,-50) size 100x100 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
RenderSVGEllipse {circle} at (50,-50) size 100x100 [fill={[type=SOLID] [color=#FF0000]}] [cx=100.00] [cy=0.00] [r=50.00]
layer at (-200,-200) size 400x200 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
RenderSVGTransformableContainer {g} at (-200,-200) size 400x200
layer at (-50,50) size 100x100 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
RenderSVGEllipse {circle} at (-50,50) size 100x100 [fill={[type=SOLID] [color=#FF0000]}] [cx=0.00] [cy=100.00] [r=50.00]
layer at (0,-200) size 200x400 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -432,10 +432,12 @@ void RenderLayerModelObject::applySVGTransform(TransformationMatrix& transform,
style.unapplyTransformOrigin(transform, originTranslate);
}

void RenderLayerModelObject::updateHasSVGTransformFlags(const SVGGraphicsElement& graphicsElement)
void RenderLayerModelObject::updateHasSVGTransformFlags()
{
bool hasSVGTransform = graphicsElement.hasTransformRelatedAttributes();
setHasTransformRelatedProperty(style().hasTransformRelatedProperty() || hasSVGTransform);
ASSERT(document().settings().layerBasedSVGEngineEnabled());

bool hasSVGTransform = needsHasSVGTransformFlags();
setHasTransformRelatedProperty(hasSVGTransform || style().hasTransformRelatedProperty());
setHasSVGTransform(hasSVGTransform);
}
#endif
@@ -49,7 +49,6 @@ class RenderLayerModelObject : public RenderElement {

void styleWillChange(StyleDifference, const RenderStyle& newStyle) override;
void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
virtual void updateFromStyle() { }

virtual bool requiresLayer() const = 0;

@@ -88,7 +87,8 @@ class RenderLayerModelObject : public RenderElement {
void mapLocalToSVGContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const;

void applySVGTransform(TransformationMatrix&, SVGGraphicsElement&, const RenderStyle&, const FloatRect& boundingBox, const std::optional<AffineTransform>& preApplySVGTransformMatrix, const std::optional<AffineTransform>& postApplySVGTransformMatrix, OptionSet<RenderStyle::TransformOperationOption>) const;
void updateHasSVGTransformFlags(const SVGGraphicsElement&);
void updateHasSVGTransformFlags();
virtual bool needsHasSVGTransformFlags() const { ASSERT_NOT_REACHED(); return false; }

LayoutPoint nominalSVGLayoutLocation() const { return flooredLayoutPoint(objectBoundingBoxWithoutTransformations().minXMinYCorner()); }
virtual LayoutPoint currentSVGLayoutLocation() const { ASSERT_NOT_REACHED(); return { }; }
@@ -108,6 +108,12 @@ class RenderLayerModelObject : public RenderElement {
void willBeDestroyed() override;
void willBeRemovedFromTree(IsInternalMove) override;

virtual void updateFromStyle() { }

#if ENABLE(LAYER_BASED_SVG_ENGINE)
void updateHasSVGTransformFlags(bool hasSVGTransform);
#endif

private:
std::unique_ptr<RenderLayer> m_layer;

@@ -46,7 +46,7 @@ void RenderSVGBlock::updateFromStyle()

#if ENABLE(LAYER_BASED_SVG_ENGINE)
if (document().settings().layerBasedSVGEngineEnabled()) {
updateHasSVGTransformFlags(graphicsElement());
updateHasSVGTransformFlags();
return;
}
#endif
@@ -66,6 +66,13 @@ void RenderSVGBlock::updateFromStyle()
setHasNonVisibleOverflow(false);
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
bool RenderSVGBlock::needsHasSVGTransformFlags() const
{
return graphicsElement().hasTransformRelatedAttributes();
}
#endif

void RenderSVGBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
#if ENABLE(LAYER_BASED_SVG_ENGINE)
@@ -36,7 +36,11 @@ class RenderSVGBlock : public RenderBlockFlow {
void willBeDestroyed() override;

void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) override;

void updateFromStyle() override;
#if ENABLE(LAYER_BASED_SVG_ENGINE)
bool needsHasSVGTransformFlags() const override;
#endif

private:
void element() const = delete;
@@ -138,12 +138,6 @@ void RenderSVGForeignObject::updateFromStyle()
{
RenderSVGBlock::updateFromStyle();

// Enforce <fO> to carry a transform: <fO> should behave as absolutely positioned container
// for CSS content. Thus it needs to become a rootPaintingLayer during paint() such that
// fixed position content uses the <fO> as ancestor layer (when computing offsets from the container).
setHasTransformRelatedProperty();
setHasSVGTransform();

if (SVGRenderSupport::isOverflowHidden(*this))
setHasNonVisibleOverflow();
}
@@ -60,7 +60,12 @@ class RenderSVGForeignObject final : public RenderSVGBlock {

LayoutRect overflowClipRect(const LayoutPoint& location, RenderFragmentContainer* = nullptr, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, PaintPhase = PaintPhase::BlockBackground) const final;

void updateFromStyle() override;
void updateFromStyle() final;

// Enforce <fO> to carry a transform: <fO> should behave as absolutely positioned container
// for CSS content. Thus it needs to become a rootPaintingLayer during paint() such that
// fixed position content uses the <fO> as ancestor layer (when computing offsets from the container).
bool needsHasSVGTransformFlags() const final { return true; }

void applyTransform(TransformationMatrix&, const RenderStyle&, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> = RenderStyle::allTransformOperations) const final;

@@ -52,6 +52,8 @@ class RenderSVGHiddenContainer : public RenderSVGContainer {

bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction) final { return false; }
void applyTransform(TransformationMatrix&, const RenderStyle&, const FloatRect&, OptionSet<RenderStyle::TransformOperationOption> = RenderStyle::allTransformOperations) const final { }
void updateFromStyle() final { }
bool needsHasSVGTransformFlags() const final { return false; }
void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
};

@@ -404,6 +404,11 @@ bool RenderSVGImage::bufferForeground(PaintInfo& paintInfo, const LayoutPoint& p
return true;
}

bool RenderSVGImage::needsHasSVGTransformFlags() const
{
return imageElement().hasTransformRelatedAttributes();
}

void RenderSVGImage::applyTransform(TransformationMatrix& transform, const RenderStyle& style, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> options) const
{
applySVGTransform(transform, imageElement(), style, boundingBox, std::nullopt, std::nullopt, options);
@@ -74,6 +74,8 @@ class RenderSVGImage final : public RenderSVGModelObject {
void notifyFinished(CachedResource&, const NetworkLoadMetrics&) final;
bool bufferForeground(PaintInfo&, const LayoutPoint&);

bool needsHasSVGTransformFlags() const final;

void applyTransform(TransformationMatrix&, const RenderStyle&, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> = RenderStyle::allTransformOperations) const final;

CachedImage* cachedImage() const { return imageResource().cachedImage(); }
@@ -22,6 +22,7 @@
#include "config.h"
#include "RenderSVGInline.h"

#include "RenderSVGInlineInlines.h"
#include "RenderSVGInlineText.h"
#include "RenderSVGResource.h"
#include "RenderSVGText.h"
@@ -153,10 +154,22 @@ void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* ol
SVGResourcesCache::clientStyleChanged(*this, diff, oldStyle, style());
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
bool RenderSVGInline::needsHasSVGTransformFlags() const
{
return graphicsElement().hasTransformRelatedAttributes();
}
#endif

void RenderSVGInline::updateFromStyle()
{
RenderInline::updateFromStyle();

#if ENABLE(LAYER_BASED_SVG_ENGINE)
if (document().settings().layerBasedSVGEngineEnabled())
updateHasSVGTransformFlags();
#endif

// SVG text layout code expects us to be an inline-level element.
setInline(true);
}
@@ -54,6 +54,8 @@ class RenderSVGInline : public RenderInline {
#if ENABLE(LAYER_BASED_SVG_ENGINE)
LayoutPoint currentSVGLayoutLocation() const final { return { }; }
void setCurrentSVGLayoutLocation(const LayoutPoint&) final { ASSERT_NOT_REACHED(); }

bool needsHasSVGTransformFlags() const final;
#endif

LayoutRect clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const final;
@@ -65,9 +65,7 @@ RenderSVGModelObject::RenderSVGModelObject(SVGElement& element, RenderStyle&& st
void RenderSVGModelObject::updateFromStyle()
{
RenderLayerModelObject::updateFromStyle();

if (!isAnonymous() && is<SVGGraphicsElement>(element()))
updateHasSVGTransformFlags(downcast<SVGGraphicsElement>(element()));
updateHasSVGTransformFlags();
}

LayoutRect RenderSVGModelObject::overflowClipRect(const LayoutPoint&, RenderFragmentContainer*, OverlayScrollbarSizeRelevancy, PaintPhase) const
@@ -41,6 +41,7 @@
#include "RenderSVGResourceContainer.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGText.h"
#include "RenderSVGViewportContainer.h"
#include "RenderTreeBuilder.h"
#include "RenderView.h"
#include "SVGContainerLayout.h"
@@ -73,10 +74,12 @@ SVGSVGElement& RenderSVGRoot::svgSVGElement() const
return downcast<SVGSVGElement>(nodeForNonAnonymous());
}

void RenderSVGRoot::setViewportContainer(RenderSVGViewportContainer& viewportContainer)
RenderSVGViewportContainer* RenderSVGRoot::viewportContainer() const
{
ASSERT(!m_viewportContainer);
m_viewportContainer = viewportContainer;
auto* child = firstChild();
if (!child || !child->isAnonymous())
return nullptr;
return dynamicDowncast<RenderSVGViewportContainer>(child);
}

void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
@@ -424,35 +427,28 @@ bool RenderSVGRoot::paintingAffectedByExternalOffset() const
return false;
}

void RenderSVGRoot::updateFromElement()
bool RenderSVGRoot::needsHasSVGTransformFlags() const
{
RenderReplaced::updateFromElement();

// Changing SVG zoom / pan properties (or page scale) triggers an updateFromElement() call
// from SVGSVGElement. Forward to the anonymous viewport container, as it is responsible
// to update the layer transform to reflect the new scale/translation.
if (auto* viewportContainer = this->viewportContainer())
viewportContainer->updateFromElement();
// Only mark us as transformed if really needed. Whenver a non-zero paintOffset could reach
// RenderSVGRoot from an ancestor, the pixel snapping logic needs to be applied. Since the rest
// of the SVG subtree doesn't know anything about subpixel offsets, we'll have to stop use/set
// 'adjustedSubpixelOffset' starting at the RenderSVGRoot boundary. This mostly affects inline
// SVG documents and SVGs embedded via <object> / <embed>.
return svgSVGElement().hasTransformRelatedAttributes() || paintingAffectedByExternalOffset();
}

void RenderSVGRoot::updateFromStyle()
{
RenderReplaced::updateFromStyle();
updateHasSVGTransformFlags();

// Additionally update style of the anonymous RenderSVGViewportContainer,
// which handles zoom / pan / viewBox transformations.
if (auto* viewportContainer = this->viewportContainer())
viewportContainer->updateFromStyle();

if (shouldApplyViewportClip())
setHasNonVisibleOverflow();

// Only mark us as transformed if really needed. Whenver a non-zero paintOffset could reach
// RenderSVGRoot from an ancestor, the pixel snapping logic needs to be applied. Since the rest
// of the SVG subtree doesn't know anything about subpixel offsets, we'll have to stop use/set
// 'adjustedSubpixelOffset' starting at the RenderSVGRoot boundary. This mostly affects inline
// SVG documents and SVGs embedded via <object> / <embed>.
if (!hasSVGTransform() && paintingAffectedByExternalOffset()) {
setHasTransformRelatedProperty();
setHasSVGTransform();
}

updateFromElement();
}

void RenderSVGRoot::updateLayerTransform()
@@ -26,13 +26,12 @@
#if ENABLE(LAYER_BASED_SVG_ENGINE)
#include "FloatRect.h"
#include "RenderReplaced.h"
#include "RenderSVGViewportContainer.h"
#include "SVGBoundingBoxComputation.h"

namespace WebCore {

class AffineTransform;
class RenderSVGResourceContainer;
class RenderSVGViewportContainer;
class SVGSVGElement;

class RenderSVGRoot final : public RenderReplaced {
@@ -71,8 +70,7 @@ class RenderSVGRoot final : public RenderReplaced {

LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }

RenderSVGViewportContainer* viewportContainer() const { return m_viewportContainer.get(); }
void setViewportContainer(RenderSVGViewportContainer&);
RenderSVGViewportContainer* viewportContainer() const;

private:
void element() const = delete;
@@ -102,7 +100,7 @@ class RenderSVGRoot final : public RenderReplaced {

void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
void updateFromStyle() final;
void updateFromElement() final;
bool needsHasSVGTransformFlags() const final;
void updateLayerTransform() final;

bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) final;
@@ -127,7 +125,6 @@ class RenderSVGRoot final : public RenderReplaced {
FloatRect m_objectBoundingBoxWithoutTransformations;
FloatRect m_strokeBoundingBox;
HashSet<RenderSVGResourceContainer*> m_resourcesNeedingToInvalidateClients;
WeakPtr<RenderSVGViewportContainer> m_viewportContainer;
};

} // namespace WebCore
@@ -527,6 +527,11 @@ void RenderSVGShape::styleWillChange(StyleDifference diff, const RenderStyle& ne
RenderSVGModelObject::styleWillChange(diff, newStyle);
}

bool RenderSVGShape::needsHasSVGTransformFlags() const
{
return graphicsElement().hasTransformRelatedAttributes();
}

void RenderSVGShape::applyTransform(TransformationMatrix& transform, const RenderStyle& style, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> options) const
{
applySVGTransform(transform, graphicsElement(), style, boundingBox, std::nullopt, std::nullopt, options);
@@ -81,6 +81,8 @@ class RenderSVGShape : public RenderSVGModelObject {

FloatRect computeMarkerBoundingBox(const SVGBoundingBoxComputation::DecorationOptions&) const;

bool needsHasSVGTransformFlags() const final;

void applyTransform(TransformationMatrix&, const RenderStyle&, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> = RenderStyle::allTransformOperations) const final;

protected:

0 comments on commit 6b5b349

Please sign in to comment.