mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 11:16:39 +00:00
feat(ui-lvgl): European fonts and phone-style keyboard
Fonts: Noto Sans generated with lv_font_conv (ui-lvgl/fonts/generate.sh, OFL) replaces ASCII-only Montserrat: European Latin (Latin-1, Extended-A/B), Greek, Cyrillic + supplement, typographic punctuation, currency, LVGL symbols + globe; 12/14/16/20 px, clock 40 px digits only (RLE, so LV_USE_FONT_COMPRESSED is on). Keyboard (ui-lvgl/Keyboard.h): one layout per script (Latin QWERTY, Cyrillic, Greek) picked by the same keyboard_main/alt_alphabet prefs as ui-new, globe key to switch, hold a key for its variants in a popup above it, one-shot shift, symbols page; compose limit counted in UTF-8 bytes. First Settings screen (Keyboard: Main / Additional). Long-press variants and UTF-8 case mapping move to ui-core/KeyboardData.h and are shared with ui-new, whose Hold-Enter accents gain Romanian, Turkish, Hungarian, Baltic and Icelandic letters (and ș/ț, Ukrainian / Serbian letters now capitalise). Verified on L2 hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -145,7 +145,7 @@ consumes keys only.
|
||||
|
||||
- LVGL 9 (pinned), memory in a PSRAM pool; partial-render buffers in internal RAM, flush over QSPI via LovyanGFX.
|
||||
- Theme tokens (colours, spacing, typography) in one place — the first chance to realise the "Amber Trace" direction in colour.
|
||||
- Fonts with full Latin/Polish/Cyrillic coverage.
|
||||
- Fonts ✅ Noto Sans generated by `ui-lvgl/fonts/generate.sh` (lv_font_conv): European Latin (Latin-1, Extended-A/B), Greek, Cyrillic + supplement, typographic punctuation, currency, LVGL symbols; 12/14/16/20 px, clock 40 px digits only. On-screen keyboard (`ui-lvgl/Keyboard.h`), phone-style: one layout per script (Latin QWERTY / Cyrillic ЙЦУКЕН / Greek) chosen by the same `keyboard_main_alphabet` / `keyboard_alt_alphabet` prefs as `ui-new` (globe key switches), hold a key for its variants; compose limit counted in UTF-8 bytes. Long-press variants and UTF-8 case mapping are shared with `ui-new` in `ui-core/KeyboardData.h`.
|
||||
- Runs in the WASM sim at 320×240 with mouse as touch, so most UI work needs no flashing.
|
||||
- PR #3381's LVGL UI is a reference for platform glue (flush, GT911, PSRAM pool) only; its screens are not adopted.
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
// Keyboard data shared by every frontend: the long-press variants offered for
|
||||
// a base key (phone-style: hold a letter to get its accented forms) and UTF-8
|
||||
// case mapping for everything the keyboards can produce. Scripts are picked by
|
||||
// NodePrefs::keyboard_main_alphabet / keyboard_alt_alphabet (Latin, Cyrillic,
|
||||
// Greek); Latin diacritics never need a page of their own -- they're all
|
||||
// reachable by holding the base letter.
|
||||
//
|
||||
// Standalone header (no MeshCore / display dependencies).
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace kbd {
|
||||
|
||||
// ── Long-press variants ──────────────────────────────────────────────────────
|
||||
// One UTF-8 string of concatenated variants per base key, lowercase. Latin
|
||||
// covers the union of the European languages written in it (Polish, Czech,
|
||||
// Slovak, German, French, Spanish, Portuguese, Italian, Nordic, Icelandic,
|
||||
// Hungarian, Romanian, Turkish, Baltic, …). Ligature / non-diacritic letters
|
||||
// are filed under their conventional key, as on a phone: ß → s, œ → o,
|
||||
// æ → a, ð → d, þ → t.
|
||||
static const char LATIN_BASES[] = "acdegiklnorstuyz";
|
||||
static const char* const LATIN_VARIANTS[] = {
|
||||
"áàâãäåąăāæ", // a
|
||||
"çćč", // c
|
||||
"ďð", // d
|
||||
"éèêëěęēė", // e
|
||||
"ğģ", // g
|
||||
"íîïīį", // i
|
||||
"ķ", // k
|
||||
"łĺľļ", // l
|
||||
"ñńňņ", // n
|
||||
"óòôõöøœő", // o
|
||||
"řŕ", // r
|
||||
"śšşșß", // s
|
||||
"ťțþ", // t
|
||||
"úùûüůűūų", // u
|
||||
"ýÿ", // y
|
||||
"źżž", // z
|
||||
};
|
||||
static const int LATIN_COUNT = sizeof(LATIN_BASES) - 1;
|
||||
|
||||
// Cyrillic, on a Russian ЙЦУКЕН base: Ukrainian / Belarusian / Serbian /
|
||||
// Macedonian letters under the key they sit on (or sound like).
|
||||
struct Variant { const char* base; const char* variants; };
|
||||
static const Variant CYRILLIC_VARIANTS[] = {
|
||||
{ "е", "ёє" }, { "и", "ії" }, { "г", "ґѓ" }, { "у", "ў" }, { "д", "ђ" },
|
||||
{ "й", "ј" }, { "л", "љ" }, { "н", "њ" }, { "ч", "ћ" }, { "ц", "џ" },
|
||||
{ "к", "ќ" }, { "з", "ѕ" }, { "ь", "ъ" },
|
||||
};
|
||||
static const Variant GREEK_VARIANTS[] = {
|
||||
{ "α", "ά" }, { "ε", "έ" }, { "η", "ή" }, { "ι", "ίϊΐ" }, { "ο", "ό" },
|
||||
{ "υ", "ύϋΰ" }, { "ω", "ώ" }, { "σ", "ς" },
|
||||
};
|
||||
// Punctuation behind the period key (any script).
|
||||
static const char PERIOD_VARIANTS[] = ",?!'\"-:;()";
|
||||
|
||||
// Latin index by ASCII base letter (for callers that key on a char), -1 if none.
|
||||
static inline int latinGroup(char base) {
|
||||
for (int i = 0; i < LATIN_COUNT; i++) if (LATIN_BASES[i] == base) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Variants for a base key given as UTF-8 (lowercase), or nullptr.
|
||||
static inline const char* variantsFor(const char* base) {
|
||||
if (!base || !base[0]) return nullptr;
|
||||
if (strcmp(base, ".") == 0) return PERIOD_VARIANTS;
|
||||
if (base[1] == '\0') {
|
||||
int g = latinGroup(base[0]);
|
||||
return g >= 0 ? LATIN_VARIANTS[g] : nullptr;
|
||||
}
|
||||
for (const Variant& v : CYRILLIC_VARIANTS) if (strcmp(v.base, base) == 0) return v.variants;
|
||||
for (const Variant& v : GREEK_VARIANTS) if (strcmp(v.base, base) == 0) return v.variants;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ── UTF-8 ────────────────────────────────────────────────────────────────────
|
||||
static inline uint32_t decode(const uint8_t*& p) {
|
||||
uint32_t c = *p++;
|
||||
if (c < 0x80) return c;
|
||||
if ((c & 0xE0) == 0xC0) { uint32_t r = (c & 0x1F) << 6; if (*p) r |= (*p++ & 0x3F); return r; }
|
||||
if ((c & 0xF0) == 0xE0) {
|
||||
uint32_t r = (c & 0x0F) << 12;
|
||||
if (*p) r |= (*p++ & 0x3F) << 6;
|
||||
if (*p) r |= (*p++ & 0x3F);
|
||||
return r;
|
||||
}
|
||||
return '?';
|
||||
}
|
||||
|
||||
static inline int encode(uint32_t cp, char* out) {
|
||||
if (cp < 0x80) { out[0] = (char)cp; return 1; }
|
||||
if (cp < 0x800) { out[0] = (char)(0xC0 | (cp >> 6)); out[1] = (char)(0x80 | (cp & 0x3F)); return 2; }
|
||||
out[0] = (char)(0xE0 | (cp >> 12));
|
||||
out[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
|
||||
out[2] = (char)(0x80 | (cp & 0x3F));
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Uppercase of one codepoint, for every letter the keyboards produce. Each
|
||||
// block pairs its cases differently:
|
||||
// - ASCII a-z, Cyrillic а-я, Greek α-ω: flat -0x20. Exceptions: ё → Ё, the
|
||||
// Cyrillic ѐ-џ extras (Ukrainian / Serbian …, U+0450-045F) are -0x50, ς has
|
||||
// no uppercase of its own and maps to Σ, and the tonos vowels ά έ ή ί ό ύ ώ
|
||||
// sit outside α-ω.
|
||||
// - Latin-1 à-þ: flat -0x20 (÷ excluded); ÿ → Ÿ (U+0178) is special.
|
||||
// - Latin Extended-A: adjacent pairs, lowercase = uppercase + 1, but the
|
||||
// parity flips around the unpaired ĸ (U+0138), ʼn (U+0149) and Ÿ (U+0178).
|
||||
// - ș ț (U+0219 / U+021B): same pair rule. Cyrillic ґ (U+0491): pair rule.
|
||||
// - ß → ẞ (U+1E9E).
|
||||
static inline uint32_t toUpper(uint32_t cp) {
|
||||
if (cp == 0x0451) return 0x0401; // ё
|
||||
if (cp >= 0x0450 && cp <= 0x045F) return cp - 0x50; // ѐ-џ
|
||||
if (cp == 0x0491) return 0x0490; // ґ
|
||||
if (cp == 0x03C2) return 0x03A3; // ς → Σ
|
||||
if (cp == 0x03AC) return 0x0386; // ά
|
||||
if (cp >= 0x03AD && cp <= 0x03AF) return cp - 0x25; // έ ή ί
|
||||
if (cp == 0x03CC) return 0x038C; // ό
|
||||
if (cp == 0x03CD || cp == 0x03CE) return cp - 0x3F; // ύ ώ
|
||||
if (cp == 0x03CA || cp == 0x03CB) return cp - 0x20; // ϊ ϋ
|
||||
if (cp == 0x00FF) return 0x0178; // ÿ
|
||||
if (cp == 0x00DF) return 0x1E9E; // ß
|
||||
if (cp >= 0x0430 && cp <= 0x044F) return cp - 0x20;
|
||||
if (cp >= 0x03B1 && cp <= 0x03C9) return cp - 0x20;
|
||||
if (cp >= 0x00E0 && cp <= 0x00FE && cp != 0x00F7) return cp - 0x20;
|
||||
if (cp >= 0x0100 && cp <= 0x0137 && (cp & 1) == 1) return cp - 1;
|
||||
if (cp >= 0x0139 && cp <= 0x0148 && (cp & 1) == 0) return cp - 1;
|
||||
if (cp >= 0x014A && cp <= 0x0177 && (cp & 1) == 1) return cp - 1;
|
||||
if (cp >= 0x0179 && cp <= 0x017E && (cp & 1) == 0) return cp - 1;
|
||||
if (cp == 0x0219 || cp == 0x021B) return cp - 1;
|
||||
if (cp >= 'a' && cp <= 'z') return cp - 0x20;
|
||||
return cp;
|
||||
}
|
||||
|
||||
// Uppercase a UTF-8 string into `out` (codepoint by codepoint).
|
||||
static inline void toUpperUtf8(const char* in, char* out, size_t out_size) {
|
||||
size_t o = 0;
|
||||
const uint8_t* p = (const uint8_t*)in;
|
||||
while (*p && o + 4 < out_size) o += encode(toUpper(decode(p)), out + o);
|
||||
out[o] = '\0';
|
||||
}
|
||||
|
||||
// Number of codepoints / the idx-th codepoint (as its own UTF-8 string).
|
||||
static inline int utf8Len(const char* s) {
|
||||
int n = 0;
|
||||
const uint8_t* p = (const uint8_t*)s;
|
||||
while (*p) { decode(p); n++; }
|
||||
return n;
|
||||
}
|
||||
static inline void utf8At(const char* s, int idx, char* out /* >= 5 bytes */) {
|
||||
const uint8_t* p = (const uint8_t*)s;
|
||||
for (int i = 0; *p; i++) {
|
||||
const uint8_t* start = p;
|
||||
decode(p);
|
||||
if (i == idx) { memcpy(out, start, p - start); out[p - start] = '\0'; return; }
|
||||
}
|
||||
out[0] = '\0';
|
||||
}
|
||||
|
||||
} // namespace kbd
|
||||
@@ -0,0 +1,265 @@
|
||||
#pragma once
|
||||
// Phone-style on-screen keyboard on top of lv_keyboard (USER_1 mode):
|
||||
// - one letter layout per script (Latin QWERTY, Cyrillic ЙЦУКЕН, Greek);
|
||||
// which scripts are offered comes from the same prefs ui-new uses
|
||||
// (NodePrefs::keyboard_main_alphabet / keyboard_alt_alphabet). The globe
|
||||
// key switches between the two when they differ.
|
||||
// - hold a key for its variants (ą ć ę … / ё є ї … / ά έ … / punctuation
|
||||
// behind '.'), from the shared table in ui-core/KeyboardData.h. The popup
|
||||
// opens above the key; tap a variant to type it, tap elsewhere to close.
|
||||
// - one-shot shift; digits / symbols page behind "1#".
|
||||
// Letters type on release (popover keys), so a long press never types the
|
||||
// base letter first.
|
||||
//
|
||||
// Single-TU fragment: included by ui-lvgl/UITask.cpp only.
|
||||
|
||||
namespace kb {
|
||||
|
||||
#define KB_BS LV_SYMBOL_BACKSPACE
|
||||
#define KB_OK LV_SYMBOL_OK
|
||||
#define KB_SH LV_SYMBOL_UP
|
||||
|
||||
static const char* const K_SYM = "1#";
|
||||
static const char* const K_BACK = "abc";
|
||||
static const char* const K_GLOBE = "\xEF\x82\xAC"; // FontAwesome globe (U+F0AC) -- see fonts/generate.sh
|
||||
|
||||
static const char* const LAT[] = {
|
||||
"q","w","e","r","t","y","u","i","o","p","\n",
|
||||
"a","s","d","f","g","h","j","k","l","\n",
|
||||
KB_SH,"z","x","c","v","b","n","m",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const LAT_UP[] = {
|
||||
"Q","W","E","R","T","Y","U","I","O","P","\n",
|
||||
"A","S","D","F","G","H","J","K","L","\n",
|
||||
KB_SH,"Z","X","C","V","B","N","M",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const CYR[] = {
|
||||
"й","ц","у","к","е","н","г","ш","щ","з","х","\n",
|
||||
"ф","ы","в","а","п","р","о","л","д","ж","э","\n",
|
||||
KB_SH,"я","ч","с","м","и","т","ь","б","ю",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const CYR_UP[] = {
|
||||
"Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","\n",
|
||||
"Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э","\n",
|
||||
KB_SH,"Я","Ч","С","М","И","Т","Ь","Б","Ю",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const GRK[] = {
|
||||
"ς","ε","ρ","τ","υ","θ","ι","ο","π","\n",
|
||||
"α","σ","δ","φ","γ","η","ξ","κ","λ","\n",
|
||||
KB_SH,"ζ","χ","ψ","ω","β","ν","μ",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const GRK_UP[] = {
|
||||
"Σ","Ε","Ρ","Τ","Υ","Θ","Ι","Ο","Π","\n",
|
||||
"Α","Σ","Δ","Φ","Γ","Η","Ξ","Κ","Λ","\n",
|
||||
KB_SH,"Ζ","Χ","Ψ","Ω","Β","Ν","Μ",KB_BS,"\n",
|
||||
nullptr };
|
||||
static const char* const SYM[] = {
|
||||
"1","2","3","4","5","6","7","8","9","0","\n",
|
||||
"-","/",":",";","(",")","€","&","@","\"","\n",
|
||||
".",",","?","!","'","#","%","+","=",KB_BS,"\n",
|
||||
nullptr };
|
||||
|
||||
// Layout ids; letter layouts in (lower, upper) pairs, in NodePrefs
|
||||
// KB_ALPHABET_* order (Latin, Cyrillic, Greek) so script * 2 = its lower layout.
|
||||
enum : uint8_t { L_LAT, L_LAT_UP, L_CYR, L_CYR_UP, L_GRK, L_GRK_UP, L_PAIRED_END = L_GRK_UP,
|
||||
L_SYM, L_COUNT };
|
||||
static const char* const* const ROWS[L_COUNT] = { LAT, LAT_UP, CYR, CYR_UP, GRK, GRK_UP, SYM };
|
||||
|
||||
// Full lv_keyboard maps: the rows above + a bottom row assembled in
|
||||
// buildMaps() (globe only when a second script is enabled).
|
||||
static const int MAX_KEYS = 40;
|
||||
static const char* s_maps[L_COUNT][MAX_KEYS + 8];
|
||||
static lv_buttonmatrix_ctrl_t s_ctrl[L_COUNT][MAX_KEYS];
|
||||
static uint8_t s_layout = L_LAT;
|
||||
static uint8_t s_script = 0; // current script (NodePrefs KB_ALPHABET_*)
|
||||
static NodePrefs* s_prefs = nullptr;
|
||||
static bool s_suppress_release = false; // a long press opened the popup: don't type the base
|
||||
static lv_obj_t* s_popup = nullptr; // overlay (on lv_layer_top) holding the variants row
|
||||
static lv_obj_t* s_popup_kbd = nullptr;
|
||||
|
||||
static uint8_t mainScript() {
|
||||
uint8_t s = s_prefs ? s_prefs->keyboard_main_alphabet : 0;
|
||||
return s < NodePrefs::KB_ALPHABET_COUNT ? s : 0;
|
||||
}
|
||||
static uint8_t altScript() {
|
||||
uint8_t s = s_prefs ? s_prefs->keyboard_alt_alphabet : 0;
|
||||
return s < NodePrefs::KB_ALPHABET_COUNT ? s : 0;
|
||||
}
|
||||
static bool hasAlt() { return altScript() != mainScript(); }
|
||||
|
||||
static bool isSpecial(const char* t) {
|
||||
static const char* const SP[] = { KB_SH, KB_BS, KB_OK, K_SYM, K_BACK, K_GLOBE };
|
||||
for (const char* s : SP) if (strcmp(t, s) == 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assemble the maps and derive key widths / styles from the labels: letters
|
||||
// narrow, typed on release with a magnified popover and no auto-repeat;
|
||||
// special keys wider and highlighted; space widest.
|
||||
static void buildMaps() {
|
||||
bool alt = hasAlt();
|
||||
for (int l = 0; l < L_COUNT; l++) {
|
||||
int m = 0;
|
||||
for (const char* const* p = ROWS[l]; *p; p++) s_maps[l][m++] = *p;
|
||||
if (l == L_SYM) {
|
||||
s_maps[l][m++] = K_BACK; s_maps[l][m++] = "_"; s_maps[l][m++] = " ";
|
||||
s_maps[l][m++] = "*"; s_maps[l][m++] = KB_OK;
|
||||
} else {
|
||||
s_maps[l][m++] = K_SYM;
|
||||
if (alt) s_maps[l][m++] = K_GLOBE;
|
||||
s_maps[l][m++] = " "; s_maps[l][m++] = "."; s_maps[l][m++] = KB_OK;
|
||||
}
|
||||
s_maps[l][m] = "";
|
||||
|
||||
int k = 0;
|
||||
for (const char* const* p = s_maps[l]; **p; p++) {
|
||||
if (strcmp(*p, "\n") == 0) continue;
|
||||
uint32_t c;
|
||||
if (strcmp(*p, " ") == 0) c = 6;
|
||||
else if (strcmp(*p, KB_BS) == 0) c = 3 | LV_BUTTONMATRIX_CTRL_CHECKED; // keeps auto-repeat
|
||||
else if (isSpecial(*p)) c = 3 | LV_BUTTONMATRIX_CTRL_CHECKED | LV_BUTTONMATRIX_CTRL_NO_REPEAT;
|
||||
else c = 2 | LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT;
|
||||
if (k < MAX_KEYS) s_ctrl[l][k++] = (lv_buttonmatrix_ctrl_t)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Label of button `id` (buttons numbered without the "\n" row breaks).
|
||||
static const char* keyText(uint8_t layout, uint32_t id) {
|
||||
uint32_t k = 0;
|
||||
for (const char* const* p = s_maps[layout]; **p; p++) {
|
||||
if (strcmp(*p, "\n") == 0) continue;
|
||||
if (k++ == id) return *p;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static void apply(lv_obj_t* kbd, uint8_t layout) {
|
||||
s_layout = layout;
|
||||
lv_keyboard_set_map(kbd, LV_KEYBOARD_MODE_USER_1, s_maps[layout], s_ctrl[layout]);
|
||||
lv_keyboard_set_mode(kbd, LV_KEYBOARD_MODE_USER_1);
|
||||
}
|
||||
|
||||
static void releaseShift(lv_obj_t* kbd) {
|
||||
if (s_layout <= L_PAIRED_END && (s_layout & 1)) apply(kbd, s_layout ^ 1);
|
||||
}
|
||||
|
||||
// ── Variants popup ───────────────────────────────────────────────────────────
|
||||
static char s_var_txt[12][8];
|
||||
static const char* s_var_map[13];
|
||||
|
||||
static void closePopup() {
|
||||
if (s_popup) { lv_obj_delete_async(s_popup); s_popup = nullptr; }
|
||||
}
|
||||
|
||||
static void onPopupPick(lv_event_t* e) {
|
||||
lv_obj_t* m = (lv_obj_t*)lv_event_get_target(e);
|
||||
uint32_t id = lv_buttonmatrix_get_selected_button(m);
|
||||
if (id == LV_BUTTONMATRIX_BUTTON_NONE || !s_popup_kbd) return;
|
||||
lv_obj_t* ta = lv_keyboard_get_textarea(s_popup_kbd);
|
||||
if (ta) lv_textarea_add_text(ta, lv_buttonmatrix_get_button_text(m, id));
|
||||
releaseShift(s_popup_kbd);
|
||||
closePopup();
|
||||
}
|
||||
|
||||
static void onPopupOutside(lv_event_t* e) { (void)e; closePopup(); }
|
||||
|
||||
static void openPopup(lv_obj_t* kbd, const char* variants, bool upper) {
|
||||
closePopup();
|
||||
int n = ::kbd::utf8Len(variants);
|
||||
if (n > 12) n = 12;
|
||||
for (int i = 0; i < n; i++) {
|
||||
char one[8];
|
||||
::kbd::utf8At(variants, i, one);
|
||||
if (upper) ::kbd::toUpperUtf8(one, s_var_txt[i], sizeof(s_var_txt[i]));
|
||||
else memcpy(s_var_txt[i], one, sizeof(one));
|
||||
s_var_map[i] = s_var_txt[i];
|
||||
}
|
||||
s_var_map[n] = "";
|
||||
|
||||
// Full-screen transparent overlay: a tap outside the row closes the popup.
|
||||
s_popup = lv_obj_create(lv_layer_top());
|
||||
lv_obj_remove_style_all(s_popup);
|
||||
lv_obj_set_size(s_popup, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_add_flag(s_popup, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_event_cb(s_popup, onPopupOutside, LV_EVENT_CLICKED, NULL);
|
||||
s_popup_kbd = kbd;
|
||||
|
||||
lv_obj_t* m = lv_buttonmatrix_create(s_popup);
|
||||
lv_buttonmatrix_set_map(m, s_var_map);
|
||||
const int key_w = 30;
|
||||
int w = n * key_w + 8;
|
||||
lv_obj_set_size(m, w, 44);
|
||||
lv_obj_set_style_pad_all(m, 3, 0);
|
||||
lv_obj_set_style_pad_gap(m, 2, 0);
|
||||
lv_obj_set_style_bg_color(m, lv_color_hex(theme::SURFACE_2), 0);
|
||||
lv_obj_set_style_border_color(m, lv_color_hex(theme::ACCENT), 0);
|
||||
lv_obj_set_style_border_width(m, 1, 0);
|
||||
lv_obj_set_style_radius(m, theme::RADIUS, 0);
|
||||
lv_obj_set_style_text_font(m, THEME_FONT_LARGE, LV_PART_ITEMS);
|
||||
|
||||
// Above the pressed key, clamped to the screen.
|
||||
lv_point_t pt = { 0, 0 };
|
||||
lv_indev_t* indev = lv_indev_active();
|
||||
if (indev) lv_indev_get_point(indev, &pt);
|
||||
int scr_w = lv_display_get_horizontal_resolution(NULL);
|
||||
int x = pt.x - w / 2;
|
||||
if (x < 2) x = 2;
|
||||
if (x + w > scr_w - 2) x = scr_w - 2 - w;
|
||||
int y = pt.y - 70;
|
||||
if (y < theme::STATUS_H) y = theme::STATUS_H;
|
||||
lv_obj_set_pos(m, x, y);
|
||||
lv_obj_add_event_cb(m, onPopupPick, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
// ── Events ───────────────────────────────────────────────────────────────────
|
||||
static void onLongPress(lv_event_t* e) {
|
||||
lv_obj_t* kbd = (lv_obj_t*)lv_event_get_target(e);
|
||||
uint32_t id = lv_keyboard_get_selected_button(kbd);
|
||||
if (id == LV_BUTTONMATRIX_BUTTON_NONE) return;
|
||||
bool upper = s_layout <= L_PAIRED_END && (s_layout & 1);
|
||||
uint8_t lower = upper ? (uint8_t)(s_layout ^ 1) : s_layout;
|
||||
const char* variants = ::kbd::variantsFor(keyText(lower, id));
|
||||
if (!variants) return; // plain key: the release types it as usual
|
||||
s_suppress_release = true;
|
||||
openPopup(kbd, variants, upper);
|
||||
}
|
||||
|
||||
static void onEvent(lv_event_t* e) {
|
||||
lv_obj_t* kbd = (lv_obj_t*)lv_event_get_target(e);
|
||||
if (s_suppress_release) { s_suppress_release = false; return; }
|
||||
uint32_t id = lv_keyboard_get_selected_button(kbd);
|
||||
if (id == LV_BUTTONMATRIX_BUTTON_NONE) return;
|
||||
const char* t = lv_keyboard_get_button_text(kbd, id);
|
||||
if (!t) return;
|
||||
|
||||
if (strcmp(t, KB_SH) == 0) { if (s_layout <= L_PAIRED_END) apply(kbd, s_layout ^ 1); return; }
|
||||
if (strcmp(t, K_SYM) == 0) { apply(kbd, L_SYM); return; }
|
||||
if (strcmp(t, K_BACK) == 0) { apply(kbd, s_script * 2); return; }
|
||||
if (strcmp(t, K_GLOBE) == 0) {
|
||||
s_script = (s_script == mainScript()) ? altScript() : mainScript();
|
||||
apply(kbd, s_script * 2);
|
||||
return;
|
||||
}
|
||||
lv_keyboard_def_event_cb(e); // type the character / backspace / OK
|
||||
if (strcmp(t, KB_BS) != 0) releaseShift(kbd);
|
||||
}
|
||||
|
||||
static void onDelete(lv_event_t* e) { (void)e; closePopup(); s_popup_kbd = nullptr; }
|
||||
|
||||
// Create a keyboard on `parent`, opening on the main script.
|
||||
static lv_obj_t* create(lv_obj_t* parent, NodePrefs* prefs) {
|
||||
s_prefs = prefs;
|
||||
buildMaps(); // cheap; picks up a changed alphabet setting
|
||||
s_script = mainScript();
|
||||
lv_obj_t* kbd = lv_keyboard_create(parent);
|
||||
lv_obj_remove_event_cb(kbd, lv_keyboard_def_event_cb);
|
||||
lv_obj_add_event_cb(kbd, onEvent, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_add_event_cb(kbd, onLongPress, LV_EVENT_LONG_PRESSED, NULL);
|
||||
lv_obj_add_event_cb(kbd, onDelete, LV_EVENT_DELETE, NULL);
|
||||
lv_keyboard_set_popovers(kbd, true);
|
||||
apply(kbd, s_script * 2);
|
||||
return kbd;
|
||||
}
|
||||
|
||||
} // namespace kb
|
||||
@@ -21,10 +21,11 @@ namespace theme {
|
||||
static const int STATUS_H = 22; // top status bar
|
||||
static const int ROW_H = 44; // list row (touch target)
|
||||
|
||||
// Type
|
||||
#define THEME_FONT_SMALL (&lv_font_montserrat_12)
|
||||
#define THEME_FONT_BODY (&lv_font_montserrat_14)
|
||||
#define THEME_FONT_TITLE (&lv_font_montserrat_16)
|
||||
#define THEME_FONT_LARGE (&lv_font_montserrat_20)
|
||||
#define THEME_FONT_CLOCK (&lv_font_montserrat_40)
|
||||
// Type -- Noto Sans, generated by fonts/generate.sh (declared in lv_conf.h).
|
||||
// ui_font_40 holds digits / ':' / '-' only (clock).
|
||||
#define THEME_FONT_SMALL (&ui_font_12)
|
||||
#define THEME_FONT_BODY (&ui_font_14)
|
||||
#define THEME_FONT_TITLE (&ui_font_16)
|
||||
#define THEME_FONT_LARGE (&ui_font_20)
|
||||
#define THEME_FONT_CLOCK (&ui_font_40)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "../ui-core/UiCore.h" // shared UI Core (header-only, this TU)
|
||||
#include "Theme.h"
|
||||
#include "LvglPort.h"
|
||||
#include "../ui-core/KeyboardData.h"
|
||||
#include "Keyboard.h"
|
||||
|
||||
// ui-lvgl skeleton (docs/development/ui-core.md, step 5): status bar, home,
|
||||
// conversation list, contact picker, conversation view with compose. Every
|
||||
@@ -353,6 +355,7 @@ void UITask::back() {
|
||||
switch (_screen) {
|
||||
case SCR_THREAD: showChats(); break;
|
||||
case SCR_CONTACTS: showChats(); break;
|
||||
case SCR_SETTINGS: showHome(); break;
|
||||
case SCR_CHATS: showHome(); break;
|
||||
default: break;
|
||||
}
|
||||
@@ -361,6 +364,24 @@ void UITask::back() {
|
||||
// ── Home ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
static void onOpenChats(lv_event_t* e) { (void)e; s_ui->showChats(); }
|
||||
static void onOpenSettings(lv_event_t* e) { (void)e; s_ui->showSettings(); }
|
||||
|
||||
// Wide home tile: icon + label left, optional value label right.
|
||||
static lv_obj_t* homeTile(lv_obj_t* parent, const char* text, lv_event_cb_t cb, lv_obj_t** value_out) {
|
||||
lv_obj_t* tile = lv_button_create(parent);
|
||||
lv_obj_set_size(tile, LV_PCT(100), 42);
|
||||
lv_obj_set_style_bg_color(tile, lv_color_hex(theme::SURFACE), 0);
|
||||
lv_obj_set_style_radius(tile, theme::RADIUS, 0);
|
||||
lv_obj_set_style_shadow_width(tile, 0, 0);
|
||||
lv_obj_add_event_cb(tile, cb, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_t* tl = label(tile, text, THEME_FONT_TITLE, theme::TEXT);
|
||||
lv_obj_align(tl, LV_ALIGN_LEFT_MID, theme::PAD, 0);
|
||||
if (value_out) {
|
||||
*value_out = label(tile, "", THEME_FONT_TITLE, theme::ACCENT);
|
||||
lv_obj_align(*value_out, LV_ALIGN_RIGHT_MID, -theme::PAD, 0);
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
void UITask::showHome() {
|
||||
_screen = SCR_HOME;
|
||||
@@ -373,21 +394,12 @@ void UITask::buildHome() {
|
||||
lv_obj_set_flex_align(body, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
_home_clock = label(body, "--:--", THEME_FONT_CLOCK, theme::TEXT);
|
||||
lv_obj_set_style_pad_top(_home_clock, 10, 0);
|
||||
_home_date = label(body, "", THEME_FONT_BODY, theme::TEXT_MUTED);
|
||||
lv_obj_t* name = label(body, the_mesh.getNodeName(), THEME_FONT_BODY, theme::ACCENT);
|
||||
lv_obj_set_style_pad_bottom(name, 8, 0);
|
||||
lv_obj_set_style_pad_bottom(name, 4, 0);
|
||||
|
||||
lv_obj_t* tile = lv_button_create(body);
|
||||
lv_obj_set_size(tile, LV_PCT(100), 56);
|
||||
lv_obj_set_style_bg_color(tile, lv_color_hex(theme::SURFACE), 0);
|
||||
lv_obj_set_style_radius(tile, theme::RADIUS, 0);
|
||||
lv_obj_set_style_shadow_width(tile, 0, 0);
|
||||
lv_obj_add_event_cb(tile, onOpenChats, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_t* tl = label(tile, LV_SYMBOL_ENVELOPE " Messages", THEME_FONT_TITLE, theme::TEXT);
|
||||
lv_obj_align(tl, LV_ALIGN_LEFT_MID, theme::PAD, 0);
|
||||
_home_unread = label(tile, "", THEME_FONT_TITLE, theme::ACCENT);
|
||||
lv_obj_align(_home_unread, LV_ALIGN_RIGHT_MID, -theme::PAD, 0);
|
||||
homeTile(body, LV_SYMBOL_ENVELOPE " Messages", onOpenChats, &_home_unread);
|
||||
homeTile(body, LV_SYMBOL_SETTINGS " Settings", onOpenSettings, NULL);
|
||||
}
|
||||
|
||||
void UITask::refreshHome() {
|
||||
@@ -547,6 +559,18 @@ static void onKeyboard(lv_event_t* e) {
|
||||
else if (code == LV_EVENT_CANCEL) lv_obj_add_flag((lv_obj_t*)lv_event_get_user_data(e), LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
// Compose limit is in UTF-8 bytes (the over-the-air limit), not characters:
|
||||
// Cyrillic / Greek / accented letters take two bytes each. Leaves room for the
|
||||
// "Name: " prefix a channel send adds.
|
||||
static const size_t COMPOSE_MAX_BYTES = MAX_TEXT_LEN - 40;
|
||||
|
||||
static void onComposeInsert(lv_event_t* e) {
|
||||
lv_obj_t* ta = (lv_obj_t*)lv_event_get_target(e);
|
||||
const char* ins = (const char*)lv_event_get_param(e);
|
||||
if (ins && strlen(lv_textarea_get_text(ta)) + strlen(ins) > COMPOSE_MAX_BYTES)
|
||||
lv_textarea_set_insert_replace(ta, ""); // reject: would exceed the byte limit
|
||||
}
|
||||
|
||||
static void onComposeClicked(lv_event_t* e) {
|
||||
lv_obj_t* kb = (lv_obj_t*)lv_event_get_user_data(e);
|
||||
lv_obj_remove_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
@@ -606,13 +630,13 @@ void UITask::buildThread() {
|
||||
_compose_ta = lv_textarea_create(bar);
|
||||
lv_textarea_set_one_line(_compose_ta, true);
|
||||
lv_textarea_set_placeholder_text(_compose_ta, "Message");
|
||||
lv_textarea_set_max_length(_compose_ta, MAX_TEXT_LEN - 40);
|
||||
lv_obj_add_event_cb(_compose_ta, onComposeInsert, LV_EVENT_INSERT, NULL);
|
||||
lv_obj_set_size(_compose_ta, LV_PCT(100), 36);
|
||||
lv_obj_align(_compose_ta, LV_ALIGN_LEFT_MID, 0, 0);
|
||||
|
||||
// In the body's flex column below the compose bar: showing it shrinks the
|
||||
// message list, so the text field stays visible just above the keys.
|
||||
_keyboard = lv_keyboard_create(body);
|
||||
_keyboard = kb::create(body, _prefs); // phone-style, scripts from prefs, hold for accents (Keyboard.h)
|
||||
lv_obj_set_size(_keyboard, LV_PCT(100), 130);
|
||||
lv_keyboard_set_textarea(_keyboard, _compose_ta);
|
||||
lv_obj_add_event_cb(_keyboard, onKeyboard, LV_EVENT_READY, _keyboard);
|
||||
@@ -756,3 +780,58 @@ void UITask::sendFromCompose() {
|
||||
showToast("Send failed");
|
||||
}
|
||||
}
|
||||
|
||||
// ── Settings (first rows; the declarative schema replaces this later) ────────
|
||||
|
||||
static lv_obj_t* s_kb_main_dd = nullptr;
|
||||
static lv_obj_t* s_kb_alt_dd = nullptr;
|
||||
|
||||
static void onKeyboardAlphabet(lv_event_t* e) {
|
||||
(void)e;
|
||||
s_ui->setKeyboardAlphabets(lv_dropdown_get_selected(s_kb_main_dd), lv_dropdown_get_selected(s_kb_alt_dd));
|
||||
}
|
||||
|
||||
// One settings row: label left, dropdown right.
|
||||
static lv_obj_t* dropdownRow(lv_obj_t* parent, const char* text, const char* options, int sel) {
|
||||
lv_obj_t* row = lv_obj_create(parent);
|
||||
styleSurface(row, theme::SURFACE);
|
||||
lv_obj_remove_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_size(row, LV_PCT(100), theme::ROW_H);
|
||||
lv_obj_set_style_radius(row, theme::RADIUS, 0);
|
||||
lv_obj_t* l = label(row, text, THEME_FONT_BODY, theme::TEXT);
|
||||
lv_obj_align(l, LV_ALIGN_LEFT_MID, theme::PAD, 0);
|
||||
lv_obj_t* dd = lv_dropdown_create(row);
|
||||
lv_dropdown_set_options_static(dd, options);
|
||||
lv_dropdown_set_selected(dd, sel);
|
||||
lv_obj_set_width(dd, 130);
|
||||
lv_obj_align(dd, LV_ALIGN_RIGHT_MID, -4, 0);
|
||||
lv_obj_add_event_cb(dd, onKeyboardAlphabet, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
return dd;
|
||||
}
|
||||
|
||||
void UITask::showSettings() {
|
||||
_screen = SCR_SETTINGS;
|
||||
buildSettings();
|
||||
}
|
||||
|
||||
void UITask::buildSettings() {
|
||||
lv_obj_t* body = newScreen("Settings", true);
|
||||
sectionTitle(body, "KEYBOARD");
|
||||
uint8_t main_a = _prefs ? _prefs->keyboard_main_alphabet : 0;
|
||||
uint8_t alt_a = _prefs ? _prefs->keyboard_alt_alphabet : 0;
|
||||
if (main_a >= NodePrefs::KB_ALPHABET_COUNT) main_a = 0;
|
||||
if (alt_a >= NodePrefs::KB_ALPHABET_COUNT) alt_a = main_a;
|
||||
// Order matches NodePrefs::KB_ALPHABET_* (Latin, Cyrillic, Greek).
|
||||
s_kb_main_dd = dropdownRow(body, "Main", "Latin\nCyrillic\nGreek", main_a);
|
||||
// "None" = no second script (stored as alt == main, as ui-new does).
|
||||
s_kb_alt_dd = dropdownRow(body, "Additional", "None\nLatin\nCyrillic\nGreek",
|
||||
alt_a == main_a ? 0 : alt_a + 1);
|
||||
label(body, "Hold a letter for accents and other variants.", THEME_FONT_SMALL, theme::TEXT_MUTED);
|
||||
}
|
||||
|
||||
void UITask::setKeyboardAlphabets(int main_idx, int alt_sel) {
|
||||
if (!_prefs) return;
|
||||
_prefs->keyboard_main_alphabet = (uint8_t)main_idx;
|
||||
_prefs->keyboard_alt_alphabet = (uint8_t)(alt_sel == 0 ? main_idx : alt_sel - 1);
|
||||
the_mesh.savePrefs();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
void showHome();
|
||||
void showChats();
|
||||
void showContacts();
|
||||
void showSettings();
|
||||
void setKeyboardAlphabets(int main_idx, int alt_sel);
|
||||
void openChannel(uint8_t channel_idx);
|
||||
void openDM(const uint8_t* pub_key);
|
||||
void back();
|
||||
@@ -47,7 +49,7 @@ public:
|
||||
void openAdminFor(const ContactInfo& ci, bool from_picker) { (void)ci; (void)from_picker; }
|
||||
|
||||
private:
|
||||
enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD };
|
||||
enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS };
|
||||
|
||||
void buildStatusBar();
|
||||
void refreshStatusBar();
|
||||
@@ -56,6 +58,7 @@ private:
|
||||
void refreshHome();
|
||||
void buildChats();
|
||||
void buildContacts();
|
||||
void buildSettings();
|
||||
void buildThread();
|
||||
void refreshThread();
|
||||
uint32_t threadSignature() const;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Regenerates the ui-lvgl fonts (Noto Sans + LVGL's built-in symbols).
|
||||
#
|
||||
# Coverage: full European Latin (Latin-1, Latin Extended-A/B -- incl. Polish,
|
||||
# Czech, Slovak, Hungarian, Romanian ș/ț, Baltic, Turkish, Nordic, Icelandic,
|
||||
# Maltese, Welsh ŵ/ŷ/ẁ…, German ẞ), Greek, Cyrillic (+ supplement: Ukrainian,
|
||||
# Belarusian, Serbian, Macedonian, Bulgarian…), typographic punctuation,
|
||||
# currency (€ ₴ ₽ …) and №, plus LVGL's LV_SYMBOL_* icons.
|
||||
#
|
||||
# Needs node (npx fetches lv_font_conv) and curl. Run from anywhere:
|
||||
# examples/companion_radio/ui-lvgl/fonts/generate.sh
|
||||
# Output: ui_font_<size>.c next to this script (commit them).
|
||||
set -euo pipefail
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
CACHE="${FONT_CACHE:-${TMPDIR:-/tmp}/meshcore-ui-fonts}"
|
||||
mkdir -p "$CACHE"
|
||||
|
||||
NOTO_BASE=https://github.com/notofonts/notofonts.github.io/raw/main/fonts/NotoSans/hinted/ttf
|
||||
for w in Medium SemiBold; do
|
||||
[ -f "$CACHE/NotoSans-$w.ttf" ] || curl -sSL -o "$CACHE/NotoSans-$w.ttf" "$NOTO_BASE/NotoSans-$w.ttf"
|
||||
done
|
||||
FA_URL=https://raw.githubusercontent.com/lvgl/lvgl/v9.2.2/scripts/built_in_font/FontAwesome5-Solid+Brands+Regular.woff
|
||||
[ -f "$CACHE/fa.woff" ] || curl -sSL -o "$CACHE/fa.woff" "$FA_URL"
|
||||
|
||||
# Text ranges
|
||||
TEXT="0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3"
|
||||
TEXT="$TEXT,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122"
|
||||
# LVGL built-in symbols (same list as lvgl/scripts/built_in_font/built_in_font_gen.py)
|
||||
# plus 61612 = globe (keyboard script key)
|
||||
SYMS="61612,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650"
|
||||
|
||||
CONV="npx -y lv_font_conv@1.5.3"
|
||||
gen() { # size weight ranges name
|
||||
$CONV --bpp 4 --size "$1" --force-fast-kern-format \
|
||||
--font "$CACHE/NotoSans-$2.ttf" -r "$3" \
|
||||
--font "$CACHE/fa.woff" -r "$SYMS" \
|
||||
--format lvgl --lv-include lvgl.h --lv-font-name "$4" -o "$HERE/$4.c"
|
||||
}
|
||||
for s in 12 14 16 20; do gen "$s" Medium "$TEXT" "ui_font_$s"; done
|
||||
# Clock: digits, colon, dash, space only.
|
||||
$CONV --bpp 4 --size 40 --no-compress --font "$CACHE/NotoSans-SemiBold.ttf" -r "0x20,0x2D,0x30-0x3A" \
|
||||
--format lvgl --lv-include lvgl.h --lv-font-name ui_font_40 -o "$HERE/ui_font_40.c"
|
||||
echo "done: $(ls "$HERE"/ui_font_*.c | wc -l) fonts"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,531 @@
|
||||
/*******************************************************************************
|
||||
* Size: 40 px
|
||||
* Bpp: 4
|
||||
* Opts: --bpp 4 --size 40 --no-compress --font /private/tmp/claude-501/-Users-jakub-Documents-MeshCore-MeshCore/3d84fa48-e031-42a4-abec-01b33a2b06ef/scratchpad/fonts/NotoSans-SemiBold.ttf -r 0x20,0x2D,0x30-0x3A --format lvgl --lv-include lvgl.h --lv-font-name ui_font_40 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_40.c
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl.h"
|
||||
#endif
|
||||
|
||||
#ifndef UI_FONT_40
|
||||
#define UI_FONT_40 1
|
||||
#endif
|
||||
|
||||
#if UI_FONT_40
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
*----------------*/
|
||||
|
||||
/*Store the image of the glyphs*/
|
||||
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
/* U+0020 " " */
|
||||
|
||||
/* U+002D "-" */
|
||||
0x23, 0x33, 0x33, 0x33, 0x33, 0x1b, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf8, 0xbf, 0xff, 0xff, 0xff, 0xff,
|
||||
0x8b, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xbf, 0xff,
|
||||
0xff, 0xff, 0xff, 0x80,
|
||||
|
||||
/* U+0030 "0" */
|
||||
0x0, 0x0, 0x0, 0x4a, 0xdf, 0xfe, 0xc8, 0x20,
|
||||
0x0, 0x0, 0x0, 0x0, 0x2, 0xdf, 0xff, 0xff,
|
||||
0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0x3, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0,
|
||||
0x1, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x90, 0x0, 0x0, 0x9f, 0xff, 0xff, 0x94, 0x24,
|
||||
0xbf, 0xff, 0xff, 0x30, 0x0, 0x1f, 0xff, 0xff,
|
||||
0x60, 0x0, 0x0, 0xaf, 0xff, 0xfb, 0x0, 0x6,
|
||||
0xff, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, 0xff,
|
||||
0xf1, 0x0, 0xaf, 0xff, 0xf7, 0x0, 0x0, 0x0,
|
||||
0xa, 0xff, 0xff, 0x60, 0xe, 0xff, 0xff, 0x30,
|
||||
0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0xff,
|
||||
0xff, 0xf0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff,
|
||||
0xd0, 0x2f, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0,
|
||||
0x1f, 0xff, 0xff, 0x4, 0xff, 0xff, 0xc0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xff, 0xff, 0xf1, 0x5f, 0xff,
|
||||
0xfc, 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xff,
|
||||
0x25, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0,
|
||||
0xef, 0xff, 0xf2, 0x5f, 0xff, 0xfb, 0x0, 0x0,
|
||||
0x0, 0x0, 0xe, 0xff, 0xff, 0x24, 0xff, 0xff,
|
||||
0xc0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff, 0xf2,
|
||||
0x3f, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf,
|
||||
0xff, 0xff, 0x12, 0xff, 0xff, 0xe0, 0x0, 0x0,
|
||||
0x0, 0x0, 0xff, 0xff, 0xf0, 0xf, 0xff, 0xff,
|
||||
0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xfe, 0x0,
|
||||
0xdf, 0xff, 0xf3, 0x0, 0x0, 0x0, 0x5, 0xff,
|
||||
0xff, 0xb0, 0x9, 0xff, 0xff, 0x70, 0x0, 0x0,
|
||||
0x0, 0xaf, 0xff, 0xf7, 0x0, 0x4f, 0xff, 0xfd,
|
||||
0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0x30, 0x0,
|
||||
0xef, 0xff, 0xf7, 0x0, 0x0, 0xa, 0xff, 0xff,
|
||||
0xd0, 0x0, 0x6, 0xff, 0xff, 0xfa, 0x43, 0x5b,
|
||||
0xff, 0xff, 0xf6, 0x0, 0x0, 0xc, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0,
|
||||
0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x10,
|
||||
0x0, 0x0, 0x0, 0x1b, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfb, 0x10, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9d,
|
||||
0xef, 0xed, 0x93, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0031 "1" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x4e, 0xff, 0xfa, 0x0,
|
||||
0x0, 0x0, 0x7, 0xff, 0xff, 0xfa, 0x0, 0x0,
|
||||
0x1, 0xbf, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x3d,
|
||||
0xff, 0xff, 0xff, 0xfa, 0x0, 0x6, 0xff, 0xff,
|
||||
0xff, 0xff, 0xfa, 0x0, 0x9f, 0xff, 0xff, 0xbf,
|
||||
0xff, 0xfa, 0xc, 0xff, 0xff, 0xf6, 0x4f, 0xff,
|
||||
0xfa, 0x8, 0xff, 0xfe, 0x40, 0x5f, 0xff, 0xfa,
|
||||
0x0, 0xbf, 0xc2, 0x0, 0x5f, 0xff, 0xfa, 0x0,
|
||||
0x8, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0,
|
||||
0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0,
|
||||
0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0,
|
||||
0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f,
|
||||
0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff,
|
||||
0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa,
|
||||
0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0,
|
||||
0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0,
|
||||
0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0,
|
||||
0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0,
|
||||
0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f,
|
||||
0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff,
|
||||
0xfa, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa,
|
||||
0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0,
|
||||
0x0, 0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0,
|
||||
0x0, 0x0, 0x6f, 0xff, 0xfa, 0x0, 0x0, 0x0,
|
||||
0x0, 0x6f, 0xff, 0xfa,
|
||||
|
||||
/* U+0032 "2" */
|
||||
0x0, 0x0, 0x2, 0x7b, 0xef, 0xfe, 0xc9, 0x40,
|
||||
0x0, 0x0, 0x0, 0x0, 0x2a, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xd3, 0x0, 0x0, 0x0, 0x7f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x0, 0x0,
|
||||
0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf3, 0x0, 0x9, 0xff, 0xff, 0xfb, 0x75, 0x57,
|
||||
0xdf, 0xff, 0xff, 0xb0, 0x0, 0xb, 0xff, 0xa2,
|
||||
0x0, 0x0, 0x0, 0xaf, 0xff, 0xff, 0x10, 0x0,
|
||||
0xb, 0x50, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
|
||||
0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0xc, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xdf, 0xff, 0xf3, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff,
|
||||
0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4,
|
||||
0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0xcf, 0xff, 0xf5, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0xfc, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xff,
|
||||
0xff, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x4f, 0xff, 0xff, 0x60, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x4f, 0xff, 0xff, 0x80, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x4f, 0xff, 0xff, 0x80,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xff,
|
||||
0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x5f, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x5f, 0xff, 0xff, 0x60, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x5f, 0xff, 0xff, 0x50,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff,
|
||||
0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x6f, 0xff, 0xff, 0x30, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x7f, 0xff, 0xff, 0xa7, 0x77, 0x77,
|
||||
0x77, 0x77, 0x77, 0x72, 0x3f, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf4, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x44, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf4,
|
||||
|
||||
/* U+0033 "3" */
|
||||
0x0, 0x0, 0x26, 0xad, 0xef, 0xfe, 0xca, 0x50,
|
||||
0x0, 0x0, 0x0, 0x3, 0xbf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe6, 0x0, 0x0, 0xa, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0,
|
||||
0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf6, 0x0, 0x1, 0xef, 0xfe, 0x95, 0x32, 0x35,
|
||||
0xbf, 0xff, 0xff, 0xd0, 0x0, 0x4, 0xc5, 0x0,
|
||||
0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0x10, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
|
||||
0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0xe, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x2, 0xff, 0xff, 0xc0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x1, 0xcf, 0xff, 0xf4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x48, 0xef,
|
||||
0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xd4, 0x0, 0x0, 0x0, 0x0,
|
||||
0xf, 0xff, 0xff, 0xff, 0xfb, 0x40, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa4, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x13, 0x7c, 0xff, 0xff, 0xfc, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff,
|
||||
0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0xb, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xff,
|
||||
0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x7f, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0xc0, 0x59,
|
||||
0x20, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xff,
|
||||
0xf7, 0x5, 0xff, 0xd9, 0x63, 0x21, 0x24, 0x8d,
|
||||
0xff, 0xff, 0xff, 0x10, 0x5f, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x5, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60,
|
||||
0x0, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfb, 0x20, 0x0, 0x0, 0x2, 0x6a, 0xce, 0xff,
|
||||
0xfe, 0xda, 0x72, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0034 "4" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff,
|
||||
0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x7, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff,
|
||||
0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0xdf, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x9f, 0xff, 0xff, 0xff, 0x70,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xff,
|
||||
0xef, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x1e, 0xff, 0xf7, 0xff, 0xff, 0x70, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xf8, 0x6f,
|
||||
0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6,
|
||||
0xff, 0xfd, 0x7, 0xff, 0xff, 0x70, 0x0, 0x0,
|
||||
0x0, 0x0, 0x2, 0xff, 0xff, 0x30, 0x7f, 0xff,
|
||||
0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xff,
|
||||
0x80, 0x8, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0,
|
||||
0x0, 0x7f, 0xff, 0xc0, 0x0, 0x8f, 0xff, 0xf7,
|
||||
0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xf2, 0x0,
|
||||
0x8, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0xd,
|
||||
0xff, 0xf6, 0x0, 0x0, 0x8f, 0xff, 0xf7, 0x0,
|
||||
0x0, 0x0, 0x9, 0xff, 0xfb, 0x0, 0x0, 0x8,
|
||||
0xff, 0xff, 0x70, 0x0, 0x0, 0x4, 0xff, 0xfe,
|
||||
0x10, 0x0, 0x0, 0x8f, 0xff, 0xf7, 0x0, 0x0,
|
||||
0x1, 0xef, 0xff, 0x50, 0x0, 0x0, 0x8, 0xff,
|
||||
0xff, 0x70, 0x0, 0x0, 0xbf, 0xff, 0xb1, 0x11,
|
||||
0x11, 0x11, 0x9f, 0xff, 0xf7, 0x11, 0x10, 0x3f,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x3f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0x70, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f,
|
||||
0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x8, 0xff, 0xff, 0x70, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff,
|
||||
0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x8, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0xf7,
|
||||
0x0, 0x0,
|
||||
|
||||
/* U+0035 "5" */
|
||||
0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe0, 0x0, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xfe, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xe0, 0x0, 0x7f, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x8, 0xff,
|
||||
0xff, 0x86, 0x66, 0x66, 0x66, 0x66, 0x50, 0x0,
|
||||
0x9f, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0xa, 0xff, 0xff, 0x10, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xcf, 0xff, 0xf0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xfd, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff,
|
||||
0xc0, 0x1, 0x20, 0x0, 0x0, 0x0, 0x0, 0xf,
|
||||
0xff, 0xfe, 0xef, 0xff, 0xff, 0xc7, 0x20, 0x0,
|
||||
0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x70, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xa0, 0x1, 0xcf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x57, 0x42,
|
||||
0x10, 0x2, 0x6c, 0xff, 0xff, 0xff, 0x10, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xf7,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff,
|
||||
0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x7f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x4, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x5f, 0xff, 0xfc, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xa0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff,
|
||||
0xf6, 0xa6, 0x10, 0x0, 0x0, 0x0, 0x1, 0xcf,
|
||||
0xff, 0xff, 0x1d, 0xff, 0xc8, 0x54, 0x33, 0x59,
|
||||
0xff, 0xff, 0xff, 0x80, 0xdf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xc0, 0xd, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0x0, 0x8f,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x70, 0x0,
|
||||
0x0, 0x5, 0x9b, 0xef, 0xff, 0xec, 0x95, 0x0,
|
||||
0x0, 0x0,
|
||||
|
||||
/* U+0036 "6" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x5, 0x9c, 0xef, 0xff,
|
||||
0xec, 0x30, 0x0, 0x0, 0x0, 0x1, 0x8f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x4,
|
||||
0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0,
|
||||
0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf4, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0x95,
|
||||
0x21, 0x0, 0x13, 0x10, 0x0, 0x0, 0xef, 0xff,
|
||||
0xf9, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x7f, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0xe, 0xff, 0xfc, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x50,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f,
|
||||
0xff, 0xf0, 0x1, 0x8c, 0xde, 0xda, 0x50, 0x0,
|
||||
0x0, 0xc, 0xff, 0xfc, 0x7, 0xff, 0xff, 0xff,
|
||||
0xff, 0xc2, 0x0, 0x0, 0xff, 0xff, 0x98, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xe3, 0x0, 0x1f, 0xff,
|
||||
0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0,
|
||||
0x2, 0xff, 0xff, 0xff, 0xf8, 0x30, 0x3, 0xbf,
|
||||
0xff, 0xff, 0x70, 0x3f, 0xff, 0xff, 0xf3, 0x0,
|
||||
0x0, 0x0, 0xaf, 0xff, 0xfd, 0x4, 0xff, 0xff,
|
||||
0xf6, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xf1,
|
||||
0x4f, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xc,
|
||||
0xff, 0xff, 0x33, 0xff, 0xff, 0xd0, 0x0, 0x0,
|
||||
0x0, 0x0, 0xaf, 0xff, 0xf5, 0x1f, 0xff, 0xfe,
|
||||
0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0xff, 0x50,
|
||||
0xff, 0xff, 0xf1, 0x0, 0x0, 0x0, 0x0, 0xbf,
|
||||
0xff, 0xf4, 0xb, 0xff, 0xff, 0x60, 0x0, 0x0,
|
||||
0x0, 0xe, 0xff, 0xff, 0x20, 0x7f, 0xff, 0xfd,
|
||||
0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0xe0, 0x1,
|
||||
0xff, 0xff, 0xfa, 0x0, 0x0, 0x1, 0xdf, 0xff,
|
||||
0xf9, 0x0, 0x7, 0xff, 0xff, 0xfc, 0x52, 0x26,
|
||||
0xef, 0xff, 0xff, 0x20, 0x0, 0xc, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, 0x0,
|
||||
0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90,
|
||||
0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfe, 0x60, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7b,
|
||||
0xef, 0xfd, 0xb6, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0037 "7" */
|
||||
0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf5, 0xbf, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf3, 0x35, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x7f, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xa, 0xff, 0xff, 0x50, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff,
|
||||
0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x9f, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x1f, 0xff, 0xff, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0x80,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef,
|
||||
0xff, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x7f, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0xe, 0xff, 0xff, 0x30, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xff,
|
||||
0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0xdf, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x5f, 0xff, 0xfd, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0xff, 0x60,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff,
|
||||
0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0xbf, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0x10, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xff,
|
||||
0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2,
|
||||
0xff, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x9f, 0xff, 0xfa, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0x30,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff,
|
||||
0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x1, 0xff, 0xff, 0xf5, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x8f, 0xff, 0xfd, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xff,
|
||||
0x60, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0038 "8" */
|
||||
0x0, 0x0, 0x1, 0x6a, 0xde, 0xfe, 0xda, 0x50,
|
||||
0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe7, 0x0, 0x0, 0x0, 0xb, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0,
|
||||
0xa, 0xff, 0xff, 0xff, 0xed, 0xef, 0xff, 0xff,
|
||||
0xf8, 0x0, 0x2, 0xff, 0xff, 0xfa, 0x20, 0x0,
|
||||
0x3c, 0xff, 0xff, 0xf0, 0x0, 0x6f, 0xff, 0xfb,
|
||||
0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0x30, 0x7,
|
||||
0xff, 0xff, 0x60, 0x0, 0x0, 0x0, 0x9f, 0xff,
|
||||
0xf4, 0x0, 0x6f, 0xff, 0xf6, 0x0, 0x0, 0x0,
|
||||
0x9, 0xff, 0xff, 0x30, 0x3, 0xff, 0xff, 0xb0,
|
||||
0x0, 0x0, 0x0, 0xdf, 0xff, 0xf0, 0x0, 0xc,
|
||||
0xff, 0xff, 0x80, 0x0, 0x0, 0x9f, 0xff, 0xf9,
|
||||
0x0, 0x0, 0x3f, 0xff, 0xff, 0xc3, 0x3, 0xcf,
|
||||
0xff, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff,
|
||||
0xfd, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0x0,
|
||||
0x2d, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4f, 0xff, 0xff, 0xff, 0xf9,
|
||||
0x0, 0x0, 0x0, 0x0, 0x1, 0xaf, 0xff, 0xff,
|
||||
0xff, 0xff, 0xfe, 0x50, 0x0, 0x0, 0x2, 0xef,
|
||||
0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xa0, 0x0,
|
||||
0x1, 0xef, 0xff, 0xfc, 0x20, 0x1, 0x9f, 0xff,
|
||||
0xff, 0xa0, 0x0, 0x9f, 0xff, 0xf9, 0x0, 0x0,
|
||||
0x0, 0x4e, 0xff, 0xff, 0x60, 0x1f, 0xff, 0xfd,
|
||||
0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfd, 0x4,
|
||||
0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xbf,
|
||||
0xff, 0xf1, 0x6f, 0xff, 0xf6, 0x0, 0x0, 0x0,
|
||||
0x0, 0x9, 0xff, 0xff, 0x35, 0xff, 0xff, 0x90,
|
||||
0x0, 0x0, 0x0, 0x0, 0xcf, 0xff, 0xf2, 0x2f,
|
||||
0xff, 0xff, 0x20, 0x0, 0x0, 0x0, 0x4f, 0xff,
|
||||
0xff, 0x0, 0xdf, 0xff, 0xfe, 0x60, 0x0, 0x1,
|
||||
0x7f, 0xff, 0xff, 0x90, 0x4, 0xff, 0xff, 0xff,
|
||||
0xfe, 0xde, 0xff, 0xff, 0xff, 0xe1, 0x0, 0x6,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1,
|
||||
0x0, 0x0, 0x4, 0xdf, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x81, 0x0, 0x0, 0x0, 0x0, 0x38, 0xbe,
|
||||
0xff, 0xed, 0xa6, 0x10, 0x0, 0x0,
|
||||
|
||||
/* U+0039 "9" */
|
||||
0x0, 0x0, 0x2, 0x7b, 0xef, 0xfe, 0xb6, 0x10,
|
||||
0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0x1d, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, 0x0,
|
||||
0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb0, 0x0, 0x6, 0xff, 0xff, 0xfc, 0x63, 0x35,
|
||||
0xbf, 0xff, 0xff, 0x60, 0x0, 0xdf, 0xff, 0xf9,
|
||||
0x0, 0x0, 0x0, 0x7f, 0xff, 0xfe, 0x0, 0x2f,
|
||||
0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff,
|
||||
0xf5, 0x5, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0,
|
||||
0x3, 0xff, 0xff, 0xa0, 0x6f, 0xff, 0xf8, 0x0,
|
||||
0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, 0x6, 0xff,
|
||||
0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff,
|
||||
0xf0, 0x5f, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0,
|
||||
0x2f, 0xff, 0xff, 0x21, 0xff, 0xff, 0xf4, 0x0,
|
||||
0x0, 0x0, 0x1d, 0xff, 0xff, 0xf2, 0xc, 0xff,
|
||||
0xff, 0xf6, 0x10, 0x1, 0x6e, 0xff, 0xff, 0xff,
|
||||
0x20, 0x4f, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff,
|
||||
0xef, 0xff, 0xf2, 0x0, 0x8f, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x8a, 0xff, 0xff, 0x10, 0x0, 0x7f,
|
||||
0xff, 0xff, 0xff, 0xff, 0x70, 0xcf, 0xff, 0xf0,
|
||||
0x0, 0x0, 0x17, 0xce, 0xff, 0xd9, 0x30, 0xe,
|
||||
0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x2, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xf6, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff,
|
||||
0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x5, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x2, 0xef, 0xff, 0xf5, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x4, 0xef, 0xff, 0xfc,
|
||||
0x0, 0x0, 0x2, 0x42, 0x10, 0x13, 0x7c, 0xff,
|
||||
0xff, 0xfe, 0x20, 0x0, 0x0, 0x6f, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x6,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x20, 0x0,
|
||||
0x0, 0x0, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xe7,
|
||||
0x0, 0x0, 0x0, 0x0, 0x4, 0xde, 0xff, 0xfe,
|
||||
0xc9, 0x50, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+003A ":" */
|
||||
0x5, 0xdf, 0xd5, 0x3, 0xff, 0xff, 0xf4, 0x8f,
|
||||
0xff, 0xff, 0x87, 0xff, 0xff, 0xf8, 0x4f, 0xff,
|
||||
0xff, 0x40, 0x8f, 0xff, 0x80, 0x0, 0x2, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0,
|
||||
0x8, 0xff, 0xf8, 0x5, 0xff, 0xff, 0xf5, 0x8f,
|
||||
0xff, 0xff, 0x87, 0xff, 0xff, 0xf8, 0x3f, 0xff,
|
||||
0xff, 0x30, 0x5d, 0xfd, 0x50
|
||||
};
|
||||
|
||||
|
||||
/*---------------------
|
||||
* GLYPH DESCRIPTION
|
||||
*--------------------*/
|
||||
|
||||
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
|
||||
{.bitmap_index = 0, .adv_w = 166, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 0, .adv_w = 205, .box_w = 11, .box_h = 5, .ofs_x = 1, .ofs_y = 9},
|
||||
{.bitmap_index = 28, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 322, .adv_w = 366, .box_w = 14, .box_h = 28, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 518, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 812, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1106, .adv_w = 366, .box_w = 23, .box_h = 28, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1428, .adv_w = 366, .box_w = 19, .box_h = 28, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1694, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1988, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2282, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2576, .adv_w = 366, .box_w = 21, .box_h = 28, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2870, .adv_w = 177, .box_w = 7, .box_h = 22, .ofs_x = 2, .ofs_y = 0}
|
||||
};
|
||||
|
||||
/*---------------------
|
||||
* CHARACTER MAPPING
|
||||
*--------------------*/
|
||||
|
||||
static const uint16_t unicode_list_0[] = {
|
||||
0x0, 0xd
|
||||
};
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||
{
|
||||
{
|
||||
.range_start = 32, .range_length = 14, .glyph_id_start = 1,
|
||||
.unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 2, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||
},
|
||||
{
|
||||
.range_start = 48, .range_length = 11, .glyph_id_start = 3,
|
||||
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*--------------------
|
||||
* ALL CUSTOM DATA
|
||||
*--------------------*/
|
||||
|
||||
#if LVGL_VERSION_MAJOR == 8
|
||||
/*Store all the custom data of the font*/
|
||||
static lv_font_fmt_txt_glyph_cache_t cache;
|
||||
#endif
|
||||
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
static const lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#else
|
||||
static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#endif
|
||||
.glyph_bitmap = glyph_bitmap,
|
||||
.glyph_dsc = glyph_dsc,
|
||||
.cmaps = cmaps,
|
||||
.kern_dsc = NULL,
|
||||
.kern_scale = 0,
|
||||
.cmap_num = 2,
|
||||
.bpp = 4,
|
||||
.kern_classes = 0,
|
||||
.bitmap_format = 0,
|
||||
#if LVGL_VERSION_MAJOR == 8
|
||||
.cache = &cache
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*-----------------
|
||||
* PUBLIC FONT
|
||||
*----------------*/
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
const lv_font_t ui_font_40 = {
|
||||
#else
|
||||
lv_font_t ui_font_40 = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
.line_height = 28, /*The maximum line height required by the font*/
|
||||
.base_line = 0, /*Baseline measured from the bottom of the line*/
|
||||
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
|
||||
.subpx = LV_FONT_SUBPX_NONE,
|
||||
#endif
|
||||
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
|
||||
.underline_position = -4,
|
||||
.underline_thickness = 2,
|
||||
#endif
|
||||
.dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
|
||||
#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9
|
||||
.fallback = NULL,
|
||||
#endif
|
||||
.user_data = NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /*#if UI_FONT_40*/
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#define LV_USE_ASSERT_NULL 1
|
||||
#define LV_USE_ASSERT_MALLOC 1
|
||||
|
||||
// Fonts. Montserrat is ASCII + a few symbols only -- Polish / Cyrillic
|
||||
// coverage needs a generated font (lv_font_conv), planned with the theme work.
|
||||
#define LV_FONT_MONTSERRAT_12 1
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 1
|
||||
#define LV_FONT_MONTSERRAT_20 1
|
||||
#define LV_FONT_MONTSERRAT_40 1
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||
// Fonts: generated Noto Sans (European Latin, Greek, Cyrillic + LV_SYMBOL_*),
|
||||
// see fonts/generate.sh. LVGL's built-in Montserrat (ASCII only) is off.
|
||||
#define LV_FONT_MONTSERRAT_14 0
|
||||
#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(ui_font_12) LV_FONT_DECLARE(ui_font_14) \
|
||||
LV_FONT_DECLARE(ui_font_16) LV_FONT_DECLARE(ui_font_20) \
|
||||
LV_FONT_DECLARE(ui_font_40)
|
||||
#define LV_FONT_DEFAULT &ui_font_14
|
||||
#define LV_USE_FONT_COMPRESSED 1 // generated fonts are RLE-compressed (without this every glyph draws as a box)
|
||||
|
||||
#define LV_USE_THEME_DEFAULT 1
|
||||
#define LV_THEME_DEFAULT_DARK 1
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "PopupMenu.h"
|
||||
#include "icons.h" // mini-icons for the special-key row (⇧ ⌫ ⎵ ✓)
|
||||
#include "../NodePrefs.h"
|
||||
#include "../ui-core/KeyboardData.h" // shared long-press variants + case table
|
||||
|
||||
// Layout constants shared by all keyboard users.
|
||||
// Two pages: letters (page 0) and symbols (page 1), toggled by the "#@"/"abc"
|
||||
@@ -147,30 +148,12 @@ static const int KB_PREVIEW_BYTES = KB_PREVIEW_CAP * 2;
|
||||
static void kbApplyCapsUtf8(const char* in, bool caps, char* out, size_t out_size) {
|
||||
size_t o = 0;
|
||||
const uint8_t* p = (const uint8_t*)in;
|
||||
while (*p && o + 2 < out_size) {
|
||||
while (*p && o + 4 < out_size) {
|
||||
uint32_t cp = DisplayDriver::decodeCodepoint(p);
|
||||
if (caps) {
|
||||
if (cp == 0x0451) cp = 0x0401; // ё -> Ё
|
||||
else if (cp == 0x03C2) cp = 0x03A3; // ς -> Σ
|
||||
else if (cp == 0x00FF) cp = 0x0178; // ÿ -> Ÿ (French; breaks the à-þ flat -0x20 rule below — Ÿ sits outside Latin-1 Supplement entirely)
|
||||
else if (cp >= 0x0430 && cp <= 0x044F) cp -= 0x20; // а-я -> А-Я
|
||||
else if (cp >= 0x03B1 && cp <= 0x03C9) cp -= 0x20; // α-ω -> Α-Ω
|
||||
else if (cp >= 0x00E0 && cp <= 0x00FE && cp != 0x00F7) cp -= 0x20; // à-þ -> À-Þ
|
||||
// ą-ż (Latin Extended-A): pairing parity flips around the unpaired
|
||||
// codepoints ĸ (U+0138), ʼn (U+0149), Ÿ (U+0178) -- verified exhaustively
|
||||
// over the whole U+0100-U+017F block, resolves ł ń ź ż + ĺ ľ ň ž too.
|
||||
else if (cp >= 0x0100 && cp <= 0x0137 && (cp & 1) == 1) cp -= 1; // odd=lower
|
||||
else if (cp >= 0x0139 && cp <= 0x0148 && (cp & 1) == 0) cp -= 1; // even=lower
|
||||
else if (cp >= 0x014A && cp <= 0x0177 && (cp & 1) == 1) cp -= 1; // odd=lower
|
||||
else if (cp >= 0x0179 && cp <= 0x017E && (cp & 1) == 0) cp -= 1; // even=lower
|
||||
else if (cp >= 'a' && cp <= 'z') cp -= 0x20; // a-z -> A-Z
|
||||
}
|
||||
if (cp < 0x80) {
|
||||
out[o++] = (char)cp;
|
||||
} else {
|
||||
out[o++] = (char)(0xC0 | (cp >> 6));
|
||||
out[o++] = (char)(0x80 | (cp & 0x3F));
|
||||
}
|
||||
// Shared case table (ui-core/KeyboardData.h). ß stays ß here: its
|
||||
// uppercase ẞ (U+1E9E) is outside the misc-fixed font's U+0020-04FF.
|
||||
if (caps && cp != 0x00DF) cp = kbd::toUpper(cp);
|
||||
o += kbd::encode(cp, out + o);
|
||||
}
|
||||
out[o] = '\0';
|
||||
}
|
||||
@@ -239,28 +222,9 @@ static int kbUtf8CharBytesAt(const char* buf, int pos, int len) {
|
||||
// Ligature/non-diacritic letters are filed under their conventional key, same
|
||||
// as a phone keyboard's long-press: ß (German) -> s, œ (French) -> o. ĺ/ŕ
|
||||
// (Slovak) are l/r with an acute, not i/e variants, so they're filed there.
|
||||
static const char KB_ACCENT_BASES[] = "acdeilnorstuyz";
|
||||
static const char* const KB_ACCENT_VARIANTS[] = {
|
||||
"áàâãäåą", // a
|
||||
"çćč", // c
|
||||
"ď", // d
|
||||
"éèêëěę", // e
|
||||
"íîï", // i
|
||||
"łĺľ", // l
|
||||
"ñńň", // n
|
||||
"óòôõöøœ", // o
|
||||
"řŕ", // r
|
||||
"śšß", // s
|
||||
"ť", // t
|
||||
"úùûüů", // u
|
||||
"ýÿ", // y
|
||||
"źżž", // z
|
||||
};
|
||||
static const int KB_ACCENT_COUNT = sizeof(KB_ACCENT_BASES) - 1; // exclude the trailing NUL
|
||||
static int findAccentGroup(char base) {
|
||||
for (int i = 0; i < KB_ACCENT_COUNT; i++) if (KB_ACCENT_BASES[i] == base) return i;
|
||||
return -1;
|
||||
}
|
||||
// The table itself is shared with every frontend (ui-core/KeyboardData.h).
|
||||
static const char* const* const KB_ACCENT_VARIANTS = kbd::LATIN_VARIANTS;
|
||||
static int findAccentGroup(char base) { return kbd::latinGroup(base); }
|
||||
|
||||
static const int KB_PH_MAX = 20; // max placeholders in list (PopupMenu::PM_MAX_ITEMS=24 is the hard ceiling)
|
||||
static const int KB_PH_LEN = 30; // max placeholder string length incl. null -- sized for the longest
|
||||
|
||||
@@ -60,6 +60,7 @@ build_src_filter = ${Wio_Tracker_L2.build_src_filter}
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-lvgl/*.cpp>
|
||||
+<../examples/companion_radio/ui-lvgl/fonts/*.c>
|
||||
lib_deps =
|
||||
${Wio_Tracker_L2.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
Reference in New Issue
Block a user