fix: improved dynamic ligature probing to handle contextual alternates

This commit is contained in:
Adam Kowalski 2026-01-16 21:35:53 -08:00 committed by Jeremy Soller
parent c6ce5e69e5
commit 723841f934
2 changed files with 29 additions and 9 deletions

View file

@ -863,10 +863,30 @@ impl ShapeSpan {
false,
);
// If we get fewer glyphs than characters, it's likely a ligature.
if glyphs.len() == 1 {
// 1. If we have fewer glyphs than chars, it's definitely a ligature (e.g. -> becoming 1 arrow).
if glyphs.len() < probe_text.chars().count() {
continue;
}
// 2. If we have the same number of glyphs, they might be contextual alternates (e.g. |> becoming 2 special glyphs).
// Check if the glyphs match the standard "cmap" (character to glyph) mapping.
// If they differ, the shaper substituted them, so we should keep them together.
if glyphs.len() == probe_text.chars().count() {
let charmap = font.as_swash().charmap();
let mut is_modified = false;
for (i, c) in probe_text.chars().enumerate() {
let std_id = charmap.map(c);
if glyphs[i].glyph_id != std_id {
is_modified = true;
break;
}
}
if is_modified {
// Ligature/Contextual Alternate detected!
continue;
}
}
}
}
}