mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
feat(eink): Text size and Icon size settings for big panels
On an 800x480 panel the doubled 6x9 font and the status bar's icons are tiny. Two opt-in build flags, each also a setting under Settings > Display: - EINK_FONT_SCALE=<n>: the landscape font's pixel multiplier (stock 2). Settings > Display > Text size (1x-5x) overrides it at run time (DisplayDriver::setUiScale -> EinkGfxDisplay re-lays out). - STATUS_ICON_SCALE=<n>: Home's status icons, battery and page-icon row drawn at n x their pixel grid, the bar growing to fit. 0 = Auto, 1.5x the text's pixel scale. Settings > Display > Icon size (Auto, 1x-8x). Both live in their own /ui_scale file, so NodePrefs is untouched. Icon size appears only where STATUS_ICON_SCALE is set; Text size appears on every e-ink build with the full-refresh setting, and builds that set neither flag draw as before until it is changed. The GDEQ0426T82 env defaults to 4x text with Auto icons. Tested in the native sim at 800x480. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KxAZVAbhhYr18Dd4guTQM1
This commit is contained in:
@@ -26,6 +26,10 @@ class SettingsScreen : public UIScreen {
|
||||
#endif
|
||||
#if FEAT_FULL_REFRESH_SETTING
|
||||
EINK_FULL_REFRESH,
|
||||
UI_TEXT_SCALE, // Text size: 1x..5x the 6x9 font
|
||||
#if STATUS_ICONS_SCALED
|
||||
UI_ICON_SCALE, // Icon size: Auto, 1x..8x
|
||||
#endif
|
||||
#endif
|
||||
// Sound section
|
||||
SECTION_SOUND,
|
||||
@@ -526,6 +530,18 @@ class SettingsScreen : public UIScreen {
|
||||
uint8_t idx = p ? p->eink_full_refresh_every : 0;
|
||||
if (idx >= EINK_FULL_REFRESH_COUNT) idx = 0;
|
||||
val("Full rfsh", EINK_FULL_REFRESH_LABELS[idx]);
|
||||
} else if (item == UI_TEXT_SCALE) {
|
||||
char b[4];
|
||||
snprintf(b, sizeof(b), "%ux", (unsigned)_task->getUiFontScale());
|
||||
val("Text size", b);
|
||||
#if STATUS_ICONS_SCALED
|
||||
} else if (item == UI_ICON_SCALE) {
|
||||
char b[12];
|
||||
const uint8_t v = _task->getStatusIconScale();
|
||||
if (v == 0) snprintf(b, sizeof(b), "Auto");
|
||||
else snprintf(b, sizeof(b), "%ux", (unsigned)v);
|
||||
val("Icon size", b);
|
||||
#endif
|
||||
#endif
|
||||
} else if (item == DM_FILTER) {
|
||||
val("DMs", (p && p->dm_show_all) ? "All" : "Fav");
|
||||
@@ -1036,6 +1052,21 @@ public:
|
||||
_dirty = true;
|
||||
return true;
|
||||
}
|
||||
if (_selected == UI_TEXT_SCALE && (left || right || enter)) {
|
||||
int v = _task->getUiFontScale(); // 1..5, wrapping
|
||||
v = left ? (v <= 1 ? 5 : v - 1) : (v >= 5 ? 1 : v + 1);
|
||||
_task->setUiFontScale(v); // saved to /ui_scale immediately
|
||||
return true;
|
||||
}
|
||||
#if STATUS_ICONS_SCALED
|
||||
if (_selected == UI_ICON_SCALE && (left || right || enter)) {
|
||||
const int n = STATUS_ICON_SCALE_MAX + 1; // Auto, 1x..8x
|
||||
int v = _task->getStatusIconScale();
|
||||
v = (v + (left ? n - 1 : 1)) % n;
|
||||
_task->setStatusIconScale(v); // saved to /ui_scale immediately
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (_selected == DM_FILTER && p && (left || right || enter)) {
|
||||
p->dm_show_all = p->dm_show_all ? 0 : 1;
|
||||
|
||||
@@ -337,8 +337,8 @@ class HomeScreen : public UIScreen {
|
||||
|
||||
// First row under the header and the page-icon row (see render()).
|
||||
static int contentTop(DisplayDriver& d) {
|
||||
const int pg_half = (PAGE_ICON_PX * miniIconScale(d) + 1) / 2;
|
||||
return d.getLineHeight() + 2 * pg_half + 4;
|
||||
const int pg_half = (PAGE_ICON_PX * statusIconScale(d) + 1) / 2;
|
||||
return statusBarH(d) + 2 * pg_half + 4;
|
||||
}
|
||||
// 0..1 eased progress of the running slide, or -1 when none.
|
||||
float slideProgress() {
|
||||
@@ -724,8 +724,11 @@ class HomeScreen : public UIScreen {
|
||||
|
||||
const int lh = display.getLineHeight();
|
||||
const int cw = display.getCharWidth();
|
||||
const int ind = cw + 2; // single-char indicator width
|
||||
const int ind_h = display.isSingleFont() ? lh - 2 : lh;
|
||||
const int sis = statusIconScale(display); // STATUS_ICON_SCALE, or the font's
|
||||
const int bar_h = statusBarH(display);
|
||||
const int ind = STATUS_ICONS_SCALED ? 7 * sis + 2 : cw + 2; // indicator slot width
|
||||
const int ind_h = (bar_h > lh) ? bar_h - 2 : (display.isSingleFont() ? lh - 2 : lh);
|
||||
const int text_y = (bar_h > lh) ? (bar_h - lh) / 2 : 0; // % / V text centred in a tall bar
|
||||
const int ind_gap = display.pixelScale() > 1 ? 3 : 1; // gap between indicator boxes
|
||||
|
||||
int battLeftX;
|
||||
@@ -733,17 +736,17 @@ class HomeScreen : public UIScreen {
|
||||
char buf[6];
|
||||
snprintf(buf, sizeof(buf),"%d%%", pct);
|
||||
battLeftX = display.width() - display.getTextWidth(buf) - 1;
|
||||
display.setCursor(battLeftX, 0);
|
||||
display.setCursor(battLeftX, text_y);
|
||||
display.print(buf);
|
||||
} else if (mode == battery::VOLTAGE) {
|
||||
char buf[8];
|
||||
snprintf(buf, sizeof(buf),"%u.%02uV", batteryMilliVolts / 1000, (batteryMilliVolts % 1000) / 10);
|
||||
battLeftX = display.width() - display.getTextWidth(buf) - 1;
|
||||
display.setCursor(battLeftX, 0);
|
||||
display.setCursor(battLeftX, text_y);
|
||||
display.print(buf);
|
||||
} else { // icon — scales with lh, same box height as the status icons beside it (ind_h)
|
||||
const int iconH = ind_h;
|
||||
const int iconW = lh * 2;
|
||||
const int iconW = (bar_h > lh) ? ind_h * 2 : lh * 2;
|
||||
const int bm = display.pixelScale() > 1 ? 3 : 2; // inner margin: 3px on a doubled panel, else 2px
|
||||
battLeftX = display.width() - iconW - 3;
|
||||
// The outline with its corner pixels left out, softly rounded.
|
||||
@@ -809,7 +812,8 @@ class HomeScreen : public UIScreen {
|
||||
if (!s.active) continue;
|
||||
int ix = x - ind - ind_gap;
|
||||
if (ix < name_min) break; // out of room — drop this + all lower priority
|
||||
drawSlotIcon(display, ix, ind, ind_h, *s.icon);
|
||||
if (STATUS_ICONS_SCALED) drawSlotIconScaled(display, ix, ind, ind_h, *s.icon, sis);
|
||||
else drawSlotIcon(display, ix, ind, ind_h, *s.icon);
|
||||
x = ix;
|
||||
}
|
||||
return x;
|
||||
@@ -1240,7 +1244,7 @@ public:
|
||||
const int W = d.width(), H = d.height();
|
||||
d.setColor(DisplayDriver::LIGHT);
|
||||
d.setTextSize(1);
|
||||
const int lh = d.getLineHeight(), top = lh + 3;
|
||||
const int lh = d.getLineHeight(), top = statusBarH(d) + 3;
|
||||
const bool hint = Features::IS_EINK || _task->lockHintShown();
|
||||
const int pill_y = H - lh - 3; // the bottom pill, clear of what's above
|
||||
const int unread = _task->getDMUnreadTotal() + _task->getChannelUnreadCount() + _task->getRoomUnreadCount();
|
||||
@@ -1476,8 +1480,8 @@ public:
|
||||
// Page-indicator row: small page icons (PAGE_ICON_PX) replace the old dots. Centre and
|
||||
// gap scale with the font so the band clears the header above and content
|
||||
// below (identical to the old lh+4 / +6 dots layout at 1x).
|
||||
const int pg_half = (PAGE_ICON_PX * miniIconScale(display) + 1) / 2;
|
||||
const int dots_y = lh + pg_half + 1; // icon-row centre, below the header
|
||||
const int pg_half = (PAGE_ICON_PX * statusIconScale(display) + 1) / 2; // page icons follow STATUS_ICON_SCALE
|
||||
const int dots_y = statusBarH(display) + pg_half + 1; // icon-row centre, below the header
|
||||
const int content_y = contentTop(display); // first content row, below the icons
|
||||
const float slide = slideProgress(); // -1, or how far a page turn has got
|
||||
|
||||
@@ -1492,6 +1496,7 @@ public:
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
|
||||
if (_page != LOCK) {
|
||||
const int bar_ty = (statusBarH(display) - lh) / 2; // text centred in a tall bar (STATUS_ICON_SCALE)
|
||||
// The time, once the clock is set (the node name before that): the
|
||||
// name is what others see, the time is what you glance at here.
|
||||
char filtered_name[sizeof(_node_prefs->node_name)];
|
||||
@@ -1517,10 +1522,10 @@ public:
|
||||
char pwr_buf[8];
|
||||
snprintf(pwr_buf, sizeof(pwr_buf), "%ddB", (int)radio_driver.getTxPower());
|
||||
int pwr_w = display.getTextWidth(pwr_buf);
|
||||
display.drawTextEllipsized(0, 0, rightEdge - 2 - pwr_w - 2, filtered_name);
|
||||
display.drawTextRightAlign(rightEdge - 2, 0, pwr_buf);
|
||||
display.drawTextEllipsized(0, bar_ty, rightEdge - 2 - pwr_w - 2, filtered_name);
|
||||
display.drawTextRightAlign(rightEdge - 2, bar_ty, pwr_buf);
|
||||
} else {
|
||||
display.drawTextEllipsized(0, 0, rightEdge - 2, filtered_name);
|
||||
display.drawTextEllipsized(0, bar_ty, rightEdge - 2, filtered_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1535,7 +1540,7 @@ public:
|
||||
int order[(int)Count]; int n = buildVisibleOrder(order);
|
||||
int curr_vis = 0;
|
||||
for (int i = 0; i < n; i++) if (order[i] == _page) { curr_vis = i; break; }
|
||||
const int s = miniIconScale(display);
|
||||
const int s = statusIconScale(display); // STATUS_ICON_SCALE, or the font's
|
||||
const int icon_w = PAGE_ICON_PX * s;
|
||||
int pitch = icon_w + 5 * s; // comfortable spacing
|
||||
if (n > 1) { // shrink to fit if many pages
|
||||
@@ -1560,7 +1565,7 @@ public:
|
||||
if (d2 <= pw - icon_w) display.setColor(DisplayDriver::DARK); // inside the pill
|
||||
else if (d2 < pw + icon_w) { x += pitch; continue; } // half under the gliding pill
|
||||
else display.setColor(DisplayDriver::LIGHT);
|
||||
if (ic) miniIconDrawCentered(display, x, dots_y, *ic);
|
||||
if (ic) miniIconDrawCenteredScaled(display, x, dots_y, *ic, s);
|
||||
x += pitch;
|
||||
}
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
@@ -2042,6 +2047,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
applyBrightness();
|
||||
applyRotation();
|
||||
applyFullRefreshInterval();
|
||||
loadUiScale(); // Settings > Display > Text size / Icon size
|
||||
applyAllGpioModes(); // restore persisted pin modes to hardware before any UI/bot use
|
||||
// Locked above (a PIN, or the cover closed) before Home existed to be told.
|
||||
if (_locked) syncLockToHome();
|
||||
@@ -4047,6 +4053,59 @@ void UITask::applyFullRefreshInterval() {
|
||||
}
|
||||
}
|
||||
|
||||
// Text size and Icon size (Settings > Display), in their own /ui_scale file --
|
||||
// [text pixel scale (0 = build default), icon scale (0 = Auto)] -- so the
|
||||
// NodePrefs schema is untouched.
|
||||
static const char* UI_SCALE_FILE = "/ui_scale";
|
||||
static const uint8_t UI_TEXT_SCALE_MAX = 5;
|
||||
|
||||
void UITask::loadUiScale() {
|
||||
uint8_t b[2] = { 0, statusIconScaleSetting() };
|
||||
DataStore* ds = the_mesh.getDataStore();
|
||||
if (ds) {
|
||||
File f = ds->openRead(UI_SCALE_FILE);
|
||||
if (f) {
|
||||
f.read(b, 2);
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
_ui_font_scale = b[0] <= UI_TEXT_SCALE_MAX ? b[0] : 0;
|
||||
if (b[1] <= STATUS_ICON_SCALE_MAX) statusIconScaleSetting() = b[1];
|
||||
if (_display != NULL && _ui_font_scale) _display->setUiScale(_ui_font_scale);
|
||||
}
|
||||
|
||||
void UITask::saveUiScale() {
|
||||
DataStore* ds = the_mesh.getDataStore();
|
||||
if (!ds) return;
|
||||
File f = ds->openWrite(UI_SCALE_FILE);
|
||||
if (f) {
|
||||
uint8_t b[2] = { _ui_font_scale, statusIconScaleSetting() };
|
||||
f.write(b, 2);
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t UITask::getUiFontScale() const {
|
||||
return _display != NULL ? (uint8_t)_display->pixelScale() : 1;
|
||||
}
|
||||
|
||||
void UITask::setUiFontScale(uint8_t s) {
|
||||
if (s < 1 || s > UI_TEXT_SCALE_MAX) s = 1;
|
||||
_ui_font_scale = s;
|
||||
if (_display != NULL) _display->setUiScale(s);
|
||||
_next_refresh = 0;
|
||||
saveUiScale();
|
||||
}
|
||||
|
||||
uint8_t UITask::getStatusIconScale() const { return statusIconScaleSetting(); }
|
||||
|
||||
void UITask::setStatusIconScale(uint8_t s) {
|
||||
if (s > STATUS_ICON_SCALE_MAX) s = 0;
|
||||
statusIconScaleSetting() = s;
|
||||
_next_refresh = 0; // the frame differs, so it's redrawn
|
||||
saveUiScale();
|
||||
}
|
||||
|
||||
void UITask::applySoundPrefs() {
|
||||
#ifdef PIN_BUZZER
|
||||
if (_node_prefs) setBuzzerVolumeLevel(_node_prefs->buzzer_volume); // with a sample at the new level
|
||||
|
||||
@@ -62,6 +62,7 @@ class UITask : public UITaskBase, public UiCoreHost {
|
||||
unsigned long _next_refresh, _auto_off;
|
||||
bool _display_was_on = true; // loop(): messagesInView() last time round
|
||||
NodePrefs* _node_prefs;
|
||||
uint8_t _ui_font_scale = 0; // Settings > Display > Text size (0 = build default)
|
||||
bool _locked;
|
||||
bool _tool_from_home = false;
|
||||
bool messagesInView() const; // Messages on a lit, unlocked display
|
||||
@@ -520,6 +521,14 @@ public:
|
||||
bool savePrefsIfDirty(bool& dirty);
|
||||
void applyRotation();
|
||||
void applyFullRefreshInterval();
|
||||
// Settings > Display > Text size / Icon size. Kept in their own /ui_scale
|
||||
// file rather than NodePrefs, so the prefs schema (and its size assert) is untouched.
|
||||
uint8_t getUiFontScale() const; // the text's current pixel scale
|
||||
void setUiFontScale(uint8_t s); // 1..5: applies + saves
|
||||
uint8_t getStatusIconScale() const; // 0 = Auto (1.5x text), else n
|
||||
void setStatusIconScale(uint8_t s); // 0..8: applies + saves
|
||||
void loadUiScale(); // boot-time restore, from begin()
|
||||
void saveUiScale();
|
||||
uint32_t autoOffMillis() const {
|
||||
if (!_node_prefs || _node_prefs->auto_off_secs == 0) return 0;
|
||||
return (uint32_t)_node_prefs->auto_off_secs * 1000UL;
|
||||
|
||||
@@ -91,6 +91,55 @@ inline void miniIconDrawCentered(DisplayDriver& d, int cx, int cy, const MiniIco
|
||||
miniIconDrawTop(d, cx - (ic.w * s) / 2, cy - (ic.h * s) / 2, ic);
|
||||
}
|
||||
|
||||
// Home status bar icon scale. Defining STATUS_ICON_SCALE (build flag) turns on
|
||||
// scalable status icons: the bar's icons, battery and the page-icon row below it
|
||||
// are drawn at n x their pixel grid, and the bar grows tall enough to hold them --
|
||||
// for big panels whose 1-line bar leaves them tiny. Its value is the default for
|
||||
// Settings > Display > Icon size: 0 = Auto (1.5x the text's pixel scale), else n.
|
||||
// Unset: icons follow the font, as stock.
|
||||
#ifdef STATUS_ICON_SCALE
|
||||
#define STATUS_ICONS_SCALED 1
|
||||
#else
|
||||
#define STATUS_ICONS_SCALED 0
|
||||
#define STATUS_ICON_SCALE 0
|
||||
#endif
|
||||
static constexpr int STATUS_ICON_SCALE_MAX = 8;
|
||||
static constexpr int STATUS_ICON_ROWS = MINI_ICONS_LARGE == 2 ? 9 : 7; // tallest status icon
|
||||
// The Icon size setting (0 = Auto). One instance across translation units.
|
||||
inline uint8_t& statusIconScaleSetting() {
|
||||
static uint8_t v = (STATUS_ICON_SCALE >= 0 && STATUS_ICON_SCALE <= STATUS_ICON_SCALE_MAX) ? STATUS_ICON_SCALE : 0;
|
||||
return v;
|
||||
}
|
||||
inline int statusIconScale(DisplayDriver& d) {
|
||||
if (!STATUS_ICONS_SCALED) return miniIconScale(d);
|
||||
int s = statusIconScaleSetting();
|
||||
if (s == 0) s = (3 * d.pixelScale() + 1) / 2; // Auto: 1.5x the text
|
||||
return s < 1 ? 1 : s;
|
||||
}
|
||||
// Height of the home status bar: one text line, or the scaled icons if taller.
|
||||
inline int statusBarH(DisplayDriver& d) {
|
||||
const int lh = d.getLineHeight();
|
||||
const int ih = STATUS_ICON_ROWS * statusIconScale(d) + 4;
|
||||
return (STATUS_ICONS_SCALED && ih > lh) ? ih : lh;
|
||||
}
|
||||
// miniIconDrawCentered at an explicit scale (the home page-icon row's).
|
||||
inline void miniIconDrawCenteredScaled(DisplayDriver& d, int cx, int cy, const MiniIcon& ic, int s) {
|
||||
const int x = cx - (ic.w * s) / 2, y = cy - (ic.h * s) / 2;
|
||||
for (int r = 0; r < ic.h; r++)
|
||||
for (int c = 0; c < ic.w; c++)
|
||||
if (ic.rows[r] & (1 << c)) d.fillRect(x + c * s, y + r * s, s, s);
|
||||
}
|
||||
// drawSlotIcon at an explicit scale (the status bar's).
|
||||
inline void drawSlotIconScaled(DisplayDriver& d, int x, int box_w, int box_h, const MiniIcon& ic, int s) {
|
||||
int ix = x + (box_w - ic.w * s) / 2;
|
||||
int iy = (box_h - ic.h * s) / 2;
|
||||
if (ix < x) ix = x;
|
||||
if (iy < 0) iy = 0;
|
||||
for (int r = 0; r < ic.h; r++)
|
||||
for (int c = 0; c < ic.w; c++)
|
||||
if (ic.rows[r] & (1 << c)) d.fillRect(ix + c * s, iy + r * s, s, s);
|
||||
}
|
||||
|
||||
// Centre a mini-icon inside the slot [x, 0, box_w, box_h] using the current ink
|
||||
// colour (no background). Centres on the box itself, not the text line, so the
|
||||
// glyph sits dead-centre regardless of font line height.
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
; a failed allocation there crashes into a boot loop. So:
|
||||
; OFFLINE_QUEUE_SIZE 32 (stock e-ink: 128) frees ~17 KB
|
||||
; MAX_CONTACTS 250 (stock: 350) frees ~18 KB
|
||||
; - EINK_FONT_SCALE 4: text at 4x the 6x9 font (24x36 cells, ~33 characters
|
||||
; x 13 lines) -- twice the stock 2x. The default for Settings > Display >
|
||||
; Text size (1x-5x), which overrides it once changed.
|
||||
; - STATUS_ICON_SCALE 0: turns on scalable Home status/page icons; 0 = Auto
|
||||
; (1.5x the text: 6x at 4x text). The default for Settings > Display >
|
||||
; Icon size (Auto, 1x-8x).
|
||||
;
|
||||
; Build: pio run -e WioTrackerL1_GDEQ0426T82_companion_solo_dual
|
||||
[env:WioTrackerL1_GDEQ0426T82_companion_solo_dual]
|
||||
@@ -35,6 +41,8 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-D EINK_DISPLAY_MODEL=GxEPD2_426_GDEQ0426T82
|
||||
-D DISPLAY_ROTATION=0
|
||||
-D JOYSTICK_UPRIGHT_ROTATION=0
|
||||
-D EINK_FONT_SCALE=4
|
||||
-D STATUS_ICON_SCALE=0
|
||||
-D GPS_BAUD_RATE=9600
|
||||
-D ENV_PIN_SDA=PIN_WIRE1_SDA
|
||||
-D ENV_PIN_SCL=PIN_WIRE1_SCL
|
||||
|
||||
@@ -536,6 +536,7 @@ public:
|
||||
virtual void setBrightness(uint8_t level) { } // level 0-4 (min to max), no-op default
|
||||
virtual void setDisplayRotation(uint8_t rot) { } // 0-3, no-op for fixed-orientation displays
|
||||
virtual void setFullRefreshInterval(uint8_t n) { } // e-ink: do full refresh every n partial refreshes (0=never)
|
||||
virtual void setUiScale(uint8_t font_scale) { } // e-ink: text pixel multiplier, 0 = build default
|
||||
// Sideways slide between two frames, for screens that page left/right.
|
||||
// slideBegin() keeps rows y0.. of the frame on screen now; call it before the
|
||||
// next frame is drawn. slideCompose(dx), at the end of drawing that frame,
|
||||
|
||||
@@ -30,6 +30,7 @@ class EinkGfxDisplay : public DisplayDriver {
|
||||
const GFXfont* _font;
|
||||
int _cell_w = 6, _cell_h = 9; // the font's cell, before _px and the text size
|
||||
int _px = 1; // pixel doubling (landscape without EINK_LARGE_FONT)
|
||||
uint8_t _px_override = 0; // Settings > Display > Text size (0 = build default)
|
||||
int _text_sz = 1;
|
||||
int _cx = 0, _cy = 0; // cursor, top of the text row
|
||||
uint32_t _hash = 0, _shown_hash = 0;
|
||||
@@ -74,6 +75,9 @@ public:
|
||||
dest[dest_size - 1] = '\0';
|
||||
}
|
||||
bool isEink() override { return true; }
|
||||
// Runtime text scale (Settings > Display > Text size): re-lays out and forces
|
||||
// a full redraw. 0 = the build default (EINK_FONT_SCALE).
|
||||
void setUiScale(uint8_t font_scale) override { _px_override = font_scale; updateLayout(); }
|
||||
|
||||
void startFrame(Color bkg = DARK) override;
|
||||
void setTextSize(int sz) override;
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
// the font tables below are static arrays.
|
||||
|
||||
#include "EinkGfxDisplay.h"
|
||||
// EINK_FONT_SCALE=<n>: pixel multiplier for the 6x9 font on a landscape panel
|
||||
// without EINK_LARGE_FONT (default 2). 4 on an 800x480 panel = 24x36 cells,
|
||||
// ~33 characters x 13 lines. Settings > Display > Text size overrides it at run time.
|
||||
#ifndef EINK_FONT_SCALE
|
||||
#define EINK_FONT_SCALE 2
|
||||
#endif
|
||||
#include "MiscFixedRenderer.h"
|
||||
#if EINK_LARGE_FONT == 2
|
||||
#include "MiscFixed9x15Font.h"
|
||||
@@ -20,7 +26,8 @@ EinkGfxDisplay::EinkGfxDisplay(int w, int h, Adafruit_GFX& gfx, uint16_t ink, ui
|
||||
void EinkGfxDisplay::updateLayout() {
|
||||
const bool landscape = width() >= height();
|
||||
_font = (EINK_LARGE_FONT && landscape) ? &EINK_LARGE_GFXFONT : &MiscFixed;
|
||||
_px = (!EINK_LARGE_FONT && landscape) ? 2 : 1;
|
||||
_px = (!EINK_LARGE_FONT && landscape) ? EINK_FONT_SCALE : 1;
|
||||
if (_px_override) _px = _px_override;
|
||||
_cell_w = miscFixedCellW(*_font);
|
||||
_cell_h = _font->yAdvance;
|
||||
_vw_dirty = true;
|
||||
@@ -87,7 +94,7 @@ void EinkGfxDisplay::fillRect(int x, int y, int w, int h) {
|
||||
void EinkGfxDisplay::drawRect(int x, int y, int w, int h) {
|
||||
mix<int>(x); mix<int>(y); mix<int>(w); mix<int>(h);
|
||||
_gfx.drawRect(x, y, w, h, _curr);
|
||||
if (_px == 2 && w > 2 && h > 2) _gfx.drawRect(x + 1, y + 1, w - 2, h - 2, _curr);
|
||||
if (_px >= 2 && w > 2 && h > 2) _gfx.drawRect(x + 1, y + 1, w - 2, h - 2, _curr);
|
||||
}
|
||||
|
||||
void EinkGfxDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
|
||||
|
||||
Reference in New Issue
Block a user