diff --git a/Libraries/LibWeb/CSS/ComputedProperties.cpp b/Libraries/LibWeb/CSS/ComputedProperties.cpp index c35ec2db24a..5e35df81a3b 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.cpp +++ b/Libraries/LibWeb/CSS/ComputedProperties.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -142,11 +143,19 @@ void ComputedProperties::set_property(PropertyID id, NonnullRefPtr value) { VERIFY(id >= first_longhand_property_id && id <= last_longhand_property_id); m_property_values[to_underlying(id) - to_underlying(first_longhand_property_id)] = move(value); + + if (property_affects_computed_font_list(id)) + clear_computed_font_list_cache(); } void ComputedProperties::revert_property(PropertyID id, ComputedProperties const& style_for_revert) @@ -173,6 +182,9 @@ void ComputedProperties::set_animated_property(PropertyID id, NonnullRefPtr ComputedProperties::computed_font_list(FontComputer const& font_computer) const +{ + if (!m_cached_computed_font_list) { + const_cast(this)->m_cached_computed_font_list = font_computer.compute_font_for_style_values(property(PropertyID::FontFamily), font_size(), font_slope(), font_weight(), font_width(), font_variation_settings()); + VERIFY(!m_cached_computed_font_list->is_empty()); + } + + return *m_cached_computed_font_list; +} + +ValueComparingNonnullRefPtr ComputedProperties::first_available_computed_font(FontComputer const& font_computer) const +{ + if (!m_cached_first_available_computed_font) { + // https://drafts.csswg.org/css-fonts/#first-available-font + // First font for which the character U+0020 (space) is not excluded by a unicode-range + const_cast(this)->m_cached_first_available_computed_font = computed_font_list(font_computer)->font_for_code_point(' '); + } + + return *m_cached_first_available_computed_font; +} + CSSPixels ComputedProperties::font_size() const { return property(PropertyID::FontSize).as_length().length().absolute_length_to_px(); diff --git a/Libraries/LibWeb/CSS/ComputedProperties.h b/Libraries/LibWeb/CSS/ComputedProperties.h index 23bcbf4234e..2d1bb266ce9 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.h +++ b/Libraries/LibWeb/CSS/ComputedProperties.h @@ -234,25 +234,9 @@ public: WillChange will_change() const; - Gfx::FontCascadeList const& computed_font_list() const - { - VERIFY(m_font_list); - return *m_font_list; - } - - Gfx::Font const& first_available_computed_font() const - { - VERIFY(m_first_available_computed_font); - return *m_first_available_computed_font; - } - - void set_computed_font_list(NonnullRefPtr font_list) - { - m_font_list = move(font_list); - // https://drafts.csswg.org/css-fonts/#first-available-font - // First font for which the character U+0020 (space) is not excluded by a unicode-range - m_first_available_computed_font = m_font_list->font_for_code_point(' '); - } + ValueComparingRefPtr cached_computed_font_list() const { return m_cached_computed_font_list; } + ValueComparingNonnullRefPtr computed_font_list(FontComputer const&) const; + ValueComparingNonnullRefPtr first_available_computed_font(FontComputer const&) const; [[nodiscard]] CSSPixels line_height() const; [[nodiscard]] CSSPixels font_size() const; @@ -306,8 +290,14 @@ private: Display m_display_before_box_type_transformation { InitialValues::display() }; int m_math_depth { InitialValues::math_depth() }; - RefPtr m_font_list; - RefPtr m_first_available_computed_font; + + RefPtr m_cached_computed_font_list; + RefPtr m_cached_first_available_computed_font; + void clear_computed_font_list_cache() + { + m_cached_computed_font_list = nullptr; + m_cached_first_available_computed_font = nullptr; + } Optional m_line_height; diff --git a/Libraries/LibWeb/CSS/FontComputer.cpp b/Libraries/LibWeb/CSS/FontComputer.cpp index 689f1a849ad..a514187c56a 100644 --- a/Libraries/LibWeb/CSS/FontComputer.cpp +++ b/Libraries/LibWeb/CSS/FontComputer.cpp @@ -354,7 +354,7 @@ RefPtr FontComputer::font_matching_algorithm_impl(Fl return {}; } -RefPtr FontComputer::compute_font_for_style_values(StyleValue const& font_family, CSSPixels const& font_size, int slope, double font_weight, Percentage const& font_width, HashMap const& font_variation_settings) const +NonnullRefPtr FontComputer::compute_font_for_style_values(StyleValue const& font_family, CSSPixels const& font_size, int slope, double font_weight, Percentage const& font_width, HashMap const& font_variation_settings) const { // FIXME: We round to int here as that is what is expected by our font infrastructure below auto width = round_to(font_width.value()); diff --git a/Libraries/LibWeb/CSS/FontComputer.h b/Libraries/LibWeb/CSS/FontComputer.h index bc4534d3420..3b32e483f6b 100644 --- a/Libraries/LibWeb/CSS/FontComputer.h +++ b/Libraries/LibWeb/CSS/FontComputer.h @@ -100,7 +100,7 @@ public: void load_fonts_from_sheet(CSSStyleSheet&); void unload_fonts_from_sheet(CSSStyleSheet&); - RefPtr compute_font_for_style_values(StyleValue const& font_family, CSSPixels const& font_size, int font_slope, double font_weight, Percentage const& font_width, HashMap const& font_variation_settings) const; + NonnullRefPtr compute_font_for_style_values(StyleValue const& font_family, CSSPixels const& font_size, int font_slope, double font_weight, Percentage const& font_width, HashMap const& font_variation_settings) const; size_t number_of_css_font_faces_with_loading_in_progress() const; diff --git a/Libraries/LibWeb/CSS/Length.cpp b/Libraries/LibWeb/CSS/Length.cpp index edf482fc55f..82feee9dbc7 100644 --- a/Libraries/LibWeb/CSS/Length.cpp +++ b/Libraries/LibWeb/CSS/Length.cpp @@ -132,8 +132,8 @@ Length::ResolutionContext Length::ResolutionContext::for_element(DOM::AbstractEl return Length::ResolutionContext { .viewport_rect = element.element().navigable()->viewport_rect(), - .font_metrics = { element.computed_properties()->font_size(), element.computed_properties()->first_available_computed_font().pixel_metrics(), element.computed_properties()->line_height() }, - .root_font_metrics = { root_element->computed_properties()->font_size(), root_element->computed_properties()->first_available_computed_font().pixel_metrics(), element.computed_properties()->line_height() } + .font_metrics = { element.computed_properties()->font_size(), element.computed_properties()->first_available_computed_font(element.document().font_computer())->pixel_metrics(), element.computed_properties()->line_height() }, + .root_font_metrics = { root_element->computed_properties()->font_size(), root_element->computed_properties()->first_available_computed_font(element.document().font_computer())->pixel_metrics(), element.computed_properties()->line_height() } }; } diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 1fb958e4922..0a0111fc0ab 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -680,7 +680,7 @@ void StyleComputer::collect_animation_into(DOM::AbstractElement abstract_element Length::FontMetrics font_metrics { computed_properties.font_size(), - computed_properties.first_available_computed_font().pixel_metrics(), + computed_properties.first_available_computed_font(document().font_computer())->pixel_metrics(), computed_properties.line_height() }; @@ -794,7 +794,7 @@ void StyleComputer::collect_animation_into(DOM::AbstractElement abstract_element .viewport_rect = viewport_rect(), .font_metrics = { computed_properties.font_size(), - computed_properties.first_available_computed_font().pixel_metrics(), + computed_properties.first_available_computed_font(document().font_computer())->pixel_metrics(), inheritance_parent_has_computed_properties ? inheritance_parent->computed_properties()->line_height() : InitialValues::line_height() }, .root_font_metrics = m_root_element_font_metrics }, .abstract_element = abstract_element @@ -1417,7 +1417,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(ComputedP { auto const& root_value = style.property(CSS::PropertyID::FontSize); - auto font_pixel_metrics = style.first_available_computed_font().pixel_metrics(); + auto font_pixel_metrics = style.first_available_computed_font(document().font_computer())->pixel_metrics(); Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, InitialValues::line_height() }; font_metrics.font_size = root_value.as_length().length().to_px(viewport_rect(), font_metrics, font_metrics); font_metrics.line_height = style.line_height(); @@ -1527,15 +1527,7 @@ void StyleComputer::compute_font(ComputedProperties& style, Optionalis_empty()); - - RefPtr const found_font = font_list->first(); - - style.set_computed_font_list(*font_list); + RefPtr const found_font = style.first_available_computed_font(m_document->font_computer()); Length::FontMetrics line_height_font_metrics { style.font_size(), @@ -1606,7 +1598,7 @@ void StyleComputer::compute_property_values(ComputedProperties& style, Optional< { Length::FontMetrics font_metrics { style.font_size(), - style.first_available_computed_font().pixel_metrics(), + style.first_available_computed_font(document().font_computer())->pixel_metrics(), style.line_height() }; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 366dc7b80ee..ed8e2c171ac 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -696,7 +696,7 @@ static CSS::RequiredInvalidationAfterStyleChange compute_required_invalidation(C { CSS::RequiredInvalidationAfterStyleChange invalidation; - if (!old_style.computed_font_list().equals(new_style.computed_font_list())) + if (old_style.cached_computed_font_list() != new_style.cached_computed_font_list()) invalidation.relayout = true; for (auto i = to_underlying(CSS::first_longhand_property_id); i <= to_underlying(CSS::last_longhand_property_id); ++i) { diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index ca083de0542..863551ed784 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -152,7 +152,7 @@ void HTMLInputElement::adjust_computed_style(CSS::ComputedProperties& style) // NOTE: Other browsers apply a minimum height of a single line's line-height to single-line input elements. if (is_single_line() && style.property(CSS::PropertyID::Height).has_auto()) { auto current_line_height = style.line_height().to_double(); - auto minimum_line_height = style.first_available_computed_font().pixel_size() * CSS::ComputedProperties::normal_line_height_scale; + auto minimum_line_height = style.first_available_computed_font(document().font_computer())->pixel_size() * CSS::ComputedProperties::normal_line_height_scale; // FIXME: Instead of overriding line-height, we should set height here instead. if (current_line_height < minimum_line_height) diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 4b25e5303e2..861150b0d0a 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -397,7 +397,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) // NOTE: We have to be careful that font-related properties get set in the right order. // m_font is used by Length::to_px() when resolving sizes against this layout node. // That's why it has to be set before everything else. - computed_values.set_font_list(computed_style.computed_font_list()); + computed_values.set_font_list(computed_style.computed_font_list(document().font_computer())); computed_values.set_font_size(computed_style.font_size()); computed_values.set_font_weight(computed_style.font_weight()); computed_values.set_line_height(computed_style.line_height()); diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index d14a8e0dede..031db584965 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -540,7 +540,7 @@ void ConnectionFromClient::inspect_dom_node(u64 page_id, WebView::DOMNodePropert auto serialize_used_fonts = [&]() { JsonArray serialized; - properties->computed_font_list().for_each_font_entry([&](Gfx::FontCascadeList::Entry const& entry) { + properties->computed_font_list(node->document().font_computer())->for_each_font_entry([&](Gfx::FontCascadeList::Entry const& entry) { auto const& font = *entry.font; JsonObject font_object; diff --git a/Tests/LibWeb/Ref/expected/css/animated-font-size-ref.html b/Tests/LibWeb/Ref/expected/css/animated-font-size-ref.html new file mode 100644 index 00000000000..87d37689985 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/css/animated-font-size-ref.html @@ -0,0 +1,2 @@ + +
TEST
diff --git a/Tests/LibWeb/Ref/input/css/animated-font-size.html b/Tests/LibWeb/Ref/input/css/animated-font-size.html new file mode 100644 index 00000000000..36c6ab6c0da --- /dev/null +++ b/Tests/LibWeb/Ref/input/css/animated-font-size.html @@ -0,0 +1,9 @@ + + +
TEST
+