From 02a642b87b029b739a12ba8f8a7618f99cead45d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 5 Mar 2025 18:22:05 +0100 Subject: [PATCH] LibWeb: Prevent infinitely growing font size due to rem units in root A font-size with rem units need to resolve against the default font metrics for the root element, otherwise every time we compute style, the reference value for rem units grows. This fixes an issue where text on some web pages would grow every time there was a relayout. This was very noticeable on https://proton.me/ Fixes #339 --- Libraries/LibWeb/CSS/StyleComputer.cpp | 19 ++++++++++----- Libraries/LibWeb/CSS/StyleComputer.h | 4 +++- Libraries/LibWeb/DOM/Element.cpp | 2 +- .../font-size-rem-units-on-root-element.txt | 4 ++++ .../font-size-rem-units-on-root-element.html | 24 +++++++++++++++++++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/font-size-rem-units-on-root-element.txt create mode 100644 Tests/LibWeb/Text/input/css/font-size-rem-units-on-root-element.html diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 0c9f1a32cc9..552ccbd8261 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1877,7 +1877,7 @@ RefPtr StyleComputer::compute_font_for_style_values( auto length = value.as_length().length(); if (length.is_absolute() || length.is_relative()) { Length::FontMetrics font_metrics { font_size_in_px, font_pixel_metrics }; - return length.to_px(viewport_rect(), font_metrics, m_root_element_font_metrics); + return length.to_px(viewport_rect(), font_metrics, root_element_font_metrics_for_element(element)); } } return font_size_in_px; @@ -1942,7 +1942,7 @@ RefPtr StyleComputer::compute_font_for_style_values( Length::ResolutionContext const length_resolution_context { .viewport_rect = viewport_rect(), .font_metrics = Length::FontMetrics { parent_font_size, font_pixel_metrics }, - .root_font_metrics = m_root_element_font_metrics, + .root_font_metrics = root_element_font_metrics_for_element(element), }; Optional maybe_length; @@ -2128,10 +2128,10 @@ Gfx::Font const& StyleComputer::initial_font() const return ComputedProperties::font_fallback(false, false, 12); } -void StyleComputer::absolutize_values(ComputedProperties& style) const +void StyleComputer::absolutize_values(ComputedProperties& style, GC::Ptr element) const { Length::FontMetrics font_metrics { - m_root_element_font_metrics.font_size, + root_element_font_metrics_for_element(element).font_size, style.first_available_computed_font().pixel_metrics() }; @@ -2359,7 +2359,7 @@ GC::Ref StyleComputer::create_document_style() const compute_math_depth(style, nullptr, {}); compute_font(style, nullptr, {}); compute_defaulted_values(style, nullptr, {}); - absolutize_values(style); + absolutize_values(style, nullptr); style->set_property(CSS::PropertyID::Width, CSS::LengthStyleValue::create(CSS::Length::make_px(viewport_rect().width()))); style->set_property(CSS::PropertyID::Height, CSS::LengthStyleValue::create(CSS::Length::make_px(viewport_rect().height()))); style->set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Block))); @@ -2644,7 +2644,7 @@ GC::Ref StyleComputer::compute_properties(DOM::Element& elem compute_font(computed_style, &element, pseudo_element); // 4. Absolutize values, turning font/viewport relative lengths into absolute lengths - absolutize_values(computed_style); + absolutize_values(computed_style, element); // 5. Default the values, applying inheritance and 'initial' as needed compute_defaulted_values(computed_style, &element, pseudo_element); @@ -3267,4 +3267,11 @@ void RuleCache::for_each_matching_rules(DOM::Element const& element, Optional element) const +{ + if (element && element->document().document_element() == element) + return m_default_font_metrics; + return m_root_element_font_metrics; +} + } diff --git a/Libraries/LibWeb/CSS/StyleComputer.h b/Libraries/LibWeb/CSS/StyleComputer.h index fcedf1ccc3d..972114c664e 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Libraries/LibWeb/CSS/StyleComputer.h @@ -200,7 +200,7 @@ public: [[nodiscard]] GC::Ref compute_properties(DOM::Element&, Optional, CascadedProperties&) const; - void absolutize_values(ComputedProperties&) const; + void absolutize_values(ComputedProperties&, GC::Ptr) const; void compute_font(ComputedProperties&, DOM::Element const*, Optional) const; [[nodiscard]] inline bool should_reject_with_ancestor_filter(Selector const&) const; @@ -303,6 +303,8 @@ private: using FontLoaderList = Vector>; HashMap m_loaded_fonts; + [[nodiscard]] Length::FontMetrics const& root_element_font_metrics_for_element(GC::Ptr) const; + Length::FontMetrics m_default_font_metrics; Length::FontMetrics m_root_element_font_metrics; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 6b719a19e3c..2c7b85805a7 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -631,7 +631,7 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style() return invalidation; document().style_computer().compute_font(*computed_properties, this, {}); - document().style_computer().absolutize_values(*computed_properties); + document().style_computer().absolutize_values(*computed_properties, this); for (auto [property_id, old_value] : old_values_with_relative_units) { auto new_value = computed_properties->maybe_null_property(static_cast(property_id)); diff --git a/Tests/LibWeb/Text/expected/css/font-size-rem-units-on-root-element.txt b/Tests/LibWeb/Text/expected/css/font-size-rem-units-on-root-element.txt new file mode 100644 index 00000000000..61d49eff1e9 --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/font-size-rem-units-on-root-element.txt @@ -0,0 +1,4 @@ +68.6875px +68.6875px +68.6875px +68.6875px diff --git a/Tests/LibWeb/Text/input/css/font-size-rem-units-on-root-element.html b/Tests/LibWeb/Text/input/css/font-size-rem-units-on-root-element.html new file mode 100644 index 00000000000..4a8d30c05b2 --- /dev/null +++ b/Tests/LibWeb/Text/input/css/font-size-rem-units-on-root-element.html @@ -0,0 +1,24 @@ + +
WHF :^)
+ +