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
@@ -114,6 +114,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 && _text_sz == 1) return lemonXAdvance(cp, scale());
return DisplayDriver::getCodepointWidth(cp);
}
void setDisplayRotation(uint8_t rot) override;
void setFullRefreshInterval(uint8_t n) override { _full_refresh_interval = n; _partial_count = 0; }
void endFrame() override;