Title: [294385] trunk/Source/WebCore
Revision
294385
Author
commit-qu...@webkit.org
Date
2022-05-18 01:47:17 -0700 (Wed, 18 May 2022)

Log Message

Activate text rendering, by re-using RenderSVGText
https://bugs.webkit.org/show_bug.cgi?id=239743

Patch by Nikolas Zimmermann <nzimmerm...@igalia.com> on 2022-05-18
Reviewed by Rob Buis.

Adapt RenderSVGText to be usable at the same time from legacy SVG engine (as
it is right now) and from LBSE. This requires minimal effort, since RenderSVGText
already inherited from RenderLayerModelObject, so there's no need for the creation
of LegacyRenderSVGText / RenderSVGText as separated legacy/LBSE implementations.

Most SVG 1.1 <text> testcases already pass out of the box with this change.
The next patch after text support will add a new 'macos-wk2-lbse-xxx' specific
platform baseline, so that we can run tests LBSE againt iself (finally we can
include the progressions in the form of TestExpectation file changes, once a certain
patch implements a new feature in LBSE. This makes sense now as enough is upstreamed
that a considerable amount of the SVG 1.1 testsuite already passes pixel perfect.

Covered by existing tests, no change in behaviour. (However testability for LBSE is ready soon!).

* rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::computeVisibleRectInSVGContainer const):
* rendering/RenderObject.cpp:
(WebCore::objectIsRelayoutBoundary):
* rendering/svg/RenderSVGBlock.cpp:
(WebCore::RenderSVGBlock::updateFromStyle):
(WebCore::RenderSVGBlock::absoluteRects const):
(WebCore::RenderSVGBlock::absoluteQuads const):
(WebCore::RenderSVGBlock::styleDidChange):
(WebCore::RenderSVGBlock::computeOverflow):
(WebCore::RenderSVGBlock::clippedOverflowRect const):
(WebCore::RenderSVGBlock::computeVisibleRectInContainer const):
(WebCore::RenderSVGBlock::computeFloatVisibleRectInContainer const):
(WebCore::RenderSVGBlock::pushMappingToContainer const):
(WebCore::RenderSVGBlock::offsetFromContainer const):
(WebCore::RenderSVGBlock::nodeAtPoint): Deleted.
* rendering/svg/RenderSVGBlock.h:
* rendering/svg/RenderSVGText.cpp:
(WebCore::RenderSVGText::RenderSVGText):
(WebCore::RenderSVGText::layout):
(WebCore::RenderSVGText::nodeAtFloatPoint):
(WebCore::RenderSVGText::nodeAtPoint):
(WebCore::RenderSVGText::paint):
(WebCore::RenderSVGText::repaintRectInLocalCoordinates const):
(WebCore::RenderSVGText::updatePositionAndOverflow):
(WebCore::RenderSVGText::absoluteQuads const): Deleted.
* rendering/svg/RenderSVGText.h:
* rendering/svg/SVGRootInlineBox.cpp:
(WebCore::SVGRootInlineBox::renderSVGText const):
(WebCore::SVGRootInlineBox::paint):
(WebCore::SVGRootInlineBox::layoutRootBox):
(WebCore::SVGRootInlineBox::renderSVGText): Deleted.
* rendering/svg/SVGRootInlineBox.h:
* svg/SVGElement.cpp:
(WebCore::createSVGLayerAwareElementSet):

Canonical link: https://commits.webkit.org/250682@main

Modified Paths

Diff

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -1187,29 +1187,35 @@
     if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
         return false;
 
