fix: draw substitution block for unsupported characters in SH1106 Lemon renderer

- drawLemonChar: for codepoints outside the font range (> U+04FF) that
  are printable (>= U+0020), render a 4×6 filled rectangle instead of
  silently advancing the cursor with no visible output
- decodeUtf8: properly decode 4-byte UTF-8 sequences (U+10000+) to their
  actual codepoints so they reach the block fallback; return U+FFFD for
  genuinely invalid bytes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-18 09:30:25 +02:00
parent acc062718f
commit de8861f574

View File

@@ -84,9 +84,16 @@ uint32_t SH1106Display::decodeUtf8(const uint8_t*& p) {
if (*p) cp = (cp << 6) | (*p++ & 0x3F);
return cp;
}
// 4-byte and invalid — skip continuation bytes
if ((c & 0xF8) == 0xF0) { // 4-byte: U+10000U+10FFFF
uint32_t cp = c & 0x07;
if (*p) cp = (cp << 6) | (*p++ & 0x3F);
if (*p) cp = (cp << 6) | (*p++ & 0x3F);
if (*p) cp = (cp << 6) | (*p++ & 0x3F);
return cp;
}
// invalid byte — skip continuation bytes
while (*p && (*p & 0xC0) == 0x80) p++;
return '?';
return 0xFFFD;
}
// Draw one Lemon glyph at (x, y), return new cursor x.
@@ -113,7 +120,8 @@ int16_t SH1106Display::drawLemonChar(int16_t x, int16_t y, uint32_t cp) {
}
if (cp < Lemon.first || cp > Lemon.last) {
// outside font range — use default advance
if (cp >= 0x20) // not a control character — draw substitution block
display.fillRect(x + 1, y - 1, 4, 6, _color);
return x + 6;
}
const GFXglyph* glyph = &lemonGlyphs[cp - Lemon.first];