Title: [293989] trunk/Source/WebCore
Revision
293989
Author
simon.fra...@apple.com
Date
2022-05-09 13:56:14 -0700 (Mon, 09 May 2022)

Log Message

Cache the viewport size inside SVGLengthContext
https://bugs.webkit.org/show_bug.cgi?id=240157

Reviewed by Alan Bujtas.

Each call to SVGLengthContext::determineViewport() did an ancestor element walk
looking for a viewport element, and some call sites hit this two or more times
(e.g. for width, then height). So cache m_viewportSize in the class, modernizing
the code to use optionals.

* rendering/RenderElement.cpp:
(WebCore::RenderElement::referenceBoxRect const):
* rendering/svg/LegacyRenderSVGRoot.cpp:
(WebCore::LegacyRenderSVGRoot::computeFloatVisibleRectInContainer const):
* rendering/svg/SVGRenderSupport.cpp:
(WebCore::clipPathReferenceBox):
* svg/SVGLengthContext.cpp:
(WebCore::SVGLengthContext::valueForLength):
(WebCore::SVGLengthContext::convertValueToUserUnits const):
(WebCore::SVGLengthContext::convertValueFromUserUnitsToPercentage const):
(WebCore::SVGLengthContext::convertValueFromPercentageToUserUnits const):
(WebCore::SVGLengthContext::viewportSize const):
(WebCore::SVGLengthContext::computeViewportSize const):
(WebCore::SVGLengthContext::determineViewport const): Deleted.
* svg/SVGLengthContext.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (293988 => 293989)


--- trunk/Source/WebCore/ChangeLog	2022-05-09 20:43:28 UTC (rev 293988)
+++ trunk/Source/WebCore/ChangeLog	2022-05-09 20:56:14 UTC (rev 293989)
@@ -1,3 +1,31 @@
+2022-05-09  Simon Fraser  <simon.fra...@apple.com>
+
+        Cache the viewport size inside SVGLengthContext
+        https://bugs.webkit.org/show_bug.cgi?id=240157
+
+        Reviewed by Alan Bujtas.
+
+        Each call to SVGLengthContext::determineViewport() did an ancestor element walk
+        looking for a viewport element, and some call sites hit this two or more times
+        (e.g. for width, then height). So cache m_viewportSize in the class, modernizing
+        the code to use optionals.
+
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::referenceBoxRect const):
+        * rendering/svg/LegacyRenderSVGRoot.cpp:
+        (WebCore::LegacyRenderSVGRoot::computeFloatVisibleRectInContainer const):
+        * rendering/svg/SVGRenderSupport.cpp:
+        (WebCore::clipPathReferenceBox):
+        * svg/SVGLengthContext.cpp:
+        (WebCore::SVGLengthContext::valueForLength):
+        (WebCore::SVGLengthContext::convertValueToUserUnits const):
+        (WebCore::SVGLengthContext::convertValueFromUserUnitsToPercentage const):
+        (WebCore::SVGLengthContext::convertValueFromPercentageToUserUnits const):
+        (WebCore::SVGLengthContext::viewportSize const):
+        (WebCore::SVGLengthContext::computeViewportSize const):
+        (WebCore::SVGLengthContext::determineViewport const): Deleted.
+        * svg/SVGLengthContext.h:
+
 2022-05-09  Tim Nguyen  <n...@apple.com>
 
         Implement CSS :modal pseudo class

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (293988 => 293989)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2022-05-09 20:43:28 UTC (rev 293988)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2022-05-09 20:56:14 UTC (rev 293989)
@@ -2452,8 +2452,7 @@
         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);
+        auto viewportSize = SVGLengthContext(downcast<SVGElement>(element())).viewportSize().value_or(FloatSize { });
         return alignReferenceBox({ { }, viewportSize });
     }
 

Modified: trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp (293988 => 293989)


--- trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2022-05-09 20:43:28 UTC (rev 293988)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderSupport.cpp	2022-05-09 20:56:14 UTC (rev 293989)
@@ -355,9 +355,9 @@
         break;
     case CSSBoxType::ViewBox:
         if (renderer.element()) {
-            FloatSize viewportSize;
-            SVGLengthContext(downcast<SVGElement>(renderer.element())).determineViewport(viewportSize);
-            referenceBox.setSize(viewportSize);
+            auto viewportSize = SVGLengthContext(downcast<SVGElement>(renderer.element())).viewportSize();
+            if (viewportSize)
+                referenceBox.setSize(*viewportSize);
             break;
         }
         FALLTHROUGH;

Modified: trunk/Source/WebCore/svg/SVGLengthContext.cpp (293988 => 293989)


--- trunk/Source/WebCore/svg/SVGLengthContext.cpp	2022-05-09 20:43:28 UTC (rev 293988)
+++ trunk/Source/WebCore/svg/SVGLengthContext.cpp	2022-05-09 20:56:14 UTC (rev 293989)
@@ -98,8 +98,7 @@
     if (length.isAuto() || !length.isSpecified())
         return 0;
 
