mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 03:06:39 +00:00
feat(ui-lvgl): even status icons, relay count badge, clearer path popup, edge scrollbars
- Status bar icons come from ui_icons_14: FontAwesome refitted to one size by fonts/status_icons.py (falls back to ui_font_12 for the battery level text), the charging bolt in a tight cell. - Own channel posts show the repeater count as a small badge, as L1, instead of a check and a number. - Message path popup: a stronger connector, roles on the right (sender / hop N / you), our post's repeaters fanned out under us, long paths scroll. - Scrollbars everywhere are thin and hug the edge, clear of the content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -228,32 +228,47 @@ void UITask::conversationAction(uint8_t act) {
|
|||||||
// ── Message actions ───────────────────────────────────────────────────────────
|
// ── Message actions ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// One stop on the path diagram: a dot on a vertical line (the line runs on to
|
// One stop on the path diagram: a dot on a vertical line (the line runs on to
|
||||||
// the next stop unless `last`), the name beside it.
|
// the next stop unless `last`), the name beside it, what it is on the right.
|
||||||
static void pathStop(lv_obj_t* parent, const char* name, bool first, bool last, uint32_t col) {
|
static void pathStop(lv_obj_t* parent, const char* name, const char* role, bool first, bool last,
|
||||||
|
uint32_t col, bool end) {
|
||||||
lv_obj_t* row = lv_obj_create(parent);
|
lv_obj_t* row = lv_obj_create(parent);
|
||||||
lv_obj_remove_style_all(row);
|
lv_obj_remove_style_all(row);
|
||||||
lv_obj_remove_flag(row, LV_OBJ_FLAG_CLICKABLE);
|
lv_obj_remove_flag(row, LV_OBJ_FLAG_CLICKABLE);
|
||||||
lv_obj_set_size(row, LV_PCT(100), 20);
|
lv_obj_set_size(row, LV_PCT(100), 22);
|
||||||
if (!first || !last) {
|
if (!first || !last) {
|
||||||
lv_obj_t* line = lv_obj_create(row);
|
lv_obj_t* line = lv_obj_create(row);
|
||||||
lv_obj_remove_style_all(line);
|
lv_obj_remove_style_all(line);
|
||||||
lv_obj_set_style_bg_opa(line, LV_OPA_COVER, 0);
|
lv_obj_set_style_bg_color(line, lv_color_hex(theme::TEXT_MUTED), 0);
|
||||||
lv_obj_set_style_bg_color(line, lv_color_hex(theme::SURFACE_2), 0);
|
lv_obj_set_style_bg_opa(line, LV_OPA_50, 0);
|
||||||
lv_obj_set_size(line, 2, first || last ? 10 : 20);
|
lv_obj_set_size(line, 2, first || last ? 11 : 22);
|
||||||
lv_obj_set_pos(line, 6, first ? 10 : 0);
|
lv_obj_set_pos(line, 6, first ? 11 : 0);
|
||||||
}
|
}
|
||||||
lv_obj_t* dot = lv_obj_create(row);
|
lv_obj_t* dot = lv_obj_create(row);
|
||||||
lv_obj_remove_style_all(dot);
|
lv_obj_remove_style_all(dot);
|
||||||
lv_obj_set_style_bg_opa(dot, LV_OPA_COVER, 0);
|
lv_obj_set_style_bg_opa(dot, LV_OPA_COVER, 0);
|
||||||
lv_obj_set_style_bg_color(dot, lv_color_hex(col), 0);
|
lv_obj_set_style_bg_color(dot, lv_color_hex(end ? col : theme::SURFACE), 0);
|
||||||
|
lv_obj_set_style_border_color(dot, lv_color_hex(col), 0);
|
||||||
|
lv_obj_set_style_border_width(dot, end ? 0 : 2, 0);
|
||||||
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, 0);
|
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, 0);
|
||||||
bool end = first || last;
|
|
||||||
lv_obj_set_size(dot, end ? 10 : 8, end ? 10 : 8);
|
lv_obj_set_size(dot, end ? 10 : 8, end ? 10 : 8);
|
||||||
lv_obj_align(dot, LV_ALIGN_LEFT_MID, end ? 2 : 3, 0);
|
lv_obj_align(dot, LV_ALIGN_LEFT_MID, end ? 2 : 3, 0);
|
||||||
lv_obj_t* t = label(row, name, end ? THEME_FONT_BODY : THEME_FONT_SMALL, end ? theme::TEXT : theme::TEXT_MUTED);
|
lv_obj_t* t = label(row, name, end ? THEME_FONT_BODY : THEME_FONT_SMALL, theme::TEXT);
|
||||||
lv_label_set_long_mode(t, LV_LABEL_LONG_DOT);
|
lv_label_set_long_mode(t, LV_LABEL_LONG_DOT);
|
||||||
lv_obj_set_width(t, 240);
|
lv_obj_set_width(t, 190);
|
||||||
lv_obj_align(t, LV_ALIGN_LEFT_MID, 22, 0);
|
lv_obj_align(t, LV_ALIGN_LEFT_MID, 22, 0);
|
||||||
|
if (role && role[0]) lv_obj_align(label(row, role, THEME_FONT_SMALL, theme::TEXT_MUTED), LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The stops of a path, in a box that scrolls once there are many (up to 64 hops).
|
||||||
|
static lv_obj_t* pathDiagram(lv_obj_t* panel) {
|
||||||
|
lv_obj_t* diag = lv_obj_create(panel);
|
||||||
|
lv_obj_remove_style_all(diag);
|
||||||
|
lv_obj_set_size(diag, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_max_height(diag, 5 * 22, 0);
|
||||||
|
lv_obj_set_style_pad_right(diag, 6, 0); // the roles clear this box's own scrollbar
|
||||||
|
lv_obj_set_flex_flow(diag, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_scroll_dir(diag, LV_DIR_VER);
|
||||||
|
return diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITask::messageMenu(int idx) {
|
void UITask::messageMenu(int idx) {
|
||||||
@@ -330,29 +345,29 @@ void UITask::messageMenu(int idx) {
|
|||||||
}
|
}
|
||||||
label(panel, st, THEME_FONT_BODY, col);
|
label(panel, st, THEME_FONT_BODY, col);
|
||||||
} else if (relay) { // our channel post: the repeaters heard passing it on
|
} else if (relay) { // our channel post: the repeaters heard passing it on
|
||||||
char hd[40];
|
char hd[48];
|
||||||
if (hops > 0) snprintf(hd, sizeof(hd), LV_SYMBOL_OK " Relayed by %u repeater%s", hops, hops == 1 ? "" : "s");
|
if (hops > 0) snprintf(hd, sizeof(hd), "Heard %u repeater%s pass it on", hops, hops == 1 ? "" : "s");
|
||||||
else snprintf(hd, sizeof(hd), "No repeater heard relaying it yet");
|
else snprintf(hd, sizeof(hd), "No repeater heard passing it on yet");
|
||||||
label(panel, hd, THEME_FONT_BODY, hops > 0 ? theme::OK : theme::TEXT_MUTED);
|
label(panel, hd, THEME_FONT_BODY, hops > 0 ? theme::OK : theme::TEXT_MUTED);
|
||||||
for (uint8_t i = 0; i < hops; i++) {
|
if (hops > 0) { // each one an echo of ours: a fan out from us, not a chain
|
||||||
char nm[33], line[40];
|
lv_obj_t* diag = pathDiagram(panel);
|
||||||
contactctl::hopName(packed, path, i, nm, sizeof(nm));
|
pathStop(diag, the_mesh.getNodeName(), "you", true, false, theme::ACCENT, true);
|
||||||
snprintf(line, sizeof(line), UI_SYMBOL_RADIO " %s", nm);
|
for (uint8_t i = 0; i < hops; i++) {
|
||||||
label(panel, line, THEME_FONT_SMALL, theme::TEXT_MUTED);
|
char nm[33];
|
||||||
|
contactctl::hopName(packed, path, i, nm, sizeof(nm));
|
||||||
|
pathStop(diag, nm, UI_SYMBOL_RADIO, false, i == hops - 1, theme::OK, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else { // incoming: sender, each hop, then us
|
} else { // incoming: sender, each hop, then us
|
||||||
lv_obj_t* diag = lv_obj_create(panel);
|
lv_obj_t* diag = pathDiagram(panel);
|
||||||
lv_obj_remove_style_all(diag);
|
pathStop(diag, m.from[0] ? m.from : "Sender", "sender", true, false, theme::ACCENT, true);
|
||||||
lv_obj_remove_flag(diag, LV_OBJ_FLAG_CLICKABLE);
|
|
||||||
lv_obj_set_size(diag, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_flex_flow(diag, LV_FLEX_FLOW_COLUMN);
|
|
||||||
pathStop(diag, m.from[0] ? m.from : "Sender", true, false, theme::ACCENT);
|
|
||||||
for (uint8_t i = 0; i < hops; i++) {
|
for (uint8_t i = 0; i < hops; i++) {
|
||||||
char nm[33];
|
char nm[33], role[12];
|
||||||
contactctl::hopName(packed, path, i, nm, sizeof(nm));
|
contactctl::hopName(packed, path, i, nm, sizeof(nm));
|
||||||
pathStop(diag, nm, false, false, theme::TEXT_MUTED);
|
snprintf(role, sizeof(role), "hop %u", (unsigned)(i + 1));
|
||||||
|
pathStop(diag, nm, role, false, false, theme::TEXT_MUTED, false);
|
||||||
}
|
}
|
||||||
pathStop(diag, the_mesh.getNodeName(), false, true, theme::OK);
|
pathStop(diag, the_mesh.getNodeName(), "you", false, true, theme::OK, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_reply = !m.own && m.from[0] && _compose_ta;
|
bool can_reply = !m.own && m.from[0] && _compose_ta;
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ namespace theme {
|
|||||||
#define THEME_FONT_TITLE (&ui_font_16)
|
#define THEME_FONT_TITLE (&ui_font_16)
|
||||||
#define THEME_FONT_LARGE (&ui_font_20)
|
#define THEME_FONT_LARGE (&ui_font_20)
|
||||||
#define THEME_FONT_CLOCK (&ui_font_40)
|
#define THEME_FONT_CLOCK (&ui_font_40)
|
||||||
|
// Status bar icons, refitted to one size (fonts/status_icons.py); any other
|
||||||
|
// character falls back to ui_font_12.
|
||||||
|
#define THEME_FONT_ICONS (&ui_icons_14)
|
||||||
|
|
||||||
// Extra FontAwesome glyphs baked into ui_font_12..20 beyond LVGL's LV_SYMBOL_*.
|
// Extra FontAwesome glyphs baked into ui_font_12..20 beyond LVGL's LV_SYMBOL_*.
|
||||||
#define UI_SYMBOL_STAR "\xEF\x80\x85" // U+F005, favourite
|
#define UI_SYMBOL_STAR "\xEF\x80\x85" // U+F005, favourite
|
||||||
@@ -78,11 +81,14 @@ namespace theme {
|
|||||||
// Over LVGL's default theme, for every widget: a checked button is
|
// Over LVGL's default theme, for every widget: a checked button is
|
||||||
// "selected" (ACCENT_DIM, not the default theme's full accent), buttons
|
// "selected" (ACCENT_DIM, not the default theme's full accent), buttons
|
||||||
// have the card radius and give a little under the finger (the default
|
// have the card radius and give a little under the finger (the default
|
||||||
// theme's transitions animate it both ways).
|
// theme's transitions animate it both ways). Scrollbars are thin and hug
|
||||||
|
// the edge, inside the padding every panel and list has, instead of the
|
||||||
|
// default's 5 px bar 7 px in, which ran over right-aligned text.
|
||||||
static lv_theme_t s_theme;
|
static lv_theme_t s_theme;
|
||||||
static lv_style_t s_btn, s_press, s_checked;
|
static lv_style_t s_btn, s_press, s_checked, s_sbar;
|
||||||
static void applyTheme(lv_theme_t* th, lv_obj_t* obj) {
|
static void applyTheme(lv_theme_t* th, lv_obj_t* obj) {
|
||||||
(void)th;
|
(void)th;
|
||||||
|
lv_obj_add_style(obj, &s_sbar, LV_PART_SCROLLBAR);
|
||||||
if (lv_obj_check_type(obj, &lv_button_class)) {
|
if (lv_obj_check_type(obj, &lv_button_class)) {
|
||||||
lv_obj_add_style(obj, &s_btn, 0);
|
lv_obj_add_style(obj, &s_btn, 0);
|
||||||
lv_obj_add_style(obj, &s_press, LV_STATE_PRESSED);
|
lv_obj_add_style(obj, &s_press, LV_STATE_PRESSED);
|
||||||
@@ -102,6 +108,12 @@ namespace theme {
|
|||||||
lv_style_set_transform_height(&s_press, -2);
|
lv_style_set_transform_height(&s_press, -2);
|
||||||
lv_style_init(&s_checked);
|
lv_style_init(&s_checked);
|
||||||
lv_style_set_text_color(&s_checked, lv_color_hex(TEXT));
|
lv_style_set_text_color(&s_checked, lv_color_hex(TEXT));
|
||||||
|
lv_style_init(&s_sbar);
|
||||||
|
lv_style_set_width(&s_sbar, 3);
|
||||||
|
lv_style_set_pad_right(&s_sbar, 2); // vertical bar: 2 px off the edge
|
||||||
|
lv_style_set_pad_bottom(&s_sbar, 2); // horizontal bar likewise
|
||||||
|
lv_style_set_pad_top(&s_sbar, RADIUS / 2);
|
||||||
|
lv_style_set_pad_left(&s_sbar, RADIUS / 2);
|
||||||
}
|
}
|
||||||
lv_style_set_bg_color(&s_checked, lv_color_hex(ACCENT_DIM));
|
lv_style_set_bg_color(&s_checked, lv_color_hex(ACCENT_DIM));
|
||||||
lv_theme_t* base = lv_theme_default_init(disp, lv_color_hex(ACCENT), lv_color_hex(ACCENT_DIM), true, THEME_FONT_BODY);
|
lv_theme_t* base = lv_theme_default_init(disp, lv_color_hex(ACCENT), lv_color_hex(ACCENT_DIM), true, THEME_FONT_BODY);
|
||||||
|
|||||||
@@ -567,7 +567,7 @@ void UITask::buildStatusBar() {
|
|||||||
|
|
||||||
_status_time = label(bar, "--:--", THEME_FONT_SMALL, theme::TEXT);
|
_status_time = label(bar, "--:--", THEME_FONT_SMALL, theme::TEXT);
|
||||||
lv_obj_align(_status_time, LV_ALIGN_LEFT_MID, 0, 0);
|
lv_obj_align(_status_time, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
_status_batt = label(bar, "", THEME_FONT_SMALL, theme::TEXT_MUTED);
|
_status_batt = label(bar, "", THEME_FONT_ICONS, theme::TEXT_MUTED);
|
||||||
lv_obj_align(_status_batt, LV_ALIGN_RIGHT_MID, 0, 0);
|
lv_obj_align(_status_batt, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
_status_icons = lv_obj_create(bar);
|
_status_icons = lv_obj_create(bar);
|
||||||
lv_obj_remove_style_all(_status_icons);
|
lv_obj_remove_style_all(_status_icons);
|
||||||
@@ -575,7 +575,7 @@ void UITask::buildStatusBar() {
|
|||||||
lv_obj_set_size(_status_icons, 200, LV_PCT(100)); // fixed: packed to its right edge
|
lv_obj_set_size(_status_icons, 200, LV_PCT(100)); // fixed: packed to its right edge
|
||||||
lv_obj_set_flex_flow(_status_icons, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(_status_icons, LV_FLEX_FLOW_ROW);
|
||||||
lv_obj_set_flex_align(_status_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
lv_obj_set_flex_align(_status_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
lv_obj_set_style_pad_column(_status_icons, 3, 0);
|
lv_obj_set_style_pad_column(_status_icons, 2, 0);
|
||||||
|
|
||||||
_toast = lv_obj_create(lv_layer_top());
|
_toast = lv_obj_create(lv_layer_top());
|
||||||
lv_obj_remove_flag(_toast, LV_OBJ_FLAG_SCROLLABLE);
|
lv_obj_remove_flag(_toast, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
@@ -619,7 +619,7 @@ void UITask::refreshStatusBar() {
|
|||||||
case battery::VOLTAGE: snprintf(level, sizeof(level), " %u.%02u V", mv / 1000, (mv % 1000) / 10); break;
|
case battery::VOLTAGE: snprintf(level, sizeof(level), " %u.%02u V", mv / 1000, (mv % 1000) / 10); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
lv_label_set_text_fmt(_status_batt, "%s%s%s", _board->isExternalPowered() ? LV_SYMBOL_CHARGE " " : "", batt, level);
|
lv_label_set_text_fmt(_status_batt, "%s%s%s", _board->isExternalPowered() ? LV_SYMBOL_CHARGE : "", batt, level);
|
||||||
|
|
||||||
// Status icons, as the original's status bar (ui-new): Bluetooth (bright
|
// Status icons, as the original's status bar (ui-new): Bluetooth (bright
|
||||||
// when the app is connected), GPS (green with a fix), the alarm, mute, then
|
// when the app is connected), GPS (green with a fix), the alarm, mute, then
|
||||||
@@ -649,13 +649,10 @@ void UITask::refreshStatusBar() {
|
|||||||
if (strcmp(sig, _status_sig) != 0) { // rebuilt only when something changed
|
if (strcmp(sig, _status_sig) != 0) { // rebuilt only when something changed
|
||||||
strcpy(_status_sig, sig);
|
strcpy(_status_sig, sig);
|
||||||
lv_obj_clean(_status_icons);
|
lv_obj_clean(_status_icons);
|
||||||
for (int i = n - 1; i >= 0; i--) { // one cell each: glyphs vary in width, the rhythm doesn't
|
for (int i = n - 1; i >= 0; i--) // the icon font gives each the same size and cell
|
||||||
lv_obj_t* l = label(_status_icons, icons[i].sym, THEME_FONT_SMALL, icons[i].col);
|
label(_status_icons, icons[i].sym, THEME_FONT_ICONS, icons[i].col);
|
||||||
lv_obj_set_width(l, 16);
|
|
||||||
lv_obj_set_style_text_align(l, LV_TEXT_ALIGN_CENTER, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lv_obj_align_to(_status_icons, _status_batt, LV_ALIGN_OUT_LEFT_MID, -8, 0);
|
lv_obj_align_to(_status_icons, _status_batt, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITask::setGps(bool on) {
|
void UITask::setGps(bool on) {
|
||||||
@@ -1964,7 +1961,8 @@ static void msgLocButton(lv_obj_t* parent, const char* text, int idx, bool save,
|
|||||||
// One message bubble. Own messages right-aligned in amber, others left.
|
// One message bubble. Own messages right-aligned in amber, others left.
|
||||||
// loc_idx >= 0: the text carries a position (s_msg_locs[loc_idx]).
|
// loc_idx >= 0: the text carries a position (s_msg_locs[loc_idx]).
|
||||||
static void bubble(lv_obj_t* list, const char* from, const char* text, bool own,
|
static void bubble(lv_obj_t* list, const char* from, const char* text, bool own,
|
||||||
uint32_t ts, const char* status, uint32_t status_col, int loc_idx = -1, int meta_idx = -1) {
|
uint32_t ts, const char* status, uint32_t status_col, int loc_idx = -1, int meta_idx = -1,
|
||||||
|
int relays = 0) {
|
||||||
// Full-width row that pushes the bubble to its side.
|
// Full-width row that pushes the bubble to its side.
|
||||||
lv_obj_t* row = lv_obj_create(list);
|
lv_obj_t* row = lv_obj_create(list);
|
||||||
styleSurface(row, theme::BG);
|
styleSurface(row, theme::BG);
|
||||||
@@ -2031,15 +2029,31 @@ static void bubble(lv_obj_t* list, const char* from, const char* text, bool own,
|
|||||||
msgLocButton(acts, UI_SYMBOL_FLAG " Save", loc_idx, true, false);
|
msgLocButton(acts, UI_SYMBOL_FLAG " Save", loc_idx, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!meta_in_header) { // the age, then the delivery mark in its colour (as L1: ✓ 3)
|
if (!meta_in_header) { // the age, then the delivery mark in its colour (as L1)
|
||||||
lv_obj_t* line = lv_obj_create(b);
|
lv_obj_t* line = lv_obj_create(b);
|
||||||
lv_obj_remove_style_all(line);
|
lv_obj_remove_style_all(line);
|
||||||
lv_obj_remove_flag(line, LV_OBJ_FLAG_CLICKABLE);
|
lv_obj_remove_flag(line, LV_OBJ_FLAG_CLICKABLE);
|
||||||
lv_obj_set_size(line, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
lv_obj_set_size(line, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||||
lv_obj_set_flex_flow(line, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(line, LV_FLEX_FLOW_ROW);
|
||||||
|
lv_obj_set_flex_align(line, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
lv_obj_set_style_pad_column(line, 6, 0);
|
lv_obj_set_style_pad_column(line, 6, 0);
|
||||||
label(line, meta, THEME_FONT_SMALL, theme::TEXT_MUTED);
|
label(line, meta, THEME_FONT_SMALL, theme::TEXT_MUTED);
|
||||||
if (status && status[0]) label(line, status, THEME_FONT_SMALL, status_col);
|
if (relays > 0) { // as L1: the count alone says it got out, no check beside it
|
||||||
|
lv_obj_t* c = lv_obj_create(line);
|
||||||
|
lv_obj_remove_style_all(c);
|
||||||
|
lv_obj_remove_flag(c, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_set_size(c, LV_SIZE_CONTENT, 15);
|
||||||
|
lv_obj_set_style_min_width(c, 15, 0);
|
||||||
|
lv_obj_set_style_pad_hor(c, 4, 0);
|
||||||
|
lv_obj_set_style_bg_opa(c, LV_OPA_COVER, 0);
|
||||||
|
lv_obj_set_style_bg_color(c, lv_color_hex(theme::OK), 0);
|
||||||
|
lv_obj_set_style_radius(c, LV_RADIUS_CIRCLE, 0);
|
||||||
|
lv_obj_t* n = label(c, "", THEME_FONT_SMALL, theme::BG);
|
||||||
|
lv_label_set_text_fmt(n, "%d", relays);
|
||||||
|
lv_obj_center(n);
|
||||||
|
} else if (status && status[0]) {
|
||||||
|
label(line, status, THEME_FONT_SMALL, status_col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2161,19 +2175,18 @@ void UITask::refreshThread() {
|
|||||||
body = sep + 2;
|
body = sep + 2;
|
||||||
}
|
}
|
||||||
bool own = strcmp(from, "Me") == 0;
|
bool own = strcmp(from, "Me") == 0;
|
||||||
// Own posts: a check once a repeater echoed it, with how many distinct
|
// Own posts: once a repeater echoed it, how many distinct repeaters did
|
||||||
// repeaters did (markChannelRelayed); nothing before -- no echo is normal.
|
// (markChannelRelayed), or a check if that's unknown; nothing before --
|
||||||
|
// no echo is normal.
|
||||||
const char* st = NULL; uint32_t col = theme::TEXT_MUTED;
|
const char* st = NULL; uint32_t col = theme::TEXT_MUTED;
|
||||||
char relays[16];
|
int nrel = 0;
|
||||||
if (own && e.relay_status == ACK_OK) {
|
if (own && e.relay_status == ACK_OK) {
|
||||||
int nrel = e.path_len & 63;
|
nrel = e.path_len & 63;
|
||||||
if (nrel > 0) snprintf(relays, sizeof(relays), LV_SYMBOL_OK " %d", nrel);
|
st = LV_SYMBOL_OK; col = theme::OK;
|
||||||
else snprintf(relays, sizeof(relays), LV_SYMBOL_OK);
|
|
||||||
st = relays; col = theme::OK;
|
|
||||||
} else if (own) st = "";
|
} else if (own) st = "";
|
||||||
int loc = own ? -1 : noteMsgLocation(body, from);
|
int loc = own ? -1 : noteMsgLocation(body, from);
|
||||||
bubble(_thread_list, own ? NULL : from, body, own, e.timestamp, st, col,
|
bubble(_thread_list, own ? NULL : from, body, own, e.timestamp, st, col,
|
||||||
loc, noteMsgMeta(i, true, own, loc, own ? "" : from));
|
loc, noteMsgMeta(i, true, own, loc, own ? "" : from), nrel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ContactInfo tc;
|
ContactInfo tc;
|
||||||
|
|||||||
@@ -45,4 +45,13 @@ for s in 12 14 16 20; do gen "$s" Medium "$TEXT" "ui_font_$s"; done
|
|||||||
# Clock: digits, colon, dash, dot, space only.
|
# Clock: digits, colon, dash, dot, space only.
|
||||||
$CONV --bpp 4 --size 40 --no-compress --font "$CACHE/NotoSans-SemiBold.ttf" -r "0x20,0x2D-0x2E,0x30-0x3A" \
|
$CONV --bpp 4 --size 40 --no-compress --font "$CACHE/NotoSans-SemiBold.ttf" -r "0x20,0x2D-0x2E,0x30-0x3A" \
|
||||||
--format lvgl --lv-include lvgl.h --lv-font-name ui_font_40 -o "$HERE/ui_font_40.c"
|
--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"
|
# Status bar icons: FontAwesome refitted to one size (status_icons.py, needs
|
||||||
|
# python3 with fonttools). Line metrics forced to ui_font_12's and text falls
|
||||||
|
# back to it, so "<battery> 85%" is one label.
|
||||||
|
ICONS="0xF024,0xF079,0xF0E7,0xF0F3,0xF124,0xF1EB,0xF240-0xF244,0xF293,0xF3C5,0xF4D7,0xF519,0xF6A9"
|
||||||
|
python3 "$HERE/status_icons.py" "$CACHE/fa.woff" "$CACHE/ui-icons.ttf"
|
||||||
|
$CONV --bpp 4 --size 14 --no-compress --font "$CACHE/ui-icons.ttf" -r "$ICONS" \
|
||||||
|
--format lvgl --lv-include lvgl.h --lv-font-name ui_icons_14 -o "$HERE/ui_icons_14.c"
|
||||||
|
sed -i.bak -e 's/\.line_height = [0-9]*,/.line_height = 18,/' -e 's/\.base_line = [0-9]*,/.base_line = 4,/' \
|
||||||
|
-e 's/\.fallback = NULL,/.fallback = \&ui_font_12,/' "$HERE/ui_icons_14.c" && rm "$HERE/ui_icons_14.c.bak"
|
||||||
|
echo "done:$(ls "$HERE"/ui_font_*.c | wc -l) fonts"
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Builds the status bar's icon font source: FontAwesome glyphs refitted so
|
||||||
|
every icon reads the same size.
|
||||||
|
|
||||||
|
FontAwesome draws each icon on its own canvas -- a battery is wide and flat,
|
||||||
|
a map pin narrow and tall, a mute sign short -- so at one font size they come
|
||||||
|
out anywhere from 9 to 16 px wide and 9 to 13 px tall. Here every glyph is
|
||||||
|
scaled to fit one box (BOX_H tall, at most BOX_W wide; WIDE icons get more
|
||||||
|
width), centred on the middle of the Noto digits, in a cell of ADVANCE (wide
|
||||||
|
icons a little more).
|
||||||
|
Line metrics match ui_font_12 (line height 18, baseline 4), so the digits of
|
||||||
|
"85%" can share a label with the icons (the font falls back to ui_font_12).
|
||||||
|
|
||||||
|
Usage: status_icons.py <FontAwesome .woff/.ttf> <out.ttf> (needs fonttools)
|
||||||
|
Called by generate.sh, which turns the result into ui_icons_14.c.
|
||||||
|
"""
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
from fontTools.fontBuilder import FontBuilder
|
||||||
|
from fontTools.pens.recordingPen import DecomposingRecordingPen
|
||||||
|
from fontTools.pens.transformPen import TransformPen
|
||||||
|
from fontTools.pens.ttGlyphPen import TTGlyphPen
|
||||||
|
from fontTools.pens.boundsPen import BoundsPen
|
||||||
|
|
||||||
|
SIZE = 14.0 # px per em, as generate.sh renders it
|
||||||
|
UPM = 1024
|
||||||
|
PX = UPM / SIZE # font units per pixel
|
||||||
|
|
||||||
|
BOX_H = 11.0 # every icon this tall...
|
||||||
|
BOX_W = 13.0 # ...unless that makes it wider than this
|
||||||
|
WIDE_W = 17.0 # battery-shaped icons may be this wide
|
||||||
|
ADVANCE = 16.0 # one cell per icon
|
||||||
|
MID_Y = 4.5 # icon centre, px above the baseline (middle of the digits)
|
||||||
|
ASCENT, DESCENT = 14.0, 4.0 # line height 18, baseline 4 = ui_font_12
|
||||||
|
|
||||||
|
ICONS = [ # codepoint, wide (True: wider box, None: tight cell)
|
||||||
|
(0xF293, False), # bluetooth
|
||||||
|
(0xF124, False), # location arrow (GPS)
|
||||||
|
(0xF0F3, False), # bell (alarm)
|
||||||
|
(0xF6A9, False), # volume mute
|
||||||
|
(0xF519, False), # broadcast tower (auto-advert)
|
||||||
|
(0xF4D7, False), # route (trail)
|
||||||
|
(0xF3C5, False), # map marker (live share)
|
||||||
|
(0xF079, True), # retweet (repeater)
|
||||||
|
(0xF024, False), # flag (arrival alert)
|
||||||
|
(0xF0E7, None), # bolt (charging): a tight cell, it leads the battery
|
||||||
|
(0xF1EB, True), # wifi
|
||||||
|
(0xF240, True), (0xF241, True), (0xF242, True), (0xF243, True), (0xF244, True), # battery
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main(src, out):
|
||||||
|
fa = TTFont(src)
|
||||||
|
gs = fa.getGlyphSet()
|
||||||
|
cmap = fa.getBestCmap()
|
||||||
|
|
||||||
|
order = [".notdef"]
|
||||||
|
glyphs, metrics, cmap_out = {}, {}, {}
|
||||||
|
pen = TTGlyphPen(None)
|
||||||
|
glyphs[".notdef"] = pen.glyph()
|
||||||
|
metrics[".notdef"] = (int(ADVANCE * PX), 0)
|
||||||
|
|
||||||
|
for cp, wide in ICONS:
|
||||||
|
name = cmap[cp]
|
||||||
|
rec = DecomposingRecordingPen(gs)
|
||||||
|
gs[name].draw(rec)
|
||||||
|
bp = BoundsPen(gs)
|
||||||
|
rec.replay(bp)
|
||||||
|
x0, y0, x1, y1 = bp.bounds
|
||||||
|
w, h = x1 - x0, y1 - y0
|
||||||
|
s = min(BOX_H * PX / h, (WIDE_W if wide else BOX_W) * PX / w)
|
||||||
|
adv = math.ceil(w * s / PX) + 2 # 1 px clear each side
|
||||||
|
if wide is not None: adv = max(ADVANCE, adv) # one cell for all; wide icons a wider one
|
||||||
|
dx = (adv * PX - w * s) / 2 - x0 * s
|
||||||
|
dy = MID_Y * PX - (y0 + h / 2) * s
|
||||||
|
pen = TTGlyphPen(None)
|
||||||
|
rec.replay(TransformPen(pen, (s, 0, 0, s, dx, dy)))
|
||||||
|
g = pen.glyph()
|
||||||
|
g.recalcBounds(None)
|
||||||
|
glyphs[name] = g
|
||||||
|
metrics[name] = (int(adv * PX), g.xMin) # left side bearing = xMin, or the centring is lost
|
||||||
|
order.append(name)
|
||||||
|
cmap_out[cp] = name
|
||||||
|
|
||||||
|
fb = FontBuilder(UPM, isTTF=True)
|
||||||
|
fb.setupGlyphOrder(order)
|
||||||
|
fb.setupCharacterMap(cmap_out)
|
||||||
|
fb.setupGlyf(glyphs)
|
||||||
|
fb.setupHorizontalMetrics(metrics)
|
||||||
|
asc, desc = round(ASCENT * PX), round(DESCENT * PX)
|
||||||
|
fb.setupHorizontalHeader(ascent=asc, descent=-desc)
|
||||||
|
fb.setupOS2(sTypoAscender=asc, sTypoDescender=-desc, sTypoLineGap=0,
|
||||||
|
usWinAscent=asc, usWinDescent=desc)
|
||||||
|
fb.setupNameTable({"familyName": "UiIcons", "styleName": "Regular"})
|
||||||
|
fb.setupPost()
|
||||||
|
fb.save(out)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[1], sys.argv[2])
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Size: 14 px
|
||||||
|
* Bpp: 4
|
||||||
|
* Opts: --bpp 4 --size 14 --no-compress --font icons.ttf -r 0xF024,0xF079,0xF0E7,0xF0F3,0xF124,0xF1EB,0xF240-0xF244,0xF293,0xF3C5,0xF4D7,0xF519,0xF6A9 --format lvgl --lv-include lvgl.h --lv-font-name ui_icons_14 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_icons_14.c
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
|
#include "lvgl.h"
|
||||||
|
#else
|
||||||
|
#include "lvgl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UI_ICONS_14
|
||||||
|
#define UI_ICONS_14 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UI_ICONS_14
|
||||||
|
|
||||||
|
/*-----------------
|
||||||
|
* BITMAPS
|
||||||
|
*----------------*/
|
||||||
|
|
||||||
|
/*Store the image of the glyphs*/
|
||||||
|
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||||
|
/* U+F024 "" */
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xa0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x5f, 0xf8, 0x97, 0x20,
|
||||||
|
0x3, 0x82, 0xe, 0xff, 0xff, 0xfe, 0xff, 0xf5,
|
||||||
|
0xe, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xe, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf6, 0xe, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xf6, 0xe, 0xff, 0xff, 0xff, 0xff, 0xf6,
|
||||||
|
0xe, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xe, 0xa2,
|
||||||
|
0x1, 0x59, 0xb8, 0x20, 0xe, 0x70, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0xd, 0x50, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
|
||||||
|
/* U+F079 "" */
|
||||||
|
0x0, 0x5, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x5, 0xff, 0xb0, 0x1c, 0xcc, 0xcc,
|
||||||
|
0xcc, 0x50, 0x0, 0x5, 0xff, 0xff, 0xb1, 0xcf,
|
||||||
|
0xff, 0xff, 0xf9, 0x0, 0x0, 0xfe, 0xcf, 0xbf,
|
||||||
|
0x70, 0x0, 0x0, 0x1f, 0x90, 0x0, 0x5, 0x2a,
|
||||||
|
0xf1, 0x61, 0x0, 0x0, 0x1, 0xf9, 0x0, 0x0,
|
||||||
|
0x0, 0xaf, 0x10, 0x0, 0x0, 0x0, 0x1f, 0x90,
|
||||||
|
0x0, 0x0, 0xa, 0xf1, 0x0, 0x0, 0x1, 0x61,
|
||||||
|
0xf9, 0x35, 0x0, 0x0, 0xaf, 0x10, 0x0, 0x0,
|
||||||
|
0x7f, 0xbf, 0xce, 0xf0, 0x0, 0xa, 0xff, 0xff,
|
||||||
|
0xff, 0xb1, 0xbf, 0xff, 0xf4, 0x0, 0x0, 0x5c,
|
||||||
|
0xcc, 0xcc, 0xcb, 0x10, 0xbf, 0xf4, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x94, 0x0,
|
||||||
|
0x0,
|
||||||
|
|
||||||
|
/* U+F0E7 "" */
|
||||||
|
0x3f, 0xff, 0xc0, 0x0, 0x6f, 0xff, 0x90, 0x0,
|
||||||
|
0x8f, 0xff, 0x40, 0x0, 0xaf, 0xff, 0x99, 0x70,
|
||||||
|
0xcf, 0xff, 0xff, 0xb0, 0xef, 0xff, 0xff, 0x20,
|
||||||
|
0x23, 0x3f, 0xf8, 0x0, 0x0, 0x3f, 0xe0, 0x0,
|
||||||
|
0x0, 0x6f, 0x60, 0x0, 0x0, 0xac, 0x0, 0x0,
|
||||||
|
0x0, 0xc3, 0x0, 0x0,
|
||||||
|
|
||||||
|
/* U+F0F3 "" */
|
||||||
|
0x0, 0x0, 0x88, 0x0, 0x0, 0x0, 0x8, 0xff,
|
||||||
|
0x90, 0x0, 0x0, 0xcf, 0xff, 0xfc, 0x0, 0x4,
|
||||||
|
0xff, 0xff, 0xff, 0x40, 0x7, 0xff, 0xff, 0xff,
|
||||||
|
0x70, 0x9, 0xff, 0xff, 0xff, 0x90, 0xc, 0xff,
|
||||||
|
0xff, 0xff, 0xc0, 0x5f, 0xff, 0xff, 0xff, 0xf6,
|
||||||
|
0xaf, 0xff, 0xff, 0xff, 0xf9, 0x0, 0x1, 0x66,
|
||||||
|
0x20, 0x0, 0x0, 0x1, 0xdd, 0x10, 0x0,
|
||||||
|
|
||||||
|
/* U+F124 "" */
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x3a, 0xe3, 0x0, 0x0, 0x0, 0x4b,
|
||||||
|
0xff, 0xf5, 0x0, 0x0, 0x5d, 0xff, 0xff, 0xe0,
|
||||||
|
0x0, 0x7e, 0xff, 0xff, 0xff, 0x70, 0x3e, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x0, 0x6f, 0xff, 0xff, 0xff,
|
||||||
|
0xf8, 0x0, 0x2, 0x33, 0x3b, 0xff, 0xf1, 0x0,
|
||||||
|
0x0, 0x0, 0xb, 0xff, 0xa0, 0x0, 0x0, 0x0,
|
||||||
|
0xb, 0xff, 0x20, 0x0, 0x0, 0x0, 0xa, 0xfb,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x6, 0xe3, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
|
||||||
|
/* U+F1EB "" */
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x1, 0x6b, 0xdf, 0xfd, 0xb6, 0x10, 0x0,
|
||||||
|
0x0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0,
|
||||||
|
0x3e, 0xff, 0xa5, 0x10, 0x1, 0x5a, 0xff, 0xe3,
|
||||||
|
0xaf, 0xc2, 0x0, 0x0, 0x0, 0x0, 0x2c, 0xfa,
|
||||||
|
0x6, 0x0, 0x3a, 0xef, 0xfe, 0xa3, 0x0, 0x60,
|
||||||
|
0x0, 0x8, 0xff, 0xfe, 0xef, 0xff, 0x80, 0x0,
|
||||||
|
0x0, 0xc, 0xf8, 0x10, 0x1, 0x8f, 0xc0, 0x0,
|
||||||
|
0x0, 0x0, 0x20, 0x0, 0x0, 0x2, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x3f, 0xf3, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x8f, 0xf8, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x2d, 0xd2, 0x0, 0x0, 0x0,
|
||||||
|
|
||||||
|
/* U+F240 "" */
|
||||||
|
0x6b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb7,
|
||||||
|
0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf2, 0xfb, 0x13, 0x33, 0x33, 0x33, 0x33, 0x31,
|
||||||
|
0x8f, 0xef, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x95, 0xef, 0xfb, 0x7f, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf9, 0xb, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0x95, 0xef, 0xfb, 0x13, 0x33, 0x33, 0x33,
|
||||||
|
0x33, 0x31, 0x8f, 0xef, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf2, 0x6b, 0xcc, 0xcc, 0xcc,
|
||||||
|
0xcc, 0xcc, 0xcc, 0xb8, 0x0,
|
||||||
|
|
||||||
|
/* U+F241 "" */
|
||||||
|
0x6b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb7,
|
||||||
|
0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf2, 0xfb, 0x13, 0x33, 0x33, 0x33, 0x30, 0x0,
|
||||||
|
0x8f, 0xef, 0xb7, 0xff, 0xff, 0xff, 0xff, 0x0,
|
||||||
|
0x5, 0xef, 0xfb, 0x7f, 0xff, 0xff, 0xff, 0xf0,
|
||||||
|
0x0, 0xb, 0xff, 0xb7, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x0, 0x5, 0xef, 0xfb, 0x13, 0x33, 0x33, 0x33,
|
||||||
|
0x30, 0x0, 0x8f, 0xef, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf2, 0x6b, 0xcc, 0xcc, 0xcc,
|
||||||
|
0xcc, 0xcc, 0xcc, 0xb8, 0x0,
|
||||||
|
|
||||||
|
/* U+F242 "" */
|
||||||
|
0x6b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb7,
|
||||||
|
0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf2, 0xfb, 0x13, 0x33, 0x33, 0x10, 0x0, 0x0,
|
||||||
|
0x8f, 0xef, 0xb7, 0xff, 0xff, 0xf8, 0x0, 0x0,
|
||||||
|
0x5, 0xef, 0xfb, 0x7f, 0xff, 0xff, 0x80, 0x0,
|
||||||
|
0x0, 0xb, 0xff, 0xb7, 0xff, 0xff, 0xf8, 0x0,
|
||||||
|
0x0, 0x5, 0xef, 0xfb, 0x13, 0x33, 0x33, 0x10,
|
||||||
|
0x0, 0x0, 0x8f, 0xef, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf2, 0x6b, 0xcc, 0xcc, 0xcc,
|
||||||
|
0xcc, 0xcc, 0xcc, 0xb8, 0x0,
|
||||||
|
|
||||||
|
/* U+F243 "" */
|
||||||
|
0x6b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb7,
|
||||||
|
0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf2, 0xfb, 0x13, 0x32, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x8f, 0xef, 0xb7, 0xff, 0xf0, 0x0, 0x0, 0x0,
|
||||||
|
0x5, 0xef, 0xfb, 0x7f, 0xff, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0xb, 0xff, 0xb7, 0xff, 0xf0, 0x0, 0x0,
|
||||||
|
0x0, 0x5, 0xef, 0xfb, 0x13, 0x32, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x8f, 0xef, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf2, 0x6b, 0xcc, 0xcc, 0xcc,
|
||||||
|
0xcc, 0xcc, 0xcc, 0xb8, 0x0,
|
||||||
|
|
||||||
|
/* U+F244 "" */
|
||||||
|
0x6b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb7,
|
||||||
|
0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xf2, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x8f, 0xef, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x5, 0xef, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0xb, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x5, 0xef, 0xfb, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x8f, 0xef, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xf2, 0x6b, 0xcc, 0xcc, 0xcc,
|
||||||
|
0xcc, 0xcc, 0xcc, 0xb8, 0x0,
|
||||||
|
|
||||||
|
/* U+F293 "" */
|
||||||
|
0x0, 0x3b, 0xef, 0xc5, 0x0, 0x2, 0xff, 0xc8,
|
||||||
|
0xff, 0x40, 0xa, 0xff, 0xc0, 0x9f, 0xc0, 0xe,
|
||||||
|
0xd5, 0xc6, 0x4c, 0xf0, 0xf, 0xf8, 0x22, 0x4f,
|
||||||
|
0xf1, 0x1f, 0xff, 0x50, 0xef, 0xf2, 0xf, 0xfa,
|
||||||
|
0x11, 0x5f, 0xf1, 0xe, 0xd3, 0xb6, 0x4a, 0xf0,
|
||||||
|
0xa, 0xff, 0xc1, 0x7f, 0xc0, 0x3, 0xff, 0xd7,
|
||||||
|
0xff, 0x50, 0x0, 0x3b, 0xef, 0xd6, 0x0,
|
||||||
|
|
||||||
|
/* U+F3C5 "" */
|
||||||
|
0x0, 0x2b, 0xff, 0xb2, 0x0, 0x3, 0xff, 0xff,
|
||||||
|
0xff, 0x30, 0xc, 0xff, 0x88, 0xff, 0xc0, 0x1f,
|
||||||
|
0xf7, 0x0, 0x7f, 0xf0, 0x1f, 0xf5, 0x0, 0x5f,
|
||||||
|
0xf1, 0xd, 0xfd, 0x44, 0xef, 0xd0, 0x5, 0xff,
|
||||||
|
0xff, 0xff, 0x50, 0x0, 0xbf, 0xff, 0xfb, 0x0,
|
||||||
|
0x0, 0x1e, 0xff, 0xe1, 0x0, 0x0, 0x5, 0xff,
|
||||||
|
0x50, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
|
||||||
|
|
||||||
|
/* U+F4D7 "" */
|
||||||
|
0x0, 0x0, 0x0, 0x1, 0xbf, 0xa0, 0x0, 0x0,
|
||||||
|
0x0, 0x7, 0xf7, 0xf6, 0x0, 0x0, 0x0, 0x7,
|
||||||
|
0xe6, 0xf6, 0x0, 0x0, 0x0, 0x1, 0xef, 0xd0,
|
||||||
|
0x0, 0x0, 0x1, 0xbf, 0xff, 0x30, 0x3, 0x84,
|
||||||
|
0x8, 0xe7, 0x64, 0x0, 0x3f, 0xff, 0x4a, 0xd2,
|
||||||
|
0x21, 0x0, 0x7f, 0xd, 0x83, 0xff, 0xff, 0xc0,
|
||||||
|
0x2f, 0xdf, 0x40, 0x13, 0x45, 0xf6, 0x9, 0xfb,
|
||||||
|
0x46, 0x66, 0x67, 0xf5, 0x0, 0xb4, 0xff, 0xff,
|
||||||
|
0xff, 0xa0,
|
||||||
|
|
||||||
|
/* U+F519 "" */
|
||||||
|
0xd, 0x30, 0x0, 0x0, 0x0, 0x3, 0xd0, 0x5f,
|
||||||
|
0x4, 0x30, 0x33, 0x3, 0x40, 0xf5, 0x7d, 0xd,
|
||||||
|
0x71, 0xff, 0x37, 0xd0, 0xd7, 0x6e, 0xc, 0x81,
|
||||||
|
0xff, 0x38, 0xc0, 0xe6, 0x2f, 0x20, 0x6, 0xfe,
|
||||||
|
0x70, 0x2, 0xf2, 0x4, 0x10, 0xc, 0x97, 0xe0,
|
||||||
|
0x1, 0x40, 0x0, 0x0, 0x3f, 0x64, 0xf5, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0xaf, 0xff, 0xfb, 0x0, 0x0,
|
||||||
|
0x0, 0x1, 0xf6, 0x11, 0x4f, 0x20, 0x0, 0x0,
|
||||||
|
0x7, 0xe0, 0x0, 0xd, 0x80, 0x0, 0x0, 0x5,
|
||||||
|
0x60, 0x0, 0x5, 0x60, 0x0,
|
||||||
|
|
||||||
|
/* U+F6A9 "" */
|
||||||
|
0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0xbf, 0xf0, 0x0, 0x0, 0x0, 0x5e, 0xef, 0xff,
|
||||||
|
0xf0, 0x1c, 0x32, 0xc2, 0x8f, 0xff, 0xff, 0xf0,
|
||||||
|
0x2e, 0xfe, 0xf3, 0x8f, 0xff, 0xff, 0xf0, 0x5,
|
||||||
|
0xff, 0x70, 0x8f, 0xff, 0xff, 0xf0, 0x2e, 0xfe,
|
||||||
|
0xf3, 0x5f, 0xff, 0xff, 0xf0, 0x1c, 0x43, 0xd2,
|
||||||
|
0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x40, 0x0, 0x0, 0x0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* 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 = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 72, .adv_w = 304, .box_w = 19, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 177, .adv_w = 144, .box_w = 8, .box_h = 11, .ofs_x = 1, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 221, .adv_w = 256, .box_w = 10, .box_h = 11, .ofs_x = 3, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 276, .adv_w = 256, .box_w = 12, .box_h = 13, .ofs_x = 2, .ofs_y = -2},
|
||||||
|
{.bitmap_index = 354, .adv_w = 288, .box_w = 16, .box_h = 12, .ofs_x = 1, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 450, .adv_w = 304, .box_w = 17, .box_h = 9, .ofs_x = 1, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 527, .adv_w = 304, .box_w = 17, .box_h = 9, .ofs_x = 1, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 604, .adv_w = 304, .box_w = 17, .box_h = 9, .ofs_x = 1, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 681, .adv_w = 304, .box_w = 17, .box_h = 9, .ofs_x = 1, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 758, .adv_w = 304, .box_w = 17, .box_h = 9, .ofs_x = 1, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 835, .adv_w = 256, .box_w = 10, .box_h = 11, .ofs_x = 3, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 890, .adv_w = 256, .box_w = 10, .box_h = 11, .ofs_x = 3, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 945, .adv_w = 256, .box_w = 12, .box_h = 11, .ofs_x = 2, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 1011, .adv_w = 256, .box_w = 14, .box_h = 11, .ofs_x = 1, .ofs_y = -1},
|
||||||
|
{.bitmap_index = 1088, .adv_w = 256, .box_w = 14, .box_h = 11, .ofs_x = 1, .ofs_y = -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* CHARACTER MAPPING
|
||||||
|
*--------------------*/
|
||||||
|
|
||||||
|
static const uint16_t unicode_list_0[] = {
|
||||||
|
0x0, 0x55, 0xc3, 0xcf, 0x100, 0x1c7, 0x21c, 0x21d,
|
||||||
|
0x21e, 0x21f, 0x220, 0x26f, 0x3a1, 0x4b3, 0x4f5, 0x685
|
||||||
|
};
|
||||||
|
|
||||||
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
|
static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.range_start = 61476, .range_length = 1670, .glyph_id_start = 1,
|
||||||
|
.unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 16, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_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 = 1,
|
||||||
|
.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_icons_14 = {
|
||||||
|
#else
|
||||||
|
lv_font_t ui_icons_14 = {
|
||||||
|
#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 = 18, /*The maximum line height required by the font*/
|
||||||
|
.base_line = 4, /*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 = 0,
|
||||||
|
.underline_thickness = 0,
|
||||||
|
#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 = &ui_font_12,
|
||||||
|
#endif
|
||||||
|
.user_data = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*#if UI_ICONS_14*/
|
||||||
|
|
||||||
@@ -31,7 +31,8 @@
|
|||||||
#define LV_FONT_MONTSERRAT_14 0
|
#define LV_FONT_MONTSERRAT_14 0
|
||||||
#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(ui_font_12) LV_FONT_DECLARE(ui_font_14) \
|
#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_16) LV_FONT_DECLARE(ui_font_20) \
|
||||||
LV_FONT_DECLARE(ui_font_40)
|
LV_FONT_DECLARE(ui_font_40) \
|
||||||
|
LV_FONT_DECLARE(ui_icons_14)
|
||||||
#define LV_FONT_DEFAULT &ui_font_14
|
#define LV_FONT_DEFAULT &ui_font_14
|
||||||
#define LV_USE_FONT_COMPRESSED 0 // fonts are generated uncompressed: no per-glyph decompression on every draw
|
#define LV_USE_FONT_COMPRESSED 0 // fonts are generated uncompressed: no per-glyph decompression on every draw
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user