Fast composed-font emoji rendering via lv_imgfont_set_range#148
Merged
ThomasFarstrike merged 1 commit intoMay 31, 2026
Merged
Conversation
Cuts the per-glyph cost of FontManager.getFont(emoji=True) labels
from "C->Python round-trip per glyph" to "two int compares in C"
for any codepoint that isn't in the emoji map.
Why this matters: a Lightning Piggy transactions row, the Files
list, basically any label using a composed (emoji-fallback) font
is overwhelmingly ASCII. Today every glyph crosses into the
MicroPython _imgfont_path_cb just to return None, then LVGL
falls back to the base Montserrat. With LVGL's imgfont gaining a
codepoint accept/exclude range, codepoints outside the emoji
range are rejected in C and skip the Python callback entirely;
LVGL falls back to the base font at C speed. Emoji codepoints
still hit the Python path (unchanged).
Three pieces:
* internal_filesystem/lib/mpos/ui/font_manager.py
- _create_emoji_font(size) now calls
lv.imgfont_set_range(font, cp_min, cp_max, 0xE000, 0xF8FF)
after creating the imgfont. cp_min/cp_max are computed
dynamically from the loaded _emoji_maps keys (so the filter
self-maintains as the emoji set grows — no hardcoded magic).
- Guarded by try/except AttributeError, so a build whose
pinned lvgl_micropython SHA predates the patch keeps working,
just without the speedup.
* scripts/build_mpos.sh
- Applies lvgl_micropython/imgfont_set_range.patch into
lib/lvgl during the build, gated by a -f existence check so
older lvgl_micropython pins (no patch file present) still
build cleanly.
* lvgl_micropython submodule bump
- 916ec6b -> e00d9d9, picks up the new imgfont_set_range.patch
plus a small unrelated brew-config parser fix in
builder/macOS.py that was breaking macOS builds entirely.
Verified end-to-end on Waveshare ESP32-S3-Touch-LCD-2 (macOS
desktop build also OK). FontManager.getFont(emoji=True) on
device computes bounds (0x203C, 0x1F9E2) — exactly the actual
min/max across the loaded 400-emoji set. Scrolling the LP
transactions list is noticeably smoother than the pre-patch
build.
Backward-compat note: lvgl_micropython e00d9d9 is currently only
on bitcoin3us/lvgl_micropython. Submodule pointer here will
resolve once that branch lands on MicroPythonOS/lvgl_micropython;
.gitmodules intentionally still points at the upstream URL.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Merged
4 tasks
Contributor
|
That's very impressive! I like how the range can be set at runtime, so it's more generic. Not sure upstream lvgl_micropython or upstream lvgl_micropython/lib/lvgl would ever merge this, but that's not a dealbreaker! Let me merge it, assuming you've already verified that it works. I'm excited! |
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.
Summary
Cuts the per-glyph cost of
FontManager.getFont(emoji=True)labels from a C→Python round-trip per glyph to two int compares in C, for any codepoint that isn't in the emoji map. User-visible result: noticeably smoother scrolling of any label that uses an emoji-fallback font (Lightning Piggy transactions row, Files list, etc.) — even though most rows have no emoji in them.How
Three pieces:
internal_filesystem/lib/mpos/ui/font_manager.py—_create_emoji_font(size)now callslv.imgfont_set_range(font, cp_min, cp_max, 0xE000, 0xF8FF)afterlv.imgfont_create.cp_min/cp_maxare computed dynamically from the loaded_emoji_mapskeys, so the filter self-maintains as the emoji set grows — no hardcoded magic number. Guarded bytry/except AttributeErrorso olderlvgl_micropythonpins still work (just without the speedup).scripts/build_mpos.sh— applieslvgl_micropython/imgfont_set_range.patchagainstlib/lvglduring the build. Gated by a-fexistence check, so olderlvgl_micropythonpins (no patch file present) still build cleanly.lvgl_micropythonsubmodule — bumped916ec6b→e00d9d9. Picks up the newimgfont_set_range.patchplus a small drive-by brew-config parser fix inbuilder/macOS.pythat was breaking macOS builds entirely.Dependency
This PR depends on MicroPythonOS/lvgl_micropython#3. The submodule pointer here references
e00d9d9, which currently lives only on thebitcoin3us/lvgl_micropythonfork. Once #3 merges intoMicroPythonOS/lvgl_micropython, this PR's submodule pointer will resolve from upstream and this can land..gitmodulesis intentionally untouched (still points at the canonical URL).Test plan
build_mpos.sh macOS) — clean,lv.imgfont_set_rangeexposed in the LVGL bindingbuild_mpos.sh esp32s3) — clean build, patch applies, all expected freezing happenslv.imgfont_set_rangecallable, FontManager wiring works(0x203C, 0x1F9E2)(exact min/max across the loaded codepoints, as designed)try/except AttributeErrorpath verified mentally (covered by gating in build_mpos.sh)