#!/usr/bin/env python3 """Patch lv_font_conv output for LVGL 9. `lv_font_conv` emits font .c files wrapped in `#if LVGL_VERSION_MAJOR` guards and (for v8) a `.cache` field. On LVGL 9 the project wants the plain, unguarded struct with `.release_glyph` / `.kerning` / `.static_bitmap` present (see the "LVGL 9 font patching" note in README.md). Without this the font compiles but renders invisible. Usage: python tools/patch_lvgl9_font.py firmware/src/font_foo.c [more.c ...] Idempotent: running it on an already-patched file is a no-op. """ import re import sys SUBS = [ # drop the v8-only glyph cache declaration (r'#if LVGL_VERSION_MAJOR == 8\n/\*Store all the custom data of the font\*/\n' r'static lv_font_fmt_txt_glyph_cache_t cache;\n#endif\n\n', ''), # collapse the font_dsc storage-class guard (r'#if LVGL_VERSION_MAJOR >= 8\nstatic const lv_font_fmt_txt_dsc_t font_dsc = \{\n' r'#else\nstatic lv_font_fmt_txt_dsc_t font_dsc = \{\n#endif\n', 'static const lv_font_fmt_txt_dsc_t font_dsc = {\n'), # drop the v8 .cache member (r'#if LVGL_VERSION_MAJOR == 8\n \.cache = &cache\n#endif\n', ''), # collapse the public-font const guard (r'#if LVGL_VERSION_MAJOR >= 8\n(const lv_font_t \w+ = \{)\n' r'#else\nlv_font_t \w+ = \{\n#endif\n', r'\1\n'), # keep .subpx and add the three LVGL 9 fields (r'#if !\(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0\)\n' r' \.subpx = LV_FONT_SUBPX_NONE,\n#endif\n', ' .subpx = LV_FONT_SUBPX_NONE,\n .release_glyph = NULL,\n' ' .kerning = 0,\n .static_bitmap = 0,\n'), # unwrap underline fields (r'#if LV_VERSION_CHECK\(7, 4, 0\) \|\| LVGL_VERSION_MAJOR >= 8\n' r'( \.underline_position = -1,\n \.underline_thickness = 2,\n)#endif\n', r'\1'), # unwrap .fallback (r'#if LV_VERSION_CHECK\(8, 2, 0\) \|\| LVGL_VERSION_MAJOR >= 9\n' r'( \.fallback = NULL,\n)#endif\n', r'\1'), ] def patch(path: str) -> None: s = open(path, encoding="utf-8").read() for pat, repl in SUBS: s = re.sub(pat, repl, s) open(path, "w", encoding="utf-8").write(s) leftover = len(re.findall(r'LVGL_VERSION_MAJOR|LV_VERSION_CHECK|\.cache = &cache', s)) print(f"patched {path} leftover_guards={leftover}") if __name__ == "__main__": if len(sys.argv) < 2: sys.exit(__doc__) for p in sys.argv[1:]: patch(p)