Przeglądaj źródła

LibWeb: Resolve CSS variables if present in SVG presentation attributes

SVG presentation attributes are parsed as CSS values, so we also need to
handle CSS variable expansion when handling them.

This (roughly) matches the behavior of other engines. It's also used on
the web, for example on https://stripe.com/ :^)
Andreas Kling 2 lat temu
rodzic
commit
71d5dc510e

+ 7 - 0
Tests/LibWeb/Layout/expected/svg/svg-with-css-variable-in-presentation-hint.txt

@@ -0,0 +1,7 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x118 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x102 children: inline
+      line 0 width: 102, height: 102, bottom: 102, baseline: 60
+        frag 0 from SVGSVGBox start: 0, length: 0, rect: [9,9 100x100]
+      SVGSVGBox <svg> at (9,9) content-size 100x100 [SVG] children: not-inline
+        SVGGeometryBox <rect> at (29,29) content-size 60x60 children: not-inline

+ 10 - 0
Tests/LibWeb/Layout/input/svg/svg-with-css-variable-in-presentation-hint.html

@@ -0,0 +1,10 @@
+<!doctype html><style>
+    :root {
+        --huge: 5px;
+    }
+    svg {
+        width: 100px;
+        height: 100px;
+        border: 1px solid black;
+    }
+</style><svg viewBox="0 0 10 10"><rect x=4.5 y=4.5 width=1 height=1 stroke="green" stroke-width="var(--huge)" />

+ 15 - 1
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -973,9 +973,23 @@ ErrorOr<void> StyleComputer::compute_cascaded_values(StyleProperties& style, DOM
     // FIXME: Normal user declarations
 
     // Author presentational hints (NOTE: The spec doesn't say exactly how to prioritize these.)
-    if (!pseudo_element.has_value())
+    if (!pseudo_element.has_value()) {
         element.apply_presentational_hints(style);
 
+        // SVG presentation attributes are parsed as CSS values, so we need to handle potential custom properties here.
+        if (element.is_svg_element()) {
+            // FIXME: This is not very efficient, we should only resolve the custom properties that are actually used.
+            for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) {
+                auto property_id = (CSS::PropertyID)i;
+                auto& property = style.m_property_values[i];
+                if (property && property->is_unresolved()) {
+                    if (auto resolved = resolve_unresolved_style_value(element, pseudo_element, property_id, property->as_unresolved()))
+                        property = resolved.release_nonnull();
+                }
+            }
+        }
+    }
+
     // Normal author declarations
     cascade_declarations(style, element, pseudo_element, matching_rule_set.author_rules, CascadeOrigin::Author, Important::No);