fix home screen ui display when montserrat or notosans selected; fix word wrap display for other fonts in tiny mode for ereader

This commit is contained in:
pelgraine
2026-04-19 17:27:48 +10:00
parent 3e6bcfb031
commit 5b38b713da
2 changed files with 45 additions and 28 deletions
@@ -16,7 +16,7 @@ class UITask;
// ============================================================================
#define BOOKS_FOLDER "/books"
#define INDEX_FOLDER "/.indexes"
#define INDEX_VERSION 12 // v12: indexer breaks page BEFORE overflowing line (matches renderer pre-check)
#define INDEX_VERSION 13 // v13: font key in header — auto-invalidate on font/style change
#define PREINDEX_PAGES 100
#define READER_MAX_FILES 50
#define READER_BUF_SIZE 4096
@@ -402,7 +402,8 @@ private:
Mode _mode;
bool _sdReady;
bool _initialized; // Layout metrics calculated
uint8_t _lastFontPref; // Font preference at last layout init (detect changes)
uint8_t _lastFontPref; // Font preference at last layout init (large_font | fontStyle<<4)
uint8_t _fontKey; // Current font key stored in .idx files for cache invalidation
bool _bootIndexed; // Boot-time pre-indexing done
DisplayDriver* _display; // Stored reference for splash screens
@@ -627,6 +628,15 @@ private:
return false;
}
// Font key: page boundaries depend on font metrics — discard if font changed
uint8_t savedFontKey = 0;
idxFile.read(&savedFontKey, 1);
if (savedFontKey != _fontKey) {
idxFile.close();
SD.remove(idxPath.c_str());
return false;
}
idxFile.read((uint8_t*)&savedSize, 4);
idxFile.read((uint8_t*)&pageCount, 4);
idxFile.read(&fullyFlag, 1);
@@ -681,6 +691,7 @@ private:
uint8_t fullyFlag = fullyIndexed ? 1 : 0;
idxFile.write(&version, 1);
idxFile.write(&_fontKey, 1); // Font key for cache invalidation
idxFile.write((uint8_t*)&fileSize, 4);
idxFile.write((uint8_t*)&pageCount, 4);
idxFile.write(&fullyFlag, 1);
@@ -714,8 +725,8 @@ private:
return false;
}
// Seek to lastReadPage field: version(1) + fileSize(4) + pageCount(4) + fullyIndexed(1)
idxFile.seek(1 + 4 + 4 + 1);
// Seek to lastReadPage field: version(1) + fontKey(1) + fileSize(4) + pageCount(4) + fullyIndexed(1)
idxFile.seek(1 + 1 + 4 + 4 + 1);
idxFile.write((uint8_t*)&page, 4);
idxFile.close();
return true;
@@ -1109,8 +1120,10 @@ private:
display.fillRect(0, y, display.width(), listLineH);
#else
// setCursor adds +5 to y internally, but fillRect does not.
// Offset fillRect by +5 to align highlight bar with text.
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width(), listLineH);
// Built-in font: offset by +5 to align with top-left positioned text.
// GFX fonts (large_font or custom style): offset by -2 to cover ascenders above baseline.
int hlOff = (!_prefs->large_font && display.getFontStyle() > 0) ? -2 : _prefs->smallHighlightOff();
display.fillRect(0, y + hlOff, display.width(), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -1281,7 +1294,7 @@ private:
public:
TextReaderScreen(UITask* task, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _mode(FILE_LIST), _sdReady(false), _initialized(false), _lastFontPref(0),
: _task(task), _prefs(prefs), _mode(FILE_LIST), _sdReady(false), _initialized(false), _lastFontPref(0), _fontKey(0),
_bootIndexed(false), _display(nullptr),
_charsPerLine(38), _linesPerPage(22), _lineHeight(5),
_textAreaHeight(100), _headerHeight(14), _footerHeight(14),
@@ -1306,14 +1319,16 @@ public:
// Call once after display is available to calculate layout metrics
void initLayout(DisplayDriver& display) {
// Re-init if font preference changed since last layout
uint8_t curFont = _prefs ? _prefs->large_font : 0;
// Re-init if font preference OR font style changed since last layout
uint8_t curFont = _prefs ? (_prefs->large_font | (display.getFontStyle() << 4)) : 0;
if (_initialized && curFont != _lastFontPref) {
_initialized = false;
_fileCache.clear(); // Page positions are font-dependent — force re-index
Serial.println("TextReader: font changed, recalculating layout");
}
if (_initialized) return;
_lastFontPref = curFont;
_fontKey = curFont; // Stored in .idx files for SD cache invalidation
// Store display reference for splash screens during openBook
_display = &display;
@@ -1344,13 +1359,15 @@ public:
if (_charsPerLine < 15) _charsPerLine = 15;
if (_charsPerLine > 80) _charsPerLine = 80;
#else
// T-Deck Pro: large_font uses FreeSans9pt (proportional) — same fix
if (_prefs && _prefs->large_font) {
// T-Deck Pro: large_font or custom proportional font — measure average
// character width from a sample sentence (M is widest glyph, ~40% wider
// than average, so M-based measurement leaves half the line empty).
if (_prefs && (_prefs->large_font || display.getFontStyle() > 0)) {
const char* sample = "the quick brown fox jumps over lazy dog";
uint16_t sampleW = display.getTextWidth(sample);
int sampleLen = strlen(sample);
if (sampleW > 0 && sampleLen > 0) {
_charsPerLine = (display.width() * sampleLen * 70) / ((int)sampleW * 100);
_charsPerLine = (display.width() * sampleLen * 85) / ((int)sampleW * 100);
}
}
if (_charsPerLine < 15) _charsPerLine = 15;
@@ -1378,10 +1395,13 @@ public:
}
#else
// T-Deck Pro large_font uses FreeSans9pt (yAdvance=22px at scale 1.5625×).
// The 6x8 formula above gives ~5-7 which is way too small — lines overlap.
// Use smallLineH() which is already tuned for this font.
// Custom proportional fonts (Noto Sans, Montserrat) at size 0 also need
// a tuned line height — the 6x8 formula above uses a width:height ratio
// that doesn't apply to GFX fonts, causing overlap or excessive spacing.
if (_prefs && _prefs->large_font) {
_lineHeight = _prefs->smallLineH();
_lineHeight = _prefs->smallLineH(); // 11 — tested for FreeSans9pt
} else if (display.getFontStyle() > 0) {
_lineHeight = 7; // Custom 7pt fonts: 7 * 2.5 = 17.5px — fits ~16 lines/page
}
#endif
@@ -1718,7 +1738,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = startY;
#else
const int bodyTop = startY + (_prefs ? _prefs->smallHighlightOff() : 5);
const int bodyTop = startY + ((_prefs && !_prefs->large_font && _prefs->ui_font_style > 0) ? -2 : (_prefs ? _prefs->smallHighlightOff() : 5));
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
+9 -12
View File
@@ -187,14 +187,14 @@ void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts,
sprintf(pctStr, "%d%%", batteryPercentage);
uint16_t textWidth = display.getTextWidth(pctStr);
if (_node_prefs->large_font) {
// Large font: text only — no room for icon in header
if (_node_prefs->large_font || display.getFontStyle() > 0) {
// Large font or custom proportional font: text only — icon doesn't align
int textX = display.width() - textWidth - 2;
if (outIconX) *outIconX = textX;
display.setCursor(textX, textY);
display.print(pctStr);
} else {
// Tiny font: icon + text
// Classic tiny font (monospaced): icon + text
// layout: [icon][cap 2px][gap 2px][text][margin 2px]
int totalWidth = iconWidth + 2 + 2 + textWidth + 2;
int iconX = display.width() - totalWidth;
@@ -482,11 +482,12 @@ public:
display.setTextSize(_node_prefs->smallTextSize());
int menuLH = _node_prefs->smallLineH();
if (_node_prefs->large_font) {
if (_node_prefs->large_font || display.getFontStyle() > 0) {
// Proportional font: two-column layout with fixed X positions
// Centered to match Classic layout's visual weight (~16-unit margins)
y += 2;
int col1 = 2;
int col2 = display.width() / 2;
int col1 = display.width() / 10; // ~12
int col2 = display.width() * 11 / 20; // ~70
display.setCursor(col1, y); display.print("[M] Messages");
display.setCursor(col2, y); display.print("[C] Contacts");
@@ -524,10 +525,7 @@ public:
#endif
y += menuLH + 2;
} else {
// Monospaced built-in font: centered space-padded strings
// Force Classic style — proportional 7pt custom fonts break column alignment
uint8_t _savedFontStyle = display.getFontStyle();
display.setFontStyle(0);
// Monospaced built-in font (Classic): centered space-padded strings
y += 6;
display.drawTextCentered(display.width() / 2, y, "Press:");
y += 12;
@@ -559,14 +557,13 @@ public:
display.drawTextCentered(display.width() / 2, y, "[F] Discover ");
#endif
y += 14;
display.setFontStyle(_savedFontStyle); // Restore custom font style
}
// Nav hint (only if room)
if (y < display.height() - 14) {
display.setColor(DisplayDriver::GREEN);
display.drawTextCentered(display.width() / 2, y,
_node_prefs->large_font ? "A/D: cycle views" : "Press A/D to cycle home views");
(_node_prefs->large_font || display.getFontStyle() > 0) ? "A/D: cycle views" : "Press A/D to cycle home views");
}
display.setTextSize(1); // restore
#endif