-    LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
-    if (deltaLeft > 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
-    else if (deltaLeft < 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
+    if (newBounds.isEmpty() && !oldBounds.isEmpty())
+        repaintUsingContainer(repaintContainer, oldBounds);
+    else if (!newBounds.isEmpty() && oldBounds.isEmpty())
+        repaintUsingContainer(repaintContainer, newBounds);
+    else {
+        LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
+        if (deltaLeft > 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
+        else if (deltaLeft < 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
 
-    LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
-    if (deltaRight > 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
-    else if (deltaRight < 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
+        LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
+        if (deltaRight > 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
+        else if (deltaRight < 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
 
-    LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
-    if (deltaTop > 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
-    else if (deltaTop < 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
+        LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
+        if (deltaTop > 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
+        else if (deltaTop < 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
 
-    LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
-    if (deltaBottom > 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
-    else if (deltaBottom < 0)
-        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
+        LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
+        if (deltaBottom > 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
+        else if (deltaBottom < 0)
+            repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
+    }
 
     if (newOutlineBox == oldOutlineBox)
         return false;

Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -29,6 +29,7 @@
 #include "RenderLayerBacking.h"
 #include "RenderLayerCompositor.h"
 #include "RenderLayerScrollableArea.h"
+#include "RenderSVGBlock.h"
 #include "RenderSVGModelObject.h"
 #include "RenderView.h"
 #include "SVGGraphicsElement.h"
@@ -245,10 +246,7 @@
 #if ENABLE(LAYER_BASED_SVG_ENGINE)
 std::optional<LayoutRect> RenderLayerModelObject::computeVisibleRectInSVGContainer(const LayoutRect& rect, const RenderLayerModelObject* container, RenderObject::VisibleRectContext context) const
 {
-    // FIXME: [LBSE] Upstream RenderSVGBlock changes
-    // ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this));
-    ASSERT(is<RenderSVGModelObject>(this));
-
+    ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this));
     ASSERT(!style().hasInFlowPosition());
     ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled());
 

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -521,6 +521,11 @@
     if (!object->hasNonVisibleOverflow())
         return false;
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (object->document().settings().layerBasedSVGEngineEnabled() && object->isSVGLayerAwareRenderer())
+        return false;
+#endif
+
     if (object->style().width().isIntrinsicOrAuto() || object->style().height().isIntrinsicOrAuto() || object->style().height().isPercentOrCalculated())
         return false;
 

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGBlock.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/RenderSVGBlock.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGBlock.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -22,6 +22,7 @@
 #include "config.h"
 #include "RenderSVGBlock.h"
 
+#include "RenderSVGBlockInlines.h"
 #include "RenderSVGResource.h"
 #include "SVGGraphicsElement.h"
 #include "SVGRenderSupport.h"
@@ -42,6 +43,13 @@
 {
     RenderBlockFlow::updateFromStyle();
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled()) {
+        updateHasSVGTransformFlags(graphicsElement());
+        return;
+    }
+#endif
+
     // RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasNonVisibleOverflow(true).
     // RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both
     // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText.
@@ -57,12 +65,27 @@
     setHasNonVisibleOverflow(false);
 }
 
-void RenderSVGBlock::absoluteRects(Vector<IntRect>&, const LayoutPoint&) const
+void RenderSVGBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled()) {
+        rects.append(snappedIntRect(LayoutRect(accumulatedOffset + location(), size())));
+        return;
+    }
+#else
+    UNUSED_PARAM(rects);
+    UNUSED_PARAM(accumulatedOffset);
+#endif
+
     // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used.
     ASSERT_NOT_REACHED();
 }
 
+void RenderSVGBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
+}
+
 void RenderSVGBlock::willBeDestroyed()
 {
     SVGResourcesCache::clientDestroyed(*this);
@@ -71,7 +94,11 @@
 
 void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (diff == StyleDifference::Layout && !document().settings().layerBasedSVGEngineEnabled())
+#else
     if (diff == StyleDifference::Layout)
+#endif
         setNeedsBoundariesUpdate();
     RenderBlockFlow::styleDidChange(diff, oldStyle);
     SVGResourcesCache::clientStyleChanged(*this, diff, style());
@@ -81,6 +108,11 @@
 {
     RenderBlockFlow::computeOverflow(oldClientAfterEdge, recomputeFloats);
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled())
+        return;
+#endif
+
     const auto* textShadow = style().textShadow();
     if (!textShadow)
         return;
@@ -90,13 +122,30 @@
     addVisualOverflow(snappedIntRect(borderRect));
 }
 
-LayoutRect RenderSVGBlock::clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const
+LayoutRect RenderSVGBlock::clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext context) const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled()) {
+        if (isInsideEntirelyHiddenLayer())
+            return { };
+
+        ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled());
+        return computeRect(visualOverflowRect(), repaintContainer, context);
+    }
+#else
+    UNUSED_PARAM(context);
+#endif
+
     return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
 }
 
 std::optional<LayoutRect> RenderSVGBlock::computeVisibleRectInContainer(const LayoutRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled())
+        return computeVisibleRectInSVGContainer(rect, container, context);
+#endif
+
     std::optional<FloatRect> adjustedRect = computeFloatVisibleRectInContainer(rect, container, context);
     if (adjustedRect)
         return enclosingLayoutRect(*adjustedRect);
@@ -105,6 +154,9 @@
 
 std::optional<FloatRect> RenderSVGBlock::computeFloatVisibleRectInContainer(const FloatRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    ASSERT(!document().settings().layerBasedSVGEngineEnabled());
+#endif
     return SVGRenderSupport::computeFloatVisibleRectInContainer(*this, rect, container, context);
 }
 
@@ -115,13 +167,23 @@
 
 const RenderObject* RenderSVGBlock::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled())
+        return RenderBox::pushMappingToContainer(ancestorToStopAt, geometryMap);
+#endif
+
     return SVGRenderSupport::pushMappingToContainer(*this, ancestorToStopAt, geometryMap);
 }
 
-bool RenderSVGBlock::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+LayoutSize RenderSVGBlock::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool*) const
 {
-    ASSERT_NOT_REACHED();
-    return false;
+    ASSERT_UNUSED(container, &container == this->container());
+    ASSERT(!isInFlowPositioned());
+    ASSERT(!isAbsolutelyPositioned());
+    ASSERT(!isInline());
+    return LayoutSize();
 }
+#endif
 
 }

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGBlock.h	2022-05-18 08:47:17 UTC (rev 294385)
@@ -45,7 +45,7 @@
     bool isRenderSVGBlock() const final { return true; }
 
     void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override;
