Переглянути джерело

LibWeb: Resolve percentages in calc() for font-size

Fixes crashing on https://react.dev/
Aliaksandr Kalenik 1 рік тому
батько
коміт
28c9015bd8

+ 17 - 0
Tests/LibWeb/Layout/expected/calc-font-size-with-percentages.txt

@@ -0,0 +1,17 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x105.21875 children: not-inline
+      BlockContainer <div.test> at (8,8) content-size 784x105.21875 children: inline
+        line 0 width: 500.8125, height: 52.40625, bottom: 52.40625, baseline: 40.59375
+          frag 0 from TextNode start: 0, length: 20, rect: [8,8 500.8125x52.40625]
+            "i resolved enough of"
+        line 1 width: 406.40625, height: 52.8125, bottom: 105.21875, baseline: 40.59375
+          frag 0 from TextNode start: 21, length: 16, rect: [8,60 406.40625x52.40625]
+            "percentages, no?"
+        TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x105.21875]
+      PaintableWithLines (BlockContainer<DIV>.test) [8,8 784x105.21875]
+        TextPaintable (TextNode<#text>)

+ 5 - 0
Tests/LibWeb/Layout/input/calc-font-size-with-percentages.html

@@ -0,0 +1,5 @@
+<style>
+    .test {
+        font-size: calc(1em + 200%);
+    }
+</style><div class="test">i resolved enough of percentages, no?</div>

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

@@ -1764,7 +1764,11 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
         } else if (font_size.is_length()) {
         } else if (font_size.is_length()) {
             maybe_length = font_size.as_length().length();
             maybe_length = font_size.as_length().length();
         } else if (font_size.is_calculated()) {
         } else if (font_size.is_calculated()) {
-            maybe_length = font_size.as_calculated().resolve_length(length_resolution_context);
+            if (font_size.as_calculated().contains_percentage()) {
+                maybe_length = font_size.as_calculated().resolve_length_percentage(length_resolution_context, Length::make_px(parent_font_size()));
+            } else {
+                maybe_length = font_size.as_calculated().resolve_length(length_resolution_context);
+            }
         }
         }
         if (maybe_length.has_value()) {
         if (maybe_length.has_value()) {
             font_size_in_px = maybe_length.value().to_px(length_resolution_context);
             font_size_in_px = maybe_length.value().to_px(length_resolution_context);

+ 8 - 14
Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp

@@ -2371,30 +2371,24 @@ Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout
 
 
 Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, Length const& percentage_basis) const
 Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, Length const& percentage_basis) const
 {
 {
-    auto result = m_calculation->resolve(Length::ResolutionContext::for_layout_node(layout_node), percentage_basis);
-
-    return result.value().visit(
-        [&](Length const& length) -> Optional<Length> {
-            return length;
-        },
-        [&](Percentage const& percentage) -> Optional<Length> {
-            return percentage_basis.percentage_of(percentage);
-        },
-        [&](auto const&) -> Optional<Length> {
-            return {};
-        });
+    return resolve_length_percentage(Length::ResolutionContext::for_layout_node(layout_node), percentage_basis);
 }
 }
 
 
 Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, CSSPixels percentage_basis) const
 Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, CSSPixels percentage_basis) const
 {
 {
-    auto result = m_calculation->resolve(Length::ResolutionContext::for_layout_node(layout_node), Length::make_px(percentage_basis));
+    return resolve_length_percentage(Length::ResolutionContext::for_layout_node(layout_node), Length::make_px(percentage_basis));
+}
+
+Optional<Length> CalculatedStyleValue::resolve_length_percentage(Length::ResolutionContext const& resolution_context, Length const& percentage_basis) const
+{
+    auto result = m_calculation->resolve(resolution_context, percentage_basis);
 
 
     return result.value().visit(
     return result.value().visit(
         [&](Length const& length) -> Optional<Length> {
         [&](Length const& length) -> Optional<Length> {
             return length;
             return length;
         },
         },
         [&](Percentage const& percentage) -> Optional<Length> {
         [&](Percentage const& percentage) -> Optional<Length> {
-            return Length::make_px(CSSPixels(percentage.value() * percentage_basis) / 100);
+            return percentage_basis.percentage_of(percentage);
         },
         },
         [&](auto const&) -> Optional<Length> {
         [&](auto const&) -> Optional<Length> {
             return {};
             return {};

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h

@@ -95,6 +95,7 @@ public:
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const;
+    Optional<Length> resolve_length_percentage(Length::ResolutionContext const&, Length const& percentage_basis) const;
 
 
     bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); }
     bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); }
     Optional<Percentage> resolve_percentage() const;
     Optional<Percentage> resolve_percentage() const;