From 69a81243f5a602e5994258bc10af132f008d5858 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 17 Aug 2023 18:45:06 +0200 Subject: [PATCH] LibWeb: Consider system fonts when looking for inexact weight match Previously, we only considered loaded (web) fonts. --- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 45 +++++++++++++++---- Userland/Libraries/LibWeb/CSS/StyleComputer.h | 5 +-- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 03f880263ee..30148224291 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -187,6 +187,19 @@ private: HashMap> mutable m_cached_fonts; }; +struct StyleComputer::MatchingFontCandidate { + FontFaceKey key; + Variant loader_or_typeface; + + [[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); + } + return loader_or_typeface.get()->get_font(point_size); + } +}; + static CSSStyleSheet& default_stylesheet(DOM::Document const& document) { static JS::Handle sheet; @@ -2004,9 +2017,10 @@ RefPtr StyleComputer::find_matching_font_weight_ascending(Vecto auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight >= target_weight; }) : Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight > target_weight; }); auto it = find_if(candidates.begin(), candidates.end(), pred); - for (; it != candidates.end(); ++it) - if (auto found_font = it->loader->font_with_point_size(font_size_in_pt)) + for (; it != candidates.end(); ++it) { + if (auto found_font = it->font_with_point_size(font_size_in_pt)) return found_font; + } return {}; } @@ -2016,9 +2030,10 @@ RefPtr StyleComputer::find_matching_font_weight_descending(Vect auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight <= target_weight; }) : Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight < target_weight; }); auto it = find_if(candidates.rbegin(), candidates.rend(), pred); - for (; it != candidates.rend(); ++it) - if (auto found_font = it->loader->font_with_point_size(font_size_in_pt)) + for (; it != candidates.rend(); ++it) { + if (auto found_font = it->font_with_point_size(font_size_in_pt)) return found_font; + } return {}; } @@ -2033,6 +2048,20 @@ RefPtr StyleComputer::font_matching_algorithm(FontFaceKey const 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()); } + Gfx::FontDatabase::the().for_each_typeface([&](Gfx::Typeface const& typeface) { + if (typeface.family().equals_ignoring_ascii_case(key.family_name)) { + matching_family_fonts.empend( + FontFaceKey { + .family_name = MUST(FlyString::from_deprecated_fly_string(typeface.family())), + .weight = static_cast(typeface.weight()), + .slope = typeface.slope(), + }, + &typeface); + } + }); + quick_sort(matching_family_fonts, [](auto const& a, auto const& b) { + return a.key.weight < b.key.weight; + }); // FIXME: 1. font-stretch is tried first. // FIXME: 2. font-style is tried next. // We don't have complete support of italic and oblique fonts, so matching on font-style can be simplified to: @@ -2052,13 +2081,13 @@ RefPtr StyleComputer::font_matching_algorithm(FontFaceKey const auto it = find_if(matching_family_fonts.begin(), matching_family_fonts.end(), [&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight >= key.weight; }); for (; it != matching_family_fonts.end() && it->key.weight <= 500; ++it) { - if (auto found_font = it->loader->font_with_point_size(font_size_in_pt)) + if (auto found_font = it->font_with_point_size(font_size_in_pt)) return found_font; } if (auto found_font = find_matching_font_weight_descending(matching_family_fonts, key.weight, font_size_in_pt, false)) return found_font; for (; it != matching_family_fonts.end(); ++it) { - if (auto found_font = it->loader->font_with_point_size(font_size_in_pt)) + if (auto found_font = it->font_with_point_size(font_size_in_pt)) return found_font; } } @@ -2193,10 +2222,10 @@ RefPtr StyleComputer::compute_font_for_style_values(DOM::Elemen return found_font; } - if (auto found_font = font_matching_algorithm(key, font_size_in_pt)) + if (auto found_font = FontCache::the().get(font_selector)) return found_font; - if (auto found_font = FontCache::the().get(font_selector)) + if (auto found_font = font_matching_algorithm(key, font_size_in_pt)) return found_font; if (auto found_font = Gfx::FontDatabase::the().get(family.to_deprecated_string(), font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes)) diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index 7ea6c51f130..66ec3ce4a7c 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -136,10 +136,7 @@ private: }; class FontLoader; - struct MatchingFontCandidate { - FontFaceKey key; - FontLoader* loader; - }; + struct MatchingFontCandidate; 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;