-
+    void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
 
 #if ENABLE(LAYER_BASED_SVG_ENGINE)
@@ -59,8 +59,9 @@
 
     void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const final;
     const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const final;
-
-    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) final;
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const override;
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -40,6 +40,7 @@
 #include "RenderSVGInline.h"
 #include "RenderSVGInlineText.h"
 #include "RenderSVGResource.h"
+#include "RenderSVGRoot.h"
 #include "SVGElementTypeHelpers.h"
 #include "SVGLengthList.h"
 #include "SVGResourcesCache.h"
@@ -57,10 +58,6 @@
 
 RenderSVGText::RenderSVGText(SVGTextElement& element, RenderStyle&& style)
     : RenderSVGBlock(element, WTFMove(style))
-    , m_needsReordering(false)
-    , m_needsPositioningValuesUpdate(false)
-    , m_needsTransformUpdate(true)
-    , m_needsTextMetricsUpdate(false)
 {
 }
 
@@ -311,15 +308,28 @@
 
 void RenderSVGText::layout()
 {
+    auto isLayerBasedSVGEngineEnabled = [&]() {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+        return document().settings().layerBasedSVGEngineEnabled();
+#else
+        return false;
+#endif
+    };
+
     StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
-    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(*this));
+    LayoutRepainter repainter(*this, isLayerBasedSVGEngineEnabled() ? checkForRepaintDuringLayout() : SVGRenderSupport::checkForSVGRepaintDuringLayout(*this));
 
+    // FIXME: [LBSE] Upstream SVGLengthContext changes
+    // textElement().updateLengthContext();
+
     bool updateCachedBoundariesInParents = false;
