Diff
Modified: trunk/Source/WebCore/ChangeLog (293503 => 293504)
--- trunk/Source/WebCore/ChangeLog 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/ChangeLog 2022-04-27 11:14:44 UTC (rev 293504)
@@ -1,3 +1,101 @@
+2022-04-27 Nikolas Zimmermann <nzimmerm...@igalia.com>
+
+ [LBSE] Fix origin of transformations in SVG
+ https://bugs.webkit.org/show_bug.cgi?id=239717
+
+ Reviewed by Rob Buis.
+
+ Fix the majority of SVG transform issues in LBSE. webkit.org/b/237711 laid the groundwork for SVG
+ transforms in LBSE, however there are still issues:
+
+ - SVG transforms specified alone on SVG elements, w/o any additional style/perspective related property
+ such as transform-box / transform-origin / ... do not trigger layer creation, fix by adapting StyleAdjuster.
+
+ - Switching on/off transforms for a SVG element, was not tracking updates to both 'HasSVGTransform' and
+ 'HasTransformRelatedProperty' flags correctly, fix that by introducing an 'updateHasSVGTransformFlags' helper.
+
+ - Modify SVGContainerLayout to avoid a dependency on the children transformations when computing container
+ boundaries. In the legacy engine, we always have to mark the whole ancestor chain as 'need to recompute boundaries'
+ and invoking a re-layout, to perform the recomputation. This change avoids the invalidation of the whole ancestor
+ chain, when an elements transform changes in a non-accelerated way (e.g. SVGTransformList manipulation, SMIL
+ <animateTransform> / <animate> / <set>). In CSS transformations do not affect layout, only hit-testing and painting.
+
+ -> SVG/CSS transforms applied on SVG elements is conceptually equivalent to CSS transformations on CSS boxes now.
+ Transformation changes no longer affect the 'internal geometry' (objectBoundingBoxWithoutTransformations()).
+ currentSVGLayoutLocation() / nominalSVGLayoutLocation() are computed using the 'internal geometry' and used
+ throughout layout.
+
+ This avoids most of the RenderLayer / RenderLayerBacking specific changes that were present in the downstream
+ LBSE implementation, while also solving an important design issue: no back-splash from children to parents.
+ Large, deep nested documents -- as seen in the wild -- will benefit the most, avoiding the frequent ancestor
+ walks to mark the containing block / parent hierachy for re-layout.
+
+ Covered by existing tests, no change in behaviour. (However testability for LBSE is ready soon!).
+
+ * rendering/RenderElement.cpp:
+ (WebCore::RenderElement::referenceBoxRect const):
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::RenderLayer):
+ (WebCore::canCreateStackingContext):
+ (WebCore::RenderLayer::paintLayerByApplyingTransform):
+ * rendering/RenderLayer.h:
+ (WebCore::RenderLayer::rendererLocation const):
+ * rendering/RenderLayerModelObject.cpp:
+ (WebCore::RenderLayerModelObject::styleDidChange):
+ (WebCore::RenderLayerModelObject::computeVisibleRectInSVGContainer const):
+ (WebCore::RenderLayerModelObject::updateHasSVGTransformFlags):
+ * rendering/RenderLayerModelObject.h:
+ (WebCore::RenderLayerModelObject::nominalSVGLayoutLocation const):
+ (WebCore::RenderLayerModelObject::currentSVGLayoutLocation const):
+ (WebCore::RenderLayerModelObject::setCurrentSVGLayoutLocation):
+ * rendering/RenderObject.h:
+ (WebCore::RenderObject::objectBoundingBoxWithoutTransformations const):
+ * rendering/svg/RenderSVGBlock.h:
+ * rendering/svg/RenderSVGContainer.cpp:
+ (WebCore::RenderSVGContainer::layoutChildren):
+ (WebCore::RenderSVGContainer::paint):
+ (WebCore::RenderSVGContainer::nodeAtPoint):
+ (WebCore::RenderSVGContainer::styleDidChange): Deleted.
+ * rendering/svg/RenderSVGContainer.h:
+ * rendering/svg/RenderSVGInline.h:
+ * rendering/svg/RenderSVGModelObject.cpp:
+ (WebCore::RenderSVGModelObject::updateFromStyle):
+ (WebCore::RenderSVGModelObject::absoluteRects const):
+ * rendering/svg/RenderSVGModelObject.h:
+ (WebCore::RenderSVGModelObject::currentSVGLayoutRect const):
+ (WebCore::RenderSVGModelObject::setCurrentSVGLayoutRect):
+ (WebCore::RenderSVGModelObject::frameRectEquivalent const):
+ (WebCore::RenderSVGModelObject::applyTopLeftLocationOffsetEquivalent const):
+ (WebCore::RenderSVGModelObject::layoutRect const): Deleted.
+ (WebCore::RenderSVGModelObject::setLayoutRect): Deleted.
+ (WebCore::RenderSVGModelObject::setLayoutLocation): Deleted.
+ (WebCore::RenderSVGModelObject::paintingLocation const): Deleted.
+ (WebCore::RenderSVGModelObject::layoutLocation const): Deleted.
+ (WebCore::RenderSVGModelObject::layoutLocationOffset const): Deleted.
+ (WebCore::RenderSVGModelObject::layoutSize const): Deleted.
+ * rendering/svg/RenderSVGRoot.cpp:
+ (WebCore::RenderSVGRoot::layout):
+ (WebCore::RenderSVGRoot::updateFromStyle):
+ * rendering/svg/RenderSVGRoot.h:
+ * rendering/svg/RenderSVGShape.cpp:
+ (WebCore::RenderSVGShape::layout):
+ (WebCore::RenderSVGShape::paint):
+ (WebCore::RenderSVGShape::nodeAtPoint):
+ * rendering/svg/RenderSVGTransformableContainer.cpp:
+ (WebCore::RenderSVGTransformableContainer::updateFromStyle):
+ * rendering/svg/SVGBoundingBoxComputation.cpp:
+ (WebCore::SVGBoundingBoxComputation::handleRootOrContainer const):
+ * rendering/svg/SVGBoundingBoxComputation.h:
+ (WebCore::SVGBoundingBoxComputation::computeVisualOverflowRect):
+ * rendering/svg/SVGContainerLayout.cpp:
+ (WebCore::SVGContainerLayout::positionChildrenRelativeToContainer):
+ (WebCore::SVGContainerLayout::verifyLayoutLocationConsistency):
+ (WebCore::layoutLocationFromRenderer): Deleted.
+ (WebCore::setLayoutLocationForRenderer): Deleted.
+ * rendering/svg/SVGContainerLayout.h:
+ * style/StyleAdjuster.cpp:
+ (WebCore::Style::Adjuster::adjust const):
+
2022-04-27 Youenn Fablet <you...@apple.com>
<link rel=preconnect> always sends credentials to different-origin, ignoring crossorigin=anonymous
Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderElement.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -2418,21 +2418,43 @@
if (!is<SVGElement>(element()))
return { };
+ auto alignReferenceBox = [&](FloatRect referenceBox) {
+ // The CSS borderBoxRect() is defined to start at an origin of (0, 0).
+ // A possible shift of a CSS box (e.g. due to non-static position + top/left properties)
+ // does not effect the borderBoxRect() location. The location information
+ // is propagated upon paint time, e.g. via 'paintOffset' when calling RenderObject::paint(),
+ // or by altering the RenderLayer TransformationMatrix to include the 'offsetFromAncestor'
+ // right in the transformation matrix, when CSS transformations are present (see RenderLayer
+ // paintLayerByApplyingTransform() for details).
+ //
+ // To mimic the expectation for SVG, 'fill-box' must behave the same: if we'd include
+ // the 'referenceBox' location in the returned rect, we'd apply the (x, y) location
+ // information for the SVG renderer twice. We would shift the 'transform-origin' by (x, y)
+ // and at the same time alter the CTM in RenderLayer::paintLayerByApplyingTransform() by
+ // including a translation to the enclosing transformed ancestor ('offsetFromAncestor').
+ // Avoid that, and move by -nominalSVGLayoutLocation().
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (isSVGLayerAwareRenderer() && !isSVGRoot() && document().settings().layerBasedSVGEngineEnabled())
+ referenceBox.moveBy(-downcast<RenderLayerModelObject>(*this).nominalSVGLayoutLocation());
+#endif
+ return referenceBox;
+ };
+
switch (boxType) {
case CSSBoxType::BoxMissing:
case CSSBoxType::ContentBox:
case CSSBoxType::PaddingBox:
case CSSBoxType::FillBox:
- return objectBoundingBox();
+ return alignReferenceBox(objectBoundingBox());
case CSSBoxType::BorderBox:
case CSSBoxType::MarginBox:
case CSSBoxType::StrokeBox:
- return strokeBoundingBox();
+ return alignReferenceBox(strokeBoundingBox());
case CSSBoxType::ViewBox:
// FIXME: [LBSE] Upstream: Cache the immutable SVGLengthContext per SVGElement, to avoid the repeated RenderSVGRoot size queries in determineViewport().
FloatSize viewportSize;
SVGLengthContext(downcast<SVGElement>(element())).determineViewport(viewportSize);
- return { { }, viewportSize };
+ return alignReferenceBox({ { }, viewportSize });
}
ASSERT_NOT_REACHED();
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -302,9 +302,9 @@
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(RenderLayer);
-RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
- : m_isRenderViewLayer(rendererLayerModelObject.isRenderView())
- , m_forcedStackingContext(rendererLayerModelObject.isMedia())
+RenderLayer::RenderLayer(RenderLayerModelObject& renderer)
+ : m_isRenderViewLayer(renderer.isRenderView())
+ , m_forcedStackingContext(renderer.isMedia())
, m_isNormalFlowOnly(false)
, m_isCSSStackingContext(false)
, m_isOpportunisticStackingContext(false)
@@ -343,7 +343,7 @@
, m_hasNotIsolatedBlendingDescendantsStatusDirty(false)
#endif
, m_repaintRectsValid(false)
- , m_renderer(rendererLayerModelObject)
+ , m_renderer(renderer)
{
setIsNormalFlowOnly(shouldBeNormalFlowOnly());
setIsCSSStackingContext(shouldBeCSSStackingContext());
@@ -353,9 +353,9 @@
if (isRenderViewLayer())
m_boxScrollingScope = m_contentsScrollingScope = nextScrollingScope();
- if (!renderer().firstChild()) {
+ if (!renderer.firstChild()) {
m_visibleContentStatusDirty = false;
- m_hasVisibleContent = renderer().style().visibility() == Visibility::Visible;
+ m_hasVisibleContent = renderer.style().visibility() == Visibility::Visible;
}
}
@@ -552,9 +552,6 @@
{
auto& renderer = layer.renderer();
return renderer.hasTransformRelatedProperty()
-#if ENABLE(LAYER_BASED_SVG_ENGINE)
- || renderer.hasSVGTransform()
-#endif
|| renderer.hasClipPath()
|| renderer.hasFilter()
|| renderer.hasMask()
@@ -3545,8 +3542,18 @@
void RenderLayer::paintLayerByApplyingTransform(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags, const LayoutSize& translationOffset)
{
+ auto usesSVGSubtreeTransformRules = [](const RenderLayerModelObject& renderer) {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ return renderer.document().settings().layerBasedSVGEngineEnabled() && renderer.isSVGLayerAwareRenderer() && !renderer.isSVGRoot();
+#else
+ UNUSED_PARAM(renderer);
+#endif
+ return false;
+ };
+
// This involves subtracting out the position of the layer in our current coordinate space, but preserving
// the accumulated error for sub-pixel layout.
+ // Note: The pixel-snapping logic is disabled for the whole SVG render tree, except the outermost <svg>.
float deviceScaleFactor = renderer().document().deviceScaleFactor();
LayoutSize offsetFromParent = offsetFromAncestor(paintingInfo.rootLayer);
offsetFromParent += translationOffset;
@@ -3553,11 +3560,11 @@
TransformationMatrix transform(renderableTransform(paintingInfo.paintBehavior));
// Add the subpixel accumulation to the current layer's offset so that we can always snap the translateRight value to where the renderer() is supposed to be painting.
LayoutSize offsetForThisLayer = offsetFromParent + paintingInfo.subpixelOffset;
- FloatSize devicePixelSnappedOffsetForThisLayer = toFloatSize(roundPointToDevicePixels(toLayoutPoint(offsetForThisLayer), deviceScaleFactor));
+ FloatSize alignedOffsetForThisLayer = usesSVGSubtreeTransformRules(renderer()) ? offsetForThisLayer : toFloatSize(roundPointToDevicePixels(toLayoutPoint(offsetForThisLayer), deviceScaleFactor));
// We handle accumulated subpixels through nested layers here. Since the context gets translated to device pixels,
// all we need to do is add the delta to the accumulated pixels coming from ancestor layers.
// Translate the graphics context to the snapping position to avoid off-device-pixel positing.
- transform.translateRight(devicePixelSnappedOffsetForThisLayer.width(), devicePixelSnappedOffsetForThisLayer.height());
+ transform.translateRight(alignedOffsetForThisLayer.width(), alignedOffsetForThisLayer.height());
// Apply the transform.
auto oldTransform = context.getCTM();
auto affineTransform = transform.toAffineTransform();
@@ -3567,7 +3574,10 @@
paintingInfo.eventRegionContext->pushTransform(affineTransform);
// Now do a paint with the root layer shifted to be us.
- LayoutSize adjustedSubpixelOffset = offsetForThisLayer - LayoutSize(devicePixelSnappedOffsetForThisLayer);
+ LayoutSize adjustedSubpixelOffset;
+ if (!usesSVGSubtreeTransformRules(renderer()) && !renderer().isSVGRoot())
+ adjustedSubpixelOffset = offsetForThisLayer - LayoutSize(alignedOffsetForThisLayer);
+
LayerPaintingInfo transformedPaintingInfo(paintingInfo);
transformedPaintingInfo.rootLayer = this;
transformedPaintingInfo.paintDirtyRect = LayoutRect(encloseRectToDevicePixels(valueOrDefault(transform.inverse()).mapRect(paintingInfo.paintDirtyRect), deviceScaleFactor));
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -984,7 +984,7 @@
return downcast<RenderBox>(renderer()).location();
#if ENABLE(LAYER_BASED_SVG_ENGINE)
if (is<RenderSVGModelObject>(renderer()))
- return downcast<RenderSVGModelObject>(renderer()).layoutLocation();
+ return downcast<RenderSVGModelObject>(renderer()).currentSVGLayoutLocation();
#endif
return LayoutPoint();
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -129,6 +129,9 @@
layer()->willRemoveChildWithBlendMode();
#endif
setHasTransformRelatedProperty(false); // All transform-related properties force layers, so we know we don't have one or the object doesn't support them.
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ setHasSVGTransform(false); // Same reason as for setHasTransformRelatedProperty().
+#endif
setHasReflection(false);
// Repaint the about to be destroyed self-painting layer when style change also triggers repaint.
@@ -275,7 +278,7 @@
*/
if (moveToOrigin)
- adjustedRect.moveBy(flooredLayoutPoint(objectBoundingBox().minXMinYCorner()));
+ adjustedRect.moveBy(nominalSVGLayoutLocation());
if (auto* transform = layer()->transform())
adjustedRect = transform->mapRect(adjustedRect);
@@ -356,6 +359,13 @@
style.unapplyTransformOrigin(transform, originTranslate);
}
+
+void RenderLayerModelObject::updateHasSVGTransformFlags(const SVGGraphicsElement& graphicsElement)
+{
+ bool hasSVGTransform = !graphicsElement.animatedLocalTransform().isIdentity();
+ setHasTransformRelatedProperty(style().hasTransformRelatedProperty() || hasSVGTransform);
+ setHasSVGTransform(hasSVGTransform);
+}
#endif
bool rendererNeedsPixelSnapping(const RenderLayerModelObject& renderer)
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -78,6 +78,11 @@
void mapLocalToSVGContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const;
void applySVGTransform(TransformationMatrix&, SVGGraphicsElement&, const RenderStyle&, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption>) const;
+ void updateHasSVGTransformFlags(const SVGGraphicsElement&);
+
+ LayoutPoint nominalSVGLayoutLocation() const { return flooredLayoutPoint(objectBoundingBoxWithoutTransformations().minXMinYCorner()); }
+ virtual LayoutPoint currentSVGLayoutLocation() const { ASSERT_NOT_REACHED(); return { }; }
+ virtual void setCurrentSVGLayoutLocation(const LayoutPoint&) { ASSERT_NOT_REACHED(); }
#endif
void updateLayerTransform();
Modified: trunk/Source/WebCore/rendering/RenderObject.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/RenderObject.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/RenderObject.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -367,6 +367,19 @@
virtual FloatRect objectBoundingBox() const;
virtual FloatRect strokeBoundingBox() const;
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ // The objectBoundingBox of a SVG container is affected by the transformations applied on its children -- the container
+ // bounding box is a union of all child bounding boxes, mapped through their transformation matrices.
+ //
+ // This method ignores all transformations and computes the objectBoundingBox, without mapping through the child
+ // transformation matrices. The SVG render tree is constructed in such a way, that it can be mapped to CSS equivalents:
+ // The SVG render tree underneath the outermost <svg> behaves as a set of absolutely positioned, possibly nested, boxes.
+ // They are laid out in such a way that transformations do NOT affect layout, as in HTML/CSS world, but take affect during
+ // painting, hit-testing etc. This allows to minimize the amount of re-layouts when animating transformations in SVG
+ // (not using CSS Animations/Transitions / Web Animations, but e.g. SMIL <animateTransform>, JS, ...).
+ virtual FloatRect objectBoundingBoxWithoutTransformations() const { return objectBoundingBox(); }
+#endif
+
// Returns the smallest rectangle enclosing all of the painted content
// respecting clipping, masking, filters, opacity, stroke-width and markers
virtual FloatRect repaintRectInLocalCoordinates() const;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -48,6 +48,11 @@
void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ LayoutPoint currentSVGLayoutLocation() const final { return location(); }
+ void setCurrentSVGLayoutLocation(const LayoutPoint& location) final { setLocation(location); }
+#endif
+
LayoutRect clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const final;
std::optional<FloatRect> computeFloatVisibleRectInContainer(const FloatRect&, const RenderLayerModelObject* container, VisibleRectContext) const final;
std::optional<LayoutRect> computeVisibleRectInContainer(const LayoutRect&, const RenderLayerModelObject* container, VisibleRectContext) const final;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -119,21 +119,16 @@
SVGBoundingBoxComputation boundingBoxComputation(*this);
m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration, &m_objectBoundingBoxValid);
+
+ constexpr auto objectBoundingBoxDecorationWithoutTransformations = SVGBoundingBoxComputation::objectBoundingBoxDecoration | SVGBoundingBoxComputation::DecorationOption::IgnoreTransformations;
+ m_objectBoundingBoxWithoutTransformations = boundingBoxComputation.computeDecoratedBoundingBox(objectBoundingBoxDecorationWithoutTransformations);
+
m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
- setLayoutRect(enclosingLayoutRect(m_objectBoundingBox));
+ setCurrentSVGLayoutRect(enclosingLayoutRect(m_objectBoundingBoxWithoutTransformations));
containerLayout.positionChildrenRelativeToContainer();
}
-void RenderSVGContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderSVGModelObject::styleDidChange(diff, oldStyle);
-
- // FIXME: [LBSE] Upstream RenderLayer changes
- // if (hasLayer())
- // layer()->setIsOpportunisticStackingContext(true);
-}
-
bool RenderSVGContainer::selfWillPaint()
{
auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
@@ -165,7 +160,7 @@
return;
}
- auto adjustedPaintOffset = paintOffset + layoutLocation();
+ auto adjustedPaintOffset = paintOffset + currentSVGLayoutLocation();
if (paintInfo.phase == PaintPhase::Mask) {
// FIXME: [LBSE] Upstream SVGRenderSupport changes
// SVGRenderSupport::paintSVGMask(*this, paintInfo, adjustedPaintOffset);
@@ -185,7 +180,7 @@
bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- auto adjustedLocation = accumulatedOffset + layoutLocation();
+ auto adjustedLocation = accumulatedOffset + currentSVGLayoutLocation();
auto visualOverflowRect = visualOverflowRectEquivalent();
visualOverflowRect.moveBy(adjustedLocation);
@@ -193,8 +188,7 @@
return false;
auto localPoint = locationInContainer.point();
- auto boundingBoxTopLeftCorner = flooredLayoutPoint(objectBoundingBox().minXMinYCorner());
- auto coordinateSystemOriginTranslation = boundingBoxTopLeftCorner - adjustedLocation;
+ auto coordinateSystemOriginTranslation = nominalSVGLayoutLocation() - adjustedLocation;
localPoint.move(coordinateSystemOriginTranslation);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGContainer.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -40,6 +40,7 @@
bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
+ FloatRect objectBoundingBoxWithoutTransformations() const final { return m_objectBoundingBoxWithoutTransformations; }
FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
@@ -49,8 +50,6 @@
ASCIILiteral renderName() const override { return "RenderSVGContainer"_s; }
bool canHaveChildren() const final { return true; }
- void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
-
void layout() override;
virtual void layoutChildren();
bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
@@ -62,6 +61,7 @@
bool m_objectBoundingBoxValid { false };
FloatRect m_objectBoundingBox;
+ FloatRect m_objectBoundingBoxWithoutTransformations;
FloatRect m_strokeBoundingBox;
private:
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGInline.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGInline.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGInline.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -51,6 +51,11 @@
FloatRect strokeBoundingBox() const final;
FloatRect repaintRectInLocalCoordinates() const final;
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ LayoutPoint currentSVGLayoutLocation() const final { return { }; }
+ void setCurrentSVGLayoutLocation(const LayoutPoint&) final { ASSERT_NOT_REACHED(); }
+#endif
+
LayoutRect clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const final;
std::optional<FloatRect> computeFloatVisibleRectInContainer(const FloatRect&, const RenderLayerModelObject* container, VisibleRectContext) const final;
void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const final;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -61,12 +61,8 @@
{
RenderLayerModelObject::updateFromStyle();
- bool hasSVGTransform = false;
if (is<SVGGraphicsElement>(element()))
- hasSVGTransform = !downcast<SVGGraphicsElement>(element()).animatedLocalTransform().isIdentity();
-
- setHasTransformRelatedProperty(style().hasTransformRelatedProperty() || hasSVGTransform);
- setHasSVGTransform(hasSVGTransform);
+ updateHasSVGTransformFlags(downcast<SVGGraphicsElement>(element()));
}
FloatRect RenderSVGModelObject::borderBoxRectInFragmentEquivalent(RenderFragmentContainer*, RenderBox::RenderBoxFragmentInfoFlags) const
@@ -141,7 +137,7 @@
void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
- rects.append(snappedIntRect(LayoutRect(accumulatedOffset + layoutLocation(), layoutSize())));
+ rects.append(snappedIntRect(LayoutRect(accumulatedOffset + m_layoutRect.location(), m_layoutRect.size())));
}
void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGModelObject.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -58,26 +58,21 @@
inline SVGElement& element() const;
+ LayoutRect currentSVGLayoutRect() const { return m_layoutRect; }
+ void setCurrentSVGLayoutRect(const LayoutRect& layoutRect) { m_layoutRect = layoutRect; }
+
+ LayoutPoint currentSVGLayoutLocation() const final { return m_layoutRect.location(); }
+ void setCurrentSVGLayoutLocation(const LayoutPoint& location) final { m_layoutRect.setLocation(location); }
+
// Mimic the RenderBox accessors - by sharing the same terminology the painting / hit testing / layout logic is
// similar to read compared to non-SVG renderers such as RenderBox & friends.
LayoutRect borderBoxRectEquivalent() const { return { LayoutPoint(), m_layoutRect.size() }; }
LayoutRect contentBoxRectEquivalent() const { return borderBoxRectEquivalent(); }
LayoutRect frameRectEquivalent() const { return m_layoutRect; }
-
LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }
- void applyTopLeftLocationOffsetEquivalent(LayoutPoint& point) const { point.moveBy(layoutLocation()); }
-
- LayoutRect layoutRect() const { return m_layoutRect; }
- void setLayoutRect(const LayoutRect& layoutRect) { m_layoutRect = layoutRect; }
- void setLayoutLocation(const LayoutPoint& layoutLocation) { m_layoutRect.setLocation(layoutLocation); }
-
- LayoutPoint paintingLocation() const { return toLayoutPoint(layoutLocation() - flooredLayoutPoint(objectBoundingBox().minXMinYCorner())); }
- LayoutPoint layoutLocation() const { return m_layoutRect.location(); }
- LayoutSize layoutLocationOffset() const { return toLayoutSize(m_layoutRect.location()); }
- LayoutSize layoutSize() const { return m_layoutRect.size(); }
-
// For RenderLayer only
+ void applyTopLeftLocationOffsetEquivalent(LayoutPoint& point) const { point.moveBy(currentSVGLayoutLocation()); }
FloatRect borderBoxRectInFragmentEquivalent(RenderFragmentContainer*, RenderBox::RenderBoxFragmentInfoFlags = RenderBox::CacheRenderBoxFragmentInfo) const;
virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderFragmentContainer* = nullptr, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, PaintPhase = PaintPhase::BlockBackground) const;
LayoutRect overflowClipRectForChildLayers(const LayoutPoint& location, RenderFragmentContainer* fragment, OverlayScrollbarSizeRelevancy relevancy) { return overflowClipRect(location, fragment, relevancy); }
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -196,6 +196,10 @@
SVGBoundingBoxComputation boundingBoxComputation(*this);
m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration);
+
+ constexpr auto objectBoundingBoxDecorationWithoutTransformations = SVGBoundingBoxComputation::objectBoundingBoxDecoration | SVGBoundingBoxComputation::DecorationOption::IgnoreTransformations;
+ m_objectBoundingBoxWithoutTransformations = boundingBoxComputation.computeDecoratedBoundingBox(objectBoundingBoxDecorationWithoutTransformations);
+
m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration);
}
@@ -397,6 +401,7 @@
RenderReplaced::updateFromStyle();
setHasSVGTransform();
+ setHasTransformRelatedProperty();
if (shouldApplyViewportClip())
setHasNonVisibleOverflow();
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -67,6 +67,7 @@
bool shouldApplyViewportClip() const;
FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
+ FloatRect objectBoundingBoxWithoutTransformations() const final { return m_objectBoundingBoxWithoutTransformations; }
FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
@@ -123,6 +124,7 @@
IntSize m_containerSize;
FloatRect m_objectBoundingBox;
+ FloatRect m_objectBoundingBoxWithoutTransformations;
FloatRect m_strokeBoundingBox;
AffineTransform m_viewBoxTransform;
AffineTransform m_supplementalLocalToParentTransform;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -151,7 +151,7 @@
updateShapeFromElement();
m_needsShapeUpdate = false;
- setLayoutRect(enclosingLayoutRect(m_fillBoundingBox));
+ setCurrentSVGLayoutRect(enclosingLayoutRect(m_fillBoundingBox));
}
updateLayerTransform();
@@ -288,7 +288,7 @@
return;
}
- auto adjustedPaintOffset = paintOffset + layoutLocation();
+ auto adjustedPaintOffset = paintOffset + currentSVGLayoutLocation();
if (paintInfo.phase == PaintPhase::Mask) {
// FIXME: [LBSE] Upstream SVGRenderSupport changes
// SVGRenderSupport::paintSVGMask(*this, paintInfo, adjustedPaintOffset);
@@ -308,7 +308,7 @@
GraphicsContextStateSaver stateSaver(paintInfo.context());
- auto coordinateSystemOriginTranslation = adjustedPaintOffset - flooredLayoutPoint(objectBoundingBox().location());
+ auto coordinateSystemOriginTranslation = adjustedPaintOffset - nominalSVGLayoutLocation();
paintInfo.context().translate(coordinateSystemOriginTranslation.width(), coordinateSystemOriginTranslation.height());
if (style().svgStyle().shapeRendering() == ShapeRendering::CrispEdges)
@@ -345,11 +345,10 @@
if (hitTestAction != HitTestForeground)
return false;
- auto adjustedLocation = accumulatedOffset + layoutLocation();
+ auto adjustedLocation = accumulatedOffset + currentSVGLayoutLocation();
auto localPoint = locationInContainer.point();
- auto boundingBoxTopLeftCorner = flooredLayoutPoint(objectBoundingBox().minXMinYCorner());
- auto coordinateSystemOriginTranslation = boundingBoxTopLeftCorner - adjustedLocation;
+ auto coordinateSystemOriginTranslation = nominalSVGLayoutLocation() - adjustedLocation;
localPoint.move(coordinateSystemOriginTranslation);
if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -97,8 +97,10 @@
{
RenderSVGContainer::updateFromStyle();
- if (associatedUseElement(graphicsElement()))
+ if (associatedUseElement(graphicsElement())) {
setHasSVGTransform();
+ setHasTransformRelatedProperty();
+ }
}
void RenderSVGTransformableContainer::applyTransform(TransformationMatrix& transform, const RenderStyle& style, const FloatRect& boundingBox, OptionSet<RenderStyle::TransformOperationOption> options) const
Modified: trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -175,8 +175,10 @@
if (options.contains(DecorationOption::OverrideBoxWithFilterBoxForChildren) && is<RenderSVGContainer>(child))
childBoundingBoxComputation.adjustBoxForClippingAndEffects({ DecorationOption::OverrideBoxWithFilterBox }, childBox);
- if (auto layerTransform = transformationMatrixFromChild(child))
- childBox = layerTransform->mapRect(childBox);
+ if (!options.contains(DecorationOption::IgnoreTransformations)) {
+ if (auto layerTransform = transformationMatrixFromChild(child))
+ childBox = layerTransform->mapRect(childBox);
+ }
if (options == objectBoundingBoxDecoration)
uniteBoundingBoxRespectingValidity(boxValid, box, child, childBox);
Modified: trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Igalia S.L.
+ * Copyright (C) 2021, 2022 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -35,7 +35,7 @@
explicit SVGBoundingBoxComputation(const RenderLayerModelObject&);
~SVGBoundingBoxComputation() = default;
- enum class DecorationOption : uint8_t {
+ enum class DecorationOption : uint16_t {
IncludeFillShape = 1 << 0, /* corresponds to 'bool fill' */
IncludeStrokeShape = 1 << 1, /* corresponds to 'bool stroke' */
IncludeMarkers = 1 << 2, /* corresponds to 'bool markers' */
@@ -42,8 +42,9 @@
IncludeClippers = 1 << 3, /* corresponds to 'bool clippers' */
IncludeMaskers = 1 << 4, /* WebKit extension - internal */
IncludeOutline = 1 << 5, /* WebKit extension - internal */
- OverrideBoxWithFilterBox = 1 << 6, /* WebKit extension - internal */
- OverrideBoxWithFilterBoxForChildren = 1 << 7 /* WebKit extension - internal */
+ IgnoreTransformations = 1 << 6, /* WebKit extension - internal */
+ OverrideBoxWithFilterBox = 1 << 7, /* WebKit extension - internal */
+ OverrideBoxWithFilterBoxForChildren = 1 << 8 /* WebKit extension - internal */
};
using DecorationOptions = OptionSet<DecorationOption>;
@@ -73,7 +74,7 @@
return LayoutRect();
auto visualOverflowRect = enclosingLayoutRect(repaintBoundingBox);
- visualOverflowRect.moveBy(-flooredLayoutPoint(renderer.objectBoundingBox().minXMinYCorner()));
+ visualOverflowRect.moveBy(-renderer.nominalSVGLayoutLocation());
return visualOverflowRect;
}
Modified: trunk/Source/WebCore/rendering/svg/SVGContainerLayout.cpp (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/SVGContainerLayout.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/SVGContainerLayout.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -120,41 +120,6 @@
ASSERT(elementsThatDidNotReceiveLayout.isEmpty());
}
-static inline LayoutPoint layoutLocationFromRenderer(const RenderObject& renderer)
-{
- if (is<RenderSVGModelObject>(renderer))
- return downcast<RenderSVGModelObject>(renderer).layoutLocation();
-
- if (is<RenderSVGBlock>(renderer)) // <foreignObject> / <text>
- return downcast<RenderSVGBlock>(renderer).location();
-
- if (is<RenderSVGInline>(renderer)) // <tspan> / <textPath>
- return { };
-
- ASSERT_NOT_REACHED();
- return { };
-}
-
-static inline void setLayoutLocationForRenderer(RenderObject& renderer, const LayoutPoint& newLocation)
-{
- if (is<RenderSVGModelObject>(renderer)) {
- downcast<RenderSVGModelObject>(renderer).setLayoutLocation(newLocation);
- return;
- }
-
- // <foreignObject> / <text>
- if (is<RenderSVGBlock>(renderer)) {
- downcast<RenderSVGBlock>(renderer).setLocation(newLocation);
- return;
- }
-
- // <tspan> / <textPath>
- if (is<RenderSVGInline>(renderer))
- return;
-
- ASSERT_NOT_REACHED();
-}
-
void SVGContainerLayout::positionChildrenRelativeToContainer()
{
if (m_positionedChildren.isEmpty())
@@ -177,40 +142,36 @@
};
// Arrange layout location for all child renderers relative to the container layout location.
- auto parentLayoutLocation = flooredLayoutPoint(m_container.objectBoundingBox().minXMinYCorner());
- for (RenderObject& child : m_positionedChildren) {
+ auto parentLayoutLocation = m_container.nominalSVGLayoutLocation();
+ for (RenderLayerModelObject& child : m_positionedChildren) {
verifyPositionedChildRendererExpectation(child);
- auto objectBoundingBoxChild = child.objectBoundingBox();
- auto layoutLocation = flooredLayoutPoint(objectBoundingBoxChild.minXMinYCorner());
- auto desiredLayoutLocation = toLayoutPoint(layoutLocation - parentLayoutLocation);
- auto currentLayoutLocation = layoutLocationFromRenderer(child);
- if (currentLayoutLocation == desiredLayoutLocation)
- continue;
- setLayoutLocationForRenderer(child, desiredLayoutLocation);
+ auto desiredLayoutLocation = toLayoutPoint(child.nominalSVGLayoutLocation() - parentLayoutLocation);
+ if (child.currentSVGLayoutLocation() != desiredLayoutLocation)
+ child.setCurrentSVGLayoutLocation(desiredLayoutLocation);
}
}
-void SVGContainerLayout::verifyLayoutLocationConsistency(const RenderElement& renderer)
+void SVGContainerLayout::verifyLayoutLocationConsistency(const RenderLayerModelObject& renderer)
{
if (renderer.isSVGLayerAwareRenderer() && !renderer.isSVGRoot()) {
- auto currentLayoutLocation = layoutLocationFromRenderer(renderer);
+ auto currentLayoutLocation = renderer.currentSVGLayoutLocation();
auto expectedLayoutLocation = currentLayoutLocation;
- for (auto& ancestor : ancestorsOfType<RenderElement>(renderer)) {
+ for (auto& ancestor : ancestorsOfType<RenderLayerModelObject>(renderer)) {
ASSERT(ancestor.isSVGLayerAwareRenderer());
if (ancestor.isSVGRoot())
break;
- expectedLayoutLocation.moveBy(layoutLocationFromRenderer(ancestor));
+ expectedLayoutLocation.moveBy(ancestor.currentSVGLayoutLocation());
}
- auto initialLayoutLocation = flooredLayoutPoint(renderer.objectBoundingBox().minXMinYCorner());
+ auto initialLayoutLocation = renderer.nominalSVGLayoutLocation();
if (expectedLayoutLocation == initialLayoutLocation) {
LOG_WITH_STREAM(SVG, stream << "--> SVGContainerLayout renderer " << &renderer << " (" << renderer.renderName().characters() << ")"
- << " - verifyLayoutLocationConsistency() objectBoundingBox / layoutLocation are in sync.");
+ << " - verifyLayoutLocationConsistency() currentSVGLayoutLocation / nominalSVGLayoutLocation are in sync.");
} else {
LOG_WITH_STREAM(SVG, stream << "--> SVGContainerLayout renderer " << &renderer << " (" << renderer.renderName().characters() << ")"
- << " - verifyLayoutLocationConsistency() objectBoundingBox / layoutLocation invariant violated -- out of sync due to partial layout?"
+ << " - verifyLayoutLocationConsistency() currentSVGLayoutLocation / nominalSVGLayoutLocation invariant violated -- out of sync due to partial layout?"
<< " currentLayoutLocation=" << currentLayoutLocation
<< " (expectedLayoutLocation=" << expectedLayoutLocation
<< " != initialLayoutLocation=" << initialLayoutLocation << ")"
@@ -224,7 +185,7 @@
}
}
- for (auto& child : childrenOfType<RenderElement>(renderer)) {
+ for (auto& child : childrenOfType<RenderLayerModelObject>(renderer)) {
if (child.isSVGLayerAwareRenderer())
verifyLayoutLocationConsistency(child);
}
Modified: trunk/Source/WebCore/rendering/svg/SVGContainerLayout.h (293503 => 293504)
--- trunk/Source/WebCore/rendering/svg/SVGContainerLayout.h 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/rendering/svg/SVGContainerLayout.h 2022-04-27 11:14:44 UTC (rev 293504)
@@ -40,7 +40,7 @@
void positionChildrenRelativeToContainer();
- static void verifyLayoutLocationConsistency(const RenderElement&);
+ static void verifyLayoutLocationConsistency(const RenderLayerModelObject&);
static bool transformToRootChanged(const RenderObject* ancestor);
private:
Modified: trunk/Source/WebCore/style/StyleAdjuster.cpp (293503 => 293504)
--- trunk/Source/WebCore/style/StyleAdjuster.cpp 2022-04-27 10:36:07 UTC (rev 293503)
+++ trunk/Source/WebCore/style/StyleAdjuster.cpp 2022-04-27 11:14:44 UTC (rev 293504)
@@ -54,6 +54,7 @@
#include "RenderTheme.h"
#include "RuntimeEnabledFeatures.h"
#include "SVGElement.h"
+#include "SVGGraphicsElement.h"
#include "SVGNames.h"
#include "SVGURIReference.h"
#include "Settings.h"
@@ -364,6 +365,22 @@
else
style.setUsedZIndex(style.specifiedZIndex());
+ // For SVG compatibility purposes we have to consider the 'animatedLocalTransform' besides the RenderStyle to query
+ // if an element has a transform. SVG transforms are not stored on the RenderStyle, and thus we need a special case here.
+ auto hasTransformRelatedProperty = [](const RenderStyle& style, const Element* element) {
+ if (style.hasTransformRelatedProperty())
+ return true;
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+ if (element && element->document().settings().layerBasedSVGEngineEnabled() && is<SVGGraphicsElement>(element))
+ return !downcast<SVGGraphicsElement>(*element).animatedLocalTransform().isIdentity();
+#else
+ UNUSED_PARAM(element);
+#endif
+
+ return false;
+ };
+
// Auto z-index becomes 0 for the root element and transparent objects. This prevents
// cases where objects that should be blended as a single unit end up with a non-transparent
// object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
@@ -370,7 +387,7 @@
if (style.hasAutoUsedZIndex()) {
if ((m_element && m_document.documentElement() == m_element)
|| style.hasOpacity()
- || style.hasTransformRelatedProperty()
+ || hasTransformRelatedProperty(style, m_element)
|| style.hasMask()
|| style.clipPath()
|| style.boxReflect()