perf(ui): O(n) FullscreenMsgView wrap via getCodepointWidth virtual

The wrap loop used to memcpy a growing substring and call getTextWidth
on it for every appended codepoint — O(n²) UTF-8 decoding with Lemon
font, ~5-20 ms on a full e-ink redraw of a long message.

Add DisplayDriver::getCodepointWidth(cp) (default: build a UTF-8 buffer
and forward to getTextWidth) plus DisplayDriver::decodeCodepoint() as
the shared UTF-8 walker. Override getCodepointWidth in GxEPDDisplay
(direct lemonXAdvance for Lemon size 1) and SH1106Display (lemonXAdvance
for Lemon, fixed 6*sz for built-in font). FullscreenMsgView now walks
codepoints once and sums widths incrementally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-24 20:22:16 +02:00
co-authored by Claude Sonnet 4.6
parent 87bdc5cb9f
commit 74764aed2b
4 changed files with 68 additions and 19 deletions
+4
View File
@@ -48,6 +48,10 @@ public:
void drawRect(int x, int y, int w, int h) override;
void drawXbm(int x, int y, const uint8_t *bits, int w, int h) override;
uint16_t getTextWidth(const char *str) override;
uint16_t getCodepointWidth(uint32_t cp) override {
if (_use_lemon) return lemonXAdvance(cp);
return 6 * _text_sz; // built-in 5x7 font: 6 px advance per glyph
}
int getCharWidth() const override { return (_use_lemon ? 5 : 6) * _text_sz; }
int getLineHeight() const override { return (_use_lemon ? 9 : 8) * _text_sz; }
void setLemonFont(bool enabled) override { _use_lemon = enabled; _vw_dirty = true; }