Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ set(SOURCES
CSS/EdgeRect.cpp
CSS/Fetch.cpp
CSS/Flex.cpp
CSS/FontComputer.cpp
CSS/FontFace.cpp
CSS/FontFaceSet.cpp
CSS/Frequency.cpp
Expand Down
5 changes: 3 additions & 2 deletions Libraries/LibWeb/CSS/CSSStyleSheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/FontComputer.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleComputer.h>
#include <LibWeb/CSS/StyleSheetList.h>
Expand Down Expand Up @@ -325,7 +326,7 @@ void CSSStyleSheet::add_owning_document_or_shadow_root(DOM::Node& document_or_sh
// All owning documents or shadow roots must be part of the same document so we only need to load this style
// sheet's fonts against the document of the first
if (this->owning_documents_or_shadow_roots().size() == 1)
document_or_shadow_root.document().style_computer().load_fonts_from_sheet(*this);
document_or_shadow_root.document().font_computer().load_fonts_from_sheet(*this);

for (auto const& import_rule : m_import_rules) {
if (import_rule->loaded_style_sheet())
Expand All @@ -340,7 +341,7 @@ void CSSStyleSheet::remove_owning_document_or_shadow_root(DOM::Node& document_or
// All owning documents or shadow roots must be part of the same document so we only need to unload this style
// sheet's fonts once we have none remaining.
if (this->owning_documents_or_shadow_roots().size() == 0)
document_or_shadow_root.document().style_computer().unload_fonts_from_sheet(*this);
document_or_shadow_root.document().font_computer().unload_fonts_from_sheet(*this);

for (auto const& import_rule : m_import_rules) {
if (import_rule->loaded_style_sheet())
Expand Down
50 changes: 46 additions & 4 deletions Libraries/LibWeb/CSS/ComputedProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <LibGC/CellAllocator.h>
#include <LibWeb/CSS/Clip.h>
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/FontComputer.h>
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
Expand Down Expand Up @@ -47,6 +48,21 @@ namespace Web::CSS {

GC_DEFINE_ALLOCATOR(ComputedProperties);

static HashTable<PropertyID> font_affecting_properties()
{
static HashTable<PropertyID> font_affecting_properties;
if (font_affecting_properties.is_empty()) {
font_affecting_properties.set(PropertyID::FontFamily);
font_affecting_properties.set(PropertyID::FontSize);
font_affecting_properties.set(PropertyID::FontStyle);
font_affecting_properties.set(PropertyID::FontWeight);
font_affecting_properties.set(PropertyID::FontWidth);
font_affecting_properties.set(PropertyID::FontVariationSettings);
}

return font_affecting_properties;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a HashTable for this fixed set of properties? I suspect first_is_one_of(property_id, ...) is just as fast when dealing with a small set, and does not allocate.


ComputedProperties::ComputedProperties() = default;

ComputedProperties::~ComputedProperties() = default;
Expand Down Expand Up @@ -128,6 +144,9 @@ void ComputedProperties::set_property_without_modifying_flags(PropertyID id, Non
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 (font_affecting_properties().contains(id))
clear_computed_font_list_cache();
}

void ComputedProperties::revert_property(PropertyID id, ComputedProperties const& style_for_revert)
Expand All @@ -153,6 +172,9 @@ void ComputedProperties::set_animated_property(PropertyID id, NonnullRefPtr<Styl
{
m_animated_property_values.set(id, move(value));
set_animated_property_inherited(id, inherited);

if (font_affecting_properties().contains(id))
clear_computed_font_list_cache();
}

void ComputedProperties::remove_animated_property(PropertyID id)
Expand All @@ -175,7 +197,7 @@ StyleValue const& ComputedProperties::property(PropertyID property_id, WithAnima
return *animated_value.value();
}

// By the time we call this method, all properties have values assigned.
// By the time we call this method, the property should have been assigned
return *m_property_values[to_underlying(property_id) - to_underlying(first_longhand_property_id)];
}

Expand Down Expand Up @@ -1901,7 +1923,7 @@ HashMap<StringView, u8> ComputedProperties::font_feature_settings() const
return {};
}

Optional<HashMap<FlyString, NumberOrCalculated>> ComputedProperties::font_variation_settings() const
HashMap<FlyString, double> ComputedProperties::font_variation_settings() const
{
auto const& value = property(PropertyID::FontVariationSettings);

Expand All @@ -1910,7 +1932,7 @@ Optional<HashMap<FlyString, NumberOrCalculated>> ComputedProperties::font_variat

if (value.is_value_list()) {
auto const& axis_tags = value.as_value_list().values();
HashMap<FlyString, NumberOrCalculated> result;
HashMap<FlyString, double> result;
result.ensure_capacity(axis_tags.size());
for (auto const& tag_value : axis_tags) {
auto const& axis_tag = tag_value->as_open_type_tagged();
Expand All @@ -1919,7 +1941,7 @@ Optional<HashMap<FlyString, NumberOrCalculated>> ComputedProperties::font_variat
result.set(axis_tag.tag(), axis_tag.value()->as_number().number());
} else {
VERIFY(axis_tag.value()->is_calculated());
result.set(axis_tag.tag(), NumberOrCalculated { axis_tag.value()->as_calculated() });
result.set(axis_tag.tag(), axis_tag.value()->as_calculated().resolve_number({}).value());
}
}
return result;
Expand Down Expand Up @@ -2517,6 +2539,26 @@ WillChange ComputedProperties::will_change() const
return WillChange::make_auto();
}

ValueComparingNonnullRefPtr<Gfx::FontCascadeList const> ComputedProperties::computed_font_list(FontComputer const& font_computer) const
{
if (!m_cached_computed_font_list) {
const_cast<ComputedProperties*>(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<Gfx::Font const> 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<ComputedProperties*>(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();
Expand Down
34 changes: 12 additions & 22 deletions Libraries/LibWeb/CSS/ComputedProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class WEB_API ComputedProperties final : public JS::Cell {
FontKerning font_kerning() const;
Optional<FlyString> font_language_override() const;
HashMap<StringView, u8> font_feature_settings() const;
Optional<HashMap<FlyString, NumberOrCalculated>> font_variation_settings() const;
HashMap<FlyString, double> font_variation_settings() const;
GridTrackSizeList grid_auto_columns() const;
GridTrackSizeList grid_auto_rows() const;
GridTrackSizeList grid_template_columns() const;
Expand Down Expand Up @@ -228,25 +228,9 @@ class WEB_API ComputedProperties final : public JS::Cell {

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<Gfx::FontCascadeList const> 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<Gfx::FontCascadeList const> cached_computed_font_list() const { return m_cached_computed_font_list; }
ValueComparingNonnullRefPtr<Gfx::FontCascadeList const> computed_font_list(FontComputer const&) const;
ValueComparingNonnullRefPtr<Gfx::Font const> first_available_computed_font(FontComputer const&) const;

[[nodiscard]] CSSPixels line_height() const;
[[nodiscard]] CSSPixels font_size() const;
Expand Down Expand Up @@ -300,8 +284,14 @@ class WEB_API ComputedProperties final : public JS::Cell {
Display m_display_before_box_type_transformation { InitialValues::display() };

int m_math_depth { InitialValues::math_depth() };
RefPtr<Gfx::FontCascadeList const> m_font_list;
RefPtr<Gfx::Font const> m_first_available_computed_font;

RefPtr<Gfx::FontCascadeList const> m_cached_computed_font_list;
RefPtr<Gfx::Font const> 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<CSSPixels> m_line_height;

Expand Down
6 changes: 3 additions & 3 deletions Libraries/LibWeb/CSS/ComputedValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ class ComputedValues {
double font_weight() const { return m_inherited.font_weight; }
Gfx::ShapeFeatures font_features() const { return m_inherited.font_features; }
Optional<FlyString> font_language_override() const { return m_inherited.font_language_override; }
Optional<HashMap<FlyString, NumberOrCalculated>> font_variation_settings() const { return m_inherited.font_variation_settings; }
HashMap<FlyString, double> font_variation_settings() const { return m_inherited.font_variation_settings; }
CSSPixels line_height() const { return m_inherited.line_height; }
Time transition_delay() const { return m_noninherited.transition_delay; }

Expand Down Expand Up @@ -682,7 +682,7 @@ class ComputedValues {
double font_weight { InitialValues::font_weight() };
Gfx::ShapeFeatures font_features { InitialValues::font_features() };
Optional<FlyString> font_language_override;
Optional<HashMap<FlyString, NumberOrCalculated>> font_variation_settings;
HashMap<FlyString, double> font_variation_settings;
CSSPixels line_height { InitialValues::line_height() };
BorderCollapse border_collapse { InitialValues::border_collapse() };
EmptyCells empty_cells { InitialValues::empty_cells() };
Expand Down Expand Up @@ -887,7 +887,7 @@ class MutableComputedValues final : public ComputedValues {
void set_font_weight(double font_weight) { m_inherited.font_weight = font_weight; }
void set_font_features(Gfx::ShapeFeatures font_features) { m_inherited.font_features = move(font_features); }
void set_font_language_override(Optional<FlyString> font_language_override) { m_inherited.font_language_override = move(font_language_override); }
void set_font_variation_settings(Optional<HashMap<FlyString, NumberOrCalculated>> value) { m_inherited.font_variation_settings = move(value); }
void set_font_variation_settings(HashMap<FlyString, double> value) { m_inherited.font_variation_settings = move(value); }
void set_line_height(CSSPixels line_height) { m_inherited.line_height = line_height; }
void set_border_spacing_horizontal(Length border_spacing_horizontal) { m_inherited.border_spacing_horizontal = move(border_spacing_horizontal); }
void set_border_spacing_vertical(Length border_spacing_vertical) { m_inherited.border_spacing_vertical = move(border_spacing_vertical); }
Expand Down
Loading
Loading