You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/frameworks/font-manager.md
+27-34Lines changed: 27 additions & 34 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,14 +1,13 @@
1
1
# FontManager
2
2
3
-
FontManager is a singleton framework for loading, caching, and composing LVGL fonts — including built-in bitmap fonts, TrueType fonts, and emoji image fonts. It automatically selects the best-quality pre-rendered emoji asset for the requested size and uses LVGL's imgfont fallback mechanism to render emoji inline with text.
3
+
FontManager is a singleton framework for loading, caching, and composing LVGL fonts — including built-in bitmap fonts, TrueType fonts, and emoji image fonts. It uses LVGL's imgfont fallback mechanism to render 20×20 emoji PNGs inline with text, with nearest-neighbour scaling to match any font size.
4
4
5
5
## Overview
6
6
7
7
FontManager centralizes all font concerns in a single class:
8
8
9
9
-**Unified API** - One call (`getFont`) to get any font, with or without emoji support
10
-
-**Emoji Compositing** - Transparently layers an emoji imgfont on top of any base font via LVGL's `fallback` mechanism
11
-
-**Size-tiered Assets** - Picks the closest pre-rendered emoji PNG directory so LVGL never has to scale further than necessary
10
+
-**Emoji Compositing** - Transparently layers 20×20 emoji PNGs via LVGL's imgfont fallback, with nearest-neighbour scaling to match any font size
12
11
-**Lazy Caching** - Fonts and scaled image descriptors are cached on first use; no redundant work on subsequent calls
13
12
-**Android-Inspired** - Follows the same singleton/class-method pattern as other MicroPythonOS frameworks
14
13
@@ -17,20 +16,20 @@ FontManager centralizes all font concerns in a single class:
17
16
```python
18
17
from mpos import FontManager
19
18
20
-
# Get a built-in Montserrat font at 16px, with emoji support (default)
19
+
# Get a built-in Montserrat font at 16px (emoji disabled by default)
21
20
font = FontManager.getFont(size=16, family="Montserrat")
22
21
23
-
# Get the same font without emoji (e.g. for glyph enumeration)
# List all available built-in fonts (each already has emoji composed in)
28
+
# List all available built-in fonts (pass emojis=True for composed fonts)
30
29
for info in FontManager.listFonts():
31
30
print(info["name"], info["size"])
32
31
33
-
# Get all available emoji codepoints (union across all size tiers)
32
+
# Get all available emoji codepoints
34
33
for cp in FontManager.getEmojiCodepoints():
35
34
print(hex(cp))
36
35
```
@@ -41,10 +40,10 @@ FontManager is implemented as a singleton using class variables and class method
41
40
42
41
### Font composition
43
42
44
-
When `emoji=True` (the default), `getFont()` wraps the requested base font in an LVGL imgfont that renders emoji as scaled PNG images. The imgfont's `fallback` is set to the base font, so LVGL automatically falls through to the base font for any codepoint that is not an emoji.
43
+
When `emoji=True`, `getFont()` wraps the requested base font in an LVGL imgfont that renders emoji as scaled PNG images. The imgfont's `fallback` is set to the base font, so LVGL automatically falls through to the base font for any codepoint that is not an emoji.
|`20x20/`| All fonts — emoji are rendered at 20×20 px and nearest-neighbour scaled up or down by LVGL as needed |
62
60
63
-
`_imgfont_path_cb` receives the rendering font's pixel height and picks the smallest tier whose `max_height` is ≥ the target. This minimises (or eliminates) the nearest-neighbour downscale performed by LVGL's software renderer.
61
+
`_imgfont_path_cb` receives the rendering font's pixel height and returns the 20×20 emoji source. LVGL's software renderer performs nearest-neighbour scaling to fit the target font size.
64
62
65
63
### Caching layers
66
64
@@ -75,7 +73,7 @@ Emoji PNGs are stored in size-specific directories under `builtin/res/emojis/`:
Return a font object suitable for use with `set_style_text_font()`.
81
79
@@ -84,7 +82,7 @@ Return a font object suitable for use with `set_style_text_font()`.
84
82
-`size` (int, optional): Target pixel size. Snapped to the nearest available builtin size. Defaults to 12.
85
83
-`ttf` (str, optional): Path to a `.ttf` file (e.g. `"M:apps/myapp/assets/MyFont.ttf"`). When provided, `family` is ignored.
86
84
-`family` (str, optional): Font family name — `"Montserrat"` (default) or `"Unscii"`.
87
-
-`emoji` (bool): If `True` (default), the returned font transparently renders emoji via a PNG imgfont fallback. Pass `False` to get the raw base font (useful for `get_glyph_dsc` enumeration).
85
+
-`emoji` (bool, optional): If `True`, the returned font transparently renders emoji via a PNG imgfont fallback. Defaults to `False`. Pass `True` to enable inline emoji rendering (adds a small rendering cost per emoji glyph).
88
86
89
87
**Returns:**`lv.font_t` — the requested font, possibly wrapped with emoji support.
90
88
@@ -94,17 +92,17 @@ Return a font object suitable for use with `set_style_text_font()`.
94
92
from mpos import FontManager
95
93
import lvgl as lv
96
94
97
-
font = FontManager.getFont(size=24, family="Montserrat")
95
+
font = FontManager.getFont(size=24, family="Montserrat", emoji=True)
98
96
label = lv.label(screen)
99
97
label.set_style_text_font(font, lv.PART.MAIN)
100
98
label.set_text("Hello ❤️ 😀")
101
99
```
102
100
103
101
---
104
102
105
-
### `listFonts()`
103
+
### `listFonts(emojis=False)`
106
104
107
-
Return a list of all available built-in fonts, each already composed with emoji support.
105
+
Return a list of all available built-in fonts. By default returns raw base fonts; pass `emojis=True` to wrap each font with emoji composition.
108
106
109
107
**Returns:** list of dicts, each with keys:
110
108
@@ -120,7 +118,7 @@ Return a list of all available built-in fonts, each already composed with emoji
Emoji PNGs are stored in `internal_filesystem/builtin/res/emojis/` and are included in the firmware image at `/builtin/res/emojis/` on the device filesystem. Each subdirectory is a size tier:
166
+
Emoji PNGs are stored in `internal_filesystem/builtin/res/emojis/` and are included in the firmware image at `/builtin/res/emojis/` on the device filesystem:
169
167
170
168
```
171
169
builtin/res/emojis/
172
-
├── 20x20/ # Pre-rendered at 20×20 px (Lanczos-downscaled from 56×56)
173
-
│ ├── 1F600.png
174
-
│ ├── 263A.png
175
-
│ └── ...
176
-
└── 56x56/ # Cropped from original 72×72 OpenMoji PNGs
170
+
└── 20x20/ # Pre-rendered at 20×20 px
177
171
├── 1F600.png
178
172
├── 263A.png
179
173
└── ...
180
174
```
181
175
182
-
Files are named by their Unicode codepoint in uppercase hex (e.g. `1F600.png` for 😀). FontManager scans each directory at runtime and builds a `{codepoint: path}` map.
176
+
Files are named by their Unicode codepoint in uppercase hex (e.g. `1F600.png` for 😀). FontManager scans the directory at runtime and builds a `{codepoint: path}` map.
183
177
184
178
### Adding new emoji
185
179
186
-
1. Add a PNG named `<CODEPOINT_HEX>.png` to both `56x56/` and `20x20/` (generate the 20×20 version with ImageMagick):
180
+
1. Add a PNG named `<CODEPOINT_HEX>.png` to `20x20/`:
0 commit comments