From de8861f574a83dc9acb7df1d7b5930330d9ea61a Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Mon, 18 May 2026 09:30:25 +0200 Subject: [PATCH] fix: draw substitution block for unsupported characters in SH1106 Lemon renderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- src/helpers/ui/SH1106Display.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/helpers/ui/SH1106Display.cpp b/src/helpers/ui/SH1106Display.cpp index 169834f2..c58870b3 100644 --- a/src/helpers/ui/SH1106Display.cpp +++ b/src/helpers/ui/SH1106Display.cpp @@ -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+10000–U+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];