setTextSize(2/3) switches GFX to non-Lemon fonts (built-in scaled or
FreeSans18pt). The Lemon path bypassed GFX entirely and rendered glyphs
at size 1 scale, shrinking splash version and clock when Lemon font
was active.
Refresh CODE_REVIEW.md: remove resolved issues (signed-int timing vars,
abs() no-op, XBM CRC, loadPrefs nesting, lock-screen LPP thrash, reply
prefix raw UTF-8), add new findings (upstream-merge surface, virtual
width()/height() per glyph, page_order sentinel), list enhancement
ideas.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The placeholder rectangle for codepoints outside U+0020-U+04FF was drawn
1 scale unit too low (y-7*sc instead of y-8*sc relative to the GFX
baseline), causing it to sit below full-height glyphs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adafruit GFX write(uint8_t) treats each byte as a glyph index and cannot
decode multi-byte UTF-8 sequences, so Cyrillic and other non-ASCII chars
were rendered as garbage even with the Lemon font selected.
Add decodeUtf8 + drawLemonChar + lemonXAdvance to GxEPDDisplay, mirroring
the existing SH1106Display implementation. Override print() for Lemon mode
to decode UTF-8 codepoints and draw each glyph directly; override
getTextWidth() to sum per-codepoint advances.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add "Full rfsh" setting (e-ink only) with options off/5/10/20/30
partial refreshes between full refreshes. Prevents ghosting on panels
that accumulate artifacts after many partial updates.
GxEPDDisplay counts partial refreshes and calls display.display(false)
every N frames when the interval is set. Persisted in DataStore and
applied at startup via applyFullRefreshInterval().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GxEPDDisplay::print() renders '\xDB' as filled rect for Lemon font,
matching OLED Lemon block behavior
- Remove translateUTF8ToBlocks override (base class passthrough sufficient)
- transliterateCodepoint fallback changed '?' → '\xDB' for consistency
- drawTextCentered/Right/LeftAlign now call translateUTF8ToBlocks
- isLemonFont() added to DisplayDriver, SH1106Display, GxEPDDisplay
- isLandscape() guarded by EINK_DISPLAY_MODEL to distinguish OLED vs e-ink
- ind_h trims indicator box height only for Lemon font
- getTextWidth disables wrap before getTextBounds, restores after
- QuickMsgScreen: tighter hist_item padding; 2 messages visible with Lemon
- Hibernate hint fits on one line when width allows, splits otherwise
- BLE PIN page shows toggle hint on landscape e-ink
- Remove unused muted_icon bitmap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GxEPDDisplay: fontAscender only applies to sz=1 with Lemon; sz=2 (NULL font)
was incorrectly getting a 16px cursor offset, causing clock text to render
16px lower than expected and overlap the date line
- KeyboardWidget: compute cell_h from available screen height instead of lh+1;
tighten sep_y to lh so the grid fits within 122px even with Lemon font (lh=20)
- SettingsScreen renderBar: constrain box size to available width so the 5th
buzzer-volume square doesn't overflow past the right edge with Lemon font
- NearbyScreen discover detail: manually truncate b64 public key by charWidth
to guarantee one-line rendering; use dynamic step = (height-hdr)/5 so
Status line doesn't fall off the bottom of the screen
- NearbyScreen contacts detail: merge dist+az into one line and use dynamic
step to fit 5 lines within the display; removes the off-screen Seen: row
- AutoAdvertScreen: replace lineStep() gap before hints with 4px fixed gap
so both hint lines fit within the display with large fonts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Portrait mode (122px wide) matches the OLED's ~21 chars/line with a 1× font.
Landscape mode (250px wide) was using the same small 6×8 font, leaving text
physically tiny and the wide display underutilised.
Size 1 now scales by orientation: 1× (6×8 / Lemon 5×10) in portrait,
2× (12×16 / Lemon 10×20) in landscape. Size 2 stays at 12×16 and size 3
at FreeSans18pt in both orientations — their layout Y-positions are hardcoded
so they cannot be scaled without a full layout refactor.
fontAscender() updated to accept a scale parameter; Lemon ascender becomes
8×scale (8px portrait, 16px landscape) to keep top-of-cell coordinate
semantics consistent with the rest of the UI code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Layout fix: GxEPDDisplay was using proportional GFX fonts (FreeSans9pt/12pt)
for sizes 1 and 2, giving lineHeight=16/20 instead of the 8/16 the UI layout
expects (designed for the OLED's bitmap font). Replaced with the GFX built-in
6×8 bitmap font (size 1) and its 2× scaled variant 12×16 (size 2). Size 3
keeps FreeSans18pt for large headings. fontAscender updated accordingly:
built-in font cursor is top-left (offset=0), Lemon GFX font adds 8px,
only FreeSans18pt still adds 26px.
Lemon font: LemonFont.h already stores the font in GFXfont format, so
GxEPDDisplay can use it directly via display.setFont(&Lemon). Added
_use_lemon flag, setLemonFont() override, and size-1 font selection in
setTextSize()/startFrame(). Adafruit GFX handles UTF-8 decoding for GFX
fonts, so Unicode characters (Cyrillic etc.) render correctly. The FONT
setting in SettingsScreen now works on e-ink the same as on OLED.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds Settings > Display > Rotation (0°/90°/180°/270°) that persists to
NodePrefs and is applied on startup. Falls back to compile-time
DISPLAY_ROTATION when the field is missing from an older prefs file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove fixed 128×128 virtual space and scaling; use 1:1 pixel mapping
- Display dimensions derived from panel native size + DISPLAY_ROTATION
- setCursor compensates for GFX font baseline offset (ascender per font size)
- Add getLineHeight() / getCharWidth() overrides for FreeSans fonts
- New envs: landscape (250×122) and portrait (122×250), BLE and dual variants
- Integrate all wio-tracker-l1-improvements features into e-ink build
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added getTextWidth method to DisplayDriver interface
- Implemented getTextWidth in all display classes
- Updated examples to use getTextWidth directly