Repository navigation
Conversation
nicoburns
commented
Jul 14, 2026
|
|
||
| #[derive(Clone, PartialEq, Eq, Hash)] | ||
| struct TextFallbackKey { | ||
| chars: SmallVec<[char; 8]>, |
Collaborator
Author
There was a problem hiding this comment.
Is 8 chars a sensible size here?
Comment on lines
+129
to
+130
| let chars: SmallVec<[char; 8]> = chars.into_iter().collect(); | ||
| if self.state.fallback_chars != chars { |
Collaborator
Author
There was a problem hiding this comment.
I think we can eliminate this allocation.
nicoburns
force-pushed
the
rigorous-font-fallback
branch
from
July 14, 2026 12:52
927b895 to
05bdd60
Compare
Contributor
|
I don’t have time for a deep dive on this right now but, at a glance, I’m generally supportive of this with a couple caveats:
Big +1 to returning multiple fallback fonts from the system. We should probably also extend the script sample array to support multiple samples per script. This would help, for example, with selecting the -ExtB CJK fonts on Windows. |
staging-devin-ai-integration
Bot
force-pushed
the
rigorous-font-fallback
branch
from
September 15, 2026 12:35
05bdd60 to
013ad2e
Compare
Script/locale fallback now yields an ordered list of families instead of a single family: the CoreText cascade list, fontconfig's sorted coverage list (FcFontSort + trim), all matching Android fallback chain entries, and DirectWrite's script-sample match. Also fix empty layouts shaping their cursor-metrics run with a zero font size by resolving the default style instead of using ResolvedStyle::default().
Add Query::set_fallback_chars so parley can tell the query which characters a cluster needs covered. When none of the requested or script/locale fallback families match, the query asks the platform for a family covering those exact characters (CTFontCreateForString, IDWriteFontFallback::MapCharacters, FcFontMatch with FC_CHARSET). Results are cached in the collection per (chars, locale), capped at 1024 entries and cleared on font registration / fallback changes. This supersedes the hack that appended a Han family to every fallback list to catch CJK punctuation in Latin text (linebender#597), so remove it.
staging-devin-ai-integration
Bot
force-pushed
the
rigorous-font-fallback
branch
from
September 17, 2026 15:09
1b9bbd5 to
8f1958d
Compare
1 task
lucasmerlin
added a commit
to emilk/egui
that referenced
this pull request
Oct 13, 2026
* Related: #5233, upstream linebender/parley#644 * [ ] I have followed the instructions in the PR template On Windows with a non-Chinese locale, fontique's Han fallback is a single Japanese font (Yu Gothic UI), which lacks many Simplified Chinese characters like 这 and 还. These rendered as tofu even with Microsoft YaHei installed. The example text from the added demo without the fix fails to show some glyphs: <img width="582" height="146" alt="image" src="https://github.com/user-attachments/assets/1f37a778-6d67-431f-9aad-c7bd23e0e360" /> `SystemFontProvider` now tries the other Han locales (Simplified/Traditional Chinese, Japanese, Korean) when the font for the preferred locale can't render a char. Simplified Chinese is looked up as `zh-SG` instead of `zh-CN`: fontique treats `zh-CN` as the default Han locale and caches the result of the locale-less Han lookup (which every `Query::set_fallbacks` makes) as that default. So `zh-CN` lookups often returned the Japanese font, depending on which scripts were looked up first. A TODO points at linebender/parley#689, which should make this workaround unnecessary. Also adds a collapsed "System font fallback" section to the Misc Demos window to check the fallback by eye. ## Testing Verified on Windows 11 (de-DE): all samples in Misc Demos → System font fallback render, and `cargo test -p egui_system_fonts -- --include-ignored` passes. **Still needs testing on macOS and Linux**: open Misc Demos → System font fallback in `egui_demo_app` and run the ignored tests above. Both platforms also pick a single fallback font per script in fontique, so they could have the same problem in milder form, e.g. a Japanese-locale Mac, or a Linux system with only a Japanese CJK font. The Misc Demos snapshot was updated on Windows; if CI disagrees, `./scripts/update_snapshots_from_ci.sh` should fix it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
汉on Windows #644Generated with Fable High.
Motivation
Font fallback completely fails to find a matching font for some glyphs.
This is because font fallback was keyed on (script, locale), and resolved by asking the OS for a single font family which matches a per-script sample string. If that one font lacked the actual character (for example, CJK extensions, symbols, punctuation shared between scripts, scripts without samples) the Fontique gave up, even if there was actually an installed font that had the required glyph.
Changes made
Implement
3-tier2-tier fallback:Tier A (all backends) - Ordered list of fonts per script (script, locale)
This is the existing fallback mechanism, but modified to work with a list of fonts rather a single font per (script, locale).
CTFontCopyDefaultCascadeListForLanguagesfont_sortwith coverage trimming instead offont_matchTier B (skipped on Android) - per-character system fallback
Query::set_fallback_chars()where Parley passes the specific characters we are falling back forCTFontCreateForString/IDWriteFontFallback::MapCharacters/FC_CHARSETmatch)Tier C (all backends) - exhaustive coverage scanAs a last resort, all families are checked for real cmap coverage (guaranteeing a glyph is found if any font has one)Fonts are sorted by name, with hidden/.-fonts last, and LastResort excluded)Positive and negative results are cached, so the scan happens once per unique character set.This scan is expensive, so there is an opt-out via a newexhaustive_fallback: boolruntime setting onCollection(Tier C removed per Chad's feedback)
This PR also:
Verification Performed
The AI has run temporary integration tests (not included in this PR) on macOS and Ubuntu.
Tested in Blitz on macOS, and it definitely seems to work and find glyphs where
maindoesn't.