-    if (m_needsTransformUpdate) {
-        m_localTransform = textElement().animatedLocalTransform();
-        m_needsTransformUpdate = false;
-        updateCachedBoundariesInParents = true;
+    if (!isLayerBasedSVGEngineEnabled()) {
+        if (m_needsTransformUpdate) {
+            m_localTransform = textElement().animatedLocalTransform();
+            m_needsTransformUpdate = false;
+            updateCachedBoundariesInParents = true;
+        }
     }
 
     if (!everHadLayout()) {
@@ -347,8 +357,15 @@
         m_needsPositioningValuesUpdate = false;
         updateCachedBoundariesInParents = true;
     } else {
-        LegacyRenderSVGRoot* rootObj = SVGRenderSupport::findTreeRootObject(*this);
-        if (m_needsTextMetricsUpdate || (rootObj && rootObj->isLayoutSizeChanged())) {
+        bool isLayoutSizeChanged = false;
+        if (auto* legacyRootObject = lineageOfType<LegacyRenderSVGRoot>(*this).first())
+            isLayoutSizeChanged = legacyRootObject->isLayoutSizeChanged();
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+        else if (auto* rootObject = lineageOfType<RenderSVGRoot>(*this).first())
+            isLayoutSizeChanged = rootObject->isLayoutSizeChanged();
+#endif
+
+        if (m_needsTextMetricsUpdate || isLayoutSizeChanged) {
             // If the root layout size changed (eg. window size changes) or the transform to the root
             // context has changed then recompute the on-screen font size.
             updateFontInAllDescendants(this, &m_layoutAttributesBuilder);
@@ -365,33 +382,44 @@
     // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text.
     // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions.
     ASSERT(!isInline());
-    ASSERT(!simplifiedLayout());
     ASSERT(!scrollsOverflow());
     ASSERT(!hasControlClip());
     ASSERT(!multiColumnFlow());
     ASSERT(!positionedObjects());
-    ASSERT(!m_overflow);
     ASSERT(!isAnonymousBlock());
+    if (!isLayerBasedSVGEngineEnabled()) {
+        ASSERT(!simplifiedLayout());
+        ASSERT(!m_overflow);
+    }
 
-    if (!firstChild())
+    // FIXME: We need to find a way to only layout the child boxes, if needed.
+    auto layoutChanged = everHadLayout() && selfNeedsLayout();
+    auto oldBoundaries = objectBoundingBox();
+
+    if (!firstChild()) {
+        updatePositionAndOverflow({ });
         setChildrenInline(true);
+    }
 
-    // FIXME: We need to find a way to only layout the child boxes, if needed.
-    FloatRect oldBoundaries = objectBoundingBox();
     ASSERT(childrenInline());
+
     LayoutUnit repaintLogicalTop;
     LayoutUnit repaintLogicalBottom;
     rebuildFloatingObjectSetFromIntrudingFloats();
     layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
 
+    // updatePositionAndOverflow() is called by SVGRootInlineBox, after forceLayoutInlineChildren() ran, before this point is reached.
     if (m_needsReordering)
         m_needsReordering = false;
 
-    if (!updateCachedBoundariesInParents)
+    if (isLayerBasedSVGEngineEnabled()) {
+        updateLayerTransform();
+        updateCachedBoundariesInParents = false; // No longer needed for LBSE.
+    } else if (!updateCachedBoundariesInParents)
         updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox();
 
     // Invalidate all resources of this client if our layout changed.
-    if (everHadLayout() && selfNeedsLayout())
+    if (layoutChanged)
         SVGResourcesCache::clientLayoutChanged(*this);
 
     // If our bounds changed, notify the parents.
@@ -404,6 +432,9 @@
 
 bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    ASSERT(!document().settings().layerBasedSVGEngineEnabled());
+#endif
     PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style().effectivePointerEvents());
     bool isVisible = (style().visibility() == Visibility::Visible);
     if (isVisible || !hitRules.requireVisible) {
@@ -412,7 +443,7 @@
             FloatPoint localPoint = valueOrDefault(localToParentTransform().inverse()).mapPoint(pointInParent);
 
             if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
-                return false;       
+                return false;
 
             SVGHitTestCycleDetectionScope hitTestScope(*this);
 
@@ -424,6 +455,33 @@
     return false;
 }
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    ASSERT(document().settings().layerBasedSVGEngineEnabled());
+    auto adjustedLocation = accumulatedOffset + location();
+
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style().pointerEvents());
+    bool isVisible = (style().visibility() == Visibility::Visible);
+    if (isVisible || !hitRules.requireVisible) {
+        if ((hitRules.canHitStroke && (style().svgStyle().hasStroke() || !hitRules.requireStroke))
+        || (hitRules.canHitFill && (style().svgStyle().hasFill() || !hitRules.requireFill))) {
+            auto localPoint = locationInContainer.point();
+            auto coordinateSystemOriginTranslation = nominalSVGLayoutLocation() - adjustedLocation;
+            localPoint.move(coordinateSystemOriginTranslation);
+
+            if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
+                return false;
+
+            SVGHitTestCycleDetectionScope hitTestScope(*this);
+            return RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
+        }
+    }
+
+    return false;
+}
+#endif
+
 VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents, const RenderFragmentContainer* fragment)
 {
     LegacyRootInlineBox* rootBox = firstRootBox();
@@ -440,19 +498,56 @@
     return closestBox->renderer().positionForPoint({ pointInContents.x(), LayoutUnit(closestBox->y()) }, fragment);
 }
 
