diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 1733dd505..146068e50 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -2,6 +2,12 @@ # SPDX-FileCopyrightText: 2021 Foundation Devices, Inc. # SPDX-License-Identifier: GPL-3.0-or-later +branch=`git symbolic-ref HEAD` +if [ "$branch" = "refs/heads/main" ] || [[ "$branch" == refs/heads/dev-v* ]]; then + echo "Direct commits to the main and dev branches are not allowed." + exit 1 +fi + RESULTS=$(find . -name '*.py' -exec grep -H fake_it[\ ]*=[\ ]*True {} +) LEN=`expr length "$RESULTS"` echo $RESULTS diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 598f43dd7..9f9d0147f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -40,7 +40,6 @@ Then run the following commands: rustup target add aarch64-unknown-none rustup target add thumbv7em-none-eabihf - rustup target add x86_64-unknown-none cargo install cbindgen #### Cross-Compiler Toolchain @@ -161,5 +160,9 @@ To build the bootloader for a reproducibility check, go to the repo root folder: Then run one of the following commands to build the corresponding bootloader: - just build color - just build mono + just build-bootloader color + just build-bootloader mono + +Please note that building the mono bootloader is not yet supported in this repository. If you need to build it, please follow the instructions at: + +https://github.com/Foundation-Devices/passport-firmware diff --git a/Dockerfile b/Dockerfile index c289a41a1..f73b07c33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,9 +40,7 @@ ENV PATH="/cargo/bin:${PATH}" # Finish installation of Rust toolchain. RUN rustup component add clippy && \ rustup component add rustfmt && \ - rustup target add aarch64-unknown-none && \ - rustup target add thumbv7em-none-eabihf && \ - rustup target add x86_64-unknown-none + rustup target add thumbv7em-none-eabihf # Install binaries using cargo. RUN cargo install cbindgen@^0.24 && \ diff --git a/extmod/foundation-rust/Cargo.lock b/extmod/foundation-rust/Cargo.lock index 6febb1ac9..88a7e55f1 100644 --- a/extmod/foundation-rust/Cargo.lock +++ b/extmod/foundation-rust/Cargo.lock @@ -17,18 +17,58 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "bitcoin_hashes" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "critical-section", + "embedded-hal", + "volatile-register", +] + [[package]] name = "crc" version = "3.0.1" @@ -56,17 +96,44 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + [[package]] name = "foundation" version = "0.1.0" dependencies = [ + "cortex-m", + "critical-section", "heapless", "minicbor", + "once_cell", + "rand", + "rand_core", + "secp256k1", "ur", "ur-foundation", "uuid", ] +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hash32" version = "0.3.1" @@ -83,7 +150,7 @@ source = "git+https://github.com/japaric/heapless#644653bf3b831c6bb4963be2de2480 dependencies = [ "atomic-polyfill", "hash32", - "rustc_version", + "rustc_version 0.4.0", "spin", "stable_deref_trait", ] @@ -103,6 +170,12 @@ dependencies = [ "either", ] +[[package]] +name = "libc" +version = "0.2.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" + [[package]] name = "lock_api" version = "0.4.9" @@ -133,6 +206,31 @@ dependencies = [ "syn", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +dependencies = [ + "atomic-polyfill", + "critical-section", +] + [[package]] name = "phf" version = "0.11.1" @@ -175,20 +273,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50686e0021c4136d1d453b2dfe059902278681512a34d4248435dc34b6b5c8ec" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -199,6 +303,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -207,6 +323,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "rand_xoshiro" @@ -217,13 +336,22 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.17", ] [[package]] @@ -232,12 +360,46 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "rand", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "siphasher" version = "0.3.10" @@ -246,9 +408,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "spin" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] @@ -305,6 +467,33 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.0" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/extmod/foundation-rust/Cargo.toml b/extmod/foundation-rust/Cargo.toml index 04029a556..1a2d95eb7 100644 --- a/extmod/foundation-rust/Cargo.toml +++ b/extmod/foundation-rust/Cargo.toml @@ -34,9 +34,38 @@ git = "https://github.com/Foundation-Devices/rust-ur-foundation" branch = "dev-v0.1.0" default-features = false +[target.'cfg(target_arch = "arm")'.dependencies.cortex-m] +version = "0.7" +features = ["cm7", "critical-section-single-core"] + +[dependencies.critical-section] +version = "1" + +[dependencies.once_cell] +version = "1" +default-features = false +features = ["critical-section"] + +[dependencies.secp256k1] +version = "0.27" +default-features = false +features = ["rand"] + +[dependencies.rand] +version = "0.8.5" +default-features = false + +[target.'cfg(not(target_arch = "arm"))'.dependencies.rand] +version = "0.8.5" +features = ["std", "std_rng"] + +[dependencies.rand_core] +version = "0.6.4" +default-features = false + [features] default = [] -std = [] +std = ["rand/std", "critical-section/std"] [lib] crate-type = ["lib", "staticlib"] @@ -46,3 +75,4 @@ lto = "fat" opt-level = "z" codegen-units = 1 strip = true +panic = "abort" diff --git a/extmod/foundation-rust/include/foundation.h b/extmod/foundation-rust/include/foundation.h index 0aebac4aa..0a88e3b40 100644 --- a/extmod/foundation-rust/include/foundation.h +++ b/extmod/foundation-rust/include/foundation.h @@ -365,6 +365,17 @@ extern UR_Decoder UR_DECODER; extern UR_Encoder UR_ENCODER; +/** + * Computes a Schnorr signature over the message `data`. + * + * - `data` is the message hash. + * - `secret_key` is the secret key used to sign the message. + * - `signature` is the output of the resulting signature. + */ +void foundation_secp256k1_schnorr_sign(const uint8_t (*data)[32], + const uint8_t (*secret_key)[32], + uint8_t (*signature)[64]); + /** * Receive a Uniform Resource part. * @@ -375,7 +386,8 @@ extern UR_Encoder UR_ENCODER; bool ur_decoder_receive(UR_Decoder *decoder, const uint8_t *ur, size_t ur_len, - UR_Error *error); + UR_Error *error, + uint32_t *num_frames); /** * Returns `true` if the decoder is complete and no more data is needed. diff --git a/extmod/foundation-rust/src/lib.rs b/extmod/foundation-rust/src/lib.rs index 837851b78..c6b3751a7 100644 --- a/extmod/foundation-rust/src/lib.rs +++ b/extmod/foundation-rust/src/lib.rs @@ -1,17 +1,24 @@ // SPDX-FileCopyrightText: 2023 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later -#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(target_arch = "arm", no_std)] #![allow(non_camel_case_types)] +#[cfg(target_arch = "arm")] +use cortex_m as _; + +pub mod secp256k1; pub mod ur; /// cbindgen:ignore -#[cfg(not(feature = "std"))] +#[cfg(all(target_os = "none", target_arch = "arm"))] +mod rand; +/// cbindgen:ignore +#[cfg(target_os = "none")] mod stdout; +#[cfg(target_os = "none")] #[panic_handler] -#[cfg(all(not(feature = "std"), not(test)))] fn panic_handler(info: &core::panic::PanicInfo) -> ! { use core::fmt::Write; diff --git a/extmod/foundation-rust/src/rand.rs b/extmod/foundation-rust/src/rand.rs new file mode 100644 index 000000000..1aa0fa07d --- /dev/null +++ b/extmod/foundation-rust/src/rand.rs @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +//! Interface to Passport random number generator. + +use core::{ffi::c_void, num::NonZeroU32}; + +use rand::{CryptoRng, Error, RngCore}; + +const ERROR_CODE_FATAL: u32 = 1; + +/// Passport cryptographically secure random number generator. +/// +/// Uses the board's avalanche noise source, the MCU RNG and the +/// hardware RNG. +#[derive(Debug, Clone, Copy)] +pub struct PassportRng; + +impl RngCore for PassportRng { + fn next_u32(&mut self) -> u32 { + rand_core::impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + rand_core::impls::next_u64_via_fill(self) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest).expect("fatal Passport RNG error"); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + const MIN_LEN: usize = 4; + + // 4 bytes at least are required to fill. + let mut tmp = [0; 4]; + let (buf, buf_len) = if dest.len() < MIN_LEN { + (tmp.as_mut_ptr() as *mut c_void, tmp.len()) + } else { + (dest.as_mut_ptr() as *mut c_void, dest.len()) + }; + + unsafe { noise_enable() }; + let succeed = + unsafe { noise_get_random_bytes(NOISE_ALL, buf, buf_len) }; + if !succeed { + unsafe { noise_disable() }; + return Err(Error::from( + NonZeroU32::new(ERROR_CODE_FATAL).unwrap(), + )); + } + unsafe { noise_disable() }; + + if dest.len() < MIN_LEN { + dest.copy_from_slice(&tmp[..dest.len()]); + } + + Ok(()) + } +} + +impl CryptoRng for PassportRng {} + +const NOISE_AVALANCHE_SOURCE: u8 = 1 << 0; +const NOISE_MCU_RNG_SOURCE: u8 = 1 << 1; +const NOISE_SE_RNG_SOURCE: u8 = 1 << 2; +const NOISE_ALL: u8 = + NOISE_AVALANCHE_SOURCE | NOISE_MCU_RNG_SOURCE | NOISE_SE_RNG_SOURCE; + +extern "C" { + fn noise_enable(); + fn noise_disable(); + fn noise_get_random_bytes( + sources: u8, + buf: *mut c_void, + buf_len: usize, + ) -> bool; +} diff --git a/extmod/foundation-rust/src/secp256k1.rs b/extmod/foundation-rust/src/secp256k1.rs new file mode 100644 index 000000000..d77f14bd9 --- /dev/null +++ b/extmod/foundation-rust/src/secp256k1.rs @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +use once_cell::sync::Lazy; +use secp256k1::{ + ffi::types::AlignedType, AllPreallocated, KeyPair, Message, Secp256k1, +}; + +/// cbindgen:ignore +static mut PRE_ALLOCATED_CTX_BUF: [AlignedType; 20] = [AlignedType::ZERO; 20]; + +/// cbindgen:ignore +static PRE_ALLOCATED_CTX: Lazy>> = + Lazy::new(|| { + let buf = unsafe { &mut PRE_ALLOCATED_CTX_BUF }; + Secp256k1::preallocated_new(buf) + .expect("the pre-allocated context buf should have enough space") + }); + +/// Computes a Schnorr signature over the message `data`. +/// +/// - `data` is the message hash. +/// - `secret_key` is the secret key used to sign the message. +/// - `signature` is the output of the resulting signature. +#[export_name = "foundation_secp256k1_schnorr_sign"] +pub extern "C" fn secp256k1_sign_schnorr( + data: &[u8; 32], + secret_key: &[u8; 32], + signature: &mut [u8; 64], +) { + let keypair = KeyPair::from_seckey_slice(&PRE_ALLOCATED_CTX, secret_key) + .expect("invalid secret key"); + + let msg = Message::from_slice(data).unwrap(); + let sig = + PRE_ALLOCATED_CTX.sign_schnorr_with_rng(&msg, &keypair, &mut rng()); + signature.copy_from_slice(sig.as_ref()); +} + +#[cfg(target_arch = "arm")] +fn rng() -> crate::rand::PassportRng { + crate::rand::PassportRng +} + +#[cfg(not(target_arch = "arm"))] +fn rng() -> rand::rngs::ThreadRng { + rand::thread_rng() +} diff --git a/extmod/foundation-rust/src/ur/decoder.rs b/extmod/foundation-rust/src/ur/decoder.rs index a68e32fae..d2871bbfe 100644 --- a/extmod/foundation-rust/src/ur/decoder.rs +++ b/extmod/foundation-rust/src/ur/decoder.rs @@ -83,6 +83,7 @@ pub unsafe extern "C" fn ur_decoder_receive( ur: *const u8, ur_len: usize, error: &mut UR_Error, + num_frames: &mut u32, ) -> bool { // SAFETY: ur and ur_len are assumed to be valid. let ur = unsafe { slice::from_raw_parts(ur, ur_len) }; @@ -109,6 +110,8 @@ pub unsafe extern "C" fn ur_decoder_receive( } }; + *num_frames = ur.sequence_count().unwrap_or(0); + let result = decoder.inner.receive(ur).map_err(|e| match e { Error::NotMultiPart => unsafe { UR_Error::new(&e, super::UR_ErrorKind::UR_ERROR_KIND_NOT_MULTI_PART) diff --git a/extmod/foundation/modfoundation-secp56k1.h b/extmod/foundation/modfoundation-secp56k1.h new file mode 100644 index 000000000..2ca47cf97 --- /dev/null +++ b/extmod/foundation/modfoundation-secp56k1.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "foundation.h" + +/// def sign_schnorr(data, secret_key) -> bytes: +/// """ +/// """ +STATIC mp_obj_t mod_foundation_secp256k1_sign_schnorr(mp_obj_t data_obj, + mp_obj_t secret_key_obj) +{ + mp_buffer_info_t data; + mp_buffer_info_t secret_key; + uint8_t signature[64]; + + mp_get_buffer_raise(data_obj, &data, MP_BUFFER_READ); + mp_get_buffer_raise(secret_key_obj, &secret_key, MP_BUFFER_READ); + + if (data.len != 32) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("data should be 32 bytes")); + } + + if (secret_key.len != 32) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("secret key should be 32 bytes")); + } + + foundation_secp256k1_schnorr_sign(data.buf, + secret_key.buf, + &signature); + + return mp_obj_new_bytes(signature, sizeof(signature)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_foundation_secp256k1_sign_schnorr_obj, + mod_foundation_secp256k1_sign_schnorr); + +STATIC const mp_rom_map_elem_t mod_foundation_secp256k1_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_schnorr_sign), MP_ROM_PTR(&mod_foundation_secp256k1_sign_schnorr_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_foundation_secp256k1_globals, mod_foundation_secp256k1_globals_table); + +STATIC const mp_obj_module_t mod_foundation_secp256k1_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_foundation_secp256k1_globals, +}; diff --git a/extmod/foundation/modfoundation-ur.h b/extmod/foundation/modfoundation-ur.h index 1402f0270..8187006d1 100644 --- a/extmod/foundation/modfoundation-ur.h +++ b/extmod/foundation/modfoundation-ur.h @@ -555,12 +555,14 @@ STATIC mp_obj_t mod_foundation_ur_decoder_receive(mp_obj_t ur_obj) mp_check_self(mp_obj_is_str(ur_obj)); GET_STR_DATA_LEN(ur_obj, ur, ur_len); + + uint32_t num_frames = 0; - if (!ur_decoder_receive(&UR_DECODER, ur, ur_len, &error)) { + if (!ur_decoder_receive(&UR_DECODER, ur, ur_len, &error, &num_frames)) { mod_foundation_ur_raise(&error); } - return mp_const_none; + return mp_obj_new_int(num_frames); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_foundation_ur_decoder_receive_obj, mod_foundation_ur_decoder_receive); diff --git a/extmod/foundation/modfoundation.c b/extmod/foundation/modfoundation.c index af2f4c918..def4218b7 100644 --- a/extmod/foundation/modfoundation.c +++ b/extmod/foundation/modfoundation.c @@ -26,6 +26,7 @@ #include "modfoundation-bip39.h" #include "modfoundation-qr.h" +#include "modfoundation-secp56k1.h" #include "modfoundation-ur.h" /// package: foundation @@ -55,7 +56,7 @@ STATIC mp_obj_t mod_foundation_convert_rgb565_to_grayscale(size_t n_args, const mp_raise_ValueError(MP_ERROR_TEXT("invalid rgb565 buffer size")); return mp_const_none; } - if (grayscale_info.len != (hor_res * ver_res)) + if (grayscale_info.len != (size_t)(hor_res * ver_res)) { mp_raise_ValueError(MP_ERROR_TEXT("invalid grayscale buffer size")); return mp_const_none; @@ -273,6 +274,7 @@ STATIC const mp_rom_map_elem_t foundation_module_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_FixedBytesIO), MP_ROM_PTR(&mp_type_fixedbytesio)}, {MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_foundation_bip39_module)}, {MP_ROM_QSTR(MP_QSTR_qr), MP_ROM_PTR(&mod_foundation_qr_module)}, + {MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_foundation_secp256k1_module)}, {MP_ROM_QSTR(MP_QSTR_ur), MP_ROM_PTR(&mod_foundation_ur_module)}, {MP_ROM_QSTR(MP_QSTR_convert_rgb565_to_grayscale), MP_ROM_PTR(&mod_foundation_convert_rgb565_to_grayscale_obj)}, {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_foundation_sha256_obj)}, diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h index 2b96caf3d..288ebe3d0 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h @@ -30,8 +30,6 @@ #include "nem.h" #endif -#define FOUNDATION_ADDITIONS - /// package: trezorcrypto.bip32 /// class HDNode: diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h index 30b84a2ae..4428b1efd 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h @@ -158,6 +158,19 @@ STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t word) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_find_word_obj, mod_trezorcrypto_bip39_find_word); +// Returns BIP39 English word of the given index +STATIC mp_obj_t mod_trezorcrypto_bip39_get_word(mp_obj_t index_obj) { + int index = mp_obj_int_get_checked(index_obj); + const char * word = mnemonic_get_word(index); + if (word) { + return mp_obj_new_str(word, strlen(word)); + } else { + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_get_word_obj, + mod_trezorcrypto_bip39_get_word); + STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip39)}, {MP_ROM_QSTR(MP_QSTR_complete_word), @@ -171,6 +184,7 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj)}, {MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj)}, {MP_ROM_QSTR(MP_QSTR_find_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_get_word_obj)}, }; STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip39_globals, mod_trezorcrypto_bip39_globals_table); diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h new file mode 100644 index 000000000..1698fa452 --- /dev/null +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h @@ -0,0 +1,65 @@ +/* + * This file is part of the TREZOR project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" + +#include "schnorr.h" +#include "secp256k1.h" + +/// package: trezorcrypto.schnorr + +/// def sign(pk: bytes, digest: bytes) -> bytes: +/// """ +/// Schnorr signatures +/// """ +STATIC mp_obj_t mod_trezorcrypto_schnorr_sign(mp_obj_t pk_obj, mp_obj_t digest_obj) { + mp_buffer_info_t pk, digest; + mp_get_buffer_raise(pk_obj, &pk, MP_BUFFER_READ); + mp_get_buffer_raise(digest_obj, &digest, MP_BUFFER_READ); + + vstr_t signature = {0}; + vstr_init_len(&signature, SCHNORR_SIG_LENGTH); + + int rv = schnorr_sign_digest(&secp256k1, pk.buf, digest.buf, (uint8_t *)signature.buf); + if (rv != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("schnorr signature failed")); + } + + return mp_obj_new_str_from_vstr(&mp_type_bytes, &signature); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2( + mod_trezorcrypto_schnorr_sign_obj, + mod_trezorcrypto_schnorr_sign); + +STATIC const mp_rom_map_elem_t mod_trezorcrypto_schnorr_globals_table[] = { + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_schnorr)}, + {MP_ROM_QSTR(MP_QSTR_sign), + MP_ROM_PTR(&mod_trezorcrypto_schnorr_sign_obj)}, +}; +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_schnorr_globals, + mod_trezorcrypto_schnorr_globals_table); + +STATIC const mp_obj_module_t mod_trezorcrypto_schnorr_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_schnorr_globals, +}; diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 6b07ada05..9f16b0924 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -34,6 +34,8 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { } } +#define FOUNDATION_ADDITIONS + #include "modtrezorcrypto-aes.h" #include "modtrezorcrypto-bip32.h" #include "modtrezorcrypto-bip340.h" @@ -44,7 +46,9 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-chacha20poly1305.h" #include "modtrezorcrypto-crc.h" #include "modtrezorcrypto-curve25519.h" +#if USE_KECCAK #include "modtrezorcrypto-ed25519.h" +#endif #include "modtrezorcrypto-groestl.h" #include "modtrezorcrypto-hmac.h" #include "modtrezorcrypto-nist256p1.h" @@ -52,12 +56,17 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-random.h" #include "modtrezorcrypto-ripemd160.h" #include "modtrezorcrypto-secp256k1.h" +#include "modtrezorcrypto-schnorr.h" #include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha256.h" +#if USE_KECCAK #include "modtrezorcrypto-sha3-256.h" #include "modtrezorcrypto-sha3-512.h" +#endif #include "modtrezorcrypto-sha512.h" +#ifndef FOUNDATION_ADDITIONS #include "modtrezorcrypto-shamir.h" +#endif #include "modtrezorcrypto-slip39.h" #if !BITCOIN_ONLY #include "modtrezorcrypto-cardano.h" @@ -70,6 +79,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&mod_trezorcrypto_AES_type)}, {MP_ROM_QSTR(MP_QSTR_bip32), MP_ROM_PTR(&mod_trezorcrypto_bip32_module)}, {MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_trezorcrypto_bip39_module)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_blake256), MP_ROM_PTR(&mod_trezorcrypto_Blake256_type)}, {MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type)}, @@ -83,8 +93,10 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module)}, {MP_ROM_QSTR(MP_QSTR_curve25519), MP_ROM_PTR(&mod_trezorcrypto_curve25519_module)}, +#if USE_KECCAK {MP_ROM_QSTR(MP_QSTR_ed25519), MP_ROM_PTR(&mod_trezorcrypto_ed25519_module)}, +#endif #if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module)}, #endif @@ -92,26 +104,37 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module)}, {MP_ROM_QSTR(MP_QSTR_groestl512), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_hmac), MP_ROM_PTR(&mod_trezorcrypto_Hmac_type)}, +#ifndef FOUNDATION_ADDITIONS #if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)}, #endif {MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module)}, {MP_ROM_QSTR(MP_QSTR_ripemd160), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type)}, {MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_bip340), MP_ROM_PTR(&mod_trezorcrypto_bip340_module)}, {MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type)}, +#endif // FOUNDATION_ADDITIONS +#if USE_KECCAK {MP_ROM_QSTR(MP_QSTR_sha3_256), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type)}, {MP_ROM_QSTR(MP_QSTR_sha3_512), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_type)}, +#endif +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_shamir), MP_ROM_PTR(&mod_trezorcrypto_shamir_module)}, {MP_ROM_QSTR(MP_QSTR_slip39), MP_ROM_PTR(&mod_trezorcrypto_slip39_module)}, +#endif // FOUNDATION_ADDITIONS }; STATIC MP_DEFINE_CONST_DICT(mp_module_trezorcrypto_globals, mp_module_trezorcrypto_globals_table); @@ -127,13 +150,13 @@ MP_REGISTER_MODULE(MP_QSTR_trezorcrypto, mp_module_trezorcrypto, #ifdef USE_SECP256K1_ZKP void secp256k1_default_illegal_callback_fn(const char *str, void *data) { (void)data; - mp_raise_ValueError(str); + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), str); return; } void secp256k1_default_error_callback_fn(const char *str, void *data) { (void)data; - __fatal_error(NULL, str, __FILE__, __LINE__, __func__); + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), str); return; } #endif diff --git a/extmod/trezor-firmware/crypto/bip32.c b/extmod/trezor-firmware/crypto/bip32.c index 7811d66a4..d6d99eeb0 100644 --- a/extmod/trezor-firmware/crypto/bip32.c +++ b/extmod/trezor-firmware/crypto/bip32.c @@ -475,10 +475,8 @@ int hdnode_fill_public_key(HDNode *node) { ed25519_publickey(node->private_key, node->public_key + 1); } else if (node->curve == &ed25519_sha3_info) { ed25519_publickey_sha3(node->private_key, node->public_key + 1); -#if USE_KECCAK } else if (node->curve == &ed25519_keccak_info) { ed25519_publickey_keccak(node->private_key, node->public_key + 1); -#endif } else if (node->curve == &curve25519_info) { curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key); #if USE_CARDANO @@ -793,9 +791,11 @@ const curve_info *get_curve_by_name(const char *curve_name) { if (strcmp(curve_name, SECP256K1_GROESTL_NAME) == 0) { return &secp256k1_groestl_info; } +#if USE_KECCAK if (strcmp(curve_name, SECP256K1_SMART_NAME) == 0) { return &secp256k1_smart_info; } +#endif if (strcmp(curve_name, NIST256P1_NAME) == 0) { return &nist256p1_info; } diff --git a/extmod/trezor-firmware/crypto/secp256k1.c b/extmod/trezor-firmware/crypto/secp256k1.c index 34ccaaacb..38c3fc0e2 100644 --- a/extmod/trezor-firmware/crypto/secp256k1.c +++ b/extmod/trezor-firmware/crypto/secp256k1.c @@ -84,6 +84,7 @@ const curve_info secp256k1_groestl_info = { .hasher_script = HASHER_SHA2, }; +#if USE_KECCAK const curve_info secp256k1_smart_info = { .bip32_name = "Bitcoin seed", .params = &secp256k1, @@ -92,3 +93,4 @@ const curve_info secp256k1_smart_info = { .hasher_pubkey = HASHER_SHA2_RIPEMD, .hasher_script = HASHER_SHA2, }; +#endif diff --git a/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c b/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c index d901968c6..51460667f 100644 --- a/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c +++ b/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c @@ -122,7 +122,7 @@ lv_res_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len, int32_t remain = res % qr_size; /* The qr version is incremented by four point */ - uint32_t version_extend = remain / (scale << 2); + int32_t version_extend = remain / (scale << 2); if(version_extend && qr_version < qrcodegen_VERSION_MAX) { qr_version = qr_version + version_extend > qrcode->max_version ? qrcode->max_version : qr_version + version_extend; diff --git a/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c b/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c index 2b0dccf92..d2a7c8708 100644 --- a/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c +++ b/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c @@ -1,17 +1,17 @@ /******************************************************************************* * Size: 16 px - * Bpp: 4 - * Opts: --no-compress --no-prefilter --bpp 4 --size 16 --font Montserrat-Medium.ttf -r 0x20-0x7F,0xB0,0x2022 --font FontAwesome5-Solid+Brands+Regular.woff -r 61441,61448,61451,61452,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl -o lv_font_montserrat_16.c --force-fast-kern-format + * Bpp: 2 + * Opts: ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE - #include "lvgl.h" +#include "lvgl.h" #else - #include "../../lvgl.h" +#include "lvgl/lvgl.h" #endif #ifndef LV_FONT_MONTSERRAT_16 - #define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_16 1 #endif #if LV_FONT_MONTSERRAT_16 @@ -25,1758 +25,522 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { /* U+0020 " " */ /* U+0021 "!" */ - 0xbf, 0xb, 0xf0, 0xaf, 0xa, 0xe0, 0x9e, 0x8, - 0xd0, 0x8c, 0x7, 0xc0, 0x0, 0x0, 0x10, 0xbf, - 0x1a, 0xe0, + 0xb2, 0xcb, 0x2c, 0xb2, 0xcb, 0x1c, 0x0, 0xb, + 0x2c, /* U+0022 "\"" */ - 0xf5, 0x1f, 0x3f, 0x51, 0xf3, 0xe4, 0xf, 0x3e, - 0x40, 0xf2, 0x72, 0x8, 0x10, + 0xd3, 0x34, 0xcd, 0x33, 0x4c, 0x42, 0x0, /* U+0023 "#" */ - 0x0, 0x5, 0xc0, 0x3, 0xe0, 0x0, 0x0, 0x7a, - 0x0, 0x5c, 0x0, 0x0, 0x9, 0x80, 0x7, 0xa0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3, 0x3e, - 0x73, 0x3c, 0x83, 0x30, 0x0, 0xf2, 0x0, 0xc5, - 0x0, 0x0, 0xf, 0x10, 0xe, 0x30, 0x0, 0x2, - 0xf0, 0x0, 0xf2, 0x0, 0x9f, 0xff, 0xff, 0xff, - 0xff, 0x41, 0x38, 0xc3, 0x36, 0xe3, 0x30, 0x0, - 0x89, 0x0, 0x5c, 0x0, 0x0, 0xa, 0x70, 0x7, - 0xa0, 0x0, + 0x1, 0xc0, 0xc0, 0x6, 0x7, 0x0, 0x28, 0x18, + 0xf, 0xff, 0xff, 0x3, 0x43, 0x80, 0xc, 0xd, + 0x0, 0x30, 0x30, 0x0, 0xc0, 0xc0, 0xbf, 0xff, + 0xf4, 0x2c, 0x1c, 0x0, 0xa0, 0x70, 0x2, 0x41, + 0x80, /* U+0024 "$" */ - 0x0, 0x0, 0x79, 0x0, 0x0, 0x0, 0x0, 0x79, - 0x0, 0x0, 0x0, 0x5c, 0xff, 0xe9, 0x20, 0x6, - 0xfc, 0xbc, 0x9e, 0x90, 0xe, 0xb0, 0x79, 0x0, - 0x10, 0xf, 0x80, 0x79, 0x0, 0x0, 0xd, 0xf5, - 0x79, 0x0, 0x0, 0x3, 0xef, 0xfd, 0x50, 0x0, - 0x0, 0x6, 0xcf, 0xfe, 0x40, 0x0, 0x0, 0x79, - 0x5e, 0xf1, 0x0, 0x0, 0x79, 0x5, 0xf3, 0x7, - 0x0, 0x79, 0x7, 0xf1, 0x2f, 0xe9, 0xbc, 0xaf, - 0xa0, 0x3, 0xae, 0xff, 0xd7, 0x0, 0x0, 0x0, - 0x79, 0x0, 0x0, 0x0, 0x0, 0x79, 0x0, 0x0, + 0x0, 0x60, 0x0, 0x6, 0x0, 0x7, 0xfe, 0x1, + 0xfb, 0xb8, 0x38, 0x60, 0x3, 0x86, 0x0, 0x3d, + 0x60, 0x0, 0xff, 0x40, 0x1, 0xff, 0x40, 0x6, + 0x7c, 0x0, 0x61, 0xc1, 0x6, 0x1c, 0x3e, 0xbb, + 0x80, 0xbf, 0xd0, 0x0, 0x60, 0x0, 0x6, 0x0, /* U+0025 "%" */ - 0x3, 0xde, 0x80, 0x0, 0x5, 0xd0, 0x0, 0xe4, - 0xc, 0x50, 0x1, 0xe3, 0x0, 0x4c, 0x0, 0x5a, - 0x0, 0xa9, 0x0, 0x6, 0xa0, 0x4, 0xc0, 0x4e, - 0x0, 0x0, 0x4c, 0x0, 0x5a, 0xd, 0x50, 0x0, - 0x0, 0xe4, 0x1c, 0x58, 0xa0, 0x0, 0x0, 0x3, - 0xce, 0x73, 0xe1, 0x3c, 0xe9, 0x0, 0x0, 0x0, - 0xd6, 0xe, 0x40, 0xa8, 0x0, 0x0, 0x7c, 0x3, - 0xc0, 0x3, 0xd0, 0x0, 0x2e, 0x20, 0x3c, 0x0, - 0x3d, 0x0, 0xb, 0x70, 0x0, 0xe2, 0x9, 0x80, - 0x6, 0xd0, 0x0, 0x4, 0xdd, 0xa0, + 0xf, 0x80, 0x1c, 0xd, 0x34, 0xc, 0x7, 0x6, + 0xa, 0x1, 0x81, 0xc7, 0x0, 0x70, 0x63, 0x40, + 0xd, 0x36, 0x80, 0x0, 0xf4, 0xc3, 0xe0, 0x0, + 0xd3, 0x4a, 0x0, 0x70, 0xc0, 0xc0, 0x30, 0x30, + 0x30, 0x24, 0xc, 0x28, 0x1c, 0x1, 0xf8, /* U+0026 "&" */ - 0x0, 0x9, 0xef, 0xb1, 0x0, 0x0, 0x9, 0xe4, - 0x3c, 0xa0, 0x0, 0x0, 0xd9, 0x0, 0x7d, 0x0, - 0x0, 0xc, 0xc0, 0x1c, 0xa0, 0x0, 0x0, 0x3f, - 0xae, 0xc1, 0x0, 0x0, 0x1, 0xdf, 0xc0, 0x0, - 0x0, 0x3, 0xeb, 0x8f, 0x70, 0x18, 0x0, 0xdb, - 0x0, 0x7f, 0x65, 0xf0, 0x3f, 0x40, 0x0, 0x8f, - 0xea, 0x3, 0xf7, 0x0, 0x0, 0xcf, 0x70, 0xb, - 0xf9, 0x66, 0xcf, 0xbf, 0x40, 0x8, 0xdf, 0xea, - 0x30, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0xf8, 0x0, 0x2d, 0x38, 0x0, 0xe0, 0x70, + 0x3, 0xc3, 0x80, 0x3, 0xbc, 0x0, 0xf, 0xc0, + 0x0, 0xeb, 0x42, 0xe, 0x7, 0x5c, 0x34, 0xb, + 0xe0, 0xd0, 0xf, 0x42, 0xe5, 0xfb, 0x42, 0xfe, + 0x9, 0x0, 0x0, 0x0, /* U+0027 "'" */ - 0xf5, 0xf5, 0xe4, 0xe4, 0x72, + 0xdd, 0xdd, 0x40, /* U+0028 "(" */ - 0x0, 0xda, 0x5, 0xf2, 0xb, 0xc0, 0xf, 0x70, - 0x3f, 0x40, 0x5f, 0x20, 0x6f, 0x10, 0x7f, 0x0, - 0x6f, 0x10, 0x5f, 0x20, 0x3f, 0x40, 0xf, 0x70, - 0xb, 0xc0, 0x5, 0xf2, 0x0, 0xda, + 0xe, 0x1c, 0x2c, 0x34, 0x34, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x34, 0x34, 0x2c, 0x1c, 0xe, /* U+0029 ")" */ - 0x3f, 0x30, 0xc, 0xb0, 0x6, 0xf1, 0x1, 0xf6, - 0x0, 0xe9, 0x0, 0xbc, 0x0, 0xad, 0x0, 0xae, - 0x0, 0xad, 0x0, 0xbc, 0x0, 0xe9, 0x1, 0xf6, - 0x6, 0xf1, 0xc, 0xb0, 0x3f, 0x30, + 0x30, 0x38, 0x1c, 0xd, 0xe, 0xb, 0xb, 0xb, + 0xb, 0xb, 0xe, 0xd, 0x1c, 0x38, 0x30, /* U+002A "*" */ - 0x0, 0x4a, 0x0, 0x6, 0x74, 0xa4, 0xa0, 0x2b, - 0xff, 0xe5, 0x0, 0x7f, 0xfb, 0x20, 0x7b, 0x6b, - 0x8d, 0x0, 0x4, 0xa0, 0x0, 0x0, 0x13, 0x0, - 0x0, + 0x6, 0x1, 0x59, 0x82, 0xfd, 0x7, 0xe0, 0x66, + 0xb0, 0x18, 0x0, 0x0, 0x0, /* U+002B "+" */ - 0x0, 0x5, 0x10, 0x0, 0x0, 0xf, 0x50, 0x0, - 0x0, 0xf, 0x50, 0x0, 0x1, 0x1f, 0x51, 0x10, - 0xef, 0xff, 0xff, 0xf3, 0x34, 0x4f, 0x74, 0x40, - 0x0, 0xf, 0x50, 0x0, 0x0, 0xf, 0x50, 0x0, + 0x1, 0x0, 0x3, 0x40, 0x3, 0x40, 0x3, 0x40, + 0xff, 0xfc, 0x17, 0x54, 0x3, 0x40, 0x3, 0x40, /* U+002C "," */ - 0x9, 0x52, 0xfd, 0xb, 0xa0, 0xc5, 0xf, 0x0, + 0x24, 0xf2, 0x8d, 0x30, /* U+002D "-" */ - 0x1, 0x11, 0x10, 0x1f, 0xff, 0xf3, 0x4, 0x44, - 0x40, + 0x0, 0x3, 0xfc, 0x15, 0x40, /* U+002E "." */ - 0x3, 0x12, 0xfc, 0x1e, 0x90, + 0x0, 0xf3, 0x80, /* U+002F "/" */ - 0x0, 0x0, 0x5, 0xf1, 0x0, 0x0, 0xa, 0xb0, - 0x0, 0x0, 0xf, 0x60, 0x0, 0x0, 0x5f, 0x10, - 0x0, 0x0, 0xab, 0x0, 0x0, 0x0, 0xf6, 0x0, - 0x0, 0x5, 0xf1, 0x0, 0x0, 0xa, 0xb0, 0x0, - 0x0, 0xf, 0x60, 0x0, 0x0, 0x4f, 0x10, 0x0, - 0x0, 0xac, 0x0, 0x0, 0x0, 0xf6, 0x0, 0x0, - 0x4, 0xf1, 0x0, 0x0, 0xa, 0xc0, 0x0, 0x0, - 0xe, 0x60, 0x0, 0x0, 0x4f, 0x10, 0x0, 0x0, + 0x0, 0x1c, 0x0, 0x28, 0x0, 0x34, 0x0, 0x70, + 0x0, 0xa0, 0x0, 0xd0, 0x1, 0xc0, 0x2, 0x80, + 0x3, 0x40, 0x7, 0x0, 0xb, 0x0, 0xd, 0x0, + 0x1c, 0x0, 0x2c, 0x0, 0x34, 0x0, 0x70, 0x0, /* U+0030 "0" */ - 0x0, 0x8, 0xef, 0xc5, 0x0, 0x0, 0xcf, 0xa8, - 0xcf, 0x70, 0x7, 0xf5, 0x0, 0xa, 0xf2, 0xd, - 0xc0, 0x0, 0x1, 0xf8, 0x1f, 0x80, 0x0, 0x0, - 0xdc, 0x3f, 0x60, 0x0, 0x0, 0xbd, 0x3f, 0x60, - 0x0, 0x0, 0xbd, 0x1f, 0x80, 0x0, 0x0, 0xdc, - 0xd, 0xc0, 0x0, 0x1, 0xf8, 0x7, 0xf5, 0x0, - 0xa, 0xf2, 0x0, 0xcf, 0xa8, 0xcf, 0x70, 0x0, - 0x8, 0xef, 0xc5, 0x0, + 0x2, 0xfd, 0x0, 0xfa, 0xf4, 0x1d, 0x2, 0xc3, + 0xc0, 0xe, 0x38, 0x0, 0xf3, 0x40, 0xb, 0x34, + 0x0, 0xb3, 0x80, 0xf, 0x3c, 0x0, 0xe1, 0xd0, + 0x2c, 0xf, 0xaf, 0x40, 0x2f, 0xd0, /* U+0031 "1" */ - 0xef, 0xff, 0x36, 0x7a, 0xf3, 0x0, 0x5f, 0x30, - 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, - 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, - 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, + 0xff, 0x16, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, + 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, /* U+0032 "2" */ - 0x4, 0xbe, 0xfd, 0x70, 0x7, 0xfd, 0x98, 0xcf, - 0x90, 0x28, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, - 0x7, 0xf2, 0x0, 0x0, 0x0, 0xaf, 0x0, 0x0, - 0x0, 0x4f, 0x80, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0x3e, 0xc1, 0x0, 0x0, 0x2e, 0xc1, 0x0, - 0x0, 0x2e, 0xd1, 0x0, 0x0, 0x2e, 0xf8, 0x77, - 0x77, 0x46, 0xff, 0xff, 0xff, 0xfa, + 0x1b, 0xf4, 0x1f, 0xaf, 0x82, 0x0, 0xb0, 0x0, + 0x1c, 0x0, 0xb, 0x0, 0x7, 0x80, 0x3, 0xc0, + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe5, + 0x55, 0xff, 0xfe, /* U+0033 "3" */ - 0x6f, 0xff, 0xff, 0xff, 0x2, 0x77, 0x77, 0x9f, - 0xb0, 0x0, 0x0, 0xc, 0xe1, 0x0, 0x0, 0x9, - 0xf3, 0x0, 0x0, 0x5, 0xf6, 0x0, 0x0, 0x0, - 0xdf, 0xe9, 0x10, 0x0, 0x4, 0x59, 0xfd, 0x0, - 0x0, 0x0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0x3f, - 0x64, 0x40, 0x0, 0x8, 0xf3, 0xbf, 0xc9, 0x8c, - 0xfb, 0x0, 0x7c, 0xff, 0xd7, 0x0, + 0x7f, 0xff, 0x5, 0x5b, 0x80, 0x3, 0xc0, 0x2, + 0xc0, 0x1, 0xd0, 0x0, 0xfe, 0x0, 0x16, 0xf0, + 0x0, 0x1d, 0x0, 0x3, 0x54, 0x2, 0xcb, 0xeb, + 0xe0, 0x7f, 0xd0, /* U+0034 "4" */ - 0x0, 0x0, 0x1, 0xeb, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x10, 0x0, 0x0, 0x0, 0x6f, 0x50, 0x0, - 0x0, 0x0, 0x2f, 0x90, 0x0, 0x0, 0x0, 0xc, - 0xd0, 0x0, 0x0, 0x0, 0x8, 0xf3, 0x1, 0xd5, - 0x0, 0x3, 0xf8, 0x0, 0x2f, 0x60, 0x0, 0xed, - 0x22, 0x23, 0xf7, 0x21, 0x6f, 0xff, 0xff, 0xff, - 0xff, 0x81, 0x55, 0x55, 0x56, 0xf9, 0x52, 0x0, - 0x0, 0x0, 0x2f, 0x60, 0x0, 0x0, 0x0, 0x2, - 0xf6, 0x0, + 0x0, 0xe, 0x0, 0x0, 0xb0, 0x0, 0x7, 0x40, + 0x0, 0x38, 0x0, 0x3, 0xc0, 0x0, 0x2c, 0xd, + 0x0, 0xe0, 0x34, 0xf, 0x0, 0xd0, 0x7f, 0xff, + 0xf8, 0x55, 0x5e, 0x40, 0x0, 0x34, 0x0, 0x0, + 0xd0, /* U+0035 "5" */ - 0x5, 0xff, 0xff, 0xff, 0x0, 0x7f, 0x77, 0x77, - 0x70, 0x8, 0xe0, 0x0, 0x0, 0x0, 0xad, 0x0, - 0x0, 0x0, 0xb, 0xc2, 0x10, 0x0, 0x0, 0xdf, - 0xff, 0xfb, 0x30, 0x4, 0x55, 0x68, 0xff, 0x20, - 0x0, 0x0, 0x4, 0xf8, 0x0, 0x0, 0x0, 0xf, - 0x92, 0x50, 0x0, 0x5, 0xf6, 0x8f, 0xd9, 0x8a, - 0xfd, 0x10, 0x5b, 0xef, 0xe9, 0x10, + 0x1f, 0xff, 0x7, 0x55, 0x42, 0xc0, 0x0, 0xb0, + 0x0, 0x2c, 0x0, 0xf, 0xfe, 0x1, 0x56, 0xf0, + 0x0, 0x1e, 0x0, 0x3, 0x84, 0x1, 0xdb, 0xea, + 0xf0, 0x6f, 0xe0, /* U+0036 "6" */ - 0x0, 0x5, 0xce, 0xfc, 0x60, 0x0, 0x9f, 0xc8, - 0x8b, 0x70, 0x5, 0xf8, 0x0, 0x0, 0x0, 0xc, - 0xd0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, - 0x0, 0x2f, 0x68, 0xef, 0xfa, 0x10, 0x3f, 0xee, - 0x64, 0x8f, 0xd0, 0x2f, 0xf1, 0x0, 0x6, 0xf4, - 0xe, 0xc0, 0x0, 0x2, 0xf6, 0x9, 0xf1, 0x0, - 0x6, 0xf3, 0x1, 0xde, 0x86, 0x9f, 0xb0, 0x0, - 0x19, 0xef, 0xd8, 0x0, + 0x1, 0xff, 0x40, 0xbe, 0xa4, 0x1e, 0x0, 0x3, + 0xc0, 0x0, 0x38, 0x0, 0x3, 0x6f, 0xe0, 0x3f, + 0x5b, 0xc3, 0xc0, 0x1d, 0x3c, 0x0, 0xd2, 0xc0, + 0x1c, 0xf, 0x9b, 0x80, 0x2f, 0xe0, /* U+0037 "7" */ - 0x8f, 0xff, 0xff, 0xff, 0xe8, 0xf7, 0x77, 0x77, - 0xfc, 0x8f, 0x0, 0x0, 0x4f, 0x55, 0x90, 0x0, - 0xb, 0xe0, 0x0, 0x0, 0x2, 0xf8, 0x0, 0x0, - 0x0, 0x9f, 0x10, 0x0, 0x0, 0xf, 0xb0, 0x0, - 0x0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0xdd, 0x0, - 0x0, 0x0, 0x3f, 0x70, 0x0, 0x0, 0xa, 0xf1, - 0x0, 0x0, 0x1, 0xf9, 0x0, 0x0, + 0xbf, 0xff, 0xed, 0x55, 0xfb, 0x0, 0x75, 0x80, + 0x2c, 0x0, 0xe, 0x0, 0xb, 0x0, 0x3, 0x80, + 0x1, 0xd0, 0x0, 0xf0, 0x0, 0x34, 0x0, 0x2c, + 0x0, 0xe, 0x0, /* U+0038 "8" */ - 0x0, 0x5c, 0xff, 0xd7, 0x0, 0x6, 0xfc, 0x76, - 0xaf, 0xa0, 0xc, 0xd0, 0x0, 0x9, 0xf1, 0xd, - 0xc0, 0x0, 0x7, 0xf2, 0x7, 0xf7, 0x11, 0x5e, - 0xc0, 0x0, 0xbf, 0xff, 0xfe, 0x10, 0x9, 0xf9, - 0x54, 0x7e, 0xd0, 0x2f, 0x80, 0x0, 0x4, 0xf6, - 0x4f, 0x50, 0x0, 0x0, 0xf8, 0x1f, 0xa0, 0x0, - 0x5, 0xf6, 0x9, 0xfb, 0x76, 0xaf, 0xd0, 0x0, - 0x6c, 0xff, 0xd8, 0x10, + 0x7, 0xfd, 0x1, 0xf5, 0xb8, 0x3c, 0x2, 0xc3, + 0xc0, 0x1c, 0x1d, 0x7, 0xc0, 0xbf, 0xf0, 0x2e, + 0x57, 0xc3, 0x80, 0x1d, 0x74, 0x0, 0xe3, 0x80, + 0x1d, 0x2e, 0x5b, 0xc0, 0x7f, 0xe0, /* U+0039 "9" */ - 0x0, 0x8e, 0xfd, 0x80, 0x0, 0xc, 0xf8, 0x68, - 0xfc, 0x0, 0x5f, 0x50, 0x0, 0x3f, 0x70, 0x8f, - 0x0, 0x0, 0xe, 0xc0, 0x7f, 0x30, 0x0, 0x1f, - 0xf0, 0x1f, 0xd4, 0x13, 0xcf, 0xf1, 0x4, 0xef, - 0xff, 0xa9, 0xf0, 0x0, 0x2, 0x31, 0xa, 0xf0, - 0x0, 0x0, 0x0, 0xe, 0xa0, 0x0, 0x0, 0x0, - 0x9f, 0x30, 0x9, 0xa7, 0x8d, 0xf7, 0x0, 0x7, - 0xdf, 0xeb, 0x40, 0x0, + 0xb, 0xf8, 0x3, 0xe6, 0xf0, 0x74, 0x3, 0x4b, + 0x0, 0x3c, 0x70, 0x3, 0xc3, 0xd0, 0xfc, 0x1f, + 0xfa, 0xc0, 0x0, 0x2c, 0x0, 0x3, 0x80, 0x0, + 0xb0, 0x29, 0xbd, 0x1, 0xfe, 0x40, /* U+003A ":" */ - 0x1e, 0x92, 0xfc, 0x3, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x12, 0xfc, 0x1e, 0x90, + 0x38, 0xf0, 0x0, 0x0, 0x0, 0xf, 0x38, /* U+003B ";" */ - 0x1e, 0x92, 0xfc, 0x3, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xe9, 0x1f, 0xd0, 0xa8, 0xe, - 0x30, 0xa0, + 0x38, 0xf0, 0x0, 0x0, 0x0, 0xe, 0x3c, 0xa3, + 0x8, /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x42, 0x0, 0x1, 0x7d, 0xf3, - 0x3, 0x9f, 0xe8, 0x10, 0xbf, 0xb5, 0x0, 0x0, - 0xee, 0x81, 0x0, 0x0, 0x17, 0xdf, 0xb4, 0x0, - 0x0, 0x4, 0xaf, 0xd2, 0x0, 0x0, 0x1, 0x82, + 0x0, 0x4, 0x0, 0x7c, 0xb, 0xe0, 0xb9, 0x0, + 0xf8, 0x0, 0x1f, 0x90, 0x1, 0xbc, 0x0, 0x8, /* U+003D "=" */ - 0xef, 0xff, 0xff, 0xf3, 0x45, 0x55, 0x55, 0x51, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x11, 0x11, 0x10, - 0xef, 0xff, 0xff, 0xf3, 0x34, 0x44, 0x44, 0x40, + 0xff, 0xfc, 0x55, 0x54, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xfc, 0x15, 0x54, /* U+003E ">" */ - 0x50, 0x0, 0x0, 0x0, 0xef, 0x92, 0x0, 0x0, - 0x6, 0xcf, 0xb5, 0x0, 0x0, 0x3, 0x9f, 0xe2, - 0x0, 0x0, 0x6c, 0xf3, 0x2, 0x9e, 0xe9, 0x20, - 0xbf, 0xc6, 0x0, 0x0, 0x93, 0x0, 0x0, 0x0, + 0x40, 0x0, 0xf8, 0x0, 0x1f, 0x90, 0x0, 0xbc, + 0x0, 0x7c, 0xb, 0xe0, 0xbd, 0x0, 0x80, 0x0, /* U+003F "?" */ - 0x4, 0xbe, 0xfd, 0x70, 0x7, 0xfc, 0x77, 0xbf, - 0xa0, 0x27, 0x0, 0x0, 0xcf, 0x0, 0x0, 0x0, - 0x9, 0xf0, 0x0, 0x0, 0x1, 0xea, 0x0, 0x0, - 0x1, 0xdd, 0x10, 0x0, 0x0, 0xce, 0x10, 0x0, - 0x0, 0x3f, 0x60, 0x0, 0x0, 0x1, 0x30, 0x0, - 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x6, 0xf5, - 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, + 0x1b, 0xf4, 0x1f, 0x5b, 0x81, 0x0, 0xf0, 0x0, + 0x2c, 0x0, 0xe, 0x0, 0xf, 0x0, 0xf, 0x0, + 0x3, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, + 0x0, 0x7, 0x40, /* U+0040 "@" */ - 0x0, 0x0, 0x17, 0xce, 0xfd, 0xb5, 0x0, 0x0, - 0x0, 0x5, 0xfb, 0x53, 0x23, 0x7d, 0xc2, 0x0, - 0x0, 0x6e, 0x40, 0x0, 0x0, 0x0, 0x8e, 0x10, - 0x2, 0xf4, 0x1, 0xae, 0xfa, 0x3f, 0x49, 0xb0, - 0xa, 0x90, 0x1e, 0xe6, 0x5b, 0xef, 0x40, 0xe3, - 0xf, 0x30, 0x8f, 0x10, 0x0, 0xaf, 0x40, 0x98, - 0x1f, 0x0, 0xd9, 0x0, 0x0, 0x3f, 0x40, 0x6a, - 0x3f, 0x0, 0xe8, 0x0, 0x0, 0x1f, 0x40, 0x5c, - 0x1f, 0x0, 0xd9, 0x0, 0x0, 0x3f, 0x40, 0x6a, - 0xf, 0x30, 0x8f, 0x10, 0x0, 0xaf, 0x40, 0x98, - 0xa, 0x90, 0x1e, 0xd6, 0x5a, 0xde, 0xa6, 0xf2, - 0x3, 0xf3, 0x1, 0xaf, 0xfa, 0x16, 0xee, 0x50, - 0x0, 0x6e, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6, 0xfb, 0x53, 0x23, 0x75, 0x0, 0x0, - 0x0, 0x0, 0x17, 0xce, 0xfd, 0xa3, 0x0, 0x0, + 0x0, 0x1f, 0xf9, 0x0, 0x1, 0xe4, 0x7, 0xc0, + 0x7, 0x40, 0x0, 0xb0, 0xd, 0xb, 0xe3, 0x68, + 0x28, 0x3d, 0x6f, 0x4c, 0x30, 0xb0, 0xb, 0x4a, + 0x30, 0xe0, 0x3, 0x46, 0x30, 0xe0, 0x3, 0x47, + 0x30, 0xe0, 0x3, 0x46, 0x30, 0xb0, 0xb, 0x4a, + 0x28, 0x3d, 0x6f, 0x9c, 0xc, 0xb, 0xe1, 0xf4, + 0x7, 0x40, 0x0, 0x0, 0x1, 0xe4, 0x5, 0x0, + 0x0, 0x1f, 0xf8, 0x0, /* U+0041 "A" */ - 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x9f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xf, - 0x9e, 0xb0, 0x0, 0x0, 0x0, 0x6, 0xf2, 0x7f, - 0x20, 0x0, 0x0, 0x0, 0xdc, 0x1, 0xf8, 0x0, - 0x0, 0x0, 0x4f, 0x60, 0xb, 0xe0, 0x0, 0x0, - 0xb, 0xf0, 0x0, 0x4f, 0x60, 0x0, 0x1, 0xfa, - 0x11, 0x11, 0xed, 0x0, 0x0, 0x8f, 0xff, 0xff, - 0xff, 0xf3, 0x0, 0xe, 0xc4, 0x44, 0x44, 0x4f, - 0xa0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0xaf, 0x10, - 0xcd, 0x0, 0x0, 0x0, 0x2, 0xf8, + 0x0, 0xf, 0x0, 0x0, 0xb, 0xd0, 0x0, 0x3, + 0xb8, 0x0, 0x1, 0xdb, 0x0, 0x0, 0xf0, 0xe0, + 0x0, 0x74, 0x3c, 0x0, 0x2c, 0x7, 0x40, 0xe, + 0x0, 0xf0, 0xb, 0xff, 0xfc, 0x3, 0xd5, 0x57, + 0x81, 0xd0, 0x0, 0xb0, 0xf0, 0x0, 0xe, /* U+0042 "B" */ - 0x5f, 0xff, 0xff, 0xeb, 0x40, 0x5, 0xf8, 0x55, - 0x57, 0xdf, 0x40, 0x5f, 0x40, 0x0, 0x1, 0xfa, - 0x5, 0xf4, 0x0, 0x0, 0xf, 0xa0, 0x5f, 0x51, - 0x11, 0x3a, 0xf4, 0x5, 0xff, 0xff, 0xff, 0xfa, - 0x0, 0x5f, 0x74, 0x44, 0x59, 0xfa, 0x5, 0xf4, - 0x0, 0x0, 0x8, 0xf2, 0x5f, 0x40, 0x0, 0x0, - 0x5f, 0x45, 0xf4, 0x0, 0x0, 0x9, 0xf2, 0x5f, - 0x85, 0x55, 0x6a, 0xfb, 0x5, 0xff, 0xff, 0xff, - 0xd7, 0x0, + 0x7f, 0xfe, 0x41, 0xe5, 0x5f, 0x47, 0x40, 0xe, + 0x1d, 0x0, 0x38, 0x74, 0x2, 0xd1, 0xff, 0xfe, + 0x7, 0x55, 0x6e, 0x1d, 0x0, 0x2c, 0x74, 0x0, + 0x75, 0xd0, 0x2, 0xc7, 0x95, 0x6e, 0x1f, 0xff, + 0xd0, /* U+0043 "C" */ - 0x0, 0x2, 0x8d, 0xfe, 0xb4, 0x0, 0x4, 0xff, - 0xb8, 0x9d, 0xf9, 0x2, 0xfd, 0x20, 0x0, 0x8, - 0x50, 0xbf, 0x20, 0x0, 0x0, 0x0, 0xf, 0xa0, - 0x0, 0x0, 0x0, 0x2, 0xf6, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0x60, 0x0, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xf2, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xd2, 0x0, 0x0, 0x85, 0x0, - 0x5f, 0xfb, 0x89, 0xdf, 0x80, 0x0, 0x29, 0xdf, - 0xeb, 0x40, + 0x0, 0xbf, 0x90, 0x1f, 0xab, 0xe0, 0xf0, 0x2, + 0x4b, 0x0, 0x0, 0x38, 0x0, 0x0, 0xd0, 0x0, + 0x3, 0x40, 0x0, 0xe, 0x0, 0x0, 0x2c, 0x0, + 0x0, 0x3c, 0x0, 0x90, 0x7e, 0xaf, 0x80, 0x2f, + 0xe4, /* U+0044 "D" */ - 0x5f, 0xff, 0xff, 0xea, 0x30, 0x0, 0x5f, 0x97, - 0x77, 0x9e, 0xf8, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0xaf, 0x60, 0x5f, 0x40, 0x0, 0x0, 0xd, 0xe0, - 0x5f, 0x40, 0x0, 0x0, 0x6, 0xf4, 0x5f, 0x40, - 0x0, 0x0, 0x3, 0xf6, 0x5f, 0x40, 0x0, 0x0, - 0x3, 0xf6, 0x5f, 0x40, 0x0, 0x0, 0x6, 0xf4, - 0x5f, 0x40, 0x0, 0x0, 0xd, 0xe0, 0x5f, 0x40, - 0x0, 0x0, 0xaf, 0x60, 0x5f, 0x97, 0x77, 0x9e, - 0xf8, 0x0, 0x5f, 0xff, 0xff, 0xea, 0x30, 0x0, + 0x7f, 0xfe, 0x0, 0x79, 0x5b, 0xe0, 0x74, 0x0, + 0xb4, 0x74, 0x0, 0x3c, 0x74, 0x0, 0x1d, 0x74, + 0x0, 0xd, 0x74, 0x0, 0xd, 0x74, 0x0, 0x1d, + 0x74, 0x0, 0x3c, 0x74, 0x0, 0xb4, 0x79, 0x5b, + 0xe0, 0x7f, 0xfe, 0x0, /* U+0045 "E" */ - 0x5f, 0xff, 0xff, 0xff, 0x95, 0xf9, 0x77, 0x77, - 0x74, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x51, 0x11, 0x11, 0x5, 0xff, - 0xff, 0xff, 0xe0, 0x5f, 0x74, 0x44, 0x44, 0x5, - 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x97, 0x77, - 0x77, 0x65, 0xff, 0xff, 0xff, 0xfd, + 0x7f, 0xff, 0x9e, 0x55, 0x57, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1f, 0xff, 0xc7, 0x55, 0x51, + 0xd0, 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x95, + 0x55, 0xff, 0xff, /* U+0046 "F" */ - 0x5f, 0xff, 0xff, 0xff, 0x95, 0xf9, 0x77, 0x77, - 0x74, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf5, - 0x22, 0x22, 0x10, 0x5f, 0xff, 0xff, 0xfe, 0x5, - 0xf8, 0x55, 0x55, 0x40, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, - 0x0, 0x5, 0xf4, 0x0, 0x0, 0x0, + 0x7f, 0xff, 0x9e, 0x55, 0x57, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0xff, 0xf1, + 0xe5, 0x54, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, + 0x1, 0xd0, 0x0, /* U+0047 "G" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x4f, - 0xfb, 0x89, 0xdf, 0xb0, 0x2, 0xfd, 0x20, 0x0, - 0x6, 0x60, 0xb, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x60, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0x60, 0x0, 0x0, - 0x9, 0xf0, 0xf, 0xa0, 0x0, 0x0, 0x9, 0xf0, - 0xb, 0xf2, 0x0, 0x0, 0x9, 0xf0, 0x2, 0xfd, - 0x20, 0x0, 0xa, 0xf0, 0x0, 0x4f, 0xfb, 0x89, - 0xdf, 0xc0, 0x0, 0x2, 0x8d, 0xfe, 0xc6, 0x0, + 0x0, 0xbf, 0x90, 0x7, 0xea, 0xf8, 0xf, 0x0, + 0x14, 0x2c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x34, + 0x0, 0x0, 0x34, 0x0, 0x2c, 0x38, 0x0, 0x2c, + 0x2c, 0x0, 0x2c, 0xf, 0x0, 0x2c, 0x7, 0xea, + 0xfc, 0x0, 0xbf, 0xd0, /* U+0048 "H" */ - 0x5f, 0x40, 0x0, 0x0, 0x4f, 0x55, 0xf4, 0x0, - 0x0, 0x4, 0xf5, 0x5f, 0x40, 0x0, 0x0, 0x4f, - 0x55, 0xf4, 0x0, 0x0, 0x4, 0xf5, 0x5f, 0x52, - 0x22, 0x22, 0x5f, 0x55, 0xff, 0xff, 0xff, 0xff, - 0xf5, 0x5f, 0x85, 0x55, 0x55, 0x8f, 0x55, 0xf4, - 0x0, 0x0, 0x4, 0xf5, 0x5f, 0x40, 0x0, 0x0, - 0x4f, 0x55, 0xf4, 0x0, 0x0, 0x4, 0xf5, 0x5f, - 0x40, 0x0, 0x0, 0x4f, 0x55, 0xf4, 0x0, 0x0, - 0x4, 0xf5, + 0x74, 0x0, 0x75, 0xd0, 0x1, 0xd7, 0x40, 0x7, + 0x5d, 0x0, 0x1d, 0x74, 0x0, 0x75, 0xff, 0xff, + 0xd7, 0x95, 0x5b, 0x5d, 0x0, 0x1d, 0x74, 0x0, + 0x75, 0xd0, 0x1, 0xd7, 0x40, 0x7, 0x5d, 0x0, + 0x1d, /* U+0049 "I" */ - 0x5f, 0x45, 0xf4, 0x5f, 0x45, 0xf4, 0x5f, 0x45, - 0xf4, 0x5f, 0x45, 0xf4, 0x5f, 0x45, 0xf4, 0x5f, - 0x45, 0xf4, + 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, + 0x5d, /* U+004A "J" */ - 0x0, 0xff, 0xff, 0xfa, 0x0, 0x77, 0x77, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xf9, 0x7, 0x20, 0x3, 0xf6, - 0xd, 0xe9, 0x8e, 0xf1, 0x1, 0xae, 0xfb, 0x30, + 0xf, 0xfe, 0x5, 0x5e, 0x0, 0xe, 0x0, 0xe, + 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, + 0x0, 0xe, 0x10, 0xd, 0x3e, 0xbc, 0xb, 0xe0, /* U+004B "K" */ - 0x5f, 0x40, 0x0, 0x2, 0xeb, 0x5, 0xf4, 0x0, - 0x1, 0xec, 0x0, 0x5f, 0x40, 0x1, 0xde, 0x10, - 0x5, 0xf4, 0x0, 0xce, 0x20, 0x0, 0x5f, 0x40, - 0xbf, 0x30, 0x0, 0x5, 0xf4, 0x9f, 0x90, 0x0, - 0x0, 0x5f, 0xcf, 0xef, 0x40, 0x0, 0x5, 0xff, - 0x91, 0xee, 0x10, 0x0, 0x5f, 0xa0, 0x3, 0xfc, - 0x0, 0x5, 0xf4, 0x0, 0x6, 0xf8, 0x0, 0x5f, - 0x40, 0x0, 0x9, 0xf5, 0x5, 0xf4, 0x0, 0x0, - 0xc, 0xf2, + 0x74, 0x0, 0xe1, 0xd0, 0xf, 0x7, 0x40, 0xf0, + 0x1d, 0xf, 0x0, 0x74, 0xb0, 0x1, 0xdb, 0x80, + 0x7, 0xff, 0x40, 0x1f, 0x8f, 0x0, 0x78, 0xf, + 0x1, 0xd0, 0x1e, 0x7, 0x40, 0x2d, 0x1d, 0x0, + 0x3c, /* U+004C "L" */ - 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, 0x0, - 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, - 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, - 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x97, 0x77, - 0x77, 0x25, 0xff, 0xff, 0xff, 0xf5, + 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, 0x1, + 0xd0, 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x95, + 0x51, 0xff, 0xfd, /* U+004D "M" */ - 0x5f, 0x40, 0x0, 0x0, 0x0, 0x1e, 0x95, 0xfc, - 0x0, 0x0, 0x0, 0x8, 0xf9, 0x5f, 0xf5, 0x0, - 0x0, 0x2, 0xff, 0x95, 0xfd, 0xe0, 0x0, 0x0, - 0xae, 0xf9, 0x5f, 0x5f, 0x70, 0x0, 0x3f, 0x5f, - 0x95, 0xf3, 0x8f, 0x10, 0xb, 0xc0, 0xf9, 0x5f, - 0x31, 0xe9, 0x4, 0xf3, 0xf, 0x95, 0xf3, 0x7, - 0xf2, 0xdb, 0x0, 0xf9, 0x5f, 0x30, 0xd, 0xef, - 0x20, 0xf, 0x95, 0xf3, 0x0, 0x5f, 0x90, 0x0, - 0xf9, 0x5f, 0x30, 0x0, 0x71, 0x0, 0xf, 0x95, - 0xf3, 0x0, 0x0, 0x0, 0x0, 0xf9, + 0x74, 0x0, 0x3, 0x9f, 0x0, 0x2, 0xe7, 0xd0, + 0x0, 0xf9, 0xfc, 0x0, 0xbe, 0x77, 0x40, 0x37, + 0x9c, 0xb0, 0x2c, 0xe7, 0xe, 0x1c, 0x39, 0xc1, + 0xce, 0xe, 0x70, 0x3f, 0x3, 0x9c, 0x7, 0x80, + 0xe7, 0x0, 0x40, 0x39, 0xc0, 0x0, 0xe, /* U+004E "N" */ - 0x5f, 0x50, 0x0, 0x0, 0x4f, 0x55, 0xff, 0x20, - 0x0, 0x4, 0xf5, 0x5f, 0xfd, 0x0, 0x0, 0x4f, - 0x55, 0xfa, 0xf9, 0x0, 0x4, 0xf5, 0x5f, 0x4a, - 0xf5, 0x0, 0x4f, 0x55, 0xf4, 0xd, 0xf2, 0x4, - 0xf5, 0x5f, 0x40, 0x2f, 0xd0, 0x4f, 0x55, 0xf4, - 0x0, 0x6f, 0x94, 0xf5, 0x5f, 0x40, 0x0, 0xaf, - 0xaf, 0x55, 0xf4, 0x0, 0x0, 0xdf, 0xf5, 0x5f, - 0x40, 0x0, 0x2, 0xff, 0x55, 0xf4, 0x0, 0x0, - 0x6, 0xf5, + 0x74, 0x0, 0x75, 0xf0, 0x1, 0xd7, 0xf0, 0x7, + 0x5e, 0xe0, 0x1d, 0x76, 0xd0, 0x75, 0xd3, 0xc1, + 0xd7, 0x43, 0xc7, 0x5d, 0x7, 0x9d, 0x74, 0xb, + 0xb5, 0xd0, 0xf, 0xd7, 0x40, 0xf, 0x5d, 0x0, + 0x1d, /* U+004F "O" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x4, - 0xff, 0xb8, 0x9e, 0xfa, 0x0, 0x2, 0xfd, 0x20, - 0x0, 0x8, 0xf9, 0x0, 0xbf, 0x20, 0x0, 0x0, - 0xa, 0xf2, 0xf, 0xa0, 0x0, 0x0, 0x0, 0x3f, - 0x72, 0xf6, 0x0, 0x0, 0x0, 0x0, 0xf9, 0x2f, - 0x60, 0x0, 0x0, 0x0, 0xf, 0x90, 0xfa, 0x0, - 0x0, 0x0, 0x3, 0xf7, 0xb, 0xf2, 0x0, 0x0, - 0x0, 0xaf, 0x20, 0x2f, 0xd2, 0x0, 0x0, 0x8f, - 0x90, 0x0, 0x4f, 0xfb, 0x89, 0xef, 0xa0, 0x0, - 0x0, 0x28, 0xdf, 0xeb, 0x50, 0x0, + 0x0, 0xbf, 0x90, 0x1, 0xfa, 0xbe, 0x0, 0xf0, + 0x2, 0xe0, 0xb0, 0x0, 0x2c, 0x38, 0x0, 0x3, + 0x4d, 0x0, 0x0, 0xe3, 0x40, 0x0, 0x38, 0xe0, + 0x0, 0xd, 0x2c, 0x0, 0xb, 0x3, 0xc0, 0xb, + 0x80, 0x7e, 0xaf, 0x80, 0x2, 0xfe, 0x40, /* U+0050 "P" */ - 0x5f, 0xff, 0xff, 0xd7, 0x0, 0x5f, 0x97, 0x78, - 0xbf, 0xc0, 0x5f, 0x40, 0x0, 0x7, 0xf6, 0x5f, - 0x40, 0x0, 0x0, 0xfa, 0x5f, 0x40, 0x0, 0x0, - 0xfa, 0x5f, 0x40, 0x0, 0x3, 0xf8, 0x5f, 0x62, - 0x23, 0x6e, 0xf1, 0x5f, 0xff, 0xff, 0xfd, 0x30, - 0x5f, 0x85, 0x54, 0x20, 0x0, 0x5f, 0x40, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x0, 0x5f, - 0x40, 0x0, 0x0, 0x0, + 0x7f, 0xfd, 0x7, 0x96, 0xbc, 0x74, 0x1, 0xd7, + 0x40, 0xe, 0x74, 0x0, 0xe7, 0x40, 0xe, 0x74, + 0x7, 0xc7, 0xff, 0xf0, 0x79, 0x50, 0x7, 0x40, + 0x0, 0x74, 0x0, 0x7, 0x40, 0x0, /* U+0051 "Q" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x0, - 0x4e, 0xfb, 0x89, 0xef, 0xa0, 0x0, 0x2, 0xfd, - 0x20, 0x0, 0x8, 0xf9, 0x0, 0xa, 0xf2, 0x0, - 0x0, 0x0, 0xaf, 0x20, 0xf, 0xa0, 0x0, 0x0, - 0x0, 0x3f, 0x70, 0x2f, 0x60, 0x0, 0x0, 0x0, - 0xf, 0x90, 0x2f, 0x60, 0x0, 0x0, 0x0, 0xf, - 0x90, 0x1f, 0x90, 0x0, 0x0, 0x0, 0x2f, 0x70, - 0xb, 0xf1, 0x0, 0x0, 0x0, 0xaf, 0x20, 0x3, - 0xfc, 0x10, 0x0, 0x7, 0xf9, 0x0, 0x0, 0x6f, - 0xfa, 0x78, 0xdf, 0xb0, 0x0, 0x0, 0x3, 0xae, - 0xff, 0xc5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0xd4, 0x15, 0xb0, 0x0, 0x0, 0x0, 0x2, 0xbf, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1, 0x31, - 0x0, + 0x0, 0xbf, 0x90, 0x0, 0x7e, 0xaf, 0x80, 0xf, + 0x0, 0x2e, 0x2, 0xc0, 0x0, 0xb0, 0x38, 0x0, + 0x3, 0x43, 0x40, 0x0, 0x38, 0x34, 0x0, 0x3, + 0x83, 0x80, 0x0, 0x34, 0x2c, 0x0, 0xb, 0x0, + 0xf0, 0x1, 0xe0, 0x7, 0xe6, 0xf8, 0x0, 0xb, + 0xfd, 0x0, 0x0, 0x3, 0xd1, 0x80, 0x0, 0xb, + 0xf8, 0x0, 0x0, 0x0, 0x0, /* U+0052 "R" */ - 0x5f, 0xff, 0xff, 0xd7, 0x0, 0x5f, 0x97, 0x78, - 0xbf, 0xc0, 0x5f, 0x40, 0x0, 0x7, 0xf6, 0x5f, - 0x40, 0x0, 0x0, 0xfa, 0x5f, 0x40, 0x0, 0x0, - 0xfa, 0x5f, 0x40, 0x0, 0x3, 0xf8, 0x5f, 0x52, - 0x23, 0x6e, 0xe1, 0x5f, 0xff, 0xff, 0xfc, 0x30, - 0x5f, 0x85, 0x55, 0xf9, 0x0, 0x5f, 0x40, 0x0, - 0x7f, 0x40, 0x5f, 0x40, 0x0, 0xc, 0xe0, 0x5f, - 0x40, 0x0, 0x2, 0xf9, + 0x7f, 0xfd, 0x7, 0x96, 0xbc, 0x74, 0x1, 0xd7, + 0x40, 0xe, 0x74, 0x0, 0xe7, 0x40, 0xe, 0x74, + 0x7, 0xc7, 0xff, 0xf0, 0x79, 0x5e, 0x7, 0x40, + 0x74, 0x74, 0x3, 0xc7, 0x40, 0xe, /* U+0053 "S" */ - 0x0, 0x5c, 0xef, 0xd9, 0x20, 0x7, 0xfc, 0x87, - 0xaf, 0x90, 0xe, 0xc0, 0x0, 0x1, 0x10, 0xf, - 0x80, 0x0, 0x0, 0x0, 0xd, 0xf5, 0x0, 0x0, - 0x0, 0x3, 0xef, 0xea, 0x50, 0x0, 0x0, 0x5, - 0xae, 0xfe, 0x40, 0x0, 0x0, 0x0, 0x4e, 0xf1, - 0x0, 0x0, 0x0, 0x5, 0xf3, 0x8, 0x0, 0x0, - 0x8, 0xf2, 0x2f, 0xfa, 0x77, 0xbf, 0xa0, 0x2, - 0x9d, 0xff, 0xc7, 0x0, + 0x7, 0xfe, 0x1, 0xf9, 0xb8, 0x3c, 0x0, 0x3, + 0x80, 0x0, 0x3d, 0x0, 0x0, 0xfe, 0x40, 0x1, + 0xbf, 0x40, 0x0, 0x7c, 0x0, 0x1, 0xc2, 0x0, + 0x2c, 0x3e, 0x5b, 0x80, 0xbf, 0xd0, /* U+0054 "T" */ - 0xff, 0xff, 0xff, 0xff, 0xf5, 0x67, 0x78, 0xfb, - 0x77, 0x72, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, - 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, - 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, - 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, + 0xff, 0xff, 0xd5, 0x6e, 0x54, 0x0, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, + 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, /* U+0055 "U" */ - 0x6f, 0x30, 0x0, 0x0, 0x8f, 0x16, 0xf3, 0x0, - 0x0, 0x8, 0xf1, 0x6f, 0x30, 0x0, 0x0, 0x8f, - 0x16, 0xf3, 0x0, 0x0, 0x8, 0xf1, 0x6f, 0x30, - 0x0, 0x0, 0x8f, 0x16, 0xf3, 0x0, 0x0, 0x8, - 0xf1, 0x6f, 0x30, 0x0, 0x0, 0x8f, 0x5, 0xf4, - 0x0, 0x0, 0x9, 0xf0, 0x3f, 0x70, 0x0, 0x0, - 0xcd, 0x0, 0xde, 0x20, 0x0, 0x5f, 0x80, 0x4, - 0xff, 0xa8, 0xbf, 0xd0, 0x0, 0x3, 0xbe, 0xfd, - 0x81, 0x0, + 0x70, 0x0, 0xb1, 0xc0, 0x2, 0xc7, 0x0, 0xb, + 0x1c, 0x0, 0x2c, 0x70, 0x0, 0xb1, 0xc0, 0x2, + 0xc7, 0x0, 0xb, 0x1d, 0x0, 0x2c, 0x34, 0x0, + 0xf0, 0xf0, 0x7, 0x81, 0xfa, 0xbc, 0x0, 0xbf, + 0x80, /* U+0056 "V" */ - 0xc, 0xe0, 0x0, 0x0, 0x0, 0x6f, 0x30, 0x6f, - 0x50, 0x0, 0x0, 0xc, 0xc0, 0x0, 0xfb, 0x0, - 0x0, 0x3, 0xf6, 0x0, 0x9, 0xf2, 0x0, 0x0, - 0xae, 0x0, 0x0, 0x2f, 0x80, 0x0, 0x1f, 0x90, - 0x0, 0x0, 0xce, 0x0, 0x7, 0xf2, 0x0, 0x0, - 0x5, 0xf6, 0x0, 0xdb, 0x0, 0x0, 0x0, 0xe, - 0xc0, 0x4f, 0x50, 0x0, 0x0, 0x0, 0x8f, 0x3b, - 0xe0, 0x0, 0x0, 0x0, 0x2, 0xfb, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x4f, 0xb0, 0x0, 0x0, + 0x3c, 0x0, 0x7, 0x7, 0x40, 0x3, 0xc0, 0xf0, + 0x0, 0xd0, 0x2c, 0x0, 0xb0, 0x3, 0x80, 0x38, + 0x0, 0xf0, 0x2c, 0x0, 0x1d, 0xe, 0x0, 0x3, + 0xc7, 0x40, 0x0, 0xb7, 0xc0, 0x0, 0xf, 0xe0, + 0x0, 0x2, 0xf0, 0x0, 0x0, 0x78, 0x0, /* U+0057 "W" */ - 0x5f, 0x40, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x2, - 0xf5, 0xf, 0x90, 0x0, 0x2, 0xff, 0x40, 0x0, - 0x7, 0xf0, 0xb, 0xe0, 0x0, 0x7, 0xfe, 0x90, - 0x0, 0xc, 0xb0, 0x6, 0xf3, 0x0, 0xc, 0xaa, - 0xe0, 0x0, 0x1f, 0x60, 0x1, 0xf8, 0x0, 0x1f, - 0x54, 0xf3, 0x0, 0x6f, 0x10, 0x0, 0xcd, 0x0, - 0x7f, 0x10, 0xf8, 0x0, 0xcc, 0x0, 0x0, 0x7f, - 0x20, 0xcb, 0x0, 0xad, 0x1, 0xf7, 0x0, 0x0, - 0x2f, 0x71, 0xf6, 0x0, 0x5f, 0x26, 0xf2, 0x0, - 0x0, 0xd, 0xc6, 0xf1, 0x0, 0xf, 0x7b, 0xd0, - 0x0, 0x0, 0x8, 0xfd, 0xc0, 0x0, 0xb, 0xdf, - 0x80, 0x0, 0x0, 0x3, 0xff, 0x70, 0x0, 0x6, - 0xff, 0x30, 0x0, 0x0, 0x0, 0xef, 0x20, 0x0, - 0x1, 0xfe, 0x0, 0x0, + 0x74, 0x0, 0xf0, 0x0, 0xd3, 0x80, 0xf, 0x40, + 0x2c, 0x2c, 0x1, 0xf8, 0x3, 0x81, 0xc0, 0x3a, + 0xc0, 0x34, 0xe, 0x3, 0x5d, 0x7, 0x0, 0xf0, + 0x70, 0xe0, 0xf0, 0x7, 0xe, 0xb, 0xd, 0x0, + 0x34, 0xd0, 0x71, 0xc0, 0x3, 0xdc, 0x3, 0xbc, + 0x0, 0x2f, 0xc0, 0x2f, 0x80, 0x0, 0xf4, 0x1, + 0xf0, 0x0, 0xf, 0x0, 0xf, 0x0, /* U+0058 "X" */ - 0x3f, 0x90, 0x0, 0x0, 0xcd, 0x0, 0x8f, 0x40, - 0x0, 0x7f, 0x30, 0x0, 0xde, 0x10, 0x2f, 0x80, - 0x0, 0x3, 0xfa, 0xc, 0xd0, 0x0, 0x0, 0x7, - 0xfb, 0xf3, 0x0, 0x0, 0x0, 0xc, 0xf8, 0x0, - 0x0, 0x0, 0x1, 0xef, 0xc0, 0x0, 0x0, 0x0, - 0xbf, 0x7f, 0x70, 0x0, 0x0, 0x6f, 0x60, 0xaf, - 0x20, 0x0, 0x2f, 0xb0, 0x1, 0xed, 0x0, 0xc, - 0xf1, 0x0, 0x4, 0xf8, 0x7, 0xf6, 0x0, 0x0, - 0x9, 0xf3, + 0x38, 0x0, 0xf0, 0xb4, 0x7, 0x0, 0xf0, 0x38, + 0x0, 0xe3, 0xc0, 0x1, 0xec, 0x0, 0x3, 0xe0, + 0x0, 0xf, 0xc0, 0x0, 0xb7, 0x40, 0x7, 0x4b, + 0x0, 0x38, 0xf, 0x3, 0xc0, 0x1e, 0x1d, 0x0, + 0x2c, /* U+0059 "Y" */ - 0xc, 0xe0, 0x0, 0x0, 0x7, 0xf2, 0x3, 0xf7, - 0x0, 0x0, 0x1f, 0x90, 0x0, 0xaf, 0x10, 0x0, - 0x9e, 0x10, 0x0, 0x1f, 0xa0, 0x2, 0xf6, 0x0, - 0x0, 0x8, 0xf3, 0xb, 0xd0, 0x0, 0x0, 0x0, - 0xec, 0x4f, 0x40, 0x0, 0x0, 0x0, 0x5f, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, - 0x0, 0x0, 0x9, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x9, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x9, 0xf0, 0x0, 0x0, + 0x3c, 0x0, 0x1c, 0xd, 0x0, 0x38, 0xb, 0x0, + 0xb0, 0x3, 0x80, 0xd0, 0x2, 0xc2, 0xc0, 0x0, + 0xf7, 0x40, 0x0, 0x7e, 0x0, 0x0, 0x3c, 0x0, + 0x0, 0x2c, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x2c, + 0x0, 0x0, 0x2c, 0x0, /* U+005A "Z" */ - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x1, 0x77, 0x77, - 0x77, 0xbf, 0x90, 0x0, 0x0, 0x0, 0x1e, 0xc0, - 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, 0x0, - 0x8, 0xf5, 0x0, 0x0, 0x0, 0x4, 0xf9, 0x0, - 0x0, 0x0, 0x1, 0xec, 0x0, 0x0, 0x0, 0x0, - 0xcf, 0x20, 0x0, 0x0, 0x0, 0x8f, 0x50, 0x0, - 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x1e, - 0xf8, 0x77, 0x77, 0x77, 0x5, 0xff, 0xff, 0xff, - 0xff, 0xf0, + 0x3f, 0xff, 0xf0, 0x55, 0x5b, 0x80, 0x0, 0x3c, + 0x0, 0x3, 0xc0, 0x0, 0x2d, 0x0, 0x1, 0xe0, + 0x0, 0xf, 0x0, 0x0, 0xf0, 0x0, 0xb, 0x40, + 0x0, 0x78, 0x0, 0x3, 0xe5, 0x55, 0x1f, 0xff, + 0xfc, /* U+005B "[" */ - 0x5f, 0xff, 0x5, 0xf7, 0x50, 0x5f, 0x30, 0x5, - 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, - 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, - 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, - 0x5, 0xf7, 0x50, 0x5f, 0xff, 0x0, + 0x7f, 0x1d, 0x47, 0x1, 0xc0, 0x70, 0x1c, 0x7, + 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, + 0x1d, 0x47, 0xf0, /* U+005C "\\" */ - 0x7e, 0x0, 0x0, 0x0, 0x1f, 0x40, 0x0, 0x0, - 0xc, 0x90, 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, - 0x2, 0xf4, 0x0, 0x0, 0x0, 0xc9, 0x0, 0x0, - 0x0, 0x7e, 0x0, 0x0, 0x0, 0x2f, 0x40, 0x0, - 0x0, 0xc, 0x90, 0x0, 0x0, 0x7, 0xe0, 0x0, - 0x0, 0x2, 0xf3, 0x0, 0x0, 0x0, 0xd9, 0x0, - 0x0, 0x0, 0x7e, 0x0, 0x0, 0x0, 0x2f, 0x30, - 0x0, 0x0, 0xd, 0x90, 0x0, 0x0, 0x7, 0xe0, + 0x70, 0x0, 0x34, 0x0, 0x38, 0x0, 0x1c, 0x0, + 0xd, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x40, + 0x3, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0x0, 0xe0, + 0x0, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x1c, /* U+005D "]" */ - 0xbf, 0xfa, 0x35, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x35, 0xea, 0xbf, 0xfa, + 0xbe, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, + 0xe, 0xe, 0xe, 0xe, 0xe, 0x1e, 0xbe, /* U+005E "^" */ - 0x0, 0x2f, 0x80, 0x0, 0x0, 0x9d, 0xe0, 0x0, - 0x0, 0xf3, 0xd5, 0x0, 0x6, 0xd0, 0x7b, 0x0, - 0xc, 0x60, 0x1f, 0x20, 0x3f, 0x10, 0xb, 0x80, - 0x9a, 0x0, 0x4, 0xe0, + 0x3, 0x80, 0xb, 0xc0, 0xc, 0xd0, 0x1c, 0x60, + 0x34, 0x30, 0x30, 0x28, 0xa0, 0x1c, /* U+005F "_" */ - 0xff, 0xff, 0xff, 0xff, 0x11, 0x11, 0x11, 0x11, + 0xff, 0xff, 0x0, 0x0, /* U+0060 "`" */ - 0x7, 0xf6, 0x0, 0x3, 0xe7, + 0x1d, 0x0, 0xd0, /* U+0061 "a" */ - 0x1, 0x9e, 0xfd, 0x80, 0x0, 0xce, 0x87, 0xaf, - 0x90, 0x2, 0x0, 0x0, 0xaf, 0x0, 0x0, 0x0, - 0x6, 0xf2, 0x2, 0xbe, 0xff, 0xff, 0x20, 0xec, - 0x42, 0x27, 0xf2, 0x2f, 0x50, 0x0, 0x7f, 0x20, - 0xec, 0x42, 0x7f, 0xf2, 0x2, 0xbf, 0xfb, 0x6f, - 0x20, + 0xb, 0xf8, 0xf, 0x9b, 0x80, 0x0, 0xb0, 0x0, + 0x1c, 0xb, 0xff, 0xf, 0x41, 0xc3, 0x40, 0x70, + 0xf4, 0x7c, 0xb, 0xe7, 0x0, /* U+0062 "b" */ - 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, 0x0, 0x0, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x2b, 0xfe, 0xb3, 0x0, 0x8f, 0xec, 0x78, 0xef, - 0x30, 0x8f, 0xa0, 0x0, 0x1e, 0xc0, 0x8f, 0x20, - 0x0, 0x7, 0xf1, 0x8f, 0x0, 0x0, 0x5, 0xf3, - 0x8f, 0x20, 0x0, 0x7, 0xf1, 0x8f, 0xa0, 0x0, - 0x1e, 0xd0, 0x8f, 0xec, 0x78, 0xef, 0x30, 0x8e, - 0x2b, 0xfe, 0xb3, 0x0, + 0xb0, 0x0, 0xb, 0x0, 0x0, 0xb0, 0x0, 0xb, + 0x2f, 0x80, 0xbf, 0x6f, 0xb, 0x80, 0x3c, 0xb0, + 0x1, 0xcb, 0x0, 0x1c, 0xb0, 0x1, 0xcb, 0x80, + 0x3c, 0xbf, 0x6f, 0xb, 0x2f, 0x80, /* U+0063 "c" */ - 0x0, 0x3a, 0xef, 0xc4, 0x0, 0x4f, 0xd8, 0x7c, - 0xf4, 0xd, 0xd0, 0x0, 0x7, 0x13, 0xf6, 0x0, - 0x0, 0x0, 0x4f, 0x30, 0x0, 0x0, 0x3, 0xf6, - 0x0, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x6, 0x10, - 0x4f, 0xd7, 0x7c, 0xf4, 0x0, 0x3a, 0xef, 0xc4, - 0x0, + 0x2, 0xfd, 0x7, 0xe7, 0xd3, 0xc0, 0x10, 0xd0, + 0x0, 0x70, 0x0, 0xd, 0x0, 0x3, 0xc0, 0x10, + 0x7d, 0x7d, 0x2, 0xfd, 0x0, /* U+0064 "d" */ - 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x3b, 0xff, 0xa3, 0xf7, 0x4, 0xfd, 0x87, 0xce, - 0xf7, 0xe, 0xd0, 0x0, 0xb, 0xf7, 0x3f, 0x60, - 0x0, 0x3, 0xf7, 0x4f, 0x30, 0x0, 0x1, 0xf7, - 0x3f, 0x50, 0x0, 0x3, 0xf7, 0xe, 0xc0, 0x0, - 0xa, 0xf7, 0x4, 0xfc, 0x65, 0xbe, 0xf7, 0x0, - 0x3b, 0xff, 0xb2, 0xf7, + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, + 0x2f, 0x8d, 0x1f, 0x9f, 0xd3, 0xc0, 0x2d, 0x34, + 0x0, 0xd7, 0x0, 0xd, 0x34, 0x0, 0xd3, 0xc0, + 0x2d, 0x1f, 0x5b, 0xd0, 0x2f, 0x8d, /* U+0065 "e" */ - 0x0, 0x3b, 0xfe, 0xa2, 0x0, 0x4, 0xfc, 0x67, - 0xee, 0x20, 0xe, 0xc0, 0x0, 0x1e, 0xa0, 0x3f, - 0x50, 0x0, 0x7, 0xf0, 0x4f, 0xff, 0xff, 0xff, - 0xf1, 0x3f, 0x72, 0x22, 0x22, 0x20, 0xe, 0xc0, - 0x0, 0x2, 0x0, 0x4, 0xfd, 0x87, 0xaf, 0x50, - 0x0, 0x3a, 0xef, 0xd6, 0x0, + 0x2, 0xf8, 0x1, 0xf5, 0xf0, 0x3c, 0x3, 0x83, + 0x40, 0x1c, 0x7f, 0xff, 0xc3, 0x40, 0x0, 0x3c, + 0x0, 0x1, 0xf9, 0xb4, 0x2, 0xfd, 0x0, /* U+0066 "f" */ - 0x0, 0x5d, 0xfc, 0x0, 0x2f, 0xb5, 0x70, 0x4, - 0xf3, 0x0, 0xc, 0xff, 0xff, 0xa0, 0x48, 0xf7, - 0x53, 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, - 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, 0x0, - 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, 0x0, 0x5f, - 0x30, 0x0, + 0x7, 0xf0, 0x39, 0x41, 0xc0, 0x3f, 0xf8, 0x6d, + 0x40, 0x70, 0x1, 0xc0, 0x7, 0x0, 0x1c, 0x0, + 0x70, 0x1, 0xc0, 0x7, 0x0, /* U+0067 "g" */ - 0x0, 0x3b, 0xff, 0xb2, 0xe9, 0x4, 0xfe, 0x87, - 0xcf, 0xf9, 0xe, 0xd1, 0x0, 0xa, 0xf9, 0x3f, - 0x60, 0x0, 0x1, 0xf9, 0x4f, 0x40, 0x0, 0x0, - 0xf9, 0x3f, 0x60, 0x0, 0x1, 0xf9, 0xe, 0xd0, - 0x0, 0x9, 0xf9, 0x4, 0xfd, 0x87, 0xcf, 0xf8, - 0x0, 0x3b, 0xff, 0xb3, 0xf7, 0x0, 0x0, 0x0, - 0x5, 0xf4, 0x9, 0xe9, 0x77, 0xaf, 0xb0, 0x1, - 0x7c, 0xff, 0xd8, 0x0, + 0x2, 0xf8, 0xe1, 0xf5, 0xbe, 0x3c, 0x2, 0xe3, + 0x40, 0xe, 0x74, 0x0, 0xe3, 0x40, 0xe, 0x3c, + 0x2, 0xe1, 0xf9, 0xfe, 0x2, 0xf8, 0xd0, 0x0, + 0x1d, 0x2e, 0x5b, 0x80, 0x7f, 0xe0, /* U+0068 "h" */ - 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, 0x0, - 0x0, 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf2, 0xbf, - 0xea, 0x10, 0x8f, 0xfb, 0x89, 0xfd, 0x8, 0xf8, - 0x0, 0x6, 0xf4, 0x8f, 0x10, 0x0, 0x1f, 0x78, - 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, - 0x88, 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, - 0xf, 0x88, 0xf0, 0x0, 0x0, 0xf8, + 0xb0, 0x0, 0x2c, 0x0, 0xb, 0x0, 0x2, 0xcb, + 0xe0, 0xbe, 0xaf, 0x2e, 0x1, 0xdb, 0x0, 0x36, + 0xc0, 0xe, 0xb0, 0x3, 0xac, 0x0, 0xeb, 0x0, + 0x3a, 0xc0, 0xe, /* U+0069 "i" */ - 0x9e, 0x1a, 0xf2, 0x0, 0x8, 0xf0, 0x8f, 0x8, - 0xf0, 0x8f, 0x8, 0xf0, 0x8f, 0x8, 0xf0, 0x8f, - 0x8, 0xf0, + 0xb2, 0xc0, 0x2c, 0xb2, 0xcb, 0x2c, 0xb2, 0xcb, + 0x2c, /* U+006A "j" */ - 0x0, 0x7, 0xe2, 0x0, 0x9, 0xf3, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, - 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, - 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x7, - 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x8, 0xf0, 0x18, - 0x6e, 0xc0, 0x3e, 0xfc, 0x20, + 0x1, 0xc0, 0x2c, 0x0, 0x0, 0x1c, 0x1, 0xc0, + 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, + 0xc0, 0x1c, 0x2, 0xc2, 0x7c, 0x3f, 0x0, /* U+006B "k" */ - 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, 0x0, - 0x0, 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, - 0x1d, 0xd1, 0x8f, 0x0, 0x1d, 0xe2, 0x8, 0xf0, - 0x1d, 0xe2, 0x0, 0x8f, 0x2d, 0xf3, 0x0, 0x8, - 0xfe, 0xff, 0x70, 0x0, 0x8f, 0xe2, 0xbf, 0x30, - 0x8, 0xf2, 0x1, 0xee, 0x10, 0x8f, 0x0, 0x3, - 0xfb, 0x8, 0xf0, 0x0, 0x7, 0xf7, + 0xb0, 0x0, 0x2c, 0x0, 0xb, 0x0, 0x2, 0xc0, + 0x3c, 0xb0, 0x3c, 0x2c, 0x3c, 0xb, 0x3c, 0x2, + 0xff, 0x40, 0xbc, 0xb0, 0x2c, 0xf, 0xb, 0x0, + 0xe2, 0xc0, 0x1d, /* U+006C "l" */ - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* U+006D "m" */ - 0x8e, 0x3c, 0xfe, 0x91, 0x3b, 0xfe, 0xa2, 0x8, - 0xff, 0x96, 0x9f, 0xcf, 0xc6, 0x8f, 0xd0, 0x8f, - 0x70, 0x0, 0x9f, 0xc0, 0x0, 0x5f, 0x58, 0xf1, - 0x0, 0x5, 0xf6, 0x0, 0x1, 0xf7, 0x8f, 0x0, - 0x0, 0x4f, 0x40, 0x0, 0xf, 0x88, 0xf0, 0x0, - 0x4, 0xf4, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, - 0x4f, 0x40, 0x0, 0xf, 0x88, 0xf0, 0x0, 0x4, - 0xf4, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0x4f, - 0x40, 0x0, 0xf, 0x80, + 0xb3, 0xf8, 0x2f, 0x82, 0xf9, 0xbf, 0xdb, 0xcb, + 0x40, 0xbc, 0x7, 0x6c, 0x1, 0xd0, 0xd, 0xb0, + 0x7, 0x40, 0x3a, 0xc0, 0x1d, 0x0, 0xeb, 0x0, + 0x74, 0x3, 0xac, 0x1, 0xd0, 0xe, 0xb0, 0x7, + 0x40, 0x38, /* U+006E "n" */ - 0x8e, 0x3b, 0xfe, 0xa1, 0x8, 0xff, 0xa6, 0x8f, - 0xd0, 0x8f, 0x80, 0x0, 0x6f, 0x48, 0xf1, 0x0, - 0x1, 0xf7, 0x8f, 0x0, 0x0, 0xf, 0x88, 0xf0, - 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, 0x88, - 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, - 0x80, + 0xb2, 0xf8, 0x2f, 0x9b, 0xcb, 0x80, 0x76, 0xc0, + 0xd, 0xb0, 0x3, 0xac, 0x0, 0xeb, 0x0, 0x3a, + 0xc0, 0xe, 0xb0, 0x3, 0x80, /* U+006F "o" */ - 0x0, 0x3b, 0xef, 0xc4, 0x0, 0x4, 0xfd, 0x87, - 0xcf, 0x60, 0xe, 0xd0, 0x0, 0xb, 0xf1, 0x3f, - 0x60, 0x0, 0x3, 0xf5, 0x4f, 0x30, 0x0, 0x1, - 0xf7, 0x3f, 0x60, 0x0, 0x3, 0xf5, 0xe, 0xd0, - 0x0, 0xb, 0xf1, 0x4, 0xfd, 0x77, 0xcf, 0x60, - 0x0, 0x3b, 0xef, 0xc4, 0x0, + 0x2, 0xfd, 0x1, 0xf9, 0xf4, 0x3c, 0x2, 0xc3, + 0x40, 0xd, 0x70, 0x0, 0xd3, 0x40, 0xd, 0x3c, + 0x2, 0xc1, 0xf5, 0xf4, 0x2, 0xfd, 0x0, /* U+0070 "p" */ - 0x8e, 0x3b, 0xfe, 0xb3, 0x0, 0x8f, 0xfb, 0x57, - 0xdf, 0x30, 0x8f, 0x90, 0x0, 0xd, 0xc0, 0x8f, - 0x10, 0x0, 0x7, 0xf1, 0x8f, 0x0, 0x0, 0x5, - 0xf3, 0x8f, 0x20, 0x0, 0x7, 0xf1, 0x8f, 0xa0, - 0x0, 0x1e, 0xd0, 0x8f, 0xec, 0x78, 0xef, 0x30, - 0x8f, 0x2b, 0xfe, 0xb3, 0x0, 0x8f, 0x0, 0x0, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x0, 0x0, 0x0, 0x0, + 0xb2, 0xf8, 0xb, 0xe5, 0xf0, 0xb8, 0x3, 0xcb, + 0x0, 0x1c, 0xb0, 0x1, 0xcb, 0x0, 0x1c, 0xb8, + 0x3, 0xcb, 0xf6, 0xf0, 0xb2, 0xf8, 0xb, 0x0, + 0x0, 0xb0, 0x0, 0xb, 0x0, 0x0, /* U+0071 "q" */ - 0x0, 0x3b, 0xff, 0xa2, 0xf7, 0x4, 0xfd, 0x87, - 0xde, 0xf7, 0xe, 0xd0, 0x0, 0xb, 0xf7, 0x3f, - 0x60, 0x0, 0x3, 0xf7, 0x4f, 0x30, 0x0, 0x1, - 0xf7, 0x3f, 0x60, 0x0, 0x3, 0xf7, 0xe, 0xd0, - 0x0, 0xb, 0xf7, 0x4, 0xfd, 0x77, 0xce, 0xf7, - 0x0, 0x3b, 0xff, 0xa3, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x0, 0x0, 0x1, 0xf7, + 0x2, 0xf8, 0xd1, 0xf5, 0xbd, 0x3c, 0x2, 0xd3, + 0x40, 0xd, 0x70, 0x0, 0xd3, 0x40, 0xd, 0x3c, + 0x2, 0xd1, 0xf5, 0xfd, 0x2, 0xf8, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, /* U+0072 "r" */ - 0x8e, 0x2b, 0xf0, 0x8f, 0xed, 0x90, 0x8f, 0xa0, - 0x0, 0x8f, 0x20, 0x0, 0x8f, 0x0, 0x0, 0x8f, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x8f, 0x0, 0x0, - 0x8f, 0x0, 0x0, + 0xb2, 0xcb, 0xf8, 0xb8, 0xb, 0x0, 0xb0, 0xb, + 0x0, 0xb0, 0xb, 0x0, 0xb0, 0x0, /* U+0073 "s" */ - 0x2, 0xae, 0xfd, 0x91, 0x1e, 0xd7, 0x69, 0xd0, - 0x4f, 0x30, 0x0, 0x0, 0x2f, 0xb4, 0x10, 0x0, - 0x6, 0xef, 0xfd, 0x60, 0x0, 0x1, 0x5b, 0xf5, - 0x1, 0x0, 0x0, 0xf7, 0x5f, 0xa7, 0x6b, 0xf3, - 0x19, 0xdf, 0xec, 0x40, + 0xb, 0xf8, 0x3d, 0x6c, 0x70, 0x0, 0x39, 0x0, + 0x1f, 0xf4, 0x0, 0x6d, 0x0, 0xd, 0x79, 0x6c, + 0x2f, 0xf4, /* U+0074 "t" */ - 0x5, 0xf3, 0x0, 0x0, 0x5f, 0x30, 0x0, 0xcf, - 0xff, 0xfa, 0x4, 0x8f, 0x75, 0x30, 0x5, 0xf3, - 0x0, 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, - 0x0, 0x5f, 0x30, 0x0, 0x4, 0xf4, 0x0, 0x0, - 0x1f, 0xc6, 0x80, 0x0, 0x5d, 0xfc, 0x10, + 0x1c, 0x0, 0x70, 0xf, 0xfe, 0x1b, 0x50, 0x1c, + 0x0, 0x70, 0x1, 0xc0, 0x7, 0x0, 0x1d, 0x0, + 0x3d, 0x80, 0x7f, 0x0, /* U+0075 "u" */ - 0xae, 0x0, 0x0, 0x2f, 0x5a, 0xe0, 0x0, 0x2, - 0xf5, 0xae, 0x0, 0x0, 0x2f, 0x5a, 0xe0, 0x0, - 0x2, 0xf5, 0xae, 0x0, 0x0, 0x2f, 0x59, 0xf0, - 0x0, 0x4, 0xf5, 0x6f, 0x30, 0x0, 0xaf, 0x51, - 0xee, 0x76, 0xbf, 0xf5, 0x2, 0xbe, 0xfb, 0x3f, - 0x50, + 0xb0, 0x3, 0x6c, 0x0, 0xdb, 0x0, 0x36, 0xc0, + 0xd, 0xb0, 0x3, 0x6c, 0x1, 0xd7, 0x0, 0xb4, + 0xf5, 0xbd, 0xb, 0xe3, 0x40, /* U+0076 "v" */ - 0xd, 0xc0, 0x0, 0x0, 0xcb, 0x6, 0xf2, 0x0, - 0x2, 0xf5, 0x0, 0xf9, 0x0, 0x9, 0xe0, 0x0, - 0x9e, 0x0, 0xf, 0x80, 0x0, 0x2f, 0x60, 0x6f, - 0x10, 0x0, 0xc, 0xc0, 0xcb, 0x0, 0x0, 0x5, - 0xf6, 0xf4, 0x0, 0x0, 0x0, 0xef, 0xd0, 0x0, - 0x0, 0x0, 0x8f, 0x70, 0x0, + 0x3c, 0x0, 0xe1, 0xc0, 0xd, 0xe, 0x2, 0xc0, + 0xb0, 0x38, 0x3, 0x47, 0x0, 0x3c, 0xe0, 0x1, + 0xdd, 0x0, 0xf, 0xc0, 0x0, 0xb4, 0x0, /* U+0077 "w" */ - 0xbb, 0x0, 0x0, 0x9f, 0x10, 0x0, 0x4f, 0x16, - 0xf1, 0x0, 0xe, 0xf6, 0x0, 0x9, 0xc0, 0xf, - 0x60, 0x5, 0xfc, 0xb0, 0x0, 0xf6, 0x0, 0xac, - 0x0, 0xab, 0x5f, 0x10, 0x5f, 0x10, 0x5, 0xf1, - 0xf, 0x50, 0xf7, 0xa, 0xb0, 0x0, 0xf, 0x76, - 0xf0, 0x9, 0xc0, 0xf5, 0x0, 0x0, 0xac, 0xba, - 0x0, 0x4f, 0x8f, 0x0, 0x0, 0x4, 0xff, 0x40, - 0x0, 0xef, 0xa0, 0x0, 0x0, 0xe, 0xe0, 0x0, - 0x8, 0xf4, 0x0, 0x0, + 0xa0, 0xb, 0x0, 0x71, 0xc0, 0x3d, 0x2, 0xc3, + 0x41, 0xfc, 0xd, 0xb, 0xa, 0x70, 0x70, 0x1c, + 0x34, 0xd2, 0x80, 0x35, 0xc2, 0xcd, 0x0, 0xba, + 0x7, 0xb0, 0x1, 0xf4, 0xf, 0x80, 0x3, 0xc0, + 0x2d, 0x0, /* U+0078 "x" */ - 0x4f, 0x70, 0x0, 0x9f, 0x20, 0x8f, 0x30, 0x5f, - 0x50, 0x0, 0xcd, 0x2e, 0x90, 0x0, 0x2, 0xff, - 0xd0, 0x0, 0x0, 0xa, 0xf6, 0x0, 0x0, 0x4, - 0xfd, 0xe1, 0x0, 0x1, 0xeb, 0xd, 0xc0, 0x0, - 0xbe, 0x10, 0x3f, 0x80, 0x6f, 0x40, 0x0, 0x7f, - 0x40, + 0x74, 0xb, 0xb, 0x7, 0x40, 0xf3, 0x80, 0xf, + 0xc0, 0x2, 0xd0, 0x1, 0xfc, 0x0, 0xe3, 0xc0, + 0xb0, 0x38, 0x74, 0x7, 0x40, /* U+0079 "y" */ - 0xd, 0xc0, 0x0, 0x0, 0xcb, 0x6, 0xf3, 0x0, - 0x2, 0xf4, 0x0, 0xea, 0x0, 0x9, 0xd0, 0x0, - 0x8f, 0x10, 0x1f, 0x70, 0x0, 0x1f, 0x70, 0x7f, - 0x10, 0x0, 0xa, 0xe0, 0xd9, 0x0, 0x0, 0x3, - 0xf9, 0xf2, 0x0, 0x0, 0x0, 0xcf, 0xb0, 0x0, - 0x0, 0x0, 0x6f, 0x40, 0x0, 0x0, 0x0, 0xad, - 0x0, 0x0, 0x1c, 0x79, 0xf5, 0x0, 0x0, 0x1a, - 0xee, 0x70, 0x0, 0x0, + 0x3c, 0x0, 0xe1, 0xc0, 0xd, 0xe, 0x2, 0xc0, + 0xb0, 0x34, 0x3, 0x47, 0x0, 0x2c, 0xe0, 0x0, + 0xec, 0x0, 0xf, 0x80, 0x0, 0x74, 0x0, 0xb, + 0x0, 0x36, 0xd0, 0x2, 0xf4, 0x0, /* U+007A "z" */ - 0x4f, 0xff, 0xff, 0xf9, 0x15, 0x55, 0x5b, 0xf4, - 0x0, 0x0, 0x4f, 0x80, 0x0, 0x1, 0xec, 0x0, - 0x0, 0xb, 0xe1, 0x0, 0x0, 0x8f, 0x40, 0x0, - 0x4, 0xf7, 0x0, 0x0, 0x1e, 0xe5, 0x55, 0x53, - 0x5f, 0xff, 0xff, 0xfc, + 0x7f, 0xfe, 0x15, 0x6d, 0x0, 0x78, 0x0, 0xf0, + 0x2, 0xc0, 0xb, 0x40, 0x1d, 0x0, 0x3d, 0x54, + 0x7f, 0xff, /* U+007B "{" */ - 0x0, 0x2c, 0xf5, 0x0, 0xaf, 0x61, 0x0, 0xcc, - 0x0, 0x0, 0xdb, 0x0, 0x0, 0xdb, 0x0, 0x0, - 0xdb, 0x0, 0x2, 0xea, 0x0, 0x1f, 0xf4, 0x0, - 0x5, 0xfa, 0x0, 0x0, 0xdb, 0x0, 0x0, 0xdb, - 0x0, 0x0, 0xdb, 0x0, 0x0, 0xcc, 0x0, 0x0, - 0xaf, 0x61, 0x0, 0x2c, 0xf5, + 0x3, 0xd0, 0xb4, 0xf, 0x0, 0xe0, 0xe, 0x0, + 0xe0, 0xe, 0x3, 0xd0, 0x1e, 0x0, 0xe0, 0xe, + 0x0, 0xe0, 0xf, 0x0, 0xb4, 0x3, 0xd0, /* U+007C "|" */ - 0x5f, 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x15, - 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, - 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x10, + 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, + 0x1c, 0x71, 0xc7, 0x0, /* U+007D "}" */ - 0xbe, 0x80, 0x3, 0xaf, 0x40, 0x1, 0xf6, 0x0, - 0x1f, 0x70, 0x1, 0xf7, 0x0, 0x1f, 0x70, 0x0, - 0xf9, 0x0, 0xa, 0xfb, 0x0, 0xfb, 0x20, 0x1f, - 0x70, 0x1, 0xf7, 0x0, 0x1f, 0x70, 0x1, 0xf6, - 0x3, 0xaf, 0x40, 0xbe, 0x90, 0x0, + 0xb8, 0xb, 0x40, 0xd0, 0x34, 0xd, 0x3, 0x40, + 0xe0, 0x2e, 0xe, 0x3, 0x40, 0xd0, 0x34, 0xd, + 0xb, 0x4b, 0x80, /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0xe4, 0x0, - 0xb5, 0xc, 0x86, 0xf5, 0x1e, 0x20, 0xf0, 0x3, - 0xef, 0x90, 0x2, 0x0, 0x0, 0x10, 0x0, - - /* U+00B0 "°" */ - 0x2, 0xce, 0x90, 0xd, 0x40, 0x89, 0x3b, 0x0, - 0xe, 0x3b, 0x0, 0xe, 0xd, 0x40, 0x89, 0x2, - 0xce, 0x90, - - /* U+2022 "•" */ - 0x0, 0x8, 0xf8, 0xef, 0xe7, 0xf7, - - /* U+F001 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xdc, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xff, 0xff, - 0x0, 0x0, 0x3, 0x8d, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xea, 0x51, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x83, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x2b, 0xff, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xdf, 0xff, 0xff, - 0x2b, 0xff, 0xff, 0x0, 0x0, 0xdf, 0xff, 0xfd, - 0xdf, 0xff, 0xff, 0x0, 0x0, 0x2b, 0xff, 0xb2, - 0xdf, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2b, 0xff, 0xb2, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F008 "" */ - 0xd0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xd, - 0xff, 0xff, 0xc8, 0x88, 0x88, 0x8c, 0xff, 0xff, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x8, 0xff, 0xff, - 0xf0, 0xf, 0xec, 0xcc, 0xcc, 0xce, 0xf0, 0xf, - 0xf0, 0xf, 0xec, 0xcc, 0xcc, 0xce, 0xf0, 0xf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x8, 0xff, 0xff, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xff, 0xff, 0xc8, 0x88, 0x88, 0x8c, 0xff, 0xff, - 0xd0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xd, - - /* U+F00B "" */ - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F00C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xc0, - 0x1b, 0xa0, 0x0, 0x0, 0xb, 0xff, 0xfc, 0x0, - 0xcf, 0xfb, 0x0, 0x0, 0xbf, 0xff, 0xc0, 0x0, - 0xbf, 0xff, 0xb0, 0xb, 0xff, 0xfc, 0x0, 0x0, - 0xc, 0xff, 0xfb, 0xbf, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0xcf, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, - 0x0, 0xc, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xb0, 0x0, 0x0, 0x0, 0x0, - - /* U+F00D "" */ - 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xfc, 0x10, - 0x0, 0x1c, 0xf8, 0xff, 0xfc, 0x10, 0x1c, 0xff, - 0xf5, 0xff, 0xfc, 0x2c, 0xff, 0xf5, 0x5, 0xff, - 0xff, 0xff, 0xf5, 0x0, 0x5, 0xff, 0xff, 0xf5, - 0x0, 0x0, 0x1d, 0xff, 0xfd, 0x10, 0x0, 0x1c, - 0xff, 0xff, 0xfc, 0x10, 0x1c, 0xff, 0xf9, 0xff, - 0xfc, 0x1c, 0xff, 0xf5, 0x5, 0xff, 0xfc, 0xdf, - 0xf5, 0x0, 0x5, 0xff, 0xd1, 0xa4, 0x0, 0x0, - 0x4, 0xa1, - - /* U+F011 "" */ - 0x0, 0x0, 0x0, 0x4f, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x10, 0x6f, 0xf1, 0x3, 0x10, 0x0, - 0x0, 0x5f, 0xd0, 0x6f, 0xf1, 0x3f, 0xd1, 0x0, - 0x3, 0xff, 0xf1, 0x6f, 0xf1, 0x5f, 0xfd, 0x0, - 0xd, 0xff, 0x40, 0x6f, 0xf1, 0x9, 0xff, 0x70, - 0x4f, 0xf7, 0x0, 0x6f, 0xf1, 0x0, 0xcf, 0xe0, - 0x9f, 0xf0, 0x0, 0x6f, 0xf1, 0x0, 0x5f, 0xf3, - 0xbf, 0xc0, 0x0, 0x6f, 0xf1, 0x0, 0x2f, 0xf5, - 0xbf, 0xc0, 0x0, 0x4f, 0xe0, 0x0, 0x1f, 0xf6, - 0xaf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf4, - 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xf0, - 0xf, 0xfe, 0x10, 0x0, 0x0, 0x5, 0xff, 0xa0, - 0x6, 0xff, 0xd3, 0x0, 0x0, 0x7f, 0xff, 0x20, - 0x0, 0x9f, 0xff, 0xda, 0xbe, 0xff, 0xf4, 0x0, - 0x0, 0x6, 0xff, 0xff, 0xff, 0xfd, 0x30, 0x0, - 0x0, 0x0, 0x17, 0xbd, 0xca, 0x50, 0x0, 0x0, - - /* U+F013 "" */ - 0x0, 0x0, 0x0, 0x8b, 0xb8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x30, 0x6, 0xff, 0xff, 0x60, 0x3, 0x0, - 0x4, 0xfd, 0xdf, 0xff, 0xff, 0xfd, 0xef, 0x40, - 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x4f, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xf4, - 0x8, 0xff, 0xff, 0x20, 0x2, 0xff, 0xff, 0x80, - 0x0, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0x0, - 0x0, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0x0, - 0x8, 0xff, 0xff, 0x20, 0x2, 0xff, 0xff, 0x80, - 0x4f, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xf4, - 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x4, 0xfe, 0xdf, 0xff, 0xff, 0xfd, 0xdf, 0x40, - 0x0, 0x30, 0x6, 0xff, 0xff, 0x60, 0x3, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x8b, 0xb8, 0x0, 0x0, 0x0, - - /* U+F015 "" */ - 0x0, 0x0, 0x0, 0x3, 0xdd, 0x30, 0x3f, 0xf3, - 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xf5, 0x4f, - 0xf4, 0x0, 0x0, 0x0, 0x9, 0xff, 0x99, 0xff, - 0xbf, 0xf4, 0x0, 0x0, 0x1, 0xbf, 0xf6, 0x22, - 0x6f, 0xff, 0xf4, 0x0, 0x0, 0x2d, 0xfe, 0x35, - 0xff, 0x53, 0xef, 0xf4, 0x0, 0x4, 0xff, 0xc1, - 0x8f, 0xff, 0xf8, 0x2d, 0xfe, 0x40, 0x7f, 0xfa, - 0x1a, 0xff, 0xff, 0xff, 0xa1, 0xaf, 0xf7, 0xcf, - 0x82, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0x28, 0xfc, - 0x14, 0xe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x41, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf9, 0x0, 0x8f, - 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf8, 0x0, - 0x8f, 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf8, - 0x0, 0x8f, 0xff, 0xf0, 0x0, 0x0, 0xe, 0xff, - 0xf6, 0x0, 0x6f, 0xff, 0xe0, 0x0, - - /* U+F019 "" */ - 0x0, 0x0, 0x0, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfb, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xb0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0xfc, 0x1b, 0xb1, 0xcf, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xc2, 0x2c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F01C "" */ - 0x0, 0x4, 0xef, 0xff, 0xff, 0xff, 0xfe, 0x40, - 0x0, 0x0, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe1, 0x0, 0x0, 0xaf, 0xb0, 0x0, 0x0, 0x0, - 0xb, 0xfa, 0x0, 0x5, 0xff, 0x10, 0x0, 0x0, - 0x0, 0x1, 0xff, 0x50, 0x1e, 0xf6, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6f, 0xe1, 0xaf, 0xb0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xfa, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, - - /* U+F021 "" */ - 0x0, 0x0, 0x6, 0xbd, 0xda, 0x50, 0x2, 0xff, - 0x0, 0x5, 0xef, 0xff, 0xff, 0xfe, 0x42, 0xff, - 0x0, 0x7f, 0xff, 0xa7, 0x7b, 0xff, 0xf9, 0xff, - 0x5, 0xff, 0xc1, 0x0, 0x0, 0x2c, 0xff, 0xff, - 0xe, 0xfc, 0x0, 0x0, 0x2, 0x22, 0xdf, 0xff, - 0x5f, 0xf2, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0x8f, 0xb0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0xb, 0xf8, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x2f, 0xf4, - 0xff, 0xfd, 0x22, 0x20, 0x0, 0x0, 0xcf, 0xe0, - 0xff, 0xff, 0xc2, 0x0, 0x0, 0x2c, 0xff, 0x40, - 0xff, 0x9f, 0xff, 0xb7, 0x6a, 0xff, 0xf7, 0x0, - 0xff, 0x24, 0xdf, 0xff, 0xff, 0xfe, 0x50, 0x0, - 0xff, 0x20, 0x5, 0xac, 0xdb, 0x60, 0x0, 0x0, - - /* U+F026 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8d, - 0x0, 0x0, 0x8, 0xff, 0x0, 0x0, 0x8f, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x8f, 0xff, 0x0, 0x0, 0x8, 0xff, - 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, 0x0, 0x0, - - /* U+F027 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x8d, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0x0, 0x0, - 0xcf, 0xff, 0xff, 0xff, 0x1, 0x50, 0xff, 0xff, - 0xff, 0xff, 0x6, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x0, 0xae, - 0xff, 0xff, 0xff, 0xff, 0x5, 0xf8, 0xdf, 0xff, - 0xff, 0xff, 0x2, 0x60, 0x0, 0x0, 0x9f, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x9e, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+F028 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xd2, 0x0, 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, - 0x3, 0xee, 0x10, 0x0, 0x0, 0x8, 0xff, 0x0, - 0xa, 0xb1, 0x2f, 0xb0, 0x0, 0x0, 0x8f, 0xff, - 0x0, 0x5, 0xfc, 0x7, 0xf4, 0xdf, 0xff, 0xff, - 0xff, 0x2, 0x50, 0x5f, 0x60, 0xf9, 0xff, 0xff, - 0xff, 0xff, 0x6, 0xf7, 0xd, 0xc0, 0xbd, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xae, 0x9, 0xf0, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xae, 0x9, 0xf0, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0x6, 0xf7, 0xd, - 0xc0, 0xad, 0xdf, 0xff, 0xff, 0xff, 0x2, 0x50, - 0x5f, 0x60, 0xe9, 0x0, 0x0, 0x8f, 0xff, 0x0, - 0x5, 0xfc, 0x6, 0xf4, 0x0, 0x0, 0x8, 0xff, - 0x0, 0xa, 0xb1, 0x2f, 0xb0, 0x0, 0x0, 0x0, - 0x8d, 0x0, 0x0, 0x2, 0xee, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xd2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x10, 0x0, - - /* U+F03E "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x20, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0xc, 0xff, 0xff, 0xee, 0xff, 0xff, - 0xff, 0x20, 0x2f, 0xff, 0xfe, 0x22, 0xef, 0xff, - 0xff, 0xfc, 0xff, 0xff, 0xe2, 0x0, 0x2e, 0xff, - 0xff, 0xfe, 0x4e, 0xfe, 0x20, 0x0, 0x2, 0xff, - 0xff, 0xe2, 0x2, 0xc2, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F043 "" */ - 0x0, 0x0, 0x4e, 0x40, 0x0, 0x0, 0x0, 0xb, - 0xfb, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf1, 0x0, - 0x0, 0x0, 0x9f, 0xff, 0x90, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0x30, 0x0, 0xc, 0xff, 0xff, 0xfc, - 0x0, 0x7, 0xff, 0xff, 0xff, 0xf8, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xf2, 0x9f, 0xff, 0xff, 0xff, - 0xff, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0x2f, 0xff, 0xff, 0xff, 0xfe, 0xf2, 0xbf, 0xff, - 0xff, 0xfe, 0x9f, 0xa1, 0xbf, 0xff, 0xff, 0x92, - 0xff, 0xa2, 0x2f, 0xff, 0xf2, 0x4, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0x2, 0x9e, 0xfe, 0x92, 0x0, - - /* U+F048 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x30, 0x0, - 0x1, 0xcc, 0xff, 0x40, 0x0, 0x2d, 0xff, 0xff, - 0x40, 0x3, 0xef, 0xff, 0xff, 0x40, 0x3f, 0xff, - 0xff, 0xff, 0x44, 0xff, 0xff, 0xff, 0xff, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0x45, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x4f, 0xff, 0xff, 0xff, 0x40, 0x3, 0xef, - 0xff, 0xff, 0x40, 0x0, 0x2e, 0xff, 0xff, 0x30, - 0x0, 0x1, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F04B "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x70, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xfd, - 0x40, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfa, - 0x10, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xb2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd5, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xf7, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfa, 0x10, - 0x0, 0x0, 0xff, 0xff, 0xfd, 0x40, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, - 0x8e, 0xa1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F04C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0xff, 0xf8, 0x0, 0x8f, 0xff, 0xf8, 0xff, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xf7, 0x0, 0x7f, 0xff, - 0xf7, - - /* U+F04D "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, - - /* U+F051 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xcc, 0x10, 0x0, - 0x3, 0xff, 0xff, 0xd2, 0x0, 0x4, 0xff, 0xff, - 0xfe, 0x30, 0x4, 0xff, 0xff, 0xff, 0xf4, 0x4, - 0xff, 0xff, 0xff, 0xff, 0x54, 0xff, 0xff, 0xff, - 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0xff, 0xff, 0xff, 0xff, 0x44, 0xff, 0xff, - 0xff, 0xf3, 0x4, 0xff, 0xff, 0xfe, 0x30, 0x4, - 0xff, 0xff, 0xd2, 0x0, 0x4, 0xff, 0xcc, 0x10, - 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F052 "" */ - 0x0, 0x0, 0x0, 0x2d, 0xd2, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xef, 0xfe, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x1d, 0xff, 0xff, 0xd1, 0x0, 0x0, - 0x0, 0x0, 0xcf, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, - 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - - /* U+F053 "" */ - 0x0, 0x0, 0x0, 0x1a, 0x40, 0x0, 0x0, 0x1, - 0xdf, 0xf0, 0x0, 0x0, 0x1d, 0xff, 0xa0, 0x0, - 0x1, 0xdf, 0xfa, 0x0, 0x0, 0x1d, 0xff, 0xa0, - 0x0, 0x1, 0xdf, 0xfa, 0x0, 0x0, 0xc, 0xff, - 0xa0, 0x0, 0x0, 0xd, 0xff, 0x80, 0x0, 0x0, - 0x1, 0xdf, 0xf8, 0x0, 0x0, 0x0, 0x1d, 0xff, - 0x80, 0x0, 0x0, 0x1, 0xdf, 0xf8, 0x0, 0x0, - 0x0, 0x1d, 0xff, 0x80, 0x0, 0x0, 0x1, 0xdf, - 0xf0, 0x0, 0x0, 0x0, 0x1b, 0x50, - - /* U+F054 "" */ - 0x4, 0xa1, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x10, - 0x0, 0x0, 0xa, 0xff, 0xd1, 0x0, 0x0, 0x0, - 0xaf, 0xfd, 0x10, 0x0, 0x0, 0xa, 0xff, 0xd1, - 0x0, 0x0, 0x0, 0xaf, 0xfd, 0x10, 0x0, 0x0, - 0xa, 0xff, 0xc0, 0x0, 0x0, 0x8, 0xff, 0xd0, - 0x0, 0x0, 0x8f, 0xfd, 0x10, 0x0, 0x8, 0xff, - 0xd1, 0x0, 0x0, 0x8f, 0xfd, 0x10, 0x0, 0x8, - 0xff, 0xd1, 0x0, 0x0, 0xf, 0xfd, 0x10, 0x0, - 0x0, 0x5, 0xb1, 0x0, 0x0, 0x0, - - /* U+F067 "" */ - 0x0, 0x0, 0x4, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x80, 0x0, 0x0, 0x48, 0x88, 0x8c, 0xff, 0xc8, - 0x88, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x48, 0x88, 0x8c, 0xff, 0xc8, 0x88, 0x84, 0x0, - 0x0, 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0x40, - 0x0, 0x0, - - /* U+F068 "" */ - 0x14, 0x44, 0x44, 0x44, 0x44, 0x44, 0x41, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xb7, - - /* U+F06E "" */ - 0x0, 0x0, 0x5, 0xad, 0xff, 0xda, 0x50, 0x0, - 0x0, 0x0, 0x4, 0xdf, 0xfc, 0x88, 0xcf, 0xfd, - 0x40, 0x0, 0x0, 0x7f, 0xfe, 0x40, 0x0, 0x4, - 0xef, 0xf7, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x9e, - 0x80, 0x4f, 0xff, 0x70, 0x4f, 0xff, 0xc0, 0x0, - 0xaf, 0xf8, 0xc, 0xff, 0xf4, 0xdf, 0xff, 0x80, - 0x9a, 0xff, 0xfe, 0x8, 0xff, 0xfd, 0xdf, 0xff, - 0x80, 0xef, 0xff, 0xfe, 0x8, 0xff, 0xfd, 0x4f, - 0xff, 0xc0, 0x8f, 0xff, 0xf8, 0xc, 0xff, 0xf4, - 0x7, 0xff, 0xf4, 0x8, 0xee, 0x80, 0x4f, 0xff, - 0x70, 0x0, 0x7f, 0xfe, 0x40, 0x0, 0x4, 0xef, - 0xf8, 0x0, 0x0, 0x4, 0xdf, 0xfc, 0x88, 0xcf, - 0xfd, 0x40, 0x0, 0x0, 0x0, 0x5, 0xad, 0xff, - 0xda, 0x50, 0x0, 0x0, - - /* U+F070 "" */ - 0x8c, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xdf, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1b, 0xff, 0x80, 0x49, - 0xdf, 0xfd, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xd8, 0x8c, 0xff, 0xd4, 0x0, 0x0, - 0x0, 0x4, 0xef, 0xf8, 0x0, 0x0, 0x4e, 0xff, - 0x70, 0x0, 0x0, 0x0, 0x1c, 0xff, 0x69, 0xe8, - 0x4, 0xff, 0xf7, 0x0, 0x4, 0xe3, 0x0, 0x9f, - 0xfe, 0xff, 0x80, 0xcf, 0xff, 0x40, 0xd, 0xff, - 0x70, 0x5, 0xff, 0xff, 0xe0, 0x8f, 0xff, 0xd0, - 0xd, 0xff, 0xf7, 0x0, 0x2d, 0xff, 0xe0, 0x8f, - 0xff, 0xd0, 0x4, 0xff, 0xfc, 0x0, 0x0, 0xaf, - 0xf8, 0xcf, 0xff, 0x30, 0x0, 0x7f, 0xff, 0x40, - 0x0, 0x6, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x8, - 0xff, 0xf4, 0x0, 0x0, 0x3e, 0xff, 0xa0, 0x0, - 0x0, 0x0, 0x4d, 0xff, 0xc8, 0x82, 0x1, 0xbf, - 0xf7, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xdf, 0xfc, - 0x10, 0x8, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4e, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xc8, - - /* U+F071 "" */ - 0x0, 0x0, 0x0, 0x0, 0x2d, 0xd2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xd, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf7, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xd8, 0x8d, - 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, - 0xa0, 0xa, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xb0, 0xb, 0xff, 0xf3, 0x0, 0x0, - 0x0, 0x0, 0xcf, 0xff, 0xc0, 0xc, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xd0, 0xd, - 0xff, 0xff, 0x50, 0x0, 0x0, 0xe, 0xff, 0xff, - 0xf9, 0x9f, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x8f, - 0xff, 0xff, 0xe2, 0x2e, 0xff, 0xff, 0xf8, 0x0, - 0x2, 0xff, 0xff, 0xff, 0x90, 0x9, 0xff, 0xff, - 0xff, 0x10, 0xa, 0xff, 0xff, 0xff, 0xe3, 0x3e, - 0xff, 0xff, 0xff, 0xa0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+F074 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, - 0xff, 0xff, 0x70, 0x0, 0x7, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xf6, 0x0, 0x6f, 0xff, 0xff, 0xfd, - 0x78, 0x8e, 0xff, 0x15, 0xff, 0xe8, 0xff, 0xe2, - 0x0, 0x2, 0xe5, 0x4f, 0xfe, 0x20, 0xfe, 0x20, - 0x0, 0x0, 0x13, 0xff, 0xf3, 0x0, 0x52, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0x31, 0x0, 0x52, 0x0, - 0x0, 0x2, 0xef, 0xf4, 0x5e, 0x20, 0xfe, 0x20, - 0x78, 0x8e, 0xff, 0x51, 0xff, 0xe8, 0xff, 0xe2, - 0xff, 0xff, 0xf6, 0x0, 0x6f, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0x70, 0x0, 0x7, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F077 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xdd, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x1d, 0xff, 0xd1, 0x0, 0x0, 0x0, 0x1, 0xdf, - 0xff, 0xfd, 0x10, 0x0, 0x0, 0x1d, 0xff, 0x99, - 0xff, 0xd1, 0x0, 0x1, 0xdf, 0xf9, 0x0, 0x9f, - 0xfd, 0x10, 0x1d, 0xff, 0x90, 0x0, 0x9, 0xff, - 0xd1, 0xbf, 0xf9, 0x0, 0x0, 0x0, 0x9f, 0xfb, - 0x5f, 0x90, 0x0, 0x0, 0x0, 0x9, 0xf5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F078 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, - 0x90, 0x0, 0x0, 0x0, 0x9, 0xf5, 0xbf, 0xf9, - 0x0, 0x0, 0x0, 0x9f, 0xfb, 0x1d, 0xff, 0x90, - 0x0, 0x9, 0xff, 0xd1, 0x1, 0xdf, 0xf9, 0x0, - 0x9f, 0xfd, 0x10, 0x0, 0x1d, 0xff, 0x99, 0xff, - 0xd1, 0x0, 0x0, 0x1, 0xdf, 0xff, 0xfd, 0x10, - 0x0, 0x0, 0x0, 0x1d, 0xff, 0xd1, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xdd, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F079 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1d, 0xd1, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xdf, 0xfd, 0x10, - 0xef, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x1d, 0xff, - 0xff, 0xd1, 0xaf, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0xcf, 0xcf, 0xfc, 0xfc, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x6b, 0x1f, 0xf1, 0xb6, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x6b, 0x1f, - 0xf1, 0xb6, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xcf, 0xcf, 0xfc, 0xfc, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xfa, 0x1d, 0xff, 0xff, 0xd1, 0x0, 0xd, - 0xff, 0xff, 0xff, 0xfe, 0x1, 0xdf, 0xfd, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, - 0xd1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+F07B "" */ - 0x8f, 0xff, 0xff, 0xe2, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xfe, 0x20, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F093 "" */ - 0x0, 0x0, 0x0, 0xb, 0xb0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xb0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfb, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0xf0, 0xdf, 0xfd, 0xf, 0xff, 0xfd, - 0xff, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F095 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xea, - 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xef, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6f, 0xff, 0x30, 0x0, 0x0, 0x2, - 0x0, 0x0, 0x4f, 0xff, 0x90, 0x0, 0x2, 0x8f, - 0xf3, 0x0, 0x6f, 0xff, 0xd0, 0x0, 0xa, 0xff, - 0xff, 0xe4, 0xbf, 0xff, 0xd1, 0x0, 0x0, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xd1, 0x0, 0x0, 0xa, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x6f, 0xff, 0xff, 0xfb, 0x30, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xdb, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F0C4 "" */ - 0x8, 0xee, 0x80, 0x0, 0x0, 0x6, 0x61, 0x8, - 0xff, 0xff, 0x80, 0x0, 0x2d, 0xff, 0xd0, 0xef, - 0x33, 0xfe, 0x0, 0x2e, 0xff, 0xf3, 0xe, 0xf3, - 0x3f, 0xe0, 0x2e, 0xff, 0xf3, 0x0, 0x8f, 0xff, - 0xff, 0x6e, 0xff, 0xf3, 0x0, 0x0, 0x8e, 0xff, - 0xff, 0xff, 0xf3, 0x0, 0x0, 0x0, 0x2, 0xef, - 0xff, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x2e, 0xff, - 0xff, 0x30, 0x0, 0x0, 0x8, 0xef, 0xff, 0xff, - 0xff, 0x30, 0x0, 0x8, 0xff, 0xff, 0xf6, 0xef, - 0xff, 0x30, 0x0, 0xef, 0x33, 0xfe, 0x2, 0xef, - 0xff, 0x30, 0xe, 0xf3, 0x3f, 0xe0, 0x2, 0xef, - 0xff, 0x30, 0x8f, 0xff, 0xf8, 0x0, 0x2, 0xdf, - 0xfd, 0x0, 0x8e, 0xe8, 0x0, 0x0, 0x0, 0x66, - 0x10, - - /* U+F0C5 "" */ - 0x0, 0x0, 0xdf, 0xff, 0xff, 0xd, 0x20, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xf, 0xe2, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xf, 0xfd, 0xdf, 0xf0, 0xff, - 0xff, 0xff, 0x20, 0x0, 0xff, 0xf0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xdf, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xf9, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - - /* U+F0C7 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x20, 0xff, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xe2, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xfc, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x11, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfb, - 0x11, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, - - /* U+F0C9 "" */ - 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x12, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x12, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, - - /* U+F0E0 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, - 0xd2, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x2d, - 0xff, 0x62, 0xcf, 0xff, 0xff, 0xfc, 0x26, 0xff, - 0xff, 0xfa, 0x18, 0xff, 0xff, 0x81, 0xaf, 0xff, - 0xff, 0xff, 0xe3, 0x4d, 0xd4, 0x3e, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x81, 0x18, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F0E7 "" */ - 0x0, 0xdf, 0xff, 0xfd, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf7, - 0x0, 0x0, 0x6, 0xff, 0xff, 0xf2, 0x0, 0x0, - 0x8, 0xff, 0xff, 0xd0, 0x0, 0x0, 0xa, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0xc, 0xff, 0xff, 0xff, - 0xff, 0xa0, 0xe, 0xff, 0xff, 0xff, 0xff, 0x20, - 0xd, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0xa, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xe, 0xff, - 0x50, 0x0, 0x0, 0x0, 0x2f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, - 0x9f, 0xa0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x10, - 0x0, 0x0, 0x0, 0x0, 0xd7, 0x0, 0x0, 0x0, - - /* U+F0EA "" */ - 0x0, 0x4, 0xee, 0x40, 0x0, 0x0, 0x0, 0xdf, - 0xff, 0x99, 0xff, 0xfd, 0x0, 0x0, 0xff, 0xff, - 0x99, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x90, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xd, 0xff, 0xff, - 0xd, 0x20, 0xff, 0xff, 0xf, 0xff, 0xff, 0xf, - 0xe2, 0xff, 0xff, 0xf, 0xff, 0xff, 0xf, 0xfd, - 0xff, 0xff, 0xf, 0xff, 0xff, 0x20, 0x0, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xfd, - - /* U+F0F3 "" */ - 0x0, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0x30, 0x0, 0x0, 0x0, 0x1, - 0xbf, 0xff, 0xfc, 0x20, 0x0, 0x0, 0x1e, 0xff, - 0xff, 0xff, 0xe1, 0x0, 0x0, 0x9f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xef, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe1, 0xcf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xcf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x4, 0xee, 0x40, 0x0, 0x0, - - /* U+F11C "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xf0, 0xf, 0x0, 0xf0, - 0xf, 0x0, 0xff, 0xff, 0x0, 0xf0, 0xf, 0x0, - 0xf0, 0xf, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x8, - 0x80, 0x88, 0x8, 0x80, 0x8f, 0xff, 0xff, 0xf8, - 0x8, 0x80, 0x88, 0x8, 0x80, 0x8f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xf, 0x0, - 0xff, 0xff, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, - - /* U+F124 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xaf, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - 0xcf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x6, - 0xdf, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x17, - 0xef, 0xff, 0xff, 0xff, 0x30, 0x0, 0x0, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x2a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, - 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf2, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x8f, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F15B "" */ - 0xdf, 0xff, 0xff, 0xf0, 0xd2, 0x0, 0xff, 0xff, - 0xff, 0xf0, 0xfe, 0x20, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xe2, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F1EB "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9c, 0xef, 0xfe, - 0xc9, 0x40, 0x0, 0x0, 0x0, 0x7, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x70, 0x0, 0x4, 0xdf, - 0xff, 0xfc, 0xa8, 0x8a, 0xcf, 0xff, 0xfd, 0x40, - 0x6f, 0xff, 0xd5, 0x0, 0x0, 0x0, 0x0, 0x5d, - 0xff, 0xf6, 0xcf, 0xf6, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6f, 0xfc, 0x1a, 0x30, 0x0, 0x5a, - 0xdf, 0xfd, 0xa5, 0x0, 0x3, 0xa1, 0x0, 0x0, - 0x4d, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x0, 0x0, - 0x0, 0x5, 0xff, 0xfe, 0xa8, 0x8a, 0xef, 0xff, - 0x50, 0x0, 0x0, 0x1, 0xdf, 0x70, 0x0, 0x0, - 0x7, 0xfd, 0x10, 0x0, 0x0, 0x0, 0x12, 0x0, - 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4e, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xef, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4e, 0xe4, 0x0, 0x0, 0x0, 0x0, - - /* U+F240 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F241 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F242 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F243 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F244 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F287 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xfd, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xcf, 0xff, 0xf5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb9, 0x29, 0xfe, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x10, 0x2, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xdf, 0x80, 0xa, - 0x90, 0x0, 0x0, 0x0, 0x3, 0x70, 0x0, 0xdf, - 0xff, 0x77, 0xf7, 0x55, 0x55, 0x55, 0x55, 0x8f, - 0xd3, 0xf, 0xff, 0xfd, 0xcc, 0xdf, 0xdc, 0xcc, - 0xcc, 0xcd, 0xff, 0xb0, 0x8f, 0xfe, 0x10, 0x0, - 0xaa, 0x0, 0x0, 0x0, 0x4d, 0x40, 0x0, 0x46, - 0x10, 0x0, 0x1, 0xf2, 0x2, 0x33, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xb1, 0xcf, - 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xa, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf9, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x22, - 0x0, 0x0, 0x0, - - /* U+F293 "" */ - 0x0, 0x18, 0xdf, 0xfd, 0x92, 0x0, 0x2, 0xef, - 0xfb, 0xef, 0xff, 0x30, 0xd, 0xff, 0xfa, 0x2e, - 0xff, 0xe0, 0x4f, 0xff, 0xfa, 0x3, 0xff, 0xf5, - 0x9f, 0xfa, 0xfa, 0x35, 0x4f, 0xfa, 0xcf, 0xc0, - 0x8a, 0x3d, 0xb, 0xfd, 0xef, 0xfb, 0x3, 0x12, - 0x8f, 0xfe, 0xff, 0xff, 0xb0, 0x6, 0xff, 0xff, - 0xff, 0xff, 0xd1, 0x8, 0xff, 0xff, 0xef, 0xfd, - 0x11, 0x10, 0x9f, 0xff, 0xdf, 0xd1, 0x59, 0x3b, - 0xb, 0xfd, 0xaf, 0xd7, 0xfa, 0x38, 0x1d, 0xfb, - 0x5f, 0xff, 0xfa, 0x1, 0xdf, 0xf7, 0xd, 0xff, - 0xfa, 0x1d, 0xff, 0xf1, 0x3, 0xef, 0xfc, 0xdf, - 0xff, 0x50, 0x0, 0x18, 0xdf, 0xfe, 0xa3, 0x0, - - /* U+F2ED "" */ - 0x0, 0x0, 0x7f, 0xff, 0xf7, 0x0, 0x0, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0xf, 0xf9, 0x9f, 0x99, 0xf9, 0x9f, - 0xf0, 0xf, 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, - 0xf, 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, - 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, - 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, 0x8f, - 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, 0x8f, 0x88, - 0xf8, 0x8f, 0xf0, 0xf, 0xf9, 0x9f, 0x99, 0xf9, - 0x9f, 0xf0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+F304 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xa0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, - 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x8a, 0x1d, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xfa, - 0x1d, 0xff, 0x70, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xfa, 0x1d, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x6f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xdf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xe, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xde, 0xdb, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F55A "" */ - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe4, 0x0, 0x1, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x1d, 0xff, 0xff, - 0xfa, 0xef, 0xfe, 0xaf, 0xff, 0xff, 0x1, 0xdf, - 0xff, 0xff, 0xa0, 0x2e, 0xe2, 0xa, 0xff, 0xff, - 0x1d, 0xff, 0xff, 0xff, 0xe2, 0x2, 0x20, 0x2e, - 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfe, 0x20, - 0x2, 0xef, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, - 0xfe, 0x20, 0x2, 0xef, 0xff, 0xff, 0x1d, 0xff, - 0xff, 0xff, 0xe2, 0x2, 0x20, 0x2e, 0xff, 0xff, - 0x1, 0xdf, 0xff, 0xff, 0xa0, 0x2e, 0xe2, 0xa, - 0xff, 0xff, 0x0, 0x1d, 0xff, 0xff, 0xfa, 0xef, - 0xfe, 0xaf, 0xff, 0xff, 0x0, 0x1, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, - - /* U+F7C2 "" */ - 0x0, 0x8, 0xff, 0xff, 0xff, 0xe4, 0x0, 0x8f, - 0xff, 0xff, 0xff, 0xfe, 0x8, 0xf8, 0xf, 0xb, - 0x40, 0xff, 0x8f, 0xf8, 0xf, 0xb, 0x40, 0xff, - 0xff, 0xf8, 0xf, 0xb, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xe4, - - /* U+F8A2 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xe0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x2, - 0xef, 0x10, 0x0, 0xbf, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xf1, 0x0, 0xcf, 0xf1, 0x0, 0x0, 0x0, - 0x7, 0xff, 0x11, 0xcf, 0xff, 0x77, 0x77, 0x77, - 0x77, 0xbf, 0xf1, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x7, 0xff, 0xf1, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xa0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + 0x0, 0x0, 0x3, 0xd0, 0x93, 0x9d, 0x30, 0xc0, + 0xf8, 0x0, 0x0, 0x0 }; @@ -1788,187 +552,113 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, {.bitmap_index = 0, .adv_w = 69, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 0, .adv_w = 69, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 18, .adv_w = 100, .box_w = 5, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 31, .adv_w = 180, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 97, .adv_w = 159, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 177, .adv_w = 216, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 255, .adv_w = 176, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 327, .adv_w = 54, .box_w = 2, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 332, .adv_w = 86, .box_w = 4, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 362, .adv_w = 87, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 392, .adv_w = 102, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 417, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 449, .adv_w = 58, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 457, .adv_w = 98, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 466, .adv_w = 58, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 471, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 535, .adv_w = 171, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 595, .adv_w = 95, .box_w = 5, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 625, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 679, .adv_w = 146, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 733, .adv_w = 171, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 799, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 853, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 913, .adv_w = 153, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 967, .adv_w = 165, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1027, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1087, .adv_w = 58, .box_w = 3, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1101, .adv_w = 58, .box_w = 3, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1119, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1151, .adv_w = 149, .box_w = 8, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 1175, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1207, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1261, .adv_w = 265, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1381, .adv_w = 187, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1459, .adv_w = 194, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1525, .adv_w = 185, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1591, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1663, .adv_w = 172, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1717, .adv_w = 163, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1771, .adv_w = 198, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1843, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1909, .adv_w = 79, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1927, .adv_w = 131, .box_w = 8, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1975, .adv_w = 184, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2041, .adv_w = 152, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2095, .adv_w = 244, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2173, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2239, .adv_w = 215, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2317, .adv_w = 185, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2377, .adv_w = 215, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2482, .adv_w = 186, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2542, .adv_w = 159, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2602, .adv_w = 150, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2662, .adv_w = 202, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2728, .adv_w = 182, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 2806, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2914, .adv_w = 172, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2980, .adv_w = 166, .box_w = 12, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 3052, .adv_w = 168, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3118, .adv_w = 85, .box_w = 5, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3156, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 3220, .adv_w = 85, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3250, .adv_w = 149, .box_w = 8, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 3278, .adv_w = 128, .box_w = 8, .box_h = 2, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3286, .adv_w = 154, .box_w = 5, .box_h = 2, .ofs_x = 1, .ofs_y = 10}, - {.bitmap_index = 3291, .adv_w = 153, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3332, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3392, .adv_w = 146, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3433, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3493, .adv_w = 157, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3538, .adv_w = 90, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3580, .adv_w = 177, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3640, .adv_w = 174, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3694, .adv_w = 71, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3712, .adv_w = 73, .box_w = 6, .box_h = 15, .ofs_x = -2, .ofs_y = -3}, - {.bitmap_index = 3757, .adv_w = 158, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3811, .adv_w = 71, .box_w = 2, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3823, .adv_w = 271, .box_w = 15, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3891, .adv_w = 174, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3932, .adv_w = 163, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3977, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 4037, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4097, .adv_w = 105, .box_w = 6, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 4124, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4160, .adv_w = 106, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4199, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 4240, .adv_w = 143, .box_w = 10, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 4285, .adv_w = 230, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4353, .adv_w = 141, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4394, .adv_w = 143, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 4454, .adv_w = 133, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4490, .adv_w = 90, .box_w = 6, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4535, .adv_w = 77, .box_w = 3, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 4558, .adv_w = 90, .box_w = 5, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4596, .adv_w = 149, .box_w = 9, .box_h = 5, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 4619, .adv_w = 107, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 6}, - {.bitmap_index = 4637, .adv_w = 80, .box_w = 3, .box_h = 4, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 4643, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 4779, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4875, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 4987, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5083, .adv_w = 176, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5149, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5277, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5405, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 5531, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5659, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5767, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5895, .adv_w = 128, .box_w = 8, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 5951, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6035, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 6179, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6275, .adv_w = 176, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 6363, .adv_w = 224, .box_w = 10, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, - {.bitmap_index = 6443, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 6569, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6674, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6772, .adv_w = 224, .box_w = 10, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, - {.bitmap_index = 6852, .adv_w = 224, .box_w = 16, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 6964, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7034, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7104, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7202, .adv_w = 224, .box_w = 14, .box_h = 4, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 7230, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7338, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 7498, .adv_w = 288, .box_w = 20, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 7658, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 7786, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 7856, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 7926, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8066, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8162, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 8290, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 8435, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8540, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 8652, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8750, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8848, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8944, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 9040, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9152, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9264, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 9372, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 9534, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9630, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 9780, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 9880, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 9980, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10080, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10180, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10280, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 10427, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 10523, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 10635, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 10780, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 10900, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 10996, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 9, .adv_w = 100, .box_w = 5, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 16, .adv_w = 180, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 49, .adv_w = 159, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 89, .adv_w = 216, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 128, .adv_w = 176, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 164, .adv_w = 54, .box_w = 2, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 167, .adv_w = 86, .box_w = 4, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 182, .adv_w = 87, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 197, .adv_w = 102, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 210, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 226, .adv_w = 58, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 230, .adv_w = 98, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 235, .adv_w = 58, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 238, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 270, .adv_w = 171, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 300, .adv_w = 95, .box_w = 5, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 315, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 342, .adv_w = 146, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 369, .adv_w = 171, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 402, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 429, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 459, .adv_w = 153, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 486, .adv_w = 165, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 516, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 546, .adv_w = 58, .box_w = 3, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 553, .adv_w = 58, .box_w = 3, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 562, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 578, .adv_w = 149, .box_w = 8, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 590, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 606, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 633, .adv_w = 265, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 693, .adv_w = 187, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 732, .adv_w = 194, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 765, .adv_w = 185, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 798, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 834, .adv_w = 172, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 861, .adv_w = 163, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 888, .adv_w = 198, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 924, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 957, .adv_w = 79, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 966, .adv_w = 131, .box_w = 8, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 990, .adv_w = 184, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1023, .adv_w = 152, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1050, .adv_w = 244, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1089, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1122, .adv_w = 215, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1161, .adv_w = 185, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1191, .adv_w = 215, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1244, .adv_w = 186, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1274, .adv_w = 159, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1304, .adv_w = 150, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1334, .adv_w = 202, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1367, .adv_w = 182, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 1406, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1460, .adv_w = 172, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1493, .adv_w = 166, .box_w = 12, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 1529, .adv_w = 168, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1562, .adv_w = 85, .box_w = 5, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1581, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 1613, .adv_w = 85, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1628, .adv_w = 149, .box_w = 8, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 1642, .adv_w = 128, .box_w = 8, .box_h = 2, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1646, .adv_w = 154, .box_w = 5, .box_h = 2, .ofs_x = 1, .ofs_y = 10}, + {.bitmap_index = 1649, .adv_w = 153, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1670, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1700, .adv_w = 146, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1721, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1751, .adv_w = 157, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1774, .adv_w = 90, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1795, .adv_w = 177, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1825, .adv_w = 174, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1852, .adv_w = 71, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1861, .adv_w = 73, .box_w = 6, .box_h = 15, .ofs_x = -2, .ofs_y = -3}, + {.bitmap_index = 1884, .adv_w = 158, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1911, .adv_w = 71, .box_w = 2, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1917, .adv_w = 271, .box_w = 15, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1951, .adv_w = 174, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1972, .adv_w = 163, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1995, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2025, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2055, .adv_w = 105, .box_w = 6, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2069, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2087, .adv_w = 106, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2107, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2128, .adv_w = 143, .box_w = 10, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 2151, .adv_w = 230, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2185, .adv_w = 141, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2206, .adv_w = 143, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 2236, .adv_w = 133, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2254, .adv_w = 90, .box_w = 6, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2277, .adv_w = 77, .box_w = 3, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2289, .adv_w = 90, .box_w = 5, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2308, .adv_w = 149, .box_w = 9, .box_h = 5, .ofs_x = 0, .ofs_y = 4} }; /*--------------------- * CHARACTER MAPPING *--------------------*/ -static const uint16_t unicode_list_1[] = { - 0x0, 0x1f72, 0xef51, 0xef58, 0xef5b, 0xef5c, 0xef5d, 0xef61, - 0xef63, 0xef65, 0xef69, 0xef6c, 0xef71, 0xef76, 0xef77, 0xef78, - 0xef8e, 0xef93, 0xef98, 0xef9b, 0xef9c, 0xef9d, 0xefa1, 0xefa2, - 0xefa3, 0xefa4, 0xefb7, 0xefb8, 0xefbe, 0xefc0, 0xefc1, 0xefc4, - 0xefc7, 0xefc8, 0xefc9, 0xefcb, 0xefe3, 0xefe5, 0xf014, 0xf015, - 0xf017, 0xf019, 0xf030, 0xf037, 0xf03a, 0xf043, 0xf06c, 0xf074, - 0xf0ab, 0xf13b, 0xf190, 0xf191, 0xf192, 0xf193, 0xf194, 0xf1d7, - 0xf1e3, 0xf23d, 0xf254, 0xf4aa, 0xf712, 0xf7f2 -}; + /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - }, - { - .range_start = 176, .range_length = 63475, .glyph_id_start = 96, - .unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 62, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -1978,7 +668,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 0, 13, 14, 15, 16, 17, @@ -1990,19 +681,12 @@ static const uint8_t kern_left_class_mapping[] = { 44, 0, 45, 46, 47, 48, 49, 50, 51, 45, 52, 52, 53, 48, 45, 45, 46, 46, 54, 55, 56, 57, 51, 58, - 58, 59, 58, 60, 41, 0, 0, 9, - 61, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 58, 59, 58, 60, 41, 0, 0, 9 }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 12, @@ -2011,58 +695,51 @@ static const uint8_t kern_right_class_mapping[] = { 23, 25, 25, 26, 25, 25, 25, 25, 23, 25, 23, 25, 3, 27, 28, 29, 29, 30, 31, 32, 33, 34, 35, 0, - 36, 0, 37, 38, 39, 39, 39, 0, - 39, 38, 40, 41, 38, 38, 42, 42, - 39, 42, 39, 42, 43, 44, 45, 46, - 46, 47, 46, 48, 0, 0, 35, 9, - 49, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 36, 0, 37, 38, 39, 39, 39, 40, + 39, 38, 41, 42, 38, 38, 43, 43, + 39, 43, 39, 43, 44, 45, 46, 47, + 47, 48, 47, 49, 0, 0, 35, 9 }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { - 0, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 3, 0, 0, 0, +static const int8_t kern_class_values[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 12, 0, 7, -6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 7, -6, 0, 0, 0, 0, -14, -15, 2, 12, 6, 4, - -10, 2, 13, 1, 11, 3, 8, 0, + -10, 2, 13, 0, 11, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 0, -8, 0, 0, 0, 0, + 0, 0, 0, -8, 0, 0, 0, 0, 0, -5, 4, 5, 0, 0, -3, 0, -2, 3, 0, -3, 0, -3, -1, -5, 0, 0, 0, 0, -3, 0, 0, -3, -4, 0, 0, -3, 0, -5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -3, - -3, 0, -4, 0, -7, 0, -31, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -3, -3, 0, 0, -7, 0, -31, 0, 0, -5, 0, 5, 8, 0, 0, -5, 3, 3, 8, 5, -4, 5, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -7, -3, -13, 0, -10, + 0, 0, 0, 0, -3, -13, 0, -10, -2, 0, 0, 0, 0, 1, 10, 0, - -8, -2, -1, 1, 0, -4, 0, 0, + -8, -2, 0, 0, 0, -4, 0, 0, -2, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -20, -2, 10, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 3, 0, 0, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 2, - 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2071,79 +748,79 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 3, 8, -3, 0, 0, 5, -3, - -8, -35, 2, 7, 5, 1, -3, 0, + -8, -35, 2, 7, 5, 0, -3, 0, 9, 0, 8, 0, 8, 0, -24, 0, -3, 8, 0, 8, -3, 5, 3, 0, - 0, 1, -3, 0, 0, -4, 20, 0, - 20, 0, 8, 0, 11, 3, 4, 8, + 0, 0, -3, 0, 0, -4, 0, 0, + 0, 20, 0, 8, 0, 11, 3, 4, 0, 0, 0, -9, 0, 0, 0, 0, - 1, -2, 0, 2, -5, -3, -5, 2, + 0, -2, 0, 2, -5, -3, -5, 2, 0, -3, 0, 0, 0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, -14, 0, -16, 0, 0, 0, + 0, 0, -14, 0, -16, 0, 0, 0, 0, -2, 0, 25, -3, -3, 3, 3, -2, 0, -3, 3, 0, 0, -14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -16, 0, 15, 0, 0, -9, 0, + 0, 0, 0, 15, 0, 0, -9, 0, 8, 0, -17, -25, -17, -5, 8, 0, 0, -17, 0, 3, -6, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, -31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 12, 0, 2, 0, 0, 0, - 0, 0, 2, 2, -3, -5, 0, -1, - -1, -3, 0, 0, -2, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 2, 2, -3, -5, 0, 0, + 0, -3, 0, 0, -2, 0, 0, 0, -5, 0, -2, 0, -6, -5, 0, -6, -8, -8, -5, 0, -5, 0, -5, 0, - 0, 0, 0, -2, 0, 0, 3, 0, - 2, -3, 0, 1, 0, 0, 0, 3, - -2, 0, 0, 0, -2, 3, 3, -1, - 0, 0, 0, -5, 0, -1, 0, 0, - 0, 0, 0, 1, 0, 3, -2, 0, + 0, 0, 0, 0, -2, 0, 0, 3, + 0, 2, -3, 0, 0, 0, 0, 3, + -2, 0, 0, 0, -2, 3, 3, 0, + 0, 0, 0, -5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, -2, 0, -3, 0, -4, 0, 0, -2, 0, 8, 0, 0, -3, 0, 0, 0, 0, 0, - -1, 1, -2, -2, 0, 0, -3, 0, + 0, 0, 0, -2, -2, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -3, -3, 0, - 0, 0, 0, 0, 1, 0, 0, -2, + 0, 0, 0, 0, 0, 0, 0, -2, 0, -3, -3, -3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -2, 0, 0, - 0, 0, -2, -3, 0, -4, 0, -8, + 0, 0, 0, 0, 0, 0, -2, 0, + 0, 0, 0, -2, -3, 0, 0, -8, -2, -8, 5, 0, 0, -5, 3, 5, - 7, 0, -6, -1, -3, 0, -1, -12, - 3, -2, 2, -14, 3, 0, 0, 1, + 7, 0, -6, 0, -3, 0, 0, -12, + 3, -2, 2, -14, 3, 0, 0, 0, -13, 0, -14, -2, -22, -2, 0, -13, 0, 5, 7, 0, 3, 0, 0, 0, - 0, 1, 0, -5, -3, 0, -8, 0, + 0, 0, 0, 0, -5, -3, 0, 0, 0, 0, -3, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, -1, 0, -1, -3, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0, -2, -3, -2, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2, -2, 0, -3, + 0, 0, 0, 0, 0, -2, -2, 0, 0, -2, 0, -5, 3, 0, 0, -3, 1, 3, 3, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 2, 0, 0, -3, 0, -3, -2, -3, 0, 0, 0, 0, 0, 0, 0, 2, 0, - -2, 0, 0, 0, 0, -3, -4, 0, - -5, 0, 8, -2, 1, -8, 0, 0, + 0, -2, 0, 0, 0, 0, -3, -4, + 0, 0, 8, -2, 0, -8, 0, 0, 7, -13, -13, -11, -5, 3, 0, -2, -17, -5, 0, -5, 0, -5, 4, -5, - -16, 0, -7, 0, 0, 1, -1, 2, - -2, 0, 3, 0, -8, -10, 0, -13, - -6, -5, -6, -8, -3, -7, -1, -5, - -7, 2, 0, 1, 0, -3, 0, 0, + -16, 0, -7, 0, 0, 1, 0, 2, + -2, 0, 3, -1, -8, -10, 0, -13, + 0, 0, -5, -6, -8, -3, -7, -1, + -5, -7, 0, 0, 0, -3, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, - 0, -1, 0, -1, -3, 0, -4, -6, - -6, -1, 0, -8, 0, 0, 0, 0, - 0, 0, -2, 0, 0, 0, 0, 1, - -2, 0, 0, 0, 3, 0, 0, 0, + 0, -1, 0, 0, -3, 0, -4, -6, + -6, 0, 0, -8, 0, 0, 0, 0, + 0, 0, 0, -2, 0, 0, 0, 0, + 1, -2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, @@ -2155,44 +832,44 @@ static const int8_t kern_class_values[] = { 0, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -5, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, -5, 0, + 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 3, 0, 2, -5, -5, 0, -3, -3, -3, 0, 0, 0, 0, 0, 0, -8, 0, -3, 0, -4, -3, 0, -6, -6, -8, -2, 0, -5, 0, - -8, 0, 0, 0, 0, 20, 0, 0, - 1, 0, 0, -3, 0, 3, 0, -11, + -8, 0, 0, 0, 0, 0, 20, 0, + 0, 1, 0, 0, -3, 0, 0, -11, 0, 0, 0, 0, 0, -24, -5, 8, 8, -2, -11, 0, 3, -4, 0, -13, -1, -3, 3, -18, -3, 3, 0, 4, -9, -4, -9, -8, -11, 0, 0, -15, 0, 15, 0, 0, -1, 0, 0, 0, - -1, -1, -3, -7, -8, -1, -24, 0, + 0, -1, -1, -3, -7, -8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -1, -3, -4, 0, 0, -5, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, -5, 0, 0, 5, - -1, 3, 0, -6, 3, -2, -1, -7, + 0, 0, 0, 0, -5, 0, 0, 5, + 0, 3, 0, -6, 3, -2, 0, -7, -3, 0, -3, -3, -2, 0, -4, -4, - 0, 0, -2, -1, -2, -4, -3, 0, + 0, 0, -2, 0, -2, -4, -3, 0, 0, -3, 0, 3, -2, 0, -6, 0, - 0, 0, -5, 0, -4, 0, -4, -4, - 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -5, 0, -4, 0, -4, + -4, 0, 0, 0, 0, 0, 0, 0, 0, -5, 3, 0, -4, 0, -2, -3, - -8, -2, -2, -2, -1, -2, -3, -1, + -8, -2, -2, -2, 0, -2, -3, 0, 0, 0, 0, 0, 0, -3, -2, -2, 0, 0, 0, 0, 3, -2, 0, -2, - 0, 0, 0, -2, -3, -2, -2, -3, - -2, 0, 2, 10, -1, 0, -7, 0, + 0, 0, 0, 0, -2, -3, -2, -2, + -3, -2, 2, 10, 0, 0, -7, 0, -2, 5, 0, -3, -11, -3, 4, 0, 0, -12, -4, 3, -4, 2, 0, -2, -2, -8, 0, -4, 1, 0, 0, -4, 0, 0, 0, 3, 3, -5, -5, 0, - -4, -3, -4, -3, -3, 0, -4, 1, - -5, -4, 8, 0, 0, 0, 0, 0, + -4, 0, 0, -4, -3, -3, 0, -4, + 1, -5, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2209,89 +886,89 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -3, 0, 0, -3, -3, 0, 0, 0, 0, - -3, 0, 0, 0, 0, -1, 0, 0, - 0, 0, 0, -2, 0, 0, 0, 0, + -3, 0, 0, 0, 0, 0, -1, 0, + 0, 0, 0, 0, -2, 0, 0, 0, -4, 0, -5, 0, 0, 0, -8, 0, - 2, -6, 5, 1, -2, -12, 0, 0, + 2, -6, 5, 0, -2, -12, 0, 0, -6, -3, 0, -10, -6, -7, 0, 0, -11, -3, -10, -10, -12, 0, -7, 0, - 2, 17, -3, 0, -6, -3, -1, -3, - -4, -7, -5, -9, -10, -6, -3, 0, - 0, -2, 0, 1, 0, 0, -18, -2, - 8, 6, -6, -9, 0, 1, -8, 0, - -13, -2, -3, 5, -24, -3, 1, 0, + 2, 17, -3, 0, -6, 0, 0, 0, + -3, -4, -7, -5, -9, -10, -6, 0, + 0, -2, 0, 0, 0, 0, -18, -2, + 8, 6, -6, -9, 0, 0, -8, 0, + -13, -2, -3, 5, -24, -3, 0, 0, 0, -17, -3, -13, -3, -19, 0, 0, - -18, 0, 15, 1, 0, -2, 0, 0, - 0, 0, -1, -2, -10, -2, 0, -17, + -18, 0, 15, 0, 0, -2, 0, 0, + 0, 0, 0, -1, -2, -10, -2, 0, 0, 0, 0, 0, -8, 0, -2, 0, - -1, -7, -12, 0, 0, -1, -4, -8, + 0, -7, -12, 0, 0, -1, -4, -8, -3, 0, -2, 0, 0, 0, 0, -12, -3, -8, -8, -2, -4, -6, -3, -4, - 0, -5, -2, -8, -4, 0, -3, -5, - -3, -5, 0, 1, 0, -2, -8, 0, - 5, 0, -5, 0, 0, 0, 0, 3, + 0, -5, -2, -8, -4, 0, -3, 0, + 0, -3, -5, 0, 1, 0, -2, -8, + 0, 0, -5, 0, 0, 0, 0, 3, 0, 2, -5, 10, 0, -3, -3, -3, 0, 0, 0, 0, 0, 0, -8, 0, -3, 0, -4, -3, 0, -6, -6, -8, -2, 0, -5, 2, 10, 0, 0, 0, - 0, 20, 0, 0, 1, 0, 0, -3, - 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, 0, 0, + 0, 0, 20, 0, 0, 1, 0, 0, + -3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2, -5, 0, 0, 0, 0, 0, -1, 0, 0, 0, -3, -3, 0, 0, -5, -3, 0, 0, -5, 0, 4, -1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 4, 5, 2, -2, 0, -8, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 5, 2, -2, 0, -8, -4, 0, 8, -8, -8, -5, -5, 10, 5, 3, -22, -2, 5, -3, 0, -3, 3, -3, -9, 0, -3, 3, -3, -2, -8, -2, 0, 0, 8, 5, 0, -7, - 0, -14, -3, 7, -3, -10, 1, -3, - -8, -8, -3, 10, 3, 0, -4, 0, + 0, -14, 0, 0, 7, -3, -10, 0, + -3, -8, -8, -3, 3, 0, -4, 0, -7, 0, 2, 8, -6, -9, -10, -6, - 8, 0, 1, -19, -2, 3, -4, -2, + 8, 0, 0, -19, -2, 3, -4, -2, -6, 0, -6, -9, -4, -4, -2, 0, 0, -6, -5, -3, 0, 8, 6, -3, - -14, 0, -14, -4, 0, -9, -15, -1, - -8, -4, -8, -7, 7, 0, 0, -3, + -14, 0, -14, 0, -4, -5, -9, -15, + 0, -8, -4, -8, -7, 0, 0, -3, 0, -5, -2, 0, -3, -5, 0, 4, -8, 3, 0, 0, -14, 0, -3, -6, -4, -2, -8, -6, -8, -6, 0, -8, - -3, -6, -5, -8, -3, 0, 0, 1, - 12, -4, 0, -8, -3, 0, -3, -5, - -6, -7, -7, -10, -3, -5, 5, 0, + -3, -6, -5, -8, -3, 0, 0, 0, + 12, -4, 0, -8, 0, 0, 0, -3, + -5, -6, -7, -7, -10, -3, 5, 0, -4, 0, -13, -3, 2, 5, -8, -9, -5, -8, 8, -3, 1, -24, -5, 5, -6, -4, -9, 0, -8, -11, -3, -3, - -2, -3, -5, -8, -1, 0, 0, 8, - 7, -2, -17, 0, -15, -6, 6, -10, - -17, -5, -9, -11, -13, -8, 5, 0, + -2, -3, -5, -8, 0, 0, 0, 8, + 7, -2, -17, 0, -15, 0, -4, 6, + -10, -17, -5, -9, -11, -13, -8, 0, 0, 0, 0, -3, 0, 0, 3, -3, - 5, 2, -5, 5, 0, 0, -8, -1, - 0, -1, 0, 1, 1, -2, 0, 0, + 5, 2, -5, 5, 0, 0, -8, 0, + 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, - 0, 2, 8, 1, 0, -3, 0, 0, - 0, 0, -2, -2, -3, 0, 0, 0, - 1, 2, 0, 0, 0, 0, 2, 0, - -2, 0, 10, 0, 5, 1, 1, -3, + 0, 2, 8, 0, 0, -3, 0, 0, + 0, 0, 0, -2, -2, -3, 0, 0, + 0, 2, 0, 0, 0, 0, 2, 0, + -2, 0, 10, 0, 5, 0, 0, -3, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, -3, 4, 0, 8, 0, 0, 25, 3, -5, -5, 3, 3, - -2, 1, -13, 0, 0, 12, -15, 0, + -2, 0, -13, 0, 0, 12, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 10, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -15, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -5, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -7, 0, - 0, 1, 0, 0, 3, 33, -5, -2, + 0, 0, 0, 0, 3, 33, -5, -2, 8, 7, -7, 3, 0, 0, 3, 3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -33, 7, 0, 0, @@ -2301,39 +978,39 @@ static const int8_t kern_class_values[] = { -6, -1, 0, 0, 0, -6, 0, -3, 0, -12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, - 0, -3, 0, 0, -5, 0, -4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -3, 0, 0, 0, -4, 0, -7, 0, 0, 0, -4, 3, -3, 0, 0, -7, -3, -6, 0, 0, -7, 0, -3, 0, -12, 0, -3, 0, 0, -21, -5, -10, -3, -9, 0, 0, -17, 0, -7, -1, 0, 0, 0, 0, 0, 0, - 0, 0, -4, -5, -2, -4, 0, 0, + 0, 0, 0, -4, -5, -2, 0, 0, 0, 0, -6, 0, -6, 3, -3, 5, 0, -2, -6, -2, -4, -5, 0, -3, - -1, -2, 2, -7, -1, 0, 0, 0, + -1, -2, 2, -7, 0, 0, 0, 0, -23, -2, -4, 0, -6, 0, -2, -12, - -2, 0, 0, -2, -2, 0, 0, 0, - 0, 2, 0, -2, -4, -2, 4, 0, + -2, 0, 0, -2, -2, 0, -2, 0, + 0, 0, 2, 0, -2, -4, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, -6, 0, -2, 0, 0, 0, -5, 3, 0, 0, 0, -7, -3, -5, 0, 0, -7, 0, -3, 0, -12, 0, 0, 0, 0, -25, 0, -5, -9, -13, 0, 0, -17, 0, -2, -4, 0, 0, 0, - 0, 0, 0, 0, 0, -3, -4, -1, - -4, 1, 0, 0, 4, -3, 0, 8, + 0, 0, 0, 0, 0, 0, -3, -4, + -1, 0, 0, 0, 4, -3, 0, 8, 13, -3, -3, -8, 3, 13, 4, 6, -7, 3, 11, 3, 7, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 12, -5, -3, 0, -2, - 20, 11, 20, 0, 0, 0, 3, 0, - 0, 9, 0, 0, -4, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 3, + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, -22, -3, -2, -10, @@ -2350,66 +1027,61 @@ static const int8_t kern_class_values[] = { 2, 5, 3, -8, 0, -1, -2, 3, 0, 2, 0, 0, 0, 0, -6, 0, -2, -2, -5, 0, -2, -10, 0, 16, - -3, 0, -6, -2, 0, -2, -4, 0, - -3, -7, -5, -3, 0, 0, 0, -4, + -3, 0, -6, 0, 0, 0, -2, -4, + 0, -3, -7, -5, -3, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, -22, -3, -2, -10, -13, 0, 0, -17, 0, - 0, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, -8, -3, -2, 8, -2, -3, - -10, 1, -2, 1, -2, -7, 1, 6, - 1, 2, 1, 2, -6, -10, -3, 0, + -10, 0, -1, 0, -2, -7, 0, 6, + 0, 2, 0, 2, -6, -10, -3, 0, -10, -5, -7, -11, -10, 0, -4, -5, - -3, -3, -2, -2, -3, -2, 0, -2, - -1, 4, 0, 4, -2, 0, 8, 0, + -3, -3, -12, -2, -3, 0, -2, 0, + -2, 0, 4, 0, 4, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -3, -3, 0, 0, -7, 0, -1, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, -3, 0, -3, + 0, 0, 0, 0, 0, -3, -3, 0, 0, 0, 0, 0, -2, 0, 0, -4, -3, 3, 0, -4, -5, -2, 0, -7, -2, -6, -2, -3, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 8, 0, 0, -5, 0, - 0, 0, 0, -3, 0, -3, 0, 0, - -1, 0, 0, -2, 0, -6, 0, 0, + 0, 0, 0, 0, -3, 0, -3, 0, + 0, 0, 0, -2, 0, -6, 0, 0, 11, -3, -8, -8, 2, 3, 3, -1, -7, 2, 4, 2, 8, 2, 8, -2, -7, 0, 0, -10, 0, 0, -8, -7, 0, 0, -5, 0, -3, -4, 0, -4, - 0, -4, 0, -2, 4, 0, -2, -8, - -3, 9, 0, 0, -2, 0, -5, 0, - 0, 3, -6, 0, 3, -3, 2, 0, - 0, -8, 0, -2, -1, 0, -3, 3, + 0, 0, -4, 0, -2, 4, 0, -2, + -8, -3, 0, 0, -2, 0, -5, 0, + 0, 3, -6, 0, 3, -3, 2, -1, + 0, -8, 0, -2, 0, 0, -3, 3, -2, 0, 0, 0, -10, -3, -6, 0, -8, 0, 0, -12, 0, 9, -3, 0, - -5, 0, 2, 0, -3, 0, -3, -8, - 0, -3, 3, 0, 0, 0, 0, -2, - 0, 0, 3, -3, 1, 0, 0, -3, + -5, 0, 0, 2, 0, -3, 0, -3, + -8, 0, -3, 0, 0, 0, 0, -2, + 0, 0, 3, -3, 0, 0, 0, -3, -2, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 0, 6, 0, - 0, -2, 0, 0, 0, 0, 1, 0, - -3, -3, 0, 0, 0, 5, 0, 6, - 0, 0, 0, 0, 0, -16, -15, 1, - 11, 8, 4, -10, 2, 11, 0, 9, - 0, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, -2, 0, 0, 0, 0, 0, 0, + 0, -3, -3, 0 }; /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, - .left_class_cnt = 61, + .left_class_cnt = 60, .right_class_cnt = 49, }; @@ -2429,8 +1101,8 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .cmaps = cmaps, .kern_dsc = &kern_classes, .kern_scale = 16, - .cmap_num = 2, - .bpp = 4, + .cmap_num = 1, + .bpp = 2, .kern_classes = 1, .bitmap_format = 0, #if LV_VERSION_CHECK(8, 0, 0) @@ -2451,7 +1123,7 @@ lv_font_t lv_font_montserrat_16 = { #endif .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 18, /*The maximum line height required by the font*/ + .line_height = 17, /*The maximum line height required by the font*/ .base_line = 3, /*Baseline measured from the bottom of the line*/ #if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) .subpx = LV_FONT_SUBPX_NONE, diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index d778539ef..74f5ea722 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -17,7 +17,6 @@ INC += -I$(BUILD) INC += -I$(TOP) INC += -I$(TOP)/extmod INC += -I$(TOP)/extmod/quirc -INC += -I$(TOP)/extmod/trezor-firmware/crypto INC += -I$(TOP)/ports/stm32/boards/Passport/include INC += -I$(TOP)/ports/stm32/boards/Passport/common/micro-ecc/ diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index 82c6124c5..71b8d8eaa 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -10,11 +10,6 @@ contribdir := join(justfile_directory(), "boards/Passport/contrib") openocd_cfg := join(contribdir, "openocd.cfg") compile_commands := join(builddir, "compile_commands.json") -base_cflags := "-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP -DLV_TICK_CUSTOM=1" -color_cflags := "-DSCREEN_MODE_COLOR -DHAS_FUEL_GAUGE " -mono_cflags := "-DSCREEN_MODE_MONO" -dev_cflags := "-DDEV_BUILD" - # Number of jobs to use when building jobs := if os() == "macos" { `sysctl -n hw.logicalcpu` @@ -83,7 +78,7 @@ build screen="mono" dev="" +ext='': @echo {{ if screen == "mono" { "Building with SCREEN_MODE=MONO" } else if screen == "color" { "Building with SCREEN_MODE=COLOR" } else { error("Unsupported screen type. Use 'mono' or 'color'") } }} make -j{{jobs}} \ - LV_CFLAGS='{{base_cflags}} {{ if screen == "mono" { mono_cflags } else { color_cflags } }} {{ if dev == "dev" { dev_cflags } else { "" } }}' \ + {{ if dev == "dev" { "DEV_BUILD=1" } else { "" } }} \ BOARD=Passport \ SCREEN_MODE={{ uppercase(screen) }} \ FROZEN_MANIFEST={{ if dev == "dev" { 'boards/Passport/manifest_dev.py' } else { 'boards/Passport/manifest.py' } }} \ @@ -123,6 +118,7 @@ sign-beta version="1.0.0" beta-num="1": rm -rf "{{version}}-beta-{{beta-num}}" mkdir -p "{{version}}-beta-{{beta-num}}" screens=("color" "mono") + screen_names=("" "-founders") paths=("passport-key-user" "passport-fe-key-user") builds=("" "dev") build_names=("" "-dev") @@ -132,9 +128,9 @@ sign-beta version="1.0.0" beta-num="1": for build in "${builds[@]}"; do just clean just sign {{version}} $screen $build - mv "build-Passport/v{{version}}-${paths[$i]}.bin" "build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-passport.bin" - just hash "build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-passport.bin" "${screen}" "{{version}}-beta-{{beta-num}}/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-notes.md" - cp build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}* "{{version}}-beta-{{beta-num}}/" + mv "build-Passport/v{{version}}-${paths[$i]}.bin" "build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-passport.bin" + just hash "build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-passport.bin" "${screen}" "{{version}}-beta-{{beta-num}}/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-notes.md" + cp build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}* "{{version}}-beta-{{beta-num}}/" j=$((j + 1)) done i=$((i + 1)) @@ -208,14 +204,15 @@ graphics-c: # graphics: graphics-py graphics-c # Build all images. -images: (convert-images 'boards/Passport/images') (convert-images 'boards/Passport/bootloader/images') +images: (convert-images "boards/Passport/images" "true") (convert-images "boards/Passport/bootloader/images" "false") # LVGL Image Conversion Tool -convert-images image_path: +convert-images image_path process_mono='false': #!/usr/bin/python3 import os from os import listdir image_path = '{{image_path}}' + process_mono = '{{process_mono}}' conv_path = '../../../../../../tools/lv_img_conv/lv_img_conv.js' f = open(image_path + '/images.h', 'w') @@ -230,6 +227,7 @@ convert-images image_path: from shutil import copyfile full_folder = image_path + '/{}'.format(folder) image_filenames = [f for f in listdir(full_folder) if f.endswith('.png')] + image_filenames.sort() for filename in image_filenames: base = os.path.splitext(filename)[0] # Trim extension parts = base.split('__') @@ -277,9 +275,10 @@ convert-images image_path: handle_images('color') f.write('#endif\n\n') - f.write('#ifdef SCREEN_MODE_MONO\n') - handle_images('mono') - f.write('#endif\n\n') + if process_mono == "true": + f.write('#ifdef SCREEN_MODE_MONO\n') + handle_images('mono') + f.write('#endif\n\n') f.close() @@ -334,20 +333,21 @@ hash filepath screen="mono" output_file="": echo "$sha" > ${directory}/${release_name}-sha256 # MD5 - md5=`mdsum {{filepath}} | sed -rn 's/^(.*) .*$/\1/p'` - md5=${md5::-1} + md5=`mdsum {{filepath}} | sed -rn 's/^(.*) .*$/\1/p' | xargs` echo "$md5" > ${directory}/${release_name}-md5 # Build Hash build_hash=`cosign -t {{screen}} -p -f {{filepath}} | sed -rn 's/^FW Build Hash: (.*)$/\1/p'` echo "$build_hash" > ${directory}/${release_name}-build-hash - output="## RELEASE HASHES\n\nSHA256: \`$sha\`\nMD5: \`$md5\`\n\nYou can check these hashes with the following commands on most operating systems:\n\n" + output="## RELEASE HASHES\n\n" if [ -n "{{output_file}}" ]; then output+="### $filename:\n\n" fi + output+="SHA256: \`$sha\`\nMD5: \`$md5\`\n\nYou can check these hashes with the following commands on most operating systems:\n\n" + output+="SHA256: \`shasum -b -a 256 $filename\`\nMD5: \`md5 $filename\` or \`mdsum $filename\` or \`md5sum $filename\`\n\n" output+="### DEVELOPERS ONLY\n\nBuild Hash: \`$build_hash\`" diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4ebdb1fb2..509aee9c7 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -556,12 +556,6 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o -# secp256k1-zkp ARM assembly. -# NOTE: this is done here because the assembly and the flag from the Unix and -# STM32 ports differ. -OBJ += $(SECP256K1_DIR)/src/asm/field_10x26_arm.o -CFLAGS += -DUSE_EXTERNAL_ASM -DSECP256K1_CONTEXT_SIZE=184 - # For extmod/trezor-firmware/crypto/rand.c, we define a random32, random_reseed and random_buffer, # in our Passport board that uses our own noise source. CFLAGS += -DRAND_PLATFORM_INDEPENDENT diff --git a/ports/stm32/boards/Passport/bootloader/images/images.h b/ports/stm32/boards/Passport/bootloader/images/images.h index 3a35b06e1..c7607305b 100644 --- a/ports/stm32/boards/Passport/bootloader/images/images.h +++ b/ports/stm32/boards/Passport/bootloader/images/images.h @@ -5,29 +5,27 @@ // #ifdef SCREEN_MODE_COLOR -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t PROGRESS_CAP_RIGHT; -extern const lv_img_dsc_t PROGRESS_CAP_RIGHT_BG; -extern const lv_img_dsc_t PROGRESS_BAR_BG; -extern const lv_img_dsc_t ICON_EMAIL; extern const lv_img_dsc_t BACKGROUND; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t ICON_ABOUT; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_CANCEL; extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t PROGRESS_CAP_LEFT; -extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_EMAIL; extern const lv_img_dsc_t ICON_EXIT; -extern const lv_img_dsc_t SPLASH; +extern const lv_img_dsc_t ICON_FORWARD; extern const lv_img_dsc_t ICON_PAGE_DOT_SELECTED; -extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_PAGE_DOT; extern const lv_img_dsc_t ICON_RETRY; -extern const lv_img_dsc_t PROGRESS_BAR_FG; extern const lv_img_dsc_t ICON_SHUTDOWN; -extern const lv_img_dsc_t ICON_ABOUT; -extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t PROGRESS_BAR_BG; +extern const lv_img_dsc_t PROGRESS_BAR_FG; +extern const lv_img_dsc_t PROGRESS_CAP_LEFT; +extern const lv_img_dsc_t PROGRESS_CAP_RIGHT_BG; +extern const lv_img_dsc_t PROGRESS_CAP_RIGHT; +extern const lv_img_dsc_t SPLASH; #endif -#ifdef SCREEN_MODE_MONO -#endif diff --git a/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png index 8d9c41e24..4e2e5bf40 100644 Binary files a/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png and b/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c b/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c deleted file mode 100644 index 992a8c485..000000000 --- a/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1 -#define LV_ATTRIBUTE_IMG_ICON_EDIT1 -#endif -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_EDIT1 uint8_t ICON_EDIT1_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0x28, /*Color of index 1*/ - 0xfe, 0xfe, 0xfe, 0x99, /*Color of index 2*/ - 0xfe, 0xfe, 0xfe, 0xe9, /*Color of index 3*/ - - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0xe0, - 0x00, 0x00, 0x00, 0x7e, 0xb8, - 0x00, 0x00, 0x01, 0xf4, 0x3c, - 0x00, 0x00, 0x07, 0xd0, 0x2c, - 0x00, 0x00, 0x1f, 0x40, 0x78, - 0x00, 0x00, 0x7d, 0x01, 0xf4, - 0x00, 0x01, 0xf4, 0x07, 0xd0, - 0x00, 0x07, 0xd0, 0x1f, 0x40, - 0x00, 0x1f, 0x40, 0x7d, 0x00, - 0x00, 0x7d, 0x01, 0xf4, 0x00, - 0x01, 0xf4, 0x07, 0xd0, 0x00, - 0x07, 0xd0, 0x1f, 0x40, 0x00, - 0x0b, 0x40, 0x7d, 0x00, 0x00, - 0x1e, 0x01, 0xf4, 0x00, 0x00, - 0x1d, 0x07, 0xd0, 0x00, 0x00, - 0x2c, 0x6f, 0x40, 0x00, 0x00, - 0x3f, 0xfd, 0x00, 0x00, 0x00, - 0x7e, 0x90, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT1 = { - .header.cf = LV_IMG_CF_INDEXED_2BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 117, - .data = ICON_EDIT1_map, -}; diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png deleted file mode 100644 index 3211950e9..000000000 Binary files a/ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png and /dev/null differ diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c b/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c deleted file mode 100644 index 94bf05b8e..000000000 --- a/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2 -#define LV_ATTRIBUTE_IMG_ICON_EDIT2 -#endif -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_EDIT2 uint8_t ICON_EDIT2_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0x20, /*Color of index 1*/ - 0xfe, 0xfe, 0xfe, 0x65, /*Color of index 2*/ - 0xfe, 0xfe, 0xfe, 0xee, /*Color of index 3*/ - - 0x00, 0x00, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x07, 0xf8, - 0x06, 0xaa, 0x90, 0x1f, 0xbd, - 0x2f, 0xff, 0xf0, 0x7d, 0x2d, - 0x79, 0x55, 0x51, 0xf4, 0x7c, - 0x78, 0x00, 0x07, 0xd1, 0xf4, - 0x78, 0x00, 0x1f, 0x47, 0xd0, - 0x78, 0x00, 0x7d, 0x1f, 0x40, - 0x78, 0x01, 0xf4, 0x7d, 0x00, - 0x78, 0x07, 0xd1, 0xf4, 0x00, - 0x78, 0x0b, 0x47, 0xd1, 0xd0, - 0x78, 0x0f, 0x1f, 0x41, 0xe0, - 0x78, 0x0f, 0xfd, 0x01, 0xe0, - 0x78, 0x1f, 0xa4, 0x01, 0xe0, - 0x78, 0x04, 0x00, 0x01, 0xe0, - 0x78, 0x00, 0x00, 0x01, 0xe0, - 0x78, 0x00, 0x00, 0x01, 0xe0, - 0x3e, 0xaa, 0xaa, 0xaa, 0xe0, - 0x1f, 0xff, 0xff, 0xff, 0x80, - 0x01, 0x55, 0x55, 0x55, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT2 = { - .header.cf = LV_IMG_CF_INDEXED_2BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 117, - .data = ICON_EDIT2_map, -}; diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png deleted file mode 100644 index f6f51b4c9..000000000 Binary files a/ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png and /dev/null differ diff --git a/ports/stm32/boards/Passport/images/images.h b/ports/stm32/boards/Passport/images/images.h index 2aca8d234..0ec2dbeab 100644 --- a/ports/stm32/boards/Passport/images/images.h +++ b/ports/stm32/boards/Passport/images/images.h @@ -5,174 +5,204 @@ // #ifdef SCREEN_MODE_COLOR -extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t ICON_PAGE_QR_MD; -extern const lv_img_dsc_t ICON_EDIT2; -extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; -extern const lv_img_dsc_t ICON_ERASE; -extern const lv_img_dsc_t ICON_SETTINGS; -extern const lv_img_dsc_t ICON_PIN; -extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_WARNING; -extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_ADD_ACCOUNT; +extern const lv_img_dsc_t ICON_ADVANCED; +extern const lv_img_dsc_t ICON_BACKUP; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_BATTERY_CHARGING; +extern const lv_img_dsc_t ICON_BATTERY; +extern const lv_img_dsc_t ICON_BITCOIN; extern const lv_img_dsc_t ICON_BRIGHTNESS; -extern const lv_img_dsc_t ICON_PAGE_DOT; -extern const lv_img_dsc_t ICON_PASSPHRASE; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; -extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_CASA; extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; -extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t ICON_PAGE_PLUS; -extern const lv_img_dsc_t ICON_ADVANCED; -extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; -extern const lv_img_dsc_t ICON_SPIRAL; -extern const lv_img_dsc_t ICON_ONE_KEY; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t ICON_SHIELD; -extern const lv_img_dsc_t LARGE_ICON_CONNECT; -extern const lv_img_dsc_t ICON_PAGE_HOME; -extern const lv_img_dsc_t LARGE_ICON_SUCCESS; -extern const lv_img_dsc_t ICON_SETUP; -extern const lv_img_dsc_t ICON_NOSTR; -extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; -extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_CIRCLE_CHECK; +extern const lv_img_dsc_t ICON_CLOCK; +extern const lv_img_dsc_t ICON_CONNECT; +extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t ICON_DEVICE; +extern const lv_img_dsc_t ICON_ERASE; +extern const lv_img_dsc_t ICON_EXTENSIONS; extern const lv_img_dsc_t ICON_FILE; -extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t ICON_FORWARD; extern const lv_img_dsc_t ICON_HAMBURGER; +extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_HOME; extern const lv_img_dsc_t ICON_INFO; -extern const lv_img_dsc_t ICON_CLOCK; -extern const lv_img_dsc_t ICON_CANCEL; -extern const lv_img_dsc_t ICON_MICROSD; -extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; -extern const lv_img_dsc_t ICON_CIRCLE_CHECK; -extern const lv_img_dsc_t ICON_CASA; -extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; -extern const lv_img_dsc_t ICON_CONNECT; -extern const lv_img_dsc_t ICON_SEED; -extern const lv_img_dsc_t ICON_ADD_ACCOUNT; extern const lv_img_dsc_t ICON_INPUT_MODE_LOWER_ALPHA; -extern const lv_img_dsc_t ICON_TWO_KEYS; -extern const lv_img_dsc_t LARGE_ICON_SEED; -extern const lv_img_dsc_t ICON_SIGN; -extern const lv_img_dsc_t ICON_RETRY; -extern const lv_img_dsc_t ICON_HOME; +extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; +extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; +extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; +extern const lv_img_dsc_t ICON_MICROSD; extern const lv_img_dsc_t ICON_MULTISIG; -extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_NETWORK; +extern const lv_img_dsc_t ICON_NOSTR; +extern const lv_img_dsc_t ICON_ONE_KEY; +extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_PAGE_HOME; +extern const lv_img_dsc_t ICON_PAGE_PLUS; +extern const lv_img_dsc_t ICON_PAGE_QR_LG; +extern const lv_img_dsc_t ICON_PAGE_QR_MD; +extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_PASSPHRASE; +extern const lv_img_dsc_t ICON_PIN; extern const lv_img_dsc_t ICON_PLUS; -extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_RETRY; extern const lv_img_dsc_t ICON_SCAN_QR; +extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_SETTINGS; +extern const lv_img_dsc_t ICON_SETUP; +extern const lv_img_dsc_t ICON_SHIELD; extern const lv_img_dsc_t ICON_SHUTDOWN; +extern const lv_img_dsc_t ICON_SIGN; +extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_SPIRAL; +extern const lv_img_dsc_t ICON_TWO_KEYS; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; +extern const lv_img_dsc_t ICON_WARNING; extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; +extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; +extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; extern const lv_img_dsc_t LARGE_ICON_BACKUP; -extern const lv_img_dsc_t ICON_BACKUP; -extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; -extern const lv_img_dsc_t LARGE_ICON_PIN; -extern const lv_img_dsc_t ICON_EXTENSIONS; -extern const lv_img_dsc_t ICON_BATTERY_CHARGING; -extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; extern const lv_img_dsc_t LARGE_ICON_CLOCK; -extern const lv_img_dsc_t ICON_BITCOIN; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; -extern const lv_img_dsc_t ICON_PAGE_QR_LG; -extern const lv_img_dsc_t ICON_NETWORK; -extern const lv_img_dsc_t ICON_BACK; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_BATTERY; -extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t LARGE_ICON_CONNECT; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_PIN; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t LARGE_ICON_SEED; +extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; extern const lv_img_dsc_t LARGE_ICON_SETUP; -extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t LARGE_ICON_SUCCESS; #endif #ifdef SCREEN_MODE_MONO -extern const lv_img_dsc_t ICON_CANCEL; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_1; -extern const lv_img_dsc_t ICON_PAGE_QR_MD; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_6; -extern const lv_img_dsc_t ICON_HOME; -extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; -extern const lv_img_dsc_t ICON_INFO; -extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; -extern const lv_img_dsc_t ICON_EXTENSIONS; -extern const lv_img_dsc_t ICON_ONE_KEY; -extern const lv_img_dsc_t LARGE_ICON_PIN; -extern const lv_img_dsc_t ICON_PAGE_QR_SM; -extern const lv_img_dsc_t ICON_PAGE_DOT; -extern const lv_img_dsc_t ICON_SHUTDOWN; -extern const lv_img_dsc_t ICON_FOLDER; -extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; +extern const lv_img_dsc_t ICON_ADD_ACCOUNT_BACKGROUND; +extern const lv_img_dsc_t ICON_ADD_ACCOUNT; +extern const lv_img_dsc_t ICON_ADVANCED_BACKGROUND; +extern const lv_img_dsc_t ICON_ADVANCED; +extern const lv_img_dsc_t ICON_BACKUP_BACKGROUND; extern const lv_img_dsc_t ICON_BACKUP; -extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; -extern const lv_img_dsc_t ICON_SIGN; -extern const lv_img_dsc_t LARGE_ICON_SHIELD; -extern const lv_img_dsc_t ICON_PAGE_PLUS; -extern const lv_img_dsc_t ICON_SHIELD; -extern const lv_img_dsc_t ICON_NETWORK; -extern const lv_img_dsc_t ICON_SPIRAL; -extern const lv_img_dsc_t ICON_SETUP; -extern const lv_img_dsc_t ICON_HAMBURGER; -extern const lv_img_dsc_t LARGE_ICON_CLOCK; -extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_5; -extern const lv_img_dsc_t ICON_RETRY; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_BATTERY_BACKGROUND; +extern const lv_img_dsc_t ICON_BATTERY_CHARGING; +extern const lv_img_dsc_t ICON_BATTERY; +extern const lv_img_dsc_t ICON_BITCOIN_BACKGROUND; +extern const lv_img_dsc_t ICON_BITCOIN; +extern const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND; extern const lv_img_dsc_t ICON_BRIGHTNESS; -extern const lv_img_dsc_t ICON_PAGE_HOME; -extern const lv_img_dsc_t LARGE_ICON_SUCCESS; -extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; -extern const lv_img_dsc_t ICON_WARNING; -extern const lv_img_dsc_t ICON_NOSTR; -extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_2; -extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_CASA; +extern const lv_img_dsc_t ICON_CHECKMARK; +extern const lv_img_dsc_t ICON_CIRCLE_CHECK_BACKGROUND; extern const lv_img_dsc_t ICON_CIRCLE_CHECK; -extern const lv_img_dsc_t ICON_ADVANCED; -extern const lv_img_dsc_t ICON_MICROSD; +extern const lv_img_dsc_t ICON_CLOCK_BACKGROUND; extern const lv_img_dsc_t ICON_CLOCK; -extern const lv_img_dsc_t ICON_SETTINGS; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_CONNECT_BACKGROUND; +extern const lv_img_dsc_t ICON_CONNECT; +extern const lv_img_dsc_t ICON_COUNTDOWN_BACKGROUND; extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t ICON_DEVICE_BACKGROUND; extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_PAGE_INDICATOR; +extern const lv_img_dsc_t ICON_ERASE_BACKGROUND; +extern const lv_img_dsc_t ICON_ERASE; +extern const lv_img_dsc_t ICON_EXTENSIONS_BACKGROUND; +extern const lv_img_dsc_t ICON_EXTENSIONS; +extern const lv_img_dsc_t ICON_FILE_BACKGROUND; +extern const lv_img_dsc_t ICON_FILE; +extern const lv_img_dsc_t ICON_FIRMWARE_BACKGROUND; +extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_FOLDER_BACKGROUND; +extern const lv_img_dsc_t ICON_FOLDER; extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t ICON_BATTERY_CHARGING; -extern const lv_img_dsc_t ICON_CASA; -extern const lv_img_dsc_t ICON_EDIT2; -extern const lv_img_dsc_t ICON_PASSPHRASE; -extern const lv_img_dsc_t LARGE_ICON_SETUP; -extern const lv_img_dsc_t ICON_BACK; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_0; -extern const lv_img_dsc_t ICON_BATTERY; -extern const lv_img_dsc_t ICON_TWO_KEYS; -extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; -extern const lv_img_dsc_t LARGE_ICON_SEED; -extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; +extern const lv_img_dsc_t ICON_HAMBURGER_BACKGROUND; +extern const lv_img_dsc_t ICON_HAMBURGER; +extern const lv_img_dsc_t ICON_HEALTH_CHECK_BACKGROUND; extern const lv_img_dsc_t ICON_HEALTH_CHECK; -extern const lv_img_dsc_t ICON_ERASE; -extern const lv_img_dsc_t ICON_ADD_ACCOUNT; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_4; -extern const lv_img_dsc_t LARGE_ICON_BACKUP; -extern const lv_img_dsc_t ICON_BITCOIN; -extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t ICON_MULTISIG; -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; -extern const lv_img_dsc_t ICON_PLUS; -extern const lv_img_dsc_t IMAGE_REGULATORY; -extern const lv_img_dsc_t ICON_CONNECT; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_3; +extern const lv_img_dsc_t ICON_HOME_BACKGROUND; +extern const lv_img_dsc_t ICON_HOME; +extern const lv_img_dsc_t ICON_INFO_BACKGROUND; +extern const lv_img_dsc_t ICON_INFO; extern const lv_img_dsc_t ICON_INPUT_MODE_LOWER_ALPHA; -extern const lv_img_dsc_t ICON_PIN; +extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; +extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; +extern const lv_img_dsc_t ICON_MICROSD_BACKGROUND; +extern const lv_img_dsc_t ICON_MICROSD; +extern const lv_img_dsc_t ICON_MULTISIG; +extern const lv_img_dsc_t ICON_NETWORK_BACKGROUND; +extern const lv_img_dsc_t ICON_NETWORK; +extern const lv_img_dsc_t ICON_NOSTR; +extern const lv_img_dsc_t ICON_ONE_KEY_BACKGROUND; +extern const lv_img_dsc_t ICON_ONE_KEY; +extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_PAGE_HOME; +extern const lv_img_dsc_t ICON_PAGE_INDICATOR; +extern const lv_img_dsc_t ICON_PAGE_PLUS; extern const lv_img_dsc_t ICON_PAGE_QR_LG; +extern const lv_img_dsc_t ICON_PAGE_QR_MD; +extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_PASSPHRASE_BACKGROUND; +extern const lv_img_dsc_t ICON_PASSPHRASE; +extern const lv_img_dsc_t ICON_PIN_BACKGROUND; +extern const lv_img_dsc_t ICON_PIN; +extern const lv_img_dsc_t ICON_PLUS; +extern const lv_img_dsc_t ICON_RETRY_BACKGROUND; +extern const lv_img_dsc_t ICON_RETRY; +extern const lv_img_dsc_t ICON_SCAN_QR_BACKGROUND; extern const lv_img_dsc_t ICON_SCAN_QR; +extern const lv_img_dsc_t ICON_SEED_BACKGROUND; +extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_SETTINGS_BACKGROUND; +extern const lv_img_dsc_t ICON_SETTINGS; +extern const lv_img_dsc_t ICON_SETUP_BACKGROUND; +extern const lv_img_dsc_t ICON_SETUP; +extern const lv_img_dsc_t ICON_SHIELD_BACKGROUND; +extern const lv_img_dsc_t ICON_SHIELD; +extern const lv_img_dsc_t ICON_SHUTDOWN; +extern const lv_img_dsc_t ICON_SIGN_BACKGROUND; +extern const lv_img_dsc_t ICON_SIGN; +extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_SPIRAL; +extern const lv_img_dsc_t ICON_TWO_KEYS_BACKGROUND; +extern const lv_img_dsc_t ICON_TWO_KEYS; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS_BACKGROUND; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; +extern const lv_img_dsc_t ICON_WARNING; +extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; +extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; +extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_0; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_1; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_2; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_3; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_4; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_5; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_6; extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; +extern const lv_img_dsc_t LARGE_ICON_BACKUP; +extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; +extern const lv_img_dsc_t LARGE_ICON_CLOCK; extern const lv_img_dsc_t LARGE_ICON_CONNECT; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_FIRMWARE; -extern const lv_img_dsc_t ICON_FILE; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_PIN; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t LARGE_ICON_SEED; +extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; +extern const lv_img_dsc_t LARGE_ICON_SETUP; +extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t LARGE_ICON_SUCCESS; #endif diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c new file mode 100644 index 000000000..d7cd4dd87 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND uint8_t ICON_ADD_ACCOUNT_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x00, + 0x3f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ADD_ACCOUNT_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ADD_ACCOUNT_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..0fc559530 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c new file mode 100644 index 000000000..37baac2de --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND uint8_t ICON_ADVANCED_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x0f, 0xff, 0xc0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ADVANCED_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ADVANCED_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..370ce8c05 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c new file mode 100644 index 000000000..0fb96beb6 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND uint8_t ICON_BACKUP_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x80, + 0x3f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BACKUP_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BACKUP_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..4dd67f558 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c new file mode 100644 index 000000000..b821e678e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND uint8_t ICON_BATTERY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x3f, 0xff, 0xc0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BATTERY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BATTERY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..1332b7a79 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c new file mode 100644 index 000000000..c6636ac7f --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND uint8_t ICON_BITCOIN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, + 0x00, 0xff, 0x00, + 0x0f, 0xff, 0x00, + 0x0f, 0xff, 0x00, + 0x0f, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x03, 0xff, 0xc0, + 0x03, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x0f, 0xff, 0x00, + 0x0f, 0xf0, 0x00, + 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BITCOIN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BITCOIN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..eb46d6be3 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c new file mode 100644 index 000000000..d78539ecd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND uint8_t ICON_BRIGHTNESS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x1e, 0x79, 0xe0, + 0x1f, 0x7b, 0xe0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x1f, 0x7b, 0xe0, + 0x1e, 0x79, 0xe0, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BRIGHTNESS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..2535e7c14 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c new file mode 100644 index 000000000..652f67e0e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND uint8_t ICON_CIRCLE_CHECK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x01, 0xfe, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CIRCLE_CHECK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CIRCLE_CHECK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..29f017679 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c new file mode 100644 index 000000000..5de1377c5 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND uint8_t ICON_CLOCK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x01, 0xfe, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CLOCK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CLOCK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..bc88391a3 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c new file mode 100644 index 000000000..9e71c0e14 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND uint8_t ICON_CONNECT_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x1f, 0xe0, + 0x00, 0x3f, 0xf0, + 0x00, 0x7f, 0xf8, + 0x00, 0x7f, 0xf8, + 0x00, 0x7f, 0xf8, + 0x03, 0xff, 0xf8, + 0x07, 0xff, 0xf8, + 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x3f, 0xf0, 0x00, + 0x1f, 0xe0, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CONNECT_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CONNECT_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..486b1e8ec Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c new file mode 100644 index 000000000..30ed3ccb8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND uint8_t ICON_COUNTDOWN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x7e, 0x00, + 0x00, 0x7f, 0x80, + 0x00, 0x7f, 0xc0, + 0x00, 0x7f, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_COUNTDOWN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_COUNTDOWN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..436203769 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c new file mode 100644 index 000000000..d7e046dd4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND uint8_t ICON_DEVICE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_DEVICE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_DEVICE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..2dd9b6f35 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1.c deleted file mode 100644 index 13a861703..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1 -#define LV_ATTRIBUTE_IMG_ICON_EDIT1 -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT1 uint8_t ICON_EDIT1_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xfe, 0xfe, 0xfe, 0x8f, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x07, 0xc0, - 0x00, 0x0f, 0xe0, - 0x00, 0x1e, 0x60, - 0x00, 0x3c, 0x60, - 0x00, 0x78, 0xe0, - 0x00, 0xf1, 0xe0, - 0x01, 0xe3, 0xc0, - 0x03, 0xc7, 0x80, - 0x07, 0x8f, 0x00, - 0x0f, 0x1e, 0x00, - 0x1e, 0x3c, 0x00, - 0x3c, 0x78, 0x00, - 0x38, 0xf0, 0x00, - 0x71, 0xe0, 0x00, - 0x73, 0xc0, 0x00, - 0x6f, 0x80, 0x00, - 0x7f, 0x00, 0x00, - 0xfc, 0x00, 0x00, - 0x40, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT1 = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 68, - .data = ICON_EDIT1_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png deleted file mode 100644 index 7fb884eab..000000000 Binary files a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png and /dev/null differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c deleted file mode 100644 index 6677684da..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2 -#define LV_ATTRIBUTE_IMG_ICON_EDIT2 -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT2 uint8_t ICON_EDIT2_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xfe, 0xfe, 0xfe, 0x84, /*Color of index 1*/ - - 0x00, 0x00, 0xc0, - 0x00, 0x03, 0xe0, - 0x3f, 0xc7, 0xf0, - 0x7f, 0xcf, 0x70, - 0xff, 0xde, 0xe0, - 0xe0, 0x3d, 0xe0, - 0xe0, 0x7b, 0xc0, - 0xe0, 0xf7, 0x80, - 0xe1, 0xef, 0x00, - 0xe3, 0xde, 0x00, - 0xe3, 0xbd, 0xc0, - 0xe3, 0x79, 0xc0, - 0xe3, 0xf1, 0xc0, - 0xe7, 0xe1, 0xc0, - 0xe2, 0x01, 0xc0, - 0xe0, 0x01, 0xc0, - 0xe0, 0x01, 0xc0, - 0x7f, 0xff, 0xc0, - 0x7f, 0xff, 0x80, - 0x1f, 0xff, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT2 = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 68, - .data = ICON_EDIT2_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2__CF_INDEXED_1_BIT.png deleted file mode 100644 index 83b624543..000000000 Binary files a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2__CF_INDEXED_1_BIT.png and /dev/null differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c new file mode 100644 index 000000000..7ee4d84b4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND uint8_t ICON_ERASE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ERASE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ERASE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..383fb23ef Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c new file mode 100644 index 000000000..a58b22e41 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND uint8_t ICON_EXTENSIONS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_EXTENSIONS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_EXTENSIONS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..d3679ff0f Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c new file mode 100644 index 000000000..8fae5a9cd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND uint8_t ICON_FILE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xff, 0x80, + 0x1f, 0xff, 0xc0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FILE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FILE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..1416b56da Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c new file mode 100644 index 000000000..bcbb4d6d1 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND uint8_t ICON_FIRMWARE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x0f, 0x7b, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FIRMWARE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FIRMWARE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..ab4a1e74b Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c new file mode 100644 index 000000000..e32d44bcd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND uint8_t ICON_FOLDER_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x00, + 0x3f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FOLDER_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FOLDER_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..0fc559530 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c new file mode 100644 index 000000000..624f6bec4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND uint8_t ICON_HAMBURGER_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HAMBURGER_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HAMBURGER_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..af8175cf4 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c new file mode 100644 index 000000000..9561ff111 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND uint8_t ICON_HEALTH_CHECK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x07, 0xcf, 0x80, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0xfc, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HEALTH_CHECK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HEALTH_CHECK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..2e8a484dc Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c new file mode 100644 index 000000000..0c1f9b1d1 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND uint8_t ICON_HOME_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HOME_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HOME_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..091f887c9 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c new file mode 100644 index 000000000..100a9ba7d --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND uint8_t ICON_INFO_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x03, 0xff, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x07, 0xff, 0xc0, + 0x03, 0xff, 0x00, +}; + +const lv_img_dsc_t ICON_INFO_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_INFO_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..a8914d400 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c new file mode 100644 index 000000000..35c91796e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND uint8_t ICON_MICROSD_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_MICROSD_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_MICROSD_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..ce36d48cf Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c new file mode 100644 index 000000000..7dbeb9dee --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND uint8_t ICON_NETWORK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x03, 0xc0, + 0x00, 0x07, 0xe0, + 0x00, 0x0f, 0xf0, + 0x00, 0x1f, 0xf8, + 0x0f, 0x7f, 0xf8, + 0x1f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0xc0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xf0, + 0x0f, 0x7f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x0f, 0xf0, + 0x00, 0x07, 0xe0, + 0x00, 0x03, 0xc0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_NETWORK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_NETWORK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..e8b126247 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c new file mode 100644 index 000000000..8c7231925 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND uint8_t ICON_ONE_KEY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, + 0x00, 0x01, 0xf0, + 0x00, 0x03, 0xf0, + 0x00, 0x07, 0xf0, + 0x00, 0x0f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x3f, 0xf8, + 0x0f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xe0, + 0x7f, 0xfb, 0xc0, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x3f, 0xf0, 0x00, + 0x3f, 0xf0, 0x00, + 0x0f, 0xc0, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ONE_KEY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ONE_KEY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..8ee3e462e Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c new file mode 100644 index 000000000..ef821d27d --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND uint8_t ICON_PASSPHRASE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_PASSPHRASE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_PASSPHRASE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..383fb23ef Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c new file mode 100644 index 000000000..8983be9a0 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND uint8_t ICON_PIN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_PIN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_PIN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..a616cc03a Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c new file mode 100644 index 000000000..c8dded83f --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND uint8_t ICON_RETRY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x07, 0xfe, 0x00, + 0x0f, 0xff, 0x3c, + 0x1f, 0xff, 0xbc, + 0x3f, 0xff, 0xfc, + 0x7f, 0x0f, 0xfc, + 0x7e, 0x07, 0xfc, + 0x7c, 0x03, 0xfc, + 0x78, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x78, + 0xff, 0x00, 0xf8, + 0xff, 0x81, 0xf8, + 0xff, 0xc3, 0xf8, + 0xff, 0xff, 0xf0, + 0xf7, 0xff, 0xe0, + 0xf3, 0xff, 0xc0, + 0x01, 0xff, 0x80, +}; + +const lv_img_dsc_t ICON_RETRY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_RETRY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..f25ae243a Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c new file mode 100644 index 000000000..91287f3b8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND uint8_t ICON_SCAN_QR_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x1f, 0xcf, 0xe0, + 0x3f, 0xcf, 0xf0, + 0x7f, 0xcf, 0xf8, + 0x7f, 0xcf, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0xc0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xcf, 0xf8, + 0x3f, 0xcf, 0xf0, + 0x1f, 0xcf, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SCAN_QR_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SCAN_QR_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..b4dc6de20 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED.c b/ports/stm32/boards/Passport/images/mono/ICON_SEED.c index 81f311f45..e56649ec6 100644 --- a/ports/stm32/boards/Passport/images/mono/ICON_SEED.c +++ b/ports/stm32/boards/Passport/images/mono/ICON_SEED.c @@ -21,26 +21,26 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SEED 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ - 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x00, - 0x00, 0x7c, 0x00, - 0x00, 0x60, 0x00, - 0x0f, 0xff, 0x00, - 0x1f, 0xff, 0x80, - 0x30, 0x00, 0xc0, - 0x20, 0x00, 0x40, - 0x30, 0x00, 0xc0, - 0x1f, 0xff, 0x80, - 0x1f, 0xff, 0x80, - 0x30, 0x00, 0xc0, - 0x30, 0x00, 0xc0, - 0x18, 0x01, 0x80, - 0x0c, 0x03, 0x00, - 0x06, 0x06, 0x00, - 0x03, 0x0c, 0x00, - 0x01, 0xf8, 0x00, - 0x00, 0x60, 0x00, - 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, + 0x00, 0x7c, 0x00, + 0x00, 0x60, 0x00, + 0x0f, 0xff, 0x00, + 0x1f, 0xff, 0x80, + 0x38, 0x01, 0xc0, + 0x30, 0x00, 0xc0, + 0x30, 0x00, 0xc0, + 0x1f, 0xff, 0x80, + 0x1f, 0xff, 0x80, + 0x30, 0x00, 0xc0, + 0x38, 0x01, 0xc0, + 0x1c, 0x03, 0x80, + 0x0e, 0x07, 0x00, + 0x07, 0x0e, 0x00, + 0x03, 0xfc, 0x00, + 0x01, 0xf8, 0x00, + 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, }; const lv_img_dsc_t ICON_SEED = { diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c new file mode 100644 index 000000000..57e18b885 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND uint8_t ICON_SEED_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x7f, 0x00, + 0x00, 0x7f, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SEED_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SEED_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..561df6bb0 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png index d6be54416..c10843985 100644 Binary files a/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png and b/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c new file mode 100644 index 000000000..996185cff --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND uint8_t ICON_SETTINGS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x01, 0xfe, 0x00, + 0x00, 0xfc, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SETTINGS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SETTINGS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..1435487e2 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c new file mode 100644 index 000000000..cbdec6274 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND uint8_t ICON_SETUP_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xf0, 0x00, + 0x0f, 0xf8, 0x00, + 0x0f, 0xfc, 0x00, + 0x7f, 0xfe, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x1f, 0xff, 0xf0, + 0x0f, 0xff, 0xf8, + 0x07, 0xff, 0xf8, + 0x00, 0x3f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x0f, 0xf8, + 0x00, 0x07, 0xf8, + 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SETUP_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SETUP_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..7ce47b30d Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c new file mode 100644 index 000000000..2fdf3747b --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND uint8_t ICON_SHIELD_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SHIELD_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SHIELD_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..383fb23ef Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c new file mode 100644 index 000000000..45b2ed727 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND uint8_t ICON_SIGN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x07, 0x80, + 0x00, 0x0f, 0xc0, + 0x00, 0x1f, 0xe0, + 0x00, 0x3f, 0xf0, + 0x00, 0x7f, 0xf0, + 0x00, 0xff, 0xf0, + 0x01, 0xff, 0xf0, + 0x03, 0xff, 0xe0, + 0x07, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x1f, 0xff, 0x00, + 0x1f, 0xfe, 0x00, + 0x3f, 0xfc, 0x00, + 0x3f, 0xf8, 0x00, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xbf, 0xf0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SIGN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SIGN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..2dd6d7650 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c new file mode 100644 index 000000000..23f69d7f8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND uint8_t ICON_TWO_KEYS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, + 0x00, 0x1f, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x7f, 0x00, + 0x0f, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xc0, + 0x0f, 0xff, 0x00, + 0x07, 0xff, 0x00, + 0x07, 0xff, 0x00, + 0x03, 0xfe, 0x00, + 0x03, 0xfe, 0x00, + 0x00, 0xf8, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_TWO_KEYS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_TWO_KEYS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..e9ceaba40 Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c new file mode 100644 index 000000000..a224fb3fd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND uint8_t ICON_VERIFY_ADDRESS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, + 0x00, 0x00, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_VERIFY_ADDRESS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_VERIFY_ADDRESS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..93a1475cc Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c index 28061f41f..4c01bfd9c 100644 --- a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c +++ b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later // @@ -18,69 +18,69 @@ #endif const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LARGE_ICON_BRANDMARK uint8_t LARGE_ICON_BRANDMARK_map[] = { - 0x07, 0x07, 0x0a, 0x07, /*Color of index 0*/ - 0x8a, 0x98, 0xcf, 0xef, /*Color of index 1*/ + 0xfe, 0xfe, 0xfe, 0xff, /*Color of index 0*/ + 0x1a, 0x19, 0x19, 0xff, /*Color of index 1*/ - 0x00, 0x00, 0x02, 0xf0, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xe0, 0xff, 0xc0, 0x00, 0x00, - 0x00, 0x01, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xc0, 0x7f, 0xfc, 0x00, 0x00, - 0x00, 0x0f, 0xff, 0xc0, 0x3f, 0xff, 0x00, 0x00, - 0x00, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0x80, 0x00, - 0x00, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0xc0, 0x00, - 0x00, 0x7f, 0xff, 0x00, 0x0f, 0xff, 0xe0, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xf0, 0x00, - 0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00, - 0x03, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xfc, 0x00, - 0x07, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xfc, 0x00, - 0x07, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xfe, 0x00, - 0x0f, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xff, 0x00, - 0x0f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x1f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x80, - 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0x80, - 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xc0, - 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x3f, 0xff, 0xc0, - 0x7f, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xe0, - 0x7f, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xe0, - 0x7f, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, - 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, - 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, - 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, - 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, - 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, - 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, - 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, - 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, - 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, - 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, - 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, - 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, - 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xf0, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xe2, 0x7f, 0xf0, 0x00, 0x00, + 0x00, 0x03, 0xff, 0xc0, 0x3f, 0xfc, 0x00, 0x00, + 0x00, 0x07, 0xfe, 0xc2, 0x37, 0xfe, 0x00, 0x00, + 0x00, 0x1f, 0xfd, 0x81, 0x1b, 0xff, 0x80, 0x00, + 0x00, 0x3f, 0xfb, 0x00, 0x8d, 0xff, 0xc0, 0x00, + 0x00, 0x7f, 0xeb, 0x02, 0x0d, 0x7f, 0xe0, 0x00, + 0x00, 0xff, 0xb6, 0x01, 0x46, 0xdf, 0xf0, 0x00, + 0x01, 0xff, 0xea, 0x00, 0x05, 0x7f, 0xf8, 0x00, + 0x03, 0xff, 0x2c, 0x02, 0xa3, 0x4f, 0xfc, 0x00, + 0x03, 0xfd, 0xd8, 0x00, 0x11, 0xbb, 0xfc, 0x00, + 0x07, 0xff, 0x28, 0x02, 0x81, 0x4f, 0xfe, 0x00, + 0x0f, 0xfa, 0xd0, 0x00, 0x50, 0xb5, 0xff, 0x00, + 0x0f, 0xf6, 0x90, 0x02, 0x04, 0x96, 0xff, 0x00, + 0x1f, 0xfd, 0x60, 0x00, 0xa0, 0x6b, 0xff, 0x80, + 0x1f, 0xd2, 0x40, 0x01, 0x08, 0x24, 0xbf, 0x80, + 0x3f, 0xf6, 0xc0, 0x00, 0x22, 0x36, 0xff, 0xc0, + 0x3f, 0xd4, 0x80, 0x02, 0x80, 0x12, 0xbf, 0xc0, + 0x3e, 0xea, 0x80, 0x00, 0x14, 0x15, 0x6f, 0xc0, + 0x7f, 0xd5, 0x00, 0x01, 0x01, 0x0a, 0xbf, 0xe0, + 0x7f, 0xaa, 0x00, 0x00, 0x44, 0x05, 0x5f, 0xe0, + 0x7e, 0xda, 0x00, 0x02, 0x10, 0x45, 0xb7, 0xe0, + 0x7f, 0x52, 0x00, 0x00, 0x41, 0x04, 0xaf, 0xe0, + 0xff, 0xd4, 0x00, 0x01, 0x00, 0x02, 0xbf, 0xf0, + 0xfb, 0x28, 0x00, 0x00, 0x08, 0x41, 0x4d, 0xf0, + 0xff, 0xd8, 0x00, 0x00, 0x41, 0x01, 0xbf, 0xf0, + 0xfe, 0x90, 0x00, 0x02, 0x04, 0x08, 0x97, 0xf0, + 0xfd, 0xb0, 0x00, 0x00, 0x10, 0x00, 0xdb, 0xf0, + 0xfe, 0xa0, 0x00, 0x00, 0x80, 0x20, 0x57, 0xf0, + 0xf7, 0x40, 0x00, 0x02, 0x00, 0x80, 0x2e, 0xf0, + 0xfe, 0xc0, 0x00, 0x00, 0x04, 0x02, 0x37, 0xf0, + 0xfe, 0xc0, 0x00, 0x00, 0x20, 0x00, 0x37, 0xf0, + 0x76, 0x80, 0x00, 0x00, 0x80, 0x08, 0x16, 0xe0, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8f, 0xe0, + 0x7d, 0x00, 0x00, 0x02, 0x02, 0x00, 0x0b, 0xe0, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xe0, + 0x3e, 0x00, 0x00, 0x00, 0x10, 0x02, 0x07, 0xc0, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x23, 0xc0, + 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xc0, + 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x80, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x21, 0x09, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x03, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xcc, 0x00, + 0x00, 0xd7, 0xff, 0xff, 0xff, 0xfe, 0xb0, 0x00, + 0x00, 0x2d, 0xff, 0xff, 0xff, 0xfb, 0x40, 0x00, + 0x00, 0x52, 0xbf, 0xff, 0xff, 0xd4, 0xa0, 0x00, + 0x00, 0x36, 0xd7, 0xff, 0xfe, 0xb6, 0xc0, 0x00, + 0x00, 0x04, 0xad, 0x6f, 0x6b, 0x52, 0x00, 0x00, + 0x00, 0x05, 0x5a, 0xdb, 0xb5, 0xaa, 0x00, 0x00, + 0x00, 0x01, 0x22, 0xad, 0x54, 0x48, 0x00, 0x00, + 0x00, 0x00, 0xad, 0x56, 0xab, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xa9, 0x51, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x0b, 0x26, 0x4d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa9, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, }; const lv_img_dsc_t LARGE_ICON_BRANDMARK = { diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png index 9a5137682..53d14b5ac 100644 Binary files a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png and b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 88d716e5b..ba65a05bb 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -94,7 +94,6 @@ 'flows/export_multisig_microsd_flow.py', 'flows/export_multisig_qr_flow.py', 'flows/export_summary_flow.py', - # 'flows/fcc_test_flow.py', 'flows/file_picker_flow.py', 'flows/flow.py', 'flows/format_microsd_flow.py', @@ -114,6 +113,9 @@ 'flows/magic_scan_sign_psbt_flow.py', 'flows/magic_scan_validate_address_flow.py', + 'flows/scan_qr_flow.py', + 'flows/series_of_pages_flow.py', + 'flows/system_test_flow.py', 'flows/system_test_camera_flow.py', 'flows/system_test_microsd_flow.py', @@ -126,6 +128,7 @@ 'flows/new_seed_flow.py', 'flows/connect_wallet_flow.py', 'flows/page_flow.py', + 'flows/read_file_flow.py', 'flows/remove_dev_pubkey_flow.py', 'flows/rename_account_flow.py', 'flows/rename_derived_key_flow.py', @@ -133,7 +136,6 @@ 'flows/reset_pin_flow.py', 'flows/restore_backup_flow.py', 'flows/restore_seed_flow.py', - 'flows/scan_private_key_qr_flow.py', 'flows/save_to_microsd_flow.py', 'flows/scv_flow.py', 'flows/seed_warning_flow.py', @@ -173,6 +175,9 @@ 'pages/file_picker_page.py', 'pages/info_page.py', 'pages/insert_microsd_page.py', + 'pages/long_error_page.py', + 'pages/long_question_page.py', + 'pages/long_success_page.py', 'pages/long_text_page.py', 'pages/menu_page.py', 'pages/page.py', diff --git a/ports/stm32/boards/Passport/manifest_dev.py b/ports/stm32/boards/Passport/manifest_dev.py index 665ff12f6..484515427 100644 --- a/ports/stm32/boards/Passport/manifest_dev.py +++ b/ports/stm32/boards/Passport/manifest_dev.py @@ -9,6 +9,9 @@ 'developer/battery_page.py', 'developer/delete_derived_keys_flow.py', 'developer/developer_functions_flow.py', + 'developer/fcc_test_flow.py', + 'developer/fcc_copy_files_task.py', + 'developer/nostr_delegation_flow.py', 'developer/spin_delay_flow.py', )) diff --git a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py index 1a2483086..6c7f19cec 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py @@ -29,10 +29,17 @@ def is_complete(self): return self.data is not None def decode(self, **kwargs): - return self.data + from utils import get_words_from_seed + + (seed_phrase, error) = get_words_from_seed(self.data) + + if error is not None or seed_phrase is None: + return None + + return seed_phrase def qr_type(self): - return QRType.QR + return QRType.COMPACT_SEED_QR class CompactSeedQREncoder(DataEncoder): @@ -83,4 +90,4 @@ def sample(cls, data): # Number of bytes required to successfully recognize this format @classmethod def min_sample_size(cls): - return 1 + return 16 diff --git a/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py b/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py index ef101b909..c8c56b410 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py @@ -37,3 +37,6 @@ def decode(self): # - etc. def qr_type(self): pass + + def num_frames(self): + return 1 diff --git a/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py b/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py index 55d432b64..7e4477ba2 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py @@ -9,16 +9,20 @@ from .qr_codec import QREncoder, QRDecoder, QRSampler from .ur1_codec import UR1Encoder, UR1Decoder, UR1Sampler from .ur2_codec import UR2Encoder, UR2Decoder, UR2Sampler -from .compact_seedqr_codec import CompactSeedQREncoder -from .seedqr_codec import SeedQREncoder +from .compact_seedqr_codec import CompactSeedQREncoder, CompactSeedQRDecoder, CompactSeedQRSampler +from .seedqr_codec import SeedQREncoder, SeedQRDecoder, SeedQRSampler from .qr_type import QRType qrs = [ {'type': QRType.UR2, 'encoder': UR2Encoder, 'decoder': UR2Decoder, 'sampler': UR2Sampler}, {'type': QRType.UR1, 'encoder': UR1Encoder, 'decoder': UR1Decoder, 'sampler': UR1Sampler}, {'type': QRType.QR, 'encoder': QREncoder, 'decoder': QRDecoder, 'sampler': QRSampler}, - {'type': QRType.COMPACT_SEED_QR, 'encoder': CompactSeedQREncoder, 'decoder': None, 'sampler': None}, - {'type': QRType.SEED_QR, 'encoder': SeedQREncoder, 'decoder': None, 'sampler': None}, + # All QR codecs that accept any data (sample always returns true) should go after QR type + # And they should explicitly pass their type to the ScanQRPage or ScanQRFlow + {'type': QRType.COMPACT_SEED_QR, 'encoder': CompactSeedQREncoder, + 'decoder': CompactSeedQRDecoder, 'sampler': CompactSeedQRSampler}, + {'type': QRType.SEED_QR, 'encoder': SeedQREncoder, + 'decoder': SeedQRDecoder, 'sampler': SeedQRSampler}, ] @@ -29,6 +33,13 @@ def make_qr_encoder(qr_type): return None +def make_qr_decoder(qr_type): + for entry in qrs: + if entry['type'] == qr_type: + return entry['decoder']() + return None + + def make_qr_decoder_from_data(data): """Given a data sample, return its decoder.""" diff --git a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py index 914899032..67e2e2da8 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py @@ -13,6 +13,7 @@ from .data_decoder import DataDecoder from .data_sampler import DataSampler from .qr_type import QRType +from public_constants import SEED_LENGTHS class SeedQRDecoder(DataDecoder): @@ -29,10 +30,24 @@ def is_complete(self): return self.data is not None def decode(self, **kwargs): - return self.data + import trezorcrypto + + try: + seed_phrase = [] + num_words = int(len(self.data) / 4) + for i in range(0, num_words): + index = int(self.data[i * 4: (i * 4) + 4]) + word = trezorcrypto.bip39.get_word(index) + seed_phrase.append(word) + if len(seed_phrase) in SEED_LENGTHS: + return seed_phrase + else: + return None + except Exception as e: + return None def qr_type(self): - return QRType.QR + return QRType.SEED_QR class SeedQREncoder(DataEncoder): @@ -65,4 +80,4 @@ def sample(cls, data): # Number of bytes required to successfully recognize this format @classmethod def min_sample_size(cls): - return 1 + return 48 diff --git a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py index 2da37133d..1710da6db 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py @@ -20,12 +20,13 @@ class UR2Decoder(DataDecoder): def __init__(self): ur.decoder_clear() self.value = None + self.frames = 0 def add_data(self, data): data = data.lower() try: - ur.decoder_receive(data) + self.frames = ur.decoder_receive(data) except ur.NotMultiPartError as exc: if ur.decoder_is_empty(): try: @@ -68,6 +69,9 @@ def decode(self): def qr_type(self): return QRType.UR2 + def num_frames(self): + return self.frames + class UR2Encoder(DataEncoder): def encode(self, value, max_fragment_len=200): diff --git a/ports/stm32/boards/Passport/modules/derived_key.py b/ports/stm32/boards/Passport/modules/derived_key.py index 454960910..3bfc6eb02 100644 --- a/ports/stm32/boards/Passport/modules/derived_key.py +++ b/ports/stm32/boards/Passport/modules/derived_key.py @@ -5,29 +5,32 @@ import lvgl as lv from tasks import bip85_24_word_seed_task, bip85_12_word_seed_task, nostr_key_task +from menus import nostr_menu # Each key generation task must take index as args, whether or not they use it. +# Each task must return ({'priv', , etc.}, None) # tn stands for Type Number key_types = [ {'tn': 0, 'title': '24 Word Seed', - 'icon': lv.ICON_SEED, + 'icon': 'ICON_SEED', 'indexed': True, 'words': True, 'task': bip85_24_word_seed_task}, {'tn': 1, 'title': '12 Word Seed', - 'icon': lv.ICON_SEED, + 'icon': 'ICON_SEED', 'indexed': True, 'words': True, 'task': bip85_12_word_seed_task}, {'tn': 2, 'title': 'Nostr Key', - 'icon': lv.ICON_NOSTR, + 'icon': 'ICON_NOSTR', 'indexed': True, 'words': False, 'task': nostr_key_task, - 'continue_text': 'post on your behalf'}, + 'continue_text': 'post on your behalf', + 'menu': nostr_menu}, ] diff --git a/ports/stm32/boards/Passport/modules/developer/__init__.py b/ports/stm32/boards/Passport/modules/developer/__init__.py index bcfa2032f..8434e6ffc 100644 --- a/ports/stm32/boards/Passport/modules/developer/__init__.py +++ b/ports/stm32/boards/Passport/modules/developer/__init__.py @@ -3,7 +3,10 @@ # # __init__.py +from .battery_page import * +from .delete_derived_keys_flow import * from .developer_functions_flow import * +from .fcc_copy_files_task import * +from .fcc_test_flow import * +from .nostr_delegation_flow import * from .spin_delay_flow import * -from .delete_derived_keys_flow import * -from .battery_page import * diff --git a/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py b/ports/stm32/boards/Passport/modules/developer/fcc_copy_files_task.py similarity index 97% rename from ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py rename to ports/stm32/boards/Passport/modules/developer/fcc_copy_files_task.py index 13b99d000..45c92b92c 100644 --- a/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py +++ b/ports/stm32/boards/Passport/modules/developer/fcc_copy_files_task.py @@ -9,7 +9,7 @@ from errors import Error -async def fcc_copy_files_task(file_path, file_size=1024, set_progress=None, set_text=None, on_done=None): +async def fcc_copy_files_task(file_path, file_size, set_progress, set_text, on_done): from common import sf # ========================================================================================================== diff --git a/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py new file mode 100644 index 000000000..12659ffe7 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# fcc_test_flow.py - Flow to iterate through a test loop indefinitely + +from animations.constants import TRANSITION_DIR_POP +import lvgl as lv +from flows import Flow, ScanQRFlow +import microns +from pages import ProgressPage +from styles.colors import COPPER +from developer import fcc_copy_files_task +from utils import start_task +from files import CardSlot +import common +from uasyncio import sleep_ms +from errors import Error + +_CAMERA_DISPLAY_DURATION_SECS = const(5 * 1000) +_FILE_SIZE_TO_CREATE = const(250 * 1024) + + +class FCCTestFlow(Flow): + def __init__(self): + super().__init__(initial_state=self.show_camera, name='FccTestFlow') + self.progress_page = None + + async def show_camera(self): + result = await ScanQRFlow(auto_close_timeout=_CAMERA_DISPLAY_DURATION_SECS, + data_description='a normal QR code').run() + + # User used a button to back out + if result is None: + self.set_result(False) + return + + self.goto(self.copy_files) + + async def copy_files(self): + self.progress_page = ProgressPage(card_header={'title': 'Copy Files'}, + text='Copying files from microSD to flash and back.', + left_micron=microns.Cancel, + right_micron=microns.Cancel) + + copy_files_task = start_task( + fcc_copy_files_task(CardSlot.get_file_path('fcc-file-copy-test.bin')[0], + _FILE_SIZE_TO_CREATE, + self.progress_page.set_progress, + self.progress_page.set_text, + self.on_done)) + + result = await self.progress_page.show() + if result is not None: + # User used a button to back out, so cancel the task. and return from the page + copy_files_task.cancel() + self.set_result(False) + self.progress_page = None + return + + # NOTE: This sleep is necessary to avoid starting to animate to the next page + # while the previous animation is still active (which causes a crash) + await sleep_ms(2000) + self.back() + + async def on_done(self, error): + # If user backed out, long_text_page will be None, so nothing to do + if self.progress_page is None: + return + + common.page_transition_dir = TRANSITION_DIR_POP + if error is Error.MICROSD_CARD_MISSING: + self.progress_page.set_icon(lv.LARGE_ICON_MICROSD, color=COPPER) + self.progress_page.set_text('Please insert microSD card.') + self.progress_page.set_result(None) + else: + self.progress_page.set_progress(100) + self.progress_page.set_icon(lv.LARGE_ICON_SUCCESS) + self.progress_page.set_result(None) diff --git a/ports/stm32/boards/Passport/modules/developer/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/developer/nostr_delegation_flow.py new file mode 100644 index 000000000..073282e26 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/developer/nostr_delegation_flow.py @@ -0,0 +1,376 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# nostr_delegation_flow.py - Sign a nostr delegation token + +from flows import Flow + + +def created_at_helper(carrot, created_at): + created = [c for c in created_at if c.count(carrot)] + assert len(created) <= 1, 'There must only be 1 "created {}" condition.'.format( + 'before' if carrot == '<' else 'after') + + if len(created) == 0: + return None + + return int(created[0].split(carrot)[1]) + + +event_kind = { + 0: 'Metadata', + 1: 'Short Text Notes', + 2: 'Recommend Relays', + 3: 'Contacts', + 4: 'Encrypted Direct Messages', + 5: 'Event Deletion', + 6: 'Reposts', + 7: 'Reactions', + 8: 'Badge Awards', + 40: 'Channel Creation', + 41: 'Channel Metadata', + 42: 'Channel Messages', + 43: 'Channel Hide Messages', + 44: 'Channel Mute Users', + 1984: 'Reporting', + 9731: 'Zap Requests', + 9735: 'Zaps', + 10000: 'Mute Lists', + 10001: 'Pin Lists', + 10002: 'Relay List Metadata', + 24133: 'Nostr Connect', + 30000: 'Categorized People Lists', + 30001: 'Categorized Bookmark Lists', + 30008: 'Profile Badges', + 30009: 'Badge Definitions', + 30023: 'Long-Form Content', + 30078: 'Application-Specific Data', +} + + +def parse_delegation_string(delegation_string): + from ubinascii import unhexlify as a2b_hex + from utils import nostr_nip19_from_key + import re + + fields = delegation_string.split(':') + num_fields = len(fields) + assert num_fields == 4, \ + 'Invalid delegation string: must have 4 fields, found {}'.format(num_fields) + assert fields[0] == 'nostr' and fields[1] == 'delegation', \ + 'First 2 fields of delegation string must be "nostr:delegation:"' + + try: + delegatee = a2b_hex(fields[2]) + except Exception as e: + raise Exception('Invalid delegatee format') + + assert len(delegatee) == 32, 'Invalid delegatee length' + delegatee_npub = nostr_nip19_from_key(delegatee, "npub") + + assert len(fields[3]) > 0, \ + 'Delegation conditions are required, found none' + + conditions = fields[3].split('&') + + assert len(set(conditions)) == len(conditions), 'Duplicate conditions found' + + # TODO: what are the condition parsing rules? Can multiple kinds be given different + # created_at rules within 1 delegation? I assume not for now. This means + # all 'kind' conditions must come before all 'created_at' conditions. + + kind_pattern = re.compile('^kind=\\d+$') + created_at_pattern = re.compile('^created_at[\\<\\>]\\d+$') + kinds = [] + created_at = [] + + # Get all kinds + for c in conditions: + if kind_pattern.search(c): + kinds.append(c) + else: + break + + assert len(kinds) > 0, 'Event kinds are required.' + + # remove all found kinds from conditions before continuing + for k in kinds: + conditions.remove(k) + + # Get all created_at + for c in conditions: + if created_at_pattern.search(c): + created_at.append(c) + else: + assert not kind_pattern.search(c), \ + 'All "kinds" must come before all "created_at" conditions.' + break + + # This throws an assertion if there are multiple of either condition + created_before = created_at_helper('<', created_at) + created_after = created_at_helper('>', created_at) + + if created_before is not None and created_after is not None: + assert created_after < created_before, 'Start date must be before end date.' + + # remove all created at to leave invalid condition and any following conditions + for c in created_at: + conditions.remove(c) + + # any remaining conditions didn't match + conditions = list(set(conditions) - set(created_at)) + assert len(conditions) == 0, \ + 'Invalid condition found:\n{}'.format(conditions[0]) + + kinds = list(map(lambda k: int(k.split('=')[1]), kinds)) + + # All inputs checked + return delegatee_npub, created_before, created_after, kinds + + +def format_delegation_string(delegatee_npub, created_before, created_after, kinds): + from utils import timestamp_to_str, recolor + import uio + from styles.colors import HIGHLIGHT_TEXT_HEX + + details = uio.StringIO() + details.write("\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegating To:'), + delegatee_npub)) + + details.write("\n\n") + + if created_after is not None: + details.write("{}\n{} UTC\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), + timestamp_to_str(created_after), + "Make sure this time isn't in the past.")) + else: + details.write("{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), + "No start date, use caution.")) + + details.write("\n\n") + + if created_before is not None: + details.write("{}\n{} UTC".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), + timestamp_to_str(created_before))) + else: + details.write("{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), + "No end date, use caution.")) + + details.write("\n\n") + + details.write("{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Event Types:'))) + + for k in kinds: + details.write("\n{}: {}".format( + k, event_kind.get(k, "Unknown event, use caution."))) + + return details.getvalue() + + +class NostrDelegationFlow(Flow): + def __init__(self, context=None): + from derived_key import get_key_type_from_tn + + self.key = context + self.key_type = get_key_type_from_tn(self.key['tn']) + self.pk = None + self.npub = None + self.delegation_string = None + self.delegatee_npub = None + self.created_before = None + self.created_after = None + self.kinds = None + self.use_qr = None + self.orig_path = None + self.basename = None + super().__init__(initial_state=self.show_warning, name='NostrDelegationFlow') + + async def show_warning(self): + from flows import SeedWarningFlow + + result = await SeedWarningFlow(action_text="sign a Nostr delegation" + .format(self.key_type['title']), + continue_text="post on your behalf").run() + if not result: + self.set_result(False) + return + + self.goto(self.choose_mode) + + async def choose_mode(self): + from pages import ChooserPage + + options = [{'label': 'Delegate via QR', 'value': True}, + {'label': 'Delegate via microSD', 'value': False}] + + mode = await ChooserPage(card_header={'title': 'Export Mode'}, options=options).show() + + if mode is None: + self.set_result(False) + return + + self.use_qr = mode + self.goto(self.export_npub) + + async def export_npub(self): + from utils import spinner_task, get_folder_path + from pages import ShowQRPage, ErrorPage, InfoPage + from flows import SaveToMicroSDFlow + from ubinascii import unhexlify as a2b_hex + import microns + from public_constants import DIR_KEY_MNGR + + (vals, error) = await spinner_task(text='Generating npub', + task=self.key_type['task'], + args=[self.key['index']]) + self.pk = vals['pk'] + # self.pk = a2b_hex("ee35e8bb71131c02c1d7e73231daa48e9953d329a4b701f7133c8f46dd21139c") + self.npub = vals['npub'] + + if not self.pk or not self.npub: + await ErrorPage("Failed to generate npub and nsec").show() + self.set_result(False) + return + + if self.use_qr: + result = await ShowQRPage(caption='Scan this npub QR code with your Nostr client', + qr_data=self.npub, + left_micron=microns.Cancel).show() + else: + result = await InfoPage('Copy the following npub into your Nostr client', + left_micron=microns.Cancel).show() + + if not result: + self.set_result(False) + return + + filename = '{}-{}-npub.txt'.format(self.key_type['title'], self.key['name']) + result = await SaveToMicroSDFlow(filename=filename, + data=self.npub, + path=get_folder_path(DIR_KEY_MNGR), + success_text="Nostr npub").run() + + if not result: + self.set_result(False) + return + + self.goto(self.scan_delegation_string) + + async def scan_delegation_string(self): + from pages import ErrorPage, InfoPage + import microns + from flows import FilePickerFlow, ReadFileFlow, ScanQRFlow + + if self.use_qr: + info_text = 'On the next screen, scan the delegation details QR from your Nostr client' + else: + info_text = 'Next, select the delegation details file from your SD card' + result = await InfoPage(text=info_text, left_micron=microns.Cancel).show() + + if not result: + self.set_result(False) + return + + if self.use_qr: + result = await ScanQRFlow(data_description='a Nostr delegation description').run() + + if result is None: + return # return to InfoPage + + self.delegation_string = result + else: + result = await FilePickerFlow(show_folders=True).run() + + if result is None: + return # return to InfoPage + + filename, full_path, is_folder = result + data = await ReadFileFlow(file_path=full_path, binary=False).run() + + if data is None: + return # return to InfoPage + + self.orig_path, self.basename = full_path.rsplit('/', 1) + self.delegation_string = data.strip() + + try: + self.delegatee_npub, self.created_before, self.created_after, self.kinds = \ + parse_delegation_string(self.delegation_string) + except Exception as e: + await ErrorPage('{}'.format(e)).show() + return # return to InfoPage + + self.goto(self.display_details) + + async def display_details(self): + from pages import LongTextPage + import microns + + details = format_delegation_string(self.delegatee_npub, + self.created_before, + self.created_after, + self.kinds) + + result = await LongTextPage(text=details, + centered=True, + card_header={'title': 'Delegation Details'}, + left_micron=microns.Cancel, + right_micron=microns.Checkmark).show() + if not result: + self.set_result(False) + return + + self.goto(self.sign_delegation) + + async def sign_delegation(self): + from serializations import sha256 + from utils import nostr_sign, B2A + from pages import ShowQRPage, InfoPage + import microns + from flows import SaveToMicroSDFlow + + sha = sha256(self.delegation_string) + sig = B2A(nostr_sign(self.pk, sha)) + + if self.use_qr: + result = await ShowQRPage(caption='Scan this QR code with your Nostr client', + qr_data=sig, + right_micron=microns.Checkmark).show() + if not result: + self.back() + return + else: + result = await InfoPage('Copy the following delegation code into your Nostr client', + left_micron=microns.Back).show() + + if not result: + self.back() + return + + # Name resulting file after original file + target_fname = self.basename.rsplit('.', 1)[0] + '-signed.txt' + result = await SaveToMicroSDFlow(filename=target_fname, + data=sig, + path=self.orig_path, + success_text="Nostr delegation").run() + + self.goto(self.show_success) + + async def show_success(self): + from pages import SuccessPage + import microns + + result = await SuccessPage(text='Delegation complete', + left_micron=microns.Back).show() + + if not result: + self.back() + return + + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/errors.py b/ports/stm32/boards/Passport/modules/errors.py index 059f1c88b..e99f12b93 100644 --- a/ports/stm32/boards/Passport/modules/errors.py +++ b/ports/stm32/boards/Passport/modules/errors.py @@ -24,4 +24,5 @@ 'SECURE_ELEMENT_ERROR', 'USER_SETTINGS_FULL', 'PSBT_TOO_LARGE', + 'PSBT_OVERSIZED', ) diff --git a/ports/stm32/boards/Passport/modules/extensions/casa_extension.py b/ports/stm32/boards/Passport/modules/extensions/casa_extension.py index e6cd62aef..d2282983a 100644 --- a/ports/stm32/boards/Passport/modules/extensions/casa_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/casa_extension.py @@ -14,7 +14,7 @@ # Casa account - account number is zero, but they use a special derivation path name = 'casa' casa_account = {'name': 'Casa', 'acct_num': 0} -icon = lv.ICON_CASA +icon = 'ICON_CASA' CasaExtension = { 'name': name, @@ -29,7 +29,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': casa_account.get('name'), 'page_micron': microns.PageDot, 'bg_color': CASA_PURPLE, diff --git a/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py b/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py index 30cf9960a..ef491f8f5 100644 --- a/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py @@ -13,7 +13,7 @@ name = 'key_manager' label = 'Key Manager' -icon = lv.ICON_ONE_KEY +icon = 'ICON_ONE_KEY' KeyManagerExtension = { 'name': name, @@ -28,7 +28,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': label, 'page_micron': microns.PageDot, 'bg_color': LIGHT_COPPER, diff --git a/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py b/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py index aa5eeb2ff..3873211f2 100644 --- a/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py @@ -14,7 +14,7 @@ # Postmix account for CoinJoin name = 'postmix' postmix_account = {'name': 'Postmix', 'acct_num': 2_147_483_646} -icon = lv.ICON_SPIRAL +icon = 'ICON_SPIRAL' PostmixExtension = { 'name': name, @@ -29,7 +29,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': postmix_account.get('name'), 'page_micron': microns.PageDot, 'bg_color': RED, diff --git a/ports/stm32/boards/Passport/modules/files.py b/ports/stm32/boards/Passport/modules/files.py index 08a3d6ae3..6fed3ed02 100644 --- a/ports/stm32/boards/Passport/modules/files.py +++ b/ports/stm32/boards/Passport/modules/files.py @@ -168,19 +168,9 @@ def pick_filename(self, pattern, path=None): basename, ext = pattern.rsplit('.', 1) ext = '.' + ext - # try w/o any number first - fname = path + '/' + basename + ext - try: - os.stat(fname) - except OSError as e: - if e.args[0] == ENOENT: - # file doesn't exist, done - return fname, basename + ext - pass - # look for existing numbered files, even if some are deleted, and pick next # highest filename - highest = 1 + highest = 0 pat = ure.compile(basename + r'-(\d+)' + ext) files = uos.ilistdir(path) @@ -190,7 +180,7 @@ def pick_filename(self, pattern, path=None): continue highest = max(highest, int(m.group(1))) - fname = path + '/' + basename + ('-%d' % (highest + 1)) + ext + fname = path + '/' + basename + ('-%03d' % (highest + 1)) + ext return fname, fname[len(path):] diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index b4b7d9497..72719015f 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -11,8 +11,10 @@ from .main_flow import * from .login_flow import * from .save_to_microsd_flow import * +from .scan_qr_flow import * from .backup_common_flow import * from .seed_warning_flow import * +from .series_of_pages_flow import * # QR Magic Scan flows from .magic_scan_import_multisig_flow import * @@ -36,7 +38,6 @@ from .export_multisig_microsd_flow import * from .export_multisig_qr_flow import * from .export_summary_flow import * -# from .fcc_test_flow import * from .selected_file_flow import * from .file_picker_flow import * from .format_microsd_flow import * @@ -51,6 +52,7 @@ from .new_derived_key_flow import * from .new_seed_flow import * from .connect_wallet_flow import * +from .read_file_flow import * from .remove_dev_pubkey_flow import * from .rename_account_flow import * from .rename_derived_key_flow import * @@ -58,7 +60,6 @@ from .reset_pin_flow import * from .restore_backup_flow import * from .restore_seed_flow import * -from .scan_private_key_qr_flow import * from .scv_flow import * from .set_chain_flow import * from .set_initial_pin_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index fc57a9af7..32771d4a8 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -4,74 +4,138 @@ # apply_passphrase_flow.py - Ask user to enter a passphrase, then apply it. from flows import Flow -from pages import SuccessPage, TextInputPage, ErrorPage, QuestionPage -from tasks import apply_passphrase_task -from utils import spinner_task -from errors import Error -from translations import t, T -from constants import MAX_PASSPHRASE_LENGTH class ApplyPassphraseFlow(Flow): def __init__(self, passphrase=None): + import stash # Caller wants to set this passphrase - if passphrase is not None: - self.passphrase = passphrase - super().__init__(initial_state=self.apply_passphrase, name='ApplyPassphraseFlow') + self.attempted = False + self.prev_passphrase = stash.bip39_passphrase + self.passphrase = passphrase + self.msg = 'Apply' + if self.passphrase is not None: + if len(self.passphrase) == 0: + super().__init__(initial_state=self.clear_passphrase, name='ApplyPassphraseFlow') + else: + super().__init__(initial_state=self.apply_passphrase, name='ApplyPassphraseFlow') else: - self.passphrase = '' - super().__init__(initial_state=self.enter_passphrase, name='ApplyPassphraseFlow') + super().__init__(initial_state=self.explainer, name='ApplyPassphraseFlow') - async def enter_passphrase(self): - self.passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, - initial_text=self.passphrase, - max_length=MAX_PASSPHRASE_LENGTH).show() - if self.passphrase is not None: + def check_attempt(self): + if self.attempted: + self.passphrase = self.prev_passphrase + self.msg = 'Clear' if len(self.passphrase) == 0 else 'Revert' self.goto(self.apply_passphrase) else: self.set_result(False) - async def apply_passphrase(self): - if len(self.passphrase) == 0: - result = await QuestionPage(text='Clear the active passphrase?').show() - if result: - msg = 'Clearing passphrase' - else: + async def explainer(self): + from pages import InfoPage + import microns + + text = '''Type with care. All passphrases are valid.\n +Passport will clear your passphrase upon shutdown.''' + result = await InfoPage(text=text, + left_micron=microns.Back).show() + + if not result: + self.set_result(False) + return + + self.goto(self.enter_passphrase) + + async def enter_passphrase(self): + from pages import TextInputPage + from constants import MAX_PASSPHRASE_LENGTH + + passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, + initial_text=self.passphrase or '', + max_length=MAX_PASSPHRASE_LENGTH).show() + + # Exit text input, means we want to go back, and no need to prompt for reverting to no passphrase + if passphrase is None or (len(passphrase) == 0 and passphrase == self.prev_passphrase): + self.check_attempt() + return + + # Clear passphrase, previous passphrase is in use + if len(passphrase) == 0: + self.goto(self.clear_passphrase) + return + + # Revert passphrase to entered field, no need to check xfp + if passphrase == self.prev_passphrase: + self.check_attempt() + return + + self.msg = 'Apply' + self.passphrase = passphrase + self.goto(self.apply_passphrase) + + async def clear_passphrase(self): + from pages import QuestionPage + result = await QuestionPage(text='Clear the active passphrase?').show() + + if not result: + if not self.back(): self.set_result(False) - return - else: - msg = 'Applying passphrase' + return - (error,) = await spinner_task(msg, apply_passphrase_task, args=[self.passphrase]) - if error is None: - import common - from utils import start_task, xfp2str + self.msg = 'Clear' + self.passphrase = '' + self.goto(self.apply_passphrase) - # Make a success page - if len(self.passphrase) == 0: - await SuccessPage( - text='Passphrase cleared\n\nFingerprint:\n\n{}'.format( - xfp2str(common.settings.get('xfp', '---'))) - ).show() + async def apply_passphrase(self): + from utils import spinner_task + from errors import Error + from tasks import apply_passphrase_task + from pages import ErrorPage + + (error,) = await spinner_task("{}ing passphrase".format(self.msg), + apply_passphrase_task, + args=[self.passphrase]) + + if error is not None: + if error is Error.NOT_BIP39_MODE: + await ErrorPage(text='Unable to {} passphrase. Not in BIP39 mode.'.format(self.msg.lower())).show() else: - result = await QuestionPage( - text='Passphrase applied\n\nFingerprint correct?\n\n{}'.format( - xfp2str(common.settings.get('xfp', '---'))) - ).show() - if result is False: - self.goto(self.enter_passphrase) - return + await ErrorPage(text='Unable to {} passphrase.'.format(self.msg.lower())).show() + self.set_result(False) + return + + self.goto(self.confirm_xfp) + + async def confirm_xfp(self): + import common + from utils import start_task, xfp2str + from pages import QuestionPage, SuccessPage + + # Make a success page + if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: + await SuccessPage( + text='Passphrase {}ed.\n\nFingerprint:\n\n{}'.format( + self.msg.lower(), # this is either 'revert' or 'clear' at this point + xfp2str(common.settings.get('xfp', '---'))) + ).show() + else: + self.attempted = True + result = await QuestionPage( + text='Passphrase applied.\n\nFingerprint correct?\n\n{}'.format( + xfp2str(common.settings.get('xfp', '---'))) + ).show() + + if result is False: + self.goto(self.enter_passphrase) + return - common.ui.update_cards(stay_on_same_card=True) + common.ui.update_cards(stay_on_same_card=True) - async def start_main_task(): - common.ui.start_card_task(card_idx=common.ui.active_card_idx) + async def start_main_task(): + common.ui.start_card_task(card_idx=common.ui.active_card_idx) - start_task(start_main_task()) + start_task(start_main_task()) - await self.wait_to_die() - elif error is Error.NOT_BIP39_MODE: - await ErrorPage(text='Unable to apply passphrase. Not in BIP39 mode.').show() + await self.wait_to_die() - self.set_result(error is None) + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index d3eb4e89f..7d05ccb03 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -19,7 +19,7 @@ def __init__(self): self.backup_quiz_passed = settings.get('backup_quiz', False) self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS - self.statusbar = {'title': 'BACKUP', 'icon': lv.ICON_BACKUP} + self.statusbar = {'title': 'BACKUP', 'icon': 'ICON_BACKUP'} async def show_intro(self): from pages import InfoPage @@ -46,7 +46,7 @@ async def show_intro(self): if result: self.goto(self.get_backup_code) else: - result = await QuestionPage(text='Skip initial Backup?\n\n{}'.format( + result = await QuestionPage(text='Skip initial backup?\n\n{}'.format( recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')), left_micron=microns.Retry).show() if result: self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py index 4f2dad23e..4223e85ee 100644 --- a/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py @@ -4,8 +4,6 @@ # casa_health_check_flow.py - Scan and process a Casa health check QR code in `crypto-request` format from flows import Flow -from files import CardSlot, CardMissingError -from pages.insert_microsd_page import InsertMicroSDPage def is_health_check(filename, path=None): @@ -40,24 +38,16 @@ async def choose_file(self): self.goto(self.parse_message) async def parse_message(self): - from files import CardSlot - from pages import ErrorPage - - try: - with CardSlot() as _card: - with open(self.file_path, 'r') as fd: - try: - self.lines = fd.read().split('\n') - except Exception as e: - await ErrorPage(text='Health check format is invalid.').show() - self.set_result(False) - return - - self.goto(self.common_flow) - except CardMissingError: - result = await InsertMicroSDPage().show() - if not result: - self.back() + from flows import ReadFileFlow + + data = await ReadFileFlow(self.file_path, binary=False).run() + + if not data: + self.set_result(False) + return + + self.lines = data.split('\n') + self.goto(self.common_flow) async def common_flow(self): from flows import CasaHealthCheckCommonFlow diff --git a/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py index af87814f3..6e4344a40 100644 --- a/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py @@ -16,58 +16,49 @@ class CasaHealthCheckQRFlow(Flow): def __init__(self): super().__init__(initial_state=self.scan_qr, name='CasaHealthCheckQRFlow') - self.lines = None - async def scan_qr(self): - from pages import ScanQRPage, ErrorPage - import microns + self.text = None + self.subpath = None - result = await ScanQRPage(right_micron=microns.Checkmark).show() + async def scan_qr(self): + from pages import ErrorPage + from flows import ScanQRFlow + result = await ScanQRFlow(qr_types=[QRType.UR2], + ur_types=[ur.Value.BYTES], + data_description='a Casa health check').run() if result is None: - # User canceled the scan self.set_result(False) - else: - # Got a scan result (aka QRScanResult). - if result.is_failure(): - await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() - self.set_result(False) - else: - if not isinstance(result.data, ur.Value): - await ErrorPage(text='Unable to scan QR code.\n\nNot a Uniform Resource.').show() - self.set_result(False) - return - - try: - data = result.data.unwrap_bytes() - self.lines = data.decode('utf-8').split('\n') - except Exception as e: - await ErrorPage('Health check format is invalid.').show() - return - if len(self.lines) != 2: - await ErrorPage('Health check format is invalid.').show() - self.set_result(False) - return + return - # Common function to validate the message - self.text = self.lines[0] - self.subpath = self.lines[1] - # print('text={}'.format(self.text)) - # print('subpath={}'.format(self.subpath)) + try: + data = result.unwrap_bytes().decode('utf-8') + lines = data.split('\n') + if len(lines) != 2: + await ErrorPage('Health check format is invalid.').show() + self.set_result(False) + return - # Validate - (subpath, error) = validate_sign_text(self.text, self.subpath) - if error is not None: - await ErrorPage(text=error).show() - self.set_result(False) - return + self.text = lines[0] + self.subpath = lines[1] + except Exception as e: + await ErrorPage('Health check format is invalid.').show() + self.set_result(False) + return - self.subpath = subpath + # Validate + (subpath, error) = validate_sign_text(self.text, self.subpath) + if error is not None: + await ErrorPage(text=error).show() + self.set_result(False) + return - self.goto(self.sign_health_check) + self.subpath = subpath + self.goto(self.sign_health_check) async def sign_health_check(self): - (signature, address, error) = await spinner_task('Performing Health Check', sign_text_file_task, + (signature, address, error) = await spinner_task('Performing Health Check', + sign_text_file_task, args=[self.text, self.subpath, AF_CLASSIC]) if error is None: self.signature = signature diff --git a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py index d2f3cb342..dd20129f4 100644 --- a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py @@ -277,7 +277,7 @@ async def export_by_qr(self): # Show the QR code result = await ShowQRPage( - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT}, + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'}, qr_type=qr_type, qr_data=data).show() if result is False: @@ -313,8 +313,9 @@ async def export_by_qr(self): self.goto_address_verification_method(save_curr=False) async def export_by_microsd(self): - from utils import xfp2str + from utils import xfp2str, get_folder_path from flows import SaveToMicroSDFlow + from public_constants import DIR_WALLET_CONFIGS # Run the software wallet's associated export function to get the data (data, self.acct_info, _error) = await spinner_task( @@ -343,7 +344,9 @@ async def export_by_microsd(self): acct=self.acct_num, xfp=xfp2str(common.settings.get('xfp')).lower()) - save_result = await SaveToMicroSDFlow(filename=filename, data=data).run() + save_result = await SaveToMicroSDFlow(filename=filename, + path=get_folder_path(DIR_WALLET_CONFIGS), + data=data).run() if not save_result: self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py index 605712071..cac6f31bb 100644 --- a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py @@ -71,6 +71,7 @@ async def set_initial_pin(self): async def update_firmware(self): from pages import ErrorPage, QuestionPage + import passport # Guards to ensure we can't get into a weird state if not self.ensure_pin_set(): @@ -78,10 +79,11 @@ async def update_firmware(self): await self.ensure_logged_in() # Intro page + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -89,7 +91,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'} ).run() if result: import machine @@ -136,7 +138,7 @@ async def connect_with_envoy_intro(self): await self.ensure_logged_in() result = await InfoPage( - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT}, + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'}, text='Now, let\'s connect Passport with Envoy.', left_micron=None).show() self.goto(self.connect_with_envoy) @@ -166,7 +168,7 @@ async def connect_with_envoy(self): result = await ConnectWalletFlow( sw_wallet='Envoy', - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT} + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'} ).run() if result: self.goto(self.show_success) diff --git a/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py b/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py index 64231de49..0f3b7aa73 100644 --- a/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py @@ -6,11 +6,12 @@ import lvgl as lv from flows import Flow -from pages import SuccessPage, QuestionPage +from pages import SuccessPage, QuestionPage, LongQuestionPage from tasks import erase_passport_task from utils import spinner_task from translations import t, T import microns +import passport class ErasePassportFlow(Flow): @@ -28,7 +29,8 @@ async def confirm_erase(self): self.set_result(False) return - if not await QuestionPage( + page_class = QuestionPage if passport.IS_COLOR else LongQuestionPage + if not await page_class( 'Without a proper backup, you could lose all funds associated with this device.\n\n' + 'Please confirm you understand these risks.').show(): self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 9dfe9a514..c7569f7a1 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -11,12 +11,17 @@ def __init__(self, context=None): self.key = context self.key_type = None self.pk = None + self.data = None + self.path = None + self.filename = None super().__init__(initial_state=self.generate_key, name="NewDerivedKeyFlow") async def generate_key(self): - from utils import spinner_task + from utils import spinner_task, B2A, get_folder_path from derived_key import get_key_type_from_tn from pages import ErrorPage + from flows import ViewSeedWordsFlow + from public_constants import DIR_KEY_MNGR self.key_type = get_key_type_from_tn(self.key['tn']) @@ -25,14 +30,32 @@ async def generate_key(self): self.set_result(False) return - (self.pk, error) = await spinner_task(text='Generating Key', - task=self.key_type['task'], - args=[self.key['index']]) + (vals, error) = await spinner_task(text='Generating key', + task=self.key_type['task'], + args=[self.key['index']]) + self.pk = vals['priv'] if error is not None: await ErrorPage(error).show() self.set_result(False) return + self.path = get_folder_path(DIR_KEY_MNGR) + self.filename = '{}-{}.txt'.format(self.key_type['title'], self.key['name']) + + if self.key_type['words']: + result = await ViewSeedWordsFlow(external_key=self.pk, + qr_option=True, + sd_option=True, + path=self.path, + filename=self.filename).run() + self.set_result(result) + return + + if isinstance(self.pk, str): + self.data = self.pk + else: + self.data = B2A(self.pk) + self.goto(self.choose_export_mode) async def choose_export_mode(self): @@ -41,10 +64,7 @@ async def choose_export_mode(self): options = [{'label': 'Export via QR', 'value': self.show_qr_code}, {'label': 'Export via microSD', 'value': self.save_to_sd}] - if self.key_type['words']: - options.append({'label': 'Show seed words', 'value': self.show_seed_words}) - - mode = await ChooserPage(card_header={'title': 'Export Mode'}, options=options).show() + mode = await ChooserPage(card_header={'title': 'Format'}, options=options).show() if mode is None: self.set_result(False) @@ -53,74 +73,59 @@ async def choose_export_mode(self): self.goto(mode) async def show_qr_code(self): - from flows import GetSeedWordsFlow, SeedWarningFlow - from pages import ShowQRPage, ChooserPage - from utils import B2A - from data_codecs.qr_type import QRType + from pages import ShowQRPage + from flows import SeedWarningFlow import microns - if self.key_type['words']: - options = [{'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, - {'label': 'SeedQR', 'value': QRType.SEED_QR}] + result = await SeedWarningFlow(action_text="display your {} as a QR code" + .format(self.key_type['title']), + continue_text=self.key_type.get('continue_text', None)).run() - qr_type = await ChooserPage(card_header={'title': 'QR Format'}, options=options).show() - else: - qr_type = QRType.QR + if not result: + self.back() + return - if qr_type is None: - self.set_result(False) + result = await ShowQRPage(qr_data=self.data, right_micron=microns.Checkmark).show() + + if not result: return - if qr_type is QRType.QR: - if isinstance(self.pk, str): - qr_data = self.pk - else: - qr_data = B2A(self.pk) - else: # SeedQR or Compact SeedQR - qr_data = await GetSeedWordsFlow(self.pk).run() + self.goto(self.confirm_qr) - if qr_data is None: - self.set_result(False) - return + async def confirm_qr(self): + from pages import InfoPage, LongTextPage + import microns - result = await SeedWarningFlow(action_text="display your {} as a QR code" - .format(self.key_type['title']), - continue_text=self.key_type.get('continue_text', None)).run() + text = 'Confirm the exported {} on the following page'.format(self.key_type['title']) + result = await InfoPage(text=text, left_micron=microns.Back).show() + + if not result: + self.back() + return + + result = await LongTextPage(text="\n" + self.data, + centered=True, + card_header={'title': 'Confirm Key'}, + left_micron=microns.Back).show() if not result: - self.set_result(False) return - await ShowQRPage(qr_type=qr_type, qr_data=qr_data, right_micron=microns.Checkmark).show() self.set_result(True) async def save_to_sd(self): - from utils import B2A - from flows import GetSeedWordsFlow, SaveToMicroSDFlow, SeedWarningFlow - - if self.key_type['words']: - words = await GetSeedWordsFlow(self.pk).run() - text = " ".join(words) - elif isinstance(self.pk, str): - text = self.pk - else: - text = B2A(self.pk) + from flows import SaveToMicroSDFlow, SeedWarningFlow result = await SeedWarningFlow(action_text="copy your {} to the microSD card" .format(self.key_type['title']), continue_text=self.key_type.get('continue_text', None)).run() if not result: - self.set_result(False) + self.back() return - filename = '{}-{}.txt'.format(self.key_type['title'], self.key['name']) - result = await SaveToMicroSDFlow(filename=filename, - data=text, + result = await SaveToMicroSDFlow(filename=self.filename, + path=self.path, + data=self.data, success_text="key").run() self.set_result(result) - - async def show_seed_words(self): - from flows import ViewSeedWordsFlow - await ViewSeedWordsFlow(external_key=self.pk).run() - self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py index 23d14fe7d..eb1e4a740 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py @@ -9,8 +9,13 @@ class ExportMultisigMicrosdFlow(SaveToMicroSDFlow): def __init__(self, context=None): from multisig_wallet import MultisigWallet + from utils import get_folder_path + from public_constants import DIR_MULTISIGS ms = MultisigWallet.get_by_idx(context) # context is multisig index data = ms.to_file() filename = "{}-multisig.txt".format(ms.name) - super().__init__(filename=filename, data=data, success_text="multisig config") + super().__init__(filename=filename, + path=get_folder_path(DIR_MULTISIGS), + data=data, + success_text="multisig config") diff --git a/ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py b/ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py deleted file mode 100644 index 98fa3194c..000000000 --- a/ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# fcc_test_flow.py - Flow to iterate through a test loop indefinitely - -from animations.constants import TRANSITION_DIR_POP -import lvgl as lv -from flows import Flow -import microns -from pages import ScanQRPage, LongTextPage -from styles.colors import COPPER -from tasks import fcc_copy_files_task -from utils import start_task -from files import CardSlot -import common -from uasyncio import sleep_ms -from errors import Error - -_CAMERA_DISPLAY_DURATION_SECS = const(5 * 1000) -_FILE_SIZE_TO_CREATE = const(250 * 1024) - - -class FCCTestFlow(Flow): - def __init__(self): - self.long_text_page = None - super().__init__(initial_state=self.show_camera, name='FccTestFlow') - - async def show_camera(self): - result = await ScanQRPage().show(auto_close_timeout=_CAMERA_DISPLAY_DURATION_SECS) - if result is None: - # User used a button to back out - self.set_result(False) - return - - self.goto(self.copy_files) - - async def copy_files(self): - self.long_text_page = LongTextPage( - card_header=('title': 'Copy Files'}, - text='Copying files from microSD to flash and back.', - show_progress=True, - left_micron=microns.Cancel, - right_micron=microns.Cancel) - - self.copy_files_task = start_task( - fcc_copy_files_task( - CardSlot.get_file_path('fcc-file-copy-test.bin')[0], - file_size=_FILE_SIZE_TO_CREATE, - set_progress=self.long_text_page.set_progress, - set_message=self.long_text_page.set_message, - on_done=self.on_done)) - - result = await self.long_text_page.show() - if result is not None: - # User used a button to back out, so cancel the task and return from the page - self.copy_files_task.cancel() - self.set_result(False) - self.long_text_page = None - return - - # NOTE: This sleep is necessary to avoid starting to animate to the next page - # while the previous animation is still active (which causes a crash) - await sleep_ms(2000) - self.back() - - async def on_done(self, error): - # If user backed out, long_text_page will be None, so nothing to do - if self.long_text_page is None: - return - - common.page_transition_dir = TRANSITION_DIR_POP - if error is Error.MICROSD_CARD_MISSING: - self.long_text_page.set_icon(lv.LARGE_ICON_MICROSD, color=COPPER) - self.long_text_page.set_text('Please insert microSD card.') - self.long_text_page.set_result(None) - else: - self.long_text_page.set_progress(100) - self.long_text_page.set_icon(lv.LARGE_ICON_SUCCESS) - self.long_text_page.set_result(None) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 5a3466a76..6aa51830b 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -21,15 +21,22 @@ def file_key(f): class FilePickerFlow(Flow): def __init__( - self, initial_path=None, show_folders=False, enable_parent_nav=False, suffix=None, - filter_fn=None, select_text="Select"): + self, + initial_path=None, + show_folders=False, + enable_parent_nav=False, + suffix=None, + filter_fn=None, + select_text="Select"): from files import CardSlot + from utils import bind, show_card_missing if not initial_path: initial_path = CardSlot.get_sd_root() - super().__init__(initial_state=self.show_file_picker, name='FilePickerFlow: {}'.format( - initial_path)) + super().__init__(initial_state=self.show_file_picker, + name='FilePickerFlow: {}'.format(initial_path)) + self.initial_path = initial_path self.paths = [initial_path] self.show_folders = show_folders @@ -41,13 +48,15 @@ def __init__( self.empty_result = None self.finished = False + bind(self, show_card_missing) + def on_empty_sd_card_change(self, sd_card_present): if sd_card_present: return True # This will cause a refresh else: self.reset_paths() self.status_page.set_result(None) - self.goto(self.show_insert_microsd_error) + self.goto(self.show_card_missing) return False async def on_empty_result(self, res): @@ -61,7 +70,7 @@ def on_exception(self, exception): def on_file_sd_card_change(self, sd_card_present): if not sd_card_present: self.reset_paths() - self.goto(self.show_insert_microsd_error) + self.goto(self.show_card_missing) return True async def on_file_result(self, res): @@ -90,7 +99,8 @@ async def on_file_result(self, res): return True async def show_file_picker(self): - from utils import show_page_with_sd_card + from utils import show_page_with_sd_card, get_backups_folder_path, get_folder_path + from public_constants import DIR_TRANSACTIONS while True: # Get list of files/folders at the current path @@ -104,21 +114,25 @@ async def show_file_picker(self): suffix=self.suffix, filter_fn=self.filter_fn) - files = sorted(files, key=file_key) + reverse = False + if (active_path == get_backups_folder_path() or + active_path == get_folder_path(DIR_TRANSACTIONS)): + reverse = True + files = sorted(files, key=file_key, reverse=reverse) except CardMissingError: self.reset_paths() - self.goto(self.show_insert_microsd_error) + self.goto(self.show_card_missing) return is_root = active_path == CardSlot.get_sd_root() if is_root: title = 'microSD' - icon = lv.ICON_MICROSD + icon = 'ICON_MICROSD' else: leaf_folder_name = active_path.split('/')[-1] title = leaf_folder_name - icon = lv.ICON_FOLDER + icon = 'ICON_FOLDER' if len(files) == 0: self.status_page = StatusPage( @@ -159,12 +173,5 @@ async def show_file_picker(self): if self.finished: return - async def show_insert_microsd_error(self): - result = await InsertMicroSDPage().show() - if not result: - self.set_result(None) - else: - self.goto(self.show_file_picker) - def reset_paths(self): self.paths = [self.initial_path] diff --git a/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py index fd9ffdbbb..6dd940c6d 100644 --- a/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py @@ -13,29 +13,21 @@ def __init__(self): self.error = None async def scan_qr_code(self): - from pages import ScanQRPage, ErrorPage - from multisig_wallet import MultisigWallet + from data_codecs.qr_type import QRType from foundation import ur + from flows import ScanQRFlow + from multisig_wallet import MultisigWallet - result = await ScanQRPage().show() + result = await ScanQRFlow(qr_types=[QRType.UR2], + ur_types=[ur.Value.BYTES], + data_description='a multisig wallet configuration file').run() if result is None: self.set_result(False) return - elif result.is_failure(): - self.set_result(False) - await ErrorPage(text='Unable to scan QR code.').show() - return - - if not isinstance(result.data, ur.Value): - await ErrorPage(text='Bad QR format.').show() - return - - data = result.data.unwrap_bytes() - if isinstance(data, (bytes, bytearray)): - data = data.decode('utf-8') try: - self.ms = await MultisigWallet.from_file(data) + file = result.unwrap_bytes().decode('utf-8') + self.ms = await MultisigWallet.from_file(file) except BaseException as e: if e.args is None or len(e.args) == 0: self.error = "Multisig Import Error" @@ -43,7 +35,6 @@ async def scan_qr_code(self): self.error = e.args[0] self.goto(self.show_error) return - # print('New MS: {}'.format(self.ms.serialize())) self.goto(self.do_import) diff --git a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py index b51b860a3..6a2c7ea24 100644 --- a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py @@ -3,7 +3,6 @@ # # initial_seed_setup_flow.py - Menu to let user choose seed setup method -from flows.view_seed_words_flow import ViewSeedWordsFlow import lvgl as lv from flows import Flow @@ -12,7 +11,7 @@ class InitialSeedSetupFlow(Flow): def __init__(self, is_envoy=True, allow_backtrack=True): super().__init__(initial_state=self.show_intro, name='InitialSeedSetupFlow') self.is_envoy = is_envoy - self.statusbar = {'title': 'CREATE SEED', 'icon': lv.ICON_SEED} + self.statusbar = {'title': 'CREATE SEED', 'icon': 'ICON_SEED'} self.allow_backtrack = allow_backtrack async def show_intro(self): @@ -46,8 +45,8 @@ async def show_seed_setup_menu(self): options = [{'label': 'Create New Seed', 'value': lambda: NewSeedFlow(show_words=not self.is_envoy, full_backup=True)}, - {'label': 'Restore Seed', 'value': lambda: RestoreSeedFlow()}, - {'label': 'Restore Backup', 'value': lambda: RestoreBackupFlow()}] + {'label': 'Restore Seed', 'value': lambda: RestoreSeedFlow(full_backup=True)}, + {'label': 'Restore Backup', 'value': lambda: RestoreBackupFlow(full_backup=True)}] flow = await ChooserPage( text=None, diff --git a/ports/stm32/boards/Passport/modules/flows/list_files_flow.py b/ports/stm32/boards/Passport/modules/flows/list_files_flow.py index 4e670eaa2..d40b3fd05 100644 --- a/ports/stm32/boards/Passport/modules/flows/list_files_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/list_files_flow.py @@ -3,7 +3,6 @@ # # list_files_flow.py - Flow to let user view microSD card files and view the SHA256 of the chosen file -from files import CardSlot from flows import Flow, FilePickerFlow from pages import SuccessPage, ErrorPage, ProgressPage, InsertMicroSDPage from tasks import calculate_file_sha256_task @@ -24,9 +23,7 @@ async def on_done(self, digest, error=None): self.progress_page.set_result(error is None) async def choose_file(self): - root_path = CardSlot.get_sd_root() - - result = await FilePickerFlow(initial_path=root_path, show_folders=True, select_text='Info').run() + result = await FilePickerFlow(show_folders=True, select_text='Info').run() if result is None: self.set_result(False) return diff --git a/ports/stm32/boards/Passport/modules/flows/login_flow.py b/ports/stm32/boards/Passport/modules/flows/login_flow.py index 2c68cf882..824d2fb11 100644 --- a/ports/stm32/boards/Passport/modules/flows/login_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/login_flow.py @@ -77,7 +77,7 @@ async def show_bricked_message(self): msg = '''This Passport is now permanently disabled. -Restore a microSD backup or seed phrase onto a new Passport to recover your funds.''' % pa.num_fails +Restore a microSD backup or seed phrase onto a new Passport to recover your funds.''' result = await ErrorPage(text=msg, left_micron=microns.Shutdown, diff --git a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py index 0e0392f46..f6eaba5df 100644 --- a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py @@ -65,6 +65,7 @@ async def set_initial_pin(self): async def update_firmware(self): from pages import ErrorPage, QuestionPage + import passport # Guards to ensure we can't get into a weird state if not self.ensure_pin_set(): @@ -72,10 +73,11 @@ async def update_firmware(self): await self.ensure_logged_in() # Intro page + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -83,7 +85,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'} ).run() if result: import machine diff --git a/ports/stm32/boards/Passport/modules/flows/menu_flow.py b/ports/stm32/boards/Passport/modules/flows/menu_flow.py index d0e052153..608b770b7 100644 --- a/ports/stm32/boards/Passport/modules/flows/menu_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/menu_flow.py @@ -14,7 +14,7 @@ class MenuFlow(Flow): latest_menu = None def __init__(self, menu, initial_selected_index=0, is_top_level=None, context=None, - card_header=None, statusbar=None): + card_header=None, statusbar=None, dynamic=None): self.menu = menu super().__init__(initial_state=self.show_menu, name='MenuFlow') @@ -24,6 +24,7 @@ def __init__(self, menu, initial_selected_index=0, is_top_level=None, context=No self.context = context self.card_header = card_header self.statusbar = statusbar + self.dynamic = dynamic MenuFlow.latest_menu = self async def show_menu(self): @@ -34,6 +35,9 @@ async def show_menu(self): # This allows them to update if any state has changed since last running. assert(callable(self.menu)) self.items = self.menu() + if self.dynamic: + assert(callable(self.dynamic)) + self.items[:0] = self.dynamic() self.prev_statusbar = None self.prev_card_header = None diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py new file mode 100644 index 000000000..818e57b57 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# read_file_flow.py - Read a file and handle errors + +from flows import Flow + + +class ReadFileFlow(Flow): + def __init__(self, file_path, binary=True, automatic=False, read_fn=None): + from utils import bind, show_card_missing + + self.file_path = file_path + self.binary = binary + self.read_fn = read_fn + + # Used in flow_show_card_missing + self.automatic = automatic + + bind(self, show_card_missing) + + super().__init__(initial_state=self.read_file, + name='ReadFileFlow') + + async def read_file(self): + from utils import spinner_task + from tasks import read_file_task + from errors import Error + from pages import ErrorPage + + (data, error) = await spinner_task('Reading file', + read_file_task, + args=[self.file_path, self.binary, self.read_fn]) + + if error is Error.MICROSD_CARD_MISSING: + self.goto(self.show_card_missing) + return + + if error is Error.FILE_READ_ERROR: + if not self.automatic: + await ErrorPage('Unable to read file from microSD card.').show() + self.set_result(None) + return + + if len(data) == 0: + if not self.automatic: + await ErrorPage('File is empty.').show() + self.set_result(None) + return + + self.set_result(data) diff --git a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py index 8d65d04c3..b440b04f8 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py @@ -18,18 +18,20 @@ YesNoChooserPage ) from utils import get_backups_folder_path, spinner_task, get_backup_code_as_password -from tasks import restore_backup_task +from tasks import restore_backup_task, get_backup_code_task from errors import Error import common class RestoreBackupFlow(Flow): - def __init__(self, refresh_cards_when_done=False): + def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): super().__init__(initial_state=self.check_if_erased, name='RestoreBackupFlow') self.refresh_cards_when_done = refresh_cards_when_done self.backup_code = [None] * TOTAL_BACKUP_CODE_DIGITS self.backup_password_words = [] self.backup_password_prefixes = [] + self.full_backup = full_backup + self.autobackup = autobackup async def check_if_erased(self): from common import pa @@ -102,6 +104,8 @@ async def enter_backup_code(self): async def do_restore(self): from utils import start_task + from flows import AutoBackupFlow, BackupFlow + from pages import InfoPage # TODO: Change from spinner to ProgressPage and pass on_progress instead of None below. (error,) = await spinner_task( @@ -109,10 +113,19 @@ async def do_restore(self): restore_backup_task, args=[self.decryption_password, self.backup_file_path]) + (new_backup_code, error_2) = await spinner_task('Restoring Backup', get_backup_code_task) + if error is None: await SuccessPage(text='Restore Complete!').show() self.set_result(True) + if self.full_backup: + if error_2 is not None or self.backup_code != new_backup_code: + await InfoPage("You will receive a new Backup Code to use with your new Passport.").show() + await BackupFlow(self.backup_code).run() + elif self.autobackup: + await AutoBackupFlow(offer=True).run() + if self.refresh_cards_when_done: common.ui.update_cards(is_init=True) diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index 6c7bcabba..538d06319 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -9,19 +9,28 @@ from pages import ErrorPage, PredictiveTextInputPage, SuccessPage, QuestionPage from utils import spinner_task from tasks import save_seed_task +from public_constants import SEED_LENGTHS class RestoreSeedFlow(Flow): - def __init__(self, refresh_cards_when_done=False): + def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): super().__init__(initial_state=self.choose_restore_method, name='RestoreSeedFlow') self.refresh_cards_when_done = refresh_cards_when_done + self.seed_format = None + self.seed_length = None + self.validate_text = None self.seed_words = [] + self.full_backup = full_backup + self.autobackup = autobackup async def choose_restore_method(self): from pages import ChooserPage + from data_codecs.qr_type import QRType options = [{'label': '24 words', 'value': 24}, - {'label': '12 words', 'value': 12}] + {'label': '12 words', 'value': 12}, + {'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, + {'label': 'SeedQR', 'value': QRType.SEED_QR}] choice = await ChooserPage(card_header={'title': 'Seed Format'}, options=options).show() @@ -29,17 +38,49 @@ async def choose_restore_method(self): self.set_result(False) return - if isinstance(choice, int): + self.seed_format = choice + if self.seed_format in SEED_LENGTHS: self.seed_length = choice + self.validate_text = 'Seed phrase' self.goto(self.explain_input_method) else: - self.goto(choice) + if self.seed_format == QRType.SEED_QR: + self.validate_text = 'SeedQR' + else: + self.validate_text = 'Compact SeedQR' + self.goto(self.scan_qr) async def scan_qr(self): - from flows import ScanPrivateKeyQRFlow - result = await ScanPrivateKeyQRFlow( - refresh_cards_when_done=self.refresh_cards_when_done).run() - self.set_result(result) + from flows import ScanQRFlow + from pages import InfoPage, SeedWordsListPage, ErrorPage + import microns + from data_codecs.qr_type import QRType + + result = await ScanQRFlow(explicit_type=self.seed_format, + data_description=self.validate_text).run() + + if result is None: + await ErrorPage("Invalid {} detected. Make sure you're using the right format." + .format(self.validate_text)).show() + self.back() + return + + self.seed_words = result + + plural_label = 's' if len(result) == 24 else '' + result = await InfoPage('Confirm the seed words in the following page{}.'.format(plural_label)).show() + + if not result: + self.back() + return + + result = await SeedWordsListPage(words=self.seed_words, left_micron=microns.Cancel).show() + + if not result: + self.back() + return + + self.goto(self.validate_seed_words) async def explain_input_method(self): from pages import InfoPage @@ -76,7 +117,8 @@ async def validate_seed_words(self): self.goto(self.valid_seed) async def invalid_seed(self): - result = await ErrorPage(text='Seed phrase is invalid. One or more of your seed words is incorrect.', + result = await ErrorPage(text='{} is invalid. One or more of your seed words is incorrect.' + .format(self.validate_text), left_micron=microns.Cancel, right_micron=microns.Retry).show() if result is None: cancel = await QuestionPage( @@ -90,8 +132,9 @@ async def invalid_seed(self): async def valid_seed(self): from foundation import bip39 + from flows import AutoBackupFlow, BackupFlow - entropy = bytearray(33) # Includes and extra byte for the checksum bits + entropy = bytearray(33) # Includes an extra byte for the checksum bits len = bip39.mnemonic_to_bits(self.mnemonic, entropy) @@ -106,7 +149,12 @@ async def valid_seed(self): (error,) = await spinner_task('Saving seed', save_seed_task, args=[entropy]) if error is None: import common + await SuccessPage(text='New seed restored and saved.').show() + if self.full_backup: + await BackupFlow().run() + elif self.autobackup: + await AutoBackupFlow(offer=True).run() if self.refresh_cards_when_done: common.ui.full_cards_refresh() @@ -115,5 +163,5 @@ async def valid_seed(self): else: self.set_result(True) else: - # WIP: This is not complete - offer backup? - pass + await ErrorPage('Unable to save seed.').show() + self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 7b6f0ecbc..524ee72e1 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -14,8 +14,10 @@ def __init__(self, success_text="file", path=None, mode='', - automatic=False): + automatic=False, + auto_prompt=None): import microns + from utils import bind, show_card_missing self.filename = filename.replace(' ', '_') self.data = data @@ -24,10 +26,33 @@ def __init__(self, self.path = path self.mode = mode self.out_full = None + # If auto_prompt isn't specified, use automatic value + auto_prompt = auto_prompt or automatic + self.auto_timeout = 1000 if auto_prompt else None + self.show_check = None if auto_prompt else microns.Checkmark + + # Used in flow_show_card_missing self.automatic = automatic - self.auto_timeout = 1000 if automatic else None - self.show_check = None if automatic else microns.Checkmark - super().__init__(initial_state=self.save, name='SaveToMicroSDFlow') + self.return_bool = True + + bind(self, show_card_missing) + + super().__init__(initial_state=self.check_inputs, + name='SaveToMicroSDFlow') + + def default_write_fn(self, filename): + with open(self.out_full, 'w' + self.mode) as fd: + fd.write(self.data) + + async def check_inputs(self): + from pages import ErrorPage + + if (not self.data and not self.write_fn) or (self.data and self.write_fn): + await ErrorPage("Either data or a write function is required to save a file.").show() + self.set_result(False) + return + + self.goto(self.save) async def save(self): from files import CardSlot, CardMissingError @@ -36,36 +61,28 @@ async def save(self): from errors import Error from tasks import custom_microsd_write_task + if self.data: + self.write_fn = self.default_write_fn + written = False for path in [self.path, None]: try: with CardSlot() as card: ensure_folder_exists(self.path) - self.out_full, _ = card.pick_filename(self.filename, path) - - if self.data: - with open(self.out_full, 'w' + self.mode) as fd: - fd.write(self.data) - written = True - elif self.write_fn: - error = await spinner_task("Writing {}".format(self.success_text), - custom_microsd_write_task, - args=[self.out_full, self.write_fn]) - if error is Error.MICROSD_CARD_MISSING: - raise CardMissingError() - elif error is Error.FILE_WRITE_ERROR: - raise Exception("write task failed") - written = True - if written: - break + error = await spinner_task("Writing {}".format(self.success_text), + custom_microsd_write_task, + args=[self.out_full, self.write_fn]) + if error is Error.MICROSD_CARD_MISSING: + raise CardMissingError() + elif error is Error.FILE_WRITE_ERROR: + raise Exception("write task failed") + written = True + break except CardMissingError: - if not self.automatic: - self.goto(self.show_card_missing) - else: - self.set_result(False) + self.goto(self.show_card_missing) return except Exception as e: @@ -78,7 +95,7 @@ async def save(self): if written: self.goto(self.success) else: - await ErrorPage("Failed to write file: no data or write task.", + await ErrorPage("Failed to write file.", right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) @@ -88,12 +105,3 @@ async def success(self): right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) self.set_result(True) - - async def show_card_missing(self): - from pages import InsertMicroSDPage - - result = await InsertMicroSDPage().show() - if not result: - self.set_result(False) - else: - self.goto(self.save) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py deleted file mode 100644 index b27d6242e..000000000 --- a/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py +++ /dev/null @@ -1,90 +0,0 @@ -# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# scan_private_key_qr_flow.py - Scan a QR code containing a private key - -from flows import Flow -from pages import ErrorPage, QuestionPage, SuccessPage -from tasks import new_seed_task, save_seed_task -from utils import has_secrets, spinner_task -from translations import t, T - - -class ScanPrivateKeyQRFlow(Flow): - def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): - super().__init__(initial_state=self.confirm_scan, name='ScanPrivateKeyQRFlow') - self.refresh_cards_when_done = refresh_cards_when_done - self.autobackup = autobackup - self.full_backup = full_backup - - async def confirm_scan(self): - # Ensure we don't overwrite an existing seed - if has_secrets(): - await ErrorPage(text='Passport already has a seed!').show() - self.set_result(False) - return - - result = await QuestionPage(text='Scan a private key QR now? Make sure you trust the source.').show() - if result: - self.goto(self.scan_seed) - else: - self.set_result(False) - - async def scan_seed(self): - from pages import ScanQRPage, ErrorPage - from ubinascii import unhexlify as a2b_hex - - result = await ScanQRPage().show() - - if result is None: - self.set_result(False) - return - - try: - seed = a2b_hex(result.data) - except Exception as e: - self.error = "Not a valid seed" - self.goto(self.show_error) - return - - if len(seed) > 32: - self.error = "Seed too long" - self.goto(self.show_error) - return - - self.seed = seed - self.goto(self.save_seed) - - async def save_seed(self): - (error,) = await spinner_task('Saving Seed', save_seed_task, args=[self.seed]) - if error is None: - self.goto(self.show_seed_words) - else: - self.error = 'Unable to save seed.' - self.goto(self.show_error) - - async def show_seed_words(self): - from flows import ViewSeedWordsFlow - await ViewSeedWordsFlow().run() - self.goto(self.show_success) - - async def show_success(self): - import common - from flows import AutoBackupFlow, BackupFlow - - await SuccessPage(text='New seed saved.').show() - if self.full_backup: - await BackupFlow().run() - elif self.autobackup: - await AutoBackupFlow(offer=True).run() - - if self.refresh_cards_when_done: - common.ui.full_cards_refresh() - - await self.wait_to_die() - else: - self.set_result(True) - - async def show_error(self): - await ErrorPage(self.error).show() - self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py new file mode 100644 index 000000000..0c302a0f0 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -0,0 +1,105 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later + +from data_codecs.qr_type import QRType +from flows import Flow +from pages import ScanQRPage, ErrorPage +from foundation import ur + + +class ScanQRFlow(Flow): + """Flow to scan a QR code or animated QR codes""" + + def __init__(self, + auto_close_timeout=None, + qr_types=None, + ur_types=None, + explicit_type=None, + data_description=None, + max_frames=None): + """ + Initialize the scan QR flow. + + :param auto_close_timeout: Timeout in seconds for the flow to + automatically close when nothing is scanned. + :param qr_types: List of supported QR types. + :param ur_types: List of supported UR types. + :raises ValueError: qr_types is provided but empty. + :raises ValueError: data_description is not provided. + """ + super().__init__(initial_state=self.scan, name='ScanQRFlow') + + self.auto_close_timeout = auto_close_timeout + + if explicit_type is not None and (qr_types is not None or ur_types is not None): + raise ValueError('No QR or UR types may be provided along with an explicit type') + + self.qr_types = [QRType.QR] if qr_types is None else qr_types + self.ur_types = [] if ur_types is None else ur_types + self.explicit_type = explicit_type + self.data_description = data_description + self.data = None + self.max_frames = max_frames + + if len(self.qr_types) == 0: + raise ValueError('At least one QR type must be provided') + + if QRType.UR2 in self.qr_types and len(self.ur_types) == 0: + raise ValueError('At least one UR type must be provided') + + if self.data_description is None: + raise ValueError('Data description must be provided') + + async def scan(self): + from errors import Error + + result = await ScanQRPage(max_frames=self.max_frames, + qr_type=self.explicit_type) \ + .show(auto_close_timeout=self.auto_close_timeout) + + if result is None: + self.set_result(None) + return + + if result.is_failure(): + await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() + self.set_result(None) + return + + if result.is_oversized(): + self.set_result(Error.PSBT_OVERSIZED) + return + + self.data = result.data + if isinstance(self.data, ur.Value): + self.goto(self.handle_ur) + else: + self.goto(self.handle_qr) + + async def handle_ur(self): + if QRType.UR2 not in self.qr_types and QRType.UR2 != self.explicit_type: + await ErrorPage(text='Scan failed.\n' + 'Expected to scan a QR code containing ' + '{}.'.format(self.data_description)).show() + self.set_result(None) + return + + if self.data.ur_type() not in self.ur_types and self.data.ur_type() != self.explicit_type: + await ErrorPage(text='Scan failed.\n' + 'This type of UR is not expected in this context. ' + '{}.'.format(self.data_description)).show() + + self.set_result(None) + return + + self.set_result(self.data) + + async def handle_qr(self): + if QRType.QR not in self.qr_types and QRType.QR != self.explicit_type: + await ErrorPage(text='Scan. failed.\n' + 'Expected to scan a Uniform Resource containing ' + '{}.'.format(self.data_description)).show() + self.set_result(None) + return + + self.set_result(self.data) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 167bf74c9..c76233017 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -4,12 +4,11 @@ # scv_flow.py - Supply Chain Validation Flow import lvgl as lv -from flows import Flow -from pages import ScanQRPage, ShowQRPage, QRScanResult -from pages.chooser_page import ChooserPage +from flows import Flow, ScanQRFlow +from pages import ShowQRPage, QuestionPage, ChooserPage from styles.colors import HIGHLIGHT_TEXT_HEX from data_codecs.qr_type import QRType -from utils import a2b_hex +from utils import a2b_hex, recolor from ubinascii import hexlify as b2a_hex from pincodes import PinAttempt from foundation import ur @@ -25,121 +24,71 @@ def __init__(self, envoy=True, ask_to_skip=True): :param envoy: True for Envoy App flow. False is manual Supply Chain Validation. """ - super().__init__(initial_state=self.show_intro, name='ScvFlow') + super().__init__(initial_state=self.show_intro, + name='ScvFlow', + statusbar={'title': 'SECURITY CHECK', 'icon': 'ICON_SHIELD'}) self.words = None self.envoy = envoy self.ask_to_skip = ask_to_skip self.uuid = None - self.statusbar = {'title': 'SECURITY CHECK', 'icon': lv.ICON_SHIELD} - async def show_intro(self): from pages import ShieldPage - - text = [] - # Only show the first item for manual flow - if not self.envoy: - text.append('Let\'s confirm Passport was not tampered with during shipping.') + from flows import SeriesOfPagesFlow if self.envoy: - text.append('On the next screen, scan the QR code shown in Envoy.') + messages = [{'text': 'On the next screen, scan the QR code shown in Envoy.'}] else: - text.append('On the next screen, scan the Security Check QR code from validate.foundationdevices.com.') + messages = [{'text': 'Let\'s confirm Passport was not tampered with during shipping.'}, + {'text': 'Next, scan the Security Check ' + 'QR code from validate.foundationdevices.com.'}] + + result = await SeriesOfPagesFlow(ShieldPage, messages).run() - result = await ShieldPage( - text=text, - left_micron=microns.Back, right_micron=microns.Forward).show() if result: self.goto(self.scan_qr_challenge) else: self.set_result(False) async def scan_qr_challenge(self): - from utils import recolor - result = await ScanQRPage(left_micron=microns.Cancel, right_micron=None).show() - - # User did not scan anything + qr_types = [QRType.UR2] if self.envoy else None + ur_types = [ur.Value.PASSPORT_REQUEST] if self.envoy else None + result = await ScanQRFlow(qr_types=qr_types, + ur_types=ur_types, + data_description='a supply chain validation challenge').run() if result is None: - from pages import QuestionPage - if self.envoy: - cancel = await QuestionPage( - text='Cancel Envoy Setup?\n\n{}'.format( - recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) - ).show() - if cancel: - self.set_result(None) - else: - return - else: - if not self.ask_to_skip: - self.set_result(True) - else: - skip = await QuestionPage( - text='Skip Security Check?\n\n{}'.format( - recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) - ).show() - if skip: - common.settings.set('validated_ok', True) - self.set_result(True) - else: - self.back() + self.goto(self.prompt_skip) return - # Scan succeeded -- verify its content if self.envoy: - if not is_valid_envoy_qrcode(result): - await self.show_error(("Security Check QR code is invalid.\n" - "Make sure you're scanning an Envoy QR code.")) - return - else: - if not is_valid_website_qrcode(result): - await self.show_error(("Security Check QR code is invalid.\n" - "There was an error scanning the QR code.")) - return - - if self.envoy: - passport_request = result.data.unwrap_passport_request() + passport_request = result.unwrap_passport_request() self.uuid = passport_request.uuid() - challenge = { - 'id': passport_request.scv_challenge_id(), - 'signature': passport_request.scv_challenge_signature(), - } + scv_id = passport_request.scv_challenge_id() + scv_signature = passport_request.scv_challenge_signature() else: - try: - parts = result.data.split(' ') - if len(parts) != 2: - await self.show_error(("Security Check QR code is invalid.\n" - "There's not enough information in the QR code.")) - return + parts = result.split(' ') + if len(parts) != 2: + await self.show_error('Security Check QR code is invalid.\n' + 'There\'s not enough information in the QR code.') + return - challenge = { - 'id': parts[0], - 'signature': parts[1], - } - # print('Manual: challenge={}'.format(challenge)) - except Exception as e: - await self.show_error(("Security Check QR code is invalid.\n" - "Make sure you're scanning a manual setup QR code.")) + try: + scv_id = a2b_hex(parts[0]) + scv_signature = a2b_hex(parts[1]) + except ValueError: + await self.show_error('Security Check QR code is invalid.\n') return id_hash = bytearray(32) - id_bin = a2b_hex(challenge['id']) if isinstance(challenge['id'], str) else challenge['id'] - id_hex = challenge['id'] if isinstance(challenge['id'], str) else b2a_hex(challenge['id']) - foundation.sha256(id_hex, - id_hash) - if isinstance(challenge['signature'], str): - signature = a2b_hex(challenge['signature']) - else: - signature = challenge['signature'] + foundation.sha256(b2a_hex(scv_id), id_hash) - signature_valid = passport.verify_supply_chain_server_signature(id_hash, signature) + signature_valid = passport.verify_supply_chain_server_signature(id_hash, scv_signature) if not signature_valid: await self.show_error('Security Check signature is invalid.') return - self.words = PinAttempt.supply_chain_validation_words(id_bin) - + self.words = PinAttempt.supply_chain_validation_words(scv_id) if self.envoy: self.goto(self.show_envoy_scan_msg) else: @@ -147,7 +96,6 @@ async def scan_qr_challenge(self): async def show_envoy_scan_msg(self): from pages import InfoPage - from utils import recolor result = await InfoPage( text='On Envoy, select {next}, and scan the following QR code.' @@ -176,7 +124,6 @@ async def show_envoy_response(self): caption='Scan with Envoy', left_micron=microns.Back, right_micron=microns.Forward).show() - if not result: self.back() else: @@ -185,13 +132,11 @@ async def show_envoy_response(self): async def show_manual_response(self): from pages import ShieldPage - words = '' - for idx, word in enumerate(self.words): - words += ' {}. {}\n'.format(idx + 1, word) - words = words[:-1] + lines = ['{}. {}\n'.format(idx + 1, word) for idx, word in enumerate(self.words)] + words = ''.join(lines) - result = await ShieldPage(text=words, card_header={'title': 'Security Check'}, centered=False, - left_micron=microns.Retry, right_micron=microns.Forward).show() + result = await ShieldPage(text=words, + left_micron=microns.Retry).show() if not result: self.back() else: @@ -221,11 +166,14 @@ async def ask_if_valid(self): if result: self.goto(self.scan_qr_challenge) else: - self.goto(self.ask_to_skip) + self.goto(self.prompt_skip) + + async def prompt_skip(self): - async def ask_to_skip(self): - from pages import QuestionPage - from utils import recolor + if not self.ask_to_skip: + common.settings.set('validated_ok', True) + self.set_result(True) + return skip = await QuestionPage( text='Skip Security Check?\n\n{}'.format( @@ -238,34 +186,7 @@ async def ask_to_skip(self): self.back() async def show_error(self, message): - from pages import InfoPage + from pages import ErrorPage - await InfoPage(text=message).show() + await ErrorPage(text=message).show() self.reset(self.show_intro) - - -def is_valid_envoy_qrcode(result): - if not isinstance(result, QRScanResult): - return False - - if ( - (result.error is not None) or - (result.data is None) or - (not isinstance(result.data, ur.Value)) - ): - return False - - return True - - -def is_valid_website_qrcode(result): - if not isinstance(result, QRScanResult): - return False - - if ( - (result.error is not None) or - (result.data is None) - ): - return False - - return True diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 4ca63116e..4c54dc9e5 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -21,10 +21,11 @@ async def show_intro(self): from pages import InfoPage import stash - if not self.mention_passphrase or not stash.bip39_passphrase: - text = 'Passport is about to {}.'.format(self.action_text) + if self.mention_passphrase and stash.bip39_passphrase: + text = 'Passport is about to {} and passphrase'.format(self.action_text) else: - text = 'Passport is about to {} and passphrase.'.format(self.action_text) + text = 'Passport is about to {}'.format(self.action_text) + result = await InfoPage( icon=lv.LARGE_ICON_SEED, text=text, left_micron=microns.Back, right_micron=microns.Forward).show() diff --git a/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py b/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py index f0306c495..79d1f00a5 100644 --- a/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py @@ -19,7 +19,7 @@ def __init__(self): self.set_result(True) return - self.statusbar = {'title': 'PASSPORT SETUP', 'icon': lv.ICON_SETUP} + self.statusbar = {'title': 'PASSPORT SETUP', 'icon': 'ICON_SETUP'} async def show_welcome(self): from pages import BrandmarkPage, ShutdownPage @@ -27,7 +27,7 @@ async def show_welcome(self): result = await BrandmarkPage( text='Welcome to Passport\n\nCongratulations on taking custody of your Bitcoin ' + 'and reclaiming your sovereignty!', - statusbar={'title': 'WELCOME', 'icon': lv.ICON_HOME}, + statusbar={'title': 'WELCOME', 'icon': 'ICON_HOME'}, left_micron=microns.Shutdown, right_micron=microns.Forward).show() if result: diff --git a/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py b/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py new file mode 100644 index 000000000..ec7ef937e --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# series_of_pages_flow.py - Display a series of pages + +from flows import Flow +from foundation import ur + + +class SeriesOfPagesFlow(Flow): + def __init__(self, page_class, page_args): + super().__init__(initial_state=self.display_pages, name='SeriesOfPagesFlow') + + self.page_class = page_class + self.page_args = page_args + + async def display_pages(self): + page_index = 0 + result = None + while page_index < len(self.page_args): + result = await self.page_class(**self.page_args[page_index]).show() + + if result: + page_index += 1 + elif page_index > 0: + page_index -= 1 + else: + break + + self.set_result(result) diff --git a/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py b/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py index d5565611f..1528f7e01 100644 --- a/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py @@ -13,7 +13,7 @@ def __init__(self): super().__init__(initial_state=self.show_setting_page, name='SetChainFlow') async def show_setting_page(self): - network = await ChainSettingPage(card_header={'title': 'Network', 'icon': lv.ICON_NETWORK}).show() + network = await ChainSettingPage(card_header={'title': 'Network', 'icon': 'ICON_NETWORK'}).show() if network is 'TBTC': text = "Passport is in Testnet mode. Use a separate seed to avoid issues " \ diff --git a/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py b/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py index cac873529..ff53e5e6e 100644 --- a/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py @@ -12,7 +12,7 @@ class SetInitialPINFlow(Flow): def __init__(self): super().__init__(initial_state=self.intro, name='SetInitialPINFlow') - self.statusbar = {'title': 'SET PIN', 'icon': lv.ICON_PIN} + self.statusbar = {'title': 'SET PIN', 'icon': 'ICON_PIN'} async def intro(self): from common import pa diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py index 5aea21be4..5b84c08ee 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py @@ -148,11 +148,7 @@ async def sign_transaction(self): options = [{'label': 'Cancel', 'value': True}, {'label': 'Review Details', 'value': False}] - should_cancel = await ChooserPage( - text='Cancel this transaction?', - options=options, - icon=lv.LARGE_ICON_QUESTION, - initial_value=options[0].get('value')).show() + should_cancel = await QuestionPage(text='Cancel this transaction?').show() if should_cancel: self.set_result(None) else: diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index c77075bea..1076c585f 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -37,12 +37,8 @@ def __init__(self): async def choose_file(self): from flows import FilePickerFlow - from files import CardSlot - root_path = CardSlot.get_sd_root() - - result = await FilePickerFlow( - initial_path=root_path, show_folders=True, suffix='psbt', filter_fn=None).run() + result = await FilePickerFlow(show_folders=True, suffix='psbt', filter_fn=None).run() if result is None: self.set_result(False) return @@ -92,22 +88,13 @@ async def common_flow(self): # This flow validates and signs if all goes well, and returns the signed psbt result = await SignPsbtCommonFlow(self.psbt_len).run() + if result is None: self.set_result(False) else: self.psbt = result self.goto(self.write_signed_transaction) - async def show_card_missing(self): - - result = await InsertMicroSDPage().show() - if not result: - result = QuestionPage(text='Cancel signing this transaction?').show() - if result: - self.set_result(None) - - self.goto(self.write_signed_transaction) - async def write_signed_transaction(self): from files import securely_blank_file from pages import ErrorPage @@ -131,10 +118,11 @@ async def write_signed_transaction(self): write_fn=self.write_psbt_fn, success_text="psbt", path=orig_path, - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_1: # Fall through - await ErrorPage(text='Unable to save {} to MicroSD'.format(target_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() return if is_comp: @@ -143,9 +131,10 @@ async def write_signed_transaction(self): write_fn=self.write_final_fn, success_text="transaction", path=orig_path, - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_2: - await ErrorPage(text='Unable to save {} to MicroSD'.format(target2_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() # Fall through return diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index a8251afea..0821fc0f5 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -4,60 +4,77 @@ # sign_psbt_qr_flow.py - Sign a PSBT from a microSD card from flows import Flow -from foundation import FixedBytesIO, ur -from passport import mem -from pages import ErrorPage class SignPsbtQRFlow(Flow): def __init__(self): super().__init__(initial_state=self.scan_transaction, name='SignPsbtQRFlow') - self.psbt = None + self.raw_psbt = None self.ur_type = None + self.psbt = None + self.txid = None + self.is_comp = None + self.out_fn = None + self.out2_fn = None + self.signed_bytes = None + self.max_frames = 35 async def scan_transaction(self): - from pages import ScanQRPage, ErrorPage + from foundation import ur + from data_codecs.qr_type import QRType + from flows import ScanQRFlow, SignPsbtMicroSDFlow + from errors import Error + from pages import YesNoChooserPage import microns + import passport - # TODO: May need to set statusbar content here and restore it after - result = await ScanQRPage(right_micron=microns.Checkmark).show() + result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], + ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], + data_description='a PSBT file', + max_frames=self.max_frames).run() if result is None: # User canceled the scan self.set_result(False) - else: - # Got a scan result (aka QRScanResult). - if result.is_failure(): - # Unable to scan QR code - show error? - await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() - self.set_result(False) + return + + if result == Error.PSBT_OVERSIZED: + text = "This transaction is large and will take some time to scan. \ +How would you like to proceed?" + + if passport.IS_COLOR: + text = '\n' + text + '\n' + + result = await YesNoChooserPage(text=text, + yes_text='Continue with QR', + no_text='Sign with microSD', + left_micron=microns.Back).show() + + if result is None or result: + self.max_frames = None else: - # TODO: handle hex not only UR. Wasn't handled before the UR - # rework too. - if isinstance(result.data, ur.Value): - self.qr_type = result.qr_type - self.ur_type = result.data.ur_type() - - if self.ur_type == ur.Value.BYTES: - self.raw_psbt = result.data.unwrap_bytes() - elif self.ur_type == ur.Value.CRYPTO_PSBT: - self.raw_psbt = result.data.unwrap_crypto_psbt() - else: - await ErrorPage(text='The QR code does not contain a transaction.').show() - self.set_result(False) - return - - self.goto(self.copy_to_flash) - else: - await ErrorPage(text='The QR code does not contain a transaction.').show() - self.set_result(False) + result = await SignPsbtMicroSDFlow().run() + self.set_result(result) + return # Run it again with no max frames if the user wants + + if isinstance(result, ur.Value): + self.ur_type = result.ur_type() + + if self.ur_type == ur.Value.CRYPTO_PSBT: + self.raw_psbt = result.unwrap_crypto_psbt() + elif self.ur_type == ur.Value.BYTES: + self.raw_psbt = result.unwrap_bytes() + else: + self.raw_psbt = result + + self.goto(self.copy_to_flash) async def copy_to_flash(self): import gc from utils import spinner_task from tasks import copy_psbt_to_external_flash_task - from pages import ErrorPage from public_constants import TXN_INPUT_OFFSET from errors import Error + from pages import ErrorPage gc.collect() # Try to avoid excessive fragmentation @@ -72,6 +89,7 @@ async def copy_to_flash(self): self.set_result(False) return + self.raw_psbt = None gc.collect() # Try to avoid excessive fragmentation # PSBT was copied to external flash @@ -81,30 +99,27 @@ async def common_flow(self): from flows import SignPsbtCommonFlow # This flow validates and signs if all goes well, and returns the signed psbt - self.psbt = await SignPsbtCommonFlow(self.psbt_len).run() + result = await SignPsbtCommonFlow(self.psbt_len).run() - if self.psbt is None: + if result is None: self.set_result(False) else: - self.goto(self.show_signed_transaction) + self.psbt = result + self.goto(self.get_signed_bytes) - async def show_signed_transaction(self): - import gc - from pages import ShowQRPage - from data_codecs.qr_type import QRType - from ubinascii import hexlify as b2a_hex - import microns + async def get_signed_bytes(self): + from foundation import FixedBytesIO + from pages import ErrorPage + from passport import mem # Copy signed txn into a bytearray and show the data as a UR - # try: - signed_bytes = None try: with FixedBytesIO(mem.psbt_output) as bfd: with self.output_encoder(bfd) as fd: # Always serialize back to PSBT for QR codes self.psbt.serialize(fd) bfd.seek(0) - signed_bytes = bfd.getvalue() + self.signed_bytes = bfd.getvalue() # print('len(signed_bytes)={}'.format(len(signed_bytes))) # print('signed_bytes={}'.format(signed_bytes)) except MemoryError as e: @@ -112,19 +127,120 @@ async def show_signed_transaction(self): self.set_result(False) return - self.psbt = None - gc.collect() - - if self.qr_type == QRType.QR: - qr_data = b2a_hex(signed_bytes) - elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.BYTES: - qr_data = ur.new_bytes(signed_bytes) - elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.CRYPTO_PSBT: - qr_data = ur.new_crypto_psbt(signed_bytes) + self.goto(self.show_signed_transaction) + + async def show_signed_transaction(self): + from pages import ShowQRPage + from data_codecs.qr_type import QRType + from ubinascii import hexlify as b2a_hex + import microns + from foundation import ur + + if self.ur_type is None: + qr_type = QRType.QR + qr_data = b2a_hex(self.signed_bytes) else: - raise RuntimeException("Unsupported output format") + qr_type = QRType.UR2 + if self.ur_type == ur.Value.CRYPTO_PSBT: + qr_data = ur.new_crypto_psbt(self.signed_bytes) + elif self.ur_type == ur.Value.BYTES: + qr_data = ur.new_bytes(self.signed_bytes) + else: + raise RuntimeError('Unknown UR type: {}'.format(self.ur_type)) + + result = await ShowQRPage(qr_type=qr_type, + qr_data=qr_data, + left_micron=microns.MicroSD, + right_micron=microns.Checkmark).show() + + if not result: + self.goto(self.save_to_microsd) + return + + self.set_result(True) + + def write_final_fn(self, filename): + from utils import HexWriter + + # write psbt to file as hex + with HexWriter(open(filename, 'w+t')) as fd: + self.txid = self.psbt.finalize(fd) + self.out2_fn = filename + + def write_psbt_fn(self, filename): + # Attempt to write-out the transaction + with self.output_encoder(open(filename, 'wb')) as fd: + # save as updated PSBT + self.psbt.serialize(fd) + self.out_fn = filename + + async def save_to_microsd(self): + from flows import SaveToMicroSDFlow + from pages import ErrorPage + from utils import get_folder_path + from public_constants import DIR_TRANSACTIONS + + # Check that the psbt has been written, and the transaction has been written if complete + if self.out_fn and (self.is_comp == bool(self.out2_fn)): + self.goto(self.show_success) + return + + base = 'QR' + + self.is_comp = self.psbt.is_complete() + if not self.is_comp: + # Keep the filename under control during multiple passes + target_fname = base + '-part.psbt' + else: + # Add -signed to end. We won't offer to sign again. + target_fname = base + '-signed.psbt' + + result_1 = await SaveToMicroSDFlow(filename=target_fname, + write_fn=self.write_psbt_fn, + success_text="psbt", + path=get_folder_path(DIR_TRANSACTIONS), + automatic=False, + auto_prompt=True).run() + if not result_1: + self.back() + return + + if self.is_comp: + target2_fname = base + '-final.txn' + result_2 = await SaveToMicroSDFlow(filename=target2_fname, + write_fn=self.write_final_fn, + success_text="transaction", + path=get_folder_path(DIR_TRANSACTIONS), + automatic=False, + auto_prompt=True).run() + if not result_2: + self.back() + return + + self.goto(self.show_success) + + async def show_success(self): + import microns + from lvgl import LARGE_ICON_SUCCESS + from styles.colors import DEFAULT_LARGE_ICON_COLOR + from pages import LongTextPage + + msg = "Updated PSBT is:\n\n%s" % self.out_fn + if self.out2_fn: + msg += '\n\nFinalized transaction (ready for broadcast):\n\n%s' % self.out2_fn + + if self.txid: + msg += '\n\nFinal TXID:\n' + self.txid + + result = await LongTextPage(text=msg, + centered=True, + left_micron=microns.ScanQR, + right_micron=microns.Checkmark, + icon=LARGE_ICON_SUCCESS, + icon_color=DEFAULT_LARGE_ICON_COLOR).show() + + if not result: + self.goto(self.show_signed_transaction) + return - await ShowQRPage(qr_type=self.qr_type, - qr_data=qr_data, - right_micron=microns.Checkmark).show() self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py b/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py index 2565c49d7..46b92a8f1 100644 --- a/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py @@ -3,31 +3,20 @@ # # system_test_camera_flow.py - Scans a QR code with the camera and shows the data in it -from flows import Flow -import microns -from pages import ScanQRPage -from pages import ErrorPage, SuccessPage, QuestionPage +from flows import Flow, ScanQRFlow +from pages import SuccessPage, QuestionPage +from foundation import ur class TestCameraFlow(Flow): - def __init__(self, card_header=None, statusbar=None): - super().__init__(initial_state=self.scan_qr, name='TestQrScanFlow') - self.card_header = card_header - self.statusbar = statusbar + def __init__(self): + super().__init__(initial_state=self.scan_qr, name='TestCameraFlow') async def scan_qr(self): - result = await ScanQRPage( - card_header=self.card_header, statusbar=self.statusbar, right_micron=microns.Cancel).show() + result = await ScanQRFlow(data_description='a normal QR code').run() if result is None: skip = await QuestionPage(text='Skip the Camera test?').show() self.set_result(skip) else: - # Got a scan result (aka QRScanResult): good data or error - if result.is_failure(): - # Unable to scan QR code - show error? - await ErrorPage(text='Unable to scan QR code.').show() - self.set_result(False) - else: - data = result.data - await SuccessPage(data).show() - self.set_result(True) + await SuccessPage(result).show() + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py b/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py index f3781c7f2..7e76f36a2 100644 --- a/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py @@ -13,7 +13,7 @@ class TermsOfUseFlow(Flow): def __init__(self): super().__init__(initial_state=self.show_terms, name='TermsOfUseFlow') - self.statusbar = {'title': 'TERMS OF USE', 'icon': lv.ICON_INFO} + self.statusbar = {'title': 'TERMS OF USE', 'icon': 'ICON_INFO'} # Skip if already accepted if common.settings.get('terms_ok') == 1: self.goto(self.show_status) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py index e9451e210..0596fb079 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py @@ -67,26 +67,23 @@ async def choose_sig_type(self): async def scan_address(self): import chains - from pages import ErrorPage, ScanQRPage + from pages import ErrorPage + from flows import ScanQRFlow from wallets.utils import get_addr_type_from_address, get_deriv_path_from_addr_type_and_acct from utils import is_valid_btc_address, get_next_addr + from data_codecs.qr_type import QRType - result = await ScanQRPage( - left_micron=microns.Back, - right_micron=None).show() + result = await ScanQRFlow(qr_types=[QRType.QR], + data_description='a Bitcoin address').run() if result is None: if not self.back(): self.set_result(False) return return - elif result.is_failure(): - await ErrorPage(text='Unable to scan QR code.').show() - self.set_result(False) - return # print('result={}'.format(result)) - self.address = result.data + self.address = result # Simple check on the data type first chain_name = chains.current_chain().name @@ -109,6 +106,11 @@ async def scan_address(self): self.goto(self.search_for_address) + def finalize(self, addr_idx, is_change): + self.found_addr_idx = addr_idx + self.found_is_change = is_change == 1 + self.goto(self.found) + async def search_for_address(self): from tasks import search_for_address_task from utils import get_prev_address_range, get_next_address_range, spinner_task @@ -123,6 +125,23 @@ async def search_for_address(self): addr_idx = -1 is_change = 0 + (addr_idx, path_info, error) = await spinner_task( + 'Searching Addresses', + search_for_address_task, + min_duration_ms=0, + args=[self.deriv_path, + 0, + self.address, + self.addr_type, + self.multisig_wallet, + is_change, + 1, + True]) + + if addr_idx >= 0: + self.finalize(addr_idx, is_change) + return + for is_change in range(0, 2): # print('CHECKING: low_range={} low_size={}'.format(self.low_range, self.low_size)) # Check downwards @@ -130,6 +149,7 @@ async def search_for_address(self): (addr_idx, path_info, error) = await spinner_task( 'Searching Addresses', search_for_address_task, + min_duration_ms=0, args=[self.deriv_path, self.low_range[is_change][0], self.address, @@ -148,6 +168,7 @@ async def search_for_address(self): (addr_idx, path_info, error) = await spinner_task( 'Searching Addresses', search_for_address_task, + min_duration_ms=0, args=[self.deriv_path, self.high_range[is_change][0], self.address, @@ -161,14 +182,13 @@ async def search_for_address(self): break if addr_idx >= 0: - self.found_addr_idx = addr_idx - self.found_is_change = is_change == 1 - self.goto(self.found) + self.finalize(addr_idx, is_change) else: self.goto(self.not_found) async def not_found(self): - from pages import ErrorPage + from pages import ErrorPage, LongErrorPage + import passport # Address was not found in that batch of 100, so offer to keep searching msg = 'Address Not Found\nRanges Checked:\n' @@ -182,15 +202,18 @@ async def not_found(self): msg += '\n\nContinue searching?' - result = await ErrorPage(msg, left_micron=microns.Cancel, right_micron=microns.Checkmark).show() + page_class = ErrorPage if passport.IS_COLOR else LongErrorPage + + result = await page_class(msg, left_micron=microns.Cancel, right_micron=microns.Checkmark).show() if result: self.goto(self.search_for_address) else: self.set_result(False) async def found(self): - from pages import SuccessPage + from pages import SuccessPage, LongSuccessPage from utils import save_next_addr, format_btc_address + import passport # Remember where to start from next time save_next_addr(self.acct_num, self.addr_type, self.found_addr_idx, self.found_is_change) @@ -203,5 +226,6 @@ async def found(self): 'Change' if self.found_is_change == 1 else 'Receive', self.found_addr_idx) - await SuccessPage(msg).show() + page_class = SuccessPage if passport.IS_COLOR else LongSuccessPage + await page_class(msg).show() self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py index 38f6f332f..f71ec4622 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py @@ -5,10 +5,11 @@ from flows import Flow, FilePickerFlow -from pages import ErrorPage, SuccessPage, InsertMicroSDPage +from pages import ErrorPage, SuccessPage, LongSuccessPage, InsertMicroSDPage from utils import get_backups_folder_path, spinner_task from tasks import verify_backup_task from errors import Error +import passport class VerifyBackupFlow(Flow): @@ -34,8 +35,9 @@ async def do_verify(self): verify_backup_task, args=[self.backup_file_path]) if error is None: - await SuccessPage(text='Backup file appears to be valid.\n\nPlease note this is only a check to ensure ' + - 'the file has not been modified or damaged.').show() + page_class = SuccessPage if passport.IS_COLOR else LongSuccessPage + await page_class(text='Backup file appears to be valid.\n\nPlease note this is only a check to ensure ' + + 'the file has not been modified or damaged.').show() self.set_result(True) elif error is Error.MICROSD_CARD_MISSING: result = await InsertMicroSDPage().show() diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index 91ef354d5..84c06f8ff 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -7,33 +7,148 @@ class ViewSeedWordsFlow(Flow): - def __init__(self, external_key=None): + def __init__(self, external_key=None, qr_option=False, sd_option=False, path=None, filename=None): self.external_key = external_key - super().__init__(initial_state=self.show_warning, name='ViewSeedWordsFlow') + self.qr_option = qr_option - async def show_warning(self): + if sd_option: + filename = filename or 'Seed.txt' # Caller should never let this happen + + self.sd_option = sd_option + self.path = path + self.filename = filename + self.qr_type = None + self.words = None + self.seed_micron = None + self.mention_passphrase = True if not external_key else False + super().__init__(initial_state=self.generate_words, name='ViewSeedWordsFlow') + + async def generate_words(self): + from flows import GetSeedWordsFlow + + self.words = await GetSeedWordsFlow(self.external_key).run() + + if self.words is None: + self.set_result(False) + return + + self.goto(self.choose_mode) + + async def choose_mode(self): + from pages import ChooserPage + from data_codecs.qr_type import QRType + import microns + + if not (self.qr_option or self.sd_option): + self.goto(self.show_seed_words) + return + + options = [{'label': 'Seed Words', 'value': self.show_seed_words}] + + if self.qr_option: + options.extend([{'label': 'Compact SeedQR', + 'value': QRType.COMPACT_SEED_QR}, + {'label': 'SeedQr', + 'value': QRType.SEED_QR}]) + + if self.sd_option: + options.append({'label': 'microSD', + 'value': self.save_to_sd}) + + mode = await ChooserPage(card_header={'title': 'Format'}, options=options).show() + + if mode is None: + self.set_result(False) + return + + if isinstance(mode, int) and mode in [QRType.SEED_QR, QRType.COMPACT_SEED_QR]: + self.qr_type = mode + mode = self.show_qr + self.seed_micron = microns.Back + + self.goto(mode) + + async def show_qr(self): from flows import SeedWarningFlow + from pages import ShowQRPage + import microns - mention_passphrase = False if self.external_key else True - result = await SeedWarningFlow(mention_passphrase=mention_passphrase).run() + result = await SeedWarningFlow(action_text="display your seed as a QR code", + mention_passphrase=self.mention_passphrase).run() if not result: - self.set_result(False) + self.back() + return + + result = await ShowQRPage(qr_type=self.qr_type, qr_data=self.words, right_micron=microns.Checkmark).show() + + if not result: + return + + self.goto(self.confirm_qr) + + async def confirm_qr(self): + from pages import InfoPage + import microns + + plural_label = 's' if len(self.words) == 24 else '' + text = 'Confirm the seed words in the following page{}.'.format(plural_label) + result = await InfoPage(text=text, left_micron=microns.Back).show() + + if not result: + self.back() + return self.goto(self.show_seed_words) - async def show_seed_words(self): - from flows import GetSeedWordsFlow - from pages import SeedWordsListPage, InfoPage - import stash + async def save_to_sd(self): + from flows import SeedWarningFlow + from utils import B2A + from flows import SaveToMicroSDFlow - words = await GetSeedWordsFlow(self.external_key).run() + result = await SeedWarningFlow(action_text="copy your seed to the microSD card", + mention_passphrase=self.mention_passphrase).run() - if words is None: - self.set_result(False) + if not result: + self.back() + return + + text = " ".join(self.words) + result = await SaveToMicroSDFlow(filename=self.filename, + path=self.path, + data=text, + success_text="seed").run() + + if not result: return - result = await SeedWordsListPage(words=words).show() + self.goto(self.show_passphrase) + + async def show_seed_words(self): + from flows import SeedWarningFlow + from pages import SeedWordsListPage + + if not self.qr_type: # We already gave the seed warning flow + result = await SeedWarningFlow(mention_passphrase=self.mention_passphrase).run() + + if not result: + self.set_result(False) + return + + result = False + while not result: + result = await SeedWordsListPage(words=self.words, + left_micron=self.seed_micron).show() + if not result and self.qr_type: + self.back() + return + + self.goto(self.show_passphrase) + + async def show_passphrase(self): + import stash + from pages import InfoPage + if stash.bip39_passphrase != '' and not self.external_key: await InfoPage(text='Passphrase: {}'.format(stash.bip39_passphrase)).show() - self.set_result(result) + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 0aba843db..b03100079 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -12,7 +12,7 @@ ######################################################################################## # field # type # description ######################################################################################## -# icon # lv.ICON* # icon +# icon # string # icon # label # string # label # submenu # menu function # a function that returns a list of menu items # page # Page # page to display @@ -33,11 +33,11 @@ def manage_account_menu(): from pages import AccountDetailsPage return [ - {'icon': lv.ICON_FOLDER, 'label': 'Account Details', 'page': AccountDetailsPage}, - {'icon': lv.ICON_INFO, 'label': 'Rename Account', 'flow': RenameAccountFlow}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, + {'icon': 'ICON_FOLDER', 'label': 'Account Details', 'page': AccountDetailsPage}, + {'icon': 'ICON_INFO', 'label': 'Rename Account', 'flow': RenameAccountFlow}, + {'icon': 'ICON_CONNECT', 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}}, - {'icon': lv.ICON_CANCEL, 'label': 'Delete Account', 'flow': DeleteAccountFlow}, + {'icon': 'ICON_CANCEL', 'label': 'Delete Account', 'flow': DeleteAccountFlow}, ] @@ -45,12 +45,12 @@ def account_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_FOLDER, 'label': 'Manage Account', 'submenu': manage_account_menu}, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_FOLDER', 'label': 'Manage Account', 'submenu': manage_account_menu}, ] @@ -58,9 +58,9 @@ def health_check_submenu(): from flows import CasaHealthCheckQRFlow, CasaHealthCheckMicrosdFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Check with QR Code', 'flow': CasaHealthCheckQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Check with QR Code', 'flow': CasaHealthCheckQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Check with microSD', 'flow': CasaHealthCheckMicrosdFlow, + {'icon': 'ICON_MICROSD', 'label': 'Check with microSD', 'flow': CasaHealthCheckMicrosdFlow, 'statusbar': {'title': 'SIGN'}}, ] @@ -69,13 +69,13 @@ def casa_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow, ConnectWalletFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_HEALTH_CHECK, 'label': 'Health Check', 'submenu': health_check_submenu}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect to Casa', 'flow': ConnectWalletFlow, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_HEALTH_CHECK', 'label': 'Health Check', 'submenu': health_check_submenu}, + {'icon': 'ICON_CONNECT', 'label': 'Connect to Casa', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}, 'args': {'sw_wallet': 'Casa'}}, ] @@ -84,12 +84,12 @@ def postmix_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow, ConnectWalletFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_CONNECT', 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}}, ] @@ -99,12 +99,12 @@ def plus_menu(): from flows import NewAccountFlow, ApplyPassphraseFlow return [ - {'icon': lv.ICON_ADD_ACCOUNT, 'label': 'New Account', 'flow': NewAccountFlow}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Enter Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_ADD_ACCOUNT', 'label': 'New Account', 'flow': NewAccountFlow}, + {'icon': 'ICON_PASSPHRASE', 'label': 'Enter Passphrase', 'flow': ApplyPassphraseFlow, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': lambda: not is_passphrase_active()}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Clear Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_PASSPHRASE', 'label': 'Clear Passphrase', 'flow': ApplyPassphraseFlow, 'args': {'passphrase': ''}, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': is_passphrase_active}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Change Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_PASSPHRASE', 'label': 'Change Passphrase', 'flow': ApplyPassphraseFlow, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': is_passphrase_active}, ] @@ -115,10 +115,10 @@ def device_menu(): from utils import is_logged_in return [ - {'icon': lv.ICON_BRIGHTNESS, 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, - {'icon': lv.ICON_COUNTDOWN, 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, - {'icon': lv.ICON_PIN, 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, - {'icon': lv.ICON_INFO, 'label': 'About', 'flow': AboutFlow}, + {'icon': 'ICON_BRIGHTNESS', 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, + {'icon': 'ICON_COUNTDOWN', 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, + {'icon': 'ICON_PIN', 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, + {'icon': 'ICON_INFO', 'label': 'About', 'flow': AboutFlow}, ] @@ -126,12 +126,12 @@ def backup_menu(): from flows import BackupFlow, RestoreBackupFlow, VerifyBackupFlow, ViewBackupCodeFlow return [ - {'icon': lv.ICON_BACKUP, 'label': 'Backup Now', 'flow': BackupFlow, 'is_visible': has_seed}, - {'icon': lv.ICON_RETRY, 'label': 'Restore', 'flow': RestoreBackupFlow, + {'icon': 'ICON_BACKUP', 'label': 'Backup Now', 'flow': BackupFlow, 'is_visible': has_seed}, + {'icon': 'ICON_RETRY', 'label': 'Restore', 'flow': RestoreBackupFlow, 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_CIRCLE_CHECK, 'label': 'Verify Backup', 'flow': VerifyBackupFlow}, - {'icon': lv.ICON_PIN, 'label': 'View Backup Code', 'flow': ViewBackupCodeFlow, - 'statusbar': {'title': 'BACKUP', 'icon': lv.ICON_PIN}, 'is_visible': has_seed} + {'icon': 'ICON_CIRCLE_CHECK', 'label': 'Verify Backup', 'flow': VerifyBackupFlow}, + {'icon': 'ICON_PIN', 'label': 'View Backup Code', 'flow': ViewBackupCodeFlow, + 'statusbar': {'title': 'BACKUP', 'icon': 'ICON_PIN'}, 'is_visible': has_seed} ] @@ -142,10 +142,10 @@ def key_item_menu(): ExportDerivedKeyFlow, HideDerivedKeyFlow) return [ - {'icon': lv.ICON_ONE_KEY, 'label': 'View Details', 'flow': ViewDerivedKeyDetailsFlow}, - {'icon': lv.ICON_SIGN, 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Export', 'flow': ExportDerivedKeyFlow}, - {'icon': lv.ICON_ERASE, 'label': 'Toggle Hidden', 'flow': HideDerivedKeyFlow}, + {'icon': 'ICON_ONE_KEY', 'label': 'View Details', 'flow': ViewDerivedKeyDetailsFlow}, + {'icon': 'ICON_INFO', 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, + {'icon': 'ICON_SCAN_QR', 'label': 'Export', 'flow': ExportDerivedKeyFlow}, + {'icon': 'ICON_ERASE', 'label': 'Toggle Hidden', 'flow': HideDerivedKeyFlow}, ] @@ -170,7 +170,7 @@ def new_key_menu(): def manage_keys(): from utils import toggle_showing_hidden_keys, are_hidden_keys_showing return [ - {'icon': lv.ICON_TWO_KEYS, + {'icon': 'ICON_TWO_KEYS', 'label': 'Show Hidden', 'action': lambda item: toggle_showing_hidden_keys(), 'is_toggle': True, @@ -178,6 +178,15 @@ def manage_keys(): ] +def nostr_menu(): + from utils import is_dev_build + + if is_dev_build(): + from developer import NostrDelegationFlow + return [{'icon': 'ICON_SIGN', 'label': 'Delegate', 'flow': NostrDelegationFlow}] + return [] + + def key_manager_menu(): from utils import get_derived_keys, are_hidden_keys_showing from derived_key import get_key_type_from_tn @@ -204,11 +213,11 @@ def key_manager_menu(): 'card_header': {'title': title, 'right_icon': key_type['icon']}, 'statusbar': {'title': 'KEY MANAGER'}, - 'args': {'context': key}, + 'args': {'context': key, 'dynamic': key_type.get('menu', None)}, 'auto_card_header': False}) - result.append({'icon': lv.ICON_ONE_KEY, 'label': 'New Key', 'submenu': new_key_menu}) - result.append({'icon': lv.ICON_SETTINGS, 'label': 'Manage', 'submenu': manage_keys}) + result.append({'icon': 'ICON_ONE_KEY', 'label': 'New Key', 'submenu': new_key_menu}) + result.append({'icon': 'ICON_SETTINGS', 'label': 'Manage', 'submenu': manage_keys}) return result @@ -219,32 +228,38 @@ def bitcoin_menu(): from utils import is_logged_in return [ - {'icon': lv.ICON_BITCOIN, 'label': 'Units', 'page': UnitsSettingPage, 'is_visible': is_logged_in}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Multisig', 'submenu': multisig_menu, 'is_visible': has_seed}, - {'icon': lv.ICON_NETWORK, 'label': 'Network', 'flow': SetChainFlow, 'statusbar': {}, + {'icon': 'ICON_BITCOIN', 'label': 'Units', 'page': UnitsSettingPage, 'is_visible': is_logged_in}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Multisig', 'submenu': multisig_menu, 'is_visible': has_seed}, + {'icon': 'ICON_NETWORK', 'label': 'Network', 'flow': SetChainFlow, 'statusbar': {}, 'is_visible': is_logged_in}, ] def security_menu(): - from flows import ChangePINFlow, SignTextFileFlow, ViewSeedWordsFlow, NewSeedFlow, RestoreSeedFlow + from flows import ChangePINFlow, SignTextFileFlow, NewSeedFlow, RestoreSeedFlow return [ - {'icon': lv.ICON_SEED, 'label': 'Restore Seed', 'flow': RestoreSeedFlow, 'is_visible': lambda: not has_seed(), + {'icon': 'ICON_SEED', 'label': 'Restore Seed', 'flow': RestoreSeedFlow, 'is_visible': lambda: not has_seed(), 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_SEED, 'label': 'New Seed', 'flow': NewSeedFlow, 'is_visible': lambda: not has_seed(), + {'icon': 'ICON_SEED', 'label': 'New Seed', 'flow': NewSeedFlow, 'is_visible': lambda: not has_seed(), 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_SIGN, 'label': 'Sign Text File', 'flow': SignTextFileFlow, 'is_visible': has_seed}, + {'icon': 'ICON_SIGN', 'label': 'Sign Text File', 'flow': SignTextFileFlow, 'is_visible': has_seed}, ] def update_menu(): from flows import UpdateFirmwareFlow, ViewCurrentFirmwareFlow from utils import is_logged_in + import passport + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') return [ - {'icon': lv.ICON_FIRMWARE, 'label': 'Update Firmware', 'flow': UpdateFirmwareFlow, 'is_visible': is_logged_in}, - {'icon': lv.ICON_INFO, 'label': 'Current Version', 'flow': ViewCurrentFirmwareFlow, 'statusbar': {}}, + {'icon': 'ICON_FIRMWARE', + 'label': 'Update Firmware', + 'flow': UpdateFirmwareFlow, + 'is_visible': is_logged_in, + 'statusbar': {'title': title, 'icon': 'ICON_FIRMWARE'}}, + {'icon': 'ICON_INFO', 'label': 'Current Version', 'flow': ViewCurrentFirmwareFlow, 'statusbar': {}}, ] @@ -252,9 +267,9 @@ def microsd_menu(): from flows import FormatMicroSDFlow, ListFilesFlow, ExportSummaryFlow return [ - {'icon': lv.ICON_MICROSD, 'label': 'Format Card', 'flow': FormatMicroSDFlow}, - {'icon': lv.ICON_FILE, 'label': 'List Files', 'flow': ListFilesFlow}, - {'icon': lv.ICON_INFO, 'label': 'Export Summary', 'flow': ExportSummaryFlow, 'is_visible': has_seed}, + {'icon': 'ICON_MICROSD', 'label': 'Format Card', 'flow': FormatMicroSDFlow}, + {'icon': 'ICON_FILE', 'label': 'List Files', 'flow': ListFilesFlow}, + {'icon': 'ICON_INFO', 'label': 'Export Summary', 'flow': ExportSummaryFlow, 'is_visible': has_seed}, ] @@ -263,13 +278,13 @@ def multisig_item_menu(): ExportMultisigQRFlow, ExportMultisigMicrosdFlow) return [ - {'icon': lv.ICON_TWO_KEYS, 'label': 'View Details', 'flow': ViewMultisigDetailsFlow}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Export via QR', 'flow': ExportMultisigQRFlow, + {'icon': 'ICON_TWO_KEYS', 'label': 'View Details', 'flow': ViewMultisigDetailsFlow}, + {'icon': 'ICON_SCAN_QR', 'label': 'Export via QR', 'flow': ExportMultisigQRFlow, 'statusbar': {'title': 'EXPORT'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Export via microSD', 'flow': ExportMultisigMicrosdFlow, + {'icon': 'ICON_MICROSD', 'label': 'Export via microSD', 'flow': ExportMultisigMicrosdFlow, 'statusbar': {'title': 'EXPORT'}}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Rename', 'flow': RenameMultisigFlow, 'exit_on_success': True}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Delete', 'flow': DeleteMultisigFlow, 'exit_on_success': True}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Rename', 'flow': RenameMultisigFlow, 'exit_on_success': True}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Delete', 'flow': DeleteMultisigFlow, 'exit_on_success': True}, ] @@ -279,14 +294,14 @@ def multisig_menu(): from flows import ImportMultisigWalletFromMicroSDFlow, ImportMultisigWalletFromQRFlow if not MultisigWallet.exists(): - items = [{'icon': lv.ICON_TWO_KEYS, 'label': '(None setup yet)', 'page': ErrorPage, + items = [{'icon': 'ICON_TWO_KEYS', 'label': '(None setup yet)', 'page': ErrorPage, 'args': {'text': "You haven't imported any multisig wallets yet."}}] else: items = [] for ms in MultisigWallet.get_all(): nice_name = '%d/%d: %s' % (ms.M, ms.N, ms.name) items.append({ - 'icon': lv.ICON_TWO_KEYS, + 'icon': 'ICON_TWO_KEYS', 'label': nice_name, 'submenu': multisig_item_menu, # Adding this below causes the header to stick around after it shoudl be gone @@ -295,11 +310,11 @@ def multisig_menu(): 'args': {'context': ms.storage_idx} }) - items.append({'icon': lv.ICON_SCAN_QR, 'label': 'Import from QR', 'flow': ImportMultisigWalletFromQRFlow, + items.append({'icon': 'ICON_SCAN_QR', 'label': 'Import from QR', 'flow': ImportMultisigWalletFromQRFlow, 'statusbar': {'title': 'IMPORT'}}) - items.append({'icon': lv.ICON_MICROSD, 'label': 'Import from microSD', + items.append({'icon': 'ICON_MICROSD', 'label': 'Import from microSD', 'flow': ImportMultisigWalletFromMicroSDFlow, 'statusbar': {'title': 'IMPORT'}}) - items.append({'icon': lv.ICON_SETTINGS, 'label': 'Multisig Policy', 'page': MultisigPolicySettingPage}) + items.append({'icon': 'ICON_SETTINGS', 'label': 'Multisig Policy', 'page': MultisigPolicySettingPage}) return items @@ -309,11 +324,11 @@ def developer_pubkey_menu(): from flows import InstallDevPubkeyFlow, ViewDevPubkeyFlow, RemoveDevPubkeyFlow return [ - {'icon': lv.ICON_ONE_KEY, 'label': 'Install PubKey', 'flow': InstallDevPubkeyFlow, + {'icon': 'ICON_ONE_KEY', 'label': 'Install PubKey', 'flow': InstallDevPubkeyFlow, 'is_visible': lambda: not has_dev_pubkey()}, - {'icon': lv.ICON_ONE_KEY, 'label': 'View PubKey', 'flow': ViewDevPubkeyFlow, + {'icon': 'ICON_ONE_KEY', 'label': 'View PubKey', 'flow': ViewDevPubkeyFlow, 'is_visible': has_dev_pubkey}, - {'icon': lv.ICON_CANCEL, 'label': 'Remove Pubkey', 'flow': RemoveDevPubkeyFlow, + {'icon': 'ICON_CANCEL', 'label': 'Remove Pubkey', 'flow': RemoveDevPubkeyFlow, 'is_visible': has_dev_pubkey} ] @@ -322,14 +337,14 @@ def advanced_menu(): from flows import ViewSeedWordsFlow, ErasePassportFlow, ScvFlow, ShowSecurityWordsSettingFlow return [ - {'icon': lv.ICON_SETTINGS, 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, - {'icon': lv.ICON_SEED, 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, - 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, + {'icon': 'ICON_SETTINGS', 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, + {'icon': 'ICON_SEED', 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, + 'statusbar': {'title': 'SEED WORDS', 'icon': 'ICON_SEED'}}, + {'icon': 'ICON_ONE_KEY', 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, 'statusbar': {'title': 'DEV. PUBKEY'}}, - {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, - {'icon': lv.ICON_ERASE, 'label': 'Erase Passport', 'flow': ErasePassportFlow}, - {'icon': lv.ICON_SHIELD, 'label': 'Security Check', 'flow': ScvFlow, + {'icon': 'ICON_MICROSD', 'label': 'microSD', 'submenu': microsd_menu}, + {'icon': 'ICON_ERASE', 'label': 'Erase Passport', 'flow': ErasePassportFlow}, + {'icon': 'ICON_SHIELD', 'label': 'Security Check', 'flow': ScvFlow, 'args': {'envoy': False, 'ask_to_skip': False}}, ] @@ -348,6 +363,7 @@ def developer_menu(): BatteryPage, DeleteDerivedKeysFlow, DeveloperFunctionsFlow, + FCCTestFlow, SpinDelayFlow, ) from pages import StatusPage, ShowQRPage @@ -355,32 +371,32 @@ def developer_menu(): from foundation import ur return [ - {'icon': lv.ICON_BATTERY, 'label': 'Battery', 'page': BatteryPage}, - {'icon': lv.ICON_ERASE, 'label': 'Factory Reset', + {'icon': 'ICON_BATTERY', 'label': 'Battery', 'page': BatteryPage}, + {'icon': 'ICON_ERASE', 'label': 'Factory Reset', 'flow': DeveloperFunctionsFlow, 'args': {'fn_name': 'factory_reset'}}, - {'icon': lv.ICON_RETRY, 'label': 'Spin!!!', 'flow': SpinDelayFlow, 'args': {'delay_ms': 10000}}, - {'icon': lv.ICON_SETTINGS, 'label': 'Dump Settings', + {'icon': 'ICON_RETRY', 'label': 'Spin!!!', 'flow': SpinDelayFlow, 'args': {'delay_ms': 10000}}, + {'icon': 'ICON_SETTINGS', 'label': 'Dump Settings', 'flow': DeveloperFunctionsFlow, 'args': {'fn_name': 'dump_settings'}}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Show Setup QR', 'page': StatusPage, 'args': { + {'icon': 'ICON_SCAN_QR', 'label': 'Show Setup QR', 'page': StatusPage, 'args': { 'text': 'Scan the QR code above with Envoy.', 'icon': lv.LARGE_ICON_SETUP_QR}, 'card_header': {}}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Show Test UR', 'page': ShowQRPage, 'args': { + {'icon': 'ICON_SCAN_QR', 'label': 'Show Test UR', 'page': ShowQRPage, 'args': { 'qr_type': QRType.UR2, 'qr_data': ur.new_bytes('test data' * 10)}}, - {'icon': lv.ICON_SHIELD, 'label': 'Supply Chain', 'flow': ScvFlow}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Login', 'flow': LoginFlow}, - {'icon': lv.ICON_SEED, 'label': 'New Seed', 'flow': NewSeedFlow, 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Set PIN', 'flow': SetInitialPINFlow}, - {'icon': lv.ICON_ERASE, 'label': 'Erase Child Keys', 'flow': DeleteDerivedKeysFlow}, - # {'icon': lv.ICON_SETTINGS, 'label': 'I\'m Busy!', 'page': LongTextPage, + {'icon': 'ICON_SHIELD', 'label': 'Supply Chain', 'flow': ScvFlow}, + {'icon': 'ICON_ONE_KEY', 'label': 'Login', 'flow': LoginFlow}, + {'icon': 'ICON_SEED', 'label': 'New Seed', 'flow': NewSeedFlow, 'args': {'refresh_cards_when_done': True}}, + {'icon': 'ICON_ONE_KEY', 'label': 'Set PIN', 'flow': SetInitialPINFlow}, + {'icon': 'ICON_ERASE', 'label': 'Erase Child Keys', 'flow': DeleteDerivedKeysFlow}, + {'icon': 'ICON_SETTINGS', 'label': 'FCC Test', 'flow': FCCTestFlow}, + # {'icon': 'ICON_SETTINGS', 'label': 'I\'m Busy!', 'page': LongTextPage, # 'args': {'show_busy': True, 'message': 'Signing Transaction...'}}, - # {'icon': lv.ICON_SETTINGS, 'label': 'FCC Test', 'flow': FCCTestFlow}, - # {'icon': lv.ICON_ABOUT, 'label': 'Color Picker', 'page': ColorPickerPage}, - # {'icon': lv.ICON_CHANGE_PIN, 'label': 'Enter PIN', 'page': PINEntryPage, + # {'icon': 'ICON_ABOUT', 'label': 'Color Picker', 'page': ColorPickerPage}, + # {'icon': 'ICON_CHANGE_PIN', 'label': 'Enter PIN', 'page': PINEntryPage, # 'args': {'title': 'Enter Initial PIN'}}, - # {'icon': lv.ICON_FOLDER, 'label': 'Rename Account', 'page': TextInputPage, - # 'args': {'card_header': {'title': 'Rename Account', 'icon': lv.ICON_ABOUT, 'right_text': '!!', + # {'icon': 'ICON_FOLDER', 'label': 'Rename Account', 'page': TextInputPage, + # 'args': {'card_header': {'title': 'Rename Account', 'icon': 'ICON_ABOUT', 'right_text': '!!', # 'bg_color': RED, 'fg_color': FD_BLUE}}}, - # {'icon': lv.ICON_SEED, 'label': 'Enter Seed', 'page': PredictiveTextInputPage}, - # {'icon': lv.ICON_CHANGE_PIN, 'label': 'Enter Backup Code', 'page': BackupCodePage}, + # {'icon': 'ICON_SEED', 'label': 'Enter Seed', 'page': PredictiveTextInputPage}, + # {'icon': 'ICON_CHANGE_PIN', 'label': 'Enter Backup Code', 'page': BackupCodePage}, ] else: return [] @@ -395,11 +411,11 @@ def settings_menu(): from utils import is_logged_in, is_dev_build return [ - {'icon': lv.ICON_DEVICE, 'label': 'Device', 'submenu': device_menu}, - {'icon': lv.ICON_BACKUP, 'label': 'Backup', 'submenu': backup_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_FIRMWARE, 'label': 'Firmware', 'submenu': update_menu}, - {'icon': lv.ICON_BITCOIN, 'label': 'Bitcoin', 'submenu': bitcoin_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_ADVANCED, 'label': 'Advanced', 'submenu': advanced_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_EXTENSIONS, 'label': 'Extensions', 'submenu': extensions_menu}, - {'icon': lv.ICON_ADVANCED, 'label': 'Developer', 'submenu': developer_menu, 'is_visible': is_dev_build} + {'icon': 'ICON_DEVICE', 'label': 'Device', 'submenu': device_menu}, + {'icon': 'ICON_BACKUP', 'label': 'Backup', 'submenu': backup_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_FIRMWARE', 'label': 'Firmware', 'submenu': update_menu}, + {'icon': 'ICON_BITCOIN', 'label': 'Bitcoin', 'submenu': bitcoin_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_ADVANCED', 'label': 'Advanced', 'submenu': advanced_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_EXTENSIONS', 'label': 'Extensions', 'submenu': extensions_menu}, + {'icon': 'ICON_ADVANCED', 'label': 'Developer', 'submenu': developer_menu, 'is_visible': is_dev_build} ] diff --git a/ports/stm32/boards/Passport/modules/microns/__init__.py b/ports/stm32/boards/Passport/modules/microns/__init__.py index 217d6e758..402afd39d 100644 --- a/ports/stm32/boards/Passport/modules/microns/__init__.py +++ b/ports/stm32/boards/Passport/modules/microns/__init__.py @@ -36,6 +36,14 @@ def Retry(color=FD_BLUE): return IconButton(icon=lv.ICON_RETRY, color=color) +def MicroSD(color=FD_BLUE): + return IconButton(icon=lv.ICON_MICROSD, color=color) + + +def ScanQR(color=FD_BLUE): + return IconButton(icon=lv.ICON_SCAN_QR, color=color) + + def PageHome(color=MICRON_GREY): return Icon(icon=lv.ICON_PAGE_HOME, color=color) diff --git a/ports/stm32/boards/Passport/modules/pages/__init__.py b/ports/stm32/boards/Passport/modules/pages/__init__.py index 10a6f3fab..aa9936ee2 100644 --- a/ports/stm32/boards/Passport/modules/pages/__init__.py +++ b/ports/stm32/boards/Passport/modules/pages/__init__.py @@ -23,6 +23,9 @@ from .file_picker_page import * from .info_page import * from .insert_microsd_page import * +from .long_error_page import * +from .long_question_page import * +from .long_success_page import * from .menu_page import * from .multisig_policy_setting_page import * from .pin_entry_page import * diff --git a/ports/stm32/boards/Passport/modules/pages/chooser_page.py b/ports/stm32/boards/Passport/modules/pages/chooser_page.py index b12277623..8be334cd5 100644 --- a/ports/stm32/boards/Passport/modules/pages/chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/chooser_page.py @@ -6,7 +6,7 @@ import lvgl as lv import microns -from styles.colors import CHOOSER_ICON +from styles.colors import CHOOSER_ICON, SCROLLBAR_BG_COLOR from styles import Stylize from pages import Page import common @@ -22,10 +22,14 @@ class ChooserPage(Page): def __init__( self, card_header=None, statusbar=None, options=[], initial_value=None, on_change=None, scroll_fix=False, - icon=None, icon_color=CHOOSER_ICON, text=None, center=False, item_icon=lv.ICON_SMALL_CHECKMARK, - left_micron=microns.Cancel, right_micron=microns.Checkmark): + icon=None, icon_color=CHOOSER_ICON, text=None, center=False, item_icon='ICON_SMALL_CHECKMARK', + left_micron=None, right_micron=None): from views import ListItem, View + import passport + + left_micron = left_micron or microns.Cancel + right_micron = right_micron or microns.Checkmark super().__init__( card_header=card_header, @@ -63,7 +67,6 @@ def __init__( # Add icon if provided if icon is not None: from views import Icon - import passport self.icon_view = Icon(self.icon) with Stylize(self.icon_view) as default: @@ -93,6 +96,8 @@ def __init__( # Adjust scrollbar position with Stylize(self.scroll_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) with Stylize(self.scroll_container) as default: default.flex_fill() diff --git a/ports/stm32/boards/Passport/modules/pages/file_picker_page.py b/ports/stm32/boards/Passport/modules/pages/file_picker_page.py index 39fc7a90d..e81113083 100644 --- a/ports/stm32/boards/Passport/modules/pages/file_picker_page.py +++ b/ports/stm32/boards/Passport/modules/pages/file_picker_page.py @@ -6,7 +6,7 @@ import lvgl as lv import microns -from styles.colors import TEXT_GREY +from styles.colors import TEXT_GREY, SCROLLBAR_BG_COLOR from styles import Stylize from pages import Page from views import FileItem, View @@ -50,6 +50,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self.scroll_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) # Add the file items to the scroll container num_files = min(MAX_FILE_DISPLAY, len(self.files)) diff --git a/ports/stm32/boards/Passport/modules/pages/long_error_page.py b/ports/stm32/boards/Passport/modules/pages/long_error_page.py new file mode 100644 index 000000000..f431d8593 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_error_page.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_error_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import COPPER +import microns + + +class LongErrorPage(LongTextPage): + def __init__( + self, + text=None, + card_header=None, + statusbar=None, + left_micron=None, + right_micron=microns.Checkmark): + super().__init__( + text=text, + card_header=card_header, + statusbar=statusbar, + centered=True, + icon=lv.LARGE_ICON_ERROR, + icon_color=COPPER, + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/pages/long_question_page.py b/ports/stm32/boards/Passport/modules/pages/long_question_page.py new file mode 100644 index 000000000..136d2e730 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_question_page.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_question_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import DEFAULT_LARGE_ICON_COLOR +import microns + + +class LongQuestionPage(LongTextPage): + def __init__( + self, + text=None, + icon=lv.LARGE_ICON_QUESTION, + icon_color=DEFAULT_LARGE_ICON_COLOR, + card_header=None, + statusbar=None, + left_micron=microns.Cancel, + right_micron=microns.Checkmark + ): + super().__init__( + text=text, + icon=icon, + icon_color=icon_color, + card_header=card_header, + statusbar=statusbar, + centered=True, + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/pages/long_success_page.py b/ports/stm32/boards/Passport/modules/pages/long_success_page.py new file mode 100644 index 000000000..9e30c7623 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_success_page.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_success_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import DEFAULT_LARGE_ICON_COLOR +import microns + + +class LongSuccessPage(LongTextPage): + def __init__( + self, + text=None, + card_header=None, + statusbar=None, + left_micron=None, + right_micron=microns.Checkmark): + super().__init__( + text=text, + card_header=card_header, + statusbar=statusbar, + icon=lv.LARGE_ICON_SUCCESS, + icon_color=DEFAULT_LARGE_ICON_COLOR, + centered=True, + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/pages/menu_page.py b/ports/stm32/boards/Passport/modules/pages/menu_page.py index f805fc741..f04431ee6 100644 --- a/ports/stm32/boards/Passport/modules/pages/menu_page.py +++ b/ports/stm32/boards/Passport/modules/pages/menu_page.py @@ -6,10 +6,12 @@ import lvgl as lv from styles import Stylize +from styles.colors import SCROLLBAR_BG_COLOR from pages import Page from views import MenuItem import common import microns +import passport class MenuPage(Page): @@ -39,6 +41,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) # Set non-style props self.set_width(lv.pct(100)) diff --git a/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py b/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py index 54f64e4e9..88df83ad0 100644 --- a/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py +++ b/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py @@ -98,7 +98,7 @@ def show_brick_warning(self): message = 'This is your FINAL attempt before Passport is permanently disabled.' else: message = '{} attempts left\nuntil Passport is permanently disabled.'.format(pa.attempts_left) - self.update_message(show_security_words=False, title='WARNING', icon=lv.ICON_WARNING, + self.update_message(show_security_words=False, title='WARNING', icon='ICON_WARNING', message=message, color=COPPER) self.brick_warning_shown = True diff --git a/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py b/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py index 609cd8122..30c363d91 100644 --- a/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py +++ b/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py @@ -5,7 +5,7 @@ import lvgl as lv -from styles.colors import BLACK +from styles.colors import BLACK, SCROLLBAR_BG_COLOR from pages import Page from utils import InputMode, set_list from views import TextInput, Label, View, ListItem, TextInput @@ -13,6 +13,7 @@ from keys import KEY_0, KEY_9 import microns from predictive_utils import get_words_matching_prefix, word_to_keypad_numbers +import passport class PredictiveTextInputPage(Page): @@ -73,6 +74,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self.predictions_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.add_child(self.predictions_container) diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 0c5c35255..14c2a76c0 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -26,7 +26,9 @@ def __init__(self, card_header=None, statusbar=None, left_micron=microns.Back, - right_micron=None): + right_micron=None, + qr_type=None, + max_frames=None): super().__init__(flex_flow=None, card_header=card_header, statusbar=statusbar, @@ -36,7 +38,9 @@ def __init__(self, self.prev_card_header = None self.timer = None - self.camera = CameraQRScanner() + self.camera = CameraQRScanner(qr_type) + self.qr_type = qr_type + self.max_frames = max_frames # TODO: # lv.pct(100) just makes the widget inside the camera view to return @@ -105,6 +109,13 @@ def update(self): self.camera.update() self.progress_label.set_text(progress_text(self.camera.estimated_percent_complete())) + + num_frames = self.camera.num_frames() + if self.max_frames is not None and num_frames > self.max_frames: + self.set_result(QRScanResult(num_frames=num_frames, + max_frames=self.max_frames)) + return + if self.camera.is_complete(): data = self.camera.qr_decoder.decode() qr_type = self.camera.qr_decoder.qr_type() @@ -115,12 +126,12 @@ def update(self): # Just return None. def left_action(self, is_pressed): - if not is_pressed: + if not is_pressed and self.left_micron: self.set_result(None) # Either the user goes back or the scan finishes def right_action(self, is_pressed): - if not is_pressed: + if not is_pressed and self.right_micron: self.set_result(None) @@ -132,10 +143,15 @@ class QRScanResult: and between a cancelled result (`None` returned by ScanQRPage). """ - def __init__(self, data=None, error=None, qr_type=None): + def __init__(self, data=None, error=None, qr_type=None, num_frames=None, max_frames=None): self.data = data self.error = error self.qr_type = qr_type + self.num_frames = num_frames + self.max_frames = max_frames def is_failure(self): return self.error is not None + + def is_oversized(self): + return self.max_frames is not None and self.num_frames > self.max_frames diff --git a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py index 1f9707938..d15ba30ac 100644 --- a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py +++ b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py @@ -8,9 +8,10 @@ from styles.style import Stylize from views import View, Label import microns -from styles.colors import HIGHLIGHT_TEXT_HEX, TEXT_GREY +from styles.colors import HIGHLIGHT_TEXT_HEX, TEXT_GREY, SCROLLBAR_BG_COLOR from micropython import const import common +import passport _NUM_COLUMNS = const(2) @@ -28,6 +29,7 @@ def __init__( self.page_idx = 0 self.prev_card_descs = None self.prev_card_idx = None + self.left_micron = left_micron if len(self.words) == 24: self.num_pages = 2 @@ -62,6 +64,8 @@ def __init__( with Stylize(self, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.update() @@ -137,13 +141,13 @@ def update(self): # Update microns if self.num_pages > 1: if self.page_idx == 0: - common.ui.set_left_micron(None) + common.ui.set_left_micron(self.left_micron) common.ui.set_right_micron(microns.Forward) else: common.ui.set_left_micron(microns.Back) common.ui.set_right_micron(microns.Checkmark) else: - common.ui.set_left_micron(None) + common.ui.set_left_micron(self.left_micron) common.ui.set_right_micron(microns.Checkmark) def attach(self, group): @@ -175,6 +179,8 @@ def left_action(self, is_pressed): # Go back a page self.page_idx -= 1 self.update() + else: + self.set_result(False) def right_action(self, is_pressed): if not is_pressed: diff --git a/ports/stm32/boards/Passport/modules/pages/shield_page.py b/ports/stm32/boards/Passport/modules/pages/shield_page.py index dda274925..4024203c6 100644 --- a/ports/stm32/boards/Passport/modules/pages/shield_page.py +++ b/ports/stm32/boards/Passport/modules/pages/shield_page.py @@ -14,10 +14,10 @@ def __init__( self, text=None, centered=True, - card_header=None, + card_header={'title': 'Security Check'}, statusbar=None, - left_micron=microns.Cancel, - right_micron=microns.Checkmark): + left_micron=microns.Back, + right_micron=microns.Forward): super().__init__( text=text, icon=lv.LARGE_ICON_SHIELD, diff --git a/ports/stm32/boards/Passport/modules/pages/status_page.py b/ports/stm32/boards/Passport/modules/pages/status_page.py index 56657553e..21bf24d54 100644 --- a/ports/stm32/boards/Passport/modules/pages/status_page.py +++ b/ports/stm32/boards/Passport/modules/pages/status_page.py @@ -7,7 +7,7 @@ from styles.style import Stylize from views import Arc, Label, View, Icon, Spinner from pages import Page -from styles.colors import DEFAULT_SPINNER, TEXT_GREY +from styles.colors import DEFAULT_SPINNER, TEXT_GREY, SCROLLBAR_BG_COLOR import microns import common import passport @@ -53,6 +53,8 @@ def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, p with Stylize(self.container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.update() @@ -160,7 +162,7 @@ def detach(self): super().detach() def right_action(self, is_pressed): - if self.interactive: + if self.interactive and self.right_micron: if not is_pressed: if self.is_list_mode and self.page_idx < len(self.text) - 1: self.page_idx += 1 @@ -169,7 +171,7 @@ def right_action(self, is_pressed): self.set_result(True) def left_action(self, is_pressed): - if self.interactive: + if self.interactive and self.left_micron: if not is_pressed: if self.is_list_mode and self.page_idx > 0: self.page_idx -= 1 diff --git a/ports/stm32/boards/Passport/modules/pages/text_input_page.py b/ports/stm32/boards/Passport/modules/pages/text_input_page.py index 062951e63..e5aa55528 100644 --- a/ports/stm32/boards/Passport/modules/pages/text_input_page.py +++ b/ports/stm32/boards/Passport/modules/pages/text_input_page.py @@ -84,6 +84,9 @@ def left_action(self, is_pressed): if self.is_showing_symbols: self.is_showing_symbols = False self.update_symbol_picker() + self.t9.set_mode(self.last_input_mode) + self.synchronize_with_t9() + return self.set_result(None) def attach(self, group): diff --git a/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py b/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py index 30cab5224..3fd06d4dd 100644 --- a/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py @@ -6,10 +6,18 @@ import lvgl as lv from pages import ChooserPage +import microns class YesNoChooserPage(ChooserPage): - def __init__(self, yes_text='Yes', no_text='No', icon=None, text=None, initial_value=True): + def __init__(self, + yes_text='Yes', + no_text='No', + icon=None, + text=None, + initial_value=True, + left_micron=None, + right_micron=None): options = [ {'label': yes_text, 'value': True}, {'label': no_text, 'value': False} @@ -23,4 +31,6 @@ def __init__(self, yes_text='Yes', no_text='No', icon=None, text=None, initial_v text=text, center=True, item_icon=None, - initial_value=options[0].get('value')) + initial_value=options[0].get('value'), + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/psbt.py b/ports/stm32/boards/Passport/modules/psbt.py index 5fa028242..f0c3a5fa0 100644 --- a/ports/stm32/boards/Passport/modules/psbt.py +++ b/ports/stm32/boards/Passport/modules/psbt.py @@ -1397,142 +1397,6 @@ def wr(*a): outp.serialize(out_fd, idx) out_fd.write(b'\0') - # def sign_it(self): - # # txn is approved. sign all inputs we can sign. add signatures - # # - hash the txn first - # # - sign all inputs we have the key for - # # - inputs might be p2sh, p2pkh and/or segwit style - # # - save partial inputs somewhere (append?) - # # - update our state with new partial sigs - - # with stash.SensitiveValues() as sv: - # # Double check the change outputs are right. This is slow, but critical because - # # it detects bad actors, not bugs or mistakes. - # # - equivilent check already done for p2sh outputs when we re-built the redeem script - # change_outs = [n for n, o in enumerate(self.outputs) if o.is_change] - # if change_outs: - - # for count, out_idx in enumerate(change_outs): - # # only expecting single case, but be general - - # oup = self.outputs[out_idx] - - # good = 0 - # for pubkey, subpath in oup.subpaths.items(): - # if subpath[0] != self.my_xfp and subpath[0] != swab32(self.my_xfp): - # # for multisig, will be N paths, and exactly one will - # # be our key. For single-signer, should always be my XFP - # continue - - # # derive actual pubkey from private - # skp = keypath_to_str(subpath) - # node = sv.derive_path(skp) - - # # check the pubkey of this BIP32 node - # if pubkey == node.public_key(): - # good += 1 - - # if not good: - # raise FraudulentChangeOutput(out_idx, - # "Deception regarding change output. " - # "BIP32 path doesn't match actual address.") - - # # Sign individual inputs - # sigs = 0 - # success = set() - # for in_idx, txi in self.input_iter(): - # inp = self.inputs[in_idx] - - # if not inp.has_utxo(): - # # maybe they didn't provide the UTXO - # continue - - # if not inp.required_key: - # # we don't know the key for this input - # continue - - # if inp.fully_signed: - # # for multisig, it's possible I need to add another sig - # # but in other cases, no more signatures are possible - # continue - - # txi.scriptSig = inp.scriptSig - # assert txi.scriptSig, "no scriptsig?" - - # if not inp.is_segwit: - # # Hash by serializing/blanking various subparts of the transaction - # digest = self.make_txn_sighash(in_idx, txi, inp.sighash) - # else: - # # Hash the inputs and such in totally new ways, based on BIP-143 - # digest = self.make_txn_segwit_sighash(in_idx, txi, - # inp.amount, inp.scriptCode, inp.sighash) - - # if inp.is_multisig: - # # need to consider a set of possible keys, since xfp may not be unique - # for which_key in inp.required_key: - # # get node required - # skp = keypath_to_str(inp.subpaths[which_key]) - # node = sv.derive_path(skp, register=False) - - # # expensive test, but works... and important - # pu = node.public_key() - # if pu == which_key: - # break - # else: - # raise AssertionError("Input #%d needs pubkey I dont have" % in_idx) - - # else: - # # single pubkey <=> single key - # which_key = inp.required_key - - # assert not inp.added_sig, "already done??" - # assert which_key in inp.subpaths, 'unk key' - - # if inp.subpaths[which_key][0] != self.my_xfp and - # inp.subpaths[which_key][0] != swab32(self.my_xfp): - # # we don't have the key for this subkey - # # (redundant, required_key wouldn't be set) - # continue - - # # get node required - # skp = keypath_to_str(inp.subpaths[which_key]) - # node = sv.derive_path(skp, register=False) - - # # expensive test, but works... and important - # pu = node.public_key() - # assert pu == which_key, "Path (%s) led to wrong pubkey for input #%d" % (skp, in_idx) - - # # The precious private key we need - # pk = node.private_key() - - # # print("privkey %s" % b2a_hex(pk).decode('ascii')) - # # print(" pubkey %s" % b2a_hex(which_key).decode('ascii')) - # # print(" digest %s" % b2a_hex(digest).decode('ascii')) - - # # Do the ACTUAL signature ... finally!!! - # result = trezorcrypto.secp256k1.sign(pk, digest) - - # # private key no longer required - # stash.blank_object(pk) - # stash.blank_object(node) - # del pk, node, pu, skp - - # # print("result %s" % b2a_hex(result).decode('ascii')) - - # # convert signature to DER format - # assert len(result) == 65 - # r = result[1:33] - # s = result[33:65] - - # inp.added_sig = (which_key, ser_sig_der(r, s, inp.sighash)) - - # success.add(in_idx) - - # # memory cleanup - # del result, r, s - - # gc.collect() - def make_txn_sighash(self, replace_idx, replacement, sighash_type): # calculate the hash value for one input of current transaction # - blank all script inputs diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 41de79281..13f983a7d 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -13,6 +13,9 @@ from constants import PSBT_MAX_SIZE +# Seed phrase lengths accepted +SEED_LENGTHS = [12, 24] + # Max PSBT txn we support (896k as PSBT) # - the max on the wire for mainnet is 100k # - but a PSBT might contain a full txn for each input @@ -94,6 +97,14 @@ TRUST_OFFER = const(1) TRUST_PSBT = const(2) +# Default Directories +DIR_BACKUPS = 'backups' +DIR_KEY_MNGR = 'key_manager' +DIR_MULTISIGS = 'multisig_configs' +DIR_WALLET_CONFIGS = 'wallet_configs' +DIR_TRANSACTIONS = 'transactions' +DIR_HEALTH_CHECKS = 'health_checks' + RFC_SIGNATURE_TEMPLATE = '''\ -----BEGIN {blockchain} SIGNED MESSAGE----- {msg} diff --git a/ports/stm32/boards/Passport/modules/styles/colors.py b/ports/stm32/boards/Passport/modules/styles/colors.py index 332c46ef7..e8ba83b9b 100644 --- a/ports/stm32/boards/Passport/modules/styles/colors.py +++ b/ports/stm32/boards/Passport/modules/styles/colors.py @@ -20,7 +20,7 @@ LIGHT_GREY_HEX = 0xDDDDDD MEDIUM_GREY_HEX = 0xA0A0A0 MICRON_GREY_HEX = 0x808080 - TEXT_GREY_HEX = 0x666666 + TEXT_GREY_HEX = 0x6D6D6D DARK_GREY_HEX = 0x626262 CHARCOAL_HEX = 0x262626 RED_HEX = 0xFF0000 @@ -63,6 +63,7 @@ DIGIT_BORDER_COLOR_FOCUSED_HEX = FD_BLUE_HEX PIN_ENTRY_MESSAGE_COLOR_HEX = FD_BLUE_HEX BATTERY_FILL_COLOR_HEX = FD_BLUE_HEX + SCROLLBAR_BG_COLOR_HEX = BLACK_HEX else: # On monochrome, white is white, and everything else is black # Shades of grey @@ -121,6 +122,7 @@ DIGIT_BORDER_COLOR_UNFOCUSED_HEX = BLACK_HEX PIN_ENTRY_MESSAGE_COLOR_HEX = BLACK_HEX BATTERY_FILL_COLOR_HEX = BLACK_HEX + SCROLLBAR_BG_COLOR_HEX = BLACK_HEX WHITE = lv.color_hex(WHITE_HEX) VERY_LIGHT_GREY = lv.color_hex(VERY_LIGHT_GREY_HEX) @@ -176,6 +178,7 @@ DIGIT_BORDER_COLOR_UNFOCUSED = lv.color_hex(DIGIT_BORDER_COLOR_UNFOCUSED_HEX) PIN_ENTRY_MESSAGE_COLOR = lv.color_hex(PIN_ENTRY_MESSAGE_COLOR_HEX) BATTERY_FILL_COLOR = lv.color_hex(BATTERY_FILL_COLOR_HEX) +SCROLLBAR_BG_COLOR = lv.color_hex(SCROLLBAR_BG_COLOR_HEX) # Account Colors if passport.IS_SIMULATOR: diff --git a/ports/stm32/boards/Passport/modules/tasks/__init__.py b/ports/stm32/boards/Passport/modules/tasks/__init__.py index 7156338db..630a54521 100644 --- a/ports/stm32/boards/Passport/modules/tasks/__init__.py +++ b/ports/stm32/boards/Passport/modules/tasks/__init__.py @@ -26,7 +26,6 @@ from .double_check_psbt_change_task import double_check_psbt_change_task from .erase_passport_task import erase_passport_task from .format_microsd_task import format_microsd_task -# from .fcc_copy_files_task import fcc_copy_files_task from .generate_addresses_task import generate_addresses_task from .get_security_words_task import get_security_words_task from .get_seed_words_task import get_seed_words_task diff --git a/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py b/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py index 0dfc03c2a..67dd0bc4f 100644 --- a/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py @@ -23,4 +23,4 @@ async def bip85_seed_task(on_done, num_words, index): node = sv.derive_path(path) entropy = hmac(512, 'bip-entropy-from-k', node.private_key()).digest() seed = entropy[0:width] - await on_done(seed, None) + await on_done({'priv': seed}, None) diff --git a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py index 218ce7980..971fa4c96 100644 --- a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py @@ -6,11 +6,13 @@ async def nostr_key_task(on_done, index): import stash - import tcc + from utils import nostr_pubkey_from_pk, nostr_nip19_from_key path = "m/44'/1237'/{}'/0/0".format(index) with stash.SensitiveValues() as sv: node = sv.derive_path(path) key = node.private_key() - key = tcc.codecs.bech32_plain_encode("nsec", key) - await on_done(key, None) + pub = nostr_pubkey_from_pk(key) + nsec = nostr_nip19_from_key(key, "nsec") + npub = nostr_nip19_from_key(pub, "npub") + await on_done({'priv': nsec, 'npub': npub, 'pk': key, 'pub': pub}, None) diff --git a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py index b0b2c0f40..abb1587f6 100644 --- a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py @@ -7,12 +7,18 @@ from files import CardSlot, CardMissingError -async def read_file_task(on_done, file_path): +def default_read_fn(fd): + return fd.read() + + +async def read_file_task(on_done, file_path, binary=True, read_fn=None): ''' NOTE: Assumes that that path above the leaf filename already exists.''' + mode = 'b' if binary else '' + read_fn = read_fn or default_read_fn try: with CardSlot() as _card: - with open(file_path, 'rb') as fd: - data = fd.read() + with open(file_path, 'r' + mode) as fd: + data = read_fn(fd) await on_done(data, None) except CardMissingError: diff --git a/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py b/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py index 73ce63f29..f2a6afc10 100644 --- a/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py @@ -123,5 +123,8 @@ async def restore_backup_task(on_done, decryption_password, backup_file_path): settings.set(k[8:], vals[k]) + # This would be true in the old backup, but false for this new device + settings.set('backup_quiz', False) + # Success! await on_done(None) diff --git a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py index 80287b30b..6f06e815b 100644 --- a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py @@ -16,18 +16,23 @@ async def save_seed_task(on_done, seed_bits): from common import pa import stash - secret = SecretStash.encode(seed_bits=seed_bits) + try: + secret = SecretStash.encode(seed_bits=seed_bits) - pa.change(new_secret=secret) + pa.change(new_secret=secret) - # Recapture XFP, etc. for new secret - await pa.new_main_secret(secret) + # Recapture XFP, etc. for new secret + await pa.new_main_secret(secret) - # Check and reload secret - pa.reset() - pa.login() + # Check and reload secret + pa.reset() + pa.login() - with stash.SensitiveValues() as sv: - sv.capture_xpub(save=True) + with stash.SensitiveValues() as sv: + sv.capture_xpub(save=True) + + except Exception as e: + await on_done(False) + return await on_done(None) diff --git a/ports/stm32/boards/Passport/modules/ui/ui.py b/ports/stm32/boards/Passport/modules/ui/ui.py index 223888cdd..b5bbc9008 100644 --- a/ports/stm32/boards/Passport/modules/ui/ui.py +++ b/ports/stm32/boards/Passport/modules/ui/ui.py @@ -149,7 +149,7 @@ def create_single_card(self, flow, card=None, args=None, add_settings=False): card = { 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'PASSPORT', 'icon': lv.ICON_HAMBURGER, 'fg_color': WHITE}, + 'statusbar': {'title': 'PASSPORT', 'icon': 'ICON_HAMBURGER', 'fg_color': WHITE}, 'page_micron': microns.PageDot, 'bg_color': TEXT_GREY, 'flow': flow @@ -182,7 +182,7 @@ def make_settings_card(self): return { 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'SETTINGS', 'icon': lv.ICON_HAMBURGER, 'fg_color': WHITE}, + 'statusbar': {'title': 'SETTINGS', 'icon': 'ICON_HAMBURGER', 'fg_color': WHITE}, 'page_micron': microns.PageHome, 'bg_color': TEXT_GREY, 'flow': MenuFlow, @@ -244,10 +244,10 @@ def update_cards( # print('account[{}]={}'.format(account, i)) account_card = { - 'right_icon': lv.ICON_BITCOIN, + 'right_icon': 'ICON_BITCOIN', 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'ACCOUNT', 'icon': lv.ICON_FOLDER, 'fg_color': get_account_fg(account)}, + 'statusbar': {'title': 'ACCOUNT', 'icon': 'ICON_FOLDER', 'fg_color': get_account_fg(account)}, 'title': account.get('name'), 'page_micron': microns.PageDot, 'bg_color': get_account_bg(account), @@ -256,7 +256,7 @@ def update_cards( 'account': account } if len(stash.bip39_passphrase) > 0: - account_card['icon'] = lv.ICON_PASSPHRASE + account_card['icon'] = 'ICON_PASSPHRASE' card_descs.append(account_card) @@ -265,13 +265,13 @@ def update_cards( for extension in supported_extensions: if common.settings.get('ext.{}.enabled'.format(extension['name']), False): if len(stash.bip39_passphrase) > 0: - extension['card']['icon'] = lv.ICON_PASSPHRASE + extension['card']['icon'] = 'ICON_PASSPHRASE' else: extension['card']['icon'] = None card_descs.append(extension['card']) more_card = { - 'statusbar': {'title': 'MORE', 'icon': lv.ICON_ADD_ACCOUNT, 'fg_color': WHITE}, + 'statusbar': {'title': 'MORE', 'icon': 'ICON_ADD_ACCOUNT', 'fg_color': WHITE}, 'page_micron': microns.PagePlus, 'bg_color': DARK_GREY, 'flow': MenuFlow, diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 159833f18..4afd1391e 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -12,6 +12,7 @@ import lvgl as lv from constants import NUM_BACKUP_CODE_SECTIONS, NUM_DIGITS_PER_BACKUP_CODE_SECTION +from public_constants import DIR_BACKUPS from files import CardSlot from styles.colors import DEFAULT_LARGE_ICON_COLOR import ustruct @@ -173,7 +174,7 @@ def sd_card_cb(): sd_card_change = False saved = save_error_log(msg, filename) if saved: - common.ui.set_card_header(title='Saved to microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Saved to microSD', icon='ICON_MICROSD') await sleep_ms(100) @@ -213,7 +214,7 @@ def handle_fatal_error(exc): # Switch immediately to a new card to show the error fatal_error_card = { - 'statusbar': {'title': 'FATAL ERROR', 'icon': lv.ICON_INFO}, + 'statusbar': {'title': 'FATAL ERROR', 'icon': 'ICON_INFO'}, 'page_micron': microns.PageDot, 'bg_color': BLACK, 'flow': PageFlow, @@ -223,9 +224,9 @@ def handle_fatal_error(exc): common.ui.set_cards([fatal_error_card]) if saved: - common.ui.set_card_header(title='Saved to microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Saved to microSD', icon='ICON_MICROSD') else: - common.ui.set_card_header(title='Insert microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Insert microSD', icon='ICON_MICROSD') loop = get_event_loop() _fatal_card_task = loop.create_task(card_task(fatal_error_card)) @@ -1017,7 +1018,11 @@ def format_btc_address(address, addr_type): def get_backups_folder_path(): - return '{}/backups'.format(CardSlot.get_sd_root()) + return get_folder_path() + + +def get_folder_path(folder=DIR_BACKUPS): + return '{}/{}'.format(CardSlot.get_sd_root(), folder) def split_to_lines(s, width): @@ -1325,4 +1330,88 @@ def get_words_from_seed(seed): except Exception as e: return (None, '{}'.format(e)) + +def nostr_pubkey_from_pk(pk): + from trezorcrypto import secp256k1 + return secp256k1.publickey(pk, True)[1:] + + +def nostr_nip19_from_key(key, key_type): # generate nsec/npub + import tcc + return tcc.codecs.bech32_plain_encode(key_type, key) + + +def nostr_sign(key, message): + from foundation import secp256k1 + return secp256k1.schnorr_sign(message, key) + + +months = { + 1: 'January', + 2: 'February', + 3: 'March', + 4: 'April', + 5: 'May', + 6: 'June', + 7: 'July', + 8: 'Aug', + 9: 'September', + 10: 'October', + 11: 'November', + 12: 'December', +} + + +def timestamp_to_str(time): + import utime + + time_tup = utime.gmtime(time) + return "{} {}, {}\n{}:{:02d}".format(months[time_tup[1]], # Month + time_tup[2], # Day + time_tup[0], # Year + time_tup[3], # Hour + time_tup[4], # Minute + ) + + +# This is a flow function, so it needs to be async +async def show_card_missing(flow): + from pages import InsertMicroSDPage + + # This makes the return type consistent with the caller + if hasattr(flow, "return_bool") and flow.return_bool: + result = False + else: + result = None + + if hasattr(flow, "automatic") and flow.automatic: + flow.set_result(result) + return + + retry = await InsertMicroSDPage().show() + if retry: + flow.back() + else: + flow.set_result(result) + + +# This assumes the function passed in is async +def bind(instance, func, as_name=None): + if as_name is None: + as_name = func.__name__ + + async def method(*args, **kwargs): + return await func(instance, *args, **kwargs) + + setattr(instance, as_name, method) + return method + + +def derive_icon(icon): + if isinstance(icon, str): + return getattr(lv, icon) + else: + return icon + + # EOF diff --git a/ports/stm32/boards/Passport/modules/views/battery_indicator.py b/ports/stm32/boards/Passport/modules/views/battery_indicator.py index 561a2d4e9..838dbca0d 100644 --- a/ports/stm32/boards/Passport/modules/views/battery_indicator.py +++ b/ports/stm32/boards/Passport/modules/views/battery_indicator.py @@ -23,7 +23,7 @@ def __init__(self, outline_color=WHITE): self.is_charging = False self.outline_color = outline_color - self.icon = Icon(lv.ICON_BATTERY, color=WHITE) + self.icon = Icon('ICON_BATTERY', color=WHITE) self.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) with Stylize(self.icon) as default: default.align(lv.ALIGN.CENTER) @@ -58,9 +58,9 @@ def set_percent(self, percent): def set_is_charging(self, is_charging): self.is_charging = is_charging if self.is_charging: - self.icon.set_icon(lv.ICON_BATTERY_CHARGING) + self.icon.set_icon('ICON_BATTERY_CHARGING') else: - self.icon.set_icon(lv.ICON_BATTERY) + self.icon.set_icon('ICON_BATTERY') def set_outline_color(self, outline_color): self.outline_color = outline_color diff --git a/ports/stm32/boards/Passport/modules/views/camera.py b/ports/stm32/boards/Passport/modules/views/camera.py index fd6681cc9..7b2214f7d 100644 --- a/ports/stm32/boards/Passport/modules/views/camera.py +++ b/ports/stm32/boards/Passport/modules/views/camera.py @@ -11,7 +11,7 @@ from views import View from styles import Stylize from styles.colors import WHITE -from data_codecs.qr_factory import make_qr_decoder_from_data +from data_codecs.qr_factory import make_qr_decoder_from_data, make_qr_decoder class Camera(View): @@ -143,9 +143,10 @@ def framebuffer(self): class CameraQRScanner(Camera): """Camera QR code scanner and decoder""" - def __init__(self): + def __init__(self, qr_type=None): super().__init__() self.qr_decoder = None + self.qr_type = qr_type qr.init(self.HOR_RES, self.VER_RES) def hook(self): @@ -175,7 +176,10 @@ def update(self): return if self.qr_decoder is None: - self.qr_decoder = make_qr_decoder_from_data(data) + if self.qr_type is not None: + self.qr_decoder = make_qr_decoder(self.qr_type) + else: + self.qr_decoder = make_qr_decoder_from_data(data) self.qr_decoder.add_data(data) @@ -193,3 +197,8 @@ def is_complete(self): if self.qr_decoder is not None: return self.qr_decoder.is_complete() return False + + def num_frames(self): + if self.qr_decoder is not None: + return self.qr_decoder.num_frames() or 0 + return 0 diff --git a/ports/stm32/boards/Passport/modules/views/file_item.py b/ports/stm32/boards/Passport/modules/views/file_item.py index 0e0fe4fc9..3317e918e 100644 --- a/ports/stm32/boards/Passport/modules/views/file_item.py +++ b/ports/stm32/boards/Passport/modules/views/file_item.py @@ -38,7 +38,7 @@ def __init__(self, filename='', is_folder=False): focus.img_recolor(FOCUSED_LIST_ITEM_TEXT) # Icon - self.icon_view = Icon(icon=lv.ICON_FOLDER if self.is_folder else lv.ICON_FILE) + self.icon_view = Icon(icon='ICON_FOLDER' if self.is_folder else 'ICON_FILE') # Filename self.filename_view = Label(text=self.filename) diff --git a/ports/stm32/boards/Passport/modules/views/icon.py b/ports/stm32/boards/Passport/modules/views/icon.py index 685b5a785..da5e6f445 100644 --- a/ports/stm32/boards/Passport/modules/views/icon.py +++ b/ports/stm32/boards/Passport/modules/views/icon.py @@ -10,8 +10,10 @@ class Icon(View): def __init__(self, icon, color=None, opa=None): + from utils import derive_icon + super().__init__() - self.icon = icon + self.icon = derive_icon(icon) self.color = color self.opa = opa @@ -22,7 +24,10 @@ def __init__(self, icon, color=None, opa=None): default.opa(self.opa) def set_icon(self, icon): - self.icon = icon + if isinstance(icon, str): + self.icon = getattr(lv, icon) + else: + self.icon = icon self.update() def set_color(self, color=None, opa=None): diff --git a/ports/stm32/boards/Passport/modules/views/list_item.py b/ports/stm32/boards/Passport/modules/views/list_item.py index f73e8db09..3947b7c30 100644 --- a/ports/stm32/boards/Passport/modules/views/list_item.py +++ b/ports/stm32/boards/Passport/modules/views/list_item.py @@ -13,10 +13,11 @@ class ListItem(View): - def __init__(self, label='', is_selected=False, icon=lv.ICON_SMALL_CHECKMARK, center=False): + def __init__(self, label='', is_selected=False, icon='ICON_SMALL_CHECKMARK', center=False): + from utils import derive_icon super().__init__(flex_flow=lv.FLEX_FLOW.ROW) - self.icon = icon + self.icon = derive_icon(icon) self.label = label self.is_selected = is_selected self.center = center diff --git a/ports/stm32/boards/Passport/modules/views/micron_bar.py b/ports/stm32/boards/Passport/modules/views/micron_bar.py index 49001b9ae..8cb91073d 100644 --- a/ports/stm32/boards/Passport/modules/views/micron_bar.py +++ b/ports/stm32/boards/Passport/modules/views/micron_bar.py @@ -117,7 +117,7 @@ def update_pagination_dots(self): page_dot.add_child(icon) if i == self.active_card_idx: - indicator = Icon(icon=lv.ICON_PAGE_INDICATOR, color=WHITE) + indicator = Icon(icon='ICON_PAGE_INDICATOR', color=WHITE) page_dot.add_child(indicator) # print('page_dot={}'.format(page_dot)) diff --git a/ports/stm32/boards/Passport/modules/views/pin_input.py b/ports/stm32/boards/Passport/modules/views/pin_input.py index a135b34db..f2511d3d0 100644 --- a/ports/stm32/boards/Passport/modules/views/pin_input.py +++ b/ports/stm32/boards/Passport/modules/views/pin_input.py @@ -6,7 +6,7 @@ import lvgl as lv from styles import Stylize -from styles.colors import TEXT_GREY, TEXT_INPUT_BG, TEXT_INPUT_CURSOR, TEXT_INPUT_TEXT, TEXT_INPUT_CURSOR +from styles.colors import TEXT_INPUT_ICON, TEXT_INPUT_BG, TEXT_INPUT_CURSOR, TEXT_INPUT_TEXT, TEXT_INPUT_CURSOR from views import View from utils import InputMode from views import Label, Icon @@ -38,7 +38,7 @@ def __init__(self, pin='', input_mode=InputMode.UPPER_ALPHA): default.pad(left=2) default.flex_align(main=lv.FLEX_ALIGN.CENTER, cross=lv.FLEX_ALIGN.CENTER, track=lv.FLEX_ALIGN.CENTER) - self.mode_icon = Icon(InputMode.get_icon(self.input_mode), color=TEXT_GREY) + self.mode_icon = Icon(InputMode.get_icon(self.input_mode), color=TEXT_INPUT_ICON) self.mode_view.add_child(self.mode_icon) self.pin_container = View(flex_flow=lv.FLEX_FLOW.ROW) @@ -63,15 +63,13 @@ def update_pin(self): num_chars = len(self.pin) for i in range(num_chars): - # ch = self.pin[i] - # item = Label(text=ch, color=TEXT_GREY) ch = self.pin[i] if not self.hidden_mode: item = Label(text=ch, color=TEXT_INPUT_TEXT) elif i == num_chars - 1 and self.show_last_char: item = Label(text=ch, color=TEXT_INPUT_TEXT) else: - item = Icon(lv.ICON_PAGE_DOT, color=TEXT_INPUT_TEXT) + item = Icon('ICON_PAGE_DOT', color=TEXT_INPUT_TEXT) self.pin_container.add_child(item) # Finally, draw a "cursor", which is always at the end diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 7cfd6aa2e..47c0cf595 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -19,18 +19,16 @@ def __init__(self, title='', icon=None, fg_color=WHITE): self.title = title self.icon = icon self.fg_color = fg_color + self.bg_color = BLACK self.title_view = None self.icon_view = None with Stylize(self) as default: - # if not passport.IS_COLOR: - # default.bg_color(BLACK) - if passport.IS_COLOR: top_pad = 0 else: - top_pad = 2 + top_pad = 8 default.pad(top=top_pad, bottom=0, left=10, right=10) default.pad_col(2) @@ -48,15 +46,18 @@ def __init__(self, title='', icon=None, fg_color=WHITE): if passport.IS_COLOR: self.add_child(self.battery) else: + battery_bg = Icon(icon='ICON_BATTERY_BACKGROUND', color=self.bg_color) + self.battery_container = View(flex_flow=None) self.battery_container.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) # self.battery_container.set_size(24, 24) with Stylize(self.battery_container) as default: - default.bg_color(BLACK) default.pad(left=2, right=2) default.radius(4) default.align(lv.ALIGN.CENTER) + self.battery_container.add_child(battery_bg) + self.battery.set_pos(1, 1) self.battery_container.add_child(self.battery) self.add_child(self.battery_container) @@ -66,9 +67,15 @@ def update_icon(self): self.remove_child(self.icon_view) if self.icon is None: - icon_view = Icon(icon=lv.ICON_SETTINGS, opa=0) # Transparent placeholder - else: - icon_view = Icon(icon=self.icon, color=self.fg_color) + self.icon = 'ICON_SETTINGS' + + icon_view = Icon(icon=self.icon, color=self.fg_color) + if not passport.IS_COLOR and isinstance(self.icon, str): + background_img = self.icon + '_BACKGROUND' + if hasattr(lv, background_img): + bg_view = Icon(icon=background_img, color=self.bg_color) + else: + bg_view = None if passport.IS_COLOR: self.icon_view = icon_view @@ -76,11 +83,16 @@ def update_icon(self): self.icon_view = View(flex_flow=None) self.icon_view.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) with Stylize(self.icon_view) as default: - default.bg_color(BLACK) + if bg_view is None: + default.bg_color(BLACK) default.pad_all(2) default.radius(4) default.align(lv.ALIGN.CENTER) + if bg_view: + self.icon_view.add_child(bg_view) + icon_view.set_pos(1, 1) + self.icon_view.add_child(icon_view) self.insert_child(0, self.icon_view) diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 359189800..c6bed7a73 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -38,21 +38,12 @@ FROZEN_MANIFEST ?= boards/Passport/manifest.py MICROPY_EXTMOD_DIR = ../../extmod CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/foundation \ - -I$(MICROPY_EXTMOD_DIR)/quirc \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core + -I$(MICROPY_EXTMOD_DIR)/quirc -CFLAGS_MOD += -DBITCOIN_ONLY=1 -DAES_128=1 -DAES_192=1 +LV_CFLAGS += -DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP -DLV_TICK_CUSTOM=1 # settings that apply only to crypto C-lang code -build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += \ - -DUSE_BIP39_CACHE=0 -DBIP32_CACHE_SIZE=0 -DUSE_BIP32_CACHE=0 -DBIP32_CACHE_MAXDEPTH=0 \ - -DRAND_PLATFORM_INDEPENDENT=1 -DUSE_BIP39_GENERATE=0 -DUSE_BIP32_25519_CURVES=0 - -CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core/embed/extmod/modtrezorcrypto -Iboards/$(BOARD)/trezor-firmware/core +build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += -DRAND_PLATFORM_INDEPENDENT=1 # Bootloader CFLAGS CFLAGS_MOD += -DBL_NVROM_BASE=$(BL_NVROM_BASE) @@ -85,13 +76,19 @@ SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ ifeq ($(SCREEN_MODE), MONO) SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ lcd-sharp-ls018b7dh02.c) - CFLAGS += -DSCREEN_MODE_MONO=1 + LV_CFLAGS += -DSCREEN_MODE_MONO=1 + CFLAGS += -DSCREEN_MODE_MONO=1 endif ifeq ($(SCREEN_MODE), COLOR) SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ lcd-st7789.c st7789.c) - CFLAGS += -DSCREEN_MODE_COLOR=1 + LV_CFLAGS += -DSCREEN_MODE_COLOR=1 -DHAS_FUEL_GAUGE=1 + CFLAGS += -DSCREEN_MODE_COLOR=1 -DHAS_FUEL_GAUGE=1 +endif + +ifeq ($(DEV_BUILD),1) + LV_CFLAGS += -DDEV_BUILD endif RUST_TARGET := thumbv7em-none-eabihf diff --git a/ports/stm32/boards/Passport/tools/add-secrets/Makefile b/ports/stm32/boards/Passport/tools/add-secrets/Makefile index 561de890e..bb4fc3ff1 100644 --- a/ports/stm32/boards/Passport/tools/add-secrets/Makefile +++ b/ports/stm32/boards/Passport/tools/add-secrets/Makefile @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: © 2020 Foundation Devices, Inc. # SPDX-License-Identifier: GPL-3.0-or-later -TOP = ../.. - SOURCES = add-secrets.c VPATH = @@ -11,7 +9,6 @@ ARCH ?= x86 CFLAGS = -Wall -fno-strict-aliasing CFLAGS += -fno-omit-frame-pointer -CFLAGS += -I$(TOP)/include LDFLAGS = -Wl,-Map,$(MAP) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 53ab1e150..756f05e9b 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -265,11 +265,6 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) -# secp256k1-zkp -# NOTE: this is done here because the flag from the Unix and STM32 ports -# differ. -CFLAGS += -DSECP256K1_CONTEXT_SIZE=208 -Wno-sign-compare - # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_CXX) $(LIB_SRC_C) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index 30374e1c4..8e72b0aa5 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -42,19 +42,11 @@ MICROPY_PY_JNI = 0 # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 -CFLAGS_MOD += -DBITCOIN_ONLY=1 -DAES_128=1 -DAES_192=1 - MICROPY_EXTMOD_DIR = ../../extmod CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/foundation \ -I$(MICROPY_EXTMOD_DIR)/quirc \ -I$(MICROPY_EXTMOD_DIR)/uasyncio \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core/embed/unix \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/include \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/common/micro-ecc # TODO: Move this the ports/stm32/boards/Passport include files? diff --git a/py/py.mk b/py/py.mk index 6fb46815b..a1f3c7ad2 100644 --- a/py/py.mk +++ b/py/py.mk @@ -54,33 +54,6 @@ SRC_MOD += $(sort $(subst $(TOP)/,,$(shell find $(LVGL_DIR)/src $(LVGL_GENERIC_D GIT_SUBMODULES += lib/lv_bindings - -# secp256k1 -SECP256K1_PATH = extmod/trezor-firmware/vendor/secp256k1-zkp -SECP256K1_DIR = $(TOP)/$(SECP256K1_PATH) -SECP256K1_ECMULT_STATIC_CONTEXT_H = $(SECP256K1_DIR)/src/ecmult_static_context.h -CFLAGS_MOD += -DUSE_NUM_NONE -DUSE_FIELD_INV_BUILTIN \ - -DUSE_FIELD_10X26 -DUSE_SCALAR_8X32 -DUSE_ECMULT_STATIC_PRECOMPUTATION \ - -DUSE_EXTERNAL_DEFAULT_CALLBACKS -DECMULT_GEN_PREC_BITS=4 \ - -DECMULT_WINDOW_SIZE=8 -DENABLE_MODULE_GENERATOR \ - -DENABLE_MODULE_RECOVERY -DENABLE_MODULE_SCHNORRSIG \ - -DENABLE_MODULE_EXTRAKEYS -I$(SECP256K1_DIR)/src -SECP256K1_MPY = $(BUILD)/secp256k1/secp256k1_mpy.c -INC += -I$(SECP256K1_DIR) -I$(SECP256K1_DIR)/include -HOST_CC = gcc -SRC_MOD += $(SECP256K1_PATH)/src/secp256k1.c $(SECP256K1_MPY) - -$(SECP256K1_ECMULT_STATIC_CONTEXT_H): - $(ECHO) "GEN-CONTEXT $@" - $(Q)$(HOST_CC) -O2 -DECMULT_GEN_PREC_BITS=4 -I$(SECP256K1_DIR)/src $(SECP256K1_DIR)/src/gen_context.c -o $(SECP256K1_DIR)/gen_context - $(Q)cd $(SECP256K1_DIR) && ./gen_context - -# NOTE: generates a dummy file in order to have ecmult_static_context.h as a dependency. -$(SECP256K1_MPY): $(SECP256K1_ECMULT_STATIC_CONTEXT_H) - $(ECHO) "GEN $@" - $(Q)mkdir -p $(dir $@) - $(Q)touch $@ - #lodepng LODEPNG_DIR = $(TOP)/lib/lv_bindings/driver/png/lodepng MP_LODEPNG_C = $(TOP)/lib/lv_bindings/driver/png/mp_lodepng.c @@ -104,6 +77,24 @@ $(LODEPNG_C): $(LODEPNG_DIR)/lodepng.cpp $(LODEPNG_DIR)/* SRC_MOD += $(subst $(TOP)/,,$(LODEPNG_C) $(MP_LODEPNG_C) $(LODEPNG_MODULE)) +# trezorcrypto +CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ + -DUSE_KECCAK=0 \ + -DBITCOIN_ONLY=1 \ + -DAES_128=1 \ + -DAES_192=1 \ + -DUSE_BIP39_CACHE=0 \ + -DUSE_BIP39_GENERATE=0 \ + -DUSE_BIP32_CACHE=0 \ + -DBIP32_CACHE_SIZE=0 \ + -DBIP32_CACHE_MAXDEPTH=0 + +INC += -I$(TOP)/extmod/trezor-firmware/crypto \ + -I$(TOP)/extmod/trezor-firmware/crypto/aes \ + -I$(TOP)/extmod/trezor-firmware/crypto/chacha20poly1305 \ + -I$(TOP)/extmod/trezor-firmware/crypto/ed25519-donna \ + -I$(TOP)/extmod/trezor-firmware/core + # External modules written in C. ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate @@ -135,19 +126,11 @@ ifeq ($(SCREEN_MODE),MONO) SRC_MOD += $(sort $(subst $(TOP)/,,$(shell find $(TOP)/ports/stm32/boards/Passport/images/mono -type f -name "*.c"))) endif - ifeq ($(RUST_TARGET),) - UNAME_M ?= $(shell uname -m) - - ifeq ($(UNAME_M),x86_64) - RUST_ARCH ?= x86_64 - else ifeq ($(UNAME_M),arm) - RUST_ARCH ?= arm - else ifeq ($(UNAME_M),arm64) - RUST_ARCH ?= aarch64 - endif - - RUST_TARGET ?= $(RUST_ARCH)-unknown-none + RUST_TARGET ?= $(shell rustc --version --verbose | $(SED) -n 's/host: \(.*\)$$/\1/p') + RUST_FEATURES ?= --features std +else + RUST_FEATURES ?= endif FOUNDATION_RUST ?= $(TOP)/extmod/foundation-rust @@ -163,7 +146,7 @@ LDFLAGS_MOD += -L$(shell dirname $(FOUNDATION_RUST_LIB)) -lfoundation $(FOUNDATION_RUST_LIB): $(FOUNDATION_RUST_SRC) $(ECHO) "CARGO foundation-rust" - @cargo build --manifest-path $(FOUNDATION_RUST)/Cargo.toml --target $(RUST_TARGET) --release + cargo build --manifest-path $(FOUNDATION_RUST)/Cargo.toml --target $(RUST_TARGET) $(RUST_FEATURES) --release # FOUNDATION CHANGE: END @@ -366,30 +349,15 @@ PY_EXTMOD_O_BASENAME = \ extmod/trezor-firmware/crypto/aes/aeskey.o \ extmod/trezor-firmware/crypto/aes/aestab.o \ extmod/trezor-firmware/crypto/aes/aes_modes.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-32bit.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-helpers.o \ - extmod/trezor-firmware/crypto/ed25519-donna/modm-donna-32bit.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-basepoint-table.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-32bit-tables.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-impl-base.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-scalarmult-base.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-keccak.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-sha3.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/chacha20poly1305.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/chacha_merged.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/poly1305-donna.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/rfc7539.o \ extmod/trezor-firmware/crypto/shamir.o \ extmod/trezor-firmware/crypto/groestl.o \ extmod/trezor-firmware/crypto/slip39.o \ + extmod/trezor-firmware/crypto/schnorr.o \ extmod/trezor-firmware/crypto/rand.o \ extmod/trezor-firmware/crypto/rfc6979.o \ extmod/trezor-firmware/crypto/hmac_drbg.o \ - extmod/trezor-firmware/crypto/zkp_bip340.o \ extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.o \ - extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/crc.o \ - extmod/trezor-firmware/core/vendor/trezor-crypto/zkp_context.o + extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/crc.o # prepend the build destination prefix to the py object files PY_CORE_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME)) @@ -415,9 +383,8 @@ endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% -SRC_MOD_QSTR_IGNORE = $(SECP256K1_PATH)/src/secp256k1.c extmod/trezor-firmware/crypto/zkp_bip340.c -SRC_EXTMOD_QSTR_IGNORE = extmod/trezor-firmware/crypto/zkp_bip340.c \ - extmod/trezor-firmware/core/vendor/trezor-crypto/zkp_context.c +SRC_MOD_QSTR_IGNORE = +SRC_EXTMOD_QSTR_IGNORE = SRC_QSTR += $(filter-out $(SRC_MOD_QSTR_IGNORE),$(SRC_MOD)) \ $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) \ $(filter-out $(SRC_EXTMOD_QSTR_IGNORE),$(PY_EXTMOD_O_BASENAME:.o=.c)) diff --git a/simulator/variant/simulator/mpconfigvariant.mk b/simulator/variant/simulator/mpconfigvariant.mk index 60ac1362a..1fdaa7bf2 100644 --- a/simulator/variant/simulator/mpconfigvariant.mk +++ b/simulator/variant/simulator/mpconfigvariant.mk @@ -11,3 +11,5 @@ CFLAGS_MOD += -DBL_FW_HDR_BASE=0 FROZEN_MANIFEST = FROZEN_MPY_DIR = + +export RUSTFLAGS := --cfg sram4