mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-27 07:18:11 +00:00
feat: add Char Test screen and extend Lemon font to Greek/Cyrillic
- Add CharTestScreen showing sample characters from 11 scripts (PL, DE, CS, FR, NO, HU, HR, TR, LT, Cyrillic, Greek) as raw UTF-8 to verify native font rendering without transliteration - Add "Char Test" entry to ToolsScreen menu - Regenerate LemonFont.h from lemon.bdf with full U+0020–U+04FF range: 1074 BDF glyphs + 174 placeholders, 4111 bitmap bytes; adds Greek (137 glyphs) and Cyrillic (256 glyphs) coverage; also fixes space advance (DWIDTH=5, was BBX+1=1) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
69
examples/companion_radio/ui-new/CharTestScreen.h
Normal file
69
examples/companion_radio/ui-new/CharTestScreen.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
// Test screen that displays sample characters from various alphabets/scripts.
|
||||
// Useful for verifying transliteration and font coverage on experimental fonts.
|
||||
|
||||
class CharTestScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
int _scroll;
|
||||
int _visible; // updated each render, used by handleInput
|
||||
|
||||
struct TestLine { const char* label; const char* sample; };
|
||||
static const int LINE_COUNT = 11;
|
||||
static const TestLine LINES[LINE_COUNT];
|
||||
|
||||
public:
|
||||
CharTestScreen(UITask* task) : _task(task), _scroll(0), _visible(6) {}
|
||||
|
||||
void enter() { _scroll = 0; }
|
||||
|
||||
int render(DisplayDriver& display) override {
|
||||
display.setTextSize(1);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextCentered(display.width() / 2, 0, "CHAR TEST");
|
||||
display.fillRect(0, 10, display.width(), 1);
|
||||
|
||||
const int lineH = display.getLineHeight();
|
||||
const int startY = 12;
|
||||
_visible = (display.height() - startY) / lineH;
|
||||
|
||||
for (int i = 0; i < _visible && (_scroll + i) < LINE_COUNT; i++) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "%s:%s", LINES[_scroll + i].label, LINES[_scroll + i].sample);
|
||||
display.setCursor(2, startY + i * lineH);
|
||||
display.print(buf);
|
||||
}
|
||||
|
||||
if (_scroll > 0) {
|
||||
display.setCursor(display.width() - 6, startY);
|
||||
display.print("^");
|
||||
}
|
||||
if (_scroll + _visible < LINE_COUNT) {
|
||||
display.setCursor(display.width() - 6, display.height() - lineH);
|
||||
display.print("v");
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
|
||||
bool handleInput(char c) override {
|
||||
if (c == KEY_UP && _scroll > 0) { _scroll--; return true; }
|
||||
if (c == KEY_DOWN && _scroll + _visible < LINE_COUNT) { _scroll++; return true; }
|
||||
if (c == KEY_CANCEL || c == KEY_CONTEXT_MENU) { _task->gotoToolsScreen(); return true; }
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Sample strings are printed as raw UTF-8 (no transliteration) to test native font coverage.
|
||||
// Lemon font covers U+0020–U+04FF: Latin, Greek and Cyrillic all render natively.
|
||||
const CharTestScreen::TestLine CharTestScreen::LINES[CharTestScreen::LINE_COUNT] = {
|
||||
{ "PL", "ąćęłńóśźżĄĆĘŁŃ" }, // Polish
|
||||
{ "DE", "äöüÄÖÜß" }, // German
|
||||
{ "CS", "čďěňřšťžůýČŘŠŤŽ" }, // Czech/Slovak
|
||||
{ "FR", "àâçèêëîïôùûÿ" }, // French
|
||||
{ "NO", "åæøÅÆØðþÐÞ" }, // Nordic/Icelandic
|
||||
{ "HU", "áéíőúűÁÉÍŐÚŰ" }, // Hungarian
|
||||
{ "HR", "čćđšžČĆĐŠŽ" }, // Croatian
|
||||
{ "TR", "çğışöüİŞĞ" }, // Turkish
|
||||
{ "LT", "āēīūģķļņŗėįų" }, // Baltic (Latvian/Lithuanian)
|
||||
{ "RU", "АБВГДЕЖЗабвгдеж" }, // Cyrillic (→ blocks █)
|
||||
{ "GR", "\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4\xCE\xB5\xCE\xB6\xCE\xB7\xCE\xB8\xCE\xB9\xCE\xBA" }, // Greek αβγδεζηθικ (→ blocks █)
|
||||
};
|
||||
@@ -6,7 +6,7 @@ class ToolsScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
int _sel;
|
||||
|
||||
static const int ITEM_COUNT = 4;
|
||||
static const int ITEM_COUNT = 5;
|
||||
static const char* ITEMS[ITEM_COUNT];
|
||||
|
||||
public:
|
||||
@@ -46,8 +46,9 @@ public:
|
||||
if (_sel == 1) { _task->gotoBotScreen(); return true; }
|
||||
if (_sel == 2) { _task->gotoNearbyScreen(); return true; }
|
||||
if (_sel == 3) { _task->gotoAutoAdvertScreen(); return true; }
|
||||
if (_sel == 4) { _task->gotoCharTestScreen(); return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const char* ToolsScreen::ITEMS[4] = { "Ringtone Editor", "Auto-Reply Bot", "Nearby Nodes", "Auto-Advert" };
|
||||
const char* ToolsScreen::ITEMS[5] = { "Ringtone Editor", "Auto-Reply Bot", "Nearby Nodes", "Auto-Advert", "Char Test" };
|
||||
|
||||
@@ -127,6 +127,7 @@ static const uint16_t HP_ALL = 0x01FF;
|
||||
#include "NearbyScreen.h"
|
||||
#include "DashboardConfigScreen.h"
|
||||
#include "AutoAdvertScreen.h"
|
||||
#include "CharTestScreen.h"
|
||||
#include "ToolsScreen.h"
|
||||
|
||||
// ── HomeScreen ────────────────────────────────────────────────────────────────
|
||||
@@ -808,6 +809,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
nearby_screen = new NearbyScreen(this);
|
||||
dashboard_config = new DashboardConfigScreen(this, node_prefs);
|
||||
auto_advert_screen = new AutoAdvertScreen(this, node_prefs);
|
||||
char_test_screen = new CharTestScreen(this);
|
||||
setCurrScreen(splash);
|
||||
|
||||
applyBrightness();
|
||||
@@ -847,6 +849,11 @@ void UITask::gotoAutoAdvertScreen() {
|
||||
setCurrScreen(auto_advert_screen);
|
||||
}
|
||||
|
||||
void UITask::gotoCharTestScreen() {
|
||||
((CharTestScreen*)char_test_screen)->enter();
|
||||
setCurrScreen(char_test_screen);
|
||||
}
|
||||
|
||||
void UITask::playMelody(const char* melody) {
|
||||
#ifdef PIN_BUZZER
|
||||
buzzer.playForced(melody);
|
||||
|
||||
@@ -72,6 +72,7 @@ class UITask : public AbstractUITask {
|
||||
UIScreen* nearby_screen;
|
||||
UIScreen* dashboard_config;
|
||||
UIScreen* auto_advert_screen;
|
||||
UIScreen* char_test_screen;
|
||||
UIScreen* curr;
|
||||
|
||||
void userLedHandler();
|
||||
@@ -113,6 +114,7 @@ public:
|
||||
void gotoNearbyScreen();
|
||||
void gotoDashboardConfig();
|
||||
void gotoAutoAdvertScreen();
|
||||
void gotoCharTestScreen();
|
||||
void playMelody(const char* melody);
|
||||
void stopMelody();
|
||||
bool isMelodyPlaying();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user