瀏覽代碼

LibWeb: Resolve SVG "scaled viewport size" without triggering layout

Percentage stroke widths are resolved against the scaled viewport size
which we were retrieving by calling client_width() and client_height()
on the element. Now that those accessors may trigger layout, this means
that we can't use them from the stroke_width() getter, which is itself
used *from within* layout.
Andreas Kling 3 年之前
父節點
當前提交
b5faeb7840
共有 1 個文件被更改,包括 11 次插入1 次删除
  1. 11 1
      Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp

+ 11 - 1
Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp

@@ -6,7 +6,9 @@
  */
 
 #include <LibWeb/CSS/Parser/Parser.h>
+#include <LibWeb/Layout/Node.h>
 #include <LibWeb/SVG/SVGGraphicsElement.h>
+#include <LibWeb/SVG/SVGSVGElement.h>
 
 namespace Web::SVG {
 
@@ -64,7 +66,15 @@ Optional<float> SVGGraphicsElement::stroke_width() const
     if (auto width = layout_node()->computed_values().stroke_width(); width.has_value()) {
         // Resolved relative to the "Scaled viewport size": https://www.w3.org/TR/2017/WD-fill-stroke-3-20170413/#scaled-viewport-size
         // FIXME: This isn't right, but it's something.
-        auto scaled_viewport_size = CSS::Length::make_px((client_width() + client_height()) * 0.5f);
+        float viewport_width = 0;
+        float viewport_height = 0;
+        if (auto* svg_svg_element = first_ancestor_of_type<SVGSVGElement>()) {
+            if (auto* svg_svg_layout_node = svg_svg_element->layout_node()) {
+                viewport_width = svg_svg_layout_node->computed_values().width().value().resolved(*svg_svg_layout_node, { 0, CSS::Length::Type::Px }).to_px(*svg_svg_layout_node);
+                viewport_height = svg_svg_layout_node->computed_values().height().value().resolved(*svg_svg_layout_node, { 0, CSS::Length::Type::Px }).to_px(*svg_svg_layout_node);
+            }
+        }
+        auto scaled_viewport_size = CSS::Length::make_px((viewport_width + viewport_height) * 0.5f);
         return width->resolved(*layout_node(), scaled_viewport_size).to_px(*layout_node());
     }
     return {};