diff --git a/docs/development/l2-hardware-checklist.md b/docs/development/l2-hardware-checklist.md index 9df0a33d..6ea6559b 100644 --- a/docs/development/l2-hardware-checklist.md +++ b/docs/development/l2-hardware-checklist.md @@ -8,7 +8,7 @@ Confirmed on the device: live share sends and receives positions. - [ ] Map: ☰ tools moved to the left column (back, pin, ☰); nothing overlaps the crosshair - [ ] Target ring sits exactly on the marker (all markers were drawn ~3 px low) - [ ] A person sharing on a channel, picked as target, is followed as they move (was a fixed point where they were); bar shows the person icon -- [ ] Settings: "Trail, live share, alerts" subtitle no longer covers the title (all list rows) +- [ ] Settings: subtitles no longer cover the titles (all list rows) - [ ] Map credit is a small "©" (tap: full line in a toast); full text also in Settings > About; long toasts wrap - [ ] Home: Messages, Nearby, Map, Settings — "Map" is the navigation map; the nodes map opens from Nearby's header (map icon), back returns to Nearby - [ ] Home tiles are wider; more apps will go on further swipeable pages (dots appear once there are two) @@ -66,6 +66,17 @@ Confirmed: green dot inside the ring, waypoints much better, download works, set - [ ] Room server login from the phone app / L1 still works while this exists (only admin logins go to the new session) - [ ] L1 (ui-new): Tools > Admin works as before (login, saved password, typed values, confirm reboot); it now also skips the login for the node you just used +## Roadmap stage 2: Arduino-ESP32 3.3.12 / IDF 5.5 (2026-09-26) +Env `Wio_Tracker_L2_companion_solo_lvgl_v3` (flash with `L2_ENV=Wio_Tracker_L2_companion_solo_lvgl_v3`). Bluetooth runs on NimBLE now, the speaker on the new I2S driver. Internal heap at runtime: 147.9 KB free on 3.x vs 147.8 KB on 2.0.17 (large UI buffers moved to PSRAM; static RAM 109 → 71 KB). +- [ ] Boots, screen and touch as before; WAKE and USER buttons +- [ ] Bluetooth: the app pairs with the PIN (asks for it: the link is encrypted), connects, syncs contacts and messages, sends; reconnects after the app is closed / reopened; the Bluetooth switch still works +- [ ] Sound: startup chime, message sounds, melody editor, volume; no new knocks +- [ ] LoRa: send / receive on a channel and a DM, adverts +- [ ] GPS fix, map, trail drawn on the map (its buffers moved to PSRAM) +- [ ] WiFi: scan, map download over HTTPS; the WiFi switch +- [ ] SD card: maps load, trail GPX export +- [ ] Settings / contacts / channels survive the update from the 2.0.17 build (same flash layout) + ## Roadmap stage 1: quick fixes (2026-09-26) - [ ] Keyboard: the keyboard key (bottom left) closes it; in a chat the typed text stays, in a dialog nothing is saved - [ ] Symbols page ("1#"): "_" is in the third row now @@ -79,7 +90,7 @@ Confirmed: green dot inside the ring, waypoints much better, download works, set - [ ] Chat "+" (left of the text field): Insert {loc} / {time} / {batt} (+ sensors) into the message; they are filled in when sent (a reply's "@[name] " stays as typed) - [ ] Chat "+" > a quick message sends it at once (the popup shows what will go out, filled in); "Edit quick messages" opens the list - [ ] Settings > Messages & contacts > Quick messages: 10 slots, tap to edit (field, placeholder chips, keyboard); empty clears; "OK" is there on a fresh device; the same slots as L1's Settings > Messages -- [ ] Settings > NODE > Send advert: Nearby only (zero-hop) / Everyone (flood through repeaters); another node sees you +- [ ] Nearby > advert button (tower icon) > Nearby only (zero-hop) / Everyone (flood through repeaters); another node sees you - [ ] Settings > CONNECTIVITY > Bluetooth: off / on; the row shows the pairing PIN while waiting, "the app is connected" when paired; USB keeps working with Bluetooth off; after a reboot Bluetooth is on again (as on L1) - [ ] Messages: "Read all" in the header while anything is unread - [ ] Nearby > a node with a position: flag button saves it as a waypoint; pin button puts a contact on the favourites dial; with five or more buttons they show icons only; delete asks with "trash?" and a toast @@ -119,10 +130,10 @@ The speaker plays through the ES8311 codec (I2S MCLK 10 / BCK 11 / WS 12 / DOUT - [ ] Settings > Display & power > TIME > Clock seconds off: Home and lock screen clocks show HH:MM; on: HH:MM:SS ## New: Diagnostics, auto-advert, compass (2026-09-25) -- [ ] Settings > SYSTEM > Diagnostics: tabs Live / System / Font; Live counters (uptime, rx/tx, heap, noise floor, RSSI/SNR, queue, errors) tick every second +- [ ] Home > Diagnostics (page 3): tabs Live / System / Font; Live counters (uptime, rx/tx, heap, noise floor, RSSI/SNR, queue, errors) tick every second - [ ] Live > Reset → confirm popup → "Counters reset", rx/tx and forwarded go back to 0 - [ ] System shows firmware, build date, board, node name, frequency / SF / BW / CR, TX power; Font shows Polish, Greek and Cyrillic samples without boxes -- [ ] Settings > Trail, live share, alerts > LIVE SHARE > Auto-advert 30 s: another node sees your advert (with position) every ~30 s; Off stops it; survives a reboot +- [ ] Nearby > advert button > AUTOMATIC > Auto-advert 30 s: another node sees your advert (with position) every ~30 s; Off stops it; survives a reboot - [ ] L1: Tools › Auto-Advert shows the value set on L2 (same pref), Tools › Diagnostics unchanged - [ ] Home page 2 > Compass: without a fix "Waiting for a GPS fix" (GPS off: hint to turn it on); standing still "Move to set the heading"; walking: dial turns so your course is under the amber pointer, degrees + cardinal on the right @@ -198,9 +209,9 @@ The speaker plays through the ES8311 codec (I2S MCLK 10 / BCK 11 / WS 12 / DOUT - [ ] ✕ on the bar clears the target - [ ] Waypoint menu (pencil): Go / Name (Polish letters, 11-byte limit) / Share / Delete (second tap confirms) - [ ] Share → Messages → pick a conversation → compose holds `[WAY]lat,lon name` → send; a Solo L1 receiving it can save it -- [ ] Settings > Trail, live share, alerts > "Show others' positions" on → someone's `[LOC]` share appears on the Map and in the list; tap → navigate to them +- [ ] Map > ☰ > Options > "Show others' positions" on → someone's `[LOC]` share appears on the Map and in the list; tap → navigate to them - [ ] Node detail (a node with a position) has the compass button → Map with that node as target -- [ ] Settings > … > "Arrival alert" on + target set → toast "Arrived: …" when you get within the radius +- [ ] Map > ☰ > Options > "Arrival alert" on + target set → toast "Arrived: …" when you get within the radius ## Positions in messages - [ ] A received message with `[WAY]lat,lon name`, `[LOC]lat,lon` or plain "lat, lon" shows Go / Save under the bubble @@ -209,7 +220,7 @@ The speaker plays through the ES8311 codec (I2S MCLK 10 / BCK 11 / WS 12 / DOUT ## Trail & live share (Map > ☰ tools button, left column) - [ ] Record → pill "REC 0 m" at the top; walk: blue trail line follows, distance grows -- [ ] Auto-pause (Settings > Trail, live share, alerts): standing still → "PAUSED", walking resumes +- [ ] Auto-pause (Map > ☰ > Options): standing still → "PAUSED", walking resumes - [ ] Stop / Save / Load / Reset (second tap confirms) behave; a trail saved on L2 loads (same /trail file as L1) - [ ] Export GPX → toast "Saved trails/trail-YYYYMMDD-HHMM.gpx"; the file opens in a GPX viewer (track + waypoints) - [ ] Live share: pick "Send to" (channel or favourite), Share live → pill "LIVE 1h00"; another node sees the [LOC] updates while you move; stops by itself after the chosen time @@ -218,8 +229,8 @@ The speaker plays through the ES8311 codec (I2S MCLK 10 / BCK 11 / WS 12 / DOUT - [ ] ☰ > Download this area opens the download popup - [ ] Waypoint averaging 5 s/10 s/30 s: pin → "Averaging GPS… n s" pill (tap cancels) → waypoint saved at the mean -## Settings > Trail, live share, alerts (schema-driven) -- [ ] Every row changes and survives a reboot; "Imperial units" relabels point spacing and distances +## Map > ☰ > Options (schema-driven) +- [ ] Every row changes and survives a reboot; Settings > Display & power > "Imperial units" relabels point spacing and distances - [ ] Changing "Stop sharing after" during a session restarts its clock - [ ] Radius / Alert on (arrive, leave, both) change when the arrival toast fires @@ -230,3 +241,13 @@ The speaker plays through the ES8311 codec (I2S MCLK 10 / BCK 11 / WS 12 / DOUT - [ ] L1: Tools › Trail Save / Load / Reset still work (now via TrailEngine) - [ ] L1: Mark with averaging (Trail › Settings › Mark avg) still counts down and marks - [ ] L1: Track back still advances along the trail and ends at the start + +## Roadmap stage 4: UI layout (2026-09-26) +- [ ] Home page 3: Repeater, Admin, Diagnostics tiles open their screens; back (arrow or USER button) returns to Home +- [ ] Home > Admin: repeaters and room servers listed, favourites (star) first; tap → login / admin tabs; back leaves to the list; with none heard yet a short note instead +- [ ] Settings order like L1: DISPLAY (Display & power), SOUND, RADIO (Radio, Bluetooth, WiFi), SYSTEM (Name, GPS, Reboot, Power off), KEYBOARD, CONTACTS & MESSAGES, ABOUT; no Repeater / Diagnostics / Send advert / trail rows left there +- [ ] Settings > Display & power: UNITS section with "Imperial units" +- [ ] Map > ☰ "Map tools": TRAIL, LIVE SHARE, ARRIVAL ALERT (On/Off with mode and radius), MAP; "Options: trail, sharing, alert" opens Map options; back returns to the map +- [ ] Nearby header: back, title, advert (tower), map, sort, scan (refresh icon) -- nothing overlaps; advert popup sends Nearby only / Everyone and sets Auto-advert +- [ ] Status bar, right to left next to the battery: Bluetooth (grey on, white with the app), GPS (grey searching, green fix), bell (alarm set), mute, then amber: auto-advert (tower), trail (route), live share (pin), repeater (loop), arrival alert (flag, with a target); each appears / disappears within a second of switching it +- [ ] All icons at once still leave the clock readable on the left diff --git a/docs/development/l2-roadmap.md b/docs/development/l2-roadmap.md index 6532e60b..2f5ed5f3 100644 --- a/docs/development/l2-roadmap.md +++ b/docs/development/l2-roadmap.md @@ -25,16 +25,22 @@ Decisions already made: ## 2. Arduino-ESP32 3.x, PSRAM -- [ ] A separate L2 env on pioarduino (as `esp32c6_base`); the 2.0.17 env - stays until the new one passes the hardware checklist. -- [ ] Port: speaker (new I2S driver), BLE, ESP-NOW, HTTPS map download, - LovyanGFX. -- [ ] Large buffers in PSRAM: message history, trail, tile cache. Measure - internal RAM before / after. +- [x] A separate L2 env on pioarduino 55.03.312-1 (Arduino-ESP32 3.3.12, + IDF 5.5): `Wio_Tracker_L2_companion_solo_lvgl_v3`; the 2.0.17 env stays + until the new one passes the hardware checklist. +- [x] Port: speaker (new I2S driver), BLE (NimBLE), ESP-NOW (IDF 5 callbacks); + HTTPS map download and LovyanGFX build unchanged (check on the device). +- [x] Large buffers in PSRAM (`psramBuf`): trail drawing, tile cache, map + marks, list rows, keyboard maps, message metadata. Internal heap free at + runtime: 2.0.17 147.8 KB; 3.x 128.2 KB before, 147.9 KB after (static RAM + 109 → 71 KB). Measured with `-D UI_HEAP_REPORT`. History and a larger + trail come to PSRAM with stage 3. - [ ] Full hardware checklist, then make the new env the default. ## 3. Data on the SD card +Postponed (2026-09-26): the user may extend this stage first. + - [ ] Message history on SD, kept across reboots (~100 per conversation; the newest ones cached in PSRAM). - [ ] Trail sized to the device: thousands of points in PSRAM (now 512), @@ -42,11 +48,19 @@ Decisions already made: ## 4. UI layout -- [ ] Every tool as its own Home tile (trail, live share, arrival alert, - repeater, admin, diagnostics, ...), not inside Settings. -- [ ] Settings in a sensible order, as on the original (L1). -- [ ] Every status icon the original has (BT, GPS, live share, trail, - repeater, alarm, mute, arrival alert, ...). +L1 splits its tools into many small screens because of the joystick and the +128x64 display; the L2 groups them where they are used instead. + +- [x] Tools: trail, live share and arrival alert stay in the map (its tools + popup, with their options behind "Options"); the advert (send now, + auto-advert) is in Nearby; Repeater, Admin (a list of repeaters and + room servers) and Diagnostics are Home tiles next to Favourites, + Compass, Clock and Bot. The melody editor stays in Sound. +- [x] Settings in L1's order: display, sound, radio (with Bluetooth, WiFi), + system, keyboard, contacts & messages. +- [x] Every status icon L1 has (Bluetooth, GPS, alarm, mute, auto-advert, + trail, live share, repeater) plus arrival alert; background modes in + the accent colour instead of L1's blinking. ## 5. Security and internet diff --git a/docs/development/ui-core.md b/docs/development/ui-core.md index 5ada9d95..e90d3cf5 100644 --- a/docs/development/ui-core.md +++ b/docs/development/ui-core.md @@ -110,7 +110,7 @@ call the same ones, so e.g. "marking a channel read" has one implementation. ### 5. Declarative settings schema -`ui-core/SettingsSchema.h` holds four pages -- navigation (trail, live share, arrival alert, units), display & power (brightness, screen off, wake on message, lock screen, battery display, battery shutdown, GPS power saving, time zone, 12-hour clock, clock seconds) messages & contacts (DM resends, contact expiry, favourites first) and sound (volume, the sound for direct messages / channels / adverts, advert sound scope). An entry is a one-byte index by default, or a `values` table over a 1/2/4-byte field (seconds, millivolts, an hour offset, `{1, 0}` for a field stored inverted); side effects run through `UiCore` (`applyGpsInterval()`, `host()->applyDisplayPrefs()`). ui-lvgl renders each page; ui-new still uses its own screens. Radio settings are not schema rows (preset list, typed frequency, radio side effects): `ui-core/RadioControl.h` applies them (`applyParams`, `applyTxPower`, `applyApc`, presets = built-ins + user slots) for both ui-new's Settings > Radio and ui-lvgl's Radio screen. Channel management is `ui-core/ChannelControl.h` (`chanctl::`): add Public / Hashtag / Private (passphrase or 32-hex key), rename, delete, notifications / favourite / scope, and `onRemoved()` -- the cleanup of every channel-keyed pref, run by `UiCore::onChannelRemoved` whoever deleted the channel (this device or the app); contacts get the same through `UiCore::cleanupContactPrefs`. Favourites dial slots: `ui-core/Favourites.h` (`pinContact` / `pinChannel` move an entry that is already on another slot; the slot's name is `contactctl::favName`). The schema's display page also carries the lock screen (`auto_lock`) and the 12-hour clock, which ui-lvgl implements (a slide-to-unlock card after the screen turns off). Remote admin is `ui-core/AdminSession.h` (`UiCore::admin`): login with the saved password (forgotten on a wrong password or a silent timeout), CLI round trips with timeouts, the field table (`admin::`), typed values; results come out one at a time through `take()`. `UiCore` offers login answers and CLI replies to it first; only room logins it wasn't waiting for reach the frontend. ui-new's Tools > Admin and ui-lvgl's Admin screen are views over it. The bot's settings are a table too, `ui-core/BotConfig.h` (`botcfg::`: tabs, rows, the NodePrefs flag / text / hour behind each, reply placeholders); ui-new's Tools > Bot and ui-lvgl's Bot screen render it, the bot itself runs in MyMesh. Room servers: `ui-core/RoomSessions.h` (`UiCore::rooms`) keeps who is logged in this session, the one login in flight (with a timeout) and the saved passwords (saved on success, forgotten on failure); `open(contact)` says whether to go straight in, wait for a background login or ask for a password, and outcomes come out through `take()`. Per-contact helpers are `ui-core/ContactControl.h` (`contactctl::`: DM notification / melody overrides, favourite flag, the `@[name] ` reply prefix, splitting a room post into author and text, naming a message's path hops). ui-new's Messages and ui-lvgl's Chats / thread use both. Diagnostics rows are `ui-core/Diagnostics.h` (`diag::`: live counters, system card, font card, counter reset), shown by ui-new's Tools > Diagnostics and ui-lvgl's Settings > Diagnostics. Auto-advert is a schema row (`advert_auto_interval_sec`, sent by MyMesh); ui-new keeps its Tools > Auto-Advert screen over the same pref. The compass (ui-lvgl Home > Compass, ui-new Tools > Compass) reads `UiCore::course`. Saving / deleting the user's radio presets is `radioctl::saveUserPreset` / `deleteUserPreset` (ui-new's preset picker and ui-lvgl's Radio > My presets); the scope list is edited through MyMesh (`addScope` / `renameScope` / `removeScope` / `setDefaultScope`), which ui-lvgl's Radio > Scopes and ui-new's Settings > Radio > Scope call directly. The battery percentage (LiPo curve, empty at the shutdown voltage) and the display mode are `ui-core/Battery.h`, used by both status bars; the schema carries Battery display and Clock seconds. The companion's own repeater mode is `ui-core/RepeaterControl.h` (`rptctl::`: on / off with its radio, RX power-save and APC side effects, Current / Custom network with the profile seeded from the chat params, the profile's preset, the filters' ranges and labels, the extra scopes mask); ui-new's Tools > Repeater and ui-lvgl's Settings > Repeater use it, MyMesh does the relaying. Sound is `ui-core/SoundControl.h` (`soundctl::`: the On / Off / Auto mode over `buzzer_quiet` + `buzzer_auto`, the volume with its preview, the built-in sounds, the two user melodies as an editable note list) and `ui-core/SoundNotifier.h` (which sound a message / advert plays: global choice, per-contact / per-channel alert and melody overrides); the schema's Sound page holds the volume and the PLAYS FOR choices, the channel melody override is `chanctl::melody`. Both frontends drive a `genericBuzzer`: a PWM piezo on L1, the ES8311 codec on the L2 (`BUZZER_I2S`: an audio task synthesises the notes and counts samples, the board powers the amp through `buzzerAmpPower()`). Outgoing text is `ui-core/MessageText.h` (`msgtext::`: the ten quick messages, the placeholders on offer -- `{loc}`, `{time}`, `{batt}`, live sensor readings -- and expanding them at send time, keeping a reply's `@[name] ` prefix as typed); ui-new's Messages / keyboard and ui-lvgl's compose "+" use it. `UiCore::markAllRead()` clears every unread counter; `MyMesh::advertFlood()` (formerly sim-only) sends the self-advert through repeaters, `advert()` zero-hop. ui-lvgl's screens share their widgets from `UITask.cpp`: `segmented()` (a one-of-N button row; `radioview::rowSegmented` puts one at the right of a settings row), `textField()` (a one-line field padded to exactly one line), `listRow`, `switchRow`, `headerButton`. +`ui-core/SettingsSchema.h` holds five pages -- map options (trail, live share, arrival alert; ui-lvgl opens it from the map's tools), advert (auto-advert; in ui-lvgl's Nearby advert popup), display & power (brightness, screen off, wake on message, lock screen, battery display, battery shutdown, GPS power saving, time zone, 12-hour clock, clock seconds, units) messages & contacts (DM resends, contact expiry, favourites first) and sound (volume, the sound for direct messages / channels / adverts, advert sound scope). An entry is a one-byte index by default, or a `values` table over a 1/2/4-byte field (seconds, millivolts, an hour offset, `{1, 0}` for a field stored inverted); side effects run through `UiCore` (`applyGpsInterval()`, `host()->applyDisplayPrefs()`). ui-lvgl renders each page (`schemaRows()` draws a page's rows into any container, a screen or a popup); ui-new still uses its own screens. Radio settings are not schema rows (preset list, typed frequency, radio side effects): `ui-core/RadioControl.h` applies them (`applyParams`, `applyTxPower`, `applyApc`, presets = built-ins + user slots) for both ui-new's Settings > Radio and ui-lvgl's Radio screen. Channel management is `ui-core/ChannelControl.h` (`chanctl::`): add Public / Hashtag / Private (passphrase or 32-hex key), rename, delete, notifications / favourite / scope, and `onRemoved()` -- the cleanup of every channel-keyed pref, run by `UiCore::onChannelRemoved` whoever deleted the channel (this device or the app); contacts get the same through `UiCore::cleanupContactPrefs`. Favourites dial slots: `ui-core/Favourites.h` (`pinContact` / `pinChannel` move an entry that is already on another slot; the slot's name is `contactctl::favName`). The schema's display page also carries the lock screen (`auto_lock`) and the 12-hour clock, which ui-lvgl implements (a slide-to-unlock card after the screen turns off). Remote admin is `ui-core/AdminSession.h` (`UiCore::admin`): login with the saved password (forgotten on a wrong password or a silent timeout), CLI round trips with timeouts, the field table (`admin::`), typed values; results come out one at a time through `take()`. `UiCore` offers login answers and CLI replies to it first; only room logins it wasn't waiting for reach the frontend. ui-new's Tools > Admin and ui-lvgl's Admin screen are views over it. The bot's settings are a table too, `ui-core/BotConfig.h` (`botcfg::`: tabs, rows, the NodePrefs flag / text / hour behind each, reply placeholders); ui-new's Tools > Bot and ui-lvgl's Bot screen render it, the bot itself runs in MyMesh. Room servers: `ui-core/RoomSessions.h` (`UiCore::rooms`) keeps who is logged in this session, the one login in flight (with a timeout) and the saved passwords (saved on success, forgotten on failure); `open(contact)` says whether to go straight in, wait for a background login or ask for a password, and outcomes come out through `take()`. Per-contact helpers are `ui-core/ContactControl.h` (`contactctl::`: DM notification / melody overrides, favourite flag, the `@[name] ` reply prefix, splitting a room post into author and text, naming a message's path hops). ui-new's Messages and ui-lvgl's Chats / thread use both. Diagnostics rows are `ui-core/Diagnostics.h` (`diag::`: live counters, system card, font card, counter reset), shown by ui-new's Tools > Diagnostics and ui-lvgl's Home > Diagnostics. Auto-advert is a schema row (`advert_auto_interval_sec`, sent by MyMesh); ui-new keeps its Tools > Auto-Advert screen over the same pref. The compass (ui-lvgl Home > Compass, ui-new Tools > Compass) reads `UiCore::course`. Saving / deleting the user's radio presets is `radioctl::saveUserPreset` / `deleteUserPreset` (ui-new's preset picker and ui-lvgl's Radio > My presets); the scope list is edited through MyMesh (`addScope` / `renameScope` / `removeScope` / `setDefaultScope`), which ui-lvgl's Radio > Scopes and ui-new's Settings > Radio > Scope call directly. The battery percentage (LiPo curve, empty at the shutdown voltage) and the display mode are `ui-core/Battery.h`, used by both status bars; the schema carries Battery display and Clock seconds. The companion's own repeater mode is `ui-core/RepeaterControl.h` (`rptctl::`: on / off with its radio, RX power-save and APC side effects, Current / Custom network with the profile seeded from the chat params, the profile's preset, the filters' ranges and labels, the extra scopes mask); ui-new's Tools > Repeater and ui-lvgl's Home > Repeater use it, MyMesh does the relaying. Sound is `ui-core/SoundControl.h` (`soundctl::`: the On / Off / Auto mode over `buzzer_quiet` + `buzzer_auto`, the volume with its preview, the built-in sounds, the two user melodies as an editable note list) and `ui-core/SoundNotifier.h` (which sound a message / advert plays: global choice, per-contact / per-channel alert and melody overrides); the schema's Sound page holds the volume and the PLAYS FOR choices, the channel melody override is `chanctl::melody`. Both frontends drive a `genericBuzzer`: a PWM piezo on L1, the ES8311 codec on the L2 (`BUZZER_I2S`: an audio task synthesises the notes and counts samples, the board powers the amp through `buzzerAmpPower()`). Outgoing text is `ui-core/MessageText.h` (`msgtext::`: the ten quick messages, the placeholders on offer -- `{loc}`, `{time}`, `{batt}`, live sensor readings -- and expanding them at send time, keeping a reply's `@[name] ` prefix as typed); ui-new's Messages / keyboard and ui-lvgl's compose "+" use it. `UiCore::markAllRead()` clears every unread counter; `MyMesh::advertFlood()` (formerly sim-only) sends the self-advert through repeaters, `advert()` zero-hop. ui-lvgl's screens share their widgets from `UITask.cpp`: `segmented()` (a one-of-N button row; `radioview::rowSegmented` puts one at the right of a settings row), `textField()` (a one-line field padded to exactly one line), `listRow`, `switchRow`, `headerButton`. Replaces the per-item code in `SettingsScreen`: diff --git a/examples/companion_radio/ui-core/SettingsSchema.h b/examples/companion_radio/ui-core/SettingsSchema.h index 996c1359..a56ef5fc 100644 --- a/examples/companion_radio/ui-core/SettingsSchema.h +++ b/examples/companion_radio/ui-core/SettingsSchema.h @@ -19,29 +19,31 @@ namespace settings { // Pages (one screen each) and the sections on them, in display order. -enum Page : uint8_t { PG_NAV, PG_DEVICE, PG_MESSAGES, PG_SOUND, PG_COUNT }; -enum Section : uint8_t { SEC_TRAIL, SEC_LIVE_SHARE, SEC_LOCATOR, SEC_UNITS, - SEC_DISPLAY, SEC_POWER, SEC_TIME, +// PG_NAV is the Map's options (its trail / live share / target tools), +// PG_ADVERT sits in Nearby's advert popup; the rest are Settings pages. +enum Page : uint8_t { PG_NAV, PG_ADVERT, PG_DEVICE, PG_MESSAGES, PG_SOUND, PG_COUNT }; +enum Section : uint8_t { SEC_TRAIL, SEC_LIVE_SHARE, SEC_LOCATOR, SEC_ADVERT, + SEC_DISPLAY, SEC_POWER, SEC_TIME, SEC_UNITS, SEC_MESSAGES, SEC_CONTACTS, SEC_SOUND, SEC_SOUND_FOR, SEC_COUNT }; static const char* pageTitle(uint8_t p) { - static const char* T[PG_COUNT] = { "Trail, live share, alerts", "Display & power", "Messages & contacts", "Sound" }; + static const char* T[PG_COUNT] = { "Map options", "Advert", "Display & power", "Messages & contacts", "Sound" }; return p < PG_COUNT ? T[p] : ""; } static const char* sectionTitle(uint8_t s) { - static const char* T[SEC_COUNT] = { "TRAIL", "LIVE SHARE", "ARRIVAL ALERT", "UNITS", - "DISPLAY", "POWER", "TIME", + static const char* T[SEC_COUNT] = { "TRAIL", "LIVE SHARE", "ARRIVAL ALERT", "AUTOMATIC", + "DISPLAY", "POWER", "TIME", "UNITS", "MESSAGES", "CONTACTS", "SOUND", "PLAYS FOR" }; return s < SEC_COUNT ? T[s] : ""; } static uint8_t sectionPage(uint8_t s) { - static const uint8_t P[SEC_COUNT] = { PG_NAV, PG_NAV, PG_NAV, PG_NAV, - PG_DEVICE, PG_DEVICE, PG_DEVICE, + static const uint8_t P[SEC_COUNT] = { PG_NAV, PG_NAV, PG_NAV, PG_ADVERT, + PG_DEVICE, PG_DEVICE, PG_DEVICE, PG_DEVICE, PG_MESSAGES, PG_MESSAGES, PG_SOUND, PG_SOUND }; - return s < SEC_COUNT ? P[s] : PG_NAV; + return s < SEC_COUNT ? P[s] : PG_DEVICE; } struct Setting { @@ -171,8 +173,6 @@ static const Setting ALL[] = { NodePrefs::LOC_SHARE_INTERVAL_COUNT, optGap, nullptr), IDX("Heartbeat", "Resend while standing still", SEC_LIVE_SHARE, loc_share_heartbeat_idx, NodePrefs::LOC_SHARE_HEARTBEAT_COUNT, optHeartbeat, nullptr), - MAP("Auto-advert", "Advert with your position", SEC_LIVE_SHARE, advert_auto_interval_sec, AUTO_ADVERT, - optAutoAdvert, nullptr), SW("Arrival alert", "When you reach the target", SEC_LOCATOR, locator_enabled, rearmLocator), IDX("Radius", nullptr, SEC_LOCATOR, locator_radius_idx, @@ -181,7 +181,8 @@ static const Setting ALL[] = { NodePrefs::LOCATOR_MODE_COUNT, optLocMode, rearmLocator), SW("Proximity beeper", "Ticks faster when closer", SEC_LOCATOR, locator_beeper, nullptr), - SW("Imperial units", "Miles and feet", SEC_UNITS, units_imperial, nullptr), + MAP("Auto-advert", "Advert with your position", SEC_ADVERT, advert_auto_interval_sec, AUTO_ADVERT, + optAutoAdvert, nullptr), IDX("Brightness", nullptr, SEC_DISPLAY, display_brightness, 5, optBrightness, applyDisplay), MAP("Screen off after", "Without a touch", SEC_DISPLAY, auto_off_secs, AUTO_OFF, optAutoOff, nullptr), @@ -197,6 +198,8 @@ static const Setting ALL[] = { SW("12-hour clock", "AM / PM instead of 24 h", SEC_TIME, clock_12h, nullptr), MAP("Clock seconds", "On the home clock", SEC_TIME, clock_hide_seconds, INVERTED, nullptr, nullptr), + SW("Imperial units", "Miles and feet", SEC_UNITS, units_imperial, nullptr), + IDX("Resend direct messages", "Retries without a tick", SEC_MESSAGES, dm_resend_count, 6, optResend, nullptr), diff --git a/examples/companion_radio/ui-lvgl/AdminScreen.h b/examples/companion_radio/ui-lvgl/AdminScreen.h index 3eaeefc6..7a134d2a 100644 --- a/examples/companion_radio/ui-lvgl/AdminScreen.h +++ b/examples/companion_radio/ui-lvgl/AdminScreen.h @@ -1,7 +1,7 @@ #pragma once -// Remote admin of a repeater / room server (node detail > Admin) -- ui-new's -// Tools > Admin. The session (login with the saved password, CLI round trips, -// timeouts, field table) is the UI Core's AdminSession; this draws it: +// Remote admin of a repeater / room server (node detail > Admin, or the Home +// tile's list) -- ui-new's Tools > Admin. The session (login with the saved +// password, CLI round trips, timeouts, field table) is the UI Core's AdminSession; this draws it: // password entry, tabs of fields, and a popup per field -- a switch, a // -/+ stepper, a row of choices (SF / bandwidth / coding rate), or a text // field with the keyboard (text, frequency, custom command); replies in a popup. @@ -62,12 +62,58 @@ static void onAdminChoice(lv_event_t* e) { static void onAdminPwKb(lv_event_t* e) { s_ui->adminLogin(lv_event_get_code(e) == LV_EVENT_READY); } static void onAdminTextKb(lv_event_t* e) { s_ui->adminTextDone(lv_event_get_code(e) == LV_EVENT_READY); } static void onAdminCancelWait(lv_event_t* e) { (void)e; s_ui->adminCancelWait(); } +static void onOpenAdminPick(lv_event_t* e) { (void)e; s_ui->showAdminPick(); } +static void onAdminPickRow(lv_event_t* e) { s_ui->adminPick((int)(uintptr_t)lv_event_get_user_data(e)); } + +namespace adminview { +static const int PICK_MAX = 64; +static uint8_t (*s_pick)[PUB_KEY_SIZE] = psramBuf(PICK_MAX); +} + +// Home > Admin: every repeater and room server, favourites first (ui-new's +// Tools > Admin picker); the session is the same as from node detail. +void UITask::showAdminPick() { + _screen = SCR_ADMIN_PICK; + buildAdminPick(); +} + +void UITask::buildAdminPick() { + lv_obj_t* body = newScreen("Admin", true); + int rows = 0; + for (int pass = 0; pass < 2; pass++) { + for (int i = 0; i < the_mesh.getNumContacts() && rows < adminview::PICK_MAX; i++) { + ContactInfo c; + if (!the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, c)) continue; + if (c.type != ADV_TYPE_REPEATER && c.type != ADV_TYPE_ROOM) continue; + bool fav = contactctl::favourite(c); + if (fav != (pass == 0)) continue; + if (!rows) sectionTitle(body, "LOG IN TO"); + char name[48]; + snprintf(name, sizeof(name), "%s%s", fav ? UI_SYMBOL_STAR " " : "", c.name); + memcpy(adminview::s_pick[rows], c.id.pub_key, PUB_KEY_SIZE); + listRow(body, name, c.type == ADV_TYPE_ROOM ? "Room server" : "Repeater", onAdminPickRow, (void*)(uintptr_t)rows); + rows++; + } + } + if (!rows) { + lv_obj_t* t = label(body, "No repeaters or room servers yet. They show up here once their advert is heard.", + THEME_FONT_BODY, theme::TEXT_MUTED); + lv_label_set_long_mode(t, LV_LABEL_LONG_WRAP); + lv_obj_set_width(t, LV_PCT(100)); + } +} + +void UITask::adminPick(int row) { + if (row < 0 || row >= adminview::PICK_MAX) return; + openAdmin(adminview::s_pick[row]); +} // Node detail > Admin. void UITask::openAdmin(const uint8_t* pub_key) { ContactInfo ci; if (!MessageHistory::contactByPrefix(pub_key, ci)) return; _core->admin.start(ci); + _admin_from_pick = _screen == SCR_ADMIN_PICK; adminview::s_tab = admin::TAB_SYSTEM; _screen = SCR_ADMIN; buildAdmin(); @@ -76,6 +122,7 @@ void UITask::openAdmin(const uint8_t* pub_key) { void UITask::adminLeave() { _core->admin.end(); navClosePopup(); + if (_admin_from_pick) { showAdminPick(); return; } _screen = SCR_NODE; buildNode(); } diff --git a/examples/companion_radio/ui-lvgl/NavMap.h b/examples/companion_radio/ui-lvgl/NavMap.h index e48cb2b0..6207cc5c 100644 --- a/examples/companion_radio/ui-lvgl/NavMap.h +++ b/examples/companion_radio/ui-lvgl/NavMap.h @@ -743,11 +743,12 @@ void UITask::shareToMessage(const char* text) { showToast("Pick a conversation to share it in"); } -// ── Tools panel: trail recording, live share, map download ──────────────────── +// ── Tools panel: trail recording, live share, arrival alert, map download, +// and their options (the schema's PG_NAV page) -- all of it lives with the map. namespace navmap { enum : uint8_t { TL_TRAIL_TOGGLE, TL_TRAIL_SAVE, TL_TRAIL_LOAD, TL_TRAIL_RESET, TL_TRAIL_GPX, TL_TRACKBACK, - TL_SHARE_TOGGLE, TL_SHARE_ONCE, TL_DOWNLOAD, + TL_SHARE_TOGGLE, TL_SHARE_ONCE, TL_DOWNLOAD, TL_OPTIONS, TL_WP_HERE, TL_WP_COORDS, TL_SPOT_ADD, TL_SPOT_GO }; // Live-share targets offered in the dropdown: channels, then favourite contacts. @@ -807,7 +808,7 @@ static lv_obj_t* toolButton(lv_obj_t* row, const char* text, uint8_t act, bool a } void UITask::navToolsPopup() { - lv_obj_t* panel = navPopupPanel("Trail & sharing", true); + lv_obj_t* panel = navPopupPanel("Map tools", true); lv_obj_t* list = lv_obj_create(panel); styleSurface(list, theme::BG); lv_obj_set_width(list, LV_PCT(100)); @@ -870,14 +871,20 @@ void UITask::navToolsPopup() { r = toolRow(list); _nav_share_btn = toolButton(r, "", navmap::TL_SHARE_TOGGLE, true); toolButton(r, LV_SYMBOL_UPLOAD " Send once", navmap::TL_SHARE_ONCE, false); - lv_obj_t* hint = label(list, "Timing and duration: Settings > Trail, live share, alerts.", THEME_FONT_SMALL, - theme::TEXT_MUTED); - lv_label_set_long_mode(hint, LV_LABEL_LONG_WRAP); - lv_obj_set_width(hint, LV_PCT(100)); + + sectionTitle(list, "ARRIVAL ALERT"); + char al[64], rad[12]; + uint16_t m = NodePrefs::locatorRadiusMeters(_prefs->locator_radius_idx); + geo::fmtDist(rad, sizeof(rad), m / 1000.0f, _prefs->units_imperial); + if (_prefs->locator_enabled) snprintf(al, sizeof(al), "On - %s, %s radius", NodePrefs::locatorModeLabel(_prefs->locator_mode), rad); + else snprintf(al, sizeof(al), "Off"); + label(list, al, THEME_FONT_SMALL, theme::TEXT); sectionTitle(list, "MAP"); r = toolRow(list); toolButton(r, LV_SYMBOL_DOWNLOAD " Download this area", navmap::TL_DOWNLOAD, false); + r = toolRow(list); + toolButton(r, LV_SYMBOL_SETTINGS " Options: trail, sharing, alert", navmap::TL_OPTIONS, false); _nav_reset_armed_ms = 0; refreshNavTools(); @@ -1028,6 +1035,9 @@ void UITask::navToolAction(uint8_t act) { navClosePopup(); mapDownloadPopup(); return; + case navmap::TL_OPTIONS: // back returns to the map + showSchemaSettings(settings::PG_NAV); + return; case navmap::TL_WP_HERE: navClosePopup(); navMarkHere(); diff --git a/examples/companion_radio/ui-lvgl/QuickScreen.h b/examples/companion_radio/ui-lvgl/QuickScreen.h index 29349d77..2bcacc27 100644 --- a/examples/companion_radio/ui-lvgl/QuickScreen.h +++ b/examples/companion_radio/ui-lvgl/QuickScreen.h @@ -180,16 +180,23 @@ void UITask::quickEditDone(bool ok) { } } -// ── Settings > Send advert ──────────────────────────────────────────────────── +// ── Nearby > advert ─────────────────────────────────────────────────────────── +// Shows you (and your position, if shared) to other nodes: now, or on a timer +// (the schema's PG_ADVERT page, ui-new's Tools > Auto-Advert). void UITask::advertPopup() { using namespace qview; - lv_obj_t* panel = navPopupPanel("Send advert", false); - lv_obj_t* t = label(panel, "Shows you (and your position, if shared) to other nodes.", THEME_FONT_SMALL, theme::TEXT_MUTED); - lv_label_set_long_mode(t, LV_LABEL_LONG_WRAP); - lv_obj_set_width(t, LV_PCT(100)); - listRow(panel, "Nearby only", "Direct range only", onAdvertGo, (void*)(uintptr_t)0); - listRow(panel, "Everyone", "Across the mesh", onAdvertGo, (void*)(uintptr_t)1); + lv_obj_t* panel = navPopupPanel("Advert", true); + lv_obj_t* list = lv_obj_create(panel); + styleSurface(list, theme::BG); + lv_obj_set_width(list, LV_PCT(100)); + lv_obj_set_flex_grow(list, 1); + lv_obj_set_flex_flow(list, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(list, theme::GAP, 0); + sectionTitle(list, "SEND NOW"); + listRow(list, "Nearby only", "Direct range only", onAdvertGo, (void*)(uintptr_t)0); + listRow(list, "Everyone", "Across the mesh", onAdvertGo, (void*)(uintptr_t)1); + schemaRows(list, settings::PG_ADVERT); } void UITask::advertSend(bool flood) { diff --git a/examples/companion_radio/ui-lvgl/RepeaterScreen.h b/examples/companion_radio/ui-lvgl/RepeaterScreen.h index e535b02a..7d9b6ec6 100644 --- a/examples/companion_radio/ui-lvgl/RepeaterScreen.h +++ b/examples/companion_radio/ui-lvgl/RepeaterScreen.h @@ -1,5 +1,5 @@ #pragma once -// Settings > Repeater -- ui-new's Tools > Repeater: relay other people's +// Home > Repeater -- ui-new's Tools > Repeater: relay other people's // messages from this device. The switch, the network it relays on (the // companion's own frequency, or a dedicated profile with its preset / freq / // SF / BW / CR), and the flood filters (adverts, hop limit, yield, min SNR, @@ -41,13 +41,6 @@ static void extraScopesSummary(const NodePrefs* p, char* b, int n) { else snprintf(b, n, "%d of %u relayed besides the default", rptctl::extraScopesPicked(p), (unsigned)sl.count); } -// Settings row: "Off", or what it relays on. -static void repeaterSummary(const NodePrefs* p, char* b, int n) { - if (!p->client_repeat) snprintf(b, n, "Off"); - else if (p->repeater_use_profile) snprintf(b, n, "On - own profile, %.3f MHz", p->repeater_freq); - else snprintf(b, n, "On - your chat frequency"); -} - void UITask::showRepeater() { _screen = SCR_REPEATER; buildRepeater(); diff --git a/examples/companion_radio/ui-lvgl/Theme.h b/examples/companion_radio/ui-lvgl/Theme.h index 16847a3a..eb4ffd48 100644 --- a/examples/companion_radio/ui-lvgl/Theme.h +++ b/examples/companion_radio/ui-lvgl/Theme.h @@ -40,4 +40,6 @@ namespace theme { #define UI_SYMBOL_STOPWATCH "\xEF\x8B\xB2" // U+F2F2 #define UI_SYMBOL_RADIO "\xEF\x94\x99" // U+F519, broadcast tower #define UI_SYMBOL_CHART "\xEF\x82\x80" // U+F080, diagnostics + #define UI_SYMBOL_KEY "\xEF\x82\x84" // U+F084, admin + #define UI_SYMBOL_ROUTE "\xEF\x93\x97" // U+F4D7, trail } diff --git a/examples/companion_radio/ui-lvgl/UITask.cpp b/examples/companion_radio/ui-lvgl/UITask.cpp index 1406b421..f27bcaed 100644 --- a/examples/companion_radio/ui-lvgl/UITask.cpp +++ b/examples/companion_radio/ui-lvgl/UITask.cpp @@ -473,9 +473,15 @@ void UITask::buildStatusBar() { _status_time = label(bar, "--:--", THEME_FONT_SMALL, theme::TEXT); lv_obj_align(_status_time, LV_ALIGN_LEFT_MID, 0, 0); - _status_icons = label(bar, "", THEME_FONT_SMALL, theme::TEXT_MUTED); - lv_obj_align(_status_icons, LV_ALIGN_RIGHT_MID, 0, 0); - _status_gps = label(bar, LV_SYMBOL_GPS, THEME_FONT_SMALL, theme::TEXT_MUTED); + _status_batt = label(bar, "", THEME_FONT_SMALL, theme::TEXT_MUTED); + lv_obj_align(_status_batt, LV_ALIGN_RIGHT_MID, 0, 0); + _status_icons = lv_obj_create(bar); + lv_obj_remove_style_all(_status_icons); + lv_obj_remove_flag(_status_icons, LV_OBJ_FLAG_CLICKABLE); + lv_obj_set_size(_status_icons, 200, LV_PCT(100)); // fixed: packed to its right edge + lv_obj_set_flex_flow(_status_icons, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(_status_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_style_pad_column(_status_icons, 7, 0); _toast = lv_obj_create(lv_layer_top()); lv_obj_remove_flag(_toast, LV_OBJ_FLAG_SCROLLABLE); @@ -519,23 +525,39 @@ void UITask::refreshStatusBar() { case battery::VOLTAGE: snprintf(level, sizeof(level), " %u.%02u V", mv / 1000, (mv % 1000) / 10); break; default: break; } - bool muted = false; -#ifdef PIN_BUZZER - muted = _buzzer.isQuiet(); -#endif - lv_label_set_text_fmt(_status_icons, "%s%s%s%s%s", muted ? LV_SYMBOL_MUTE " " : "", - _prefs && _prefs->client_repeat ? LV_SYMBOL_LOOP " " : "", - hasConnection() ? LV_SYMBOL_BLUETOOTH " " : "", batt, level); - // GPS: green with a fix, muted while on and searching, absent when off. + lv_label_set_text_fmt(_status_batt, "%s%s", batt, level); + + // Status icons, as the original's status bar (ui-new): Bluetooth (bright + // when the app is connected), GPS (green with a fix), the alarm, mute, then + // the modes that keep running in the background -- auto-advert, trail, live + // share, repeater, arrival alert -- in the accent colour. Right to left in + // that order, next to the battery. + struct Icon { const char* sym; uint32_t col; }; + Icon icons[10]; + int n = 0; + if (isSerialEnabled()) icons[n++] = { LV_SYMBOL_BLUETOOTH, hasConnection() ? theme::TEXT : theme::TEXT_MUTED }; int32_t lat, lon; bool fix = _core->course.currentLocation(lat, lon); - if (_core->gpsEnabled() || fix) { - lv_obj_set_style_text_color(_status_gps, lv_color_hex(fix ? theme::OK : theme::TEXT_MUTED), 0); - lv_obj_remove_flag(_status_gps, LV_OBJ_FLAG_HIDDEN); - lv_obj_align_to(_status_gps, _status_icons, LV_ALIGN_OUT_LEFT_MID, -8, 0); - } else { - lv_obj_add_flag(_status_gps, LV_OBJ_FLAG_HIDDEN); + if (_core->gpsEnabled() || fix) icons[n++] = { LV_SYMBOL_GPS, fix ? theme::OK : theme::TEXT_MUTED }; + if (_prefs && _prefs->alarm_on) icons[n++] = { LV_SYMBOL_BELL, theme::TEXT_MUTED }; +#ifdef PIN_BUZZER + if (_buzzer.isQuiet()) icons[n++] = { LV_SYMBOL_MUTE, theme::TEXT_MUTED }; +#endif + if (_prefs && _prefs->advert_auto_interval_sec > 0) icons[n++] = { UI_SYMBOL_RADIO, theme::ACCENT }; + if (_core->trail.isActive()) icons[n++] = { UI_SYMBOL_ROUTE, theme::ACCENT }; + if (_prefs && _prefs->loc_share_enabled) icons[n++] = { UI_SYMBOL_PIN, theme::ACCENT }; + if (_prefs && _prefs->client_repeat) icons[n++] = { LV_SYMBOL_LOOP, theme::ACCENT }; + if (_prefs && _prefs->locator_enabled && _prefs->locator_has_target) icons[n++] = { UI_SYMBOL_FLAG, theme::ACCENT }; + char sig[48]; + int o = 0; + for (int i = 0; i < n && o < (int)sizeof(sig) - 12; i++) o += snprintf(sig + o, sizeof(sig) - o, "%s%lx", icons[i].sym, (unsigned long)icons[i].col); + sig[o] = '\0'; + if (strcmp(sig, _status_sig) != 0) { // rebuilt only when something changed + strcpy(_status_sig, sig); + lv_obj_clean(_status_icons); + for (int i = n - 1; i >= 0; i--) label(_status_icons, icons[i].sym, THEME_FONT_SMALL, icons[i].col); } + lv_obj_align_to(_status_icons, _status_batt, LV_ALIGN_OUT_LEFT_MID, -8, 0); } void UITask::setGps(bool on) { @@ -641,11 +663,14 @@ void UITask::back() { case SCR_CHANNEL_EDIT: showChats(); break; case SCR_BOT: if (_nav_overlay) navClosePopup(); else showHome(); break; case SCR_FAVS: if (_nav_overlay) navClosePopup(); else showHome(); break; - case SCR_DIAG: if (_nav_overlay) navClosePopup(); else showSettings(); break; + case SCR_DIAG: if (_nav_overlay) navClosePopup(); else showHome(); break; + case SCR_ADMIN_PICK: showHome(); break; case SCR_COMPASS: showHome(); break; case SCR_ADMIN: if (_nav_overlay) navClosePopup(); else adminLeave(); break; case SCR_SETTINGS: if (_nav_overlay) navClosePopup(); else showHome(); break; - case SCR_SETTINGS_NAV: showSettings(); break; + case SCR_SETTINGS_NAV: // the map's options go back to the map + if (_settings_page == settings::PG_NAV) openMap(true); else showSettings(); + break; case SCR_QUICK: // back to Messages & contacts' bottom, where the row is if (_nav_overlay) { navClosePopup(); break; } showSchemaSettings(settings::PG_MESSAGES); @@ -666,7 +691,7 @@ void UITask::back() { case SCR_REPEATER: if (radioPopupOpen()) radioCloseFreq(); else if (_nav_overlay) navClosePopup(); - else showSettings(); + else showHome(); break; case SCR_SCOPES: // back to the Radio screen's bottom, where Scopes is if (_nav_overlay) { navClosePopup(); break; } @@ -675,7 +700,8 @@ void UITask::back() { break; case SCR_CHATS: if (_nav_overlay) navClosePopup(); else showHome(); break; case SCR_NEARBY: - if (_scan_overlay) closeScanPopup(); + if (_nav_overlay) navClosePopup(); // the advert popup + else if (_scan_overlay) closeScanPopup(); else showHome(); break; case SCR_NODE: // back to where the node was picked: map, the list, or the scan popup over it @@ -708,6 +734,8 @@ static void onOpenBot(lv_event_t* e); // BotScreen.h static void onOpenFavourites(lv_event_t* e); // DeviceScreen.h static void onOpenCompass(lv_event_t* e); // CompassScreen.h static void onOpenDiag(lv_event_t* e); // DiagScreen.h +static void onOpenRepeater(lv_event_t* e); // RepeaterScreen.h +static void onOpenAdminPick(lv_event_t* e); // AdminScreen.h static void onNodeName(lv_event_t* e); static void onPowerRow(lv_event_t* e); @@ -725,6 +753,11 @@ static const App APPS[] = { { UI_SYMBOL_COMPASS, "Compass", onOpenCompass, false }, { UI_SYMBOL_CLOCK, "Clock", onOpenClock, false }, { LV_SYMBOL_CHARGE, "Bot", onOpenBot, false }, + // Page 3: the device and the network (the map's tools and Nearby's advert + // are in those screens, not tiles of their own) + { LV_SYMBOL_LOOP, "Repeater", onOpenRepeater, false }, + { UI_SYMBOL_KEY, "Admin", onOpenAdminPick, false }, + { UI_SYMBOL_CHART, "Diagnostics", onOpenDiag, false }, }; static const int COUNT = sizeof(APPS) / sizeof(APPS[0]); static const int PER_PAGE = 4; @@ -1104,6 +1137,7 @@ enum : uint8_t { NODE_MSG, NODE_PING, NODE_FAV, NODE_ADD, NODE_DELETE, NODE_NAV, static void onNearbyChip(lv_event_t* e) { s_ui->setNearbyFilter((uint8_t)(uintptr_t)lv_event_get_user_data(e)); } static void onNearbySort(lv_event_t* e) { (void)e; s_ui->toggleNearbySort(); } static void onNearbyScan(lv_event_t* e) { (void)e; s_ui->startNearbyScan(); } +static void onAdvertRow(lv_event_t* e); // QuickScreen.h static void onNearbyRow(lv_event_t* e) { s_ui->openNode((int)(uintptr_t)lv_event_get_user_data(e)); } static void onScanRow(lv_event_t* e) { s_ui->openScanNode((int)(uintptr_t)lv_event_get_user_data(e)); } static void onScanClose(lv_event_t* e) { (void)e; s_ui->closeScanPopup(); } @@ -1135,9 +1169,10 @@ void UITask::buildNearby() { lv_obj_t* body = newScreen("Nearby", true); lv_obj_set_style_pad_row(body, 4, 0); if (_header) { - headerButton(_header, LV_SYMBOL_REFRESH " Scan", onNearbyScan, 4, NULL); - lv_obj_set_width(headerButton(_header, "", onNearbySort, 84, &_nearby_sort_lbl), 62); // fits "Recent" / "Dist" - headerButton(_header, UI_SYMBOL_MAP, onOpenNodesMap, 152, NULL); // the Nodes map + headerButton(_header, LV_SYMBOL_REFRESH, onNearbyScan, 4, NULL); // scan + lv_obj_set_width(headerButton(_header, "", onNearbySort, 46, &_nearby_sort_lbl), 62); // fits "Recent" / "Dist" + headerButton(_header, UI_SYMBOL_MAP, onOpenNodesMap, 114, NULL); // the Nodes map + headerButton(_header, UI_SYMBOL_RADIO, onAdvertRow, 156, NULL); // send advert, auto-advert } // Type filter chips @@ -2056,7 +2091,6 @@ static void onSchemaDropdown(lv_event_t* e) { } static void onOpenSchemaPage(lv_event_t* e) { s_ui->showSchemaSettings((int)(uintptr_t)lv_event_get_user_data(e)); } static void onPruneContacts(lv_event_t* e) { (void)e; s_ui->pruneContacts(); } -static void onAdvertRow(lv_event_t* e); // QuickScreen.h static void onOpenQuickMsgs(lv_event_t* e); static void bluetoothRow(lv_obj_t* body); static void onVolumeSlider(lv_event_t* e) { @@ -2113,10 +2147,32 @@ void UITask::buildSchemaSettings() { lv_obj_t* body = newScreen(settings::pageTitle(_settings_page), true); _prune_lbl = nullptr; _prune_armed_ms = 0; + schemaRows(body, _settings_page); + if (_settings_page == settings::PG_MESSAGES) { // the action that goes with "Contact expiry" + lv_obj_t* b = lv_button_create(body); + lv_obj_set_size(b, LV_PCT(100), 38); + lv_obj_set_style_shadow_width(b, 0, 0); + lv_obj_set_style_radius(b, theme::RADIUS, 0); + lv_obj_set_style_bg_color(b, lv_color_hex(theme::SURFACE), 0); + lv_obj_add_event_cb(b, onPruneContacts, LV_EVENT_CLICKED, NULL); + _prune_lbl = label(b, LV_SYMBOL_TRASH " Remove inactive contacts now", THEME_FONT_BODY, theme::TEXT); + lv_obj_center(_prune_lbl); + } + if (_settings_page == settings::PG_SOUND) buildSoundRows(body, false); // the melodies + if (_settings_page == settings::PG_MESSAGES) { + sectionTitle(body, "QUICK MESSAGES"); + char sub[48]; + snprintf(sub, sizeof(sub), "%d of %d set - sent with one tap", msgtext::quickUsed(_prefs), msgtext::QUICK_COUNT); + listRow(body, LV_SYMBOL_EDIT " Quick messages", sub, onOpenQuickMsgs, NULL); + } +} + +// A page's schema rows under their section titles (Settings pages and the tools' options). +void UITask::schemaRows(lv_obj_t* body, uint8_t page) { uint8_t sec = 0xFF; for (int i = 0; i < settings::COUNT; i++) { const settings::Setting& st = settings::ALL[i]; - if (settings::sectionPage(st.section) != _settings_page) continue; + if (settings::sectionPage(st.section) != page) continue; if (st.section != sec) { sec = st.section; sectionTitle(body, settings::sectionTitle(sec)); @@ -2187,23 +2243,6 @@ void UITask::buildSchemaSettings() { lv_obj_align(dd, LV_ALIGN_RIGHT_MID, -4, 0); lv_obj_add_event_cb(dd, onSchemaDropdown, LV_EVENT_VALUE_CHANGED, (void*)(uintptr_t)i); } - if (_settings_page == settings::PG_MESSAGES) { // the action that goes with "Contact expiry" - lv_obj_t* b = lv_button_create(body); - lv_obj_set_size(b, LV_PCT(100), 38); - lv_obj_set_style_shadow_width(b, 0, 0); - lv_obj_set_style_radius(b, theme::RADIUS, 0); - lv_obj_set_style_bg_color(b, lv_color_hex(theme::SURFACE), 0); - lv_obj_add_event_cb(b, onPruneContacts, LV_EVENT_CLICKED, NULL); - _prune_lbl = label(b, LV_SYMBOL_TRASH " Remove inactive contacts now", THEME_FONT_BODY, theme::TEXT); - lv_obj_center(_prune_lbl); - } - if (_settings_page == settings::PG_SOUND) buildSoundRows(body, false); // the melodies - if (_settings_page == settings::PG_MESSAGES) { - sectionTitle(body, "QUICK MESSAGES"); - char sub[48]; - snprintf(sub, sizeof(sub), "%d of %d set - sent with one tap", msgtext::quickUsed(_prefs), msgtext::QUICK_COUNT); - listRow(body, LV_SYMBOL_EDIT " Quick messages", sub, onOpenQuickMsgs, NULL); - } } void UITask::setSchemaValue(int idx, int v) { @@ -2226,46 +2265,40 @@ void UITask::showSettings() { } static void onOpenRadio(lv_event_t* e); // RadioScreen.h -static void onOpenRepeater(lv_event_t* e); // RepeaterScreen.h -static void repeaterSummary(const NodePrefs* p, char* b, int n); void UITask::buildSettings() { + // The order of the original (ui-new): display, sound, radio, system, + // keyboard, contacts and messages. Tools have their own Home tiles. lv_obj_t* body = newScreen("Settings", true); - sectionTitle(body, "NODE"); - listRow(body, LV_SYMBOL_EDIT " Name", the_mesh.getNodeName(), onNodeName, NULL); - listRow(body, UI_SYMBOL_RADIO " Send advert", "Let other nodes see you now", onAdvertRow, NULL); - sectionTitle(body, "CONNECTIVITY"); - bluetoothRow(body); - wifiRow(body); if (_prefs) { - char sub[48]; + sectionTitle(body, "DISPLAY"); + listRow(body, LV_SYMBOL_EYE_OPEN " Display & power", "Screen, battery, time, units", + onOpenSchemaPage, (void*)(uintptr_t)settings::PG_DEVICE); + sectionTitle(body, "SOUND"); + char sub[48], vol[12]; + settings::optVolume(_prefs->buzzer_volume, vol, sizeof(vol), *_prefs); + snprintf(sub, sizeof(sub), "%s, %s - alerts, melodies", soundctl::modeLabel(soundctl::mode(_prefs)), vol); + listRow(body, LV_SYMBOL_VOLUME_MAX " Sound", sub, onOpenSchemaPage, (void*)(uintptr_t)settings::PG_SOUND); + sectionTitle(body, "RADIO"); int pi = radioctl::currentPreset(_prefs); const char* pn = "Custom"; float f, b; uint8_t sf, cr; if (pi >= 0) radioctl::presetAt(_prefs, pi, pn, f, b, sf, cr); snprintf(sub, sizeof(sub), "%s - %.3f MHz, %d dBm", pn, _prefs->freq, _prefs->tx_power_dbm); listRow(body, UI_SYMBOL_RADIO " Radio", sub, onOpenRadio, NULL); - repeaterSummary(_prefs, sub, sizeof(sub)); - listRow(body, LV_SYMBOL_LOOP " Repeater", sub, onOpenRepeater, NULL); + } else { + sectionTitle(body, "RADIO"); } - if (_prefs) { // the same NodePrefs switches as ui-new's Home GPS toggle / Live share / Locator screens - sectionTitle(body, "NAVIGATION"); - if (_core->gpsAvailable()) { - lv_obj_t* sw = switchRow(body, "GPS", "For maps and sharing", nullptr); - if (_core->gpsEnabled()) lv_obj_add_state(sw, LV_STATE_CHECKED); - lv_obj_add_event_cb(sw, onGpsSwitch, LV_EVENT_VALUE_CHANGED, NULL); - } - listRow(body, UI_SYMBOL_COMPASS " Trail, live share, alerts", "Trail, sharing, alerts", - onOpenSchemaPage, (void*)(uintptr_t)settings::PG_NAV); - sectionTitle(body, "DEVICE"); - listRow(body, LV_SYMBOL_EYE_OPEN " Display & power", "Screen, battery, GPS, time", - onOpenSchemaPage, (void*)(uintptr_t)settings::PG_DEVICE); - listRow(body, LV_SYMBOL_ENVELOPE " Messages & contacts", "Resend, expiry, sorting", - onOpenSchemaPage, (void*)(uintptr_t)settings::PG_MESSAGES); - char sub[48], vol[12]; - settings::optVolume(_prefs->buzzer_volume, vol, sizeof(vol), *_prefs); - snprintf(sub, sizeof(sub), "%s, %s - alerts, melodies", soundctl::modeLabel(soundctl::mode(_prefs)), vol); - listRow(body, LV_SYMBOL_VOLUME_MAX " Sound", sub, onOpenSchemaPage, (void*)(uintptr_t)settings::PG_SOUND); + bluetoothRow(body); + wifiRow(body); + sectionTitle(body, "SYSTEM"); + listRow(body, LV_SYMBOL_EDIT " Name", the_mesh.getNodeName(), onNodeName, NULL); + if (_core->gpsAvailable()) { + lv_obj_t* sw = switchRow(body, "GPS", "For maps and sharing", nullptr); + if (_core->gpsEnabled()) lv_obj_add_state(sw, LV_STATE_CHECKED); + lv_obj_add_event_cb(sw, onGpsSwitch, LV_EVENT_VALUE_CHANGED, NULL); } + listRow(body, LV_SYMBOL_REFRESH " Reboot", NULL, onPowerRow, (void*)(uintptr_t)1); + listRow(body, LV_SYMBOL_POWER " Power off", NULL, onPowerRow, (void*)(uintptr_t)0); sectionTitle(body, "KEYBOARD"); uint8_t main_a = _prefs ? _prefs->keyboard_main_alphabet : 0; uint8_t alt_a = _prefs ? _prefs->keyboard_alt_alphabet : 0; @@ -2278,10 +2311,11 @@ void UITask::buildSettings() { alt_a == main_a ? 0 : alt_a + 1); label(body, "Hold a letter for accents and other variants.", THEME_FONT_SMALL, theme::TEXT_MUTED); - sectionTitle(body, "SYSTEM"); - listRow(body, UI_SYMBOL_CHART " Diagnostics", "Packets, memory, firmware", onOpenDiag, NULL); - listRow(body, LV_SYMBOL_REFRESH " Reboot", NULL, onPowerRow, (void*)(uintptr_t)1); - listRow(body, LV_SYMBOL_POWER " Power off", NULL, onPowerRow, (void*)(uintptr_t)0); + if (_prefs) { + sectionTitle(body, "CONTACTS & MESSAGES"); + listRow(body, LV_SYMBOL_ENVELOPE " Messages & contacts", "Resend, expiry, quick messages", + onOpenSchemaPage, (void*)(uintptr_t)settings::PG_MESSAGES); + } sectionTitle(body, "ABOUT"); char about[200], built[24] = ""; diff --git a/examples/companion_radio/ui-lvgl/UITask.h b/examples/companion_radio/ui-lvgl/UITask.h index efb73c34..a86e9640 100644 --- a/examples/companion_radio/ui-lvgl/UITask.h +++ b/examples/companion_radio/ui-lvgl/UITask.h @@ -45,6 +45,9 @@ public: void showContacts(); void showSettings(); void showSchemaSettings(int page); + // Home > Admin: the repeaters / room servers to log in to (AdminScreen.h) + void showAdminPick(); + void adminPick(int row); void pruneContacts(); void setBrightnessPct(uint8_t pct, bool save); void applyDisplayPrefs() override; @@ -222,7 +225,7 @@ public: void openAdminFor(const ContactInfo& ci, bool from_picker) { (void)ci; (void)from_picker; } private: - enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE, SCR_MAP, SCR_WIFI, SCR_SETTINGS_NAV, SCR_CLOCK, SCR_RADIO, SCR_CHANNEL_EDIT, SCR_ADMIN, SCR_BOT, SCR_FAVS, SCR_DIAG, SCR_COMPASS, SCR_SCOPES, SCR_REPEATER, SCR_MELODY, SCR_QUICK }; + enum Screen : uint8_t { SCR_HOME, SCR_CHATS, SCR_CONTACTS, SCR_THREAD, SCR_SETTINGS, SCR_NEARBY, SCR_NODE, SCR_MAP, SCR_WIFI, SCR_SETTINGS_NAV, SCR_CLOCK, SCR_RADIO, SCR_CHANNEL_EDIT, SCR_ADMIN, SCR_BOT, SCR_FAVS, SCR_DIAG, SCR_COMPASS, SCR_SCOPES, SCR_REPEATER, SCR_MELODY, SCR_QUICK, SCR_ADMIN_PICK }; void buildStatusBar(); void refreshStatusBar(); @@ -234,6 +237,8 @@ private: void buildContacts(); void buildSettings(); void buildSchemaSettings(); + void schemaRows(lv_obj_t* body, uint8_t page); + void buildAdminPick(); void buildNearby(); void refreshNearbyList(); uint32_t nearbySignature() const; @@ -341,6 +346,7 @@ private: uint32_t _next_trackback_ms = 0; uint32_t _next_clock_ms = 0; uint8_t _settings_page = 0; // settings::Page shown in SCR_SETTINGS_NAV + bool _admin_from_pick = false; // Admin opened from its Home tile (back returns there) uint32_t _prune_armed_ms = 0; uint16_t _batt_mv = 0; // smoothed, for the low-battery shutdown uint32_t _next_batt_ms = 0; @@ -355,8 +361,9 @@ private: // Widgets lv_obj_t* _status_time = nullptr; - lv_obj_t* _status_icons = nullptr; - lv_obj_t* _status_gps = nullptr; + lv_obj_t* _status_icons = nullptr; // a row of icon labels, rebuilt with the state + lv_obj_t* _status_batt = nullptr; + char _status_sig[48] = ""; // what the icon row shows, to skip unchanged rebuilds lv_obj_t* _toast = nullptr; lv_timer_t* _toast_timer = nullptr; lv_obj_t* _home_clock = nullptr; diff --git a/examples/companion_radio/ui-lvgl/fonts/generate.sh b/examples/companion_radio/ui-lvgl/fonts/generate.sh index 61625f65..17c84782 100755 --- a/examples/companion_radio/ui-lvgl/fonts/generate.sh +++ b/examples/companion_radio/ui-lvgl/fonts/generate.sh @@ -29,8 +29,9 @@ TEXT="$TEXT,0x2010-0x2027,0x2030,0x2039-0x203A,0x20A4-0x20BF,0x2116,0x2122" # plus 61612 = globe (keyboard script key), 61445 = star (favourite), # 62073 = map, 61632 = users (home tiles), 61774 = compass (Navigate), # 61476 = flag (waypoint), 62405 = map marker (mark here), 61463 = clock, -# 62194 = stopwatch, 62745 = broadcast tower (radio), 61568 = bar chart (diagnostics) -SYMS="61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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" +# 62194 = stopwatch, 62745 = broadcast tower (radio), 61568 = bar chart (diagnostics), +# 61572 = key (admin), 62679 = route (trail in the status bar) +SYMS="61572,62679,61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,61441,61448,61451,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650" CONV="npx -y lv_font_conv@1.5.3" gen() { # size weight ranges name diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c index 14c76117..4ae89156 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_12.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 12 px * 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 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 61572,62679,61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 @@ -6694,6 +6694,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xbb, 0x3f, 0x9f, 0x98, 0x24, 0x47, 0xf3, 0x91, 0xbb, 0xff, 0x40, + /* U+F084 "" */ + 0x0, 0xf3, 0xd5, 0x14, 0x3, 0xc3, 0xb0, 0xaa, + 0xab, 0x0, 0xea, 0x20, 0x5, 0x51, 0x1c, 0x2, + 0x14, 0x0, 0xa, 0xa8, 0x68, 0x2, 0x20, 0x8, + 0x5d, 0xc2, 0x40, 0x11, 0x0, 0x68, 0x80, 0x8, + 0x5, 0x60, 0x1f, 0x30, 0x2, 0x94, 0x3, 0xc7, + 0x1, 0x2a, 0x1, 0x88, 0xdf, 0x2, 0x58, 0x2, + 0x4a, 0xdc, 0x80, 0x3, 0x0, 0x68, 0x50, 0xf, + 0xc7, 0xc6, 0x1, 0xe7, 0x66, 0x48, 0x80, 0x7c, + /* U+F093 "" */ 0x0, 0xe2, 0x20, 0x7, 0xf1, 0xe6, 0xc, 0x3, 0xe3, 0xd1, 0x16, 0x98, 0x7, 0x1e, 0x88, 0x0, @@ -6956,6 +6966,17 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x80, 0x5c, 0x1, 0x70, 0x6, 0x37, 0x7, 0x30, 0xe, 0x8a, 0x80, 0x8, + /* U+F4D7 "" */ + 0x0, 0xfc, 0x2e, 0xa0, 0x1f, 0x87, 0xa2, 0xa4, + 0x3, 0xe6, 0xc, 0x56, 0x0, 0xf8, 0xc2, 0x50, + 0xc0, 0x3e, 0x43, 0x51, 0x80, 0xe, 0x1b, 0xf3, + 0x6, 0x40, 0x57, 0x10, 0x84, 0x77, 0x44, 0x84, + 0xd4, 0x70, 0x90, 0xc4, 0x1c, 0x0, 0xcb, 0x80, + 0xdc, 0x3f, 0xf6, 0x99, 0x92, 0x40, 0xd7, 0x21, + 0xdc, 0x7d, 0x2, 0xa6, 0x80, 0x6f, 0x10, 0x42, + 0x46, 0xf, 0xef, 0xfe, 0x56, 0x9, 0xc7, 0x67, + 0x7d, 0x15, 0x20, + /* U+F519 "" */ 0x14, 0x0, 0xff, 0x90, 0x62, 0xc0, 0x3f, 0xeb, 0x84, 0x50, 0x97, 0x5, 0xb5, 0x7, 0x90, 0x54, @@ -8056,38 +8077,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 32776, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 32796, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 32839, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 32896, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 32960, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33030, .adv_w = 240, .box_w = 15, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33104, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33165, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33205, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33249, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33281, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33320, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 33366, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33411, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33464, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33520, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 33583, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33655, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 33678, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 33753, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33796, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33845, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33894, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33943, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 33985, .adv_w = 216, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 34022, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 34087, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34151, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34194, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34255, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 34322, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34374, .adv_w = 240, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34456, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 34511, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 34540, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 32903, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32960, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 33024, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33094, .adv_w = 240, .box_w = 15, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33168, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33229, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33269, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33313, .adv_w = 168, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33345, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33384, .adv_w = 120, .box_w = 9, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 33430, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33475, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33528, .adv_w = 216, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33584, .adv_w = 192, .box_w = 14, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 33647, .adv_w = 186, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33719, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33742, .adv_w = 240, .box_w = 15, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33817, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33860, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33909, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33958, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 34007, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 34049, .adv_w = 216, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34086, .adv_w = 240, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34151, .adv_w = 168, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34215, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34258, .adv_w = 168, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34319, .adv_w = 192, .box_w = 13, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 34386, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34438, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34505, .adv_w = 240, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34587, .adv_w = 240, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 34642, .adv_w = 144, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34671, .adv_w = 193, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -8116,11 +8139,11 @@ static const uint16_t unicode_list_12[] = { 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, - 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, - 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, - 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, - 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, - 0xd78c + 0xcf6e, 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, + 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, + 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, + 0xd171, 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd3c1, 0xd403, + 0xd444, 0xd6ac, 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -8176,7 +8199,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 75, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -8324,7 +8347,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 }; /*Map glyph_ids to kern right classes*/ @@ -8466,7 +8489,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 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c index 1dfa1a22..4c52a359 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_14.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 14 px * 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 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 61572,62679,61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 @@ -7629,6 +7629,18 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x23, 0x60, 0x1, 0xe6, 0x7f, 0xd6, 0x60, 0x67, 0xff, 0x20, + /* U+F084 "" */ + 0x0, 0xfc, 0x46, 0x20, 0x1f, 0xcd, 0xdb, 0x9d, + 0x42, 0x1, 0xe8, 0x91, 0x0, 0x97, 0x0, 0x38, + 0x9c, 0x2, 0x8f, 0x82, 0x80, 0xc, 0xa0, 0x18, + 0xc0, 0xc1, 0x80, 0x37, 0x0, 0x6b, 0xb8, 0x4, + 0x3, 0x70, 0x7, 0x20, 0x0, 0x80, 0x21, 0xa0, + 0xf, 0xca, 0x0, 0x1c, 0x20, 0xf, 0x8e, 0x0, + 0x70, 0x80, 0x3e, 0x6c, 0x1, 0xc2, 0x0, 0xc7, + 0xba, 0xf9, 0x0, 0x61, 0x0, 0x6d, 0xc2, 0x20, + 0x6, 0x20, 0x8, 0x90, 0x80, 0x3f, 0xe8, 0xb0, + 0xf, 0xd2, 0xef, 0x20, 0x7, 0xf0, + /* U+F093 "" */ 0x0, 0xff, 0xe3, 0x8e, 0xe8, 0x40, 0x3f, 0x87, 0x8, 0x98, 0x20, 0x1f, 0xe, 0x10, 0x0, 0xb0, @@ -7938,6 +7950,19 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x3d, 0x42, 0x16, 0x20, 0x1e, 0x1a, 0x85, 0x0, 0xc0, + /* U+F4D7 "" */ + 0x0, 0xff, 0x84, 0x3, 0xfe, 0x4e, 0xe6, 0x90, + 0x7, 0xf5, 0x8a, 0x17, 0x0, 0x7e, 0x30, 0x6b, + 0x23, 0x0, 0xfc, 0x62, 0xda, 0x4a, 0x1, 0xfd, + 0x60, 0x41, 0x0, 0x1f, 0x57, 0xd0, 0x2, 0x48, + 0x0, 0x62, 0x0, 0x95, 0x23, 0x33, 0xb0, 0x1f, + 0x67, 0x30, 0x20, 0x6e, 0x62, 0x0, 0x1e, 0x34, + 0x52, 0x28, 0x19, 0x76, 0xa6, 0x3, 0x14, 0x70, + 0x38, 0x43, 0x44, 0x2c, 0xba, 0x8f, 0x29, 0x10, + 0x6f, 0xfe, 0xe1, 0x98, 0x0, 0xa0, 0x3, 0xf8, + 0xa4, 0x14, 0x7f, 0xfd, 0xc2, 0xc0, 0xd1, 0x7c, + 0x67, 0xe4, 0x98, + /* U+F519 "" */ 0x2, 0x0, 0xff, 0xe0, 0x88, 0x81, 0xb5, 0x80, 0x3f, 0xf8, 0x19, 0xc1, 0xa0, 0xe2, 0xc2, 0x0, @@ -9048,38 +9073,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 40252, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 40281, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 40331, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40403, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 40482, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40575, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40673, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40754, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 40802, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40858, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 40898, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 40951, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 41007, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41070, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41136, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41209, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 41286, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41375, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41407, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41504, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41556, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41611, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41666, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41721, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41770, .adv_w = 252, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41815, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 41895, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 41979, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42035, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42100, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 42177, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42250, .adv_w = 280, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42365, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 42443, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 42479, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 40409, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40481, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 40560, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40653, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40751, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40832, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40880, .adv_w = 196, .box_w = 13, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40936, .adv_w = 196, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40976, .adv_w = 224, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41029, .adv_w = 140, .box_w = 10, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 41085, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41148, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41214, .adv_w = 252, .box_w = 16, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41287, .adv_w = 224, .box_w = 16, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 41364, .adv_w = 217, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41453, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41485, .adv_w = 280, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41582, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41634, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41689, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41744, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41799, .adv_w = 280, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 41848, .adv_w = 252, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41893, .adv_w = 280, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41973, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42057, .adv_w = 196, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42113, .adv_w = 196, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42178, .adv_w = 224, .box_w = 15, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 42255, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42328, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42411, .adv_w = 280, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42526, .adv_w = 280, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 42604, .adv_w = 168, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42640, .adv_w = 225, .box_w = 15, .box_h = 10, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -9108,11 +9135,11 @@ static const uint16_t unicode_list_12[] = { 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, - 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, - 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, - 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, - 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, - 0xd78c + 0xcf6e, 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, + 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, + 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, + 0xd171, 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd3c1, 0xd403, + 0xd444, 0xd6ac, 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -9168,7 +9195,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 75, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -9316,7 +9343,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 }; /*Map glyph_ids to kern right classes*/ @@ -9458,7 +9485,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 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c index 21601745..1d59d136 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_16.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 16 px * 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 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 61572,62679,61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 @@ -8719,6 +8719,20 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xf8, 0x3f, 0xc0, 0x1f, 0xfc, 0x7f, 0xff, 0xfe, 0xf, 0x18, 0x7, 0xff, 0xc, + /* U+F084 "" */ + 0x0, 0xf8, 0xa7, 0x7f, 0xa4, 0x80, 0x3f, 0x26, + 0xb1, 0x0, 0xb6, 0xa0, 0x7, 0x8a, 0xc0, 0x32, + 0xa8, 0x2c, 0x80, 0x3a, 0xc0, 0x32, 0xd5, 0x14, + 0x2c, 0x3, 0x90, 0x3, 0xf9, 0xc0, 0x38, 0x80, + 0x32, 0xd5, 0x14, 0x4, 0x3, 0x84, 0x3, 0x95, + 0x40, 0x1, 0x0, 0xc2, 0x1, 0xfe, 0x70, 0x8, + 0x7c, 0x40, 0x3f, 0xac, 0x0, 0x3e, 0x20, 0x1f, + 0xd6, 0x40, 0x3e, 0x20, 0x1f, 0xb, 0x6a, 0x0, + 0xf8, 0x80, 0x71, 0x77, 0xf4, 0x90, 0x3, 0x4, + 0x3, 0xbf, 0x44, 0x3, 0xc4, 0x1, 0xc4, 0x1, + 0xff, 0xc2, 0xfd, 0x0, 0xfe, 0x20, 0x8, 0x80, + 0x3f, 0xe0, + /* U+F093 "" */ 0x0, 0xfa, 0xec, 0x1, 0xff, 0xc1, 0xb4, 0x45, 0x80, 0x7f, 0xd6, 0x80, 0x4, 0xb0, 0xf, 0xeb, @@ -9049,6 +9063,20 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x78, 0xa0, 0x1, 0x4, 0x1, 0xf3, 0xa2, 0x1c, 0x3, 0x0, + /* U+F4D7 "" */ + 0x0, 0xff, 0xa3, 0xb9, 0x0, 0x1f, 0xf4, 0x38, + 0x89, 0xe0, 0x3, 0xfc, 0xc1, 0x98, 0x6, 0x0, + 0xff, 0xe7, 0x30, 0x66, 0x2, 0x40, 0x3f, 0xd0, + 0x20, 0x1, 0x70, 0xf, 0xd1, 0xde, 0x20, 0xd, + 0x0, 0xfd, 0xe, 0x20, 0x14, 0x98, 0x2, 0x3b, + 0x90, 0x0, 0x60, 0xcf, 0xf9, 0x80, 0x10, 0xe2, + 0x27, 0x80, 0xf, 0xf3, 0x6, 0x60, 0x18, 0x18, + 0x33, 0xfe, 0xe8, 0x0, 0xfd, 0xe, 0x20, 0x10, + 0xbc, 0x48, 0x66, 0x2, 0x40, 0x11, 0xdf, 0xf6, + 0x3, 0x39, 0x0, 0x5, 0xc0, 0x3f, 0xee, 0x0, + 0x6c, 0xff, 0xfd, 0x80, 0xc0, 0x73, 0x26, 0x60, + 0x7, 0xc2, 0xf0, + /* U+F519 "" */ 0x3f, 0xc0, 0xf, 0xfe, 0x16, 0x79, 0xd0, 0x58, 0x7, 0xff, 0x9, 0x2, 0x90, 0x14, 0x2f, 0xc8, @@ -10164,38 +10192,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 48992, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 49021, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 49058, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49126, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 49220, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49328, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49438, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49529, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49576, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49628, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 49683, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 49742, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 49810, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49871, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 49941, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 50007, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 50096, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50198, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50231, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 50344, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50389, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50433, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50477, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 49148, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49216, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49310, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49418, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49528, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49619, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49666, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49718, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49773, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 49832, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49900, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49961, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50031, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 50097, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 50186, .adv_w = 248, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50288, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50321, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50434, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50479, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 50523, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 50563, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50622, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 50723, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 50819, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50874, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 50956, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 51050, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 51132, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 51263, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 51352, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 51391, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 50567, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50613, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 50653, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50712, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50813, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 50909, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50964, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51046, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 51140, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51222, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51313, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 51444, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 51533, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51572, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} }; /*--------------------- @@ -10224,11 +10254,11 @@ static const uint16_t unicode_list_12[] = { 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, - 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, - 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, - 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, - 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, - 0xd78c + 0xcf6e, 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, + 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, + 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, + 0xd171, 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd3c1, 0xd403, + 0xd444, 0xd6ac, 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -10284,7 +10314,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 75, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -10432,7 +10462,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 }; /*Map glyph_ids to kern right classes*/ @@ -10574,7 +10604,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 }; /*Kern values between classes*/ diff --git a/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c b/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c index 77a24a30..5e833d94 100644 --- a/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c +++ b/examples/companion_radio/ui-lvgl/fonts/ui_font_20.c @@ -1,7 +1,7 @@ /******************************************************************************* * Size: 20 px * 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 61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 61572,62679,61568,62745,61463,62194,61612,61445,62073,61632,61774,61476,62405,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 @@ -10966,6 +10966,25 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xff, 0x11, 0x80, 0x6, 0xef, 0xff, 0xc4, 0x95, 0x0, 0xff, 0xe3, 0x8, + /* U+F084 "" */ + 0x0, 0xff, 0x84, 0xcc, 0x40, 0x1f, 0xfc, 0x23, + 0xbe, 0xcc, 0x6e, 0x98, 0x3, 0xfe, 0x7c, 0x40, + 0xc, 0x53, 0x60, 0x1f, 0xcd, 0x0, 0x1c, 0x22, + 0x4, 0xa0, 0xf, 0xd2, 0x1, 0xcd, 0xdc, 0x60, + 0x54, 0x0, 0xf3, 0x0, 0x7a, 0xc0, 0x16, 0x0, + 0xf0, 0xf, 0x78, 0x7, 0xa8, 0x1, 0x40, 0x5, + 0x0, 0xf1, 0x0, 0x79, 0xf7, 0x4e, 0x0, 0x10, + 0xf, 0x8, 0x7, 0xc4, 0x40, 0x8, 0x40, 0x3c, + 0x40, 0x1f, 0xfc, 0x4, 0x0, 0xe5, 0x70, 0xf, + 0xfe, 0x4, 0x80, 0x65, 0xa0, 0xf, 0xfe, 0x3, + 0x98, 0x4, 0xb4, 0x1, 0xff, 0xc0, 0x68, 0x0, + 0x96, 0x80, 0x3f, 0xe4, 0xb9, 0x0, 0x9a, 0x80, + 0x3f, 0x4f, 0x73, 0xed, 0x0, 0x26, 0x90, 0xf, + 0x14, 0xdb, 0x8, 0x80, 0x3d, 0x20, 0x1f, 0x33, + 0x10, 0x3, 0xff, 0x86, 0x22, 0xc0, 0xf, 0xfe, + 0x2d, 0x73, 0x80, 0x7f, 0xf1, 0x5c, 0x3, 0xff, + 0x83, 0x93, 0x3a, 0x8c, 0x3, 0xff, 0x82, + /* U+F093 "" */ 0x0, 0xfe, 0x31, 0x0, 0xff, 0xe2, 0xb6, 0x60, 0x40, 0x3f, 0xf8, 0x6d, 0x20, 0x58, 0x20, 0x1f, @@ -11426,6 +11445,28 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xe6, 0x40, 0x46, 0x0, 0xff, 0xaa, 0x28, 0x3, 0xc0, + /* U+F4D7 "" */ + 0x0, 0xff, 0xe1, 0xb, 0x3a, 0x0, 0x7f, 0xf0, + 0xd3, 0xa6, 0x2e, 0xc0, 0x1f, 0xfc, 0x11, 0xb0, + 0xc, 0x90, 0x1, 0xff, 0xc0, 0x70, 0x5, 0x71, + 0x83, 0x0, 0x7f, 0xf0, 0x4, 0x0, 0x82, 0xa0, + 0x1f, 0xfc, 0x25, 0x0, 0x6c, 0xb0, 0x20, 0x7, + 0xff, 0x0, 0x94, 0xd, 0x80, 0x12, 0x1, 0xff, + 0xc1, 0xb0, 0xc, 0xc6, 0x1, 0xfe, 0x6d, 0xfe, + 0x0, 0x8a, 0x40, 0x3f, 0xcf, 0x24, 0x1, 0xde, + 0x1, 0x91, 0xd8, 0x40, 0x28, 0x1, 0x77, 0xd8, + 0x40, 0x15, 0xda, 0x27, 0x90, 0xc, 0x1, 0x71, + 0x18, 0xc0, 0x28, 0x40, 0xd, 0x62, 0x20, 0x6, + 0x0, 0x7e, 0x60, 0x3e, 0xa0, 0x3, 0x91, 0x83, + 0x7f, 0xf6, 0x18, 0x8, 0x28, 0xa0, 0x6, 0xe2, + 0x0, 0xf1, 0xe1, 0xa8, 0x34, 0xe8, 0x1, 0x0, + 0xb6, 0xa1, 0xde, 0x60, 0x7, 0xc8, 0x1, 0x8c, + 0x14, 0x80, 0x25, 0x78, 0x8a, 0x58, 0xc, 0xcc, + 0x1, 0xac, 0x3, 0xf8, 0x54, 0x4, 0x24, 0x80, + 0x12, 0x7f, 0xff, 0xdc, 0x60, 0xc0, 0xf, 0x6, + 0x67, 0x80, 0x7f, 0xc9, 0x0, 0x2, 0xc9, 0x35, + 0x77, 0xfe, 0x8b, 0xb0, 0x0, + /* U+F519 "" */ 0x3, 0x41, 0x0, 0xff, 0xe2, 0x8a, 0x18, 0x16, 0x5c, 0x80, 0x7f, 0xf1, 0x66, 0xf0, 0xa8, 0x1, @@ -12557,38 +12598,40 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 66699, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 66743, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 66819, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 66929, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 67067, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 67226, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67395, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67543, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 67616, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 67709, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 67769, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 67859, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 67952, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68040, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68151, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 68277, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 68398, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68549, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 68597, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 68761, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 68828, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 66954, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 67064, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 67202, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 67361, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67530, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67678, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 67751, .adv_w = 280, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 67844, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 67904, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 67994, .adv_w = 200, .box_w = 14, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 68087, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68175, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68286, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 68412, .adv_w = 320, .box_w = 22, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 68533, .adv_w = 310, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68684, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 68732, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, {.bitmap_index = 68896, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 68963, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 69030, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 69090, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 69177, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 69311, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 69458, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69545, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69674, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 69814, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 69927, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 70131, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 70251, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 70310, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 69031, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 69098, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 69165, .adv_w = 400, .box_w = 25, .box_h = 13, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 69225, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 69312, .adv_w = 400, .box_w = 26, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 69446, .adv_w = 280, .box_w = 16, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 69593, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 69680, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 69809, .adv_w = 320, .box_w = 21, .box_h = 21, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 69949, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70062, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70219, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70423, .adv_w = 400, .box_w = 25, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 70543, .adv_w = 240, .box_w = 15, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 70602, .adv_w = 322, .box_w = 21, .box_h = 13, .ofs_x = 0, .ofs_y = 1} }; /*--------------------- @@ -12617,11 +12660,11 @@ static const uint16_t unicode_list_12[] = { 0xcf10, 0xcf11, 0xcf12, 0xcf28, 0xcf2d, 0xcf32, 0xcf35, 0xcf36, 0xcf37, 0xcf3b, 0xcf3c, 0xcf3d, 0xcf3e, 0xcf51, 0xcf52, 0xcf58, 0xcf5a, 0xcf5b, 0xcf5e, 0xcf61, 0xcf62, 0xcf63, 0xcf65, 0xcf6a, - 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, 0xcfb3, - 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, 0xd045, - 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, 0xd171, - 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd403, 0xd444, 0xd6ac, - 0xd78c + 0xcf6e, 0xcf7d, 0xcf7f, 0xcf96, 0xcfaa, 0xcfae, 0xcfaf, 0xcfb1, + 0xcfb3, 0xcfca, 0xcfd1, 0xcfd4, 0xcfdd, 0xd006, 0xd00e, 0xd038, + 0xd045, 0xd0d5, 0xd12a, 0xd12b, 0xd12c, 0xd12d, 0xd12e, 0xd163, + 0xd171, 0xd17d, 0xd1d7, 0xd1dc, 0xd1ee, 0xd2af, 0xd3c1, 0xd403, + 0xd444, 0xd6ac, 0xd78c }; /*Collect the unicode lists and glyph_id offsets*/ @@ -12677,7 +12720,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 8470, .range_length = 55181, .glyph_id_start = 1017, - .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 73, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_12, .glyph_id_ofs_list = NULL, .list_length = 75, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -12825,7 +12868,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 }; /*Map glyph_ids to kern right classes*/ @@ -12967,7 +13010,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 }; /*Kern values between classes*/