fw/graphics: consult the font's other own resource when the routed glyph lookup misses#1771
Open
vvzvlad wants to merge 1 commit into
Open
fw/graphics: consult the font's other own resource when the routed glyph lookup misses#1771vvzvlad wants to merge 1 commit into
vvzvlad wants to merge 1 commit into
Conversation
… misses prv_font_res_for_codepoint() picks base vs extension purely from the codepoint's Unicode class, before any glyph-presence check, and a miss never revisited the other resource of the same font. With a language pack loaded this breaks both ways: latin-classified codepoints (0x2000-0x2BFF: U+2103, U+2116, U+20BD) present only in the pack's extension render as the wildcard box, and base-only non-latin codepoints (U+03C0, U+02C6-02DD) degrade to the 14px system fallback. Make classification a lookup-order hint instead of a hard partition: prv_get_glyph_in_font() tries the routed resource first and, on a miss, retries the font's other own resource. The rescue is skipped when the emoji font took over (owner != font_info), so emoji substitution and baseline adjustment are unaffected. The rescue stays within the same FontInfo, so the baseline adjust is 0 by construction. When a glyph exists in both resources the routed one still wins. Without a loaded extension the change is a strict no-op. Cost: one extra offset-table load, only on lookups that missed their routed resource, i.e. paths that already headed for the fallback font. Side effect: an emoji-classified codepoint with no system emoji font available can now also be rescued from the extension, which is the desired outcome for packs carrying 0x2B00-0x2BFF glyphs. Fixes coredevices#1709 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Vlad Zaytsev <git@vvzvlad.xyz>
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.
Fixes #1709.
When a language pack is loaded, a glyph that exists in the pack's extension font can still render as the missing-glyph box — and, in the mirror case, a glyph that exists in the base font can degrade to the 14px system fallback. ℃ (U+2103) from the issue is one instance of a whole class.
Mechanism
prv_font_res_for_codepoint()picks base vs extension purely from the codepoint's Unicode class:codepoint_is_latin()(0x0000–0x02AF and 0x2000–0x2BFF) → base, everything else → extension. The pick happens before any glyph-presence check, and the fallback chain inprv_get_glyph()never revisits the other resource of the same font — a miss goes straight to the process-global system fallback and then the wildcard box.So the classification acts as a hard partition, when in reality it's only a guess about which resource carries the glyph. Both directions of a wrong guess are live bugs:
The fix
prv_get_glyph_in_font()— the single-font leaf resolver — now treats classification as a lookup-order hint instead of a partition: try the routed resource first; on a miss, try the font's other own resource (base ↔ extension) before giving up. The outer fallback chain (primary → system fallback → wildcard) is untouched, and the leaf still never consults the fallback font, so the depth-1 invariant holds as documented.Scoping decisions:
owner == font_info: when the emoji font takes over, the routed resource belongs to a differentFontInfo, and the rescue is skipped — the emoji substitution and baseline-adjust behavior from fw/graphics: fix tiny, top-aligned emoji at the largest text size #1766 is unchanged. The two compose: that PR places glyphs that legitimately come from another font; this one stops base-present glyphs from being outsourced at all.FontInfo, soprv_baseline_adjust()yields 0 by construction — extension glyphs are already baked against their base font's own baseline.font_info->extended(or on being routed to the extension, which requires it). A firmware without a loaded extension resolves byte-for-byte as before.The alternative — narrowing the 0x2000–0x2BFF "latin" range in
codepoint_is_latin()— was rejected: the base fonts genuinely carry glyphs across that block (U+2013/2014, U+2018–201E, U+2026, U+20AC, U+2122, U+2212, …), and reclassifying them would regress each one to a pack lookup that packs don't cover. The nonstandard-emoji handling in the 0x25xx block also leans on the current classification.Cost: one extra offset-table probe, only on lookups that missed their routed resource — i.e. paths that were already headed for the (more expensive) fallback-font lookup. The font cache negative-caches misses as before.
Tested
./pbl build(obelix) and the full./pbl testsuite pass.Unit tests added in
test_text_resources.c, all through the real resolver against the shipped PBF fixtures (no fixture regeneration needed):GOTHIC_18_EMOJIbase font lacks it — pairing them makes U+2026 route to base, miss, and resolve from the extension. The resolver keys only on glyph presence and codepoint class, so this exercises exactly the issue's path.Both rescue tests fail without the resolver change (verified by disabling the rescue block and re-running: got wildcard/fallback bytes instead of the expected glyphs).
On-device (obelix@pvt): a Russian language pack whose extension carries № (U+2116) and ₽ (U+20BD) — both absent from every base Gothic font — previously rendered both as the wildcard box; with this change they render from the pack (screenshots above). Latin text, base punctuation (— … « »), and emoji substitution are visually unchanged.