-    FloatSize viewportSize;
-    determineViewport(viewportSize);
+    auto viewportSize = this->viewportSize().value_or(FloatSize { });
 
     switch (lengthMode) {
     case SVGLengthMode::Width:
@@ -115,7 +114,7 @@
 ExceptionOr<float> SVGLengthContext::convertValueToUserUnits(float value, SVGLengthType lengthType, SVGLengthMode lengthMode) const
 {
     // If the SVGLengthContext carries a custom viewport, force resolving against it.
-    if (!m_overriddenViewport.isEmpty()) {
+    if (!m_overriddenViewport.isZero()) {
         // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
         if (lengthType == SVGLengthType::Percentage)
             value /= 100;
@@ -184,17 +183,17 @@
 
 ExceptionOr<float> SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode lengthMode) const
 {
-    FloatSize viewportSize;
-    if (!determineViewport(viewportSize))
+    auto viewportSize = this->viewportSize();
+    if (!viewportSize)
         return Exception { NotSupportedError };
 
     switch (lengthMode) {
     case SVGLengthMode::Width:
-        return value / viewportSize.width() * 100;
+        return value / viewportSize->width() * 100;
     case SVGLengthMode::Height:
-        return value / viewportSize.height() * 100;
+        return value / viewportSize->height() * 100;
     case SVGLengthMode::Other:
-        return value / (viewportSize.diagonalLength() / sqrtOfTwoFloat) * 100;
+        return value / (viewportSize->diagonalLength() / sqrtOfTwoFloat) * 100;
     };
 
     ASSERT_NOT_REACHED();
@@ -203,17 +202,17 @@
 
 ExceptionOr<float> SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode lengthMode) const
 {
-    FloatSize viewportSize;
-    if (!determineViewport(viewportSize))
+    auto viewportSize = this->viewportSize();
+    if (!viewportSize)
         return Exception { NotSupportedError };
 
     switch (lengthMode) {
     case SVGLengthMode::Width:
-        return value * viewportSize.width();
+        return value * viewportSize->width();
     case SVGLengthMode::Height:
-        return value * viewportSize.height();
+        return value * viewportSize->height();
     case SVGLengthMode::Other:
-        return value * viewportSize.diagonalLength() / sqrtOfTwoFloat;
+        return value * viewportSize->diagonalLength() / sqrtOfTwoFloat;
     };
 
     ASSERT_NOT_REACHED();
@@ -285,34 +284,41 @@
     return value * std::ceil(style->metricsOfPrimaryFont().xHeight());
 }
 
-bool SVGLengthContext::determineViewport(FloatSize& viewportSize) const
+std::optional<FloatSize> SVGLengthContext::viewportSize() const
 {
     if (!m_context)
-        return false;
+        return std::nullopt;
 
     // If an overridden viewport is given, it has precedence.
-    if (!m_overriddenViewport.isEmpty()) {
-        viewportSize = m_overriddenViewport.size();
-        return true;
-    }
+    if (!m_overriddenViewport.isZero())
+        return m_overriddenViewport.size();
 
+    if (!m_viewportSize)
+        m_viewportSize = computeViewportSize();
+    
+    return m_viewportSize;
+}
+
+std::optional<FloatSize> SVGLengthContext::computeViewportSize() const
+{
+    ASSERT(m_overriddenViewport.isZero());
+    ASSERT(m_context);
+
     // Root <svg> element lengths are resolved against the top level viewport.
-    if (m_context->isOutermostSVGSVGElement()) {
-        viewportSize = downcast<SVGSVGElement>(*m_context).currentViewportSize();
-        return true;
-    }
+    if (m_context->isOutermostSVGSVGElement())
+        return downcast<SVGSVGElement>(*m_context).currentViewportSize();
 
     // Take size from nearest viewport element.
     RefPtr viewportElement = m_context->viewportElement();
     if (!is<SVGSVGElement>(viewportElement))
-        return false;
+        return std::nullopt;
 
     const SVGSVGElement& svg = downcast<SVGSVGElement>(*viewportElement);
-    viewportSize = svg.currentViewBoxRect().size();
+    auto viewportSize = svg.currentViewBoxRect().size();
     if (viewportSize.isEmpty())
         viewportSize = svg.currentViewportSize();
 
-    return true;
+    return viewportSize;
 }
 
 }

Modified: trunk/Source/WebCore/svg/SVGLengthContext.h (293988 => 293989)


--- trunk/Source/WebCore/svg/SVGLengthContext.h	2022-05-09 20:43:28 UTC (rev 293988)
+++ trunk/Source/WebCore/svg/SVGLengthContext.h	2022-05-09 20:56:14 UTC (rev 293989)
@@ -49,7 +49,7 @@
     ExceptionOr<float> convertValueToUserUnits(float, SVGLengthType, SVGLengthMode) const;
     ExceptionOr<float> convertValueFromUserUnits(float, SVGLengthType, SVGLengthMode) const;
 
-    bool determineViewport(FloatSize&) const;
+    std::optional<FloatSize> viewportSize() const;
 
 private:
     SVGLengthContext(const SVGElement*, const FloatRect& viewport);
@@ -63,8 +63,11 @@
     ExceptionOr<float> convertValueFromUserUnitsToEXS(float value) const;
     ExceptionOr<float> convertValueFromEXSToUserUnits(float value) const;
 
+    std::optional<FloatSize> computeViewportSize() const;
+
     const SVGElement* m_context;
-    FloatRect m_overriddenViewport;
+    FloatRect m_overriddenViewport; // Ideally this would be std::optional<FloatRect>, but some tests depend on the behavior of it being a zero rect.
+    mutable std::optional<FloatSize> m_viewportSize;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to