mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 23:08:11 +00:00
fix(ui): unified unknown-char block rendering and display layout fixes
- 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>
This commit is contained in:
@@ -31,6 +31,7 @@ public:
|
||||
virtual int getCharWidth() const { return 6; } // typical character advance width (px)
|
||||
virtual int getLineHeight() const { return 8; } // pixel rows per text line
|
||||
virtual void setLemonFont(bool) { } // no-op; overridden by displays that support Lemon
|
||||
virtual bool isLemonFont() const { return false; }
|
||||
|
||||
// Layout helpers — derived from font metrics and screen size.
|
||||
// Use these instead of hardcoded pixel values so layouts adapt to any display.
|
||||
@@ -41,21 +42,30 @@ public:
|
||||
int listVisible() const { return listVisible(lineStep()); }
|
||||
// x where a right-side value column starts (leaves ~8 chars for the value)
|
||||
int valCol() const { return width() - getCharWidth() * 8; }
|
||||
// separator line thickness: 2px on landscape e-ink, 1px on OLED
|
||||
int sepH() const { return (width() >= height()) ? 2 : 1; }
|
||||
virtual void drawTextCentered(int mid_x, int y, const char* str) { // helper method (override to optimise)
|
||||
int w = getTextWidth(str);
|
||||
// true only on landscape e-ink; use instead of comparing pixel counts or getLineHeight()
|
||||
#ifdef EINK_DISPLAY_MODEL
|
||||
bool isLandscape() const { return width() >= height(); }
|
||||
#else
|
||||
bool isLandscape() const { return false; }
|
||||
#endif
|
||||
// separator line thickness: 2px on landscape e-ink, 1px everywhere else
|
||||
int sepH() const { return isLandscape() ? 2 : 1; }
|
||||
virtual void drawTextCentered(int mid_x, int y, const char* str) {
|
||||
char tmp[256]; translateUTF8ToBlocks(tmp, str, sizeof(tmp));
|
||||
int w = getTextWidth(tmp);
|
||||
setCursor(mid_x - w/2, y);
|
||||
print(str);
|
||||
print(tmp);
|
||||
}
|
||||
virtual void drawTextRightAlign(int x_anch, int y, const char* str) {
|
||||
int w = getTextWidth(str);
|
||||
char tmp[256]; translateUTF8ToBlocks(tmp, str, sizeof(tmp));
|
||||
int w = getTextWidth(tmp);
|
||||
setCursor(x_anch - w, y);
|
||||
print(str);
|
||||
print(tmp);
|
||||
}
|
||||
virtual void drawTextLeftAlign(int x_anch, int y, const char* str) {
|
||||
char tmp[256]; translateUTF8ToBlocks(tmp, str, sizeof(tmp));
|
||||
setCursor(x_anch, y);
|
||||
print(str);
|
||||
print(tmp);
|
||||
}
|
||||
|
||||
static char transliterateCodepoint(uint32_t cp) {
|
||||
@@ -137,7 +147,7 @@ public:
|
||||
case 0x00E7: return 'c'; case 0x00C7: return 'C'; // ç Ç
|
||||
case 0x00F1: return 'n'; case 0x00D1: return 'N'; // ñ Ñ
|
||||
case 0x00FD: return 'y'; case 0x00DD: return 'Y'; // ý Ý
|
||||
default: return '?';
|
||||
default: return '\xDB';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,22 @@ void GxEPDDisplay::setCursor(int x, int y) {
|
||||
|
||||
void GxEPDDisplay::print(const char* str) {
|
||||
display_crc.update<char>(str, strlen(str));
|
||||
display.print(str);
|
||||
if (!_use_lemon) {
|
||||
display.print(str);
|
||||
return;
|
||||
}
|
||||
int sc = (width() >= height()) ? 2 : 1;
|
||||
for (const char* p = str; *p; p++) {
|
||||
if ((uint8_t)*p == 0xDB) {
|
||||
int cx = display.getCursorX();
|
||||
int cy = display.getCursorY();
|
||||
display.fillRect(cx, cy - 8 * sc, 5 * sc, 8 * sc, _curr_color);
|
||||
display.setCursor(cx + 6 * sc, cy);
|
||||
} else {
|
||||
char tmp[2] = {*p, 0};
|
||||
display.print(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GxEPDDisplay::fillRect(int x, int y, int w, int h) {
|
||||
@@ -162,9 +177,11 @@ void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
|
||||
}
|
||||
|
||||
uint16_t GxEPDDisplay::getTextWidth(const char* str) {
|
||||
display.setTextWrap(false);
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
|
||||
display.setTextWrap(true);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
return (_use_lemon ? 10 : 8) * sc;
|
||||
}
|
||||
void setLemonFont(bool enabled) override { _use_lemon = enabled; }
|
||||
|
||||
bool isLemonFont() const override { return _use_lemon; }
|
||||
bool begin();
|
||||
|
||||
bool isOn() override { return _isOn; }
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
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; }
|
||||
bool isLemonFont() const override { return _use_lemon; }
|
||||
void translateUTF8ToBlocks(char* dest, const char* src, size_t dest_size) override;
|
||||
void setBrightness(uint8_t level) override;
|
||||
void endFrame() override;
|
||||
|
||||
Reference in New Issue
Block a user