LibWeb: Verify whitespace font has the glyph in font_for_space()

When inline layout emits a whitespace chunk, it previously selected the
surrounding text's font without checking whether that font actually
contains a glyph for the whitespace codepoint. On pages that use
`@font-face` rules sharded by `unicode-range` (e.g. a Roboto webfont
split across one file for Cyrillic letters and another for basic Latin),
the shard covering the letters is picked for an adjacent space even
though the space codepoint lives in a different shard. HarfBuzz then
shapes the space with a font that has no glyph for it and emits
`.notdef`, rendering spaces as tofu boxes.

Check `contains_glyph(space_code_point)` on each candidate in
`font_for_space()` and fall through to
`FontCascadeList::font_for_code_point()` for the whitespace codepoint
when no surrounding font has the glyph.

Fixes whitespace rendering on web.telegram.org/a.
This commit is contained in:
Aliaksandr Kalenik
2026-04-22 16:43:53 +02:00
committed by Andreas Kling
parent 1f46651af5
commit 0bfe4677ae
Notes: github-actions[bot] 2026-04-22 18:28:54 +00:00
5 changed files with 48 additions and 8 deletions

Binary file not shown.

View File

@@ -0,0 +1 @@
space matches fallback: true

View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<style>
@font-face {
font-family: "HashFontNoSpace";
src: url("../../Assets/HashSansNoSpace.woff");
unicode-range: U+0041-005A;
}
.subset {
font-family: "HashFontNoSpace", "SerenitySans";
font-size: 100px;
}
.fallback-only {
font-family: "SerenitySans";
font-size: 100px;
}
span {
white-space: pre;
}
</style>
<script src="include.js"></script>
<div>
<span class="subset" id="letters-only">AB</span>
<span class="subset" id="with-space">A B</span>
<span class="fallback-only" id="ref-space">&nbsp;</span>
</div>
<script>
test(() => {
// HashFontNoSpace covers only AZ; the space in "A B" must come from the
// SerenitySans fallback, not from HashFontNoSpace's .notdef glyph.
let lettersOnlyWidth = document.getElementById("letters-only").getBoundingClientRect().width;
let withSpaceWidth = document.getElementById("with-space").getBoundingClientRect().width;
let fallbackSpaceWidth = document.getElementById("ref-space").getBoundingClientRect().width;
let spaceWidth = withSpaceWidth - lettersOnlyWidth;
println("space matches fallback: " + (Math.abs(spaceWidth - fallbackSpaceWidth) < 2));
});
</script>