diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index 643b8b7b66..99f8a06cf0 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES Filters/FastBoxBlurFilter.cpp Filters/LumaFilter.cpp Filters/StackBlurFilter.cpp + FontCascadeList.cpp Font/BitmapFont.cpp Font/Emoji.cpp Font/Font.cpp diff --git a/Userland/Libraries/LibGfx/FontCascadeList.cpp b/Userland/Libraries/LibGfx/FontCascadeList.cpp new file mode 100644 index 0000000000..1104492e10 --- /dev/null +++ b/Userland/Libraries/LibGfx/FontCascadeList.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Gfx { + +void FontCascadeList::add(NonnullRefPtr font) +{ + m_fonts.append({ move(font), {} }); +} + +void FontCascadeList::add(NonnullRefPtr font, Vector unicode_ranges) +{ + m_fonts.append({ move(font), move(unicode_ranges) }); +} + +void FontCascadeList::extend(FontCascadeList const& other) +{ + for (auto const& font : other.m_fonts) { + m_fonts.append({ font.font->clone(), font.unicode_ranges }); + } +} + +Gfx::Font const& FontCascadeList::font_for_code_point(u32 code_point) const +{ + for (auto const& entry : m_fonts) { + if (!entry.unicode_ranges.has_value()) + return entry.font; + if (!entry.font->contains_glyph(code_point)) + continue; + for (auto const& range : *entry.unicode_ranges) { + if (range.contains(code_point)) + return entry.font; + } + } + VERIFY_NOT_REACHED(); +} + +bool FontCascadeList::equals(FontCascadeList const& other) const +{ + if (m_fonts.size() != other.m_fonts.size()) + return false; + for (size_t i = 0; i < m_fonts.size(); ++i) { + if (m_fonts[i].font != other.m_fonts[i].font) + return false; + } + return true; +} + +} diff --git a/Userland/Libraries/LibGfx/FontCascadeList.h b/Userland/Libraries/LibGfx/FontCascadeList.h new file mode 100644 index 0000000000..e3f9dae62e --- /dev/null +++ b/Userland/Libraries/LibGfx/FontCascadeList.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Gfx { + +class FontCascadeList : public RefCounted { +public: + static NonnullRefPtr create() + { + return adopt_ref(*new FontCascadeList()); + } + + size_t size() const { return m_fonts.size(); } + bool is_empty() const { return m_fonts.is_empty(); } + Font const& first() const { return *m_fonts.first().font; } + + void add(NonnullRefPtr font); + void add(NonnullRefPtr font, Vector unicode_ranges); + + void extend(FontCascadeList const& other); + + Gfx::Font const& font_for_code_point(u32 code_point) const; + + bool equals(FontCascadeList const& other) const; + + struct Entry { + NonnullRefPtr font; + Optional> unicode_ranges; + }; + +private: + Vector m_fonts; +}; + +} diff --git a/Userland/Libraries/LibWeb/CSS/Length.cpp b/Userland/Libraries/LibWeb/CSS/Length.cpp index fc5f0bf681..ec4d571de0 100644 --- a/Userland/Libraries/LibWeb/CSS/Length.cpp +++ b/Userland/Libraries/LibWeb/CSS/Length.cpp @@ -138,8 +138,8 @@ Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Nod VERIFY(root_element->layout_node()); return Length::ResolutionContext { .viewport_rect = node.navigable()->viewport_rect(), - .font_metrics = { node.computed_values().font_size(), node.font().pixel_metrics(), node.line_height() }, - .root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() }, + .font_metrics = { node.computed_values().font_size(), node.first_available_font().pixel_metrics(), node.line_height() }, + .root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->first_available_font().pixel_metrics(), root_element->layout_node()->line_height() }, }; } @@ -169,12 +169,12 @@ CSSPixels Length::to_px(Layout::Node const& layout_node) const FontMetrics font_metrics { layout_node.computed_values().font_size(), - layout_node.font().pixel_metrics(), + layout_node.first_available_font().pixel_metrics(), layout_node.line_height() }; FontMetrics root_font_metrics { root_element->layout_node()->computed_values().font_size(), - root_element->layout_node()->font().pixel_metrics(), + root_element->layout_node()->first_available_font().pixel_metrics(), root_element->layout_node()->line_height() }; diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index e050af5197..234a49eae1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -91,15 +91,18 @@ StyleComputer::~StyleComputer() = default; class StyleComputer::FontLoader : public ResourceClient { public: - explicit FontLoader(StyleComputer& style_computer, FlyString family_name, Vector urls) + explicit FontLoader(StyleComputer& style_computer, FlyString family_name, Vector unicode_ranges, Vector urls) : m_style_computer(style_computer) , m_family_name(move(family_name)) + , m_unicode_ranges(move(unicode_ranges)) , m_urls(move(urls)) { } virtual ~FontLoader() override { } + Vector const& unicode_ranges() const { return m_unicode_ranges; } + virtual void resource_did_load() override { auto result = try_load_font(); @@ -183,6 +186,7 @@ private: StyleComputer& m_style_computer; FlyString m_family_name; + Vector m_unicode_ranges; RefPtr m_vector_font; Vector m_urls; @@ -191,14 +195,21 @@ private: struct StyleComputer::MatchingFontCandidate { FontFaceKey key; - Variant loader_or_typeface; + Variant loader_or_typeface; - [[nodiscard]] RefPtr font_with_point_size(float point_size) const + [[nodiscard]] RefPtr font_with_point_size(float point_size) const { - if (auto* loader = loader_or_typeface.get_pointer(); loader) { - return (*loader)->font_with_point_size(point_size); + RefPtr font_list = Gfx::FontCascadeList::create(); + if (auto* loader_list = loader_or_typeface.get_pointer(); loader_list) { + for (auto const& loader : **loader_list) { + if (auto font = loader->font_with_point_size(point_size); font) + font_list->add(*font, loader->unicode_ranges()); + } + return font_list; } - return loader_or_typeface.get()->get_font(point_size); + + font_list->add(*loader_or_typeface.get()->get_font(point_size)); + return font_list; } }; @@ -1529,7 +1540,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProp { auto root_value = style.property(CSS::PropertyID::FontSize); - auto font_pixel_metrics = style.computed_font().pixel_metrics(); + auto font_pixel_metrics = style.first_available_computed_font().pixel_metrics(); Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, CSSPixels::nearest_value_for(font_pixel_metrics.line_spacing()) }; font_metrics.font_size = root_value->as_length().length().to_px(viewport_rect(), font_metrics, font_metrics); font_metrics.line_height = style.line_height(viewport_rect(), font_metrics, font_metrics); @@ -1537,7 +1548,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProp return font_metrics; } -RefPtr StyleComputer::find_matching_font_weight_ascending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive) +RefPtr StyleComputer::find_matching_font_weight_ascending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive) { using Fn = AK::Function; auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight >= target_weight; }) @@ -1550,7 +1561,7 @@ RefPtr StyleComputer::find_matching_font_weight_ascending(Vecto return {}; } -RefPtr StyleComputer::find_matching_font_weight_descending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive) +RefPtr StyleComputer::find_matching_font_weight_descending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive) { using Fn = AK::Function; auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight <= target_weight; }) @@ -1565,14 +1576,14 @@ RefPtr StyleComputer::find_matching_font_weight_descending(Vect // Partial implementation of the font-matching algorithm: https://www.w3.org/TR/css-fonts-4/#font-matching-algorithm // FIXME: This should be replaced by the full CSS font selection algorithm. -RefPtr StyleComputer::font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const +RefPtr StyleComputer::font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const { // If a font family match occurs, the user agent assembles the set of font faces in that family and then // narrows the set to a single face using other font properties in the order given below. Vector matching_family_fonts; for (auto const& font_key_and_loader : m_loaded_fonts) { if (font_key_and_loader.key.family_name.equals_ignoring_ascii_case(key.family_name)) - matching_family_fonts.empend(font_key_and_loader.key, font_key_and_loader.value.ptr()); + matching_family_fonts.empend(font_key_and_loader.key, const_cast(&font_key_and_loader.value)); } Gfx::FontDatabase::the().for_each_typeface_with_family_name(key.family_name.to_string(), [&](Gfx::Typeface const& typeface) { matching_family_fonts.empend( @@ -1634,7 +1645,7 @@ RefPtr StyleComputer::font_matching_algorithm(FontFaceKey const return {}; } -RefPtr StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const +RefPtr StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const { auto* parent_element = element_to_inherit_style_from(element, pseudo_element); @@ -1649,7 +1660,7 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen auto parent_line_height = parent_or_root_element_line_height(element, pseudo_element); 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(); + font_pixel_metrics = parent_element->computed_css_values()->first_available_computed_font().pixel_metrics(); else font_pixel_metrics = Platform::FontPlugin::the().default_font().pixel_metrics(); auto parent_font_size = [&]() -> CSSPixels { @@ -1746,7 +1757,7 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen // and smaller may compute the font size to the previous entry in the table. if (identifier == CSS::ValueID::Smaller || identifier == CSS::ValueID::Larger) { if (parent_element && parent_element->computed_css_values()) { - font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size); + font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->first_available_computed_font().pixel_metrics().size); } } font_size_in_px *= get_absolute_size_mapping(identifier); @@ -1787,7 +1798,7 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen float const font_size_in_pt = font_size_in_px * 0.75f; - auto find_font = [&](FlyString const& family) -> RefPtr { + auto find_font = [&](FlyString const& family) -> RefPtr { font_selector = { family, font_size_in_pt, weight, width, slope }; FontFaceKey key { @@ -1796,25 +1807,29 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen .slope = slope, }; + auto result = Gfx::FontCascadeList::create(); if (auto it = m_loaded_fonts.find(key); it != m_loaded_fonts.end()) { - auto& loader = *it->value; - if (auto found_font = loader.font_with_point_size(font_size_in_pt)) - return found_font; + auto const& loaders = it->value; + for (auto const& loader : loaders) { + if (auto found_font = loader->font_with_point_size(font_size_in_pt)) + result->add(*found_font, loader->unicode_ranges()); + } + return result; } - if (auto found_font = m_font_cache.get(font_selector)) + if (auto found_font = font_matching_algorithm(key, font_size_in_pt); found_font && !found_font->is_empty()) { return found_font; + } - if (auto found_font = font_matching_algorithm(key, font_size_in_pt)) - return found_font; - - if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes)) - return found_font; + if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes)) { + result->add(*found_font); + return result; + } return {}; }; - auto find_generic_font = [&](ValueID font_id) -> RefPtr { + auto find_generic_font = [&](ValueID font_id) -> RefPtr { Platform::GenericFont generic_font {}; switch (font_id) { case ValueID::Monospace: @@ -1849,40 +1864,38 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen return find_font(Platform::FontPlugin::the().generic_font_name(generic_font)); }; - RefPtr found_font; - + auto font_list = Gfx::FontCascadeList::create(); if (font_family.is_value_list()) { auto const& family_list = static_cast(font_family).values(); for (auto const& family : family_list) { + RefPtr other_font_list; if (family->is_identifier()) { - found_font = find_generic_font(family->to_identifier()); + other_font_list = find_generic_font(family->to_identifier()); } else if (family->is_string()) { - found_font = find_font(family->as_string().string_value()); + other_font_list = find_font(family->as_string().string_value()); } else if (family->is_custom_ident()) { - found_font = find_font(family->as_custom_ident().custom_ident()); + other_font_list = find_font(family->as_custom_ident().custom_ident()); } - if (found_font) - break; + if (other_font_list) + font_list->extend(*other_font_list); } } else if (font_family.is_identifier()) { - found_font = find_generic_font(font_family.to_identifier()); + if (auto other_font_list = find_generic_font(font_family.to_identifier())) + font_list->extend(*other_font_list); } else if (font_family.is_string()) { - found_font = find_font(font_family.as_string().string_value()); + if (auto other_font_list = find_font(font_family.as_string().string_value())) + font_list->extend(*other_font_list); } else if (font_family.is_custom_ident()) { - found_font = find_font(font_family.as_custom_ident().custom_ident()); + if (auto other_font_list = find_font(font_family.as_custom_ident().custom_ident())) + font_list->extend(*other_font_list); } - if (!found_font) { - found_font = StyleProperties::font_fallback(monospace, bold); - if (found_font) { - if (auto scaled_fallback_font = found_font->with_size(font_size_in_pt)) - found_font = scaled_fallback_font; - } + auto found_font = StyleProperties::font_fallback(monospace, bold); + if (auto scaled_fallback_font = found_font->with_size(font_size_in_pt)) { + font_list->add(*scaled_fallback_font); } - m_font_cache.set(font_selector, *found_font); - - return found_font; + return font_list; } void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* element, Optional pseudo_element) const @@ -1902,12 +1915,16 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele auto font_weight = style.property(CSS::PropertyID::FontWeight); auto font_stretch = style.property(CSS::PropertyID::FontStretch); - auto found_font = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch, style.math_depth()); + auto font_list = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch, style.math_depth()); + VERIFY(font_list); + VERIFY(!font_list->is_empty()); + + RefPtr const found_font = font_list->first(); style.set_property(CSS::PropertyID::FontSize, LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(found_font->pixel_size()))), nullptr); style.set_property(CSS::PropertyID::FontWeight, NumberStyleValue::create(font_weight->to_font_weight())); - style.set_computed_font(found_font.release_nonnull()); + style.set_computed_font_list(*font_list); if (element && is(*element)) { const_cast(*this).m_root_element_font_metrics = calculate_root_element_font_metrics(style); @@ -1928,7 +1945,7 @@ CSSPixels StyleComputer::parent_or_root_element_line_height(DOM::Element const* auto const* computed_values = parent_element->computed_css_values(); if (!computed_values) return m_root_element_font_metrics.line_height; - auto parent_font_pixel_metrics = computed_values->computed_font().pixel_metrics(); + auto parent_font_pixel_metrics = computed_values->first_available_computed_font().pixel_metrics(); auto parent_font_size = computed_values->property(CSS::PropertyID::FontSize)->as_length().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() : m_root_element_font_metrics.font_size; @@ -1941,7 +1958,7 @@ void StyleComputer::absolutize_values(StyleProperties& style, DOM::Element const { 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 font_pixel_metrics = style.first_available_computed_font().pixel_metrics(); Length::FontMetrics font_metrics { m_root_element_font_metrics.font_size, font_pixel_metrics, parent_or_root_line_height }; @@ -2367,8 +2384,6 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet) .weight = font_face.weight().value_or(0), .slope = font_face.slope().value_or(0), }; - if (m_loaded_fonts.contains(key)) - continue; Vector urls; for (auto& source : font_face.sources()) { @@ -2381,8 +2396,15 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet) if (urls.is_empty()) continue; - auto loader = make(const_cast(*this), font_face.font_family(), move(urls)); - const_cast(*this).m_loaded_fonts.set(key, move(loader)); + auto loader = make(const_cast(*this), font_face.font_family(), font_face.unicode_ranges(), move(urls)); + auto maybe_font_loaders_list = const_cast(*this).m_loaded_fonts.get(key); + if (maybe_font_loaders_list.has_value()) { + maybe_font_loaders_list->append(move(loader)); + } else { + FontLoaderList loaders; + loaders.append(move(loader)); + const_cast(*this).m_loaded_fonts.set(key, move(loaders)); + } } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index 2145dc006d..7e658c224c 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -74,7 +74,7 @@ public: void load_fonts_from_sheet(CSSStyleSheet const&); - RefPtr compute_font_for_style_values(DOM::Element const* element, Optional pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const; + RefPtr compute_font_for_style_values(DOM::Element const* element, Optional pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const; struct AnimationKey { CSS::CSSStyleDeclaration const* source_declaration; @@ -123,9 +123,9 @@ private: ErrorOr> compute_style_impl(DOM::Element&, Optional, ComputeStyleMode) const; ErrorOr compute_cascaded_values(StyleProperties&, DOM::Element&, Optional, bool& did_match_any_pseudo_element_rules, ComputeStyleMode) const; - static RefPtr find_matching_font_weight_ascending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); - static RefPtr find_matching_font_weight_descending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); - RefPtr font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const; + static RefPtr find_matching_font_weight_ascending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); + static RefPtr find_matching_font_weight_descending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); + RefPtr font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const; void compute_font(StyleProperties&, DOM::Element const*, Optional) const; void compute_math_depth(StyleProperties&, DOM::Element const*, Optional) const; void compute_defaulted_values(StyleProperties&, DOM::Element const*, Optional) const; @@ -186,7 +186,8 @@ private: mutable FontCache m_font_cache; - HashMap> m_loaded_fonts; + using FontLoaderList = Vector>; + HashMap m_loaded_fonts; Length::FontMetrics m_default_font_metrics; Length::FontMetrics m_root_element_font_metrics; diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index 1ac1151790..ad767d6551 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -191,7 +191,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const auto line_height = property(CSS::PropertyID::LineHeight); if (line_height->is_identifier() && line_height->to_identifier() == ValueID::Normal) - return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing()); + return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing()); if (line_height->is_length()) { auto line_height_length = line_height->as_length().length(); @@ -213,7 +213,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const auto resolved = line_height->as_calculated().resolve_number(); if (!resolved.has_value()) { dbgln("FIXME: Failed to resolve calc() line-height (number): {}", line_height->as_calculated().to_string()); - return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing()); + return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing()); } return Length(resolved.value(), Length::Type::Em).to_px(layout_node); } @@ -221,12 +221,12 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const auto resolved = line_height->as_calculated().resolve_length(layout_node); if (!resolved.has_value()) { dbgln("FIXME: Failed to resolve calc() line-height: {}", line_height->as_calculated().to_string()); - return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing()); + return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing()); } return resolved->to_px(layout_node); } - return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing()); + return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing()); } Optional StyleProperties::z_index() const diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index be587b0a82..88cb18d4ac 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -22,8 +23,6 @@ public: static NonnullRefPtr create() { return adopt_ref(*new StyleProperties); } - NonnullRefPtr clone() const; - template inline void for_each_property(Callback callback) const { @@ -128,15 +127,17 @@ public: float stroke_opacity() const; Optional fill_rule() const; - Gfx::Font const& computed_font() const + Gfx::Font const& first_available_computed_font() const { return m_font_list->first(); } + + Gfx::FontCascadeList const& computed_font_list() const { - VERIFY(m_font); - return *m_font; + VERIFY(m_font_list); + return *m_font_list; } - void set_computed_font(NonnullRefPtr font) + void set_computed_font_list(NonnullRefPtr font_list) const { - m_font = move(font); + m_font_list = move(font_list); } CSSPixels line_height(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const; @@ -162,7 +163,7 @@ private: Vector shadow(CSS::PropertyID, Layout::Node const&) const; int m_math_depth { InitialValues::math_depth() }; - mutable RefPtr m_font; + mutable RefPtr m_font_list; }; } diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 32d62dcc2a..7bb9dc9ae6 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -492,7 +492,7 @@ static Element::RequiredInvalidationAfterStyleChange compute_required_invalidati { Element::RequiredInvalidationAfterStyleChange invalidation; - if (&old_style.computed_font() != &new_style.computed_font()) + if (!old_style.computed_font_list().equals(new_style.computed_font_list())) invalidation.relayout = true; for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) { diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h index 208bd4dedc..56b0100440 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h @@ -58,7 +58,8 @@ public: auto& font_stretch = *font_style_value.longhand(CSS::PropertyID::FontStretch); auto& font_size = *font_style_value.longhand(CSS::PropertyID::FontSize); auto& font_family = *font_style_value.longhand(CSS::PropertyID::FontFamily); - my_drawing_state().current_font = canvas_element.document().style_computer().compute_font_for_style_values(&canvas_element, {}, font_family, font_size, font_style, font_weight, font_stretch); + auto font_list = canvas_element.document().style_computer().compute_font_for_style_values(&canvas_element, {}, font_family, font_size, font_style, font_weight, font_stretch); + my_drawing_state().current_font = font_list->first(); } Bindings::CanvasTextAlign text_align() const { return my_drawing_state().text_align; } diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 27590d4437..c06f4e0422 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -1093,17 +1093,17 @@ void BlockFormattingContext::layout_list_item_marker(ListItemBox const& list_ite image_height = list_style_image->natural_height().value_or(0); } - CSSPixels default_marker_width = max(4, marker.font().pixel_size_rounded_up() - 4); + CSSPixels default_marker_width = max(4, marker.first_available_font().pixel_size_rounded_up() - 4); auto marker_text = marker.text().value_or(""); if (marker_text.is_empty()) { marker_state.set_content_width(image_width + default_marker_width); } else { - auto text_width = marker.font().width(marker_text); + auto text_width = marker.first_available_font().width(marker_text); marker_state.set_content_width(image_width + CSSPixels::nearest_value_for(text_width)); } - marker_state.set_content_height(max(image_height, marker.font().pixel_size_rounded_up() + 1)); + marker_state.set_content_height(max(image_height, marker.first_available_font().pixel_size_rounded_up() + 1)); auto final_marker_width = marker_state.content_width() + default_marker_width; diff --git a/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp b/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp index bd53ad536b..d578ac8f1a 100644 --- a/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp @@ -25,8 +25,8 @@ void ButtonBox::prepare_for_replaced_layout() // value attribute. This is not the case with