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/ :^)
This commit is contained in:
Andreas Kling 2023-05-23 18:14:47 +02:00
parent dd19f61538
commit 71d5dc510e
3 changed files with 32 additions and 1 deletions

View file

@ -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

View file

@ -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)" />

View file

@ -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);