mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-27 15:28:11 +00:00
feat: dynamic font-adaptive layout and Lemon font icon support for SH1106
- Add getCharWidth()/getLineHeight() virtual methods to DisplayDriver so all layout math adapts to whatever font is active - Fix Lemon font baseline offset from +8 to +6 (cap height, not FONT_ASCENT) - Add LemonIcons.h with Private Use Area glyph table; U+E03B mute icon rendered via drawLemonChar icon lookup - FullscreenMsgView: compute wrap width and visible lines dynamically from display font metrics instead of hardcoded constants - SettingsScreen and MessagesScreen: replace hardcoded ITEM_H/VISIBLE with members computed at render() time from getLineHeight() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,8 @@ public:
|
||||
virtual void drawRect(int x, int y, int w, int h) = 0;
|
||||
virtual void drawXbm(int x, int y, const uint8_t* bits, int w, int h) = 0;
|
||||
virtual uint16_t getTextWidth(const char* str) = 0;
|
||||
virtual int getCharWidth() const { return 6; } // advance width of a typical character (xAdvance for monospace)
|
||||
virtual int getLineHeight() const { return 8; } // pixel rows per line (cell height, not just glyph height)
|
||||
virtual void drawTextCentered(int mid_x, int y, const char* str) { // helper method (override to optimise)
|
||||
int w = getTextWidth(str);
|
||||
setCursor(mid_x - w/2, y);
|
||||
|
||||
19
src/helpers/ui/LemonIcons.h
Normal file
19
src/helpers/ui/LemonIcons.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Lemon font icon glyphs (Private Use Area), converted manually from lemon.bdf
|
||||
// Add new icons by appending to the bitmap array, lemonIconCPs, and lemonIconGlyphs.
|
||||
#pragma once
|
||||
#include <Adafruit_GFX.h>
|
||||
|
||||
static const uint8_t lemonIconBitmaps[] PROGMEM = {
|
||||
0xEE, 0xBA, 0x2B, 0xA3, 0xB0, // U+E03B mute: 6×6, yoff=0
|
||||
};
|
||||
|
||||
static const uint32_t lemonIconCPs[] PROGMEM = {
|
||||
0xE03B, // mute
|
||||
};
|
||||
|
||||
static const GFXglyph lemonIconGlyphs[] PROGMEM = {
|
||||
// off w h adv xo yo
|
||||
{ 0, 6, 6, 5, 0, -6 }, // U+E03B mute
|
||||
};
|
||||
|
||||
static const uint8_t lemonIconCount = sizeof(lemonIconCPs) / sizeof(lemonIconCPs[0]);
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <Adafruit_GrayOLED.h>
|
||||
#include "Adafruit_SH110X.h"
|
||||
#include "LemonFont.h"
|
||||
#include "LemonIcons.h"
|
||||
|
||||
bool SH1106Display::i2c_probe(TwoWire &wire, uint8_t addr)
|
||||
{
|
||||
@@ -90,6 +91,27 @@ uint32_t SH1106Display::decodeUtf8(const uint8_t*& p) {
|
||||
|
||||
// Draw one Lemon glyph at (x, y), return new cursor x.
|
||||
int16_t SH1106Display::drawLemonChar(int16_t x, int16_t y, uint32_t cp) {
|
||||
// Check icon table for Private Use Area codepoints
|
||||
for (uint8_t i = 0; i < lemonIconCount; i++) {
|
||||
if (pgm_read_dword(&lemonIconCPs[i]) == cp) {
|
||||
const GFXglyph* g = &lemonIconGlyphs[i];
|
||||
uint8_t w = pgm_read_byte(&g->width);
|
||||
uint8_t h = pgm_read_byte(&g->height);
|
||||
int8_t xo = (int8_t)pgm_read_byte(&g->xOffset);
|
||||
int8_t yo = (int8_t)pgm_read_byte(&g->yOffset);
|
||||
uint8_t xa = pgm_read_byte(&g->xAdvance);
|
||||
uint16_t bo = pgm_read_word(&g->bitmapOffset);
|
||||
uint8_t bits = 0, bit = 0;
|
||||
for (uint8_t row = 0; row < h; row++)
|
||||
for (uint8_t col = 0; col < w; col++) {
|
||||
if (!bit) { bits = pgm_read_byte(&lemonIconBitmaps[bo++]); bit = 0x80; }
|
||||
if (bits & bit) display.drawPixel(x + xo + col, y + 6 + yo + row, _color);
|
||||
bit >>= 1;
|
||||
}
|
||||
return x + xa;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp < Lemon.first || cp > Lemon.last) {
|
||||
// outside font range — use default advance
|
||||
return x + 6;
|
||||
@@ -107,7 +129,7 @@ int16_t SH1106Display::drawLemonChar(int16_t x, int16_t y, uint32_t cp) {
|
||||
for (uint8_t col = 0; col < w; col++) {
|
||||
if (!bit) { bits = pgm_read_byte(&lemonBitmaps[bo++]); bit = 0x80; }
|
||||
if (bits & bit)
|
||||
display.drawPixel(x + xo + col, y + yo + row, _color);
|
||||
display.drawPixel(x + xo + col, y + 6 + yo + row, _color); // +6 = cap height: cursor y aligns with top of uppercase/digit glyphs
|
||||
bit >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ 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;
|
||||
int getCharWidth() const override { return 5; } // Lemon font: xAdvance = 5
|
||||
int getLineHeight() const override { return 9; } // Lemon font: visual line spacing (yAdvance=10, used as 9 for tighter fit)
|
||||
void setBrightness(uint8_t level) override;
|
||||
void endFrame() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user