-void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
-    quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
-}
-
-void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
-{
     if (paintInfo.context().paintingDisabled())
         return;
 
-    if (paintInfo.phase != PaintPhase::Foreground && paintInfo.phase != PaintPhase::Selection)
-         return;
+    if (paintInfo.phase != PaintPhase::ClippingMask && paintInfo.phase != PaintPhase::Mask && paintInfo.phase != PaintPhase::Foreground && paintInfo.phase != PaintPhase::Outline && paintInfo.phase != PaintPhase::SelfOutline)
+        return;
 
+    if (!paintInfo.shouldPaintWithinRoot(*this))
+        return;
+
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled()) {
+        if (style().visibility() == Visibility::Hidden || style().display() == DisplayType::None)
+            return;
+
+        // FIXME: [LBSE] Upstream SVGRenderSupport changes
+        // if (!SVGRenderSupport::shouldPaintHiddenRenderer(*this))
+        //     return;
+
+        if (paintInfo.phase == PaintPhase::ClippingMask) {
+            // FIXME: [LBSE] Upstream SVGRenderSupport changes
+            // SVGRenderSupport::paintSVGClippingMask(*this, paintInfo);
+            return;
+        }
+
+        auto adjustedPaintOffset = paintOffset + location();
+        if (paintInfo.phase == PaintPhase::Mask) {
+            // FIXME: [LBSE] Upstream SVGRenderSupport changes
+            // SVGRenderSupport::paintSVGMask(*this, paintInfo, adjustedPaintOffset);
+            return;
+        }
+
+        if (paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) {
+            RenderBlock::paint(paintInfo, paintOffset);
+            return;
+        }
+
+        GraphicsContextStateSaver stateSaver(paintInfo.context());
+
+        auto coordinateSystemOriginTranslation = adjustedPaintOffset - nominalSVGLayoutLocation();
+        paintInfo.context().translate(coordinateSystemOriginTranslation.width(), coordinateSystemOriginTranslation.height());
+
+        RenderBlock::paint(paintInfo, paintOffset);
+        return;
+    }
+#else
+    UNUSED_PARAM(paintOffset);
+#endif
+
     PaintInfo blockInfo(paintInfo);
     GraphicsContextStateSaver stateSaver(blockInfo.context());
     blockInfo.applyTransform(localToParentTransform());
@@ -479,6 +574,11 @@
 
 FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
 {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled())
+        return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this);
+#endif
+
     FloatRect repaintRect = strokeBoundingBox();
     SVGRenderSupport::intersectRepaintRectWithResources(*this, repaintRect);
 
@@ -488,4 +588,32 @@
     return repaintRect;
 }
 
+void RenderSVGText::updatePositionAndOverflow(const FloatRect& boundaries)
+{
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (document().settings().layerBasedSVGEngineEnabled()) {
+        clearOverflow();
+
+        m_objectBoundingBox = boundaries;
+
+        auto boundingRect = enclosingLayoutRect(m_objectBoundingBox);
+        setLocation(boundingRect.location());
+        setSize(boundingRect.size());
+
+        auto overflowRect = visualOverflowRectEquivalent();
+        if (const auto* textShadow = style().textShadow())
+            textShadow->adjustRectForShadow(overflowRect);
+
+        addVisualOverflow(overflowRect);
+        return;
+    }
+#endif
+
+    auto boundingRect = enclosingLayoutRect(boundaries);
+    setLocation(boundingRect.location());
+    setSize(boundingRect.size());
+    m_objectBoundingBox = boundingRect;
+    ASSERT(m_objectBoundingBox == frameRect());
 }
