fonts: Remove the per-FontGroup cached fallback font (#35705)

Instead of keeping a per-FontGroup cache of the previously used fallback
font, cache this value in the caller of `FontGroup::find_by_codepoint`.
The problem with caching this value in the `FontGroup` is that it can
make one layout different from the next.

Still, it is important to cache the value somewhere so that, for
instance, Chinese character don't have to continuously walk through the
entire fallback list when laying out. The heuristic here is to try to
last used font first if the `Script`s match. At the very least this
should make one layout consistent with the next.

Fixes #35704.
Fixes #35697.
Fixes #35689.
Fixes #35679.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-02-28 15:33:21 +01:00 committed by GitHub
parent 06d4272462
commit f949d2adc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 43 additions and 38 deletions

View file

@ -430,17 +430,29 @@ impl TextRun {
continue;
}
let Some(font) =
font_group
.write()
.find_by_codepoint(font_context, character, next_character)
else {
// If the script and BiDi level do not change, use the current font as the first fallback. This
// can potentially speed up fallback on long font lists or with uncommon scripts which might be
// at the bottom of the list.
let script = Script::from(character);
let bidi_level = bidi_info.levels[current_byte_index];
let current_font = current.as_ref().and_then(|(text_run_segment, font)| {
if text_run_segment.bidi_level == bidi_level && text_run_segment.script == script {
Some(font.clone())
} else {
None
}
});
let Some(font) = font_group.write().find_by_codepoint(
font_context,
character,
next_character,
current_font,
) else {
continue;
};
// If the existing segment is compatible with the character, keep going.
let script = Script::from(character);
let bidi_level = bidi_info.levels[current_byte_index];
if let Some(current) = current.as_mut() {
if current.0.update_if_compatible(
&font,