What changed, and why it matters
This commit replaces the BitBox02's old ASCII-only font system with a new UTF-8-capable font engine based on LVGL. It adds checks to reject or sanitize characters that the device cannot display, preserves UTF-8 boundaries when shortening names, and updates tests. The change is primarily a defensive hardening and internationalization improvement rather than a fix for an active attack.
Review the new LVGL font conversion tooling and the `lvgl_font_compat.c` adapter for off-by-one or glyph lookup errors. Verify that all Rust/C UI entry points now call `has_glyph` or equivalent before passing user-controlled strings to C renderers, and that the bootloader-only font set covers all strings it may display.
Security signals we found
Replaced ASCII-only input validation with per-font glyph coverage checks
Added UTF-8 boundary preservation when truncating device names
Added malformed UTF-8 rejection before rendering in UI components
Removed direct font width table access in favor of `UG_GetCharWidth`
Updated legacy backup name sanitization to use font glyph coverage
Added tests for unsupported characters, malformed UTF-8, and lockscreen truncation
Evidence from the diff
The patch migrates the firmware and bootloader from legacy uGUI/ASCII font descriptors to LVGL 1bpp font descriptors with compatibility callbacks. It removes hardcoded ASCII-only validation in many UI components, introduces has_glyph checks in Rust and C, updates device-name validation to allow selected UTF-8 characters while rejecting unsupported ones, and fixes lockscreen truncation to avoid splitting UTF-8 code points. New unit tests cover ASCII pixel/metric compatibility, font fallbacks, malformed UTF-8 handling, and lockscreen truncation.
Changed components
src/ui/ugui/ugui.csrc/ui/fonts/*src/ui/components/label.csrc/ui/components/lockscreen.csrc/ui/components/button.csrc/ui/components/confirm.csrc/ui/components/confirm_swap.csrc/ui/components/confirm_transaction.csrc/ui/components/trinary_input_char.csrc/ui/components/trinary_input_string.csrc/rust/bitbox02/src/ui/ui.rssrc/rust/bitbox02/src/ui/types.rssrc/rust/bitbox02/src/memory.rssrc/rust/util/src/name.rssrc/memory/memory.hsrc/bootloader/bootloader.cInspect captured patch +1200 / −1447
### .clang-tidy
@@ -24,7 +24,7 @@ Checks: >-
-clang-analyzer-core.FixedAddressDereference,
-clang-diagnostic-cast-qual
HeaderFilterRegex: '.*'
-ExcludeHeaderFilterRegex: '.*/external/asf4-drivers/.*'
+ExcludeHeaderFilterRegex: '.*/external/(asf4-drivers|lvgl)/.*'
ExtraArgs:
- -Wno-unknown-warning-option
- -Qunused-arguments
### src/CMakeLists.txt
@@ -37,15 +37,13 @@ set(DBB-FIRMWARE-UI-SOURCES
${CMAKE_SOURCE_DIR}/src/screen.c
${CMAKE_SOURCE_DIR}/src/ui/graphics/graphics.c
${CMAKE_SOURCE_DIR}/src/ui/ugui/ugui.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_9X9.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_11X10.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_11X12.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_13X14.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_15X16.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_17X18.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/monogram_5X9.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/password_9X9.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/password_11X12.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/regular_11.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/regular_12.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/regular_9.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/lvgl_font_compat.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/monogram_16.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/password_9.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/password_12.c
${CMAKE_SOURCE_DIR}/src/ui/screen_saver.c
${CMAKE_SOURCE_DIR}/src/ui/screen_stack.c
${CMAKE_SOURCE_DIR}/src/ui/screen_process.c
@@ -97,9 +95,9 @@ set(DBB-BOOTLOADER-SOURCES
${CMAKE_SOURCE_DIR}/src/memory/memory_spi.c
${CMAKE_SOURCE_DIR}/src/usb/usb_processing.c
${CMAKE_SOURCE_DIR}/src/ui/ugui/ugui.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_9X9.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/font_a_11X10.c
- ${CMAKE_SOURCE_DIR}/src/ui/fonts/monogram_5X9.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/regular_9_bootloader.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/lvgl_font_compat.c
+ ${CMAKE_SOURCE_DIR}/src/ui/fonts/monogram_16_bootloader.c
${CMAKE_SOURCE_DIR}/src/ui/graphics/graphics.c
${CMAKE_SOURCE_DIR}/src/screen.c
${CMAKE_SOURCE_DIR}/src/hardfault.c
@@ -181,9 +179,17 @@ set(INCLUDES
${CMAKE_SOURCE_DIR}/src/usb/class/hid
${CMAKE_SOURCE_DIR}/src/usb/class/hid/hww
${CMAKE_SOURCE_DIR}/src/usb/class/hid/u2f
+ ${CMAKE_SOURCE_DIR}/external/lvgl
)
set(INCLUDES ${INCLUDES} PARENT_SCOPE)
+set(LVGL_DEFINITIONS
+ LV_KCONFIG_IGNORE
+ LV_LVGL_H_INCLUDE_SIMPLE
+ LV_CONF_PATH="${CMAKE_SOURCE_DIR}/src/rust/bitbox-lvgl-sys/lv_conf.h"
+ LV_CONF_INCLUDE_SIMPLE
+)
+
#-----------------------------------------------------------------------------
# Build embedded firmware
@@ -379,6 +385,7 @@ foreach(type ${RUST_LIBS})
_UNIT_TEST_
PRODUCT_BITBOX_MULTI=1
APP_U2F=1
+ ${LVGL_DEFINITIONS}
)
# For tests all C-files are built into the rust lib.
target_include_directories(${type}_rust_c INTERFACE
@@ -429,6 +436,7 @@ if(CMAKE_CROSSCOMPILING)
asf4-drivers
-Wl,-u,exception_table)
target_include_directories(${elf} PRIVATE ${INCLUDES})
+ target_compile_definitions(${elf} PRIVATE ${LVGL_DEFINITIONS})
# needed to find version.h
target_include_directories(${elf} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
@@ -548,6 +556,7 @@ if(CMAKE_CROSSCOMPILING)
${bootloader_type}
${product}
"APP_U2F=0"
+ ${LVGL_DEFINITIONS}
)
target_compile_options(${target}.elf PRIVATE --specs=nano.specs --specs=nosys.specs)
if(is_plus)
@@ -1021,6 +1030,7 @@ if(CMAKE_CROSSCOMPILING)
"APP_U2F=${app_u2f}"
BB02_STAGE1_TARGET_PRODUCT_ID=${target_product_id}
${blupgrade_compile_definitions}
+ ${LVGL_DEFINITIONS}
OPTIGA_LIB_EXTERNAL="optiga_config.h"
)
target_sources(${target}.elf PRIVATE ${PLATFORM-BITBOX02-SOURCES})
### src/bootloader/bootloader.c
@@ -19,7 +19,7 @@
#include <stdint.h>
#include <string.h>
#include <ui/components/ui_images.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/graphics/graphics.h>
#include <ui/oled/oled.h>
#include <ui/ugui/ugui.h>
@@ -300,9 +300,9 @@ void bootloader_render_ble_confirm_screen(bool confirmed)
image_cross(SCREEN_WIDTH / 16, 0, IMAGE_DEFAULT_CROSS_HEIGHT);
image_checkmark(SCREEN_WIDTH * 15 / 16 - check_width, 0, IMAGE_DEFAULT_CHECKMARK_HEIGHT);
}
- UG_FontSelect(&font_monogram_5X9);
+ UG_FontSelect(&font_monogram_16);
UG_PutString(45, SCREEN_HEIGHT / 2 - 9, code_str);
- UG_FontSelect(&font_font_a_9X9);
+ UG_FontSelect(&font_regular_9);
UG_SendBuffer();
}
#endif
@@ -332,8 +332,8 @@ static void _render_hash(const char* title, const uint8_t* hash)
// If you change this, check the timer_buf size below.
const uint8_t seconds = 10; // how many seconds to show screen
const UG_S16 title_margin = 7; // Margin between title and hash
- const UG_FONT* f_mono = &font_monogram_5X9; // monospaced font
- const UG_FONT* f_regular = &font_font_a_9X9; // regular font
+ const UG_FONT* f_mono = &font_monogram_16; // monospaced font
+ const UG_FONT* f_regular = &font_regular_9; // regular font
// Convert hash to ascii hex
char hash_hex[2 * SHA256_DIGEST_LENGTH + 1];
@@ -355,10 +355,10 @@ static void _render_hash(const char* title, const uint8_t* hash)
bootloader_format_timer(timer_buf, sizeof(timer_buf), seconds - i);
UG_MeasureString(&timer_str_width, NULL, timer_buf);
UG_PutString(
- SCREEN_WIDTH - timer_str_width, SCREEN_HEIGHT - f_regular->char_height, timer_buf);
+ SCREEN_WIDTH - timer_str_width, SCREEN_HEIGHT - f_regular->line_height, timer_buf);
UG_FontSelect(f_mono);
- UG_PutString(0, title_margin + f_regular->char_height, hash_multiline);
+ UG_PutString(0, title_margin + f_regular->line_height, hash_multiline);
UG_FontSelect(f_regular);
@@ -1020,7 +1020,7 @@ void bootloader_jump(void)
boot_args_clear_command();
}
- UG_FontSelect(&font_font_a_9X9);
+ UG_FontSelect(&font_regular_9);
if (!bootloader_wait && shared_data.fields.auto_enter != sectrue_u8) {
#ifdef BOOTLOADER_DEVDEVICE
### src/da14531/da14531_handler.c
@@ -15,7 +15,7 @@
#include <rust/rust.h>
#include <ui/components/confirm.h>
#include <ui/components/ui_images.h>
-#include <ui/fonts/monogram_5X9.h>
+#include <ui/fonts/monogram_16.h>
#include <utils_assert.h>
const uint8_t* da14531_handler_current_product = NULL;
@@ -189,7 +189,7 @@ static void _ctrl_handler(const struct da14531_ctrl_frame* frame, struct RustByt
const confirm_params_t confirm_params = {
.title = "Pairing code",
.body = pairing_code,
- .font = &font_monogram_5X9,
+ .font = &font_monogram_16,
};
_ble_pairing_component = confirm_create(
&confirm_params, _ble_pairing_callback, (void*)&_ble_pairing_callback_data);
### src/memory/memory.h
@@ -69,9 +69,9 @@ USE_RESULT bool memory_cleanup_smarteeprom(void);
extern const char* MEMORY_DEFAULT_DEVICE_NAME;
// Set device name. `name` is null terminated and `name_len` is its length excluding the null
-// terminator. The name must be larger than 0 in size, consist of printable ASCII characters only
-// (and space), not start or end with whitespace, and contain no whitespace other than space. Names
-// longer than MEMORY_DEVICE_MAX_LEN_WITH_NULL - 1 are truncated.
+// terminator. The name must be larger than 0 in size, consist only of safe display characters, not
+// start or end with whitespace, and contain no whitespace other than space. Names longer than
+// MEMORY_DEVICE_MAX_LEN_WITH_NULL - 1 bytes are truncated without splitting a UTF-8 code point.
USE_RESULT bool memory_set_device_name(const char* name, size_t name_len);
// name_out must have MEMORY_DEVICE_MAX_LEN_WITH_NULL bytes in size. If no device name is set, or if
### src/rust/bitbox-hal/src/ui.rs
@@ -24,9 +24,9 @@ pub enum WordlistEntryAbort {
#[derive(Copy, Clone, Default)]
pub enum Font {
#[default]
- Default,
- Password11X12,
- Monogram5X9,
+ Regular11,
+ Password12,
+ Monogram16,
}
#[derive(Default)]
@@ -101,6 +101,12 @@ pub trait Ui {
/// Returns `Ok(())` if the user accepts, `Err(UserAbort)` if the user rejects.
async fn confirm(&mut self, params: &ConfirmParams<'_>) -> Result<(), UserAbort>;
+ /// Returns true if `font` can render `c`.
+ ///
+ /// Control characters such as newlines are workflow-specific layout markers and are not
+ /// considered font glyphs here.
+ fn has_glyph(&self, font: Font, c: char) -> bool;
+
/// Returns `Ok(())` if the user accepts the swap, `Err(UserAbort)` if the user rejects it.
async fn confirm_swap(&mut self, title: &str, from: &str, to: &str) -> Result<(), UserAbort>;
### src/rust/bitbox02-rust-c/src/u2f_c_api.rs
@@ -8,7 +8,7 @@ extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String;
-use bitbox_hal::ui::{ConfirmParams, UserAbort};
+use bitbox_hal::ui::{ConfirmParams, Font, UserAbort};
use bitbox_hal::{Hal, Ui};
use core::ffi::CStr;
use core::sync::atomic::{AtomicU32, Ordering};
@@ -151,9 +151,14 @@ pub unsafe extern "C" fn rust_workflow_spawn_confirm(
) else {
return false;
};
- if !util::ascii::is_printable_ascii(title, util::ascii::Charset::AllNewline)
- || !util::ascii::is_printable_ascii(body, util::ascii::Charset::AllNewline)
- {
+ let has_all_glyphs = {
+ let ui = unsafe { BITBOX02_HAL.get().as_mut().unwrap() }.ui();
+ title
+ .chars()
+ .chain(body.chars())
+ .all(|c| c == '\n' || ui.has_glyph(Font::Regular11, c))
+ };
+ if !has_all_glyphs {
return false;
}
let title: String = title.into();
### src/rust/bitbox02-rust/src/backup.rs
@@ -61,16 +61,14 @@ pub fn id(seed: &[u8]) -> String {
hex::encode(mac.finalize_reset().into_bytes())
}
-/// Replaces non-printable-ASCII characters in legacy backup names with `?`.
-pub(crate) fn sanitize_name(name: &str) -> String {
+/// Replaces characters that cannot be displayed safely in legacy backup names with `?`.
+pub(crate) fn sanitize_name(name: &str, mut has_glyph: impl FnMut(char) -> bool) -> String {
name.chars()
- .map(|character| {
- if util::ascii::Charset::All.contains(character) {
- character
- } else {
- '?'
- }
- })
+ .map(
+ |character| {
+ if has_glyph(character) { character } else { '?' }
+ },
+ )
.collect()
}
@@ -558,6 +556,16 @@ mod tests {
.await;
}
+ #[test]
+ fn test_sanitize_name() {
+ assert_eq!(
+ sanitize_name("Bït\nBox\t東京", |c| matches!(c, ' '..='~' | 'ï')),
+ "Bït?Box???"
+ );
+ assert_eq!(sanitize_name("東京", |_| true), "東京");
+ assert_eq!(sanitize_name("BïtBox", |c| c != 'ï'), "B?tBox");
+ }
+
#[test]
fn test_bitwise_recovery() {
assert!(bitwise_recovery(&[1], &[], &[]).is_err());
### src/rust/bitbox02-rust/src/hal/testing/ui.rs
@@ -2,7 +2,7 @@
use crate::hal::Ui;
use crate::hal::ui::{
- CanCancel, ConfirmParams, Empty, EnterStringParams, Progress, TrinaryChoice, UserAbort,
+ CanCancel, ConfirmParams, Empty, EnterStringParams, Font, Progress, TrinaryChoice, UserAbort,
WordlistEntryAbort,
};
@@ -72,6 +72,7 @@ type EnterStringAsyncCb<'a> = Box<
>;
type EnterWordlistWordCb<'a> =
Box<dyn FnMut(&EnterStringParams<'_>) -> Result<String, WordlistEntryAbort> + 'a>;
+type HasGlyphCb<'a> = Box<dyn Fn(Font, char) -> bool + 'a>;
type MenuCb<'a> = Box<dyn FnMut(&[&str], Option<&str>) -> Result<u8, UserAbort> + 'a>;
type TrinaryChoiceCb<'a> =
Box<dyn FnMut(&str, Option<&str>, Option<&str>, Option<&str>) -> TrinaryChoice + 'a>;
@@ -86,6 +87,7 @@ pub struct TestingUi<'a> {
progress_screens: Rc<RefCell<Vec<ProgressScreen>>>,
_enter_string_async: Option<EnterStringAsyncCb<'a>>,
_enter_wordlist_word: Option<EnterWordlistWordCb<'a>>,
+ _has_glyph: Option<HasGlyphCb<'a>>,
_menu: Option<MenuCb<'a>>,
_trinary_choice: Option<TrinaryChoiceCb<'a>>,
_quiz_choices: VecDeque<u8>,
@@ -161,6 +163,13 @@ impl Ui for TestingUi<'_> {
Ok(())
}
+ fn has_glyph(&self, font: Font, c: char) -> bool {
+ if let Some(has_glyph) = self._has_glyph.as_ref() {
+ return has_glyph(font, c);
+ }
+ matches!(c, '\u{20}'..='\u{7e}' | '\u{a0}'..='\u{17f}')
+ }
+
async fn confirm_swap(&mut self, title: &str, from: &str, to: &str) -> Result<(), UserAbort> {
self.screens.push(Screen::Swap {
title: title.into(),
@@ -350,6 +359,7 @@ impl<'a> TestingUi<'a> {
_abort_nth: None,
_enter_string_async: None,
_enter_wordlist_word: None,
+ _has_glyph: None,
_menu: None,
_trinary_choice: None,
_quiz_choices: VecDeque::new(),
@@ -391,6 +401,10 @@ impl<'a> TestingUi<'a> {
self._enter_string_async = None;
}
+ pub fn set_has_glyph(&mut self, cb: Box<dyn Fn(Font, char) -> bool + 'a>) {
+ self._has_glyph = Some(cb);
+ }
+
pub fn set_menu(&mut self, cb: MenuCb<'a>) {
self._menu = Some(cb);
}
### src/rust/bitbox02-rust/src/hww/api/backup.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use super::Error;
-use crate::hal::ui::{CanCancel, ConfirmParams};
+use crate::hal::ui::{CanCancel, ConfirmParams, Font};
use crate::pb;
use alloc::vec::Vec;
@@ -29,7 +29,10 @@ pub async fn check(
return Err(Error::Generic);
}
if !silent {
- let name = backup::sanitize_name(&metadata.name);
+ let name = {
+ let ui = hal.ui();
+ backup::sanitize_name(&metadata.name, |c| ui.has_glyph(Font::Regular11, c))
+ };
hal.ui()
.confirm(&ConfirmParams {
title: "Name?",
### src/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rs
@@ -3,7 +3,7 @@
use super::Error;
use super::params;
use super::pb;
-use crate::hal::ui::ConfirmParams;
+use crate::hal::ui::{ConfirmParams, Font};
use alloc::string::String;
@@ -93,7 +93,11 @@ async fn get_name(
} else {
request.name.clone()
};
- if !util::name::validate(&name, bitbox_hal::memory::MULTISIG_NAME_MAX_LEN) {
+ let has_all_glyphs = {
+ let ui = hal.ui();
+ name.chars().all(|c| ui.has_glyph(Font::Regular11, c))
+ };
+ if !util::name::validate(&name, bitbox_hal::memory::MULTISIG_NAME_MAX_LEN) || !has_all_glyphs {
return Err(Error::InvalidInput);
}
Ok(name)
@@ -174,6 +178,24 @@ mod tests {
use crate::hal::testing::TestingHal;
+ #[async_test::test]
+ async fn test_get_name_utf8() {
+ let request = pb::BtcRegisterScriptConfigRequest {
+ name: "Müller".into(),
+ ..Default::default()
+ };
+ let mut mock_hal = TestingHal::new();
+ assert_eq!(get_name(&mut mock_hal, &request).await.unwrap(), "Müller");
+
+ mock_hal
+ .ui
+ .set_has_glyph(alloc::boxed::Box::new(|_, character| character != 'ü'));
+ assert!(matches!(
+ get_name(&mut mock_hal, &request).await,
+ Err(Error::InvalidInput)
+ ));
+ }
+
use pb::btc_script_config::{Multisig, multisig::ScriptType};
#[test]
### src/rust/bitbox02-rust/src/hww/api/restore.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use super::Error;
-use crate::hal::ui::ConfirmParams;
+use crate::hal::ui::{ConfirmParams, Font};
use crate::pb;
use pb::response::Response;
@@ -32,7 +32,10 @@ pub async fn from_file(
}
};
- let device_name = crate::backup::sanitize_name(&metadata.name);
+ let device_name = {
+ let ui = hal.ui();
+ crate::backup::sanitize_name(&metadata.name, |c| ui.has_glyph(Font::Regular11, c))
+ };
hal.ui()
.confirm(&ConfirmParams {
body: &format!("Name: {}. ID: {}", &device_name, &request.id),
@@ -208,11 +211,11 @@ mod tests {
mock_hal.ui.screens[1],
Screen::Confirm {
title: "".into(),
- body: format!("Name: B?t?Box?. ID: {id}"),
+ body: format!("Name: Bït?Box?. ID: {id}"),
longtouch: false,
}
);
- assert_eq!(mock_hal.memory.get_device_name(), "B?t?Box?");
+ assert_eq!(mock_hal.memory.get_device_name(), "Bït?Box?");
}
#[async_test::test]
### src/rust/bitbox02-rust/src/hww/api/set_device_name.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use super::Error;
-use crate::hal::ui::ConfirmParams;
+use crate::hal::ui::{ConfirmParams, Font};
use crate::pb;
use pb::response::Response;
@@ -20,7 +20,11 @@ pub async fn process(
return Ok(Response::Success(pb::Success {}));
}
- if !util::name::validate(name, bitbox_hal::memory::DEVICE_NAME_MAX_LEN) {
+ let has_all_glyphs = {
+ let ui = hal.ui();
+ name.chars().all(|c| ui.has_glyph(Font::Regular11, c))
+ };
+ if !util::name::validate(name, bitbox_hal::memory::DEVICE_NAME_MAX_LEN) || !has_all_glyphs {
return Err(Error::InvalidInput);
}
@@ -48,7 +52,7 @@ mod tests {
#[async_test::test]
pub async fn test_set_device_name() {
- const SOME_NAME: &str = "foo";
+ const SOME_NAME: &str = "BïtBöx";
// All good.
let mut mock_hal = TestingHal::new();
@@ -94,7 +98,7 @@ mod tests {
}]
);
- // Non-ascii character.
+ // Unsupported character.
assert_eq!(
process(
&mut TestingHal::new(),
@@ -106,6 +110,35 @@ mod tests {
Err(Error::InvalidInput)
);
+ // A character that is unavailable in the active font is rejected.
+ let mut mock_hal = TestingHal::new();
+ mock_hal
+ .ui
+ .set_has_glyph(Box::new(|_, character| character != 'ï'));
+ assert_eq!(
+ process(
+ &mut mock_hal,
+ &pb::SetDeviceNameRequest {
+ name: SOME_NAME.into()
+ }
+ )
+ .await,
+ Err(Error::InvalidInput)
+ );
+
+ mock_hal.ui.set_has_glyph(Box::new(|_, _| true));
+ assert_eq!(
+ process(
+ &mut mock_hal,
+ &pb::SetDeviceNameRequest {
+ name: "東京".into()
+ }
+ )
+ .await,
+ Ok(Response::Success(pb::Success {}))
+ );
+ assert_eq!(mock_hal.memory.get_device_name(), "東京");
+
// Non-printable character.
assert_eq!(
process(
### src/rust/bitbox02-rust/src/workflow/pairing.rs
@@ -24,7 +24,7 @@ pub async fn confirm(hal: &mut impl crate::hal::Hal, hash: &[u8; 32]) -> Result<
let params = ConfirmParams {
title: "Pairing code",
body: &format_hash(hash),
- font: Font::Monogram5X9,
+ font: Font::Monogram16,
..Default::default()
};
### src/rust/bitbox02-rust/src/workflow/unlock.rs
@@ -44,7 +44,7 @@ pub(crate) async fn confirm_mnemonic_passphrase(
let params = ConfirmParams {
title: "Confirm",
body: passphrase,
- font: crate::hal::ui::Font::Password11X12,
+ font: crate::hal::ui::Font::Password12,
scrollable: true,
longtouch: true,
..Default::default()
### src/rust/bitbox02-sys/build.rs
@@ -13,10 +13,10 @@ const ALLOWLIST_VARS: &[&str] = &[
"da14531_handler_current_product_len",
"BITBOX02_FLASH_BOOT_LEN",
"BITBOX02_FLASH_BOOT_START",
- "font_font_a_11X10",
- "font_font_a_9X9",
- "font_monogram_5X9",
- "font_password_11X12",
+ "font_regular_11",
+ "font_regular_9",
+ "font_monogram_16",
+ "font_password_12",
"INPUT_STRING_MAX_SIZE",
"MAX_LABEL_SIZE",
"MAX_PK_SCRIPT_SIZE",
@@ -54,6 +54,8 @@ const ALLOWLIST_TYPES: &[&str] = &[
const OPAQUE_TYPES: &[&str] = &[
"da14531_protocol_frame",
+ "_lv_font_t",
+ "lv_font_t",
"RustByteQueue",
"RustUsbReportQueue",
];
@@ -180,6 +182,7 @@ const ALLOWLIST_FNS: &[&str] = &[
"uart_poll",
"UG_ClearBuffer",
"UG_FontSelect",
+ "UG_GetCharWidth",
"UG_PutString",
"UG_SendBuffer",
"ui_screen_stack_pop_all",
@@ -261,15 +264,13 @@ const BITBOX02_SOURCES: &[&str] = &[
"src/ui/components/ui_images.c",
"src/ui/components/waiting.c",
"src/ui/event_handler.c",
- "src/ui/fonts/font_a_11X10.c",
- "src/ui/fonts/font_a_11X12.c",
- "src/ui/fonts/font_a_13X14.c",
- "src/ui/fonts/font_a_15X16.c",
- "src/ui/fonts/font_a_17X18.c",
- "src/ui/fonts/font_a_9X9.c",
- "src/ui/fonts/monogram_5X9.c",
- "src/ui/fonts/password_11X12.c",
- "src/ui/fonts/password_9X9.c",
+ "src/ui/fonts/regular_11.c",
+ "src/ui/fonts/regular_12.c",
+ "src/ui/fonts/regular_9.c",
+ "src/ui/fonts/lvgl_font_compat.c",
+ "src/ui/fonts/monogram_16.c",
+ "src/ui/fonts/password_12.c",
+ "src/ui/fonts/password_9.c",
"src/ui/graphics/graphics.c",
"src/ui/oled/sh1107.c",
"src/ui/oled/ssd1312.c",
@@ -327,6 +328,44 @@ pub fn main() -> BuildResult<()> {
emit_rerun_if_changed("../../../src/bootloader/stage0/stage0_version.h.tmpl");
emit_rerun_if_changed("../../../scripts/generate_version_headers.py");
emit_rerun_if_changed("../../../scripts/generate_rust_header.sh");
+ emit_rerun_if_changed("../bitbox-lvgl-sys/lv_conf.h");
+
+ // Watch C headers and their subdirectories without watching src/rust and its build outputs.
+ for path in [
+ "../../../src/atecc",
+ "../../../src/bootloader",
+ "../../../src/bootloader_upgrade",
+ "../../../src/common_main.h",
+ "../../../src/compiler_util.h",
+ "../../../src/da14531",
+ "../../../src/delay.h",
+ "../../../src/flags.h",
+ "../../../src/hardfault.h",
+ "../../../src/hww.h",
+ "../../../src/i2c_ecc.h",
+ "../../../src/memory",
+ "../../../src/optiga",
+ "../../../src/pac_ext.h",
+ "../../../src/platform",
+ "../../../src/pukcc",
+ "../../../src/qtouch",
+ "../../../src/random.h",
+ "../../../src/reset.h",
+ "../../../src/screen.h",
+ "../../../src/sd.h",
+ "../../../src/sd_mmc",
+ "../../../src/securechip",
+ "../../../src/system.h",
+ "../../../src/touch",
+ "../../../src/u2f",
+ "../../../src/u2f.h",
+ "../../../src/uart.h",
+ "../../../src/ui",
+ "../../../src/usb",
+ "../../../src/util.h",
+ ] {
+ emit_rerun_if_changed(path);
+ }
// Generating version headers depends on the current state of the git repo.
emit_git_rerun_if_changed(&repo_root);
@@ -337,11 +376,22 @@ pub fn main() -> BuildResult<()> {
emit_bindgen_env_rerun_if_changed(&target);
let cross_compiling = target.starts_with("thumb");
- let target_definitions = if cross_compiling {
- vec!["-D__SAMD51J20A__"]
+ let lv_conf = manifest_dir.join("../bitbox-lvgl-sys/lv_conf.h");
+ let mut target_definitions = if cross_compiling {
+ vec!["-D__SAMD51J20A__".to_owned()]
} else {
- vec!["-DTESTING", "-D_UNIT_TEST_", "-DPRODUCT_BITBOX_MULTI=1"]
+ vec![
+ "-DTESTING".to_owned(),
+ "-D_UNIT_TEST_".to_owned(),
+ "-DPRODUCT_BITBOX_MULTI=1".to_owned(),
+ ]
};
+ target_definitions.extend([
+ "-DLV_KCONFIG_IGNORE".to_owned(),
+ "-DLV_LVGL_H_INCLUDE_SIMPLE".to_owned(),
+ format!("-DLV_CONF_PATH=\"{}\"", lv_conf.display()),
+ "-DLV_CONF_INCLUDE_SIMPLE".to_owned(),
+ ]);
// If user enables -Dwarnings for Rust we also want to enable -Werror for C.
let warnings_as_errors = std::env::var("CARGO_ENCODED_RUSTFLAGS")
@@ -354,6 +404,7 @@ pub fn main() -> BuildResult<()> {
// $INCLUDES
"../..".to_owned(),
"../../ui/ugui".to_owned(),
+ "../../../external/lvgl".to_owned(),
"../../platform".to_owned(),
"../../qtouch".to_owned(),
"../../usb/class".to_owned(),
@@ -411,15 +462,23 @@ pub fn main() -> BuildResult<()> {
includes.push("../../../test/hardware-fakes/include".to_owned());
}
+ // Track included headers, including LVGL, ASF4 and hardware fakes. The src root is covered
+ // above. Avoid watching the generated output directory itself.
+ for include in &includes {
+ if include != "../.." && Path::new(include) != generated_headers_dir.as_path() {
+ emit_rerun_if_changed(include);
+ }
+ }
+
let out_path = out_dir.join("bindings.rs");
let out_path = out_path.into_os_string().into_string().unwrap();
// Needs to match the definitions in `CMakeList.txt' files (unit tests, hardware fakes and
// simulator)
- let mut definitions = vec!["-DAPP_U2F=1"];
+ let mut definitions = vec!["-DAPP_U2F=1".to_owned()];
definitions.extend(target_definitions);
if warnings_as_errors {
- definitions.push("-Werror");
+ definitions.push("-Werror".to_owned());
}
let mut bindgen = Command::new("bindgen");
### src/rust/bitbox02-sys/wrapper.h
@@ -39,10 +39,10 @@
#include <ui/components/trinary_choice.h>
#include <ui/components/trinary_input_string.h>
#include <ui/components/unlock_animation.h>
-#include <ui/fonts/font_a_11X10.h>
-#include <ui/fonts/font_a_9X9.h>
-#include <ui/fonts/monogram_5X9.h>
-#include <ui/fonts/password_11X12.h>
+#include <ui/fonts/monogram_16.h>
+#include <ui/fonts/password_12.h>
+#include <ui/fonts/regular_11.h>
+#include <ui/fonts/regular_9.h>
#include <ui/oled/oled.h>
#include <ui/screen_process.h>
#include <ui/screen_saver.h>
### src/rust/bitbox02/src/hal/ui.rs
@@ -33,9 +33,9 @@ impl HalEmpty for BitBox02Empty {}
fn to_bitbox02_font(font: Font) -> crate::ui::Font {
match font {
- Font::Default => crate::ui::Font::Default,
- Font::Password11X12 => crate::ui::Font::Password11X12,
- Font::Monogram5X9 => crate::ui::Font::Monogram5X9,
+ Font::Regular11 => crate::ui::Font::Regular11,
+ Font::Password12 => crate::ui::Font::Password12,
+ Font::Monogram16 => crate::ui::Font::Monogram16,
}
}
@@ -145,6 +145,10 @@ impl<Timer: bitbox_hal::timer::Timer> Ui for BitBox02Ui<Timer> {
}
}
+ fn has_glyph(&self, font: Font, c: char) -> bool {
+ to_bitbox02_font(font).has_glyph(c)
+ }
+
#[inline(always)]
async fn confirm_swap(&mut self, title: &str, from: &str, to: &str) -> Result<(), UserAbort> {
if !crate::ui::transaction_amount_fits(from) || !crate::ui::transaction_amount_fits(to) {
@@ -315,21 +319,29 @@ mod tests {
#[test]
fn test_to_bitbox02_font() {
let cases = [
- (Font::Default, crate::ui::Font::Default),
- (Font::Password11X12, crate::ui::Font::Password11X12),
- (Font::Monogram5X9, crate::ui::Font::Monogram5X9),
+ (Font::Regular11, crate::ui::Font::Regular11),
+ (Font::Password12, crate::ui::Font::Password12),
+ (Font::Monogram16, crate::ui::Font::Monogram16),
];
for (input, expected) in cases {
assert_eq!(to_bitbox02_font(input) as i32, expected as i32);
}
}
+ #[test]
+ fn test_has_glyph_uses_actual_bitbox02_font() {
+ assert!(to_bitbox02_font(Font::Regular11).has_glyph('A'));
+ assert!(to_bitbox02_font(Font::Regular11).has_glyph('ü'));
+ assert!(!to_bitbox02_font(Font::Regular11).has_glyph('ȑ'));
+ assert!(!to_bitbox02_font(Font::Regular11).has_glyph('\t'));
+ }
+
#[test]
fn test_to_bitbox02_confirm_params() {
let fonts = [
- (Font::Default, crate::ui::Font::Default),
- (Font::Password11X12, crate::ui::Font::Password11X12),
- (Font::Monogram5X9, crate::ui::Font::Monogram5X9),
+ (Font::Regular11, crate::ui::Font::Regular11),
+ (Font::Password12, crate::ui::Font::Password12),
+ (Font::Monogram16, crate::ui::Font::Monogram16),
];
for (font, expected_font) in fonts {
let input = ConfirmParams {
### src/rust/bitbox02/src/lib.rs
@@ -71,11 +71,11 @@ pub fn ug_send_buffer() {
}
pub fn ug_font_select_9x9() {
- unsafe { bitbox02_sys::UG_FontSelect(&bitbox02_sys::font_font_a_9X9) }
+ unsafe { bitbox02_sys::UG_FontSelect(&bitbox02_sys::font_regular_9) }
}
pub fn ug_font_select_11x10() {
- unsafe { bitbox02_sys::UG_FontSelect(&bitbox02_sys::font_font_a_11X10) }
+ unsafe { bitbox02_sys::UG_FontSelect(&bitbox02_sys::font_regular_11) }
}
pub fn screen_rotate() {
### src/rust/bitbox02/src/memory.rs
@@ -11,6 +11,29 @@ pub use bitbox02_sys::memory_optiga_config_version_t as OptigaConfigVersion;
pub use bitbox02_sys::memory_password_stretch_algo_t as PasswordStretchAlgo;
pub use bitbox02_sys::memory_result_t as MemoryError;
+/// Calls `util::name::validate()` on the provided C string and checks glyph availability.
+///
+/// # Safety
+///
+/// `buf` must point to a valid buffer of size `max_len`.
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn rust_util_is_name_valid(buf: *const u8, max_len: usize) -> bool {
+ if max_len == 0 {
+ return false;
+ }
+ let slice = unsafe { core::slice::from_raw_parts(buf, max_len) };
+ match core::ffi::CStr::from_bytes_until_nul(slice) {
+ Ok(cstr) => match cstr.to_str() {
+ Ok(s) => {
+ util::name::validate(s, max_len - 1)
+ && s.chars().all(|c| crate::ui::Font::Regular11.has_glyph(c))
+ }
+ Err(_) => false,
+ },
+ Err(_) => false,
+ }
+}
+
pub fn get_device_name() -> String {
let mut name = [0u8; DEVICE_NAME_MAX_LEN + 1];
unsafe { bitbox02_sys::memory_get_device_name(name.as_mut_ptr().cast()) }
@@ -417,6 +440,10 @@ mod tests {
set_device_name(new_name).unwrap();
assert_eq!(get_device_name(), new_name);
+ let utf8_name = "BïtBöx Zürich";
+ set_device_name(utf8_name).unwrap();
+ assert_eq!(get_device_name(), utf8_name);
+
// A name with the maximum allowed length is accepted.
let max_len_name = "DeviceName_ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxy";
assert_eq!(max_len_name.len(), DEVICE_NAME_MAX_LEN);
@@ -435,8 +462,8 @@ mod tests {
" name", // leading space
"name ", // trailing space
"foo\nbar", // control character
- "Ä", // non-ASCII
- "漢字", // non-ASCII
+ "漢字", // unsupported character
+ "emoji 😃", // unsupported character
];
for invalid in invalid_names {
@@ -851,4 +878,25 @@ mod tests {
Ok(OptigaConfigVersion::MEMORY_OPTIGA_CONFIG_V1),
));
}
+
+ #[test]
+ // For clarity we want explicit null terminators in the strings below, not CStr literals
+ // `c"..."`.
+ #[allow(clippy::manual_c_str_literals)]
+ fn test_rust_util_is_name_valid() {
+ unsafe {
+ // Valid
+ assert!(rust_util_is_name_valid("foo\0".as_ptr(), 4));
+ assert!(rust_util_is_name_valid("foo\0........".as_ptr(), 12));
+ assert!(rust_util_is_name_valid("BïtBöx\0".as_ptr(), 10));
+
+ // Invalid
+ assert!(!rust_util_is_name_valid("fo\no\0".as_ptr(), 5));
+ assert!(!rust_util_is_name_valid("".as_ptr(), 0));
+ assert!(!rust_util_is_name_valid("foo\0".as_ptr(), 3));
+ assert!(!rust_util_is_name_valid("foo".as_ptr(), 3));
+ assert!(!rust_util_is_name_valid("東京\0".as_ptr(), 7));
+ assert!(!rust_util_is_name_valid("ȑ\0".as_ptr(), 3));
+ }
+ }
}
### src/rust/bitbox02/src/ui/types.rs
@@ -13,20 +13,31 @@ const _: () = assert!(MAX_LABEL_SIZE == bitbox02_sys::MAX_LABEL_SIZE as usize);
#[derive(Default)]
pub enum Font {
#[default]
- Default,
- Password11X12,
- Monogram5X9,
+ Regular11,
+ Password12,
+ Monogram16,
+ Regular9,
}
impl Font {
#[cfg_attr(any(feature = "testing", feature = "c-unit-testing"), allow(dead_code))]
pub(crate) fn as_ptr(&self) -> *const bitbox02_sys::UG_FONT {
match self {
- Font::Default => core::ptr::null() as *const _,
- Font::Password11X12 => unsafe { &bitbox02_sys::font_password_11X12 },
- Font::Monogram5X9 => unsafe { &bitbox02_sys::font_monogram_5X9 },
+ Font::Regular11 => unsafe { &bitbox02_sys::font_regular_11 },
+ Font::Password12 => unsafe { &bitbox02_sys::font_password_12 },
+ Font::Monogram16 => unsafe { &bitbox02_sys::font_monogram_16 },
+ Font::Regular9 => unsafe { &bitbox02_sys::font_regular_9 },
}
}
+
+ #[cfg_attr(any(feature = "testing", feature = "c-unit-testing"), allow(dead_code))]
+ pub(crate) fn has_glyph(&self, c: char) -> bool {
+ if c.is_control() {
+ return false;
+ }
+ let mut width = 0u16;
+ unsafe { bitbox02_sys::UG_GetCharWidth(self.as_ptr(), c as u32, &mut width) }
+ }
}
pub enum SdcardResponse {
### src/rust/bitbox02/src/ui/ui.rs
@@ -20,36 +20,51 @@ use zeroize::Zeroizing;
// Rust-side cut moves back to a UTF-8 boundary.
const LABEL_TRUNCATE_SIZE: usize = super::types::MAX_LABEL_SIZE + 4;
-/// BitBox02 fonts contain glyphs for printable ASCII only. Keep this check at the common UI
-/// boundary so unsupported text cannot be silently omitted by the renderer.
-/// The returned buffer is wiped on drop.
-fn display_str_to_cstr_vec(text: &str) -> Zeroizing<Vec<c_char>> {
+/// Keep this check at the common UI boundary so unsupported text cannot be silently omitted by
+/// the renderer. The returned buffer is wiped on drop.
+fn display_str_to_cstr_vec(text: &str, font: &Font) -> Zeroizing<Vec<c_char>> {
assert!(
- util::ascii::is_printable_ascii(text, util::ascii::Charset::AllNewline),
+ text.chars().all(|c| c == '\n' || font.has_glyph(c)),
"BitBox02 UI text contains unsupported characters"
);
// UI strings can contain passphrases or mnemonic words. Include the NUL in the initial
// allocation so growing the buffer cannot leave a discarded copy of the secret.
util::strings::str_to_cstr_vec_zeroizing(text).unwrap()
}
-fn label_fits_width(text: &str, font: *const bitbox02_sys::UG_FONT) -> bool {
- let text = display_str_to_cstr_vec(text);
- unsafe { bitbox02_sys::label_fits_width(text.as_ptr(), font, bitbox02_sys::SCREEN_WIDTH as _) }
+/// The C function retains the selected font, so every `Font` refers to static font data.
+fn label_fits_width(text: &str, font: &Font) -> bool {
+ let text = display_str_to_cstr_vec(text, font);
+ unsafe {
+ bitbox02_sys::label_fits_width(
+ text.as_ptr(),
+ font.as_ptr(),
+ bitbox02_sys::SCREEN_WIDTH as _,
+ )
+ }
+}
+
+/// Mirrors the amount font selection in the C transaction and swap components.
+fn transaction_amount_font(amount: &str) -> Font {
+ if label_fits_width(amount, &Font::Regular11) {
+ Font::Regular11
+ } else {
+ Font::Regular9
+ }
}
/// Returns true if the amount fits the transaction screen, using the smaller font if necessary.
pub fn transaction_amount_fits(amount: &str) -> bool {
- if label_fits_width(amount, unsafe { &bitbox02_sys::font_font_a_11X10 }) {
+ if label_fits_width(amount, &Font::Regular11) {
true
} else {
- label_fits_width(amount, unsafe { &bitbox02_sys::font_font_a_9X9 })
+ label_fits_width(amount, &Font::Regular9)
}
}
/// Returns true if the fee fits the transaction screen's smaller fee font.
pub fn transaction_fee_fits(fee: &str) -> bool {
- label_fits_width(fee, unsafe { &bitbox02_sys::font_font_a_9X9 })
+ label_fits_width(fee, &Font::Regular9)
}
/// Wraps the C component_t to be used in Rust.
@@ -168,10 +183,10 @@ pub async fn trinary_input_string(
(None, core::ptr::null_mut())
};
- let title = display_str_to_cstr_vec(util::strings::truncate_str(
- params.title,
- LABEL_TRUNCATE_SIZE,
- ));
+ let title = display_str_to_cstr_vec(
+ util::strings::truncate_str(params.title, LABEL_TRUNCATE_SIZE),
+ &Font::Regular11,
+ );
let c_params = bitbox02_sys::trinary_input_string_params_t {
title: title.as_ptr().cast(),
wordlist: match params.wordlist {
@@ -201,7 +216,7 @@ pub async fn trinary_input_string(
unsafe {
bitbox02_sys::trinary_input_string_set_input(
component,
- display_str_to_cstr_vec(preset).as_ptr(),
+ display_str_to_cstr_vec(preset, &Font::Password12).as_ptr(),
)
}
}
@@ -260,14 +275,14 @@ pub async fn confirm(params: &ConfirmParams<'_>) -> ConfirmResponse {
}
}
- let title = display_str_to_cstr_vec(util::strings::truncate_str(
- params.title,
- LABEL_TRUNCATE_SIZE,
- ));
- let body = display_str_to_cstr_vec(util::strings::truncate_str(
- params.body,
- LABEL_TRUNCATE_SIZE,
- ));
+ let title = display_str_to_cstr_vec(
+ util::strings::truncate_str(params.title, LABEL_TRUNCATE_SIZE),
+ &Font::Regular11,
+ );
+ let body = display_str_to_cstr_vec(
+ util::strings::truncate_str(params.body, LABEL_TRUNCATE_SIZE),
+ ¶ms.font,
+ );
let c_params = bitbox02_sys::confirm_params_t {
title: title.as_ptr().cast(),
title_autowrap: params.title_autowrap,
@@ -319,7 +334,7 @@ pub fn screen_process() {
pub fn status_create(text: &str, status_success: bool) -> Component {
let component = unsafe {
bitbox02_sys::status_create(
- display_str_to_cstr_vec(text).as_ptr(), // copied in C
+ display_str_to_cstr_vec(text, &Font::Regular11).as_ptr(), // copied in C
status_success,
)
};
@@ -333,7 +348,7 @@ pub fn info_centered_create(text: &str) -> Component {
Component {
component: unsafe {
bitbox02_sys::info_centered_create(
- display_str_to_cstr_vec(text).as_ptr(), // copied in C
+ display_str_to_cstr_vec(text, &Font::Regular11).as_ptr(), // copied in C
None,
)
},
@@ -456,7 +471,7 @@ pub async fn menu(params: MenuParams<'_>) -> MenuResponse {
let words: Vec<_> = params
.words
.iter()
- .map(|word| display_str_to_cstr_vec(word))
+ .map(|word| display_str_to_cstr_vec(word, &Font::Regular11))
.collect();
// Step two: collect pointers. This var also has to be valid until menu() finishes, or
// the pointer will be invalid.
@@ -478,7 +493,9 @@ pub async fn menu(params: MenuParams<'_>) -> MenuResponse {
shared_state_ptr, // passed to continue_on_last_cb as `user_data`.
),
};
- let title = params.title.map(display_str_to_cstr_vec);
+ let title = params
+ .title
+ .map(|title| display_str_to_cstr_vec(title, &Font::Regular11));
let component = unsafe {
bitbox02_sys::menu_create(
c_words.as_ptr(),
@@ -572,13 +589,13 @@ pub async fn trinary_choice(
}
}
- let label_left = label_left.map(display_str_to_cstr_vec);
- let label_middle = label_middle.map(display_str_to_cstr_vec);
- let label_right = label_right.map(display_str_to_cstr_vec);
+ let label_left = label_left.map(|label| display_str_to_cstr_vec(label, &Font::Regular11));
+ let label_middle = label_middle.map(|label| display_str_to_cstr_vec(label, &Font::Regular11));
+ let label_right = label_right.map(|label| display_str_to_cstr_vec(label, &Font::Regular11));
let component = unsafe {
bitbox02_sys::trinary_choice_create(
- display_str_to_cstr_vec(message).as_ptr(), // copied in C
+ display_str_to_cstr_vec(message, &Font::Regular11).as_ptr(), // copied in C
// copied in C
label_left
.as_ref()
@@ -651,8 +668,8 @@ pub async fn confirm_transaction_address(amount: &str, address: &str) -> Confirm
let component = unsafe {
bitbox02_sys::confirm_transaction_address_create(
- display_str_to_cstr_vec(amount).as_ptr(), // copied in C
- display_str_to_cstr_vec(address).as_ptr(), // copied in C
+ display_str_to_cstr_vec(amount, &transaction_amount_font(amount)).as_ptr(), // copied in C
+ display_str_to_cstr_vec(address, &Font::Regular11).as_ptr(), // copied in C
Some(callback),
shared_state_ptr, // passed to callback as `user_data`.
)
@@ -712,9 +729,9 @@ pub async fn confirm_swap(title: &str, from: &str, to: &str) -> ConfirmResponse
let component = unsafe {
bitbox02_sys::confirm_swap_create(
- display_str_to_cstr_vec(title).as_ptr(), // copied in C
- display_str_to_cstr_vec(from).as_ptr(), // copied in C
- display_str_to_cstr_vec(to).as_ptr(), // copied in C
+ display_str_to_cstr_vec(title, &Font::Regular11).as_ptr(), // copied in C
+ display_str_to_cstr_vec(from, &transaction_amount_font(from)).as_ptr(), // copied in C
+ display_str_to_cstr_vec(to, &transaction_amount_font(to)).as_ptr(), // copied in C
Some(callback),
shared_state_ptr, // passed to callback as `user_data`.
)
@@ -774,8 +791,8 @@ pub async fn confirm_transaction_fee(amount: &str, fee: &str, longtouch: bool) -
let component = unsafe {
bitbox02_sys::confirm_transaction_fee_create(
- display_str_to_cstr_vec(amount).as_ptr(), // copied in C
- display_str_to_cstr_vec(fee).as_ptr(), // copied in C
+ display_str_to_cstr_vec(amount, &transaction_amount_font(amount)).as_ptr(), // copied in C
+ display_str_to_cstr_vec(fee, &Font::Regular9).as_ptr(), // copied in C
longtouch,
Some(callback),
shared_state_ptr, // passed to callback as `user_data`.
@@ -814,7 +831,7 @@ pub fn screen_stack_pop_all() {
pub fn progress_create(title: &str) -> Component {
let component = unsafe {
bitbox02_sys::progress_create(
- display_str_to_cstr_vec(title).as_ptr(), // copied in C
+ display_str_to_cstr_vec(title, &Font::Regular11).as_ptr(), // copied in C
)
};
@@ -923,3 +940,52 @@ pub async fn choose_orientation() -> bool {
})
.await
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_display_str_to_cstr_vec() {
+ for (font, text) in [
+ (Font::Regular11, "Café\nZürich"),
+ (Font::Regular9, "Café\nZürich"),
+ (Font::Password12, "Café\nZürich"),
+ (Font::Monogram16, "ABCD 1234\nEFGH 5678"),
+ ] {
+ let encoded = display_str_to_cstr_vec(text, &font);
+ let decoded = unsafe { core::ffi::CStr::from_ptr(encoded.as_ptr()) };
+ assert_eq!(decoded.to_str().unwrap(), text);
+ }
+ }
+
+ #[async_test::test]
+ #[should_panic(expected = "BitBox02 UI text contains unsupported characters")]
+ async fn test_confirm_rejects_missing_body_glyph() {
+ confirm(&ConfirmParams {
+ title: "Confirm",
+ body: "Café",
+ font: Font::Monogram16,
+ ..Default::default()
+ })
+ .await;
+ }
+
+ #[async_test::test]
+ async fn test_confirm_uses_regular11_font_for_title() {
+ crate::screen::init(|_, _, _| {}, |_| {}, || {});
+ let params = ConfirmParams {
+ title: "Café",
+ body: "ABCD 1234",
+ font: Font::Monogram16,
+ ..Default::default()
+ };
+ assert!(
+ futures_lite::future::poll_once(confirm(¶ms))
+ .await
+ .is_none()
+ );
+ // Dropping the pending confirmation queues its C component for cleanup.
+ crate::screen::process(true);
+ }
+}
### src/rust/bitbox03/src/ui.rs
@@ -71,6 +71,10 @@ impl<Timer: bitbox_hal::timer::Timer> hal::ui::Ui for BitBox03Ui<Timer> {
self.with_result_screen(demo::build_demo_screen).await
}
+ fn has_glyph(&self, _font: bitbox_hal::ui::Font, c: char) -> bool {
+ matches!(c, ' '..='~')
+ }
+
async fn confirm_swap(
&mut self,
title: &str,
### src/rust/util/src/name.rs
@@ -1,49 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
-use super::ascii;
-
/// Validate a user given name. The name must be smaller or equal to `max_len` and larger than 0 in
-/// size, consist of printable ASCII characters only (and space), not
-/// start or end with whitespace, and contain no whitespace other than space.
+/// size, contain no control characters, not start or end with whitespace, and contain no
+/// whitespace other than space.
+/// Callers must check glyph availability before displaying the name.
pub fn validate(name: &str, max_len: usize) -> bool {
if name.is_empty() || name.len() > max_len {
return false;
}
- if !ascii::is_printable_ascii(name, ascii::Charset::All) {
+ if name
+ .chars()
+ .any(|c| c.is_control() || (c.is_whitespace() && c != ' '))
+ {
return false;
}
- // Safe because all_ascii passed.
let bytes = name.as_bytes();
if bytes[0] == b' ' || bytes[bytes.len() - 1] == b' ' {
return false;
}
true
}
-//
-// C interface
-//
-
-/// Calls `util::name::validate()` on the provided C string.
-///
-/// # Safety
-///
-/// `buf` must point to a valid buffer of size `max_len`.
-#[unsafe(no_mangle)]
-pub unsafe extern "C" fn rust_util_is_name_valid(buf: *const u8, max_len: usize) -> bool {
- if max_len == 0 {
- return false;
- }
- let slice = unsafe { core::slice::from_raw_parts(buf, max_len) };
- match core::ffi::CStr::from_bytes_until_nul(slice) {
- Ok(cstr) => match cstr.to_str() {
- Ok(s) => validate(s, max_len - 1),
- Err(_) => false,
- },
- Err(_) => false,
- }
-}
-
#[cfg(test)]
mod tests {
extern crate std;
@@ -56,34 +33,21 @@ mod tests {
assert!(validate("foo", 4));
assert!(validate("foo", 3));
assert!(!validate("foo", 2));
+ assert!(validate("ä", 2));
+ assert!(!validate("ä", 1));
// Min len.
assert!(!validate("", 100));
- // Ascii.
+ // Name characters.
assert!(validate("some name", 100));
+ assert!(validate("BïtBöx Zürich", 100));
assert!(!validate("\n", 100));
assert!(!validate("\t", 100));
+ assert!(validate("東京", 100));
+ assert!(!validate("non\u{a0}breaking", 100));
// Starts / ends with space.
assert!(!validate(" foo", 100));
assert!(!validate("foo ", 100));
}
-
- #[test]
- // For clarity we want explicit null terminators in the strings below, not CStr literals
- // `c"..."`.
- #[allow(clippy::manual_c_str_literals)]
- fn test_rust_util_is_name_valid() {
- unsafe {
- // Valid
- assert!(rust_util_is_name_valid("foo\0".as_ptr(), 4));
- assert!(rust_util_is_name_valid("foo\0........".as_ptr(), 12));
-
- // Invalid
- assert!(!rust_util_is_name_valid("fo\no\0".as_ptr(), 5));
- assert!(!rust_util_is_name_valid("".as_ptr(), 0));
- assert!(!rust_util_is_name_valid("foo\0".as_ptr(), 3));
- assert!(!rust_util_is_name_valid("foo".as_ptr(), 3));
- }
- }
}
### src/screen.c
@@ -7,7 +7,7 @@
#include <stdint.h>
#include <string.h>
#include <ui/components/ui_images.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/oled/oled.h>
#include <ui/ugui/ugui.h>
#include <util.h>
@@ -55,7 +55,7 @@ void screen_print_debug(const char* message, int duration)
char print[100] = {0};
_escape_debug_string(print, sizeof(print), message);
screen_clear();
- UG_FontSelect(&font_font_a_9X9);
+ UG_FontSelect(&font_regular_9);
UG_PutString(0, 0, print);
UG_SendBuffer();
#ifndef TESTING
@@ -124,9 +124,9 @@ void screen_init(
_mirror_fn = mirror_fn;
_clear_fn = clear_fn;
#ifdef BOOTLOADER
- UG_Init(&guioled, pixel_fn, &font_font_a_9X9, SCREEN_WIDTH, SCREEN_HEIGHT);
+ UG_Init(&guioled, pixel_fn, &font_regular_9, SCREEN_WIDTH, SCREEN_HEIGHT);
#else
- UG_Init(&guioled, pixel_fn, &font_font_a_11X10, SCREEN_WIDTH, SCREEN_HEIGHT);
+ UG_Init(&guioled, pixel_fn, &font_regular_11, SCREEN_WIDTH, SCREEN_HEIGHT);
#endif
}
### src/ui/components/button.c
@@ -6,7 +6,7 @@
#include <hardfault.h>
#include <screen.h>
#include <touch/gestures.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ui_util.h>
#include <stdbool.h>
@@ -32,7 +32,7 @@ typedef struct {
static void _render(component_t* component)
{
button_data_t* data = (button_data_t*)component->data;
- UG_FontSelect(&font_font_a_11X10);
+ UG_FontSelect(&font_regular_11);
UG_FontSetHSpace(0);
UG_PutStringCentered(
component->position.left,
@@ -163,13 +163,10 @@ void button_update(component_t* button, const char* text, void (*callback)(compo
{
button_data_t* data = (button_data_t*)button->data;
data->callback = callback;
- if (!util_is_printable_ascii(text, true)) {
- Abort("Unsupported button character");
- }
if (util_utf8_strlcpy(data->text, text, sizeof(data->text)) < 0) {
Abort("Invalid UTF-8 button");
}
- UG_FontSelect(&font_font_a_11X10);
+ UG_FontSelect(&font_regular_11);
UG_FontSetHSpace(0);
UG_MeasureString(&(button->dimension.width), &(button->dimension.height), data->text);
if (button->dimension.width < MIN_BUTTON_WIDTH) {
### src/ui/components/confirm.c
@@ -9,7 +9,7 @@
#include <hardfault.h>
#include <screen.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ugui/ugui.h>
#include <string.h>
@@ -96,7 +96,7 @@ component_t* confirm_create(
// Create labels. We nest them in a body component that covers the screen minus the title bar,
// so that the CENTER positioning starts below the title bar.
- const UG_FONT* font = &font_font_a_11X10;
+ const UG_FONT* font = &font_regular_11;
const char* title = params->title;
// Arbitrary size big enough to fit all wrapped titles. Increase if needed.
char wrapped_title[128] = {0};
### src/ui/components/confirm.h
@@ -16,6 +16,8 @@ typedef struct {
bool title_autowrap;
// The confirmation body of the screen.
const char* body;
+ // Font retained by the created labels, or NULL for the default font. Must have static lifetime
+ // if non-NULL.
const UG_FONT* font;
// If true, the body is horizontally scrollable.
bool scrollable;
@@ -32,7 +34,8 @@ typedef struct {
/**
* Creates a confirm screen.
- * @param[in] params see confirm_params_t for details.
+ * @param[in] params see confirm_params_t for details. A non-NULL params->font must have static
+ * lifetime because the created labels retain it.
* @param[in] callback The callback triggered when the user accepts or rejects. Will be called at
* most once.
* @param[in] user_data passed through to the callback.
### src/ui/components/confirm_swap.c
@@ -8,7 +8,7 @@
#include <hardfault.h>
#include <screen.h>
#include <string.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <util.h>
typedef struct {
@@ -93,11 +93,11 @@ component_t* confirm_swap_create(
ui_util_add_sub_component(
confirm, icon_button_create(top_slider, ICON_BUTTON_NEXT, _confirm_cb, confirm));
- component_t* title_component = label_create(title, &font_font_a_11X10, CENTER_TOP, confirm);
+ component_t* title_component = label_create(title, &font_regular_11, CENTER_TOP, confirm);
ui_util_add_sub_component(confirm, title_component);
- const UG_FONT* from_font = label_fits_width(from, NULL, SCREEN_WIDTH) ? NULL : &font_font_a_9X9;
- const UG_FONT* to_font = label_fits_width(to, NULL, SCREEN_WIDTH) ? NULL : &font_font_a_9X9;
+ const UG_FONT* from_font = label_fits_width(from, NULL, SCREEN_WIDTH) ? NULL : &font_regular_9;
+ const UG_FONT* to_font = label_fits_width(to, NULL, SCREEN_WIDTH) ? NULL : &font_regular_9;
ui_util_add_sub_component(
confirm, label_create_offset(from, from_font, CENTER_TOP, 0, 17, confirm));
### src/ui/components/confirm_transaction.c
@@ -10,7 +10,7 @@
#include <screen.h>
#include <stdbool.h>
#include <string.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <util.h>
typedef struct {
@@ -117,13 +117,13 @@ static component_t* _confirm_transaction_create(
}
if (strlens(fee)) {
ui_util_add_sub_component(
- confirm, label_create_offset("Fee", &font_font_a_9X9, CENTER_TOP, 0, 38, confirm));
+ confirm, label_create_offset("Fee", &font_regular_9, CENTER_TOP, 0, 38, confirm));
ui_util_add_sub_component(
- confirm, label_create_offset(fee, &font_font_a_9X9, CENTER_TOP, 0, 50, confirm));
+ confirm, label_create_offset(fee, &font_regular_9, CENTER_TOP, 0, 50, confirm));
}
const UG_FONT* amount_font =
- label_fits_width(amount, NULL, SCREEN_WIDTH) ? NULL : &font_font_a_9X9;
+ label_fits_width(amount, NULL, SCREEN_WIDTH) ? NULL : &font_regular_9;
if (verify_total) {
ui_util_add_sub_component(
confirm, label_create_offset("Total", NULL, CENTER_TOP, 0, 8, confirm));
### src/ui/components/keyboard_switch.c
@@ -7,7 +7,7 @@
#include <hardfault.h>
#include <screen.h>
#include <touch/gestures.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ui_util.h>
#include <stdbool.h>
@@ -32,7 +32,7 @@ typedef struct {
static void _render(component_t* component)
{
keyboard_switch_data_t* ks_data = (keyboard_switch_data_t*)component->data;
- UG_FontSelect(&font_font_a_11X10);
+ UG_FontSelect(&font_regular_11);
UG_S16 w = 0, h = 0;
switch (ks_data->mode) {
case LOWER_CASE:
### src/ui/components/label.c
@@ -7,7 +7,7 @@
#include <screen.h>
#include <string.h>
#include <touch/gestures.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ugui/ugui.h>
#include <ui/ui_util.h>
#include <util.h>
@@ -34,17 +34,14 @@ bool label_fits_width(const char* text, const UG_FONT* font, uint16_t max_width)
{
UG_S16 width;
UG_S16 height;
- UG_FontSelect(font != NULL ? font : &font_font_a_11X10);
+ UG_FontSelect(font != NULL ? font : &font_regular_11);
UG_MeasureStringNoBreak(&width, &height, text);
return width <= max_width;
}
void label_update(component_t* component, const char* text)
{
data_t* data = (data_t*)component->data;
- if (!util_is_printable_ascii(text, true)) {
- Abort("Unsupported label character");
- }
const intptr_t result = util_utf8_strlcpy(data->text, text, MAX_LABEL_SIZE + 1);
if (result < 0) {
Abort("Invalid UTF-8 label");
@@ -211,6 +208,7 @@ static const component_functions_t _component_functions = {
/********************************** Create Instance **********************************/
+// A non-NULL `font` must have static lifetime: the label and current GUI retain it.
static component_t* _label_create(
const char* text,
const UG_FONT* font,
@@ -231,7 +229,7 @@ static component_t* _label_create(
memset(data, 0, sizeof(data_t));
memset(label, 0, sizeof(component_t));
- data->font = font != NULL ? font : &font_font_a_11X10;
+ data->font = font != NULL ? font : &font_regular_11;
data->scrollable = scrollable;
data->position = position;
data->xoffset = xoffset;
### src/ui/components/label.h
@@ -16,7 +16,8 @@
/**
* Returns true if the text fits within max_width without wrapping using the given font.
* @param[in] text The text to measure.
- * @param[in] font The font to use. If NULL, the default 11x10 font is used.
+ * @param[in] font The font to use. If NULL, the default 11x10 font is used. A non-NULL font
+ * must have static lifetime: it remains selected in the current GUI after this call.
* @param[in] max_width The available width in pixels.
*/
bool label_fits_width(const char* text, const UG_FONT* font, uint16_t max_width);
@@ -32,7 +33,8 @@ void label_update(component_t* component, const char* text);
* Creates a label with the given font. If the text is longer than MAX_LABEL_SIZE, it is truncated
* and suffixed with '...'.
* @param[in] text The text of the label.
- * @param[in] font The font of the label.
+ * @param[in] font The font retained by the label, or NULL for the default font. A non-NULL font
+ * must have static lifetime.
* @param[in] position The position of the label.
* @param[in] parent The parent component.
*/
@@ -45,7 +47,8 @@ component_t* label_create(
/**
* Creates a label with the given font.
* @param[in] text The text of the label.
- * @param[in] font The font of the label.
+ * @param[in] font The font retained by the label, or NULL for the default font. A non-NULL font
+ * must have static lifetime.
* @param[in] position The position of the label.
* @param[in] xoffset The horizontal offset.
* @param[in] yoffset The vertical offset.
@@ -62,7 +65,8 @@ component_t* label_create_offset(
/**
* Creates a label with the given font that can be scrolled.
* @param[in] text The text of the label.
- * @param[in] font The font of the label.
+ * @param[in] font The font retained by the label, or NULL for the default font. A non-NULL font
+ * must have static lifetime.
* @param[in] position The position of the label.
* @param[in] parent The parent component.
*/
@@ -75,7 +79,8 @@ component_t* label_create_scrollable(
/**
* Creates a label with the given font that can be scrolled.
* @param[in] text The text of the label.
- * @param[in] font The font of the label.
+ * @param[in] font The font retained by the label, or NULL for the default font. A non-NULL font
+ * must have static lifetime.
* @param[in] position The position of the label.
* @param[in] xoffset The horizontal offset.
* @param[in] yoffset The vertical offset.
### src/ui/components/lockscreen.c
@@ -10,7 +10,7 @@
#include <screen.h>
#include <string.h>
#include <touch/gestures.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <util.h>
/********************************** Component Functions **********************************/
@@ -28,6 +28,7 @@ static const component_functions_t _component_functions = {
// Outputs `in` as is if it can be rendered to fit in `max_width`.
// If it can't, it is truncated (with appended "...") to a size where it fits.
+// `font` must have static lifetime because it remains selected in the current GUI.
static void _truncate_to_fit(
const char* in,
char* out,
@@ -46,37 +47,37 @@ static void _truncate_to_fit(
out[0] = 0;
return;
}
- if (!util_is_printable_ascii(in, false)) {
- out[0] = 0;
- return;
- }
UG_S16 width = 0;
UG_S16 height = 0;
UG_FontSelect(font);
UG_MeasureStringCentered(&width, &height, in);
// Name fits without truncation.
if (width <= max_width) {
- util_utf8_strlcpy(out, in, out_len);
+ if (util_utf8_strlcpy(out, in, out_len) < 0) {
+ out[0] = 0;
+ }
return;
}
// Truncate if too long to a size where "<name>..." fits.
const size_t text_capacity = out_len - 4;
- size_t truncate_len = MIN(strlen(in), text_capacity);
+ const size_t in_len = strlen(in);
+ size_t truncate_len = MIN(in_len, text_capacity);
do {
- const intptr_t result = util_utf8_copy(out, out_len, in, truncate_len);
+ // Limit the copied prefix while validating the complete UTF-8 input.
+ const intptr_t result = util_utf8_copy(out, truncate_len + 1, in, in_len);
if (result < 0) {
out[0] = 0;
return;
}
const size_t copied_len = (size_t)result;
memcpy(&out[copied_len], "...", 4);
UG_MeasureStringCentered(&width, &height, out);
- if (truncate_len == 0) {
+ if (copied_len == 0) {
break;
}
- truncate_len--;
+ truncate_len = copied_len - 1;
} while (width >= max_width);
}
@@ -92,7 +93,7 @@ component_t* lockscreen_create(void)
component->dimension.width = SCREEN_WIDTH;
component->dimension.height = SCREEN_HEIGHT;
- const UG_FONT* device_name_font = &font_font_a_9X9;
+ const UG_FONT* device_name_font = &font_regular_9;
char device_name[MEMORY_DEVICE_MAX_LEN_WITH_NULL] = {0};
memory_get_device_name(device_name);
### src/ui/components/trinary_input_char.c
@@ -6,10 +6,11 @@
#include <hardfault.h>
#include <touch/gestures.h>
-#include <ui/fonts/password_11X12.h>
-#include <ui/fonts/password_9X9.h>
+#include <ui/fonts/password_12.h>
+#include <ui/fonts/password_9.h>
#include <ui/ui_util.h>
#include <util.h>
+#include <utils_assert.h>
#include <string.h>
@@ -34,6 +35,15 @@ typedef struct {
// Each of the three groups can occupy roughly a third of the width.
static const UG_S16 _group_width = SCREEN_WIDTH / 3;
+static UG_U16 _char_width(const UG_FONT* font, char chr)
+{
+ UG_U16 width = 0;
+ const bool found = UG_GetCharWidth(font, (uint8_t)chr, &width);
+ ASSERT(found);
+ (void)found;
+ return width;
+}
+
// Stack entry for navigation history
typedef struct {
char alphabet[MAX_CHARS + 1];
@@ -256,15 +266,15 @@ static void _put_string(
UG_S16 total_width = 0;
for (size_t idx = 0; idx < elements_size; idx++) {
char c = elements[idx]->character;
- total_width += font->widths[c - font->start_char];
+ total_width += _char_width(font, c);
total_width += horiz_space;
}
// Split into two rows of roughly equal size by number of elements if too big.
if (elements_size > 6) {
// split in two halfs; size/2 rounded up
const size_t half = (elements_size + 1) / 2;
- _put_string(font, x_offset, y_offset - font->char_height - 1, horiz_space, elements, half);
+ _put_string(font, x_offset, y_offset - font->line_height - 1, horiz_space, elements, half);
_put_string(font, x_offset, y_offset, horiz_space, elements + half, elements_size - half);
return;
}
@@ -275,8 +285,7 @@ static void _put_string(
char c = elements[idx]->character;
bool update_position = !element->newly_born;
element->target_x = x;
- x += c == ' ' ? UI_UTIL_VISIBLE_SPACE_WIDTH
- : font->widths[element->character - font->start_char];
+ x += c == ' ' ? UI_UTIL_VISIBLE_SPACE_WIDTH : _char_width(font, element->character);
x += horiz_space;
element->target_y = y_offset;
if (!update_position) {
@@ -301,9 +310,9 @@ static void _set_alphabet_internal(
// Switch to larger font for fewer characters
if (len < 12) {
- data->font = &font_password_11X12;
+ data->font = &font_password_12;
} else {
- data->font = &font_password_9X9;
+ data->font = &font_password_9;
}
size_t a = 0;
@@ -354,7 +363,7 @@ static void _set_alphabet_internal(
element->character = alphabet[char_idx];
}
- UG_S16 y_offset = SCREEN_HEIGHT - data->font->char_height;
+ UG_S16 y_offset = SCREEN_HEIGHT - data->font->line_height;
{ // left
_put_string(data->font, 0, y_offset, data->horiz_space, elements_lookup, left_size);
}
@@ -425,7 +434,7 @@ component_t* trinary_input_char_create(
}
memset(component, 0, sizeof(component_t));
- data->font = &font_password_9X9;
+ data->font = &font_password_9;
component->data = data;
component->parent = parent;
component->f = &_component_functions;
### src/ui/components/trinary_input_string.c
@@ -14,7 +14,7 @@
#include <touch/gestures.h>
#include <ui/event.h>
#include <ui/event_handler.h>
-#include <ui/fonts/password_11X12.h>
+#include <ui/fonts/password_12.h>
#include <ui/ugui/ugui.h>
#include <ui/ui_util.h>
#include <util.h>
@@ -43,12 +43,19 @@
static char _alphabet_uppercase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static char _alphabet_lowercase[] = "abcdefghijklmnopqrstuvwxyz";
static char _digits[] = "0123456789";
-// ` and ~ are missing here as they don't legible on the device with arial 9x9. Can add them back
+// ` and ~ are missing here as they don't legible on the device with regular 9x9. Can add them back
// after tuning the font.
// Keep in sync with SPECIAL in src/rust/bitbox02-rust/src/hww/api/unlock.rs.
static char _special_chars[] = " !\"#$%&'()*+,-./:;<=>?^[\\]@_{|}";
-static const UG_FONT* _font = &font_password_11X12;
+static const UG_FONT* _font = &font_password_12;
+
+static UG_U16 _char_width(char chr)
+{
+ UG_U16 width = 0;
+ UG_GetCharWidth(_font, (uint8_t)chr, &width);
+ return width;
+}
static void _get_bip39_word_stack(uint16_t idx, char* word_out, size_t word_out_size)
{
@@ -121,10 +128,10 @@ static UG_S16 _constant_string_width(const component_t* component)
for (size_t i = 0; i <= data->string_index; i++) {
if (i == data->string_index) {
char chr = EMPTY_CHAR;
- width += _font->widths[chr - _font->start_char];
+ width += _char_width(chr);
} else if (!data->hide) {
char chr = data->string[i];
- width += _font->widths[chr - _font->start_char];
+ width += _char_width(chr);
} else {
width += MASK_CHAR_WIDTH;
}
@@ -174,14 +181,14 @@ static void _render(component_t* component)
}
char chr;
- uint8_t width;
+ UG_U16 width;
if (i == data->string_index) {
chr = EMPTY_CHAR;
- width = _font->widths[chr - _font->start_char];
+ width = _char_width(chr);
} else if ((data->show_last_character && i == data->string_index - 1) || !data->hide) {
// Show character (or only last entered character in if input is hidden).
chr = data->string[i];
- width = _font->widths[chr - _font->start_char];
+ width = _char_width(chr);
} else {
// ad-hoc encoding of the masked char, which will be drawn as a filled circle below.
chr = '\0';
@@ -204,7 +211,7 @@ static void _render(component_t* component)
// Draw '...' when the left part scrolled out of view.
if (data->target_x < STRING_POS_X_START) {
// HACK: blank out the chars rendered at this position first.
- UG_FillFrame(0, STRING_POS_Y, 11, STRING_POS_Y + _font->char_height, screen_back_color);
+ UG_FillFrame(0, STRING_POS_Y, 11, STRING_POS_Y + _font->line_height, screen_back_color);
UG_PutString(0, STRING_POS_Y, "...");
}
### src/ui/fonts/arial_fonts.h
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef _ARIAL_FONTS_H_
-#define _ARIAL_FONTS_H_
-
-#include "font_a_11X10.h"
-#include "font_a_11X12.h"
-#include "font_a_13X14.h"
-#include "font_a_15X16.h"
-#include "font_a_17X18.h"
-#include "font_a_9X9.h"
-#include "monogram_5X9.h"
-
-#endif
### src/ui/fonts/font_a_11X10.c
@@ -1,107 +0,0 @@
-// Converted from font_a.ttf
-// --size 11
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_11X10[95][20] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x20 ' '
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x21 '!'
- {0x05,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x22 '"'
- {0x14,0x00,0x14,0x00,0x1F,0x00,0x0A,0x00,0x0A,0x00,0x1F,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00 }, // 0x23 '#'
- {0x0E,0x00,0x15,0x00,0x05,0x00,0x0E,0x00,0x14,0x00,0x14,0x00,0x15,0x00,0x0E,0x00,0x04,0x00,0x00,0x00 }, // 0x24 '$'
- {0x46,0x00,0x29,0x00,0x29,0x00,0x16,0x00,0xD0,0x00,0x28,0x01,0x28,0x01,0xC4,0x00,0x00,0x00,0x00,0x00 }, // 0x25 '%'
- {0x0C,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0A,0x00,0x31,0x00,0x11,0x00,0x2E,0x00,0x00,0x00,0x00,0x00 }, // 0x26 '&'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x27 '''
- {0x04,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x04,0x00 }, // 0x28 '('
- {0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x00 }, // 0x29 ')'
- {0x02,0x00,0x07,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2A '*'
- {0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2B '+'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00 }, // 0x2C ','
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2D '-'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x2E '.'
- {0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x2F '/'
- {0x0E,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x30 '0'
- {0x04,0x00,0x06,0x00,0x05,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x31 '1'
- {0x0E,0x00,0x11,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x32 '2'
- {0x0E,0x00,0x11,0x00,0x10,0x00,0x0C,0x00,0x10,0x00,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x33 '3'
- {0x08,0x00,0x0C,0x00,0x0A,0x00,0x0A,0x00,0x09,0x00,0x1F,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x34 '4'
- {0x1E,0x00,0x02,0x00,0x01,0x00,0x0F,0x00,0x10,0x00,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x35 '5'
- {0x0E,0x00,0x11,0x00,0x01,0x00,0x0F,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x36 '6'
- {0x1F,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x37 '7'
- {0x0E,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x38 '8'
- {0x0E,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x1E,0x00,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x39 '9'
- {0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x3A ':'
- {0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00 }, // 0x3B ';'
- {0x00,0x00,0x00,0x00,0x10,0x00,0x0E,0x00,0x01,0x00,0x0E,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3C '<'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3D '='
- {0x00,0x00,0x00,0x00,0x01,0x00,0x0E,0x00,0x10,0x00,0x0E,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3E '>'
- {0x0E,0x00,0x11,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x3F '?'
- {0xF8,0x00,0x06,0x01,0xB2,0x02,0xC9,0x02,0x45,0x02,0x45,0x02,0x65,0x01,0xD9,0x00,0x02,0x02,0xFC,0x01 }, // 0x40 '@'
- {0x08,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x22,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00 }, // 0x41 'A'
- {0x1F,0x00,0x21,0x00,0x21,0x00,0x1F,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x42 'B'
- {0x1C,0x00,0x22,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x43 'C'
- {0x0F,0x00,0x11,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x11,0x00,0x0F,0x00,0x00,0x00,0x00,0x00 }, // 0x44 'D'
- {0x1F,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x45 'E'
- {0x1F,0x00,0x01,0x00,0x01,0x00,0x0F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x46 'F'
- {0x1C,0x00,0x22,0x00,0x41,0x00,0x01,0x00,0x71,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x47 'G'
- {0x21,0x00,0x21,0x00,0x21,0x00,0x3F,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x00,0x00,0x00,0x00 }, // 0x48 'H'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x49 'I'
- {0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x4A 'J'
- {0x21,0x00,0x11,0x00,0x09,0x00,0x0D,0x00,0x0B,0x00,0x11,0x00,0x11,0x00,0x21,0x00,0x00,0x00,0x00,0x00 }, // 0x4B 'K'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x4C 'L'
- {0x41,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x4D 'M'
- {0x21,0x00,0x23,0x00,0x25,0x00,0x25,0x00,0x29,0x00,0x29,0x00,0x31,0x00,0x21,0x00,0x00,0x00,0x00,0x00 }, // 0x4E 'N'
- {0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x4F 'O'
- {0x0F,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x0F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x50 'P'
- {0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x59,0x00,0x22,0x00,0x7C,0x00,0x00,0x00,0x00,0x00 }, // 0x51 'Q'
- {0x1F,0x00,0x21,0x00,0x21,0x00,0x1F,0x00,0x09,0x00,0x11,0x00,0x11,0x00,0x21,0x00,0x00,0x00,0x00,0x00 }, // 0x52 'R'
- {0x1E,0x00,0x21,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x20,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x53 'S'
- {0x1F,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x54 'T'
- {0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x55 'U'
- {0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x56 'V'
- {0x21,0x04,0x51,0x04,0x52,0x02,0x52,0x02,0x8a,0x02,0x8a,0x02,0x04,0x01,0x04,0x01,0x00,0x00,0x00,0x00 }, // 0x57 'W'
- {0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x00,0x00,0x00,0x00 }, // 0x58 'X'
- {0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x59 'Y'
- {0x3E,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x3F,0x00,0x00,0x00,0x00,0x00 }, // 0x5A 'Z'
- {0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x03,0x00 }, // 0x5B '['
- {0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x5C '\'
- {0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00 }, // 0x5D ']'
- {0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5E '^'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00 }, // 0x5F '_'
- {0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x60 '`'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x11,0x00,0x1E,0x00,0x11,0x00,0x19,0x00,0x17,0x00,0x00,0x00,0x00,0x00 }, // 0x61 'a'
- {0x01,0x00,0x01,0x00,0x0D,0x00,0x13,0x00,0x11,0x00,0x11,0x00,0x13,0x00,0x0D,0x00,0x00,0x00,0x00,0x00 }, // 0x62 'b'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x11,0x00,0x01,0x00,0x01,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x63 'c'
- {0x10,0x00,0x10,0x00,0x16,0x00,0x19,0x00,0x11,0x00,0x11,0x00,0x19,0x00,0x16,0x00,0x00,0x00,0x00,0x00 }, // 0x64 'd'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x11,0x00,0x1F,0x00,0x01,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x65 'e'
- {0x04,0x00,0x02,0x00,0x07,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x66 'f'
- {0x00,0x00,0x00,0x00,0x16,0x00,0x19,0x00,0x11,0x00,0x11,0x00,0x19,0x00,0x16,0x00,0x10,0x00,0x0F,0x00 }, // 0x67 'g'
- {0x01,0x00,0x01,0x00,0x0D,0x00,0x13,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00 }, // 0x68 'h'
- {0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x69 'i'
- {0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x00,0x00 }, // 0x6A 'j'
- {0x01,0x00,0x01,0x00,0x09,0x00,0x05,0x00,0x03,0x00,0x07,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x6B 'k'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x6C 'l'
- {0x00,0x00,0x00,0x00,0x3D,0x00,0x4B,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x6D 'm'
- {0x00,0x00,0x00,0x00,0x0F,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00 }, // 0x6E 'n'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x6F 'o'
- {0x00,0x00,0x00,0x00,0x0D,0x00,0x13,0x00,0x11,0x00,0x11,0x00,0x13,0x00,0x0D,0x00,0x01,0x00,0x01,0x00 }, // 0x70 'p'
- {0x00,0x00,0x00,0x00,0x16,0x00,0x19,0x00,0x11,0x00,0x11,0x00,0x19,0x00,0x16,0x00,0x10,0x00,0x10,0x00 }, // 0x71 'q'
- {0x00,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x72 'r'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x11,0x00,0x06,0x00,0x08,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x73 's'
- {0x02,0x00,0x02,0x00,0x07,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x74 't'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x19,0x00,0x16,0x00,0x00,0x00,0x00,0x00 }, // 0x75 'u'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x76 'v'
- {0x00,0x00,0x00,0x00,0x11,0x01,0x29,0x01,0xAA,0x00,0xAA,0x00,0x44,0x00,0x44,0x00,0x00,0x00,0x00,0x00 }, // 0x77 'w'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x0A,0x00,0x04,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x00,0x00,0x00,0x00 }, // 0x78 'x'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x79 'y'
- {0x00,0x00,0x00,0x00,0x1F,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x7A 'z'
- {0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00 }, // 0x7B '{'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00 }, // 0x7C '|'
- {0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x7D '}'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_11X10[] = {
-3,2,4,6,6,10,7,2,4,4,4,6,3,4,3,3,6,6,6,6,6,6,6,6,6,6,3,3,6,6,6,6,11,8,7,7,7,6,6,8,7,2,5,7,6,8,7,8,6,8,7,7,6,7,8,11,7,8,7,3,3,3,5,6,4,6,6,6,6,6,4,6,6,2,3,5,2,8,6,6,6,6,4,6,4,6,6,10,6,6,6,4,2,4,6};
-const UG_FONT font_font_a_11X10 = { (unsigned char*)fontBits_font_a_11X10, FONT_TYPE_1BPP, 11, 10, 32, 126, fontWidths_font_a_11X10 };
### src/ui/fonts/font_a_11X10.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_11X10;
### src/ui/fonts/font_a_11X12.c
@@ -1,109 +0,0 @@
-// Converted from font_a.ttf
-// --size 12
-// --dpi 72
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_11X12[95][24] = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20 ' '
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!'
- {0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '"'
- {0x28, 0x00, 0x28, 0x00, 0x7F, 0x00, 0x14, 0x00, 0x14, 0x00, 0x7F, 0x00, 0x14, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#'
- {0x1C, 0x00, 0x2A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x1C, 0x00, 0x28, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$'
- {0x8C, 0x00, 0x52, 0x00, 0x52, 0x00, 0x32, 0x00, 0xAC, 0x01, 0x60, 0x02, 0x50, 0x02, 0x50, 0x02, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%'
- {0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x14, 0x00, 0x0C, 0x00, 0x52, 0x00, 0x22, 0x00, 0x62, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '''
- {0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00 }, // 0x28 '('
- {0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00 }, // 0x29 ')'
- {0x04, 0x00, 0x1F, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2A '*'
- {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x3E, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x2C ','
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2D '-'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2E '.'
- {0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0'
- {0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1'
- {0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2'
- {0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3'
- {0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x3E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4'
- {0x3C, 0x00, 0x04, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5'
- {0x1C, 0x00, 0x22, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6'
- {0x3E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9'
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':'
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x3B ';'
- {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3C '<'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '='
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?'
- {0xE0, 0x01, 0x18, 0x06, 0x04, 0x04, 0x64, 0x09, 0x92, 0x09, 0x8A, 0x08, 0x8A, 0x08, 0x8A, 0x04, 0xF2, 0x03, 0x04, 0x08, 0x08, 0x06, 0xF0, 0x01 }, // 0x40 '@'
- {0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x3E, 0x00, 0x22, 0x00, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A'
- {0x3E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C'
- {0x3E, 0x00, 0x42, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D'
- {0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E'
- {0x3E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x02, 0x00, 0xE2, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G'
- {0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xFE, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I'
- {0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J'
- {0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x16, 0x00, 0x22, 0x00, 0x42, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L'
- {0x82, 0x00, 0xC6, 0x00, 0xC6, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x92, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M'
- {0x82, 0x00, 0x86, 0x00, 0x8A, 0x00, 0x8A, 0x00, 0x92, 0x00, 0xA2, 0x00, 0xA2, 0x00, 0xC2, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O'
- {0x3E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xB2, 0x00, 0x44, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q'
- {0x7E, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x7E, 0x00, 0x22, 0x00, 0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x52 'R'
- {0x3C, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S'
- {0x7F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T'
- {0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U'
- {0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V'
- {0x21, 0x04, 0x51, 0x04, 0x51, 0x02, 0x52, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x04, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W'
- {0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X'
- {0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y'
- {0x7E, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z'
- {0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00 }, // 0x5B '['
- {0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5C '\'
- {0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00 }, // 0x5D ']'
- {0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5E '^'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00 }, // 0x5F '_'
- {0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a'
- {0x02, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b'
- {0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x12, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c'
- {0x20, 0x00, 0x20, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3E, 0x00, 0x02, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e'
- {0x0C, 0x00, 0x02, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f'
- {0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x1E, 0x00, 0x00, 0x00 }, // 0x67 'g'
- {0x02, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x68 'h'
- {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i'
- {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00 }, // 0x6A 'j'
- {0x02, 0x00, 0x02, 0x00, 0x22, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x0E, 0x00, 0x12, 0x00, 0x12, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6B 'k'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l'
- {0x00, 0x00, 0x00, 0x00, 0x9A, 0x01, 0x66, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm'
- {0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o'
- {0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x1A, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x70 'p'
- {0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00 }, // 0x71 'q'
- {0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x72 'r'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's'
- {0x02, 0x00, 0x02, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't'
- {0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x11, 0x01, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x44, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x79 'y'
- {0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7A 'z'
- {0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00 }, // 0x7B '{'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x7C '|'
- {0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x7D '}'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_11X12[] = {
- 3, 3, 4, 7, 7, 11, 8, 2, 4, 4, 5, 7, 3, 4, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 12, 7, 8, 9, 9, 8, 7, 9, 9, 3, 6, 8, 7, 9, 9, 9, 8, 9, 9, 8, 7, 9, 7, 11, 7, 7, 7, 3, 3, 3, 5, 7, 4, 7, 7, 6, 7, 7, 3, 7, 7, 3, 3, 6, 3, 11, 7, 7, 7, 7, 4, 7, 3, 7, 5, 9, 5, 5, 5, 4, 3, 4, 7
-};
-const UG_FONT font_font_a_11X12 = { (unsigned char *)fontBits_font_a_11X12, FONT_TYPE_1BPP, 11, 12, 32, 126, fontWidths_font_a_11X12 };
### src/ui/fonts/font_a_11X12.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_11X12;
### src/ui/fonts/font_a_13X14.c
@@ -1,108 +0,0 @@
-// Converted from font_a.ttf
-// --size 14
-// --dpi 72
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_13X14[95][28] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x20 ' '
- {0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x21 '!'
- {0x00,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x22 '"'
- {0x00,0x00,0x48,0x00,0x48,0x00,0x24,0x00,0xFF,0x00,0x24,0x00,0x24,0x00,0xFF,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x23 '#'
- {0x08,0x00,0x3C,0x00,0x4A,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x38,0x00,0x48,0x00,0x48,0x00,0x29,0x00,0x1E,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x24 '$'
- {0x00,0x00,0x0C,0x01,0x92,0x00,0x92,0x00,0x52,0x00,0x4C,0x00,0x20,0x03,0xA0,0x04,0x90,0x04,0x90,0x04,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x25 '%'
- {0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x24,0x00,0x18,0x00,0x14,0x00,0xA2,0x00,0x42,0x00,0xC2,0x00,0x3C,0x01,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x26 '&'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x27 '''
- {0x00,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00 }, // 0x28 '('
- {0x00,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x29 ')'
- {0x00,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2A '*'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0xFE,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2B '+'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00 }, // 0x2C ','
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2D '-'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2E '.'
- {0x00,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2F '/'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x30 '0'
- {0x00,0x00,0x10,0x00,0x18,0x00,0x14,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x31 '1'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x32 '2'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x40,0x00,0x38,0x00,0x40,0x00,0x40,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x33 '3'
- {0x00,0x00,0x20,0x00,0x30,0x00,0x28,0x00,0x24,0x00,0x24,0x00,0x22,0x00,0x21,0x00,0x7F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x34 '4'
- {0x00,0x00,0x7C,0x00,0x04,0x00,0x02,0x00,0x3E,0x00,0x42,0x00,0x40,0x00,0x40,0x00,0x42,0x00,0x22,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x35 '5'
- {0x00,0x00,0x38,0x00,0x44,0x00,0x02,0x00,0x02,0x00,0x3A,0x00,0x46,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x36 '6'
- {0x00,0x00,0x7E,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x37 '7'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x38 '8'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x40,0x00,0x40,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x39 '9'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3A ':'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x3B ';'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3C '<'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3D '='
- {0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3E '>'
- {0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3F '?'
- {0x00,0x00,0xF0,0x03,0x0C,0x04,0x02,0x08,0xE2,0x12,0x11,0x13,0x09,0x12,0x09,0x11,0x09,0x09,0x89,0x09,0x72,0x07,0x02,0x10,0x0C,0x0C,0xF0,0x03 }, // 0x40 '@'
- {0x00,0x00,0x10,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x44,0x00,0x44,0x00,0xFE,0x00,0x82,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x41 'A'
- {0x00,0x00,0x7E,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x7E,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x42 'B'
- {0x00,0x00,0x78,0x00,0x84,0x00,0x02,0x01,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x01,0x84,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x43 'C'
- {0x00,0x00,0x7E,0x00,0x82,0x00,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x82,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x44 'D'
- {0x00,0x00,0xFE,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0xFE,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x45 'E'
- {0x00,0x00,0xFE,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x7E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x46 'F'
- {0x00,0x00,0xF8,0x00,0x04,0x01,0x02,0x02,0x02,0x00,0x02,0x00,0xC2,0x03,0x02,0x02,0x02,0x02,0x04,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x47 'G'
- {0x00,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0xFE,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x48 'H'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x49 'I'
- {0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x11,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4A 'J'
- {0x00,0x00,0x02,0x01,0x82,0x00,0x42,0x00,0x22,0x00,0x12,0x00,0x2A,0x00,0x46,0x00,0x42,0x00,0x82,0x00,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4B 'K'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4C 'L'
- {0x00,0x00,0x02,0x02,0x06,0x03,0x06,0x03,0x8A,0x02,0x8A,0x02,0x52,0x02,0x52,0x02,0x52,0x02,0x22,0x02,0x22,0x02,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4D 'M'
- {0x00,0x00,0x82,0x00,0x86,0x00,0x8A,0x00,0x8A,0x00,0x92,0x00,0x92,0x00,0xA2,0x00,0xA2,0x00,0xC2,0x00,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4E 'N'
- {0x00,0x00,0xF8,0x00,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x04,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x4F 'O'
- {0x00,0x00,0x7E,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x7E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x50 'P'
- {0x00,0x00,0xF8,0x00,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x01,0x84,0x01,0x78,0x03,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x51 'Q'
- {0x00,0x00,0xFE,0x00,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0xFE,0x00,0x22,0x00,0x42,0x00,0x82,0x00,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x52 'R'
- {0x00,0x00,0x7C,0x00,0x82,0x00,0x82,0x00,0x02,0x00,0x1C,0x00,0xE0,0x00,0x80,0x00,0x82,0x00,0x82,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x53 'S'
- {0x00,0x00,0xFE,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x54 'T'
- {0x00,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x44,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x55 'U'
- {0x00,0x00,0x01,0x01,0x01,0x01,0x82,0x00,0x82,0x00,0x44,0x00,0x44,0x00,0x28,0x00,0x28,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x56 'V'
- {0x00,0x00,0x41,0x10,0xA1,0x10,0xA2,0x08,0xA2,0x08,0xA2,0x08,0x14,0x05,0x14,0x05,0x14,0x05,0x08,0x02,0x08,0x02,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x57 'W'
- {0x00,0x00,0x81,0x00,0x42,0x00,0x42,0x00,0x24,0x00,0x18,0x00,0x18,0x00,0x24,0x00,0x42,0x00,0x42,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x58 'X'
- {0x00,0x00,0x01,0x01,0x82,0x00,0x44,0x00,0x44,0x00,0x28,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x59 'Y'
- {0x00,0x00,0xFE,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5A 'Z'
- {0x00,0x00,0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00 }, // 0x5B '['
- {0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5C '\'
- {0x00,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x06,0x00 }, // 0x5D ']'
- {0x00,0x00,0x04,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5E '^'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00 }, // 0x5F '_'
- {0x00,0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x60 '`'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x40,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x61 'a'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x3A,0x00,0x46,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x46,0x00,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x62 'b'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x63 'c'
- {0x00,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x64 'd'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x7E,0x00,0x02,0x00,0x02,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x65 'e'
- {0x00,0x00,0x0C,0x00,0x02,0x00,0x0F,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x66 'f'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x40,0x00,0x42,0x00,0x3C,0x00 }, // 0x67 'g'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x3A,0x00,0x46,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x68 'h'
- {0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x69 'i'
- {0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00 }, // 0x6A 'j'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x42,0x00,0x22,0x00,0x12,0x00,0x0A,0x00,0x16,0x00,0x22,0x00,0x22,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x6B 'k'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x6C 'l'
- {0x00,0x00,0x00,0x00,0x00,0x00,0xDA,0x01,0x66,0x02,0x22,0x02,0x22,0x02,0x22,0x02,0x22,0x02,0x22,0x02,0x22,0x02,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x6D 'm'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0x00,0x46,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x6E 'n'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x6F 'o'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0x00,0x46,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x46,0x00,0x3A,0x00,0x02,0x00,0x02,0x00,0x02,0x00 }, // 0x70 'p'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x40,0x00,0x40,0x00,0x40,0x00 }, // 0x71 'q'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x00,0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x72 'r'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x02,0x00,0x1C,0x00,0x20,0x00,0x20,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x73 's'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x0F,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x74 't'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x62,0x00,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x75 'u'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x76 'v'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x11,0x01,0xAA,0x00,0xAA,0x00,0xAA,0x00,0xAA,0x00,0x44,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x77 'w'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x78 'x'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x06,0x00 }, // 0x79 'y'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x7A 'z'
- {0x00,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x08,0x00 }, // 0x7B '{'
- {0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00 }, // 0x7C '|'
- {0x00,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x7D '}'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0x00,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_13X14[] = {
-4,5,5,8,8,12,9,3,5,5,5,8,4,5,4,4,8,8,8,8,8,8,8,8,8,8,4,4,8,8,8,8,14,9,9,10,10,9,9,11,9,3,6,9,8,11,9,11,9,11,10,9,9,9,9,13,8,9,8,4,4,4,5,8,5,8,8,7,8,8,4,8,8,3,3,7,3,11,8,8,8,8,5,7,4,8,7,9,6,7,6,5,3,5,8};
-const UG_FONT font_font_a_13X14 = { (unsigned char*)fontBits_font_a_13X14, FONT_TYPE_1BPP, 13, 14, 32, 126, fontWidths_font_a_13X14 };
### src/ui/fonts/font_a_13X14.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_13X14;
### src/ui/fonts/font_a_15X16.c
@@ -1,109 +0,0 @@
-// Converted from font_a.ttf
-// --size 16
-// --dpi 72
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_15X16[95][32] = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20 ' '
- {0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!'
- {0x00, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '"'
- {0x00, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x44, 0x00, 0xFF, 0x01, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0xFF, 0x01, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#'
- {0x10, 0x00, 0x78, 0x00, 0x94, 0x00, 0x92, 0x00, 0x12, 0x00, 0x12, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x90, 0x00, 0x90, 0x00, 0x92, 0x00, 0x54, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$'
- {0x00, 0x00, 0x1C, 0x02, 0x22, 0x01, 0x22, 0x01, 0xA2, 0x00, 0xA2, 0x00, 0x9C, 0x00, 0x40, 0x0E, 0x40, 0x11, 0x20, 0x11, 0x20, 0x11, 0x10, 0x11, 0x10, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x18, 0x00, 0x14, 0x00, 0x22, 0x02, 0x42, 0x01, 0x82, 0x00, 0x44, 0x01, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '''
- {0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00 }, // 0x28 '('
- {0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00 }, // 0x29 ')'
- {0x00, 0x00, 0x04, 0x00, 0x1F, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2A '*'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00 }, // 0x2C ','
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2D '-'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2E '.'
- {0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0'
- {0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x28, 0x00, 0x24, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1'
- {0x00, 0x00, 0x78, 0x00, 0x44, 0x00, 0x82, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x42, 0x00, 0x40, 0x00, 0x60, 0x00, 0x38, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x82, 0x00, 0x46, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3'
- {0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x50, 0x00, 0x48, 0x00, 0x48, 0x00, 0x44, 0x00, 0x42, 0x00, 0x41, 0x00, 0xFF, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4'
- {0x00, 0x00, 0xFC, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x42, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x02, 0x00, 0x3A, 0x00, 0x46, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6'
- {0x00, 0x00, 0xFC, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC4, 0x00, 0xB8, 0x00, 0x80, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x3B ';'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x70, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3C '<'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '='
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x60, 0x00, 0x80, 0x00, 0x60, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>'
- {0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?'
- {0x00, 0x00, 0xC0, 0x0F, 0x30, 0x30, 0x08, 0x40, 0x84, 0x4B, 0x44, 0x8C, 0x22, 0x88, 0x12, 0x88, 0x12, 0x84, 0x12, 0x84, 0x12, 0x44, 0x22, 0x26, 0xC4, 0x1D, 0x08, 0x80, 0x30, 0x60, 0xC0, 0x1F }, // 0x40 '@'
- {0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xFC, 0x01, 0x04, 0x01, 0x04, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A'
- {0x00, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0xFE, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B'
- {0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x04, 0x04, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x04, 0x08, 0x02, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C'
- {0x00, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D'
- {0x00, 0x00, 0xFE, 0x03, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E'
- {0x00, 0x00, 0xFE, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F'
- {0x00, 0x00, 0xF0, 0x00, 0x08, 0x01, 0x04, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xC2, 0x07, 0x02, 0x04, 0x02, 0x04, 0x04, 0x02, 0x08, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G'
- {0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I'
- {0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J'
- {0x00, 0x00, 0x02, 0x02, 0x02, 0x01, 0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2A, 0x00, 0x46, 0x00, 0x82, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L'
- {0x00, 0x00, 0x02, 0x08, 0x06, 0x0C, 0x06, 0x0C, 0x0A, 0x0A, 0x0A, 0x0A, 0x12, 0x09, 0x12, 0x09, 0xA2, 0x08, 0xA2, 0x08, 0xA2, 0x08, 0x42, 0x08, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M'
- {0x00, 0x00, 0x02, 0x02, 0x06, 0x02, 0x0A, 0x02, 0x0A, 0x02, 0x12, 0x02, 0x22, 0x02, 0x22, 0x02, 0x42, 0x02, 0x82, 0x02, 0x82, 0x02, 0x02, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N'
- {0x00, 0x00, 0xF0, 0x00, 0x08, 0x01, 0x04, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x04, 0x02, 0x08, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O'
- {0x00, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0xFE, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P'
- {0x00, 0x00, 0xF0, 0x00, 0x08, 0x01, 0x04, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0xC4, 0x06, 0x08, 0x03, 0xF0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q'
- {0x00, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0xFE, 0x00, 0x42, 0x00, 0x82, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x52 'R'
- {0x00, 0x00, 0xF8, 0x00, 0x04, 0x01, 0x02, 0x02, 0x02, 0x00, 0x04, 0x00, 0x38, 0x00, 0xC0, 0x01, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x04, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S'
- {0x00, 0x00, 0xFF, 0x01, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T'
- {0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U'
- {0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x50, 0x00, 0x50, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V'
- {0x00, 0x00, 0x81, 0x40, 0x41, 0x41, 0x42, 0x21, 0x42, 0x21, 0x22, 0x22, 0x22, 0x22, 0x24, 0x12, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W'
- {0x00, 0x00, 0x02, 0x02, 0x04, 0x01, 0x88, 0x00, 0x88, 0x00, 0x50, 0x00, 0x20, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0x02, 0x02, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X'
- {0x00, 0x00, 0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y'
- {0x00, 0x00, 0xFE, 0x01, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z'
- {0x00, 0x00, 0x0E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0E, 0x00 }, // 0x5B '['
- {0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5C '\'
- {0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x07, 0x00 }, // 0x5D ']'
- {0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5E '^'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01 }, // 0x5F '_'
- {0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x82, 0x00, 0xE0, 0x00, 0x9C, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC2, 0x00, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3A, 0x00, 0x46, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x46, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c'
- {0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xB8, 0x00, 0xC4, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC4, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0xFE, 0x00, 0x02, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e'
- {0x00, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0xC4, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC4, 0x00, 0xB8, 0x00, 0x80, 0x00, 0x42, 0x00, 0x3C, 0x00 }, // 0x67 'g'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3A, 0x00, 0x46, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x68 'h'
- {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i'
- {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00 }, // 0x6A 'j'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x12, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x42, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6B 'k'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x07, 0xC6, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x46, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x46, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x46, 0x00, 0x3A, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00 }, // 0x70 'p'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0xC4, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC4, 0x00, 0xB8, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }, // 0x71 'q'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x72 'r'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's'
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x62, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0x21, 0x04, 0x52, 0x02, 0x52, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x04, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x41, 0x00, 0x21, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x18, 0x00, 0x08, 0x00, 0x08, 0x00, 0x06, 0x00 }, // 0x79 'y'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7A 'z'
- {0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x18, 0x00 }, // 0x7B '{'
- {0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00 }, // 0x7C '|'
- {0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x18, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00 }, // 0x7D '}'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_15X16[] = {
- 4, 5, 6, 9, 9, 14, 11, 3, 5, 5, 6, 9, 4, 5, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 9, 9, 9, 9, 16, 11, 11, 12, 12, 11, 10, 12, 11, 3, 8, 11, 9, 13, 11, 12, 11, 12, 11, 11, 9, 11, 11, 15, 11, 9, 9, 4, 4, 4, 7, 9, 5, 9, 9, 8, 9, 9, 4, 9, 8, 4, 3, 8, 3, 13, 8, 9, 9, 9, 5, 8, 4, 8, 7, 11, 7, 7, 7, 5, 3, 5, 9
-};
-const UG_FONT font_font_a_15X16 = { (unsigned char *)fontBits_font_a_15X16, FONT_TYPE_1BPP, 15, 16, 32, 126, fontWidths_font_a_15X16 };
### src/ui/fonts/font_a_15X16.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_15X16;
### src/ui/fonts/font_a_17X18.c
@@ -1,109 +0,0 @@
-// Converted from font_a.ttf
-// --size 18
-// --dpi 72
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_17X18[95][54] = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20 ' '
- {0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!'
- {0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '"'
- {0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x98, 0x01, 0x00, 0xFF, 0x07, 0x00, 0xFF, 0x07, 0x00, 0x98, 0x01, 0x00, 0xDC, 0x01, 0x00, 0xCC, 0x00, 0x00, 0xFF, 0x07, 0x00, 0xFF, 0x07, 0x00, 0xCC, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#'
- {0x20, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x26, 0x03, 0x00, 0x26, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF0, 0x01, 0x00, 0xE0, 0x03, 0x00, 0x20, 0x03, 0x00, 0x26, 0x03, 0x00, 0xAE, 0x03, 0x00, 0xFC, 0x01, 0x00, 0xF8, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$'
- {0x00, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x66, 0x06, 0x00, 0x66, 0x06, 0x00, 0x66, 0x03, 0x00, 0x66, 0x03, 0x00, 0xE6, 0x03, 0x00, 0xBC, 0x3D, 0x00, 0x80, 0x67, 0x00, 0xC0, 0x66, 0x00, 0xC0, 0x66, 0x00, 0x60, 0x66, 0x00, 0x60, 0x66, 0x00, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%'
- {0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x98, 0x01, 0x00, 0x98, 0x01, 0x00, 0xD8, 0x00, 0x00, 0x70, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x6C, 0x06, 0x00, 0xC6, 0x06, 0x00, 0x86, 0x03, 0x00, 0x8E, 0x03, 0x00, 0xFC, 0x07, 0x00, 0x78, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&'
- {0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '''
- {0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00 }, // 0x28 '('
- {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00 }, // 0x29 ')'
- {0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x08, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2A '*'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x07, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2C ','
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2D '-'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2E '.'
- {0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0'
- {0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x64, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2'
- {0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3'
- {0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x66, 0x00, 0x00, 0x63, 0x00, 0x00, 0xFF, 0x01, 0x00, 0xFF, 0x01, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4'
- {0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x76, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x86, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x76, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x8E, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x8C, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6'
- {0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x01, 0x00, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xC6, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xB8, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xC6, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3B ';'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0x03, 0x00, 0xF0, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x80, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3C '<'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '='
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x03, 0x00, 0xE0, 0x01, 0x00, 0x7C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>'
- {0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x80, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?'
- {0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0xE0, 0x7F, 0x00, 0x70, 0xE0, 0x00, 0x18, 0xF7, 0x01, 0x8C, 0xBF, 0x03, 0xCC, 0x1C, 0x03, 0xE6, 0x18, 0x03, 0x66, 0x18, 0x03, 0x66, 0x08, 0x03, 0x66, 0x8C, 0x01, 0xE6, 0xCC, 0x01, 0xC6, 0xFF, 0x00, 0xCC, 0x3D, 0x00, 0x1C, 0x80, 0x03, 0x78, 0xC0, 0x01, 0xF0, 0xFF, 0x00, 0xC0, 0x3F, 0x00 }, // 0x40 '@'
- {0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x8C, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x03, 0x06, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A'
- {0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x07, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B'
- {0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0xF8, 0x07, 0x00, 0x1C, 0x0E, 0x00, 0x0C, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x06, 0x00, 0xF8, 0x07, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C'
- {0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x07, 0x00, 0x06, 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x06, 0x00, 0x06, 0x07, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D'
- {0x00, 0x00, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x07, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E'
- {0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x01, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F'
- {0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0xF8, 0x0F, 0x00, 0x1C, 0x0C, 0x00, 0x0C, 0x18, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x86, 0x1F, 0x00, 0x86, 0x1F, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x18, 0x00, 0x1C, 0x1C, 0x00, 0xF8, 0x0F, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G'
- {0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I'
- {0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J'
- {0x00, 0x00, 0x00, 0x06, 0x07, 0x00, 0x86, 0x03, 0x00, 0xC6, 0x01, 0x00, 0xE6, 0x00, 0x00, 0x76, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xC6, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x03, 0x00, 0x06, 0x07, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L'
- {0x00, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x1E, 0x3C, 0x00, 0x1E, 0x3C, 0x00, 0x1E, 0x3C, 0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x00, 0x26, 0x32, 0x00, 0x66, 0x33, 0x00, 0x66, 0x33, 0x00, 0x66, 0x33, 0x00, 0xC6, 0x31, 0x00, 0xC6, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M'
- {0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x0E, 0x0C, 0x00, 0x1E, 0x0C, 0x00, 0x1E, 0x0C, 0x00, 0x36, 0x0C, 0x00, 0x66, 0x0C, 0x00, 0xE6, 0x0C, 0x00, 0xC6, 0x0C, 0x00, 0x86, 0x0D, 0x00, 0x06, 0x0F, 0x00, 0x06, 0x0F, 0x00, 0x06, 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N'
- {0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0xF8, 0x07, 0x00, 0x1C, 0x0E, 0x00, 0x0C, 0x0C, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x0E, 0x00, 0xF8, 0x07, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O'
- {0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x03, 0x00, 0x06, 0x07, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x07, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x01, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P'
- {0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 0xF8, 0x07, 0x00, 0x1C, 0x0E, 0x00, 0x0C, 0x1C, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x8C, 0x0D, 0x00, 0x1C, 0x07, 0x00, 0xF8, 0x07, 0x00, 0xF0, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q'
- {0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x07, 0x00, 0x06, 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0E, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x03, 0x00, 0x86, 0x01, 0x00, 0x86, 0x03, 0x00, 0x06, 0x07, 0x00, 0x06, 0x06, 0x00, 0x06, 0x0E, 0x00, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x52 'R'
- {0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0xFC, 0x03, 0x00, 0x0E, 0x07, 0x00, 0x06, 0x06, 0x00, 0x06, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xF8, 0x01, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x07, 0x00, 0xFC, 0x03, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S'
- {0x00, 0x00, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x07, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T'
- {0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x0E, 0x06, 0x00, 0xFC, 0x07, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U'
- {0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x03, 0x06, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x8C, 0x01, 0x00, 0x8C, 0x01, 0x00, 0x8C, 0x01, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V'
- {0x00, 0x00, 0x00, 0x83, 0x83, 0x01, 0x83, 0x83, 0x01, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0x00, 0x46, 0xC4, 0x00, 0x6C, 0x6C, 0x00, 0x6C, 0x6C, 0x00, 0x6C, 0x6C, 0x00, 0x6C, 0x6C, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W'
- {0x00, 0x00, 0x00, 0x8E, 0x03, 0x00, 0x8C, 0x01, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0xD8, 0x00, 0x00, 0xD8, 0x00, 0x00, 0xDC, 0x01, 0x00, 0x8C, 0x01, 0x00, 0x06, 0x03, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X'
- {0x00, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x03, 0x00, 0x9C, 0x03, 0x00, 0x98, 0x01, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y'
- {0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0xFE, 0x03, 0x00, 0x80, 0x01, 0x00, 0xC0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0xFF, 0x03, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z'
- {0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00 }, // 0x5B '['
- {0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5C '\'
- {0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00 }, // 0x5D ']'
- {0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x14, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x22, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5E '^'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0xFF, 0x03, 0x00 }, // 0x5F '_'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x86, 0x01, 0x00, 0xE0, 0x01, 0x00, 0xFC, 0x01, 0x00, 0x9E, 0x01, 0x00, 0x86, 0x01, 0x00, 0xC6, 0x01, 0x00, 0xFE, 0x01, 0x00, 0xBC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x76, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFE, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xCE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c'
- {0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xB8, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x86, 0x01, 0x00, 0xFE, 0x01, 0x00, 0xFE, 0x01, 0x00, 0x06, 0x00, 0x00, 0x8E, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e'
- {0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xB8, 0x01, 0x00, 0x80, 0x01, 0x00, 0xC6, 0x01, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00 }, // 0x67 'g'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xF6, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x8E, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x68 'h'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00 }, // 0x6A 'j'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0xC6, 0x01, 0x00, 0xE6, 0x00, 0x00, 0x76, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x36, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6B 'k'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x0E, 0x00, 0x7E, 0x1F, 0x00, 0xCE, 0x19, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0xC6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x8E, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFE, 0x00, 0x00, 0x76, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00 }, // 0x70 'p'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xCE, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xCE, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xB8, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00 }, // 0x71 'q'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x72 'r'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's'
- {0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0x86, 0x01, 0x00, 0xC6, 0x01, 0x00, 0xFE, 0x01, 0x00, 0xBC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x01, 0x00, 0x83, 0x01, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x18, 0x00, 0xE3, 0x18, 0x00, 0xE3, 0x18, 0x00, 0xA6, 0x0C, 0x00, 0xB6, 0x0D, 0x00, 0xB6, 0x0D, 0x00, 0x14, 0x05, 0x00, 0x1C, 0x07, 0x00, 0x1C, 0x07, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x01, 0x00, 0x83, 0x01, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00 }, // 0x79 'y'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7A 'z'
- {0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00 }, // 0x7B '{'
- {0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00 }, // 0x7C '|'
- {0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00 }, // 0x7D '}'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x3F, 0x02, 0x00, 0xF1, 0x03, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_17X18[] = {
- 5, 6, 6, 10, 10, 16, 12, 3, 6, 6, 7, 11, 5, 6, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 11, 11, 11, 10, 18, 11, 12, 13, 13, 12, 11, 14, 13, 4, 9, 12, 10, 15, 13, 14, 12, 14, 13, 12, 12, 13, 11, 17, 11, 12, 11, 5, 5, 5, 7, 10, 6, 10, 10, 9, 10, 10, 5, 10, 10, 4, 4, 9, 4, 14, 10, 10, 10, 10, 6, 9, 5, 10, 9, 13, 8, 9, 8, 6, 6, 6, 11
-};
-const UG_FONT font_font_a_17X18 = { (unsigned char *)fontBits_font_a_17X18, FONT_TYPE_1BPP, 17, 18, 32, 126, fontWidths_font_a_17X18 };
### src/ui/fonts/font_a_17X18.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_17X18;
### src/ui/fonts/font_a_9X9.c
@@ -1,108 +0,0 @@
-// Converted from font_a.ttf
-// --size 9
-// --dpi 72
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_font_a_9X9[95][18] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x20 ' '
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x21 '!'
- {0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x22 '"'
- {0x0A,0x00,0x0A,0x00,0x0F,0x00,0x0A,0x00,0x0F,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00 }, // 0x23 '#'
- {0x0E,0x00,0x15,0x00,0x05,0x00,0x0E,0x00,0x14,0x00,0x15,0x00,0x0E,0x00,0x04,0x00,0x00,0x00 }, // 0x24 '$'
- {0x24,0x00,0x1A,0x00,0x14,0x00,0x10,0x00,0x28,0x00,0x58,0x00,0x28,0x00,0x00,0x00,0x00,0x00 }, // 0x25 '%'
- {0x0C,0x00,0x12,0x00,0x12,0x00,0x0E,0x00,0x29,0x00,0x11,0x00,0x2E,0x00,0x00,0x00,0x00,0x00 }, // 0x26 '&'
- {0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x27 '''
- {0x04,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x04,0x00 }, // 0x28 '('
- {0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x00 }, // 0x29 ')'
- {0x07,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2A '*'
- {0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x2B '+'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x2C ','
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2D '-'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x2E '.'
- {0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x2F '/'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x30 '0'
- {0x04,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x31 '1'
- {0x06,0x00,0x09,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x0F,0x00,0x00,0x00,0x00,0x00 }, // 0x32 '2'
- {0x06,0x00,0x09,0x00,0x08,0x00,0x04,0x00,0x08,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x33 '3'
- {0x08,0x00,0x0C,0x00,0x0A,0x00,0x09,0x00,0x1F,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x34 '4'
- {0x0E,0x00,0x02,0x00,0x07,0x00,0x09,0x00,0x08,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x35 '5'
- {0x06,0x00,0x09,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x36 '6'
- {0x0F,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x37 '7'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x38 '8'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x39 '9'
- {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x3A ':'
- {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x3B ';'
- {0x00,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3C '<'
- {0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3D '='
- {0x00,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3E '>'
- {0x0E,0x00,0x11,0x00,0x10,0x00,0x0C,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x3F '?'
- {0x78,0x00,0x84,0x00,0x52,0x01,0x6A,0x01,0x2A,0x01,0xAA,0x00,0x7A,0x00,0x84,0x01,0x78,0x00 }, // 0x40 '@'
- {0x08,0x00,0x14,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x41 'A'
- {0x0E,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x12,0x00,0x12,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x42 'B'
- {0x1C,0x00,0x22,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x43 'C'
- {0x1E,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x44 'D'
- {0x3E,0x00,0x02,0x00,0x02,0x00,0x3E,0x00,0x02,0x00,0x02,0x00,0x3E,0x00,0x00,0x00,0x00,0x00 }, // 0x45 'E'
- {0x1E,0x00,0x02,0x00,0x02,0x00,0x0E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x46 'F'
- {0x1C,0x00,0x22,0x00,0x02,0x00,0x32,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x47 'G'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x48 'H'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x49 'I'
- {0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x09,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x4A 'J'
- {0x22,0x00,0x12,0x00,0x0A,0x00,0x06,0x00,0x0A,0x00,0x12,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x4B 'K'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x4C 'L'
- {0x41,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x4D 'M'
- {0x22,0x00,0x26,0x00,0x26,0x00,0x2A,0x00,0x32,0x00,0x32,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x4E 'N'
- {0x1C,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x4F 'O'
- {0x1E,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x50 'P'
- {0x1C,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x12,0x00,0x3C,0x00,0x00,0x00,0x00,0x00 }, // 0x51 'Q'
- {0x1E,0x00,0x22,0x00,0x22,0x00,0x1E,0x00,0x12,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x52 'R'
- {0x0C,0x00,0x12,0x00,0x02,0x00,0x0C,0x00,0x10,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00 }, // 0x53 'S'
- {0x1F,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x54 'T'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x55 'U'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x56 'V'
- {0x11,0x01,0x29,0x01,0xAA,0x00,0xAA,0x00,0xAA,0x00,0xAA,0x00,0x44,0x00,0x00,0x00,0x00,0x00 }, // 0x57 'W'
- {0x11,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x00,0x00,0x00,0x00 }, // 0x58 'X'
- {0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x59 'Y'
- {0x3F,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x3F,0x00,0x00,0x00,0x00,0x00 }, // 0x5A 'Z'
- {0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00 }, // 0x5B '['
- {0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x5C '\'
- {0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00 }, // 0x5D ']'
- {0x02,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5E '^'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00 }, // 0x5F '_'
- {0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x60 '`'
- {0x00,0x00,0x00,0x00,0x0F,0x00,0x08,0x00,0x0E,0x00,0x09,0x00,0x0F,0x00,0x00,0x00,0x00,0x00 }, // 0x61 'a'
- {0x01,0x00,0x01,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x62 'b'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x01,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x63 'c'
- {0x08,0x00,0x08,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x64 'd'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x0F,0x00,0x01,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x65 'e'
- {0x04,0x00,0x02,0x00,0x07,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x66 'f'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x09,0x00,0x06,0x00 }, // 0x67 'g'
- {0x01,0x00,0x01,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x68 'h'
- {0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x69 'i'
- {0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00 }, // 0x6A 'j'
- {0x01,0x00,0x01,0x00,0x09,0x00,0x05,0x00,0x07,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x6B 'k'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x6C 'l'
- {0x00,0x00,0x00,0x00,0x3F,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x6D 'm'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x6E 'n'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x6F 'o'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x07,0x00,0x01,0x00,0x01,0x00 }, // 0x70 'p'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x08,0x00,0x08,0x00 }, // 0x71 'q'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x72 'r'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x01,0x00,0x06,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x73 's'
- {0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00 }, // 0x74 't'
- {0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x75 'u'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x76 'v'
- {0x00,0x00,0x00,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x0A,0x00,0x00,0x00,0x00,0x00 }, // 0x77 'w'
- {0x00,0x00,0x00,0x00,0x09,0x00,0x06,0x00,0x02,0x00,0x06,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x78 'x'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x79 'y'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x7A 'z'
- {0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00 }, // 0x7B '{'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x7C '|'
- {0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00 }, // 0x7D '}'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_font_a_9X9[] = {
-3,3,3,5,5,8,6,2,3,3,4,5,3,3,3,3,5,5,5,5,5,5,5,5,5,5,3,3,5,5,5,5,9,6,6,7,7,6,6,7,7,3,5,6,5,7,7,7,6,7,7,6,5,7,6,9,5,7,6,3,3,3,3,5,3,5,5,5,5,5,4,5,5,2,3,5,2,8,5,5,5,5,3,5,3,5,6,6,5,6,4,3,3,3,5};
-UG_FONT font_font_a_9X9 = { (unsigned char*)fontBits_font_a_9X9, FONT_TYPE_1BPP, 9, 9, 32, 126, fontWidths_font_a_9X9 };
### src/ui/fonts/font_a_9X9.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_font_a_9X9;
### src/ui/fonts/lvgl_font_compat.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include "lvgl.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+static bool _font_dsc_supported(const lv_font_fmt_txt_dsc_t* font_dsc)
+{
+ if (font_dsc == NULL || font_dsc->glyph_bitmap == NULL || font_dsc->glyph_dsc == NULL ||
+ (font_dsc->cmap_num != 0 && font_dsc->cmaps == NULL) || font_dsc->bpp != 1 ||
+ font_dsc->stride != 0 || font_dsc->bitmap_format != LV_FONT_FMT_TXT_PLAIN ||
+ font_dsc->kern_dsc != NULL || font_dsc->kern_scale != 0 || font_dsc->kern_classes != 0) {
+ return false;
+ }
+
+ for (uint16_t i = 0; i < font_dsc->cmap_num; i++) {
+ const lv_font_fmt_txt_cmap_t* cmap = &font_dsc->cmaps[i];
+ if (cmap->type != LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY || cmap->unicode_list != NULL ||
+ cmap->glyph_id_ofs_list != NULL || cmap->list_length != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static uint32_t _get_glyph_id(const lv_font_fmt_txt_dsc_t* font_dsc, uint32_t codepoint)
+{
+ if (codepoint == '\0') {
+ return 0;
+ }
+
+ for (uint16_t i = 0; i < font_dsc->cmap_num; i++) {
+ const lv_font_fmt_txt_cmap_t* cmap = &font_dsc->cmaps[i];
+ uint32_t relative_codepoint = codepoint - cmap->range_start;
+ if (relative_codepoint < cmap->range_length) {
+ return cmap->glyph_id_start + relative_codepoint;
+ }
+ }
+ return 0;
+}
+
+__attribute__((weak)) bool lv_font_get_glyph_dsc_fmt_txt(
+ const lv_font_t* font,
+ lv_font_glyph_dsc_t* dsc_out,
+ uint32_t unicode_letter,
+ uint32_t unicode_letter_next)
+{
+ (void)unicode_letter_next;
+ if (font == NULL || font->dsc == NULL || dsc_out == NULL) {
+ return false;
+ }
+
+ bool is_tab = unicode_letter == '\t';
+ if (is_tab) {
+ unicode_letter = ' ';
+ }
+
+ const lv_font_fmt_txt_dsc_t* font_dsc = (const lv_font_fmt_txt_dsc_t*)font->dsc;
+ if (!_font_dsc_supported(font_dsc)) {
+ return false;
+ }
+
+ uint32_t glyph_id = _get_glyph_id(font_dsc, unicode_letter);
+ if (glyph_id == 0) {
+ return false;
+ }
+
+ const lv_font_fmt_txt_glyph_dsc_t* glyph_dsc = &font_dsc->glyph_dsc[glyph_id];
+
+ memset(dsc_out, 0, sizeof(*dsc_out));
+ dsc_out->resolved_font = font;
+ dsc_out->adv_w = (glyph_dsc->adv_w + (1 << 3)) >> 4;
+ dsc_out->box_w = glyph_dsc->box_w;
+ dsc_out->box_h = glyph_dsc->box_h;
+ dsc_out->ofs_x = glyph_dsc->ofs_x;
+ dsc_out->ofs_y = glyph_dsc->ofs_y;
+ dsc_out->stride = 0;
+ dsc_out->format = LV_FONT_GLYPH_FORMAT_A1;
+ dsc_out->is_placeholder = false;
+ dsc_out->gid.index = glyph_id;
+
+ if (is_tab) {
+ dsc_out->adv_w *= 2;
+ }
+
+ return true;
+}
+
+__attribute__((weak)) const void* lv_font_get_bitmap_fmt_txt(
+ lv_font_glyph_dsc_t* glyph_dsc,
+ lv_draw_buf_t* draw_buf)
+{
+ (void)draw_buf;
+ if (glyph_dsc == NULL || glyph_dsc->resolved_font == NULL ||
+ glyph_dsc->resolved_font->dsc == NULL || glyph_dsc->gid.index == 0 ||
+ glyph_dsc->format != LV_FONT_GLYPH_FORMAT_A1 || glyph_dsc->stride != 0) {
+ return NULL;
+ }
+
+ const lv_font_fmt_txt_dsc_t* font_dsc =
+ (const lv_font_fmt_txt_dsc_t*)glyph_dsc->resolved_font->dsc;
+ if (!_font_dsc_supported(font_dsc)) {
+ return NULL;
+ }
+
+ const lv_font_fmt_txt_glyph_dsc_t* font_glyph_dsc =
+ &font_dsc->glyph_dsc[glyph_dsc->gid.index];
+ return &font_dsc->glyph_bitmap[font_glyph_dsc->bitmap_index];
+}
### src/ui/fonts/monogram_5X9.c
@@ -1,107 +0,0 @@
-// Converted from /home/niklas/.local/share/fonts/monogram.ttf
-// --size 16
-// --bpp 1
-// For copyright, see original font file.
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_monogram_5X9[95][9] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x20 ' '
- {0x04,0x04,0x04,0x04,0x04,0x00,0x04,0x00,0x00 }, // 0x21 '!'
- {0x0A,0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x22 '"'
- {0x00,0x0A,0x1F,0x0A,0x0A,0x1F,0x0A,0x00,0x00 }, // 0x23 '#'
- {0x04,0x1E,0x05,0x0E,0x14,0x0F,0x04,0x00,0x00 }, // 0x24 '$'
- {0x11,0x11,0x08,0x04,0x02,0x11,0x11,0x00,0x00 }, // 0x25 '%'
- {0x06,0x09,0x09,0x1E,0x09,0x09,0x16,0x00,0x00 }, // 0x26 '&'
- {0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x27 '''
- {0x08,0x04,0x04,0x04,0x04,0x04,0x08,0x00,0x00 }, // 0x28 '('
- {0x02,0x04,0x04,0x04,0x04,0x04,0x02,0x00,0x00 }, // 0x29 ')'
- {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00,0x00 }, // 0x2A '*'
- {0x00,0x04,0x04,0x1F,0x04,0x04,0x00,0x00,0x00 }, // 0x2B '+'
- {0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x02,0x00 }, // 0x2C ','
- {0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00 }, // 0x2D '-'
- {0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x00,0x00 }, // 0x2E '.'
- {0x10,0x10,0x08,0x04,0x02,0x01,0x01,0x00,0x00 }, // 0x2F '/'
- {0x0E,0x11,0x19,0x15,0x13,0x11,0x0E,0x00,0x00 }, // 0x30 '0'
- {0x04,0x06,0x04,0x04,0x04,0x04,0x1F,0x00,0x00 }, // 0x31 '1'
- {0x0E,0x11,0x10,0x08,0x04,0x02,0x1F,0x00,0x00 }, // 0x32 '2'
- {0x0E,0x11,0x10,0x0C,0x10,0x11,0x0E,0x00,0x00 }, // 0x33 '3'
- {0x12,0x12,0x11,0x1F,0x10,0x10,0x10,0x00,0x00 }, // 0x34 '4'
- {0x1F,0x01,0x0F,0x10,0x10,0x11,0x0E,0x00,0x00 }, // 0x35 '5'
- {0x0E,0x01,0x01,0x0F,0x11,0x11,0x0E,0x00,0x00 }, // 0x36 '6'
- {0x1F,0x10,0x10,0x08,0x04,0x04,0x04,0x00,0x00 }, // 0x37 '7'
- {0x0E,0x11,0x11,0x0E,0x11,0x11,0x0E,0x00,0x00 }, // 0x38 '8'
- {0x0E,0x11,0x11,0x1E,0x10,0x11,0x0E,0x00,0x00 }, // 0x39 '9'
- {0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00 }, // 0x3A ':'
- {0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x02,0x00 }, // 0x3B ';'
- {0x00,0x18,0x06,0x01,0x06,0x18,0x00,0x00,0x00 }, // 0x3C '<'
- {0x00,0x00,0x1F,0x00,0x1F,0x00,0x00,0x00,0x00 }, // 0x3D '='
- {0x00,0x03,0x0C,0x10,0x0C,0x03,0x00,0x00,0x00 }, // 0x3E '>'
- {0x0E,0x11,0x10,0x08,0x04,0x00,0x04,0x00,0x00 }, // 0x3F '?'
- {0x0E,0x19,0x15,0x15,0x19,0x01,0x0E,0x00,0x00 }, // 0x40 '@'
- {0x0E,0x11,0x11,0x11,0x1F,0x11,0x11,0x00,0x00 }, // 0x41 'A'
- {0x0F,0x11,0x11,0x0F,0x11,0x11,0x0F,0x00,0x00 }, // 0x42 'B'
- {0x0E,0x11,0x01,0x01,0x01,0x11,0x0E,0x00,0x00 }, // 0x43 'C'
- {0x0F,0x11,0x11,0x11,0x11,0x11,0x0F,0x00,0x00 }, // 0x44 'D'
- {0x1F,0x01,0x01,0x0F,0x01,0x01,0x1F,0x00,0x00 }, // 0x45 'E'
- {0x1F,0x01,0x01,0x0F,0x01,0x01,0x01,0x00,0x00 }, // 0x46 'F'
- {0x0E,0x11,0x01,0x1D,0x11,0x11,0x0E,0x00,0x00 }, // 0x47 'G'
- {0x11,0x11,0x11,0x1F,0x11,0x11,0x11,0x00,0x00 }, // 0x48 'H'
- {0x1F,0x04,0x04,0x04,0x04,0x04,0x1F,0x00,0x00 }, // 0x49 'I'
- {0x10,0x10,0x10,0x10,0x11,0x11,0x0E,0x00,0x00 }, // 0x4A 'J'
- {0x11,0x09,0x05,0x03,0x05,0x09,0x11,0x00,0x00 }, // 0x4B 'K'
- {0x01,0x01,0x01,0x01,0x01,0x01,0x1F,0x00,0x00 }, // 0x4C 'L'
- {0x11,0x1B,0x15,0x11,0x11,0x11,0x11,0x00,0x00 }, // 0x4D 'M'
- {0x11,0x11,0x13,0x15,0x19,0x11,0x11,0x00,0x00 }, // 0x4E 'N'
- {0x0E,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00 }, // 0x4F 'O'
- {0x0F,0x11,0x11,0x0F,0x01,0x01,0x01,0x00,0x00 }, // 0x50 'P'
- {0x0E,0x11,0x11,0x11,0x11,0x11,0x0E,0x18,0x00 }, // 0x51 'Q'
- {0x0F,0x11,0x11,0x0F,0x11,0x11,0x11,0x00,0x00 }, // 0x52 'R'
- {0x0E,0x11,0x01,0x0E,0x10,0x11,0x0E,0x00,0x00 }, // 0x53 'S'
- {0x1F,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00 }, // 0x54 'T'
- {0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00 }, // 0x55 'U'
- {0x11,0x11,0x11,0x11,0x0A,0x0A,0x04,0x00,0x00 }, // 0x56 'V'
- {0x11,0x11,0x11,0x11,0x15,0x1B,0x11,0x00,0x00 }, // 0x57 'W'
- {0x11,0x11,0x0A,0x04,0x0A,0x11,0x11,0x00,0x00 }, // 0x58 'X'
- {0x11,0x11,0x0A,0x04,0x04,0x04,0x04,0x00,0x00 }, // 0x59 'Y'
- {0x1F,0x10,0x08,0x04,0x02,0x01,0x1F,0x00,0x00 }, // 0x5A 'Z'
- {0x0C,0x04,0x04,0x04,0x04,0x04,0x0C,0x00,0x00 }, // 0x5B '['
- {0x01,0x01,0x02,0x04,0x08,0x10,0x10,0x00,0x00 }, // 0x5C '\'
- {0x06,0x04,0x04,0x04,0x04,0x04,0x06,0x00,0x00 }, // 0x5D ']'
- {0x04,0x0A,0x11,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5E '^'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00 }, // 0x5F '_'
- {0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x60 '`'
- {0x00,0x00,0x1E,0x11,0x11,0x11,0x1E,0x00,0x00 }, // 0x61 'a'
- {0x01,0x01,0x0F,0x11,0x11,0x11,0x0F,0x00,0x00 }, // 0x62 'b'
- {0x00,0x00,0x0E,0x11,0x01,0x11,0x0E,0x00,0x00 }, // 0x63 'c'
- {0x10,0x10,0x1E,0x11,0x11,0x11,0x1E,0x00,0x00 }, // 0x64 'd'
- {0x00,0x00,0x0E,0x11,0x1F,0x01,0x0E,0x00,0x00 }, // 0x65 'e'
- {0x0C,0x12,0x02,0x0F,0x02,0x02,0x02,0x00,0x00 }, // 0x66 'f'
- {0x00,0x00,0x1E,0x11,0x11,0x11,0x1E,0x10,0x0E }, // 0x67 'g'
- {0x01,0x01,0x0F,0x11,0x11,0x11,0x11,0x00,0x00 }, // 0x68 'h'
- {0x04,0x00,0x06,0x04,0x04,0x04,0x1F,0x00,0x00 }, // 0x69 'i'
- {0x10,0x00,0x18,0x10,0x10,0x10,0x10,0x11,0x0E }, // 0x6A 'j'
- {0x01,0x01,0x11,0x09,0x07,0x09,0x11,0x00,0x00 }, // 0x6B 'k'
- {0x03,0x02,0x02,0x02,0x02,0x02,0x1C,0x00,0x00 }, // 0x6C 'l'
- {0x00,0x00,0x0F,0x15,0x15,0x15,0x15,0x00,0x00 }, // 0x6D 'm'
- {0x00,0x00,0x0F,0x11,0x11,0x11,0x11,0x00,0x00 }, // 0x6E 'n'
- {0x00,0x00,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00 }, // 0x6F 'o'
- {0x00,0x00,0x0F,0x11,0x11,0x11,0x0F,0x01,0x01 }, // 0x70 'p'
- {0x00,0x00,0x1E,0x11,0x11,0x11,0x1E,0x10,0x10 }, // 0x71 'q'
- {0x00,0x00,0x0D,0x13,0x01,0x01,0x01,0x00,0x00 }, // 0x72 'r'
- {0x00,0x00,0x1E,0x01,0x0E,0x10,0x0F,0x00,0x00 }, // 0x73 's'
- {0x02,0x02,0x0F,0x02,0x02,0x02,0x1C,0x00,0x00 }, // 0x74 't'
- {0x00,0x00,0x11,0x11,0x11,0x11,0x1E,0x00,0x00 }, // 0x75 'u'
- {0x00,0x00,0x11,0x11,0x11,0x0A,0x04,0x00,0x00 }, // 0x76 'v'
- {0x00,0x00,0x11,0x11,0x15,0x15,0x0A,0x00,0x00 }, // 0x77 'w'
- {0x00,0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00 }, // 0x78 'x'
- {0x00,0x00,0x11,0x11,0x11,0x11,0x1E,0x10,0x0E }, // 0x79 'y'
- {0x00,0x00,0x1F,0x08,0x04,0x02,0x1F,0x00,0x00 }, // 0x7A 'z'
- {0x08,0x04,0x04,0x02,0x04,0x04,0x08,0x00,0x00 }, // 0x7B '{'
- {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00 }, // 0x7C '|'
- {0x02,0x04,0x04,0x08,0x04,0x04,0x02,0x00,0x00 }, // 0x7D '}'
- {0x12,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_monogram_5X9[] = {
-6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};
-const UG_FONT font_monogram_5X9 = { (unsigned char*)fontBits_monogram_5X9, FONT_TYPE_1BPP, 5, 9, 32, 126, fontWidths_monogram_5X9 };
### src/ui/fonts/monogram_5X9.h
@@ -1,3 +0,0 @@
-#include <ugui.h>
-
-extern const UG_FONT font_monogram_5X9;
### src/ui/fonts/password_11X12.c
@@ -1,105 +0,0 @@
-// This is a copy of font_a_11X12.c with a modified space character
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_password_11X12[95][24] = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x7F, 0x00, 0x00, 0x00 }, // 0x20 (0x2423) '#'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!'
- {0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '"'
- {0x28, 0x00, 0x28, 0x00, 0x7F, 0x00, 0x14, 0x00, 0x14, 0x00, 0x7F, 0x00, 0x14, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#'
- {0x1C, 0x00, 0x2A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x1C, 0x00, 0x28, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$'
- {0x8C, 0x00, 0x52, 0x00, 0x52, 0x00, 0x32, 0x00, 0xAC, 0x01, 0x60, 0x02, 0x50, 0x02, 0x50, 0x02, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%'
- {0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x14, 0x00, 0x0C, 0x00, 0x52, 0x00, 0x22, 0x00, 0x62, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '''
- {0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00 }, // 0x28 '('
- {0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00 }, // 0x29 ')'
- {0x04, 0x00, 0x1F, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2A '*'
- {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x3E, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x2C ','
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2D '-'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2E '.'
- {0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0'
- {0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1'
- {0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2'
- {0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3'
- {0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x3E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4'
- {0x3C, 0x00, 0x04, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5'
- {0x1C, 0x00, 0x22, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6'
- {0x3E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9'
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':'
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x3B ';'
- {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3C '<'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '='
- {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>'
- {0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?'
- {0xE0, 0x01, 0x18, 0x06, 0x04, 0x04, 0x64, 0x09, 0x92, 0x09, 0x8A, 0x08, 0x8A, 0x08, 0x8A, 0x04, 0xF2, 0x03, 0x04, 0x08, 0x08, 0x06, 0xF0, 0x01 }, // 0x40 '@'
- {0x08, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x3E, 0x00, 0x22, 0x00, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A'
- {0x3E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C'
- {0x3E, 0x00, 0x42, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D'
- {0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E'
- {0x3E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x02, 0x00, 0xE2, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G'
- {0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xFE, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I'
- {0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J'
- {0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x16, 0x00, 0x22, 0x00, 0x42, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L'
- {0x82, 0x00, 0xC6, 0x00, 0xC6, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x92, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M'
- {0x82, 0x00, 0x86, 0x00, 0x8A, 0x00, 0x8A, 0x00, 0x92, 0x00, 0xA2, 0x00, 0xA2, 0x00, 0xC2, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O'
- {0x3E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P'
- {0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xB2, 0x00, 0x44, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q'
- {0x7E, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x7E, 0x00, 0x22, 0x00, 0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x52 'R'
- {0x3C, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S'
- {0x7F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T'
- {0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U'
- {0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V'
- {0x21, 0x04, 0x51, 0x04, 0x51, 0x02, 0x52, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x8A, 0x02, 0x04, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W'
- {0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X'
- {0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y'
- {0x7E, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z'
- {0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00 }, // 0x5B '['
- {0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5C '\'
- {0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00 }, // 0x5D ']'
- {0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5E '^'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00 }, // 0x5F '_'
- {0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a'
- {0x02, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b'
- {0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x12, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c'
- {0x20, 0x00, 0x20, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3E, 0x00, 0x02, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e'
- {0x0C, 0x00, 0x02, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f'
- {0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x1E, 0x00, 0x00, 0x00 }, // 0x67 'g'
- {0x02, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x68 'h'
- {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i'
- {0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00 }, // 0x6A 'j'
- {0x02, 0x00, 0x02, 0x00, 0x22, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x0E, 0x00, 0x12, 0x00, 0x12, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6B 'k'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l'
- {0x00, 0x00, 0x00, 0x00, 0x9A, 0x01, 0x66, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm'
- {0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o'
- {0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x26, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x26, 0x00, 0x1A, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x70 'p'
- {0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x32, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00 }, // 0x71 'q'
- {0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x72 'r'
- {0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's'
- {0x02, 0x00, 0x02, 0x00, 0x07, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't'
- {0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x11, 0x01, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x44, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x'
- {0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x79 'y'
- {0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7A 'z'
- {0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00 }, // 0x7B '{'
- {0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x7C '|'
- {0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 }, // 0x7D '}'
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_password_11X12[] = {
- 7, 3, 4, 7, 7, 11, 8, 2, 4, 4, 5, 7, 3, 4, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 7, 7, 7, 7, 12, 7, 8, 9, 9, 8, 7, 9, 9, 3, 6, 8, 7, 9, 9, 9, 8, 9, 9, 8, 7, 9, 7, 11, 7, 7, 7, 3, 3, 3, 5, 7, 4, 7, 7, 6, 7, 7, 3, 7, 7, 3, 3, 6, 3, 11, 7, 7, 7, 7, 4, 7, 3, 7, 5, 9, 5, 5, 5, 4, 3, 4, 7
-};
-const UG_FONT font_password_11X12 = { (unsigned char *)fontBits_password_11X12, FONT_TYPE_1BPP, 11, 12, 32, 126, fontWidths_password_11X12 };
### src/ui/fonts/password_11X12.h
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include <ugui.h>
-
-extern const UG_FONT font_password_11X12;
### src/ui/fonts/password_9X9.c
@@ -1,104 +0,0 @@
-// This is a copy of font_a_9X9.c with a modified space character
-
-#include <ugui.h>
-
-static UG_FONT_DATA unsigned char fontBits_password_9X9[95][18] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x22,0x00,0x3E,0x00 }, // 0x20 (0x2423) '#'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x21 '!'
- {0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x22 '"'
- {0x0A,0x00,0x0A,0x00,0x0F,0x00,0x0A,0x00,0x0F,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00 }, // 0x23 '#'
- {0x0E,0x00,0x15,0x00,0x05,0x00,0x0E,0x00,0x14,0x00,0x15,0x00,0x0E,0x00,0x04,0x00,0x00,0x00 }, // 0x24 '$'
- {0x24,0x00,0x1A,0x00,0x14,0x00,0x10,0x00,0x28,0x00,0x58,0x00,0x28,0x00,0x00,0x00,0x00,0x00 }, // 0x25 '%'
- {0x0C,0x00,0x12,0x00,0x12,0x00,0x0E,0x00,0x29,0x00,0x11,0x00,0x2E,0x00,0x00,0x00,0x00,0x00 }, // 0x26 '&'
- {0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x27 '''
- {0x04,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x04,0x00 }, // 0x28 '('
- {0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x00 }, // 0x29 ')'
- {0x07,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2A '*'
- {0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x2B '+'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x2C ','
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x2D '-'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x2E '.'
- {0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x2F '/'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x30 '0'
- {0x04,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x31 '1'
- {0x06,0x00,0x09,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x0F,0x00,0x00,0x00,0x00,0x00 }, // 0x32 '2'
- {0x06,0x00,0x09,0x00,0x08,0x00,0x04,0x00,0x08,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x33 '3'
- {0x08,0x00,0x0C,0x00,0x0A,0x00,0x09,0x00,0x1F,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x34 '4'
- {0x0E,0x00,0x02,0x00,0x07,0x00,0x09,0x00,0x08,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x35 '5'
- {0x06,0x00,0x09,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x36 '6'
- {0x0F,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x37 '7'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x38 '8'
- {0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x39 '9'
- {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x3A ':'
- {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x3B ';'
- {0x00,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3C '<'
- {0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3D '='
- {0x00,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x3E '>'
- {0x0E,0x00,0x11,0x00,0x10,0x00,0x0C,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x3F '?'
- {0x78,0x00,0x84,0x00,0x52,0x01,0x6A,0x01,0x2A,0x01,0xAA,0x00,0x7A,0x00,0x84,0x01,0x78,0x00 }, // 0x40 '@'
- {0x08,0x00,0x14,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x41 'A'
- {0x0E,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x12,0x00,0x12,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x42 'B'
- {0x1C,0x00,0x22,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x43 'C'
- {0x1E,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x44 'D'
- {0x3E,0x00,0x02,0x00,0x02,0x00,0x3E,0x00,0x02,0x00,0x02,0x00,0x3E,0x00,0x00,0x00,0x00,0x00 }, // 0x45 'E'
- {0x1E,0x00,0x02,0x00,0x02,0x00,0x0E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x46 'F'
- {0x1C,0x00,0x22,0x00,0x02,0x00,0x32,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x47 'G'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x48 'H'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x49 'I'
- {0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x09,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x4A 'J'
- {0x22,0x00,0x12,0x00,0x0A,0x00,0x06,0x00,0x0A,0x00,0x12,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x4B 'K'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x1E,0x00,0x00,0x00,0x00,0x00 }, // 0x4C 'L'
- {0x41,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x4D 'M'
- {0x22,0x00,0x26,0x00,0x26,0x00,0x2A,0x00,0x32,0x00,0x32,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x4E 'N'
- {0x1C,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x4F 'O'
- {0x1E,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x50 'P'
- {0x1C,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x12,0x00,0x3C,0x00,0x00,0x00,0x00,0x00 }, // 0x51 'Q'
- {0x1E,0x00,0x22,0x00,0x22,0x00,0x1E,0x00,0x12,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00 }, // 0x52 'R'
- {0x0C,0x00,0x12,0x00,0x02,0x00,0x0C,0x00,0x10,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00 }, // 0x53 'S'
- {0x1F,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x54 'T'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00 }, // 0x55 'U'
- {0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x56 'V'
- {0x11,0x01,0x29,0x01,0xAA,0x00,0xAA,0x00,0xAA,0x00,0xAA,0x00,0x44,0x00,0x00,0x00,0x00,0x00 }, // 0x57 'W'
- {0x11,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x0A,0x00,0x0A,0x00,0x11,0x00,0x00,0x00,0x00,0x00 }, // 0x58 'X'
- {0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00 }, // 0x59 'Y'
- {0x3F,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x3F,0x00,0x00,0x00,0x00,0x00 }, // 0x5A 'Z'
- {0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00 }, // 0x5B '['
- {0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x5C '\'
- {0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00 }, // 0x5D ']'
- {0x02,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x5E '^'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00 }, // 0x5F '_'
- {0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0x60 '`'
- {0x00,0x00,0x00,0x00,0x0F,0x00,0x08,0x00,0x0E,0x00,0x09,0x00,0x0F,0x00,0x00,0x00,0x00,0x00 }, // 0x61 'a'
- {0x01,0x00,0x01,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x62 'b'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x01,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x63 'c'
- {0x08,0x00,0x08,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x64 'd'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x0F,0x00,0x01,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x65 'e'
- {0x04,0x00,0x02,0x00,0x07,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00 }, // 0x66 'f'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x09,0x00,0x06,0x00 }, // 0x67 'g'
- {0x01,0x00,0x01,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x68 'h'
- {0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x69 'i'
- {0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00 }, // 0x6A 'j'
- {0x01,0x00,0x01,0x00,0x09,0x00,0x05,0x00,0x07,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x6B 'k'
- {0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x6C 'l'
- {0x00,0x00,0x00,0x00,0x3F,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00 }, // 0x6D 'm'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x6E 'n'
- {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x00,0x00 }, // 0x6F 'o'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x07,0x00,0x01,0x00,0x01,0x00 }, // 0x70 'p'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x08,0x00,0x08,0x00 }, // 0x71 'q'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }, // 0x72 'r'
- {0x00,0x00,0x00,0x00,0x0E,0x00,0x01,0x00,0x06,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x73 's'
- {0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00 }, // 0x74 't'
- {0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x0E,0x00,0x00,0x00,0x00,0x00 }, // 0x75 'u'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x00,0x00,0x00,0x00 }, // 0x76 'v'
- {0x00,0x00,0x00,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x0A,0x00,0x00,0x00,0x00,0x00 }, // 0x77 'w'
- {0x00,0x00,0x00,0x00,0x09,0x00,0x06,0x00,0x02,0x00,0x06,0x00,0x09,0x00,0x00,0x00,0x00,0x00 }, // 0x78 'x'
- {0x00,0x00,0x00,0x00,0x11,0x00,0x0A,0x00,0x0A,0x00,0x0A,0x00,0x04,0x00,0x04,0x00,0x02,0x00 }, // 0x79 'y'
- {0x00,0x00,0x00,0x00,0x07,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00 }, // 0x7A 'z'
- {0x06,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x06,0x00 }, // 0x7B '{'
- {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00 }, // 0x7C '|'
- {0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00 }, // 0x7D '}'
- {0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // 0x7E '~'
-};
-static UG_U8 fontWidths_password_9X9[] = {
-7,3,3,5,5,8,6,2,3,3,4,5,3,3,3,3,5,5,5,5,5,5,5,5,5,5,3,3,5,5,5,5,9,6,6,7,7,6,6,7,7,3,5,6,5,7,7,7,6,7,7,6,5,7,6,9,5,7,6,3,3,3,3,5,3,5,5,5,5,5,4,5,5,2,3,5,2,8,5,5,5,5,3,5,3,5,6,6,5,6,4,3,3,3,5};
-UG_FONT font_password_9X9 = { (unsigned char*)fontBits_password_9X9, FONT_TYPE_1BPP, 9, 9, 32, 126, fontWidths_password_9X9 };
### src/ui/fonts/password_9X9.h
@@ -1,3 +0,0 @@
-#include <ugui.h>
-
-extern const UG_FONT font_password_9X9;
### src/ui/oled/oled.c
@@ -57,13 +57,11 @@
#include <driver_init.h>
#include <hardfault.h>
#include <memory/memory_shared.h>
-#include <screen.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <ui/oled/sh1107.h>
#include <ui/oled/ssd1312.h>
-#include <ui/ugui/ugui.h>
static bool _frame_buffer_updated = false;
static uint8_t _frame_buffer[128 * 8];
### src/ui/ugui/ugui.c
@@ -51,6 +51,7 @@
#include <stdbool.h>
#include <string.h>
+#include <hardfault.h>
#include <ui/oled/oled.h>
#include <util.h>
#include <utils_assert.h>
@@ -87,99 +88,128 @@ static void _UG_PSet(UG_S16 x, UG_S16 y, UG_COLOR c)
gui->pset(x, y, c);
}
-static void _UG_PutChar( char chr, UG_S16 x, UG_S16 y, UG_COLOR fc, UG_COLOR bc,
- const UG_FONT *font)
-{
- UG_U16 i, j, k, xo, yo, c, bn, actual_char_width;
- UG_U8 b, bt;
- UG_U32 index;
- UG_COLOR color;
-
- bt = (UG_U8)chr;
-
- switch (bt ) {
- case 0xF6:
- bt = 0x94;
- break; // ö
- case 0xD6:
- bt = 0x99;
- break; // Ö
- case 0xFC:
- bt = 0x81;
- break; // ü
- case 0xDC:
- bt = 0x9A;
- break; // Ü
- case 0xE4:
- bt = 0x84;
- break; // ä
- case 0xC4:
- bt = 0x8E;
- break; // Ä
- case 0xB5:
- bt = 0xE6;
- break; // µ
- case 0xB0:
- bt = 0xF8;
- break; // °
- default:
- break;
+static bool _UG_IsUtf8Continuation(uint8_t byte)
+{
+ return (byte & 0xC0) == 0x80;
+}
+
+/**
+ * Decodes the next UTF-8 codepoint and returns the byte after it.
+ *
+ * The leading byte determines the sequence length. ASCII bytes are returned
+ * directly, valid 2-, 3-, and 4-byte sequences are assembled from their payload
+ * bits. Returns NULL on malformed UTF-8, leaving `codepoint` unchanged.
+ * At the NUL terminator, sets `codepoint` to zero and returns `str` unchanged.
+ */
+static const char* _UG_NextCodepoint(const char* str, uint32_t* codepoint)
+{
+ const uint8_t* bytes = (const uint8_t*)str;
+ if (bytes[0] == '\0') {
+ *codepoint = '\0';
+ return str;
+ }
+ if (bytes[0] < 0x80) {
+ *codepoint = bytes[0];
+ return str + 1;
+ }
+ if (bytes[0] >= 0xC2 && bytes[0] <= 0xDF && _UG_IsUtf8Continuation(bytes[1])) {
+ *codepoint = ((uint32_t)(bytes[0] & 0x1F) << 6) | (uint32_t)(bytes[1] & 0x3F);
+ return str + 2;
+ }
+ if (bytes[0] >= 0xE0 && bytes[0] <= 0xEF && _UG_IsUtf8Continuation(bytes[1]) &&
+ (bytes[0] != 0xE0 || bytes[1] >= 0xA0) &&
+ (bytes[0] != 0xED || bytes[1] <= 0x9F) && _UG_IsUtf8Continuation(bytes[2])) {
+ *codepoint = ((uint32_t)(bytes[0] & 0x0F) << 12) |
+ ((uint32_t)(bytes[1] & 0x3F) << 6) | (uint32_t)(bytes[2] & 0x3F);
+ return str + 3;
+ }
+ if (bytes[0] >= 0xF0 && bytes[0] <= 0xF4 && _UG_IsUtf8Continuation(bytes[1]) &&
+ (bytes[0] != 0xF0 || bytes[1] >= 0x90) &&
+ (bytes[0] != 0xF4 || bytes[1] <= 0x8F) && _UG_IsUtf8Continuation(bytes[2]) &&
+ _UG_IsUtf8Continuation(bytes[3])) {
+ *codepoint = ((uint32_t)(bytes[0] & 0x07) << 18) |
+ ((uint32_t)(bytes[1] & 0x3F) << 12) |
+ ((uint32_t)(bytes[2] & 0x3F) << 6) | (uint32_t)(bytes[3] & 0x3F);
+ return str + 4;
+ }
+ return NULL;
+}
+
+static bool _UG_GetGlyph(const UG_FONT* font, uint32_t codepoint, lv_font_glyph_dsc_t* glyph_dsc)
+{
+ for (const lv_font_t* f = font; f != NULL; f = f->fallback) {
+ if (f->get_glyph_dsc == NULL) {
+ continue;
+ }
+ if (f->get_glyph_dsc(f, glyph_dsc, codepoint, 0)) {
+ glyph_dsc->resolved_font = f;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool UG_GetCharWidth(const UG_FONT* font, uint32_t codepoint, UG_U16* width)
+{
+ lv_font_glyph_dsc_t glyph_dsc;
+ if (!_UG_GetGlyph(font, codepoint, &glyph_dsc)) {
+ return false;
}
+ *width = glyph_dsc.adv_w;
+ return true;
+}
- if (bt < font->start_char || bt > font->end_char) {
+static bool _UG_GlyphPixelSet(
+ const uint8_t* bitmap,
+ const lv_font_glyph_dsc_t* glyph_dsc,
+ UG_U16 x,
+ UG_U16 y)
+{
+ uint32_t bit_index = (uint32_t)y * glyph_dsc->box_w + x;
+ return ((bitmap[bit_index / 8] >> (7 - (bit_index % 8))) & 0x01) != 0;
+}
+
+static void _UG_PutCodepoint( uint32_t codepoint, UG_S16 x, UG_S16 y, UG_COLOR fc, UG_COLOR bc,
+ const UG_FONT *font)
+{
+ lv_font_glyph_dsc_t glyph_dsc;
+ if (!_UG_GetGlyph(font, codepoint, &glyph_dsc)) {
+ return;
+ }
+ const lv_font_t* resolved_font = glyph_dsc.resolved_font;
+ if (resolved_font == NULL || glyph_dsc.format != LV_FONT_GLYPH_FORMAT_A1 ||
+ glyph_dsc.stride != 0) {
return;
}
- yo = y;
- bn = font->char_width;
- if ( !bn ) {
+ if (x + glyph_dsc.adv_w < 0 || x > gui->x_dim) {
return;
}
- bn >>= 3;
- if ( font->char_width % 8 ) {
- bn++;
+
+ for (UG_S16 row = 0; row < font->line_height; row++) {
+ for (UG_U16 col = 0; col < glyph_dsc.adv_w; col++) {
+ _UG_PSet(x + col, y + row, bc);
+ }
+ }
+ if (codepoint == '\t' || glyph_dsc.box_w == 0 || glyph_dsc.box_h == 0 ||
+ resolved_font->get_glyph_bitmap == NULL) {
+ return;
}
- actual_char_width = (font->widths ? font->widths[bt - font->start_char] :
- font->char_width);
- if (x + actual_char_width < 0 || x > gui->x_dim) {
+ const uint8_t* bitmap = (const uint8_t*)resolved_font->get_glyph_bitmap(&glyph_dsc, NULL);
+ if (bitmap == NULL) {
return;
}
- if (font->font_type == FONT_TYPE_1BPP) {
- index = (bt - font->start_char) * font->char_height * bn;
- for ( j = 0; j < font->char_height; j++ ) {
- xo = x;
- c = actual_char_width;
- for ( i = 0; i < bn; i++ ) {
- b = font->p[index++];
- for ( k = 0; (k < 8) && c; k++ ) {
- if ( b & 0x01 ) {
- _UG_PSet(xo, yo, fc);
- } else {
- _UG_PSet(xo, yo, bc);
- }
- b >>= 1;
- xo++;
- c--;
- }
- }
- yo++;
- }
- } else if (font->font_type == FONT_TYPE_8BPP) {
- index = (bt - font->start_char) * font->char_height * font->char_width;
- for ( j = 0; j < font->char_height; j++ ) {
- xo = x;
- for ( i = 0; i < actual_char_width; i++ ) {
- b = font->p[index++];
- color = ((((fc & 0xFF) * b + (bc & 0xFF) * (256 - b)) >> 8) & 0xFF) |//Blue component
- ((((fc & 0xFF00) * b + (bc & 0xFF00) * (256 - b)) >> 8) & 0xFF00) |//Green component
- ((((fc & 0xFF0000) * b + (bc & 0xFF0000) * (256 - b)) >> 8) & 0xFF0000); //Red component
- _UG_PSet(xo, yo, color);
- xo++;
+ UG_S16 glyph_y =
+ font->line_height - resolved_font->base_line - glyph_dsc.box_h - glyph_dsc.ofs_y;
+ for (UG_U16 row = 0; row < glyph_dsc.box_h; row++) {
+ for (UG_U16 col = 0; col < glyph_dsc.box_w; col++) {
+ UG_S16 xo = x + glyph_dsc.ofs_x + col;
+ UG_S16 yo = y + glyph_y + row;
+ if (_UG_GlyphPixelSet(bitmap, &glyph_dsc, col, row)) {
+ _UG_PSet(xo, yo, fc);
}
- index += font->char_width - actual_char_width;
- yo++;
}
}
}
@@ -190,39 +220,41 @@ static void _UG_PutString( UG_S16 x, UG_S16 y, UG_S16 *xout, UG_S16 *yout, const
ASSERT(gui != NULL);
UG_S16 xp, yp;
- UG_U8 cw;
- char chr;
+ UG_U16 cw;
+ uint32_t codepoint;
UG_S16 max_x = x;
xp = x;
yp = y;
- const int str_length = strlens(str);
+ const char* cursor = str;
- for (int i = 0; i < str_length; i++) {
- chr = str[i];
- if (chr != '\n' && (chr < gui->font.start_char || chr > gui->font.end_char)) {
+ while (*cursor != '\0') {
+ cursor = _UG_NextCodepoint(cursor, &codepoint);
+ if (cursor == NULL) {
+ Abort("Invalid UTF-8 string");
+ }
+ if (codepoint != '\n' && !UG_GetCharWidth(gui->font, codepoint, &cw)) {
continue;
}
- if ( chr == '\n' ) {
+ if ( codepoint == '\n' ) {
if (autobreak == 1) {
xp = gui->x_dim;
} else {
xp = x;
- yp += gui->font.char_height + gui->char_v_space;
+ yp += gui->font->line_height + gui->char_v_space;
}
continue;
}
- cw = gui->font.widths ? gui->font.widths[chr - gui->font.start_char] :
- gui->font.char_width;
if ( autobreak == 1 && xp + cw > gui->x_dim - 1 ) {
xp = x;
- yp += gui->font.char_height + gui->char_v_space;
+ yp += gui->font->line_height + gui->char_v_space;
}
if (!calconly) {
- UG_PutChar(chr, xp, yp, gui->fore_color, gui->back_color);
+ _UG_PutCodepoint(
+ codepoint, xp, yp, gui->fore_color, gui->back_color, gui->font);
}
xp += cw + gui->char_h_space;
@@ -234,7 +266,7 @@ static void _UG_PutString( UG_S16 x, UG_S16 y, UG_S16 *xout, UG_S16 *yout, const
*xout = max_x;
}
if (yout) {
- *yout = yp + gui->font.char_height;
+ *yout = yp + gui->font->line_height;
}
}
@@ -248,7 +280,7 @@ UG_S16 UG_Init( UG_GUI *g, void (*p)(UG_S16, UG_S16, UG_COLOR),
g->pset = p;
g->x_dim = x;
g->y_dim = y;
- g->font = *font;
+ g->font = font;
g->char_h_space = 1;
g->char_v_space = 1;
g->fore_color = C_WHITE;
@@ -264,7 +296,7 @@ void UG_FontSelect( const UG_FONT *font )
ASSERT(gui != NULL);
ASSERT(font != NULL);
- gui->font = *font;
+ gui->font = font;
}
void UG_FillScreen( UG_COLOR c )
@@ -633,15 +665,42 @@ static bool _is_whitespace(char c) {
}
static UG_S16 _word_width(const char* p) {
- const UG_FONT* font = &gui->font;
+ const UG_FONT* font = gui->font;
UG_S16 x = 0;
while(!_is_whitespace(*p)) {
- x += font->widths[(UG_U8)*p - font->start_char];
- p += 1;
+ uint32_t codepoint = 0;
+ p = _UG_NextCodepoint(p, &codepoint);
+ if (p == NULL) {
+ Abort("Invalid UTF-8 string");
+ }
+ UG_U16 char_width = 0;
+ if (UG_GetCharWidth(font, codepoint, &char_width)) {
+ x += char_width;
+ }
}
return x;
}
+static void _copy_codepoint(const char** str, char** str_out, UG_S16* x)
+{
+ const UG_FONT* font = gui->font;
+ const char* next;
+ uint32_t codepoint = 0;
+ UG_U16 char_width = 0;
+ next = _UG_NextCodepoint(*str, &codepoint);
+ if (next == NULL) {
+ Abort("Invalid UTF-8 string");
+ }
+ while (*str < next) {
+ **str_out = **str;
+ *str_out += 1;
+ *str += 1;
+ }
+ if (UG_GetCharWidth(font, codepoint, &char_width)) {
+ *x += char_width;
+ }
+}
+
// Try to wrap string at spaces if it is longer than `width` pixels.
// Since the purpose of this function is to wrap title text, only wrap a single time. The rest of
// the title may span/overflow the whole screen.
@@ -653,7 +712,7 @@ void UG_WrapTitleString(const char* str, char* str_out, UG_S16 width) {
ASSERT(str_out != NULL);
const char* start = str;
- const UG_FONT* font = &gui->font;
+ const UG_FONT* font = gui->font;
UG_S16 x = 0;
// This loop will copy bytes until the first newline.
@@ -668,7 +727,9 @@ void UG_WrapTitleString(const char* str, char* str_out, UG_S16 width) {
}
if (*str == ' ') {
UG_S16 wwidth = _word_width(str+1);
- if (x + font->widths[(UG_U8)' ' - font->start_char] + wwidth > width) {
+ UG_U16 space_width = 0;
+ UG_GetCharWidth(font, ' ', &space_width);
+ if (x + space_width + wwidth > width) {
*str_out = '\n';
str_out += 1;
str += 1;
@@ -678,12 +739,7 @@ void UG_WrapTitleString(const char* str, char* str_out, UG_S16 width) {
str_out += 1;
str += 1;
while (!_is_whitespace(*str)) {
- *str_out = *str;
- if (*str >= font->start_char){
- x += font->widths[(UG_U8)*str - font->start_char];
- }
- str_out += 1;
- str += 1;
+ _copy_codepoint(&str, &str_out, &x);
}
continue;
}
@@ -696,12 +752,7 @@ void UG_WrapTitleString(const char* str, char* str_out, UG_S16 width) {
break;
}
}
- *str_out = *str;
- if (*str >= font->start_char && *str < font->end_char){
- x += font->widths[(UG_U8)*str - font->start_char];
- }
- str_out += 1;
- str += 1;
+ _copy_codepoint(&str, &str_out, &x);
}
// Copy any bytes that are left
@@ -815,7 +866,7 @@ void UG_PutChar( char chr, UG_S16 x, UG_S16 y, UG_COLOR fc, UG_COLOR bc )
{
ASSERT(gui != NULL);
- _UG_PutChar(chr, x, y, fc, bc, &gui->font);
+ _UG_PutCodepoint((UG_U8)chr, x, y, fc, bc, gui->font);
}
void UG_SetForecolor( UG_COLOR c )
### src/ui/ugui/ugui.h
@@ -25,6 +25,8 @@
#include <stdlib.h>
#include <math.h>
+#include <ui/fonts/lvgl.h>
+
/* -------------------------------------------------------------------------------- */
/* -- TYPEDEFS -- */
/* -------------------------------------------------------------------------------- */
@@ -40,22 +42,9 @@ typedef UG_U8 UG_COLOR;
/* -------------------------------------------------------------------------------- */
/* -- µGUI FONTS -- */
/* -------------------------------------------------------------------------------- */
-typedef enum {
- FONT_TYPE_1BPP,
- FONT_TYPE_8BPP
-} FONT_TYPE;
-
-typedef struct {
- unsigned char *p;
- FONT_TYPE font_type;
- UG_S16 char_width;
- UG_S16 char_height;
- UG_U16 start_char;
- UG_U16 end_char;
- UG_U8 *widths;
-} UG_FONT;
-
-#define UG_FONT_DATA const
+// Fonts retained by the GUI or components must have static lifetime, including their referenced
+// glyph data and fallback fonts.
+typedef lv_font_t UG_FONT;
/* -------------------------------------------------------------------------------- */
/* -- µGUI CORE STRUCTURE -- */
@@ -64,7 +53,7 @@ typedef struct {
void (*pset)(UG_S16, UG_S16, UG_COLOR);
UG_S16 x_dim;
UG_S16 y_dim;
- UG_FONT font;
+ const UG_FONT *font;
UG_S8 char_h_space;
UG_S8 char_v_space;
UG_COLOR fore_color;
@@ -91,8 +80,16 @@ typedef struct {
/* -- PROTOTYPES -- */
/* -------------------------------------------------------------------------------- */
+/**
+ * Initializes and selects the GUI, retaining `font` for later rendering.
+ * @param[in] font The initial font. Must have static lifetime.
+ */
UG_S16 UG_Init( UG_GUI *g, void (*p)(UG_S16, UG_S16, UG_COLOR),
const UG_FONT *font, UG_S16 x, UG_S16 y );
+/**
+ * Selects and retains the font in the current GUI.
+ * @param[in] font The font to use. Must have static lifetime.
+ */
void UG_FontSelect( const UG_FONT *font );
void UG_FillScreen( UG_COLOR c );
void UG_FillFrame( UG_S16 x1, UG_S16 y1, UG_S16 x2, UG_S16 y2, UG_COLOR c );
@@ -120,6 +117,7 @@ void UG_PutStringNoBreak( UG_S16 x, UG_S16 y, const char *str);
void UG_MeasureString( UG_S16 *xout, UG_S16 *yout, const char *str);
void UG_MeasureStringNoBreak(UG_S16 *xout, UG_S16 *yout, const char *str);
void UG_MeasureStringCentered( UG_S16 *xout, UG_S16 *yout, const char *str);
+bool UG_GetCharWidth(const UG_FONT* font, uint32_t codepoint, UG_U16* width);
void UG_PutStringNoBreakCenter( UG_S16 x, UG_S16 y, UG_S16 width, const char *str);
void UG_PutStringCentered( UG_S16 x, UG_S16 y, UG_S16 width, UG_S16 height, const char *str);
void UG_PutChar( char chr, UG_S16 x, UG_S16 y, UG_COLOR fc, UG_COLOR bc );
### src/util.c
@@ -69,20 +69,6 @@ intptr_t util_utf8_strlcpy(char* dst, const char* src, const size_t dst_len)
return util_utf8_copy(dst, dst_len, src, strlen(src));
}
-bool util_is_printable_ascii(const char* str, const bool allow_newline)
-{
- if (str == NULL) {
- return false;
- }
- for (; *str != '\0'; str++) {
- const unsigned char chr = (unsigned char)*str;
- if ((chr < 32 || chr > 126) && !(allow_newline && chr == '\n')) {
- return false;
- }
- }
- return true;
-}
-
void util_uint8_to_hex(const uint8_t* in_bin, const size_t in_len, char* out)
{
memset(out, 0, in_len * 2 + 1);
### src/util.h
@@ -63,9 +63,6 @@ intptr_t util_utf8_copy(char* dst, size_t dst_len, const char* src, size_t src_l
*/
intptr_t util_utf8_strlcpy(char* dst, const char* src, size_t dst_len);
-/** Returns true if `str` contains only printable ASCII, optionally including newlines. */
-bool util_is_printable_ascii(const char* str, bool allow_newline);
-
// `out` must be of size in_len*2+1. Use BB_HEX_SIZE() to compute the size.
void util_uint8_to_hex(const uint8_t* in_bin, size_t in_len, char* out);
### test/unit-test/CMakeLists.txt
@@ -51,6 +51,8 @@ else()
""
ui_components
""
+ lockscreen
+ ""
ui_util
""
ui_component_gestures
@@ -68,7 +70,7 @@ else()
util
""
ugui
- ""
+ "-Wl,--wrap=Abort"
)
list(LENGTH TEST_LIST TEST_LIST_LEN)
### test/unit-test/test_lockscreen.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <cmocka.h>
+
+#include "../../src/ui/components/lockscreen.c"
+
+static UG_GUI gui;
+
+static void _set_pixel(UG_S16 x, UG_S16 y, UG_COLOR color)
+{
+ (void)x;
+ (void)y;
+ (void)color;
+}
+
+static int _setup(void** state)
+{
+ (void)state;
+ UG_Init(&gui, _set_pixel, &font_regular_9, SCREEN_WIDTH, SCREEN_HEIGHT);
+ return 0;
+}
+
+static void test_truncate_to_fit_utf8(void** state)
+{
+ (void)state;
+ const char* names[] = {
+ "ThisIsANiceValidNameWhichIsMoreThan48ButLessThan63ü",
+ "üüüüüüüüüüüüüüüüüüüüüüüüüüüüüüü",
+ };
+ for (size_t i = 0; i < sizeof(names) / sizeof(*names); i++) {
+ char out[MEMORY_DEVICE_MAX_LEN_WITH_NULL + 3] = {0};
+ assert_false(label_fits_width(names[i], &font_regular_9, SCREEN_WIDTH));
+ _truncate_to_fit(names[i], out, sizeof(out), &font_regular_9, SCREEN_WIDTH);
+
+ const size_t len = strlen(out);
+ assert_true(len > 3);
+ assert_string_equal(out + len - 3, "...");
+ assert_memory_equal(out, names[i], len - 3);
+ assert_int_equal(
+ rust_util_utf8_truncate(rust_util_bytes((const uint8_t*)out, len), len), len);
+ assert_true(label_fits_width(out, &font_regular_9, SCREEN_WIDTH));
+ }
+}
+
+static void test_truncate_to_fit_capacity(void** state)
+{
+ (void)state;
+ const char* name = "1234567üThisNameIsTooLongToFitOnTheScreen";
+ char out[12] = {0};
+ // Reserving the ellipsis leaves eight bytes, which would split the two-byte ü.
+ _truncate_to_fit(name, out, sizeof(out), &font_regular_9, SCREEN_WIDTH);
+ assert_string_equal(out, "1234567...");
+
+ char ellipsis_only[4] = {0};
+ _truncate_to_fit(name, ellipsis_only, sizeof(ellipsis_only), &font_regular_9, SCREEN_WIDTH);
+ assert_string_equal(ellipsis_only, "...");
+}
+
+static void test_truncate_to_fit_short_name(void** state)
+{
+ (void)state;
+ char out[MEMORY_DEVICE_MAX_LEN_WITH_NULL + 3] = {0};
+ _truncate_to_fit("BïtBöx", out, sizeof(out), &font_regular_9, SCREEN_WIDTH);
+ assert_string_equal(out, "BïtBöx");
+ _truncate_to_fit("", out, sizeof(out), &font_regular_9, SCREEN_WIDTH);
+ assert_string_equal(out, "");
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_truncate_to_fit_utf8),
+ cmocka_unit_test(test_truncate_to_fit_capacity),
+ cmocka_unit_test(test_truncate_to_fit_short_name),
+ };
+ return cmocka_run_group_tests(tests, _setup, NULL);
+}
### test/unit-test/test_memory.c
@@ -538,7 +538,7 @@ static void _test_memory_get_device_name(void** state)
char name_out[MEMORY_DEVICE_MAX_LEN_WITH_NULL] = {0};
EMPTYCHUNK(chunk);
memset(chunk + _addr_device_name, 0, MEMORY_DEVICE_MAX_LEN_WITH_NULL);
- const char* device_name = "foo bar";
+ const char* device_name = "BïtBöx";
snprintf((char*)chunk + _addr_device_name, MEMORY_DEVICE_MAX_LEN_WITH_NULL, "%s", device_name);
expect_value(__wrap_memory_read_chunk_fake, chunk_num, 1);
@@ -588,6 +588,7 @@ static void _test_memory_device_name(void** state)
const char* device_name = "test name";
_set_device_name(device_name);
+ _set_device_name("BïtBöx");
const char* device_name2 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
_set_device_name(device_name2);
}
### test/unit-test/test_ugui.c
@@ -5,7 +5,9 @@
#include <stddef.h>
#include <cmocka.h>
-#include "ui/fonts/arial_fonts.h"
+#include "ui/fonts/password_12.h"
+#include "ui/fonts/password_9.h"
+#include "ui/fonts/regular_fonts.h"
#include "ui/ugui/ugui.h"
#include <string.h>
@@ -25,13 +27,52 @@ static UG_S16 last_x;
static UG_S16 last_y;
static UG_COLOR last_color;
static uint8_t pixels_set;
+static size_t set_pixel_count = 0;
+static size_t black_pixel_count = 0;
+
+void __wrap_Abort(const char* msg)
+{
+ check_expected(msg);
+ mock_assert(false, msg, __FILE__, __LINE__);
+}
+
+static void _assert_supported_font_subset(const UG_FONT* font)
+{
+ assert_non_null(font);
+ assert_ptr_equal(font->get_glyph_dsc, lv_font_get_glyph_dsc_fmt_txt);
+ assert_ptr_equal(font->get_glyph_bitmap, lv_font_get_bitmap_fmt_txt);
+ assert_non_null(font->dsc);
+
+ const lv_font_fmt_txt_dsc_t* font_dsc = (const lv_font_fmt_txt_dsc_t*)font->dsc;
+ assert_int_equal(font_dsc->bpp, 1);
+ assert_int_equal(font_dsc->stride, 0);
+ assert_int_equal(font_dsc->bitmap_format, LV_FONT_FMT_TXT_PLAIN);
+ assert_null(font_dsc->kern_dsc);
+ assert_int_equal(font_dsc->kern_scale, 0);
+ assert_int_equal(font_dsc->kern_classes, 0);
+ for (uint16_t i = 0; i < font_dsc->cmap_num; i++) {
+ const lv_font_fmt_txt_cmap_t* cmap = &font_dsc->cmaps[i];
+ assert_int_equal(cmap->type, LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY);
+ assert_null(cmap->unicode_list);
+ assert_null(cmap->glyph_id_ofs_list);
+ assert_int_equal(cmap->list_length, 0);
+ }
+
+ if (font->fallback != NULL) {
+ _assert_supported_font_subset(font->fallback);
+ }
+}
static void _set_pixel(UG_S16 x, UG_S16 y, UG_COLOR color)
{
last_x = x;
last_y = y;
last_color = color;
pixels_set++;
+ set_pixel_count++;
+ if (color == C_BLACK) {
+ black_pixel_count++;
+ }
}
static void _reset_pixel_capture(void)
@@ -45,7 +86,7 @@ static void _reset_pixel_capture(void)
static void _test_ugui_word_wrap(void** state)
{
(void)state; /* unused */
- UG_Init(&gui, _set_pixel, &font_font_a_11X10, 128, 64);
+ UG_Init(&gui, _set_pixel, &font_regular_9, 128, 64);
for (size_t i = 0; i < sizeof(data) / sizeof(*data); ++i) {
char buf[1024] = {0};
printf("test:\n%s\n", data[i][0]);
@@ -64,7 +105,7 @@ static void _draw_pixel(void* ctx)
static void _test_ugui_render_rotated_180(void** state)
{
(void)state; /* unused */
- UG_Init(&gui, _set_pixel, &font_font_a_11X10, 128, 64);
+ UG_Init(&gui, _set_pixel, &font_regular_11, 128, 64);
_reset_pixel_capture();
UG_RenderRotated180(10, 20, 30, 10, _draw_pixel, NULL);
@@ -83,7 +124,7 @@ static void _test_ugui_render_rotated_180(void** state)
static void _test_ugui_measure_string_centered(void** state)
{
(void)state;
- UG_Init(&gui, _set_pixel, &font_font_a_11X10, 128, 64);
+ UG_Init(&gui, _set_pixel, &font_regular_11, 128, 64);
UG_S16 centered_width = 0;
UG_S16 centered_height = 0;
@@ -96,12 +137,246 @@ static void _test_ugui_measure_string_centered(void** state)
assert_int_equal(centered_height, 2 * single_line_height + 2 * gui.char_v_space);
}
+static bool _capture_glyph_dsc(
+ const lv_font_t* font,
+ lv_font_glyph_dsc_t* glyph_dsc,
+ uint32_t codepoint,
+ uint32_t codepoint_next)
+{
+ (void)font;
+ check_expected(codepoint);
+ (void)codepoint_next;
+ memset(glyph_dsc, 0, sizeof(*glyph_dsc));
+ glyph_dsc->adv_w = 1;
+ return true;
+}
+
+static void _test_ugui_utf8_validation(void** state)
+{
+ (void)state;
+ static const UG_FONT capture_font = {
+ .get_glyph_dsc = _capture_glyph_dsc,
+ .line_height = 1,
+ };
+ UG_Init(&gui, _set_pixel, &capture_font, 128, 64);
+ UG_FontSetHSpace(0);
+
+ const struct {
+ const char* text;
+ uint32_t codepoint;
+ } valid[] = {
+ {"A", 0x41},
+ {"\xc2\x80", 0x80},
+ {"\xdf\xbf", 0x7ff},
+ {"\xe0\xa0\x80", 0x800},
+ {"\xed\x9f\xbf", 0xd7ff},
+ {"\xee\x80\x80", 0xe000},
+ {"\xef\xbf\xbf", 0xffff},
+ {"\xf0\x90\x80\x80", 0x10000},
+ {"\xf4\x8f\xbf\xbf", 0x10ffff},
+ };
+ UG_S16 width = 0;
+ UG_MeasureStringNoBreak(&width, NULL, "");
+ assert_int_equal(width, 0);
+ for (size_t i = 0; i < sizeof(valid) / sizeof(*valid); ++i) {
+ expect_value(_capture_glyph_dsc, codepoint, valid[i].codepoint);
+ UG_MeasureStringNoBreak(&width, NULL, valid[i].text);
+ assert_int_equal(width, 1);
+ }
+
+ const char* invalid[] = {
+ "\x80", // Stray continuation byte.
+ "\xbf",
+ "\xc0\xaf", // Overlong encodings.
+ "\xc1\xbf",
+ "\xe0\x80\xaf",
+ "\xf0\x80\x80\xaf",
+ "\xed\xa0\x80", // Surrogate.
+ "\xf4\x90\x80\x80", // Above U+10FFFF.
+ "\xf5\x80\x80\x80", // Invalid leading bytes.
+ "\xff",
+ "\xc2", // Truncated sequences.
+ "\xe4",
+ "\xe0\xa0",
+ "\xf0",
+ "\xf0\x90",
+ "\xf0\x90\x80",
+ "\xc2"
+ "A", // Invalid continuation bytes.
+ "\xe0\xa0"
+ "A",
+ "\xf0\x90\x80"
+ "A",
+ };
+ for (size_t i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i) {
+ expect_string(__wrap_Abort, msg, "Invalid UTF-8 string");
+ expect_assert_failure(UG_MeasureStringNoBreak(&width, NULL, invalid[i]));
+ }
+
+ // Reject malformed input after a valid prefix as well.
+ expect_value(_capture_glyph_dsc, codepoint, 'A');
+ expect_string(__wrap_Abort, msg, "Invalid UTF-8 string");
+ expect_assert_failure(UG_MeasureStringNoBreak(&width, NULL, "A\xff"));
+}
+
+static void _test_ugui_word_wrap_invalid_utf8(void** state)
+{
+ (void)state;
+ UG_Init(&gui, _set_pixel, &font_regular_9, 128, 64);
+ char output[32] = {0};
+
+ // Reject malformed input when measuring the first or a following word.
+ expect_string(__wrap_Abort, msg, "Invalid UTF-8 string");
+ expect_assert_failure(UG_WrapTitleString("\xff", output, 55));
+ expect_string(__wrap_Abort, msg, "Invalid UTF-8 string");
+ expect_assert_failure(UG_WrapTitleString("A \xff", output, 55));
+
+ // A tab ends the initial width scan, so copying detects this error.
+ expect_string(__wrap_Abort, msg, "Invalid UTF-8 string");
+ expect_assert_failure(UG_WrapTitleString("\t\xff", output, 55));
+}
+
+static void _test_ugui_lvgl_font(void** state)
+{
+ (void)state; /* unused */
+ UG_Init(&gui, _set_pixel, &font_regular_9, 128, 64);
+
+ UG_S16 width = 0;
+ UG_S16 height = 0;
+ UG_MeasureStringNoBreak(
+ &width,
+ &height,
+ "A"
+ "\xc3"
+ "\xa4");
+ assert_true(width > 0);
+ assert_int_equal(height, font_regular_9.line_height);
+
+ set_pixel_count = 0;
+ black_pixel_count = 0;
+ UG_PutString(0, 0, " ");
+ assert_true(set_pixel_count >= (size_t)font_regular_9.line_height);
+ assert_int_equal(set_pixel_count, black_pixel_count);
+}
+
+static void _test_ugui_lvgl_font_fallback(void** state)
+{
+ (void)state; /* unused */
+ UG_Init(&gui, _set_pixel, &font_password_12, 128, 64);
+
+ UG_U16 width = 0;
+ assert_true(UG_GetCharWidth(&font_password_12, ' ', &width));
+ assert_true(width > 0);
+ assert_true(UG_GetCharWidth(&font_password_12, 'A', &width));
+ assert_true(width > 0);
+
+ set_pixel_count = 0;
+ black_pixel_count = 0;
+ UG_PutString(0, 0, " ");
+ assert_true(set_pixel_count > black_pixel_count);
+
+ set_pixel_count = 0;
+ black_pixel_count = 0;
+ UG_PutString(0, 0, "A");
+ assert_true(set_pixel_count > black_pixel_count);
+}
+
+static void _test_ugui_fonts_use_supported_subset(void** state)
+{
+ (void)state; /* unused */
+ _assert_supported_font_subset(&font_regular_9);
+ _assert_supported_font_subset(&font_regular_11);
+ _assert_supported_font_subset(&font_regular_12);
+ _assert_supported_font_subset(&font_monogram_16);
+ _assert_supported_font_subset(&font_password_9);
+ _assert_supported_font_subset(&font_password_12);
+}
+
+static void _test_ugui_fonts_exclude_ambiguous_characters(void** state)
+{
+ (void)state;
+ const UG_FONT* fonts[] = {
+ &font_regular_9,
+ &font_regular_11,
+ &font_regular_12,
+ &font_monogram_16,
+ &font_password_9,
+ &font_password_12,
+ };
+ for (size_t i = 0; i < sizeof(fonts) / sizeof(*fonts); i++) {
+ UG_U16 width = 0;
+ assert_true(UG_GetCharWidth(fonts[i], ' ', &width));
+ assert_true(UG_GetCharWidth(fonts[i], '-', &width));
+ assert_false(UG_GetCharWidth(fonts[i], 0x00A0, &width)); // Non-breaking space.
+ assert_false(UG_GetCharWidth(fonts[i], 0x00AD, &width)); // Soft hyphen.
+ }
+}
+
+static uint8_t _glyph_pixels[32][32];
+
+static void _set_glyph_pixel(UG_S16 x, UG_S16 y, UG_COLOR color)
+{
+ assert_in_range(x, 0, 31);
+ assert_in_range(y, 0, 31);
+ _glyph_pixels[y][x] = color == C_WHITE;
+}
+
+static uint32_t _hash_bytes(uint32_t hash, const uint8_t* bytes, size_t len)
+{
+ for (size_t i = 0; i < len; i++) {
+ hash = (hash ^ bytes[i]) * 16777619u;
+ }
+ return hash;
+}
+
+static void _test_ugui_ascii_font_pixels_and_metrics(void** state)
+{
+ (void)state;
+ // Lock down printable ASCII glyph pixels, positions, advances and line heights.
+ const struct {
+ const UG_FONT* font;
+ uint32_t hash;
+ } cases[] = {
+ {&font_regular_9, 0xea2a3af8},
+ {&font_regular_11, 0x7a72fbc2},
+ {&font_regular_12, 0x3f5b6308},
+ {&font_password_9, 0x3e5071ab},
+ {&font_password_12, 0xf1db9eeb},
+ {&font_monogram_16, 0xd2698414},
+ };
+ for (size_t i = 0; i < sizeof(cases) / sizeof(*cases); i++) {
+ UG_Init(&gui, _set_glyph_pixel, cases[i].font, 32, 32);
+ UG_FontSetHSpace(0);
+ uint32_t hash = 2166136261u;
+ for (uint8_t codepoint = 32; codepoint <= 126; codepoint++) {
+ memset(_glyph_pixels, 0, sizeof(_glyph_pixels));
+ UG_PutChar((char)codepoint, 8, 8, C_WHITE, C_BLACK);
+ const char text[] = {(char)codepoint, '\0'};
+ UG_S16 width = 0;
+ UG_S16 height = 0;
+ UG_MeasureStringNoBreak(&width, &height, text);
+ const uint8_t metrics[] = {
+ (uint8_t)width, (uint8_t)(width >> 8), (uint8_t)height, (uint8_t)(height >> 8)};
+ hash = _hash_bytes(hash, metrics, sizeof(metrics));
+ hash = _hash_bytes(hash, (const uint8_t*)_glyph_pixels, sizeof(_glyph_pixels));
+ }
+ assert_int_equal(hash, cases[i].hash);
+ }
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(_test_ugui_word_wrap),
cmocka_unit_test(_test_ugui_render_rotated_180),
cmocka_unit_test(_test_ugui_measure_string_centered),
+ cmocka_unit_test(_test_ugui_utf8_validation),
+ cmocka_unit_test(_test_ugui_word_wrap_invalid_utf8),
+ cmocka_unit_test(_test_ugui_lvgl_font),
+ cmocka_unit_test(_test_ugui_lvgl_font_fallback),
+ cmocka_unit_test(_test_ugui_fonts_use_supported_subset),
+ cmocka_unit_test(_test_ugui_fonts_exclude_ambiguous_characters),
+ cmocka_unit_test(_test_ugui_ascii_font_pixels_and_metrics),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
### test/unit-test/test_ui_components.c
@@ -15,8 +15,7 @@
#include <ui/components/left_arrow.h>
#include <ui/components/right_arrow.h>
#include <ui/components/status.h>
-#include <ui/fonts/arial_fonts.h>
-#include <ui/fonts/monogram_5X9.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ugui/ugui.h>
#include <ui/ui_util.h>
@@ -35,7 +34,7 @@ static void _set_pixel(UG_S16 x, UG_S16 y, UG_COLOR color)
static int _setup(void** state)
{
(void)state;
- UG_Init(&gui, _set_pixel, &font_font_a_11X10, 128, 64);
+ UG_Init(&gui, _set_pixel, &font_regular_11, 128, 64);
return 0;
}
@@ -58,10 +57,10 @@ static void assert_ui_component_functions(component_t* component)
static void test_ui_components_label(void** state)
{
- assert_true(label_fits_width("Test", &font_font_a_11X10, 128));
- assert_true(label_fits_width("11111111111111111 BNB", &font_font_a_9X9, 128));
+ assert_true(label_fits_width("Test", &font_regular_11, 128));
+ assert_true(label_fits_width("11111111111111111 BNB", &font_regular_9, 128));
assert_false(
- label_fits_width("This label is much wider than the screen", &font_font_a_9X9, 128));
+ label_fits_width("This label is much wider than the screen", &font_regular_9, 128));
component_t* mock_component = fake_component_create();
@@ -132,7 +131,7 @@ static void test_ui_components_confirm(void** state)
const confirm_params_t params = {
.title = "Is the Code correct?",
.body = "CODE",
- .font = &font_monogram_5X9,
+ .font = &font_monogram_16,
};
component_t* confirm = confirm_create(¶ms, confirm_callback, NULL);
assert_non_null(confirm);
### test/unit-test/test_ui_util.c
@@ -6,7 +6,7 @@
#include <stddef.h>
#include <cmocka.h>
-#include <ui/fonts/arial_fonts.h>
+#include <ui/fonts/regular_fonts.h>
#include <ui/ui_util.h>
#include "fake_component.h"
@@ -213,7 +213,7 @@ static void test_ui_util_position_right_top(void** state)
static void test_ui_util_component_render_rotated_180(void** state)
{
(void)state;
- UG_Init(&gui, _set_pixel, &font_font_a_11X10, 128, 64);
+ UG_Init(&gui, _set_pixel, &font_regular_11, 128, 64);
component_t component = {
.f = &_pixel_component_functions,
.dimension = {.width = 10, .height = 8},
### test/unit-test/test_util.c
@@ -75,23 +75,12 @@ static void test_util_utf8_copy(void** state)
assert_string_equal(out, "");
}
-static void test_util_is_printable_ascii(void** state)
-{
- (void)state;
-
- assert_true(util_is_printable_ascii("printable ASCII", false));
- assert_false(util_is_printable_ascii("line one\nline two", false));
- assert_true(util_is_printable_ascii("line one\nline two", true));
- assert_false(util_is_printable_ascii("t\xC3\xA4st", true));
-}
-
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_minmax),
cmocka_unit_test(test_util_strlcpy),
cmocka_unit_test(test_util_utf8_copy),
- cmocka_unit_test(test_util_is_printable_ascii),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.