+
+}

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGText.h (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/RenderSVGText.h	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGText.h	2022-05-18 08:47:17 UTC (rev 294385)
@@ -23,6 +23,7 @@
 
 #include "AffineTransform.h"
 #include "RenderSVGBlock.h"
+#include "SVGBoundingBoxComputation.h"
 #include "SVGTextLayoutAttributesBuilder.h"
 
 namespace WebCore {
@@ -42,10 +43,11 @@
     bool isChildAllowed(const RenderObject&, const RenderStyle&) const override;
 
     void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
-    void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
     void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
-    FloatRect repaintRectInLocalCoordinates() const override;
 
+    // FIXME: [LBSE] Only needed for legacy SVG engine.
+    void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
+
     static RenderSVGText* locateRenderSVGTextAncestor(RenderObject&);
     static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject&);
 
@@ -58,9 +60,15 @@
     void subtreeStyleDidChange(RenderSVGInlineText*);
     void subtreeTextDidChange(RenderSVGInlineText*);
 
-    FloatRect objectBoundingBox() const override { return frameRect(); }
-    FloatRect strokeBoundingBox() const override;
+    FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
+    FloatRect strokeBoundingBox() const final;
+    FloatRect repaintRectInLocalCoordinates() const final;
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }
+#endif
+    void updatePositionAndOverflow(const FloatRect&);
+
 private:
     void graphicsElement() const = delete;
 
@@ -68,28 +76,40 @@
     bool isSVGText() const override { return true; }
 
     void paint(PaintInfo&, const LayoutPoint&) override;
-    bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
+#endif
     VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override;
 
-    bool requiresLayer() const override { return false; }
+    bool requiresLayer() const override
+    {
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+        if (document().settings().layerBasedSVGEngineEnabled())
+            return true;
+#endif
+        return false;
+    }
+
     void layout() override;
 
-    void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
-
     void willBeDestroyed() override;
 
+    // FIXME: [LBSE] Begin code only needed for legacy SVG engine.
+    bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
     const AffineTransform& localToParentTransform() const override { return m_localTransform; }
     AffineTransform localTransform() const override { return m_localTransform; }
+    // FIXME: [LBSE] End code only needed for legacy SVG engine.
 
     bool shouldHandleSubtreeMutations() const;
 
-    bool m_needsReordering : 1;
-    bool m_needsPositioningValuesUpdate : 1;
-    bool m_needsTransformUpdate : 1;
-    bool m_needsTextMetricsUpdate : 1;
-    AffineTransform m_localTransform;
+    bool m_needsReordering : 1 { false };
+    bool m_needsPositioningValuesUpdate : 1 { false };
+    bool m_needsTransformUpdate : 1 { true }; // FIXME: [LBSE] Only needed for legacy SVG engine.
+    bool m_needsTextMetricsUpdate : 1 { false };
+    AffineTransform m_localTransform; // FIXME: [LBSE] Only needed for legacy SVG engine.
     SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder;
     Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
+    FloatRect m_objectBoundingBox;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -46,21 +46,37 @@
 {
 }
 
-RenderSVGText& SVGRootInlineBox::renderSVGText()
+RenderSVGText& SVGRootInlineBox::renderSVGText() const
 {
     return downcast<RenderSVGText>(blockFlow());
 }
 
