mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 03:06:39 +00:00
feat(ui-lvgl): offline raster map from the microSD
Map screen (Home > Map): Web-Mercator tiles from /maps/{z}/{x}/{y}.png on
the card (Meshtastic MUI layout; per-column TPK1 .pak also read), drag to
pan, +/- zoom, re-centre/follow GPS, Nearby nodes with a position as
markers opening node detail. Tiles decode one per loop pass into a
12-slot RGB565 cache in PSRAM. map/TileProvider.h is the swap point for a
later vector renderer: the screen only calls renderTile(). The tile set's
credit line comes from maps/attribution.txt.
L2 mounts the card over SDMMC 1-bit (CLK 2, CMD 3, D0 1). LVGL's lodepng
is enabled; note its LVGL patch returns an lv_draw_buf_t*, not pixels.
LVGL pool 2 MB for PNG decoding. Fonts gain map / users icons.
tools/maps/fetch_tiles.py prepares a card for an area (presets for
Poland), requires an explicit tile URL (tile.openstreetmap.org blocks
offline use) and stops on placeholder images. The LVGL sim preloads
web/maps into the L2's /sdcard and puts its GPS on Kraków.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ tools/gpx/
|
|||||||
sim_data/
|
sim_data/
|
||||||
variants/sim/tools/emsdk/
|
variants/sim/tools/emsdk/
|
||||||
variants/sim/web/build/
|
variants/sim/web/build/
|
||||||
|
variants/sim/web/maps/
|
||||||
|
|
||||||
# graphify
|
# graphify
|
||||||
graphify-out/
|
graphify-out/
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ consumes keys only.
|
|||||||
- Theme tokens (colours, spacing, typography) in one place — the first chance to realise the "Amber Trace" direction in colour.
|
- Theme tokens (colours, spacing, typography) in one place — the first chance to realise the "Amber Trace" direction in colour.
|
||||||
- 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`.
|
- 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`.
|
||||||
- Simulator ✅: `SIM_UI=lvgl variants/sim/build_wasm.sh` builds the same `ui-lvgl` code for the browser (`SimLcdDisplay` in `variants/sim/SimDisplayDriver.h` blits LVGL's RGB565 flush to a 320×240 canvas; the `SIM_PLATFORM` branch of `ui-lvgl/LvglPort.h` feeds the mouse in as touch). LVGL comes from the L2 env's PlatformIO libdeps; its objects are cached in `web/build/obj_lvgl/`. `web/lvgl.html` runs it next to a `ui-new` peer on a direct link (buttons: advert, peer DM, peer → Public, the board button) and exposes `window.sim` (`tap`, `hold`, `touch`, `peerDM`, `peerChannel`) for headless checks.
|
- Simulator ✅: `SIM_UI=lvgl variants/sim/build_wasm.sh` builds the same `ui-lvgl` code for the browser (`SimLcdDisplay` in `variants/sim/SimDisplayDriver.h` blits LVGL's RGB565 flush to a 320×240 canvas; the `SIM_PLATFORM` branch of `ui-lvgl/LvglPort.h` feeds the mouse in as touch). LVGL comes from the L2 env's PlatformIO libdeps; its objects are cached in `web/build/obj_lvgl/`. `web/lvgl.html` runs it next to a `ui-new` peer on a direct link (buttons: advert, peer DM, peer → Public, the board button) and exposes `window.sim` (`tap`, `hold`, `touch`, `peerDM`, `peerChannel`) for headless checks.
|
||||||
|
- Map (in progress): offline Web-Mercator raster tiles on the microSD (`/maps/{z}/{x}/{y}.png`, the Meshtastic MUI layout; optional per-column `.pak` from PR #3381's packer), SDMMC 1-bit mount in `LvglPort.h`. `ui-lvgl/map/TileProvider.h` is the swap point: the screen and `map/TileCache.h` (12 decoded RGB565 tiles in PSRAM, LRU) only call `renderTile(z, x, y, rgb565)`, so a vector renderer can replace the PNG provider later. `MapScreen.h`: pan by drag, +/-, re-centre/follow GPS, Nearby nodes with a position as markers (tap = node detail), one tile decoded per loop pass. `maps/attribution.txt` is shown on the map. Planned split (user, 2026-09-25): a Nodes map (every contact with a position) and a separate Navigation map (waypoints + live shares only, for walking to a target). Tiles come from `tools/maps/fetch_tiles.py` (no default server: tile.openstreetmap.org blocks offline use) or, next, an on-device WiFi download of the visible area.
|
||||||
- PR #3381's LVGL UI is a reference for platform glue (flush, GT911, PSRAM pool) only; its screens are not adopted.
|
- PR #3381's LVGL UI is a reference for platform glue (flush, GT911, PSRAM pool) only; its screens are not adopted.
|
||||||
|
|
||||||
## Migration plan
|
## Migration plan
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
// LVGL <-> board glue: display flush and pointer input. One implementation per
|
// LVGL <-> board glue: display flush, pointer input and the storage card (map
|
||||||
// display stack; the rest of ui-lvgl never touches the hardware directly.
|
// tiles, mounted at /sdcard). One implementation per board; the rest of
|
||||||
|
// ui-lvgl never touches the hardware directly.
|
||||||
//
|
//
|
||||||
// Single-TU fragment: included by ui-lvgl/UITask.cpp only.
|
// Single-TU fragment: included by ui-lvgl/UITask.cpp only.
|
||||||
|
|
||||||
|
#if defined(SEEED_WIO_TRACKER_L2)
|
||||||
|
#include <SD_MMC.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace lvport {
|
namespace lvport {
|
||||||
|
|
||||||
#if defined(SEEED_WIO_TRACKER_L2)
|
#if defined(SEEED_WIO_TRACKER_L2)
|
||||||
@@ -69,6 +74,17 @@ static bool touched() {
|
|||||||
|
|
||||||
static void swallowTouch() { s_swallow = true; }
|
static void swallowTouch() { s_swallow = true; }
|
||||||
|
|
||||||
|
// microSD over SDMMC, 1-bit (CLK 2, CMD 3, D0 1); its power rail (expander
|
||||||
|
// P14) is switched on in WioTrackerL2Board::begin(). Retried on every call
|
||||||
|
// until it works, so a card inserted later is picked up the next time.
|
||||||
|
static bool mountStorage() {
|
||||||
|
static bool mounted = false;
|
||||||
|
if (mounted) return true;
|
||||||
|
SD_MMC.setPins(2, 3, 1);
|
||||||
|
mounted = SD_MMC.begin("/sdcard", true /* 1-bit */);
|
||||||
|
return mounted;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(SIM_PLATFORM) && defined(__EMSCRIPTEN__)
|
#elif defined(SIM_PLATFORM) && defined(__EMSCRIPTEN__)
|
||||||
// Browser simulator (variants/sim/build_wasm_lvgl.sh): SimLcdDisplay blits to
|
// Browser simulator (variants/sim/build_wasm_lvgl.sh): SimLcdDisplay blits to
|
||||||
// a <canvas>, the host page feeds the mouse in as touch.
|
// a <canvas>, the host page feeds the mouse in as touch.
|
||||||
@@ -109,6 +125,9 @@ static bool begin() {
|
|||||||
static bool touched() { return SimLcdDisplay::touchState().down; }
|
static bool touched() { return SimLcdDisplay::touchState().down; }
|
||||||
static void swallowTouch() { s_swallow = true; }
|
static void swallowTouch() { s_swallow = true; }
|
||||||
|
|
||||||
|
// The host page preloads map tiles into the in-memory FS under /sdcard/maps.
|
||||||
|
static bool mountStorage() { return true; }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "ui-lvgl: no LVGL port for this board (see LvglPort.h)"
|
#error "ui-lvgl: no LVGL port for this board (see LvglPort.h)"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,332 @@
|
|||||||
|
#pragma once
|
||||||
|
// Map screen: offline Web-Mercator tiles from the card (map/TileProvider.h,
|
||||||
|
// cached by map/TileCache.h) under own position and the nodes Nearby knows a
|
||||||
|
// position for. Drag to pan, +/- to zoom, the crosshair re-centres and
|
||||||
|
// follows the GPS again; tap a marker for its node detail.
|
||||||
|
//
|
||||||
|
// Tiles decode one per loop pass (a PNG takes tens of ms), so panning stays
|
||||||
|
// responsive and the radio keeps being serviced while a view fills in.
|
||||||
|
//
|
||||||
|
// Single-TU fragment: included by ui-lvgl/UITask.cpp after the Nearby section.
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "map/TileProvider.h"
|
||||||
|
#include "map/TileCache.h"
|
||||||
|
|
||||||
|
namespace mapview {
|
||||||
|
|
||||||
|
static RasterTileProvider s_raster("/sdcard/maps");
|
||||||
|
static TileProvider* s_provider = &s_raster; // the one place to swap in a vector renderer
|
||||||
|
static TileCache s_cache;
|
||||||
|
|
||||||
|
static const int MIN_Z = 3, MAX_Z = 18;
|
||||||
|
static const int GRID_COLS = 3, GRID_ROWS = 2; // covers 320x218 at any offset
|
||||||
|
|
||||||
|
// Fallback centre with no GPS fix and no saved position: Poland.
|
||||||
|
static const double DEFAULT_LAT = 52.0, DEFAULT_LON = 19.4;
|
||||||
|
static const int DEFAULT_Z = 6;
|
||||||
|
|
||||||
|
static double lonToTileX(double lon, int z) { return (lon + 180.0) / 360.0 * (double)(1 << z); }
|
||||||
|
static double latToTileY(double lat, int z) {
|
||||||
|
double r = lat * M_PI / 180.0;
|
||||||
|
return (1.0 - asinh(tan(r)) / M_PI) / 2.0 * (double)(1 << z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markers: one per positioned Nearby row, remembered so layout can reposition them.
|
||||||
|
struct Mark { int32_t lat_e6, lon_e6; int row; lv_obj_t* obj; };
|
||||||
|
static Mark s_marks[NearbyModel::MAX_NEARBY];
|
||||||
|
static int s_mark_count = 0;
|
||||||
|
static int s_drag = 0; // px moved in the current press: a drag isn't a tap
|
||||||
|
static bool s_available = false; // provider has data; checked when the map opens, not per frame
|
||||||
|
|
||||||
|
} // namespace mapview
|
||||||
|
|
||||||
|
static void onMapPress(lv_event_t* e) {
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
if (code == LV_EVENT_PRESSED) { mapview::s_drag = 0; return; }
|
||||||
|
lv_point_t v;
|
||||||
|
lv_indev_get_vect(lv_indev_active(), &v);
|
||||||
|
if (v.x == 0 && v.y == 0) return;
|
||||||
|
mapview::s_drag += abs(v.x) + abs(v.y);
|
||||||
|
s_ui->mapPan(v.x, v.y);
|
||||||
|
}
|
||||||
|
static void onMapZoomIn(lv_event_t* e) { (void)e; s_ui->mapZoom(+1); }
|
||||||
|
static void onMapZoomOut(lv_event_t* e) { (void)e; s_ui->mapZoom(-1); }
|
||||||
|
static void onMapCenter(lv_event_t* e) { (void)e; s_ui->mapCenterOnMe(); }
|
||||||
|
static void onMapMarker(lv_event_t* e) {
|
||||||
|
if (mapview::s_drag > 8) return; // the press was a pan that ended on a marker
|
||||||
|
s_ui->mapOpenMarker((int)(uintptr_t)lv_event_get_user_data(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_obj_t* mapButton(lv_obj_t* parent, const char* text, lv_event_cb_t cb) {
|
||||||
|
lv_obj_t* b = lv_button_create(parent);
|
||||||
|
lv_obj_set_size(b, 40, 40);
|
||||||
|
lv_obj_set_style_radius(b, theme::RADIUS, 0);
|
||||||
|
lv_obj_set_style_shadow_width(b, 0, 0);
|
||||||
|
lv_obj_set_style_bg_color(b, lv_color_hex(theme::BG), 0);
|
||||||
|
lv_obj_set_style_bg_opa(b, LV_OPA_80, 0);
|
||||||
|
lv_obj_set_style_bg_color(b, lv_color_hex(theme::SURFACE_2), LV_STATE_PRESSED);
|
||||||
|
lv_obj_set_style_border_color(b, lv_color_hex(theme::SURFACE_2), 0);
|
||||||
|
lv_obj_set_style_border_width(b, 1, 0);
|
||||||
|
lv_obj_add_event_cb(b, cb, LV_EVENT_CLICKED, NULL);
|
||||||
|
lv_obj_center(label(b, text, THEME_FONT_TITLE, theme::TEXT));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_obj_t* mapPill(lv_obj_t* parent, const char* text) {
|
||||||
|
lv_obj_t* l = label(parent, text, THEME_FONT_SMALL, theme::TEXT);
|
||||||
|
lv_obj_set_style_bg_color(l, lv_color_hex(theme::BG), 0);
|
||||||
|
lv_obj_set_style_bg_opa(l, LV_OPA_70, 0);
|
||||||
|
lv_obj_set_style_pad_hor(l, 5, 0);
|
||||||
|
lv_obj_set_style_pad_ver(l, 1, 0);
|
||||||
|
lv_obj_set_style_radius(l, 4, 0);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::showMap() {
|
||||||
|
_screen = SCR_MAP;
|
||||||
|
mapview::s_available = lvport::mountStorage() && mapview::s_provider->available();
|
||||||
|
if (_map_z == 0) { // first open: own position, else the node's own advert position, else Poland
|
||||||
|
int32_t lat, lon;
|
||||||
|
double la = mapview::DEFAULT_LAT, lo = mapview::DEFAULT_LON;
|
||||||
|
int z = mapview::DEFAULT_Z;
|
||||||
|
if (_core->course.currentLocation(lat, lon)) { la = lat / 1e6; lo = lon / 1e6; z = 15; }
|
||||||
|
else if (_sensors && (_sensors->node_lat != 0 || _sensors->node_lon != 0)) { // saved / app-set position
|
||||||
|
la = _sensors->node_lat; lo = _sensors->node_lon; z = 13;
|
||||||
|
}
|
||||||
|
_map_z = z;
|
||||||
|
_map_cx = mapview::lonToTileX(lo, z);
|
||||||
|
_map_cy = mapview::latToTileY(la, z);
|
||||||
|
}
|
||||||
|
buildMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::buildMap() {
|
||||||
|
lv_obj_t* body = newScreen(NULL, false);
|
||||||
|
lv_obj_set_layout(body, LV_LAYOUT_NONE);
|
||||||
|
lv_obj_set_style_pad_all(body, 0, 0);
|
||||||
|
lv_obj_remove_flag(body, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
lv_obj_set_style_bg_color(body, lv_color_hex(0x1A1A1E), 0); // unloaded / missing tiles
|
||||||
|
lv_obj_add_flag(body, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_add_event_cb(body, onMapPress, LV_EVENT_PRESSED, NULL);
|
||||||
|
lv_obj_add_event_cb(body, onMapPress, LV_EVENT_PRESSING, NULL);
|
||||||
|
_map_area = body;
|
||||||
|
|
||||||
|
for (int i = 0; i < mapview::GRID_COLS * mapview::GRID_ROWS; i++) {
|
||||||
|
_map_tiles[i] = lv_image_create(body);
|
||||||
|
lv_obj_add_flag(_map_tiles[i], LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marker layer: same size as the map, lets presses through to it.
|
||||||
|
_map_marks = lv_obj_create(body);
|
||||||
|
lv_obj_remove_style_all(_map_marks);
|
||||||
|
lv_obj_set_size(_map_marks, LV_PCT(100), LV_PCT(100));
|
||||||
|
lv_obj_remove_flag(_map_marks, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_remove_flag(_map_marks, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
lv_obj_add_flag(_map_marks, LV_OBJ_FLAG_EVENT_BUBBLE);
|
||||||
|
|
||||||
|
_map_me = lv_obj_create(_map_marks);
|
||||||
|
lv_obj_remove_style_all(_map_me);
|
||||||
|
lv_obj_set_size(_map_me, 16, 16);
|
||||||
|
lv_obj_set_style_radius(_map_me, LV_RADIUS_CIRCLE, 0);
|
||||||
|
lv_obj_set_style_bg_color(_map_me, lv_color_hex(theme::ACCENT), 0);
|
||||||
|
lv_obj_set_style_bg_opa(_map_me, LV_OPA_COVER, 0);
|
||||||
|
lv_obj_set_style_border_color(_map_me, lv_color_hex(theme::BG), 0);
|
||||||
|
lv_obj_set_style_border_width(_map_me, 3, 0);
|
||||||
|
lv_obj_remove_flag(_map_me, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_add_flag(_map_me, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
lv_obj_t* back = mapButton(body, LV_SYMBOL_LEFT, onBack);
|
||||||
|
lv_obj_align(back, LV_ALIGN_TOP_LEFT, 6, 6);
|
||||||
|
lv_obj_align(mapButton(body, LV_SYMBOL_PLUS, onMapZoomIn), LV_ALIGN_TOP_RIGHT, -6, 6);
|
||||||
|
lv_obj_align(mapButton(body, LV_SYMBOL_MINUS, onMapZoomOut), LV_ALIGN_TOP_RIGHT, -6, 52);
|
||||||
|
lv_obj_align(mapButton(body, LV_SYMBOL_GPS, onMapCenter), LV_ALIGN_BOTTOM_RIGHT, -6, -6);
|
||||||
|
_map_zoom_lbl = mapPill(body, "");
|
||||||
|
lv_obj_align(_map_zoom_lbl, LV_ALIGN_TOP_LEFT, 52, 16);
|
||||||
|
lv_obj_t* attr = mapPill(body, mapview::s_provider->attribution()); // required by the data licences
|
||||||
|
lv_label_set_long_mode(attr, LV_LABEL_LONG_WRAP);
|
||||||
|
lv_obj_set_style_max_width(attr, 250, 0);
|
||||||
|
lv_obj_set_width(attr, LV_SIZE_CONTENT);
|
||||||
|
lv_obj_align(attr, LV_ALIGN_BOTTOM_LEFT, 6, -6);
|
||||||
|
_map_hint = mapPill(body, "");
|
||||||
|
lv_label_set_long_mode(_map_hint, LV_LABEL_LONG_WRAP);
|
||||||
|
lv_obj_set_width(_map_hint, 200);
|
||||||
|
lv_obj_set_style_text_align(_map_hint, LV_TEXT_ALIGN_CENTER, 0);
|
||||||
|
lv_obj_center(_map_hint);
|
||||||
|
lv_obj_add_flag(_map_hint, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
lv_obj_update_layout(body);
|
||||||
|
mapview::s_mark_count = 0; // the previous markers went with the previous screen
|
||||||
|
rebuildMapMarkers();
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Places tiles and markers for the current centre / zoom; queues tiles that
|
||||||
|
// aren't decoded yet for mapLoop().
|
||||||
|
void UITask::layoutMap() {
|
||||||
|
if (!_map_area) return;
|
||||||
|
int w = lv_obj_get_width(_map_area), h = lv_obj_get_height(_map_area);
|
||||||
|
double left = _map_cx * mapview::TILE_PX - w / 2.0; // world px of the view's top-left
|
||||||
|
double top = _map_cy * mapview::TILE_PX - h / 2.0;
|
||||||
|
int tx0 = (int)floor(left / mapview::TILE_PX), ty0 = (int)floor(top / mapview::TILE_PX);
|
||||||
|
int n = 1 << _map_z;
|
||||||
|
bool have_provider = mapview::s_available;
|
||||||
|
int shown = 0, missing = 0;
|
||||||
|
_map_pending = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < mapview::GRID_ROWS; j++) {
|
||||||
|
for (int i = 0; i < mapview::GRID_COLS; i++) {
|
||||||
|
lv_obj_t* img = _map_tiles[j * mapview::GRID_COLS + i];
|
||||||
|
int tx = tx0 + i, ty = ty0 + j;
|
||||||
|
int px = (int)lround(tx * (double)mapview::TILE_PX - left);
|
||||||
|
int py = (int)lround(ty * (double)mapview::TILE_PX - top);
|
||||||
|
bool on_screen = px < w && py < h && px + mapview::TILE_PX > 0 && py + mapview::TILE_PX > 0;
|
||||||
|
mapview::TileCache::Slot* s = nullptr;
|
||||||
|
if (have_provider && on_screen && ty >= 0 && ty < n) {
|
||||||
|
s = mapview::s_cache.find(_map_z, ((tx % n) + n) % n, ty);
|
||||||
|
if (!s) _map_pending = true;
|
||||||
|
}
|
||||||
|
if (s && s->present) {
|
||||||
|
if (lv_image_get_src(img) != &s->dsc) lv_image_set_src(img, &s->dsc);
|
||||||
|
lv_obj_set_pos(img, px, py);
|
||||||
|
lv_obj_remove_flag(img, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
shown++;
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(img, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
if (s) missing++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Own position
|
||||||
|
int32_t lat, lon;
|
||||||
|
if (_core->course.currentLocation(lat, lon)) {
|
||||||
|
double x = mapview::lonToTileX(lon / 1e6, _map_z) * mapview::TILE_PX - left;
|
||||||
|
double y = mapview::latToTileY(lat / 1e6, _map_z) * mapview::TILE_PX - top;
|
||||||
|
lv_obj_set_pos(_map_me, (int)x - 8, (int)y - 8);
|
||||||
|
lv_obj_remove_flag(_map_me, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(_map_me, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
for (int k = 0; k < mapview::s_mark_count; k++) {
|
||||||
|
const mapview::Mark& m = mapview::s_marks[k];
|
||||||
|
double x = mapview::lonToTileX(m.lon_e6 / 1e6, _map_z) * mapview::TILE_PX - left;
|
||||||
|
double y = mapview::latToTileY(m.lat_e6 / 1e6, _map_z) * mapview::TILE_PX - top;
|
||||||
|
lv_obj_set_pos(m.obj, (int)x - 6, (int)y - 6); // the dot's centre on the spot; name to its right
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_label_set_text_fmt(_map_zoom_lbl, "z%d", _map_z);
|
||||||
|
const char* hint = !have_provider ? "No map on the SD card.\nPut tiles in /maps (tools/maps)."
|
||||||
|
: (!_map_pending && shown == 0 && missing > 0) ? "No tiles here at this zoom." : nullptr;
|
||||||
|
if (hint) { lv_label_set_text(_map_hint, hint); lv_obj_remove_flag(_map_hint, LV_OBJ_FLAG_HIDDEN); }
|
||||||
|
else lv_obj_add_flag(_map_hint, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// One tile decode per call, nearest to the centre first.
|
||||||
|
void UITask::mapLoop() {
|
||||||
|
if ((int32_t)(millis() - _next_map_marks_ms) >= 0) {
|
||||||
|
_next_map_marks_ms = millis() + 3000;
|
||||||
|
if (_map_follow) {
|
||||||
|
int32_t lat, lon;
|
||||||
|
if (_core->course.currentLocation(lat, lon)) {
|
||||||
|
_map_cx = mapview::lonToTileX(lon / 1e6, _map_z);
|
||||||
|
_map_cy = mapview::latToTileY(lat / 1e6, _map_z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rebuildMapMarkers();
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
if (!_map_pending || !_map_area) return;
|
||||||
|
int w = lv_obj_get_width(_map_area), h = lv_obj_get_height(_map_area);
|
||||||
|
double left = _map_cx * mapview::TILE_PX - w / 2.0, top = _map_cy * mapview::TILE_PX - h / 2.0;
|
||||||
|
int tx0 = (int)floor(left / mapview::TILE_PX), ty0 = (int)floor(top / mapview::TILE_PX);
|
||||||
|
int n = 1 << _map_z;
|
||||||
|
int best_x = 0, best_y = 0;
|
||||||
|
double best_d = 1e18;
|
||||||
|
for (int j = 0; j < mapview::GRID_ROWS; j++) {
|
||||||
|
for (int i = 0; i < mapview::GRID_COLS; i++) {
|
||||||
|
int tx = tx0 + i, ty = ty0 + j;
|
||||||
|
double px = tx * (double)mapview::TILE_PX - left, py = ty * (double)mapview::TILE_PX - top;
|
||||||
|
if (px >= w || py >= h || px + mapview::TILE_PX <= 0 || py + mapview::TILE_PX <= 0) continue;
|
||||||
|
if (ty < 0 || ty >= n) continue;
|
||||||
|
int wx = ((tx % n) + n) % n;
|
||||||
|
if (mapview::s_cache.find(_map_z, wx, ty)) continue;
|
||||||
|
double d = fabs(px + 128 - w / 2.0) + fabs(py + 128 - h / 2.0);
|
||||||
|
if (d < best_d) { best_d = d; best_x = wx; best_y = ty; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best_d < 1e18) mapview::s_cache.load(*mapview::s_provider, _map_z, best_x, best_y);
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::rebuildMapMarkers() {
|
||||||
|
if (!_map_marks) return;
|
||||||
|
for (int k = 0; k < mapview::s_mark_count; k++) lv_obj_delete(mapview::s_marks[k].obj);
|
||||||
|
mapview::s_mark_count = 0;
|
||||||
|
_nearby->refreshStored();
|
||||||
|
for (int i = 0; i < _nearby->count() && mapview::s_mark_count < NearbyModel::MAX_NEARBY; i++) {
|
||||||
|
const NearbyModel::Entry& e = _nearby->at(i);
|
||||||
|
if (e.lat_e6 == 0 && e.lon_e6 == 0) continue;
|
||||||
|
uint32_t col = e.is_live ? theme::OK : e.type == ADV_TYPE_CHAT ? theme::TEXT : theme::TEXT_MUTED;
|
||||||
|
|
||||||
|
// One clickable object per marker: a dot plus the name beside it.
|
||||||
|
lv_obj_t* m = lv_obj_create(_map_marks);
|
||||||
|
lv_obj_remove_style_all(m);
|
||||||
|
lv_obj_set_size(m, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_flex_flow(m, LV_FLEX_FLOW_ROW);
|
||||||
|
lv_obj_set_flex_align(m, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
lv_obj_set_style_pad_column(m, 3, 0);
|
||||||
|
lv_obj_add_flag(m, LV_OBJ_FLAG_EVENT_BUBBLE); // a drag starting here still pans
|
||||||
|
lv_obj_add_event_cb(m, onMapMarker, LV_EVENT_CLICKED, (void*)(uintptr_t)mapview::s_mark_count);
|
||||||
|
lv_obj_t* dot = lv_obj_create(m);
|
||||||
|
lv_obj_remove_style_all(dot);
|
||||||
|
lv_obj_set_size(dot, 12, 12);
|
||||||
|
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, 0);
|
||||||
|
lv_obj_set_style_bg_color(dot, lv_color_hex(col), 0);
|
||||||
|
lv_obj_set_style_bg_opa(dot, LV_OPA_COVER, 0);
|
||||||
|
lv_obj_set_style_border_color(dot, lv_color_hex(theme::BG), 0);
|
||||||
|
lv_obj_set_style_border_width(dot, 2, 0);
|
||||||
|
lv_obj_remove_flag(dot, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
lv_obj_t* name = mapPill(m, e.name[0] ? e.name : "?");
|
||||||
|
lv_obj_remove_flag(name, LV_OBJ_FLAG_CLICKABLE);
|
||||||
|
|
||||||
|
mapview::Mark& mk = mapview::s_marks[mapview::s_mark_count++];
|
||||||
|
mk.lat_e6 = e.lat_e6; mk.lon_e6 = e.lon_e6; mk.row = i; mk.obj = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::mapPan(int dx, int dy) {
|
||||||
|
_map_cx -= dx / (double)mapview::TILE_PX;
|
||||||
|
_map_cy -= dy / (double)mapview::TILE_PX;
|
||||||
|
double n = (double)(1 << _map_z);
|
||||||
|
if (_map_cy < 0) _map_cy = 0;
|
||||||
|
if (_map_cy > n) _map_cy = n;
|
||||||
|
_map_follow = false;
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::mapZoom(int delta) {
|
||||||
|
int z = _map_z + delta;
|
||||||
|
if (z < mapview::MIN_Z || z > mapview::MAX_Z) return;
|
||||||
|
double f = delta > 0 ? 2.0 : 0.5;
|
||||||
|
_map_cx *= f; _map_cy *= f;
|
||||||
|
_map_z = z;
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::mapCenterOnMe() {
|
||||||
|
int32_t lat, lon;
|
||||||
|
if (!_core->course.currentLocation(lat, lon)) { showToast("No GPS fix"); return; }
|
||||||
|
_map_follow = true;
|
||||||
|
_map_cx = mapview::lonToTileX(lon / 1e6, _map_z);
|
||||||
|
_map_cy = mapview::latToTileY(lat / 1e6, _map_z);
|
||||||
|
layoutMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITask::mapOpenMarker(int idx) {
|
||||||
|
if (idx < 0 || idx >= mapview::s_mark_count) return;
|
||||||
|
openNode(mapview::s_marks[idx].row);
|
||||||
|
_node_from_map = true;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -31,4 +31,6 @@ namespace theme {
|
|||||||
|
|
||||||
// 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
|
||||||
|
#define UI_SYMBOL_MAP "\xEF\x89\xB9" // U+F279
|
||||||
|
#define UI_SYMBOL_USERS "\xEF\x83\x80" // U+F0C0, Nearby
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ void UITask::loop() {
|
|||||||
refreshNode();
|
refreshNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_screen == SCR_MAP) mapLoop();
|
||||||
if (_screen == SCR_THREAD && (int32_t)(millis() - _next_thread_check_ms) >= 0) {
|
if (_screen == SCR_THREAD && (int32_t)(millis() - _next_thread_check_ms) >= 0) {
|
||||||
_next_thread_check_ms = millis() + 500;
|
_next_thread_check_ms = millis() + 500;
|
||||||
uint32_t sig = threadSignature();
|
uint32_t sig = threadSignature();
|
||||||
@@ -343,6 +344,8 @@ lv_obj_t* UITask::newScreen(const char* title, bool with_back) {
|
|||||||
_nearby_list = _nearby_status = _nearby_sort_lbl = _nearby_chips = nullptr;
|
_nearby_list = _nearby_status = _nearby_sort_lbl = _nearby_chips = nullptr;
|
||||||
_node_info = _node_ping = _node_delete_lbl = nullptr;
|
_node_info = _node_ping = _node_delete_lbl = nullptr;
|
||||||
_scan_overlay = _scan_list = _scan_status = nullptr; // the popup went with the old screen
|
_scan_overlay = _scan_list = _scan_status = nullptr; // the popup went with the old screen
|
||||||
|
_map_area = _map_marks = _map_me = _map_zoom_lbl = _map_hint = nullptr;
|
||||||
|
for (lv_obj_t*& t : _map_tiles) t = nullptr;
|
||||||
lv_obj_t* prev = lv_screen_active();
|
lv_obj_t* prev = lv_screen_active();
|
||||||
lv_obj_t* scr = lv_obj_create(NULL);
|
lv_obj_t* scr = lv_obj_create(NULL);
|
||||||
styleSurface(scr, theme::BG);
|
styleSurface(scr, theme::BG);
|
||||||
@@ -395,11 +398,13 @@ void UITask::back() {
|
|||||||
if (_scan_overlay) closeScanPopup();
|
if (_scan_overlay) closeScanPopup();
|
||||||
else showHome();
|
else showHome();
|
||||||
break;
|
break;
|
||||||
case SCR_NODE: // back to where the node was picked: the list, or the scan popup over it
|
case SCR_NODE: // back to where the node was picked: map, the list, or the scan popup over it
|
||||||
|
if (_node_from_map) { showMap(); break; }
|
||||||
_screen = SCR_NEARBY;
|
_screen = SCR_NEARBY;
|
||||||
buildNearby();
|
buildNearby();
|
||||||
if (_node_from_scan) showScanPopup();
|
if (_node_from_scan) showScanPopup();
|
||||||
break;
|
break;
|
||||||
|
case SCR_MAP: showHome(); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,6 +415,7 @@ static void onOpenChats(lv_event_t* e) { (void)e; s_ui->showChats(); }
|
|||||||
static void onOpenSettings(lv_event_t* e) { (void)e; s_ui->showSettings(); }
|
static void onOpenSettings(lv_event_t* e) { (void)e; s_ui->showSettings(); }
|
||||||
|
|
||||||
static void onOpenNearby(lv_event_t* e) { (void)e; s_ui->showNearby(); }
|
static void onOpenNearby(lv_event_t* e) { (void)e; s_ui->showNearby(); }
|
||||||
|
static void onOpenMap(lv_event_t* e) { (void)e; s_ui->showMap(); }
|
||||||
|
|
||||||
// Home tile: icon over label, one of a row of three; optional amber value
|
// Home tile: icon over label, one of a row of three; optional amber value
|
||||||
// (unread count) in its top-right corner.
|
// (unread count) in its top-right corner.
|
||||||
@@ -455,7 +461,8 @@ void UITask::buildHome() {
|
|||||||
lv_obj_set_flex_flow(tiles, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(tiles, LV_FLEX_FLOW_ROW);
|
||||||
lv_obj_set_style_pad_column(tiles, theme::GAP, 0);
|
lv_obj_set_style_pad_column(tiles, theme::GAP, 0);
|
||||||
homeTile(tiles, LV_SYMBOL_ENVELOPE, "Messages", onOpenChats, &_home_unread);
|
homeTile(tiles, LV_SYMBOL_ENVELOPE, "Messages", onOpenChats, &_home_unread);
|
||||||
homeTile(tiles, LV_SYMBOL_GPS, "Nearby", onOpenNearby, NULL);
|
homeTile(tiles, UI_SYMBOL_USERS, "Nearby", onOpenNearby, NULL);
|
||||||
|
homeTile(tiles, UI_SYMBOL_MAP, "Map", onOpenMap, NULL);
|
||||||
homeTile(tiles, LV_SYMBOL_SETTINGS, "Settings", onOpenSettings, NULL);
|
homeTile(tiles, LV_SYMBOL_SETTINGS, "Settings", onOpenSettings, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,6 +811,7 @@ void UITask::openScanNode(int row) {
|
|||||||
if (row < 0 || row >= _scan->count()) return;
|
if (row < 0 || row >= _scan->count()) return;
|
||||||
s_node = _scan->at(row);
|
s_node = _scan->at(row);
|
||||||
_node_from_scan = true;
|
_node_from_scan = true;
|
||||||
|
_node_from_map = false;
|
||||||
_scanning = false;
|
_scanning = false;
|
||||||
_pinging = false;
|
_pinging = false;
|
||||||
_delete_armed_ms = 0;
|
_delete_armed_ms = 0;
|
||||||
@@ -876,6 +884,7 @@ void UITask::openNode(int row) {
|
|||||||
if (row < 0 || row >= _nearby->count()) return;
|
if (row < 0 || row >= _nearby->count()) return;
|
||||||
s_node = _nearby->at(row);
|
s_node = _nearby->at(row);
|
||||||
_node_from_scan = false;
|
_node_from_scan = false;
|
||||||
|
_node_from_map = false;
|
||||||
_pinging = false;
|
_pinging = false;
|
||||||
_delete_armed_ms = 0;
|
_delete_armed_ms = 0;
|
||||||
_screen = SCR_NODE;
|
_screen = SCR_NODE;
|
||||||
@@ -1044,6 +1053,8 @@ void UITask::nodeAction(uint8_t action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "MapScreen.h"
|
||||||
|
|
||||||
// ── Conversation ──────────────────────────────────────────────────────────────
|
// ── Conversation ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
static void onKeyboard(lv_event_t* e) {
|
static void onKeyboard(lv_event_t* e) {
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ public:
|
|||||||
void showContacts();
|
void showContacts();
|
||||||
void showSettings();
|
void showSettings();
|
||||||
void showNearby();
|
void showNearby();
|
||||||
|
void showMap();
|
||||||
|
void mapZoom(int delta);
|
||||||
|
void mapCenterOnMe();
|
||||||
|
void mapPan(int dx, int dy);
|
||||||
|
void mapOpenMarker(int idx);
|
||||||
void setNearbyFilter(uint8_t f);
|
void setNearbyFilter(uint8_t f);
|
||||||
void toggleNearbySort();
|
void toggleNearbySort();
|
||||||
void startNearbyScan();
|
void startNearbyScan();
|
||||||
@@ -59,7 +64,7 @@ public:
|
|||||||
void openAdminFor(const ContactInfo& ci, bool from_picker) { (void)ci; (void)from_picker; }
|
void openAdminFor(const ContactInfo& ci, bool from_picker) { (void)ci; (void)from_picker; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE };
|
enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE, SCR_MAP };
|
||||||
|
|
||||||
void buildStatusBar();
|
void buildStatusBar();
|
||||||
void refreshStatusBar();
|
void refreshStatusBar();
|
||||||
@@ -74,6 +79,10 @@ private:
|
|||||||
uint32_t nearbySignature() const;
|
uint32_t nearbySignature() const;
|
||||||
void showScanPopup();
|
void showScanPopup();
|
||||||
void refreshScanPopup();
|
void refreshScanPopup();
|
||||||
|
void buildMap();
|
||||||
|
void layoutMap();
|
||||||
|
void mapLoop();
|
||||||
|
void rebuildMapMarkers();
|
||||||
void buildNode();
|
void buildNode();
|
||||||
void refreshNode();
|
void refreshNode();
|
||||||
void buildThread();
|
void buildThread();
|
||||||
@@ -138,4 +147,18 @@ private:
|
|||||||
lv_obj_t* _node_info = nullptr;
|
lv_obj_t* _node_info = nullptr;
|
||||||
lv_obj_t* _node_ping = nullptr;
|
lv_obj_t* _node_ping = nullptr;
|
||||||
lv_obj_t* _node_delete_lbl = nullptr;
|
lv_obj_t* _node_delete_lbl = nullptr;
|
||||||
|
bool _node_from_map = false;
|
||||||
|
|
||||||
|
// Map (SCR_MAP): view centre in fractional tile coords at zoom _map_z
|
||||||
|
double _map_cx = 0, _map_cy = 0;
|
||||||
|
int _map_z = 0; // 0 = not initialised yet
|
||||||
|
bool _map_follow = true; // keep centred on own position until panned
|
||||||
|
bool _map_pending = false; // visible tiles still to decode
|
||||||
|
uint32_t _next_map_marks_ms = 0;
|
||||||
|
lv_obj_t* _map_area = nullptr;
|
||||||
|
lv_obj_t* _map_tiles[6] = {nullptr};
|
||||||
|
lv_obj_t* _map_marks = nullptr;
|
||||||
|
lv_obj_t* _map_me = nullptr;
|
||||||
|
lv_obj_t* _map_zoom_lbl = nullptr;
|
||||||
|
lv_obj_t* _map_hint = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ FA_URL=https://raw.githubusercontent.com/lvgl/lvgl/v9.2.2/scripts/built_in_font/
|
|||||||
TEXT="0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3"
|
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"
|
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)
|
# LVGL built-in symbols (same list as lvgl/scripts/built_in_font/built_in_font_gen.py)
|
||||||
# plus 61612 = globe (keyboard script key), 61445 = star (favourite)
|
# plus 61612 = globe (keyboard script key), 61445 = star (favourite),
|
||||||
SYMS="61612,61445,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"
|
# 62073 = map, 61632 = users (home tiles)
|
||||||
|
SYMS="61612,61445,62073,61632,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"
|
CONV="npx -y lv_font_conv@1.5.3"
|
||||||
gen() { # size weight ranges name
|
gen() { # size weight ranges name
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Size: 12 px
|
* Size: 12 px
|
||||||
* Bpp: 4
|
* Bpp: 4
|
||||||
* Opts: --bpp 4 --size 12 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_12 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c
|
* Opts: --bpp 4 --size 12 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,62073,61632,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_12 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
@@ -6699,6 +6699,18 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0xe, 0x0, 0x44, 0x3a, 0xc0, 0x8, 0xf8, 0x60,
|
0xe, 0x0, 0x44, 0x3a, 0xc0, 0x8, 0xf8, 0x60,
|
||||||
0x13, 0xdb, 0x56, 0x16, 0x18, 0x0,
|
0x13, 0xdb, 0x56, 0x16, 0x18, 0x0,
|
||||||
|
|
||||||
|
/* U+F0C0 "" */
|
||||||
|
0x0, 0xe1, 0x9c, 0x91, 0x0, 0xf1, 0x20, 0x2,
|
||||||
|
0x98, 0xda, 0x80, 0x8, 0x40, 0x3b, 0x70, 0x8,
|
||||||
|
0x1, 0x20, 0xc5, 0xe8, 0x98, 0x0, 0x80, 0x3c,
|
||||||
|
0x24, 0x0, 0x32, 0xa6, 0xb0, 0x90, 0xa, 0x42,
|
||||||
|
0xda, 0x88, 0x98, 0xc, 0xd, 0xb5, 0xac, 0xe,
|
||||||
|
0x18, 0x5e, 0xcc, 0x23, 0x77, 0x33, 0xc1, 0x8b,
|
||||||
|
0x33, 0xc8, 0x14, 0x32, 0x2b, 0x29, 0xf0, 0x90,
|
||||||
|
0x9, 0xd3, 0xa0, 0x3, 0xe8, 0xf4, 0x78, 0xb4,
|
||||||
|
0x20, 0xf, 0x89, 0x2e, 0x0, 0x25, 0x0, 0xf9,
|
||||||
|
0x40, 0x20,
|
||||||
|
|
||||||
/* U+F0C4 "" */
|
/* U+F0C4 "" */
|
||||||
0x7, 0x93, 0x0, 0xc4, 0x40, 0xa8, 0x6c, 0x20,
|
0x7, 0x93, 0x0, 0xc4, 0x40, 0xa8, 0x6c, 0x20,
|
||||||
0x4, 0x6e, 0x95, 0x4d, 0xc0, 0xa1, 0xe, 0xc,
|
0x4, 0x6e, 0x95, 0x4d, 0xc0, 0xa1, 0xe, 0xc,
|
||||||
@@ -6841,6 +6853,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0x34, 0x88, 0xff, 0x30, 0xc6, 0x7f, 0xff, 0xf0,
|
0x34, 0x88, 0xff, 0x30, 0xc6, 0x7f, 0xff, 0xf0,
|
||||||
0x38, 0x40,
|
0x38, 0x40,
|
||||||
|
|
||||||
|
/* U+F279 "" */
|
||||||
|
0x0, 0x1b, 0xab, 0x8, 0x7, 0x33, 0xb6, 0xe5,
|
||||||
|
0x94, 0xf6, 0x38, 0xc7, 0x4e, 0xc9, 0x0, 0x71,
|
||||||
|
0xc1, 0x38, 0x80, 0x7f, 0xff, 0xc0, 0x3f, 0xf8,
|
||||||
|
0x25, 0x2a, 0xc2, 0x1, 0xc9, 0x2b, 0x7a, 0xa5,
|
||||||
|
0x3d, 0x8e, 0x2f, 0xb6, 0x60,
|
||||||
|
|
||||||
/* U+F287 "" */
|
/* U+F287 "" */
|
||||||
0x0, 0xff, 0xe5, 0x12, 0xfd, 0x80, 0x7f, 0xcb,
|
0x0, 0xff, 0xe5, 0x12, 0xfd, 0x80, 0x7f, 0xcb,
|
||||||
0xdc, 0x5, 0x0, 0xf8, 0x40, 0x28, 0xdb, 0xb6,
|
0xdc, 0x5, 0x0, 0xf8, 0x40, 0x28, 0xdb, 0xb6,
|
||||||
@@ -7967,30 +7986,32 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
|||||||
{.bitmap_index = 32689, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 32689, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 32746, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 32746, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 32810, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 32810, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 32880, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 32880, .adv_w = 240, .box_w = 15, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 32941, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 32954, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 32981, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 33015, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33025, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 33055, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 33057, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33099, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 33096, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 33131, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33142, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33170, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 33187, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33216, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33240, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33261, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33296, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 33314, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33359, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33370, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 33382, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 33433, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33457, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33456, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 33500, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33531, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33549, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33574, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33598, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33623, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33647, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33672, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33689, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 33721, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 33754, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33763, .adv_w = 216, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 33818, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33800, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 33861, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 33865, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33928, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 33929, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 33983, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 33972, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 34012, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0}
|
{.bitmap_index = 34039, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 34094, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2},
|
||||||
|
{.bitmap_index = 34123, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------
|
/*---------------------
|
||||||
@@ -8019,9 +8040,10 @@ static const uint16_t unicode_list_12[] = {
|
|||||||
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
||||||
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
||||||
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
||||||
0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd,
|
0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4,
|
||||||
0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d,
|
0xcfdd, 0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c,
|
||||||
0xd12e, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444, 0xd6ac, 0xd78c
|
0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444,
|
||||||
|
0xd6ac, 0xd78c
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Collect the unicode lists and glyph_id offsets*/
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
@@ -8077,7 +8099,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
||||||
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 64, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 66, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8224,7 +8246,7 @@ static const uint8_t kern_left_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Map glyph_ids to kern right classes*/
|
/*Map glyph_ids to kern right classes*/
|
||||||
@@ -8365,7 +8387,7 @@ static const uint8_t kern_right_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Kern values between classes*/
|
/*Kern values between classes*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Size: 14 px
|
* Size: 14 px
|
||||||
* Bpp: 4
|
* Bpp: 4
|
||||||
* Opts: --bpp 4 --size 14 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_14 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c
|
* Opts: --bpp 4 --size 14 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,62073,61632,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_14 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
@@ -7635,6 +7635,21 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0x57, 0x9, 0x20, 0x2a, 0x5a, 0xa0, 0x1c, 0xec,
|
0x57, 0x9, 0x20, 0x2a, 0x5a, 0xa0, 0x1c, 0xec,
|
||||||
0xf9, 0xe5, 0x44, 0x1, 0x0,
|
0xf9, 0xe5, 0x44, 0x1, 0x0,
|
||||||
|
|
||||||
|
/* U+F0C0 "" */
|
||||||
|
0x0, 0xfc, 0x62, 0x1, 0xff, 0xc2, 0x3e, 0xce,
|
||||||
|
0xa0, 0xf, 0xc2, 0xe6, 0x0, 0xd1, 0x0, 0x2b,
|
||||||
|
0x80, 0x19, 0x40, 0x2f, 0x8c, 0x23, 0x10, 0xd,
|
||||||
|
0x81, 0x53, 0x4c, 0x2, 0x20, 0x3, 0x8, 0x7,
|
||||||
|
0x8, 0x30, 0x3, 0x80, 0x60, 0x55, 0x9, 0x0,
|
||||||
|
0x34, 0x84, 0x9, 0x50, 0x1, 0xb2, 0xc0, 0x16,
|
||||||
|
0xe6, 0x98, 0x60, 0x99, 0xe4, 0x11, 0xdb, 0xca,
|
||||||
|
0x4b, 0x59, 0x6c, 0x83, 0x9b, 0xae, 0x27, 0x0,
|
||||||
|
0x41, 0x6d, 0x6f, 0xfa, 0xaf, 0x38, 0x40, 0x54,
|
||||||
|
0x40, 0x52, 0x0, 0x3e, 0x29, 0x80, 0xb, 0xf3,
|
||||||
|
0x8, 0x1, 0xfc, 0x8d, 0x98, 0x71, 0x32, 0x0,
|
||||||
|
0xff, 0xe0, 0x19, 0x80, 0x32, 0x99, 0x17, 0xe8,
|
||||||
|
0x0, 0xc0,
|
||||||
|
|
||||||
/* U+F0C4 "" */
|
/* U+F0C4 "" */
|
||||||
0x4, 0x86, 0x0, 0xf0, 0x80, 0x1a, 0xde, 0x68,
|
0x4, 0x86, 0x0, 0xf0, 0x80, 0x1a, 0xde, 0x68,
|
||||||
0x2, 0x2d, 0xed, 0x18, 0xc, 0x35, 0x10, 0x1f,
|
0x2, 0x2d, 0xed, 0x18, 0xc, 0x35, 0x10, 0x1f,
|
||||||
@@ -7801,6 +7816,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0xff, 0xc1, 0xe, 0x1a, 0xff, 0xff, 0xe1, 0xa8,
|
0xff, 0xc1, 0xe, 0x1a, 0xff, 0xff, 0xe1, 0xa8,
|
||||||
0x0,
|
0x0,
|
||||||
|
|
||||||
|
/* U+F279 "" */
|
||||||
|
0x0, 0x84, 0x44, 0x1, 0xfc, 0x80, 0x73, 0xcf,
|
||||||
|
0x3f, 0x4a, 0x1, 0xc, 0x75, 0x5e, 0x30, 0x6,
|
||||||
|
0x5a, 0xf7, 0x5e, 0x71, 0x4, 0x0, 0xfe, 0xd2,
|
||||||
|
0x0, 0xff, 0xff, 0x80, 0x7f, 0xf7, 0xc5, 0xdd,
|
||||||
|
0x2e, 0x40, 0x1e, 0x4d, 0x38, 0xe8, 0x12, 0x8d,
|
||||||
|
0xd3, 0x91, 0x23, 0xac, 0xc0,
|
||||||
|
|
||||||
/* U+F287 "" */
|
/* U+F287 "" */
|
||||||
0x0, 0xfe, 0x7b, 0x20, 0xf, 0xfe, 0xd, 0x6c,
|
0x0, 0xfe, 0x7b, 0x20, 0xf, 0xfe, 0xd, 0x6c,
|
||||||
0x24, 0x0, 0x7f, 0xf0, 0x28, 0xf8, 0x83, 0xc0,
|
0x24, 0x0, 0x7f, 0xf0, 0x28, 0xf8, 0x83, 0xc0,
|
||||||
@@ -8939,30 +8962,32 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
|||||||
{.bitmap_index = 40145, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 40145, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 40217, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 40217, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 40296, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 40296, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 40389, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 40389, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 40470, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 40487, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 40518, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 40568, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 40574, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 40616, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 40614, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 40672, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 40667, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 40712, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 40723, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 40765, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 40786, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 40821, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 40852, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 40884, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 40925, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 40950, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41002, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 41023, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 41034, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 41100, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 41131, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41132, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 41183, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41229, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41238, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41281, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41293, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41336, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41348, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41391, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41397, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 41446, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 41477, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 41495, .adv_w = 252, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 41561, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 41540, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 41617, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 41620, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 41694, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 41704, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 41772, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 41760, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 41808, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0}
|
{.bitmap_index = 41837, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 41915, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2},
|
||||||
|
{.bitmap_index = 41951, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------
|
/*---------------------
|
||||||
@@ -8991,9 +9016,10 @@ static const uint16_t unicode_list_12[] = {
|
|||||||
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
||||||
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
||||||
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
||||||
0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd,
|
0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4,
|
||||||
0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d,
|
0xcfdd, 0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c,
|
||||||
0xd12e, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444, 0xd6ac, 0xd78c
|
0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444,
|
||||||
|
0xd6ac, 0xd78c
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Collect the unicode lists and glyph_id offsets*/
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
@@ -9049,7 +9075,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
||||||
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 64, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 66, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9196,7 +9222,7 @@ static const uint8_t kern_left_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Map glyph_ids to kern right classes*/
|
/*Map glyph_ids to kern right classes*/
|
||||||
@@ -9337,7 +9363,7 @@ static const uint8_t kern_right_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Kern values between classes*/
|
/*Kern values between classes*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Size: 16 px
|
* Size: 16 px
|
||||||
* Bpp: 4
|
* Bpp: 4
|
||||||
* Opts: --bpp 4 --size 16 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_16 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c
|
* Opts: --bpp 4 --size 16 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,62073,61632,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_16 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
@@ -8728,6 +8728,22 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0x40, 0x8, 0x63, 0xd3, 0x0, 0xe6, 0xe0, 0xf5,
|
0x40, 0x8, 0x63, 0xd3, 0x0, 0xe6, 0xe0, 0xf5,
|
||||||
0x85, 0x56, 0x10, 0x4,
|
0x85, 0x56, 0x10, 0x4,
|
||||||
|
|
||||||
|
/* U+F0C0 "" */
|
||||||
|
0x0, 0xf8, 0xaf, 0xfa, 0x0, 0x3f, 0xf8, 0x43,
|
||||||
|
0x88, 0x2, 0xf2, 0x1, 0xf9, 0x3b, 0x88, 0x12,
|
||||||
|
0x20, 0x19, 0x84, 0x13, 0xb8, 0x80, 0xa, 0x11,
|
||||||
|
0x50, 0x18, 0x7, 0x94, 0x28, 0x45, 0x40, 0x1f,
|
||||||
|
0x18, 0x7, 0x94, 0x3, 0xea, 0x11, 0x50, 0x48,
|
||||||
|
0x80, 0x66, 0x10, 0xa1, 0x15, 0x0, 0x13, 0xb8,
|
||||||
|
0x80, 0x38, 0x80, 0x2f, 0x20, 0x4, 0xee, 0x20,
|
||||||
|
0x27, 0x7f, 0xb8, 0x40, 0xaf, 0xfa, 0x0, 0x5,
|
||||||
|
0xdf, 0xee, 0x4a, 0x10, 0x5, 0x26, 0xfd, 0xc4,
|
||||||
|
0xef, 0xe3, 0x58, 0x0, 0x68, 0x40, 0xc, 0x14,
|
||||||
|
0x40, 0x8e, 0xc4, 0x7, 0x62, 0xc0, 0x1, 0x30,
|
||||||
|
0x5, 0x40, 0x7, 0xfa, 0x28, 0x0, 0x79, 0xfe,
|
||||||
|
0x33, 0x0, 0x7f, 0x8c, 0xdf, 0xec, 0x0, 0xff,
|
||||||
|
0xe6, 0x38, 0x7, 0xf9, 0xc0, 0x30,
|
||||||
|
|
||||||
/* U+F0C4 "" */
|
/* U+F0C4 "" */
|
||||||
0x8, 0xee, 0x40, 0x7, 0x99, 0x82, 0x10, 0xe2,
|
0x8, 0xee, 0x40, 0x7, 0x99, 0x82, 0x10, 0xe2,
|
||||||
0x27, 0x80, 0x8, 0xb6, 0x65, 0x80, 0xc1, 0x98,
|
0x27, 0x80, 0x8, 0xb6, 0x65, 0x80, 0xc1, 0x98,
|
||||||
@@ -8898,6 +8914,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0xed, 0xf8, 0x7, 0xff, 0x24, 0x80, 0x1f, 0xff,
|
0xed, 0xf8, 0x7, 0xff, 0x24, 0x80, 0x1f, 0xff,
|
||||||
0xfc, 0x30, 0x6, 0xb8, 0x7, 0xff, 0x15, 0xc0,
|
0xfc, 0x30, 0x6, 0xb8, 0x7, 0xff, 0x15, 0xc0,
|
||||||
|
|
||||||
|
/* U+F279 "" */
|
||||||
|
0x0, 0xff, 0xe4, 0xb6, 0x6, 0xb9, 0x0, 0x78,
|
||||||
|
0xa7, 0x8a, 0x7e, 0x4c, 0xa, 0x37, 0x4e, 0x40,
|
||||||
|
0x75, 0xac, 0x38, 0xc0, 0x1f, 0x14, 0x68, 0x62,
|
||||||
|
0x80, 0x42, 0x1, 0xff, 0xff, 0x0, 0xff, 0xff,
|
||||||
|
0x80, 0x7f, 0x84, 0x2, 0x5c, 0xd, 0x72, 0x0,
|
||||||
|
0xf9, 0xb0, 0x9b, 0x68, 0xc0, 0xa3, 0x74, 0xe4,
|
||||||
|
0x7, 0x3f, 0x25, 0xb2, 0x40, 0x1e, 0x28, 0xd0,
|
||||||
|
0xc6, 0x0, 0x80,
|
||||||
|
|
||||||
/* U+F287 "" */
|
/* U+F287 "" */
|
||||||
0x0, 0xff, 0x84, 0x3, 0xff, 0x8e, 0xfd, 0xa2,
|
0x0, 0xff, 0x84, 0x3, 0xff, 0x8e, 0xfd, 0xa2,
|
||||||
0x1, 0xff, 0xc2, 0x1c, 0xf8, 0x2, 0x40, 0xf,
|
0x1, 0xff, 0xc2, 0x1c, 0xf8, 0x2, 0x40, 0xf,
|
||||||
@@ -10045,30 +10071,32 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
|||||||
{.bitmap_index = 48861, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 48861, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 48929, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 48929, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 49023, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 49023, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 49131, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 49131, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 49222, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 49241, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 49269, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 49332, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 49321, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 49379, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 49376, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 49431, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 49435, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2},
|
{.bitmap_index = 49486, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 49503, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 49545, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2},
|
||||||
{.bitmap_index = 49564, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 49613, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 49634, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 49674, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 49700, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 49744, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 49789, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 49810, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 49822, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 49899, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 49935, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 49932, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 49980, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 50045, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 50024, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 50090, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 50068, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 50134, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 50114, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 50178, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 50154, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 50224, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 50255, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2},
|
{.bitmap_index = 50264, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 50351, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 50323, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 50406, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 50424, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2},
|
||||||
{.bitmap_index = 50500, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 50520, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 50589, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 50575, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 50628, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1}
|
{.bitmap_index = 50669, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 50758, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2},
|
||||||
|
{.bitmap_index = 50797, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------
|
/*---------------------
|
||||||
@@ -10097,9 +10125,10 @@ static const uint16_t unicode_list_12[] = {
|
|||||||
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
||||||
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
||||||
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
||||||
0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd,
|
0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4,
|
||||||
0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d,
|
0xcfdd, 0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c,
|
||||||
0xd12e, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444, 0xd6ac, 0xd78c
|
0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444,
|
||||||
|
0xd6ac, 0xd78c
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Collect the unicode lists and glyph_id offsets*/
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
@@ -10155,7 +10184,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
||||||
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 64, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 66, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -10302,7 +10331,7 @@ static const uint8_t kern_left_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Map glyph_ids to kern right classes*/
|
/*Map glyph_ids to kern right classes*/
|
||||||
@@ -10443,7 +10472,7 @@ static const uint8_t kern_right_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Kern values between classes*/
|
/*Kern values between classes*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Size: 20 px
|
* Size: 20 px
|
||||||
* Bpp: 4
|
* Bpp: 4
|
||||||
* Opts: --bpp 4 --size 20 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_20 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c
|
* Opts: --bpp 4 --size 20 --force-fast-kern-format --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/NotoSans-Medium.ttf -r 0x20-0x7E,0xA0-0x24F,0x370-0x3FF,0x400-0x52F,0x1E80-0x1E85,0x1E9E,0x1EF2-0x1EF3,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122 --font /var/folders/1d/dgkmygls6x5gsb16pbn2mwlr0000gn/T//meshcore-ui-fonts/fa.woff -r 61612,61445,62073,61632,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 --format lvgl --lv-include lvgl.h --lv-font-name ui_font_20 -o /Users/jakub/Documents/MeshCore/MeshCore/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
@@ -10980,6 +10980,30 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0xf9, 0xf8, 0x12, 0x0, 0xec, 0xbb, 0x8, 0x3,
|
0xf9, 0xf8, 0x12, 0x0, 0xec, 0xbb, 0x8, 0x3,
|
||||||
0xf8, 0x50, 0x1f, 0xf0, 0x48, 0xc0, 0x3c,
|
0xf8, 0x50, 0x1f, 0xf0, 0x48, 0xc0, 0x3c,
|
||||||
|
|
||||||
|
/* U+F0C0 "" */
|
||||||
|
0x0, 0xff, 0xe0, 0x8, 0x7, 0xff, 0x24, 0x6b,
|
||||||
|
0xfb, 0xe4, 0x3, 0xff, 0x8f, 0x8a, 0x1, 0x36,
|
||||||
|
0x0, 0x7f, 0xc9, 0x2e, 0x1, 0x41, 0x0, 0x71,
|
||||||
|
0xb8, 0x4, 0xf2, 0x60, 0x12, 0x5b, 0x45, 0x80,
|
||||||
|
0x10, 0x3, 0xeb, 0x0, 0x64, 0x36, 0x20, 0x3,
|
||||||
|
0xc0, 0x24, 0x20, 0x10, 0xf, 0x84, 0x8, 0xc0,
|
||||||
|
0x2f, 0x0, 0x8, 0x6, 0x30, 0x60, 0xf, 0x9c,
|
||||||
|
0xc, 0x3, 0x8, 0x2, 0x4, 0x0, 0xe2, 0x10,
|
||||||
|
0x1, 0xf4, 0x80, 0xb8, 0x0, 0x60, 0x0, 0x5f,
|
||||||
|
0x7b, 0x0, 0x3, 0x90, 0xe, 0xa3, 0x0, 0x46,
|
||||||
|
0x5f, 0x90, 0x0, 0x90, 0x91, 0x0, 0x13, 0x6c,
|
||||||
|
0x34, 0x72, 0x80, 0x4a, 0xa2, 0x42, 0x6, 0xda,
|
||||||
|
0x99, 0x5a, 0x82, 0xb0, 0xbc, 0xb9, 0x3a, 0x82,
|
||||||
|
0x54, 0xca, 0xb5, 0x60, 0x3, 0x58, 0x75, 0x4e,
|
||||||
|
0x7e, 0xfe, 0x45, 0x70, 0x60, 0x6, 0xb1, 0x0,
|
||||||
|
0xa1, 0xe8, 0x40, 0x31, 0x0, 0x61, 0xb0, 0x90,
|
||||||
|
0x8, 0x48, 0x2, 0x78, 0x0, 0xff, 0xe0, 0xc3,
|
||||||
|
0x0, 0x45, 0x97, 0x70, 0x20, 0x7, 0xff, 0x5,
|
||||||
|
0x2, 0xee, 0xc1, 0x44, 0x80, 0x3f, 0xf8, 0xa8,
|
||||||
|
0x90, 0x80, 0x7f, 0xf4, 0xa4, 0x3, 0xff, 0x83,
|
||||||
|
0x20, 0x1f, 0xe6, 0xff, 0xff, 0xe0, 0xb0, 0x7,
|
||||||
|
0x0,
|
||||||
|
|
||||||
/* U+F0C4 "" */
|
/* U+F0C4 "" */
|
||||||
0x0, 0x12, 0xa0, 0x7, 0xff, 0xa, 0x76, 0xaf,
|
0x0, 0x12, 0xa0, 0x7, 0xff, 0xa, 0x76, 0xaf,
|
||||||
0x8c, 0x3, 0xc9, 0x54, 0x50, 0x76, 0x0, 0x87,
|
0x8c, 0x3, 0xc9, 0x54, 0x50, 0x76, 0x0, 0x87,
|
||||||
@@ -11215,6 +11239,19 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
|||||||
0x1b, 0xbf, 0xff, 0x18, 0x41, 0xd2, 0x84, 0x3,
|
0x1b, 0xbf, 0xff, 0x18, 0x41, 0xd2, 0x84, 0x3,
|
||||||
0xff, 0x90, 0x70, 0x0,
|
0xff, 0x90, 0x70, 0x0,
|
||||||
|
|
||||||
|
/* U+F279 "" */
|
||||||
|
0x0, 0xf8, 0x40, 0x3f, 0xf8, 0x24, 0x1, 0x8a,
|
||||||
|
0x39, 0x27, 0xa4, 0xc0, 0x3f, 0x2e, 0x6a, 0x2,
|
||||||
|
0xde, 0xb8, 0x80, 0x5, 0xb3, 0xa4, 0xc0, 0x26,
|
||||||
|
0xda, 0x30, 0x1c, 0xa4, 0x0, 0xfc, 0x2d, 0x9c,
|
||||||
|
0x1b, 0x24, 0x1, 0x8c, 0x3, 0xff, 0x82, 0x20,
|
||||||
|
0x60, 0x1f, 0xff, 0xf0, 0xf, 0xff, 0xf8, 0x7,
|
||||||
|
0xff, 0xfc, 0x3, 0xff, 0x8a, 0xfc, 0x1, 0xff,
|
||||||
|
0xc2, 0x70, 0xc, 0xfc, 0x6d, 0xd2, 0x60, 0x1f,
|
||||||
|
0x8a, 0x38, 0x80, 0x63, 0xa0, 0x40, 0x2, 0xd9,
|
||||||
|
0xd2, 0x60, 0x12, 0xde, 0xb8, 0x86, 0xf3, 0x88,
|
||||||
|
0x7, 0xc2, 0xd9, 0xc1, 0xf4, 0x80, 0x18,
|
||||||
|
|
||||||
/* U+F287 "" */
|
/* U+F287 "" */
|
||||||
0x0, 0xff, 0xe1, 0x8, 0x7, 0xff, 0x33, 0x3b,
|
0x0, 0xff, 0xe1, 0x8, 0x7, 0xff, 0x33, 0x3b,
|
||||||
0x84, 0x1, 0xff, 0xc7, 0x7c, 0xd3, 0x1, 0xb0,
|
0x84, 0x1, 0xff, 0xc7, 0x7c, 0xd3, 0x1, 0xb0,
|
||||||
@@ -12390,30 +12427,32 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
|||||||
{.bitmap_index = 66527, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 66527, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 66637, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 66637, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 66775, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 66775, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 66934, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 66934, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 67082, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 67103, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 67155, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 67251, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 67248, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 67324, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 67308, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 67417, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 67398, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 67477, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 67491, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 67567, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 67579, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 67660, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 67690, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 67748, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 67816, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 67859, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||||
{.bitmap_index = 67937, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 67985, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 67985, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
{.bitmap_index = 68106, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 68149, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 68154, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 68216, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 68318, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 68284, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 68385, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 68351, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 68453, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 68418, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
{.bitmap_index = 68520, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 68478, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
{.bitmap_index = 68587, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1},
|
||||||
{.bitmap_index = 68612, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3},
|
{.bitmap_index = 68647, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||||
{.bitmap_index = 68759, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 68734, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||||
{.bitmap_index = 68846, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
{.bitmap_index = 68868, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3},
|
||||||
{.bitmap_index = 68986, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
{.bitmap_index = 69015, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
{.bitmap_index = 69106, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
{.bitmap_index = 69102, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3},
|
||||||
{.bitmap_index = 69165, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1}
|
{.bitmap_index = 69242, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||||
|
{.bitmap_index = 69362, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||||
|
{.bitmap_index = 69421, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------
|
/*---------------------
|
||||||
@@ -12442,9 +12481,10 @@ static const uint16_t unicode_list_12[] = {
|
|||||||
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b,
|
||||||
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b,
|
||||||
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf7d, 0xcf7f, 0xcf96,
|
||||||
0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd,
|
0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4,
|
||||||
0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d,
|
0xcfdd, 0xd006, 0xd00e, 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c,
|
||||||
0xd12e, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444, 0xd6ac, 0xd78c
|
0xd12d, 0xd12e, 0xd163, 0xd171, 0xd17d, 0xd1d7, 0xd1ee, 0xd444,
|
||||||
|
0xd6ac, 0xd78c
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Collect the unicode lists and glyph_id offsets*/
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
@@ -12500,7 +12540,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
.range_start = 8470, .range_length = 55181, .glyph_id_start = 1017,
|
||||||
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 64, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
.unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 66, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -12647,7 +12687,7 @@ static const uint8_t kern_left_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Map glyph_ids to kern right classes*/
|
/*Map glyph_ids to kern right classes*/
|
||||||
@@ -12788,7 +12828,7 @@ static const uint8_t kern_right_class_mapping[] =
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Kern values between classes*/
|
/*Kern values between classes*/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN
|
#define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN
|
||||||
#define LV_USE_STDLIB_STRING LV_STDLIB_CLIB
|
#define LV_USE_STDLIB_STRING LV_STDLIB_CLIB
|
||||||
#define LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB
|
#define LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB
|
||||||
#define LV_MEM_SIZE (1024U * 1024U)
|
#define LV_MEM_SIZE (2048U * 1024U) // map tiles decode through it (~0.5 MB peak per PNG)
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#define LV_MEM_ADR 0
|
#define LV_MEM_ADR 0
|
||||||
#define LV_MEM_POOL_INCLUDE "lv_psram_pool.h"
|
#define LV_MEM_POOL_INCLUDE "lv_psram_pool.h"
|
||||||
@@ -35,6 +35,9 @@
|
|||||||
#define LV_FONT_DEFAULT &ui_font_14
|
#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_FONT_COMPRESSED 1 // generated fonts are RLE-compressed (without this every glyph draws as a box)
|
||||||
|
|
||||||
|
// PNG decoder for raster map tiles (map/TileProvider.h calls lodepng directly).
|
||||||
|
#define LV_USE_LODEPNG 1
|
||||||
|
|
||||||
#define LV_USE_THEME_DEFAULT 1
|
#define LV_USE_THEME_DEFAULT 1
|
||||||
#define LV_THEME_DEFAULT_DARK 1
|
#define LV_THEME_DEFAULT_DARK 1
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
// Decoded map tiles (RGB565, 128 KB each) kept for reuse while panning / zooming
|
||||||
|
// back, least-recently-used evicted. Buffers live in PSRAM on the ESP32 and are
|
||||||
|
// allocated on first use, then kept for the session.
|
||||||
|
//
|
||||||
|
// Single-TU fragment: included by ui-lvgl/UITask.cpp only.
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
#include <esp_heap_caps.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" void lv_image_cache_drop(const void* src); // not exported through lvgl.h here
|
||||||
|
|
||||||
|
namespace mapview {
|
||||||
|
|
||||||
|
class TileCache {
|
||||||
|
public:
|
||||||
|
static const int SLOTS = 12; // 6 on screen at 320x218 + a ring of neighbours
|
||||||
|
|
||||||
|
struct Slot {
|
||||||
|
int16_t z = -1;
|
||||||
|
int32_t x = 0, y = 0;
|
||||||
|
bool present = false; // false: looked up, there is no tile (don't retry)
|
||||||
|
uint32_t used = 0;
|
||||||
|
uint16_t* px = nullptr;
|
||||||
|
lv_image_dsc_t dsc;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The slot holding z/x/y if it was loaded (present or known missing), else nullptr.
|
||||||
|
Slot* find(int z, int x, int y) {
|
||||||
|
for (Slot& s : _slots)
|
||||||
|
if (s.z == z && s.x == x && s.y == y) { s.used = ++_tick; return &s; }
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render z/x/y through `src` into the least recently used slot.
|
||||||
|
Slot* load(TileProvider& src, int z, int x, int y) {
|
||||||
|
Slot* s = &_slots[0];
|
||||||
|
for (Slot& c : _slots) if (c.used < s->used) s = &c;
|
||||||
|
if (!s->px) {
|
||||||
|
#if defined(ESP32)
|
||||||
|
s->px = (uint16_t*)heap_caps_malloc(TILE_PX * TILE_PX * 2, MALLOC_CAP_SPIRAM);
|
||||||
|
#else
|
||||||
|
s->px = (uint16_t*)malloc(TILE_PX * TILE_PX * 2);
|
||||||
|
#endif
|
||||||
|
if (!s->px) return nullptr;
|
||||||
|
}
|
||||||
|
lv_image_cache_drop(&s->dsc); // same descriptor, new pixels
|
||||||
|
s->z = z; s->x = x; s->y = y;
|
||||||
|
s->used = ++_tick;
|
||||||
|
s->present = src.renderTile(z, x, y, s->px);
|
||||||
|
memset(&s->dsc, 0, sizeof(s->dsc));
|
||||||
|
s->dsc.header.magic = LV_IMAGE_HEADER_MAGIC;
|
||||||
|
s->dsc.header.cf = LV_COLOR_FORMAT_RGB565;
|
||||||
|
s->dsc.header.w = TILE_PX;
|
||||||
|
s->dsc.header.h = TILE_PX;
|
||||||
|
s->dsc.header.stride = TILE_PX * 2;
|
||||||
|
s->dsc.data_size = TILE_PX * TILE_PX * 2;
|
||||||
|
s->dsc.data = (const uint8_t*)s->px;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forget everything (e.g. the card was swapped); keeps the buffers.
|
||||||
|
void invalidate() { for (Slot& s : _slots) { s.z = -1; s.used = 0; } }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Slot _slots[SLOTS];
|
||||||
|
uint32_t _tick = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mapview
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
#pragma once
|
||||||
|
// Map tile sources. The map screen, its tile cache and the overlays only ever
|
||||||
|
// call renderTile(): 256x256 RGB565 pixels for Web-Mercator tile z/x/y. The
|
||||||
|
// raster provider decodes PNG files from the card; a vector renderer would be
|
||||||
|
// another TileProvider drawing into the same buffer, with nothing else changing.
|
||||||
|
//
|
||||||
|
// Single-TU fragment: included by ui-lvgl/UITask.cpp only.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
// LVGL's copy of lodepng (LV_USE_LODEPNG), compiled as C. It is patched for
|
||||||
|
// LVGL: the decode "output" is an lv_draw_buf_t* (32-bit RGBA pixels in ->data),
|
||||||
|
// not a plain pixel array, and is freed with lv_draw_buf_destroy().
|
||||||
|
#define LODEPNG_NO_COMPILE_CPP
|
||||||
|
extern "C" {
|
||||||
|
#include "src/libs/lodepng/lodepng.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mapview {
|
||||||
|
|
||||||
|
static const int TILE_PX = 256;
|
||||||
|
|
||||||
|
class TileProvider {
|
||||||
|
public:
|
||||||
|
virtual ~TileProvider() {}
|
||||||
|
virtual bool available() = 0; // anything to draw at all
|
||||||
|
virtual bool renderTile(int z, int x, int y, uint16_t* out) = 0; // false: no tile there
|
||||||
|
virtual const char* attribution() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Raster tiles under <root>/{z}/{x}/{y}.png -- the Meshtastic MUI layout, so
|
||||||
|
// cards prepared for either work for both (tools/maps/fetch_tiles.py writes
|
||||||
|
// it) -- or packed per column in <root>/{z}/{x}.pak ('TPK1': y_min, y_max,
|
||||||
|
// offsets[n+1], PNG blobs; the format of upstream PR #3381's tile_packer.py),
|
||||||
|
// which copies onto a FAT card far faster than millions of loose files.
|
||||||
|
class RasterTileProvider : public TileProvider {
|
||||||
|
public:
|
||||||
|
explicit RasterTileProvider(const char* root) : _root(root) {}
|
||||||
|
|
||||||
|
// Also reads <root>/attribution.txt (written by tools/maps/fetch_tiles.py and
|
||||||
|
// the on-device downloader): the tile set's credit line, shown on the map.
|
||||||
|
bool available() override {
|
||||||
|
struct stat st;
|
||||||
|
if (stat(_root, &st) != 0 || !S_ISDIR(st.st_mode)) return false;
|
||||||
|
char path[64];
|
||||||
|
snprintf(path, sizeof(path), "%s/attribution.txt", _root);
|
||||||
|
_attr[0] = '\0';
|
||||||
|
if (FILE* f = fopen(path, "r")) {
|
||||||
|
size_t n = fread(_attr, 1, sizeof(_attr) - 1, f);
|
||||||
|
fclose(f);
|
||||||
|
while (n > 0 && (_attr[n - 1] == '\n' || _attr[n - 1] == '\r')) n--;
|
||||||
|
_attr[n] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool renderTile(int z, int x, int y, uint16_t* out) override {
|
||||||
|
uint32_t len = 0;
|
||||||
|
uint8_t* png = readLoose(z, x, y, len);
|
||||||
|
if (!png) png = readPacked(z, x, y, len);
|
||||||
|
if (!png) return false;
|
||||||
|
|
||||||
|
unsigned char* res = nullptr;
|
||||||
|
unsigned w = 0, h = 0;
|
||||||
|
unsigned err = lodepng_decode32(&res, &w, &h, png, len);
|
||||||
|
lv_free(png);
|
||||||
|
lv_draw_buf_t* db = (lv_draw_buf_t*)res;
|
||||||
|
if (err || !db) { if (db) lv_draw_buf_destroy(db); return false; }
|
||||||
|
if (w != TILE_PX || h != TILE_PX) { lv_draw_buf_destroy(db); return false; }
|
||||||
|
|
||||||
|
for (int row = 0; row < TILE_PX; row++) {
|
||||||
|
const uint8_t* p = db->data + row * db->header.stride; // R, G, B, A
|
||||||
|
uint16_t* o = out + row * TILE_PX;
|
||||||
|
for (int i = 0; i < TILE_PX; i++, p += 4)
|
||||||
|
o[i] = (uint16_t)(((p[0] & 0xF8) << 8) | ((p[1] & 0xFC) << 3) | (p[2] >> 3));
|
||||||
|
}
|
||||||
|
lv_draw_buf_destroy(db);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* attribution() const override { return _attr[0] ? _attr : "\xC2\xA9 OpenStreetMap contributors"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* _root;
|
||||||
|
char _attr[96] = "";
|
||||||
|
|
||||||
|
static uint8_t* readRange(FILE* f, long off, uint32_t len) {
|
||||||
|
if (len == 0 || len > 512 * 1024) return nullptr;
|
||||||
|
uint8_t* buf = (uint8_t*)lv_malloc(len);
|
||||||
|
if (!buf) return nullptr;
|
||||||
|
if (fseek(f, off, SEEK_SET) != 0 || fread(buf, 1, len, f) != len) { lv_free(buf); return nullptr; }
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* readLoose(int z, int x, int y, uint32_t& len) {
|
||||||
|
char path[64];
|
||||||
|
snprintf(path, sizeof(path), "%s/%d/%d/%d.png", _root, z, x, y);
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (!f) return nullptr;
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long sz = ftell(f);
|
||||||
|
uint8_t* buf = sz > 0 ? readRange(f, 0, (uint32_t)sz) : nullptr;
|
||||||
|
fclose(f);
|
||||||
|
if (buf) len = (uint32_t)sz;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* readPacked(int z, int x, int y, uint32_t& len) {
|
||||||
|
char path[64];
|
||||||
|
snprintf(path, sizeof(path), "%s/%d/%d.pak", _root, z, x);
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (!f) return nullptr;
|
||||||
|
uint8_t hdr[12];
|
||||||
|
uint32_t y0, y1, off[2];
|
||||||
|
uint8_t* buf = nullptr;
|
||||||
|
if (fread(hdr, 1, 12, f) == 12 && memcmp(hdr, "TPK1", 4) == 0) {
|
||||||
|
memcpy(&y0, hdr + 4, 4);
|
||||||
|
memcpy(&y1, hdr + 8, 4);
|
||||||
|
if (y >= (int)y0 && y <= (int)y1 &&
|
||||||
|
fseek(f, 12 + 4 * (y - (int)y0), SEEK_SET) == 0 && fread(off, 4, 2, f) == 2 && off[1] > off[0]) {
|
||||||
|
len = off[1] - off[0];
|
||||||
|
buf = readRange(f, off[0], len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mapview
|
||||||
@@ -65,3 +65,5 @@ lib_deps =
|
|||||||
${Wio_Tracker_L2.lib_deps}
|
${Wio_Tracker_L2.lib_deps}
|
||||||
densaugeo/base64 @ ~1.4.0
|
densaugeo/base64 @ ~1.4.0
|
||||||
lvgl/lvgl @ 9.2.2 ; pinned: bump deliberately, re-test on hardware
|
lvgl/lvgl @ 9.2.2 ; pinned: bump deliberately, re-test on hardware
|
||||||
|
SD_MMC ; map tiles on the microSD (framework library)
|
||||||
|
FS
|
||||||
|
|||||||
Executable
+152
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Offline raster map tiles for the ui-lvgl map screen (Wio Tracker L2 SD card).
|
||||||
|
|
||||||
|
Writes <out>/maps/{z}/{x}/{y}.png -- the same layout Meshtastic MUI uses, so a
|
||||||
|
card prepared for either works for both. Copy the `maps` folder to the root of
|
||||||
|
the SD card. The device can also download an area itself over WiFi; this is
|
||||||
|
the offline / bulk option.
|
||||||
|
|
||||||
|
tools/maps/fetch_tiles.py --preset krakow --url URL --out /Volumes/SDCARD
|
||||||
|
tools/maps/fetch_tiles.py --bbox 19.90,50.04,19.98,50.08 --zoom 10-16 --url URL --out ./card
|
||||||
|
tools/maps/fetch_tiles.py --preset krakow --dry-run # count + size estimate
|
||||||
|
|
||||||
|
Tile source: --url (or TILE_URL) with {z}/{x}/{y}. There is deliberately no
|
||||||
|
default. Check the provider's terms before downloading an area:
|
||||||
|
- tile.openstreetmap.org forbids offline use and answers with an
|
||||||
|
"access blocked" image;
|
||||||
|
- OpenTopoMap (https://a.tile.opentopomap.org/{z}/{x}/{y}.png) tolerates
|
||||||
|
moderate use -- a town or a trip, not a country;
|
||||||
|
- keyed providers (MapTiler, Thunderforest, Stadia, ...) put the key in the
|
||||||
|
URL; their plans say whether offline caching is allowed;
|
||||||
|
- your own render server (e.g. from an OSM extract) has no limits.
|
||||||
|
--attribution is written to maps/attribution.txt; the device shows it on the
|
||||||
|
map, as the data licences require.
|
||||||
|
|
||||||
|
The tool stops if the server answers every tile with the same image (a
|
||||||
|
"blocked" or "API key required" placeholder).
|
||||||
|
|
||||||
|
Resumable (existing files are skipped), single connection, throttled.
|
||||||
|
--manifest also writes maps/manifest.json (the list of tiles), which the
|
||||||
|
browser simulator (variants/sim/web/lvgl.html) uses to preload them.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import urllib.error
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
PRESETS = {
|
||||||
|
# name: (lon_min, lat_min, lon_max, lat_max, z_min, z_max)
|
||||||
|
"krakow": (19.90, 50.04, 19.98, 50.08, 10, 16), # Old Town + Kazimierz; test set
|
||||||
|
"krakow-wide": (19.79, 49.97, 20.22, 50.13, 10, 15),
|
||||||
|
"tatry": (19.75, 49.15, 20.25, 49.32, 10, 15),
|
||||||
|
"warszawa": (20.85, 52.10, 21.20, 52.35, 10, 15),
|
||||||
|
"poland": (14.07, 49.00, 24.15, 54.84, 5, 9), # overview zooms only
|
||||||
|
}
|
||||||
|
|
||||||
|
USER_AGENT = "MeshCore-Solo-map-prep/1.0 (offline tiles for a LoRa handheld; throttled)"
|
||||||
|
|
||||||
|
|
||||||
|
def tile_xy(lon, lat, z):
|
||||||
|
n = 1 << z
|
||||||
|
x = int((lon + 180.0) / 360.0 * n)
|
||||||
|
lat_r = math.radians(max(min(lat, 85.0511), -85.0511))
|
||||||
|
y = int((1.0 - math.asinh(math.tan(lat_r)) / math.pi) / 2.0 * n)
|
||||||
|
return min(max(x, 0), n - 1), min(max(y, 0), n - 1)
|
||||||
|
|
||||||
|
|
||||||
|
def tiles_for(bbox, z_min, z_max):
|
||||||
|
lon_min, lat_min, lon_max, lat_max = bbox
|
||||||
|
for z in range(z_min, z_max + 1):
|
||||||
|
x0, y0 = tile_xy(lon_min, lat_max, z) # north-west corner
|
||||||
|
x1, y1 = tile_xy(lon_max, lat_min, z) # south-east corner
|
||||||
|
for x in range(x0, x1 + 1):
|
||||||
|
for y in range(y0, y1 + 1):
|
||||||
|
yield z, x, y
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
ap.add_argument("--preset", choices=sorted(PRESETS))
|
||||||
|
ap.add_argument("--bbox", help="lon_min,lat_min,lon_max,lat_max")
|
||||||
|
ap.add_argument("--zoom", help="z_min-z_max (default from preset, else 10-15)")
|
||||||
|
ap.add_argument("--out", default=".", help="folder that gets maps/ (e.g. the SD card root)")
|
||||||
|
ap.add_argument("--url", default=os.environ.get("TILE_URL"), help="tile URL template with {z} {x} {y}")
|
||||||
|
ap.add_argument("--attribution", default="\u00a9 OpenStreetMap contributors",
|
||||||
|
help="credit line shown on the device's map")
|
||||||
|
ap.add_argument("--delay", type=float, default=1.0, help="seconds between requests (default 1)")
|
||||||
|
ap.add_argument("--manifest", action="store_true", help="also write maps/manifest.json")
|
||||||
|
ap.add_argument("--dry-run", action="store_true")
|
||||||
|
a = ap.parse_args()
|
||||||
|
|
||||||
|
if a.preset:
|
||||||
|
*bbox, z_min, z_max = PRESETS[a.preset]
|
||||||
|
elif a.bbox:
|
||||||
|
bbox = [float(v) for v in a.bbox.split(",")]
|
||||||
|
z_min, z_max = 10, 15
|
||||||
|
else:
|
||||||
|
ap.error("give --preset or --bbox")
|
||||||
|
if a.zoom:
|
||||||
|
z_min, z_max = (int(v) for v in a.zoom.split("-"))
|
||||||
|
|
||||||
|
tiles = list(tiles_for(bbox, z_min, z_max))
|
||||||
|
print(f"{len(tiles)} tiles, z{z_min}-{z_max}, ~{len(tiles) * 25 // 1024} MB (at ~25 KB/tile)")
|
||||||
|
if a.dry_run:
|
||||||
|
return
|
||||||
|
if not a.url:
|
||||||
|
ap.error("give --url (see the provider notes in --help)")
|
||||||
|
|
||||||
|
root = os.path.join(a.out, "maps")
|
||||||
|
os.makedirs(root, exist_ok=True)
|
||||||
|
with open(os.path.join(root, "attribution.txt"), "w", encoding="utf-8") as f:
|
||||||
|
f.write(a.attribution + "\n")
|
||||||
|
got = skipped = failed = 0
|
||||||
|
seen = {} # payload -> count, over the first downloads: a placeholder repeats
|
||||||
|
for i, (z, x, y) in enumerate(tiles, 1):
|
||||||
|
path = os.path.join(root, str(z), str(x), f"{y}.png")
|
||||||
|
if os.path.exists(path) and os.path.getsize(path) > 0:
|
||||||
|
skipped += 1
|
||||||
|
continue
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
url = a.url.format(z=z, x=x, y=y)
|
||||||
|
for attempt in range(3):
|
||||||
|
try:
|
||||||
|
req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
|
||||||
|
with urllib.request.urlopen(req, timeout=20) as r:
|
||||||
|
data = r.read()
|
||||||
|
if got < 8:
|
||||||
|
seen[data] = seen.get(data, 0) + 1
|
||||||
|
if seen[data] >= 4:
|
||||||
|
sys.exit("stopped: the server returns the same image for different tiles "
|
||||||
|
"(blocked or API key required?) -- check --url; delete what was written")
|
||||||
|
with open(path + ".tmp", "wb") as f:
|
||||||
|
f.write(data)
|
||||||
|
os.replace(path + ".tmp", path)
|
||||||
|
got += 1
|
||||||
|
break
|
||||||
|
except (urllib.error.URLError, TimeoutError) as e:
|
||||||
|
if attempt == 2:
|
||||||
|
failed += 1
|
||||||
|
print(f" failed {z}/{x}/{y}: {e}", file=sys.stderr)
|
||||||
|
time.sleep(2 * (attempt + 1))
|
||||||
|
if i % 50 == 0:
|
||||||
|
print(f" {i}/{len(tiles)}")
|
||||||
|
time.sleep(a.delay)
|
||||||
|
|
||||||
|
if a.manifest:
|
||||||
|
listed = []
|
||||||
|
for dirpath, _, files in os.walk(root):
|
||||||
|
for fn in files:
|
||||||
|
if fn.endswith(".png") or fn == "attribution.txt":
|
||||||
|
listed.append(os.path.relpath(os.path.join(dirpath, fn), root).replace(os.sep, "/"))
|
||||||
|
with open(os.path.join(root, "manifest.json"), "w") as f:
|
||||||
|
json.dump(sorted(listed), f)
|
||||||
|
print(f"done: {got} downloaded, {skipped} already there, {failed} failed -> {root}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -12,6 +12,10 @@
|
|||||||
cd variants/sim/web && python3 -m http.server 8080
|
cd variants/sim/web && python3 -m http.server 8080
|
||||||
and open http://localhost:8080/lvgl.html .
|
and open http://localhost:8080/lvgl.html .
|
||||||
|
|
||||||
|
Map: tiles in web/maps (tools/maps/fetch_tiles.py --preset krakow --out
|
||||||
|
variants/sim/web --manifest) are copied into the L2's /sdcard/maps at boot,
|
||||||
|
and its GPS is put on Kraków's Old Town.
|
||||||
|
|
||||||
The mouse is the finger: press / drag / release on the LCD. Holding a key
|
The mouse is the finger: press / drag / release on the LCD. Holding a key
|
||||||
on the on-screen keyboard opens its accent popup, as on the device.
|
on the on-screen keyboard opens its accent popup, as on the device.
|
||||||
|
|
||||||
@@ -144,12 +148,31 @@
|
|||||||
inst.call('sim_test_disable_screen_timeout', 'number');
|
inst.call('sim_test_disable_screen_timeout', 'number');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map tiles listed in maps/manifest.json -> the instance's /sdcard/maps.
|
||||||
|
async function loadMaps(inst) {
|
||||||
|
let list;
|
||||||
|
try { list = await (await fetch('maps/manifest.json')).json(); }
|
||||||
|
catch (e) { log('no maps/manifest.json (map will be empty)'); return; }
|
||||||
|
const FS = inst.mod.FS;
|
||||||
|
await Promise.all(list.map(async (rel) => {
|
||||||
|
const buf = new Uint8Array(await (await fetch('maps/' + rel)).arrayBuffer());
|
||||||
|
const path = '/sdcard/maps/' + rel;
|
||||||
|
FS.mkdirTree(path.substring(0, path.lastIndexOf('/')));
|
||||||
|
FS.writeFile(path, buf);
|
||||||
|
}));
|
||||||
|
log('map: ' + list.length + ' tiles loaded');
|
||||||
|
}
|
||||||
|
|
||||||
async function bootL() {
|
async function bootL() {
|
||||||
document.getElementById('status-L').textContent = 'booting…';
|
document.getElementById('status-L').textContent = 'booting…';
|
||||||
if (L) L.call('sim_stop_main_loop', null);
|
if (L) L.call('sim_stop_main_loop', null);
|
||||||
L = wrap(await MeshCoreSimLvgl({ simInstanceTag: 'L' }), 'L');
|
L = wrap(await MeshCoreSimLvgl({ simInstanceTag: 'L' }), 'L');
|
||||||
const ok = await waitReady(L);
|
const ok = await waitReady(L);
|
||||||
if (ok) prepare(L);
|
if (ok) {
|
||||||
|
prepare(L);
|
||||||
|
L.call('sim_location_set', null, ['number', 'number', 'number'], [50.0614, 19.9372, 220]);
|
||||||
|
await loadMaps(L);
|
||||||
|
}
|
||||||
document.getElementById('status-L').textContent = ok ? 'ready' : 'boot timed out';
|
document.getElementById('status-L').textContent = ok ? 'ready' : 'boot timed out';
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user