Add lv_imgfont codepoint range filter (and fix macOS brew parser)#3
Merged
ThomasFarstrike merged 15 commits intoMay 31, 2026
Merged
Conversation
Custom font source files for MicroPythonOS, including compressed Montserrat variants, CJK fonts, and custom symbol definitions.
- Bump image cache size for 1280x720 PNG support - Set color depth to 16 - Disable verbose trace logging for speed - Enable assert style checks - Enable sysmon and perf monitor - Configure font sizes (enable small/medium, disable large) - Enable compressed font support - Set default font to Montserrat 12 - Enable GIF decode cache, file explorer, image header cache - Various UI tweaks (calendar start Monday, etc.)
- macOS: remove -static LDFLAGS (fixes black window on macOS) - unix: add LDFLAGS_EXTRA=-static for portable binary, fix binary path print - SDL: add SDL_WINDOW_FULLSCREEN env var support, set arrow cursor
- gen/lvgl_api_gen_mpy.py, gen/python_api_gen_mpy.py: wrap LVGL callbacks in nlr_buf_t try/except to catch Python exceptions and disable failing callbacks instead of crashing - task_handler.py: improve exception handling robustness - display_driver_framework.py: reduce backlight PWM frequency
is_homebrew_arm() built a dict from `brew config` lines via
`line.split(':', 1)`, but output.split('\n') yields a trailing empty
string with no ':' — IndexError, build aborts before anything
compiles. Filter to lines containing ':' before parsing.
Reproduces with Python 3.14 + recent Homebrew on macOS 26.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Bakes an optional accept/exclude codepoint range into lv_imgfont so
LVGL can fast-reject non-emoji glyphs in C before invoking the
path_cb. For MicroPython callers — where path_cb is a Python
function — this is the difference between a C->Python round-trip
per glyph and a pair of int compares.
Effect on MPOS scrolling: a transactions list label is composed-font
with emoji=True, but typical content is mostly ASCII. Without the
filter every glyph (digits, letters, punctuation) crosses into
Python just to bail out. With it, only codepoints actually in the
emoji map reach Python, so plain-text scrolling stays in C
end-to-end.
void lv_imgfont_set_range(font, cp_min, cp_max, excl_min, excl_max);
- Cp outside [cp_min, cp_max] or inside [excl_min, excl_max]
-> get_glyph_dsc returns false immediately (LVGL falls back
to the next font in the chain at C speed).
- cp_min=0 / cp_max=UINT32_MAX defaults preserve existing behaviour
for any caller that doesn't call the setter.
- Setter no-ops safely on non-imgfont lv_font_t (fingerprint check)
so it's safe to call defensively from MicroPython.
Applied at build time to lvgl_micropython/lib/lvgl via build_mpos.sh,
matching the existing esp32_*.patch pattern in this repo. The
MicroPython auto-binder picks the new setter up from the header
declaration with no extra binding glue.
Patch applies cleanly to LVGL v9.4.0 (the current pinned lvgl SHA).
Verified end-to-end: macOS desktop build + ESP32-S3 device. On
device, FontManager.getFont(emoji=True) sets the range to the
actual min/max codepoint in the loaded emoji map; scrolling a
transactions list in Lightning Piggy is now noticeably smoother.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
6 tasks
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
Two small things; the imgfont one is the headline. macOS.py is a drive-by that was blocking the build entirely.
1.
imgfont_set_range.patch— fast filter for composed-font glyph lookupAdds an optional accept/exclude codepoint range to
lv_imgfontso LVGL can reject codepoints in C before callingpath_cb:For MicroPython callers — where
path_cbis a Python function — this turns the per-glyph cost from a C→Python round-trip into a pair of int compares. A typical text label usinggetFont(emoji=True)is overwhelmingly ASCII, so almost every glyph today crosses into Python just to bail out withNone. With the filter set, only codepoints actually in the emoji map reach Python.lv_imgfont_createinitialises the range to "accept everything", so any existing caller behaves identically.lv_font_t(fingerprint check onget_glyph_dsc) — safe to call defensively from MicroPython.build_mpos.shover in Fast composed-font emoji rendering via lv_imgfont_set_range MicroPythonOS#148 using the samepatch -p1 --forward < ../../*.patchpattern as the existingesp32_*.patchfiles in this repo.2.
builder/macOS.pybrew-config parseris_homebrew_arm()built a dict frombrew configlines vialine.split(':', 1), butoutput.split('\n')yields a trailing empty string with no:—IndexError, build aborts before anything compiles. Filter to lines containing:before parsing. One-line fix.Reproduced on Python 3.14 + recent Homebrew on macOS 26.
Test plan
build_mpos.sh macOS) — patch applies cleanly,lv.imgfont_set_rangeexposed in the binding, FontManager wiring worksbuild_mpos.sh esp32s3) — patch applies cleanly, builds clean (no warnings on the patched files)lv.imgfont_set_rangeis callable, FontManager computes bounds dynamically from the loaded emoji map, scrolling the Lightning Piggy transactions list is noticeably smoother than the pre-patch buildlv.font_montserrat_14no-ops without crashing, as designedCompanion PR
The MPOS-side wiring (FontManager invokes the new setter;
build_mpos.shapplies the patch) lives in MicroPythonOS/MicroPythonOS#148 — depends on this one merging first so the submodule pointer resolves.