From c7d6a7aafb06a4b4b462378b56e98dcaec7ffc95 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 2 Jan 2025 04:48:23 +0300 Subject: [PATCH] LibWeb: Insert default font in font list before emoji font This fixes a bug where, if a non-existent font family is specified in CSS, whitespaces would be rendered using the emoji font, while letters would use the default font. This issue occurred because the font was resolved separately for each code point. Since the emoji font was listed before the default font, it was chosen for whitespace characters due to its inclusion of whitespace glyphs (at least in the Apple Color Emoji font on macOS). This change resolves the issue by placing the default font before the emoji font in the list. --- Libraries/LibWeb/CSS/StyleComputer.cpp | 18 ++++++++++-------- .../expected/non-existing-font-family.txt | 11 +++++++++++ .../Layout/input/non-existing-font-family.html | 5 +++++ 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/non-existing-font-family.txt create mode 100644 Tests/LibWeb/Layout/input/non-existing-font-family.html diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 8675d01d9b9..1d168e7a052 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1775,9 +1775,7 @@ RefPtr StyleComputer::compute_font_for_style_values( auto* parent_element = element_to_inherit_style_from(element, pseudo_element); auto width = font_stretch.to_font_width(); - auto weight = font_weight.to_font_weight(); - bool bold = weight > Gfx::FontWeight::Regular; // FIXME: Should be based on "user's default font size" CSSPixels font_size_in_px = 16; @@ -1915,9 +1913,6 @@ RefPtr StyleComputer::compute_font_for_style_values( // FIXME: Implement the full font-matching algorithm: https://www.w3.org/TR/css-fonts-4/#font-matching-algorithm - // Note: This is modified by the find_font() lambda - bool monospace = false; - float const font_size_in_pt = font_size_in_px * 0.75f; auto find_font = [&](FlyString const& family) -> RefPtr { @@ -1954,7 +1949,6 @@ RefPtr StyleComputer::compute_font_for_style_values( case Keyword::Monospace: case Keyword::UiMonospace: generic_font = Platform::GenericFont::Monospace; - monospace = true; break; case Keyword::Serif: generic_font = Platform::GenericFont::Serif; @@ -2009,12 +2003,20 @@ RefPtr StyleComputer::compute_font_for_style_values( font_list->extend(*other_font_list); } + auto default_font = Platform::FontPlugin::the().default_font(font_size_in_pt); + if (font_list->is_empty()) { + // This is needed to make sure we check default font before reaching to emojis. + font_list->add(*default_font); + } + if (auto emoji_font = Platform::FontPlugin::the().default_emoji_font(font_size_in_pt); emoji_font) { font_list->add(*emoji_font); } - auto found_font = ComputedProperties::font_fallback(monospace, bold, font_size_in_pt); - font_list->set_last_resort_font(found_font->with_size(font_size_in_pt)); + // The default font is already included in the font list, but we explicitly set it + // as the last-resort font. This ensures that if none of the specified fonts contain + // the requested code point, there is still a font available to provide a fallback glyph. + font_list->set_last_resort_font(*default_font); return font_list; } diff --git a/Tests/LibWeb/Layout/expected/non-existing-font-family.txt b/Tests/LibWeb/Layout/expected/non-existing-font-family.txt new file mode 100644 index 00000000000..077fa5260cd --- /dev/null +++ b/Tests/LibWeb/Layout/expected/non-existing-font-family.txt @@ -0,0 +1,11 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x17 children: inline + frag 0 from TextNode start: 0, length: 77, rect: [8,8 647.140625x17] baseline: 13.296875 + "the same font is supposed to be used for all characters including whitespaces" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x17] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/non-existing-font-family.html b/Tests/LibWeb/Layout/input/non-existing-font-family.html new file mode 100644 index 00000000000..491bb3a8115 --- /dev/null +++ b/Tests/LibWeb/Layout/input/non-existing-font-family.html @@ -0,0 +1,5 @@ +the same font is supposed to be used for all characters including whitespaces \ No newline at end of file