WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch, v4
bug-239717-20220425165328.patch (text/plain), 48.19 KB, created by
Nikolas Zimmermann
on 2022-04-25 16:53:29 PDT
(
hide
)
Description:
Patch, v4
Filename:
MIME Type:
Creator:
Nikolas Zimmermann
Created:
2022-04-25 16:53:29 PDT
Size:
48.19 KB
patch
obsolete
>Subversion Revision: 293368 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 5c2981668e2124ae214ba71669ee86ea2951b096..2dbed010e6c7ab24cffdca67556164478fe4f7bb 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,101 @@ >+2022-04-25 Nikolas Zimmermann <nzimmermann@igalia.com> >+ >+ [LBSE] Fix origin of transformations in SVG >+ https://bugs.webkit.org/show_bug.cgi?id=239717 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-25 Devin Rousso <drousso@apple.com> > > Web Inspector: request interception should not be guarded based on service workers >diff --git a/Source/WebCore/rendering/RenderElement.cpp b/Source/WebCore/rendering/RenderElement.cpp >index b76e181e6a200d708cf8464f50d80e50b03e1aca..680ce5c76ca6ad6a37caa73b0a9b5ca0a0beb2c3 100644 >--- a/Source/WebCore/rendering/RenderElement.cpp >+++ b/Source/WebCore/rendering/RenderElement.cpp >@@ -2418,21 +2418,43 @@ FloatRect RenderElement::referenceBoxRect(CSSBoxType boxType) const > 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(); >diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp >index c2de0b6d5fd6fd82102f70bccc19ba7693daec67..bb4d3a4e462bcc97566efba49b8d183978ca4a3c 100644 >--- a/Source/WebCore/rendering/RenderLayer.cpp >+++ b/Source/WebCore/rendering/RenderLayer.cpp >@@ -302,9 +302,9 @@ static ScrollingScope nextScrollingScope() > > 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 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject) > , m_hasNotIsolatedBlendingDescendantsStatusDirty(false) > #endif > , m_repaintRectsValid(false) >- , m_renderer(rendererLayerModelObject) >+ , m_renderer(renderer) > { > setIsNormalFlowOnly(shouldBeNormalFlowOnly()); > setIsCSSStackingContext(shouldBeCSSStackingContext()); >@@ -353,9 +353,9 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject) > 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 @@ static bool canCreateStackingContext(const RenderLayer& layer) > { > auto& renderer = layer.renderer(); > return renderer.hasTransformRelatedProperty() >-#if ENABLE(LAYER_BASED_SVG_ENGINE) >- || renderer.hasSVGTransform() >-#endif > || renderer.hasClipPath() > || renderer.hasFilter() > || renderer.hasMask() >@@ -3545,19 +3542,29 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti > > 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; > 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 @@ void RenderLayer::paintLayerByApplyingTransform(GraphicsContext& context, const > 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)); >diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h >index 7d3cb157d0fbf202ea7d8a64923f804df3091c72..804761a8f920004e8fdd427e18d4a79845131b9d 100644 >--- a/Source/WebCore/rendering/RenderLayer.h >+++ b/Source/WebCore/rendering/RenderLayer.h >@@ -984,7 +984,7 @@ private: > 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(); >diff --git a/Source/WebCore/rendering/RenderLayerModelObject.cpp b/Source/WebCore/rendering/RenderLayerModelObject.cpp >index 01b98af481eeff27b460aa46badac0eadf7d12e0..cec04fa3b3fc578f1f45bdd49d13dc2fc995a825 100644 >--- a/Source/WebCore/rendering/RenderLayerModelObject.cpp >+++ b/Source/WebCore/rendering/RenderLayerModelObject.cpp >@@ -129,6 +129,9 @@ void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderSt > 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 @@ std::optional<LayoutRect> RenderLayerModelObject::computeVisibleRectInSVGContain > */ > > if (moveToOrigin) >- adjustedRect.moveBy(flooredLayoutPoint(objectBoundingBox().minXMinYCorner())); >+ adjustedRect.moveBy(nominalSVGLayoutLocation()); > > if (auto* transform = layer()->transform()) > adjustedRect = transform->mapRect(adjustedRect); >@@ -356,6 +359,13 @@ void RenderLayerModelObject::applySVGTransform(TransformationMatrix& transform, > > 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) >diff --git a/Source/WebCore/rendering/RenderLayerModelObject.h b/Source/WebCore/rendering/RenderLayerModelObject.h >index 06ac78c3fe3cec502fd703d47aac375604e07a24..c8b70ed893f0fd7f01e06b5eee198125106800dd 100644 >--- a/Source/WebCore/rendering/RenderLayerModelObject.h >+++ b/Source/WebCore/rendering/RenderLayerModelObject.h >@@ -78,6 +78,11 @@ public: > 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(); >diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h >index 368c3d17b3b60b75229d6d3ac478c0ceabddb3dc..e90e9048ae854e1c317ff234bfad264f6ee595c2 100644 >--- a/Source/WebCore/rendering/RenderObject.h >+++ b/Source/WebCore/rendering/RenderObject.h >@@ -367,6 +367,19 @@ public: > 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. >+ // Their 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; >diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.h b/Source/WebCore/rendering/svg/RenderSVGBlock.h >index 9e99ae06460f989c8aa1768bfe59b5b979c995a4..c146ddaef20b53c4d41a59484a974cadfcd6f356 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGBlock.h >+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h >@@ -48,6 +48,11 @@ private: > > 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; >diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp >index 345d636134d5fdbcf9267bfcdacc4cf62cb3c6c7..2138093963c72ddc43dad432cc934b929d61fa23 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp >@@ -119,19 +119,14 @@ void RenderSVGContainer::layoutChildren() > > SVGBoundingBoxComputation boundingBoxComputation(*this); > m_objectBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::objectBoundingBoxDecoration, &m_objectBoundingBoxValid); >- m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration); >- setLayoutRect(enclosingLayoutRect(m_objectBoundingBox)); > >- containerLayout.positionChildrenRelativeToContainer(); >-} >+ constexpr auto objectBoundingBoxDecorationWithoutTransformations = SVGBoundingBoxComputation::objectBoundingBoxDecoration | SVGBoundingBoxComputation::DecorationOption::IgnoreTransformations; >+ m_objectBoundingBoxWithoutTransformations = boundingBoxComputation.computeDecoratedBoundingBox(objectBoundingBoxDecorationWithoutTransformations); > >-void RenderSVGContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) >-{ >- RenderSVGModelObject::styleDidChange(diff, oldStyle); >+ m_strokeBoundingBox = boundingBoxComputation.computeDecoratedBoundingBox(SVGBoundingBoxComputation::strokeBoundingBoxDecoration); >+ setCurrentSVGLayoutRect(enclosingLayoutRect(m_objectBoundingBoxWithoutTransformations)); > >- // FIXME: [LBSE] Upstream RenderLayer changes >- // if (hasLayer()) >- // layer()->setIsOpportunisticStackingContext(true); >+ containerLayout.positionChildrenRelativeToContainer(); > } > > bool RenderSVGContainer::selfWillPaint() >@@ -165,7 +160,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOff > 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 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOff > > 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 @@ bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResul > 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)) >diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h >index e3482ab9f03a15f931a29969d1f65406605f57bb..fd425a30c48edd2217786557aae5fb0b262e77c8 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h >+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h >@@ -40,6 +40,7 @@ public: > 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 @@ protected: > 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 @@ protected: > > bool m_objectBoundingBoxValid { false }; > FloatRect m_objectBoundingBox; >+ FloatRect m_objectBoundingBoxWithoutTransformations; > FloatRect m_strokeBoundingBox; > > private: >diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h >index 200014775cee825d1dafba4d940e2b8d02327542..54a5a17e8e0af6ce1370bef79abff5be99a1c243 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGInline.h >+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h >@@ -51,6 +51,11 @@ private: > 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; >diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp >index c9695e6b6a43f9cf4ff0395ac361a43261db8e23..6ffee997182e9ee72052a9af0796921890c3c32f 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp >@@ -61,12 +61,8 @@ void RenderSVGModelObject::updateFromStyle() > { > 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 @@ LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelO > > 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 >diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h >index bc11245043c9d1e54eb0cc4cc2c148c9a9b238c3..ae89b8deac98b2de5bc99176a298a43328447dc3 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h >+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h >@@ -58,26 +58,21 @@ public: > > 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); } >diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp >index a9b93322b0a8f246e02c5603625df3346d3dfbcc..22a00cf4493cb4bd193260b1197d432ccc7f737e 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp >@@ -196,6 +196,10 @@ void RenderSVGRoot::layout() > > 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 @@ void RenderSVGRoot::updateFromStyle() > RenderReplaced::updateFromStyle(); > > setHasSVGTransform(); >+ setHasTransformRelatedProperty(); > > if (shouldApplyViewportClip()) > setHasNonVisibleOverflow(); >diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h >index e7f71553267eb23980058d17ed08dc820180008f..c0d1ccdda38689f72dcfb3ea140323fb712a5025 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h >+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h >@@ -67,6 +67,7 @@ public: > 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 @@ private: > > IntSize m_containerSize; > FloatRect m_objectBoundingBox; >+ FloatRect m_objectBoundingBoxWithoutTransformations; > FloatRect m_strokeBoundingBox; > AffineTransform m_viewBoxTransform; > AffineTransform m_supplementalLocalToParentTransform; >diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp >index caaf6b35b0e052003df9201eec0004d54351f406..99b2884d724599f36994aa3070f8743baf29e820 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp >@@ -151,7 +151,7 @@ void RenderSVGShape::layout() > updateShapeFromElement(); > > m_needsShapeUpdate = false; >- setLayoutRect(enclosingLayoutRect(m_fillBoundingBox)); >+ setCurrentSVGLayoutRect(enclosingLayoutRect(m_fillBoundingBox)); > } > > updateLayerTransform(); >@@ -288,7 +288,7 @@ void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) > 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 @@ void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) > > 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 @@ bool RenderSVGShape::nodeAtPoint(const HitTestRequest& request, HitTestResult& r > 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)) >diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp >index b00fb50aa9e0001797fc95508586a6b214077f79..0deb0e37bbc3dfeee099200bfd5c5b0048c9cc25 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp >@@ -97,8 +97,10 @@ void RenderSVGTransformableContainer::updateFromStyle() > { > 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 >diff --git a/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp b/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp >index 798098deb2c985465b91607864794c86efb46733..4db5c8216ffa08185d000593f7e521bd5116e2af 100644 >--- a/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp >+++ b/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp >@@ -175,8 +175,10 @@ FloatRect SVGBoundingBoxComputation::handleRootOrContainer(const SVGBoundingBoxC > 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); >diff --git a/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h b/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h >index 83da63bd6f0982ec67fa5b3bc946bd882d259d44..0d754ad4311ec85db91700908a0a03b12d566e4c 100644 >--- a/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h >+++ b/Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h >@@ -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,15 +35,16 @@ public: > 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' */ > 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 @@ public: > return LayoutRect(); > > auto visualOverflowRect = enclosingLayoutRect(repaintBoundingBox); >- visualOverflowRect.moveBy(-flooredLayoutPoint(renderer.objectBoundingBox().minXMinYCorner())); >+ visualOverflowRect.moveBy(-renderer.nominalSVGLayoutLocation()); > return visualOverflowRect; > } > >diff --git a/Source/WebCore/rendering/svg/SVGContainerLayout.cpp b/Source/WebCore/rendering/svg/SVGContainerLayout.cpp >index 813c3ecef938bda486444d4af708d97cb73ceae0..83282cf03166e82dc4d26069100924fb2850e570 100644 >--- a/Source/WebCore/rendering/svg/SVGContainerLayout.cpp >+++ b/Source/WebCore/rendering/svg/SVGContainerLayout.cpp >@@ -120,41 +120,6 @@ void SVGContainerLayout::layoutChildren(bool containerNeedsLayout) > 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 @@ void SVGContainerLayout::positionChildrenRelativeToContainer() > }; > > // 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 @@ void SVGContainerLayout::verifyLayoutLocationConsistency(const RenderElement& re > } > } > >- for (auto& child : childrenOfType<RenderElement>(renderer)) { >+ for (auto& child : childrenOfType<RenderLayerModelObject>(renderer)) { > if (child.isSVGLayerAwareRenderer()) > verifyLayoutLocationConsistency(child); > } >diff --git a/Source/WebCore/rendering/svg/SVGContainerLayout.h b/Source/WebCore/rendering/svg/SVGContainerLayout.h >index ec130935126cf7ece159992a8db71c11673026e7..534401ccd4fb8c8efc22578fadbf061d1f2fe888 100644 >--- a/Source/WebCore/rendering/svg/SVGContainerLayout.h >+++ b/Source/WebCore/rendering/svg/SVGContainerLayout.h >@@ -40,7 +40,7 @@ public: > > void positionChildrenRelativeToContainer(); > >- static void verifyLayoutLocationConsistency(const RenderElement&); >+ static void verifyLayoutLocationConsistency(const RenderLayerModelObject&); > static bool transformToRootChanged(const RenderObject* ancestor); > > private: >diff --git a/Source/WebCore/style/StyleAdjuster.cpp b/Source/WebCore/style/StyleAdjuster.cpp >index f2c076f7b772d115e4eef6a806fbabb25f55fe93..869b19a6b7897193cd438ba820fa3ea981d43133 100644 >--- a/Source/WebCore/style/StyleAdjuster.cpp >+++ b/Source/WebCore/style/StyleAdjuster.cpp >@@ -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,13 +365,29 @@ void Adjuster::adjust(RenderStyle& style, const RenderStyle* userAgentAppearance > 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. > 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()
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 239717
:
458267
|
458305
|
458310
|
458314
|
458434