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