-void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
 {
     ASSERT(paintInfo.phase == PaintPhase::Foreground || paintInfo.phase == PaintPhase::Selection);
     ASSERT(!paintInfo.context().paintingDisabled());
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (renderer().document().settings().layerBasedSVGEngineEnabled()) {
+        auto overflowRect(visualOverflowRect(lineTop, lineBottom));
+        flipForWritingMode(overflowRect);
+        overflowRect.moveBy(paintOffset);
+
+        if (!paintInfo.rect.intersects(overflowRect))
+            return;
+    }
+#else
+    UNUSED_PARAM(lineTop);
+    UNUSED_PARAM(lineBottom);
+#endif
+
     bool isPrinting = renderSVGText().document().printing();
     bool hasSelection = !isPrinting && selectionState() != RenderObject::HighlightState::None;
     bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior.contains(PaintBehavior::SkipSelectionHighlight));
 
     PaintInfo childPaintInfo(paintInfo);
+    childPaintInfo.updateSubtreePaintRootForChildren(&renderer());
+
     if (hasSelection && shouldPaintSelectionHighlight) {
         for (auto* child = firstChild(); child; child = child->nextOnLine()) {
             if (is<SVGInlineTextBox>(*child))
@@ -70,6 +86,17 @@
         }
     }
 
+#if ENABLE(LAYER_BASED_SVG_ENGINE)
+    if (renderer().document().settings().layerBasedSVGEngineEnabled()) {
+        for (auto* child = firstChild(); child; child = child->nextOnLine()) {
+            if (child->renderer().isText() || !child->boxModelObject()->hasSelfPaintingLayer())
+                child->paint(childPaintInfo, paintOffset, lineTop, lineBottom);
+        }
+
+        return;
+    }
+#endif
+
     SVGRenderingContext renderingContext(renderSVGText(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
     if (renderingContext.isRenderingPrepared()) {
         for (auto* child = firstChild(); child; child = child->nextOnLine())
@@ -170,9 +197,7 @@
     RenderSVGText& parentBlock = renderSVGText();
 
     // Finally, assign the root block position, now that all content is laid out.
-    LayoutRect boundingRect = enclosingLayoutRect(childRect);
-    parentBlock.setLocation(boundingRect.location());
-    parentBlock.setSize(boundingRect.size());
+    parentBlock.updatePositionAndOverflow(childRect);
 
     // Position all children relative to the parent block.
     for (auto* child = firstChild(); child; child = child->nextOnLine()) {
@@ -187,6 +212,8 @@
     setY(0);
     setLogicalWidth(childRect.width());
     setLogicalHeight(childRect.height());
+
+    auto boundingRect = enclosingLayoutRect(childRect);
     setLineTopBottomPositions(0, boundingRect.height(), 0, boundingRect.height());
 }
 

Modified: trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.h (294384 => 294385)


--- trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.h	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.h	2022-05-18 08:47:17 UTC (rev 294385)
@@ -35,8 +35,6 @@
 public:
     explicit SVGRootInlineBox(RenderSVGText&);
 
-    RenderSVGText& renderSVGText();
-
     float virtualLogicalHeight() const override { return m_logicalHeight; }
     void setLogicalHeight(float height) { m_logicalHeight = height; }
 
@@ -49,6 +47,8 @@
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) final;
 
 private:
+    RenderSVGText& renderSVGText() const;
+
     bool isSVGRootInlineBox() const override { return true; }
     void reorderValueListsToLogicalOrder(Vector<SVGTextLayoutAttributes*>&);
     void layoutCharactersInTextBoxes(LegacyInlineFlowBox*, SVGTextLayoutEngine&);

Modified: trunk/Source/WebCore/svg/SVGElement.cpp (294384 => 294385)


--- trunk/Source/WebCore/svg/SVGElement.cpp	2022-05-18 07:18:55 UTC (rev 294384)
+++ trunk/Source/WebCore/svg/SVGElement.cpp	2022-05-18 08:47:17 UTC (rev 294385)
@@ -531,7 +531,7 @@
     // List of all SVG elements whose renderers support the layer aware layout / painting / hit-testing mode ('LBSE-mode').
     using namespace SVGNames;
     MemoryCompactLookupOnlyRobinHoodHashSet<AtomString> set;
-    for (auto& tag : { gTag.get(), rectTag.get() })
+    for (auto& tag : { gTag.get(), rectTag.get(), textTag.get() })
         set.add(tag.localName());
     return set;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to