summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2023-05-08 10:28:21 +0200
committerAndreas Kling <kling@serenityos.org>2023-05-08 12:13:20 +0200
commit3f4de06fc2f0fbb52e0198bf786b1b0d5d3bd774 (patch)
tree3232f2d71710b3b32522f73e842e4567e5b8cea7
parent214eaebe73811ca197aaacd0dcdee1f894814e3c (diff)
downloadserenity-3f4de06fc2f0fbb52e0198bf786b1b0d5d3bd774.zip
LibWeb: Cache the root element font metrics when calculating them
The root element font metrics were getting queried again and again during style computation. Before this change we would do some work to recalculate them each time. This patch simply caches them in a StyleComputer member. Since style updates always start with the root element, we know that it'll be up-to-date by the time we look at any other element. Before this change, we were spending ~5% of CPU time on Google Groups in root_element_font_metrics().
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleComputer.cpp54
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleComputer.h5
2 files changed, 26 insertions, 33 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp
index ca0112ee5f..1bdf909f08 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp
@@ -63,6 +63,8 @@ namespace Web::CSS {
StyleComputer::StyleComputer(DOM::Document& document)
: m_document(document)
+ , m_default_font_metrics(16, Gfx::FontDatabase::default_font().pixel_metrics(), 16)
+ , m_root_element_font_metrics(m_default_font_metrics)
{
}
@@ -1053,24 +1055,14 @@ void StyleComputer::compute_defaulted_values(StyleProperties& style, DOM::Elemen
}
}
-Length::FontMetrics StyleComputer::root_element_font_metrics() const
+Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProperties const& style) const
{
- Length::FontMetrics const default_font_metrics { 16, Gfx::FontDatabase::default_font().pixel_metrics(), 16 };
+ auto root_value = style.property(CSS::PropertyID::FontSize);
- auto const* root_element = m_document->first_child_of_type<HTML::HTMLHtmlElement>();
- if (!root_element)
- return default_font_metrics;
-
- auto const* computed_root_style = root_element->computed_css_values();
- if (!computed_root_style)
- return default_font_metrics;
-
- auto root_value = computed_root_style->property(CSS::PropertyID::FontSize);
-
- auto font_pixel_metrics = computed_root_style->computed_font().pixel_metrics();
- Length::FontMetrics font_metrics { default_font_metrics.font_size, font_pixel_metrics, font_pixel_metrics.line_spacing() };
+ auto font_pixel_metrics = style.computed_font().pixel_metrics();
+ Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, font_pixel_metrics.line_spacing() };
font_metrics.font_size = root_value->to_length().to_px(viewport_rect(), font_metrics, font_metrics);
- font_metrics.line_height = computed_root_style->line_height(viewport_rect(), font_metrics, font_metrics);
+ font_metrics.line_height = style.line_height(viewport_rect(), font_metrics, font_metrics);
return font_metrics;
}
@@ -1218,8 +1210,6 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
font_size_in_px *= multiplier;
} else {
- auto root_font_metrics = root_element_font_metrics();
-
Gfx::FontPixelMetrics font_pixel_metrics;
if (parent_element && parent_element->computed_css_values())
font_pixel_metrics = parent_element->computed_css_values()->computed_font().pixel_metrics();
@@ -1235,7 +1225,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
auto parent_line_height = parent_or_root_element_line_height(parent_element, {});
if (length.is_absolute() || length.is_relative()) {
Length::FontMetrics font_metrics { font_size_in_px, font_pixel_metrics, parent_line_height };
- return length.to_px(viewport_rect(), font_metrics, root_font_metrics);
+ return length.to_px(viewport_rect(), font_metrics, m_root_element_font_metrics);
}
}
return font_size_in_px;
@@ -1256,7 +1246,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
if (maybe_length.has_value()) {
auto parent_line_height = parent_or_root_element_line_height(element, pseudo_element);
Length::FontMetrics font_metrics { parent_font_size(), font_pixel_metrics, parent_line_height };
- auto px = maybe_length.value().to_px(viewport_rect(), font_metrics, root_font_metrics).value();
+ auto px = maybe_length.value().to_px(viewport_rect(), font_metrics, m_root_element_font_metrics).value();
if (px != 0)
font_size_in_px = px;
}
@@ -1368,6 +1358,10 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
style.set_property(CSS::PropertyID::FontWeight, NumericStyleValue::create_integer(weight).release_value_but_fixme_should_propagate_errors());
style.set_computed_font(found_font.release_nonnull());
+
+ if (element && is<HTML::HTMLHtmlElement>(*element)) {
+ const_cast<StyleComputer&>(*this).m_root_element_font_metrics = calculate_root_element_font_metrics(style);
+ }
}
Gfx::Font const& StyleComputer::initial_font() const
@@ -1378,20 +1372,17 @@ Gfx::Font const& StyleComputer::initial_font() const
CSSPixels StyleComputer::parent_or_root_element_line_height(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element) const
{
- auto root_font_metrics = root_element_font_metrics();
auto* parent_element = element_to_inherit_style_from(element, pseudo_element);
if (!parent_element)
- return root_font_metrics.line_height;
- auto* computed_values = parent_element->computed_css_values();
- auto parent_font_pixel_metrics = parent_element->layout_node()
- ? parent_element->layout_node()->font().pixel_metrics()
- : Gfx::FontDatabase::default_font().pixel_metrics();
+ return m_root_element_font_metrics.line_height;
+ auto const* computed_values = parent_element->computed_css_values();
+ auto parent_font_pixel_metrics = computed_values->computed_font().pixel_metrics();
auto parent_font_size = computed_values->property(CSS::PropertyID::FontSize)->to_length();
// FIXME: Can the parent font size be non-absolute here?
- auto parent_font_size_value = parent_font_size.is_absolute() ? parent_font_size.absolute_length_to_px() : root_font_metrics.font_size;
+ auto parent_font_size_value = parent_font_size.is_absolute() ? parent_font_size.absolute_length_to_px() : m_root_element_font_metrics.font_size;
auto parent_parent_line_height = parent_or_root_element_line_height(parent_element, {});
Length::FontMetrics parent_font_metrics { parent_font_size_value, parent_font_pixel_metrics, parent_parent_line_height };
- return computed_values->line_height(viewport_rect(), parent_font_metrics, root_font_metrics);
+ return computed_values->line_height(viewport_rect(), parent_font_metrics, m_root_element_font_metrics);
}
ErrorOr<void> StyleComputer::absolutize_values(StyleProperties& style, DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element) const
@@ -1399,11 +1390,10 @@ ErrorOr<void> StyleComputer::absolutize_values(StyleProperties& style, DOM::Elem
auto parent_or_root_line_height = parent_or_root_element_line_height(element, pseudo_element);
auto font_pixel_metrics = style.computed_font().pixel_metrics();
- auto root_font_metrics = root_element_font_metrics();
- Length::FontMetrics font_metrics { root_font_metrics.font_size, font_pixel_metrics, parent_or_root_line_height };
+ Length::FontMetrics font_metrics { m_root_element_font_metrics.font_size, font_pixel_metrics, parent_or_root_line_height };
- auto font_size = style.property(CSS::PropertyID::FontSize)->to_length().to_px(viewport_rect(), font_metrics, root_font_metrics);
+ auto font_size = style.property(CSS::PropertyID::FontSize)->to_length().to_px(viewport_rect(), font_metrics, m_root_element_font_metrics);
font_metrics.font_size = font_size;
// NOTE: Percentage line-height values are relative to the font-size of the element.
@@ -1416,7 +1406,7 @@ ErrorOr<void> StyleComputer::absolutize_values(StyleProperties& style, DOM::Elem
Length::make_px(font_size * line_height_value_slot->as_percentage().percentage().as_fraction())));
}
- auto line_height = style.line_height(viewport_rect(), font_metrics, root_font_metrics);
+ auto line_height = style.line_height(viewport_rect(), font_metrics, m_root_element_font_metrics);
font_metrics.line_height = line_height;
// NOTE: line-height might be using lh which should be resolved against the parent line height (like we did here already)
@@ -1427,7 +1417,7 @@ ErrorOr<void> StyleComputer::absolutize_values(StyleProperties& style, DOM::Elem
auto& value_slot = style.m_property_values[i];
if (!value_slot)
continue;
- value_slot = TRY(value_slot->absolutized(viewport_rect(), font_metrics, root_font_metrics));
+ value_slot = TRY(value_slot->absolutized(viewport_rect(), font_metrics, m_root_element_font_metrics));
}
return {};
}
diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h
index 64e97ce00f..afdd7d96f4 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h
+++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h
@@ -102,7 +102,7 @@ private:
void for_each_stylesheet(CascadeOrigin, Callback) const;
CSSPixelRect viewport_rect() const;
- Length::FontMetrics root_element_font_metrics() const;
+ [[nodiscard]] Length::FontMetrics calculate_root_element_font_metrics(StyleProperties const&) const;
CSSPixels parent_or_root_element_line_height(DOM::Element const*, Optional<CSS::Selector::PseudoElement>) const;
struct MatchingRuleSet {
@@ -133,6 +133,9 @@ private:
class FontLoader;
HashMap<String, NonnullOwnPtr<FontLoader>> m_loaded_fonts;
+
+ Length::FontMetrics m_default_font_metrics;
+ Length::FontMetrics m_root_element_font_metrics;
};
}