diff --git a/Data/system/fonts/AdwaitaMono.ttf b/Data/system/fonts/AdwaitaMono.ttf new file mode 100644 index 000000000..99e2518ee Binary files /dev/null and b/Data/system/fonts/AdwaitaMono.ttf differ diff --git a/Data/system/fonts/AdwaitaSans.ttf b/Data/system/fonts/AdwaitaSans.ttf new file mode 100644 index 000000000..ecd3a057b Binary files /dev/null and b/Data/system/fonts/AdwaitaSans.ttf differ diff --git a/Data/system/fonts/MaterialSymbolsRounded.codepoints b/Data/system/fonts/MaterialSymbolsRounded.codepoints index 19433809a..39ee896a7 100644 --- a/Data/system/fonts/MaterialSymbolsRounded.codepoints +++ b/Data/system/fonts/MaterialSymbolsRounded.codepoints @@ -53,6 +53,7 @@ network_wifi_1_bar ebe4 network_wifi_2_bar ebd6 network_wifi_3_bar ebe1 note_add e89c +palette e40a power_settings_new f8c7 refresh e5d5 sd_card e623 diff --git a/Data/system/fonts/MaterialSymbolsRounded.ttf b/Data/system/fonts/MaterialSymbolsRounded.ttf index 3be21646d..039d1b3d0 100644 Binary files a/Data/system/fonts/MaterialSymbolsRounded.ttf and b/Data/system/fonts/MaterialSymbolsRounded.ttf differ diff --git a/Documentation/pics/screenshot-AppList.png b/Documentation/pics/screenshot-AppList.png index c5e8d1947..920ef917f 100644 Binary files a/Documentation/pics/screenshot-AppList.png and b/Documentation/pics/screenshot-AppList.png differ diff --git a/Documentation/pics/screenshot-Launcher.png b/Documentation/pics/screenshot-Launcher.png index b5e4bd978..0f4e21adc 100644 Binary files a/Documentation/pics/screenshot-Launcher.png and b/Documentation/pics/screenshot-Launcher.png differ diff --git a/Documentation/pics/screenshot-Settings.png b/Documentation/pics/screenshot-Settings.png index 3809d80f9..a59074a47 100644 Binary files a/Documentation/pics/screenshot-Settings.png and b/Documentation/pics/screenshot-Settings.png differ diff --git a/Modules/binfont-module/include/binfont/generator.h b/Modules/binfont-module/include/binfont/generator.h index f25fc2a64..713d6f210 100644 --- a/Modules/binfont-module/include/binfont/generator.h +++ b/Modules/binfont-module/include/binfont/generator.h @@ -17,7 +17,10 @@ typedef struct BinFontGeneratorConfig { uint16_t size; /** Bits per pixel: 1, 2, 3 or 4 */ uint8_t bpp; - /** Codepoints to include. Codepoints that the TTF doesn't contain are skipped. */ + /** + * Codepoints to include. Codepoints that the TTF doesn't contain are skipped. + * NULL (with codepoint_count 0) includes every codepoint in the TTF's character map. + */ const uint32_t* codepoints; size_t codepoint_count; } BinFontGeneratorConfig; @@ -30,11 +33,23 @@ typedef struct BinFontGeneratorConfig { * @retval ERROR_NONE on success * @retval ERROR_INVALID_ARGUMENT when the configuration is invalid * @retval ERROR_NOT_FOUND when the TTF file can't be read - * @retval ERROR_NOT_SUPPORTED when the TTF file can't be parsed or contains none of the codepoints + * @retval ERROR_NOT_SUPPORTED when the TTF file or its character map can't be parsed, or it contains none of the codepoints * @retval ERROR_OUT_OF_MEMORY when memory allocation failed */ error_t binfont_generate(const BinFontGeneratorConfig* config, uint8_t** out_data, size_t* out_size); +/** + * @brief Lists the codepoints in the character map of a TrueType font. + * @param[in] ttf_path path to a TrueType (.ttf) file + * @param[out] out_codepoints the codepoints, to be released with memory_free() + * @param[out] out_count the number of codepoints + * @retval ERROR_NONE on success + * @retval ERROR_NOT_FOUND when the TTF file can't be read + * @retval ERROR_NOT_SUPPORTED when the TTF file or its character map can't be parsed + * @retval ERROR_OUT_OF_MEMORY when memory allocation failed + */ +error_t binfont_get_ttf_codepoints(const char* ttf_path, uint32_t** out_codepoints, size_t* out_count); + #ifdef __cplusplus } #endif diff --git a/Modules/binfont-module/private/stb_truetype.h b/Modules/binfont-module/private/stb_truetype.h index 90a5c2e2b..1ce33bbe7 100644 --- a/Modules/binfont-module/private/stb_truetype.h +++ b/Modules/binfont-module/private/stb_truetype.h @@ -1,6 +1,9 @@ // stb_truetype.h - v1.26 - public domain // authored from 2009-2021 by Sean Barrett / RAD Game Tools // +// Modified for Tactility: stbtt__hheap_alloc() allocates smaller chunks, so rasterizing works +// with a fragmented heap on devices without PSRAM. +// // ======================================================================= // // NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES @@ -2775,7 +2778,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) return p; } else { if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + int count = (size < 32 ? 100 : size < 128 ? 50 : 10); stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); if (c == NULL) return NULL; diff --git a/Modules/binfont-module/source/generator.cpp b/Modules/binfont-module/source/generator.cpp index c16b0e7e2..176326449 100644 --- a/Modules/binfont-module/source/generator.cpp +++ b/Modules/binfont-module/source/generator.cpp @@ -9,10 +9,29 @@ #include #include +namespace { + +/** Passed to stb_truetype as user data, to detect allocation failures it otherwise ignores */ +struct AllocationState { + bool failed; +}; + +void* stbtt_allocate(size_t size, void* user) { + void* pointer = memory_alloc(size); + if (pointer == nullptr && user != nullptr) { + static_cast(user)->failed = true; + } + return pointer; +} + +} // namespace + #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION -#define STBTT_malloc(size, user) ((void)(user), memory_alloc(size)) +#define STBTT_malloc(size, user) stbtt_allocate(size, user) #define STBTT_free(pointer, user) ((void)(user), memory_free(pointer)) +// stb_truetype skips what it can't allocate, allocation failures are detected via AllocationState +#define STBTT_assert(condition) ((void)0) #include "stb_truetype.h" namespace { @@ -253,15 +272,125 @@ void write_cmap(ByteBuffer& out, const GlyphInfo* glyphs, size_t count) { out.endRecord(record); } -error_t generate(const BinFontGeneratorConfig* config, const stbtt_fontinfo& info, GlyphInfo* glyphs, ByteBuffer& out) { +/** Appends codepoints to a growable array */ +class CodepointList { + uint32_t* data = nullptr; + size_t count = 0; + size_t capacity = 0; + bool failed = false; + +public: + ~CodepointList() { memory_free(data); } + + void addRange(uint32_t first, uint32_t last) { + for (uint32_t codepoint = first; codepoint <= last && !failed; codepoint++) { + if (count == capacity) { + const size_t new_capacity = capacity ? capacity * 2 : 256; + auto* new_data = static_cast(memory_realloc(data, new_capacity * sizeof(uint32_t))); + if (new_data == nullptr) { + failed = true; + return; + } + data = new_data; + capacity = new_capacity; + } + data[count++] = codepoint; + } + } + + const uint32_t* getData() const { return data; } + size_t getCount() const { return count; } + bool hasFailed() const { return failed; } + + uint32_t* release() { + uint32_t* result = data; + data = nullptr; + count = 0; + capacity = 0; + return result; + } +}; + +/** + * Collects the codepoints of the character map that stb_truetype selected (formats 0, 4, 6 and 12). + * @return false when the format is not supported or the table is out of bounds + */ +bool collect_codepoints(const stbtt_fontinfo& info, size_t ttfSize, CodepointList& list) { + stbtt_uint8* data = info.data; + const auto map = static_cast(info.index_map); + auto in_bounds = [ttfSize](size_t offset, size_t size) { return offset <= ttfSize && size <= ttfSize - offset; }; + if (!in_bounds(map, 2)) { + return false; + } + + switch (ttUSHORT(data + map)) { + case 0: + list.addRange(0, 255); + break; + case 4: { + if (!in_bounds(map, 14)) { + return false; + } + const size_t segment_count = ttUSHORT(data + map + 6) / 2; + const size_t end_codes = map + 14; + const size_t start_codes = end_codes + segment_count * 2 + 2; + if (!in_bounds(start_codes, segment_count * 2)) { + return false; + } + for (size_t i = 0; i < segment_count; i++) { + const uint32_t start = ttUSHORT(data + start_codes + i * 2); + const uint32_t end = ttUSHORT(data + end_codes + i * 2); + // The last segment maps 0xFFFF to the missing glyph + if (start <= end && start != 0xFFFF) { + list.addRange(start, end == 0xFFFF ? 0xFFFE : end); + } + } + break; + } + case 6: { + if (!in_bounds(map, 10)) { + return false; + } + const uint32_t first = ttUSHORT(data + map + 6); + const uint32_t entry_count = ttUSHORT(data + map + 8); + if (entry_count > 0) { + list.addRange(first, first + entry_count - 1); + } + break; + } + case 12: { + if (!in_bounds(map, 16)) { + return false; + } + const size_t group_count = ttULONG(data + map + 12); + if (!in_bounds(map + 16, group_count * 12)) { + return false; + } + for (size_t i = 0; i < group_count; i++) { + stbtt_uint8* group = data + map + 16 + i * 12; + const uint32_t start = ttULONG(group); + const uint32_t end = ttULONG(group + 4); + if (start <= end && end <= 0x10FFFF) { + list.addRange(start, end); + } + } + break; + } + default: + return false; + } + return !list.hasFailed(); +} + +error_t generate(const BinFontGeneratorConfig* config, const uint32_t* codepoints, size_t codepointCount, const stbtt_fontinfo& info, GlyphInfo* glyphs, ByteBuffer& out) { const float scale = stbtt_ScaleForMappingEmToPixels(&info, config->size); // Collect glyphs, sorted by codepoint and without duplicates or missing glyphs size_t count = 0; - for (size_t i = 0; i < config->codepoint_count; i++) { - const int index = stbtt_FindGlyphIndex(&info, static_cast(config->codepoints[i])); + for (size_t i = 0; i < codepointCount; i++) { + const int index = stbtt_FindGlyphIndex(&info, static_cast(codepoints[i])); if (index != 0) { - glyphs[count].codepoint = config->codepoints[i]; + glyphs[count].codepoint = codepoints[i]; glyphs[count].ttfIndex = index; count++; } @@ -386,6 +515,10 @@ error_t generate(const BinFontGeneratorConfig* config, const stbtt_fontinfo& inf bitmap_capacity = pixel_count; } stbtt_MakeGlyphBitmap(&info, bitmap, width, height, width, scale, scale, glyph.ttfIndex); + if (static_cast(info.userdata)->failed) { + memory_free(bitmap); + return ERROR_OUT_OF_MEMORY; + } for (size_t i = 0; i < pixel_count; i++) { writer.write((bitmap[i] * max_value + 127) / 255, config->bpp); } @@ -404,7 +537,7 @@ error_t generate(const BinFontGeneratorConfig* config, const stbtt_fontinfo& inf extern "C" { error_t binfont_generate(const BinFontGeneratorConfig* config, uint8_t** out_data, size_t* out_size) { - if (config->ttf_path == nullptr || config->size == 0 || config->bpp < 1 || config->bpp > 4 || config->codepoint_count == 0) { + if (config->ttf_path == nullptr || config->size == 0 || config->bpp < 1 || config->bpp > 4 || (config->codepoints == nullptr) != (config->codepoint_count == 0)) { return ERROR_INVALID_ARGUMENT; } @@ -420,15 +553,29 @@ error_t binfont_generate(const BinFontGeneratorConfig* config, uint8_t** out_dat memory_free(ttf); return ERROR_NOT_SUPPORTED; } + AllocationState allocation = { .failed = false }; + info.userdata = &allocation; + + const uint32_t* codepoints = config->codepoints; + size_t codepoint_count = config->codepoint_count; + CodepointList all_codepoints; + if (codepoints == nullptr) { + if (!collect_codepoints(info, ttf_size, all_codepoints)) { + memory_free(ttf); + return all_codepoints.hasFailed() ? ERROR_OUT_OF_MEMORY : ERROR_NOT_SUPPORTED; + } + codepoints = all_codepoints.getData(); + codepoint_count = all_codepoints.getCount(); + } - auto* glyphs = static_cast(memory_alloc(config->codepoint_count * sizeof(GlyphInfo))); + auto* glyphs = static_cast(memory_alloc(codepoint_count * sizeof(GlyphInfo))); if (glyphs == nullptr) { memory_free(ttf); return ERROR_OUT_OF_MEMORY; } ByteBuffer out; - const error_t error = generate(config, info, glyphs, out); + const error_t error = generate(config, codepoints, codepoint_count, info, glyphs, out); memory_free(glyphs); memory_free(ttf); if (error != ERROR_NONE) { @@ -440,4 +587,30 @@ error_t binfont_generate(const BinFontGeneratorConfig* config, uint8_t** out_dat return ERROR_NONE; } +error_t binfont_get_ttf_codepoints(const char* ttf_path, uint32_t** out_codepoints, size_t* out_count) { + size_t ttf_size = 0; + uint8_t* ttf = read_file(ttf_path, ttf_size); + if (ttf == nullptr) { + return ERROR_NOT_FOUND; + } + + stbtt_fontinfo info; + const int font_offset = stbtt_GetFontOffsetForIndex(ttf, 0); + CodepointList codepoints; + error_t error = ERROR_NONE; + if (font_offset < 0 || stbtt_InitFont(&info, ttf, font_offset) == 0) { + error = ERROR_NOT_SUPPORTED; + } else if (!collect_codepoints(info, ttf_size, codepoints)) { + error = codepoints.hasFailed() ? ERROR_OUT_OF_MEMORY : ERROR_NOT_SUPPORTED; + } + memory_free(ttf); + if (error != ERROR_NONE) { + return error; + } + + *out_count = codepoints.getCount(); + *out_codepoints = codepoints.release(); + return ERROR_NONE; +} + } diff --git a/Modules/binfont-module/source/module.c b/Modules/binfont-module/source/module.c index 6a4740eb7..fc4c5f159 100644 --- a/Modules/binfont-module/source/module.c +++ b/Modules/binfont-module/source/module.c @@ -17,6 +17,7 @@ static const struct ModuleSymbol SYMBOLS[] = { DEFINE_MODULE_SYMBOL(binfont_get_glyph_bitmap), // generator DEFINE_MODULE_SYMBOL(binfont_generate), + DEFINE_MODULE_SYMBOL(binfont_get_ttf_codepoints), // render DEFINE_MODULE_SYMBOL(binfont_draw_glyph_rgb565), DEFINE_MODULE_SYMBOL(binfont_draw_text_rgb565), diff --git a/Modules/binfont-module/tests/CMakeLists.txt b/Modules/binfont-module/tests/CMakeLists.txt index cad3d7a20..4dc86aa19 100644 --- a/Modules/binfont-module/tests/CMakeLists.txt +++ b/Modules/binfont-module/tests/CMakeLists.txt @@ -10,6 +10,7 @@ target_include_directories(BinFontModuleTests PRIVATE ${DOCTESTINC} ${PROJECT_SO target_compile_definitions(BinFontModuleTests PRIVATE "BINFONT_TEST_FIXTURES_DIR=\"${PROJECT_SOURCE_DIR}/fixtures\"" "BINFONT_TEST_TEMP_DIR=\"${CMAKE_CURRENT_BINARY_DIR}\"" + "BINFONT_TEST_TEXT_TTF=\"${CMAKE_SOURCE_DIR}/Data/system/fonts/AdwaitaSans.ttf\"" "BINFONT_TEST_ICON_TTF=\"${CMAKE_SOURCE_DIR}/Data/system/fonts/MaterialSymbolsRounded.ttf\"" ) diff --git a/Modules/binfont-module/tests/source/binfont_test.cpp b/Modules/binfont-module/tests/source/binfont_test.cpp index a5bb2bc0c..b492b933b 100644 --- a/Modules/binfont-module/tests/source/binfont_test.cpp +++ b/Modules/binfont-module/tests/source/binfont_test.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -300,6 +301,58 @@ TEST_CASE("binfont_generate rasterizes a TTF close to lv_font_conv") { binfont_close(reference); } +TEST_CASE("binfont_generate includes every codepoint of the TTF without a codepoint list") { + const BinFontGeneratorConfig config = { + .ttf_path = BINFONT_TEST_TEXT_TTF, + .size = 14, + .bpp = 2, + .codepoints = nullptr, + .codepoint_count = 0, + }; + uint8_t* data = nullptr; + size_t size = 0; + REQUIRE(binfont_generate(&config, &data, &size) == ERROR_NONE); + BinFont* font = nullptr; + REQUIRE(binfont_open_memory(data, size, true, &font) == ERROR_NONE); + + BinFontGlyph glyph; + for (uint32_t codepoint : { 0x20u, 0x41u, 0x7Eu, 0xE9u, 0xFFu, 0x2026u, 0x20ACu }) { + CAPTURE(codepoint); + CHECK(binfont_get_glyph(font, codepoint, &glyph)); + } + // Not in the subset + CHECK_FALSE(binfont_get_glyph(font, 0x0100, &glyph)); + CHECK_FALSE(binfont_get_glyph(font, 0x0416, &glyph)); + + binfont_close(font); +} + +TEST_CASE("binfont_get_ttf_codepoints lists the character map of a TTF") { + uint32_t* codepoints = nullptr; + size_t count = 0; + REQUIRE(binfont_get_ttf_codepoints(BINFONT_TEST_TEXT_TTF, &codepoints, &count) == ERROR_NONE); + CHECK(count > 190); + CHECK(std::find(codepoints, codepoints + count, 0x41u) != codepoints + count); + CHECK(std::find(codepoints, codepoints + count, 0x20ACu) != codepoints + count); + CHECK(std::find(codepoints, codepoints + count, 0x0416u) == codepoints + count); + memory_free(codepoints); + + CHECK_EQ(binfont_get_ttf_codepoints(BINFONT_TEST_FIXTURES_DIR "/missing.ttf", &codepoints, &count), ERROR_NOT_FOUND); +} + +TEST_CASE("binfont_generate rejects a codepoint count without codepoints") { + const BinFontGeneratorConfig config = { + .ttf_path = BINFONT_TEST_TEXT_TTF, + .size = 14, + .bpp = 2, + .codepoints = nullptr, + .codepoint_count = 5, + }; + uint8_t* data = nullptr; + size_t size = 0; + CHECK_EQ(binfont_generate(&config, &data, &size), ERROR_INVALID_ARGUMENT); +} + TEST_CASE("binfont_generate fails for a missing TTF") { const uint32_t codepoint = 0xE5C3; const BinFontGeneratorConfig config = { diff --git a/Modules/graphics-module/Kconfig b/Modules/graphics-module/Kconfig deleted file mode 100644 index 395019154..000000000 --- a/Modules/graphics-module/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -menu "Fonts" - config TT_FONT_IBMPLEXMONO_12 - bool "IBM Plex Mono 12 (7x12)" - default n - help - Include the ibmplexmono12 bitmap font. - config TT_FONT_IBMPLEXMONO_14 - bool "IBM Plex Mono 14 (8x14)" - default n - help - Include the ibmplexmono14 bitmap font. - config TT_FONT_IBMPLEXMONO_16 - bool "IBM Plex Mono 16 (10x16)" - default n - help - Include the ibmplexmono16 bitmap font. - config TT_FONT_IBMPLEXMONO_18 - bool "IBM Plex Mono 18 (11x18)" - default n - help - Include the ibmplexmono18 bitmap font. - config TT_FONT_IBMPLEXMONO_24 - bool "IBM Plex Mono 24 (14x24)" - default n - help - Include the ibmplexmono24 bitmap font. - config TT_FONT_IBMPLEXMONO_28 - bool "IBM Plex Mono 28 (17x28)" - default n - help - Include the ibmplexmono28 bitmap font. -endmenu diff --git a/Modules/graphics-module/include/font/font.h b/Modules/graphics-module/include/font/font.h deleted file mode 100644 index 3074d5b68..000000000 --- a/Modules/graphics-module/include/font/font.h +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A fixed-width bitmap font: monospaced glyphs covering a contiguous codepoint range, one row of - * glyph_bytes_per_row bytes per pixel row (bit 7 of the first byte is the leftmost pixel). - * - * glyph_bitmap is indexed as glyph_bitmap[(ch - first_codepoint) * glyph_height * - * glyph_bytes_per_row + row * glyph_bytes_per_row + byte]; a codepoint outside - * [first_codepoint, last_codepoint] has no entry. - */ -typedef struct FixedWidthFont { - uint8_t glyph_width; - uint8_t glyph_height; - uint8_t glyph_bytes_per_row; - uint8_t first_codepoint; - uint8_t last_codepoint; - const uint8_t* glyph_bitmap; -} FixedWidthFont; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/fonts.h b/Modules/graphics-module/include/font/fonts.h deleted file mode 100644 index a2a328914..000000000 --- a/Modules/graphics-module/include/font/fonts.h +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -// Every font generate-all.py produces, so a caller can pull them all in with one include. -#include -#include -#include -#include -#include -#include diff --git a/Modules/graphics-module/include/font/ibmplexmono12.h b/Modules/graphics-module/include/font/ibmplexmono12.h deleted file mode 100644 index 00a300552..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono12.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_12_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/ibmplexmono14.h b/Modules/graphics-module/include/font/ibmplexmono14.h deleted file mode 100644 index 42a23c2b2..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono14.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_14_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/ibmplexmono16.h b/Modules/graphics-module/include/font/ibmplexmono16.h deleted file mode 100644 index 81beb6206..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono16.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_16_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/ibmplexmono18.h b/Modules/graphics-module/include/font/ibmplexmono18.h deleted file mode 100644 index 7691cd0d0..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono18.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_18_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/ibmplexmono24.h b/Modules/graphics-module/include/font/ibmplexmono24.h deleted file mode 100644 index 06188439c..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono24.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_24_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/ibmplexmono28.h b/Modules/graphics-module/include/font/ibmplexmono28.h deleted file mode 100644 index 81a3e4ba5..000000000 --- a/Modules/graphics-module/include/font/ibmplexmono28.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern const FixedWidthFont ibmplexmono_28_font; - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/include/font/render.h b/Modules/graphics-module/include/font/render.h deleted file mode 100644 index 46c6fd588..000000000 --- a/Modules/graphics-module/include/font/render.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Renders one character's glyph into a PixelBuffer, in whatever pixel format it holds. - * - * The glyph occupies a font->glyph_width x font->glyph_height box at (x, y). A character outside - * [first_codepoint, last_codepoint] renders as a space. - * - * @param[out] buffer destination, in any pixel format - * @param[in] x pixel x of the glyph's top-left corner - * @param[in] y pixel y of the glyph's top-left corner - * @param[in] font the font to render with - * @param[in] character the character to render - * @param[in] fgColor colour for covered glyph pixels, as RGB565 - * @param[in] bgColor colour for uncovered glyph pixels, as RGB565 - * @param[in] conversion how fg/bg reduce into buffer's native format where that's ambiguous (see - * PixelBufferConversion) - */ -void font_render_char_pixel_buffer_rgb565( - struct PixelBuffer* buffer, - int x, - int y, - const FixedWidthFont* font, - char character, - uint16_t fgColor, - uint16_t bgColor, - enum PixelBufferConversion conversion -); - -#ifdef __cplusplus -} -#endif diff --git a/Modules/graphics-module/scripts/.gitignore b/Modules/graphics-module/scripts/.gitignore deleted file mode 100644 index d259f0582..000000000 --- a/Modules/graphics-module/scripts/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.ttf diff --git a/Modules/graphics-module/scripts/generate-all.py b/Modules/graphics-module/scripts/generate-all.py deleted file mode 100644 index 60a12cd2f..000000000 --- a/Modules/graphics-module/scripts/generate-all.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -""" -Generates bitmap font files (see generate.py) for a fixed set of glyph heights, from the same -monospace TTF. - -Requires the freetype-py package: pip install freetype-py - -Usage: - python3 generate-all.py -""" - -import importlib.util -import os - -MONO_URL = "https://github.com/google/fonts/raw/refs/heads/main/ofl/ibmplexmono/IBMPlexMono-Regular.ttf" -SIZES = [12, 14, 16, 18, 24, 28] - -spec = importlib.util.spec_from_file_location("generate_font", os.path.join(os.path.dirname(__file__), "generate.py")) -generate_font = importlib.util.module_from_spec(spec) -spec.loader.exec_module(generate_font) - - -def write_fonts_header(outputs: list): - path = os.path.join(generate_font.INCLUDE_DIR, "fonts.h") - print(f"Generating {path}") - with open(path, "w") as f: - f.write("// SPDX-License-Identifier: Apache-2.0\n") - f.write("#pragma once\n\n") - f.write("// Every font generate-all.py produces, so a caller can pull them all in with one include.\n") - for output in outputs: - f.write(f"#include \n") - - -if __name__ == "__main__": - outputs = [f"ibmplexmono{size}" for size in SIZES] - for output, size in zip(outputs, SIZES): - generate_font.generate(MONO_URL, size, output) - write_fonts_header(outputs) diff --git a/Modules/graphics-module/scripts/generate.py b/Modules/graphics-module/scripts/generate.py deleted file mode 100644 index 3adf8b0d1..000000000 --- a/Modules/graphics-module/scripts/generate.py +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env python3 -""" -Downloads a monospace TTF and rasterizes it into a FixedWidthFont (see include/font/font.h) covering: - -- U+0020-U+007E -- Height rows per glyph -- Each row ceil(width / 8) -- Bytes (bit 7 of the first byte = leftmost pixel) -Plus a header declaring the font. Glyph width is the font's own natural advance width at the given size. - -Requires the freetype-py package: pip install freetype-py - -Usage: - python3 generate.py --url URL --size SIZE --output NAME -""" - -import argparse -import math -import os -import re -import urllib.request - -import freetype - -GLYPH_FIRST = 0x20 -GLYPH_LAST = 0x7E - -MODULE_DIR = os.path.join(os.path.dirname(__file__), "..") -SOURCE_DIR = os.path.join(MODULE_DIR, "source") -INCLUDE_DIR = os.path.join(MODULE_DIR, "include", "font") - - -def download_file(url: str, filename: str): - if not os.path.exists(filename): - print(f"Downloading {filename} from {url}") - urllib.request.urlretrieve(url, filename) - else: - print(f"{filename} already exists, skipping download.") - - -def measure_advance_width(face: freetype.Face, size: int) -> float: - """Natural advance width (px) of the font at `size` px tall, isotropic DPI.""" - face.set_char_size(0, size * 64, 72, 72) - face.load_char("M", freetype.FT_LOAD_DEFAULT) - return face.glyph.advance.x / 64 - - -def get_bit(bitmap, x: int, y: int) -> bool: - if x < 0 or x >= bitmap.width or y < 0 or y >= bitmap.rows: - return False - byte = bitmap.buffer[y * abs(bitmap.pitch) + x // 8] - return bool((byte >> (7 - x % 8)) & 1) - - -def measure_baseline(face: freetype.Face, cell_height: int) -> int: - """ - Row (from the cell top) the baseline sits on. - - face.size.ascender/descender are line-spacing metrics, not ink extents - many fonts set them - taller than the glyphs actually are, which pushes the baseline row below the bottom of the - cell and clips it off entirely. Measuring the real cap-height ('A') and descender depth ('g') - at this pixel size keeps both in view instead. - """ - face.load_char("A", freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO) - cap_top = face.glyph.bitmap_top - face.load_char("g", freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO) - descender = face.glyph.bitmap.rows - face.glyph.bitmap_top - - max_baseline = cell_height - 1 - descender - if max_baseline >= cap_top: - baseline = cap_top + (max_baseline - cap_top) // 2 - else: - # Cap height and descender depth don't both fit in cell_height rows (common at very - # small sizes) - keep the cap/baseline row intact and let the descender clip instead. - baseline = cap_top - return min(max(baseline, 0), cell_height - 1) - - -def render_glyph(face: freetype.Face, codepoint: int, cell_width: int, cell_height: int, baseline_y: int, bytes_per_row: int) -> bytearray: - face.load_char(chr(codepoint), freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO) - glyph = face.glyph - bitmap = glyph.bitmap - - out = bytearray(cell_height * bytes_per_row) - for row in range(cell_height): - src_y = row - baseline_y + glyph.bitmap_top - for col in range(cell_width): - src_x = col - glyph.bitmap_left - if get_bit(bitmap, src_x, src_y): - out[row * bytes_per_row + col // 8] |= 1 << (7 - col % 8) - return out - - -def split_name(output: str) -> tuple: - """'ibmplexmono14' -> ('ibmplexmono', '14'), so identifiers can put an underscore between the - font name and its size instead of running them together.""" - match = re.match(r"^([a-zA-Z]+)(\d+)$", output) - if not match: - raise ValueError(f"'{output}' must be a name followed by digits, e.g. 'ibmplexmono14'") - return match.group(1), match.group(2) - - -def escape_char(ch: str) -> str: - if ch == "\\": - return "\\\\" - if ch == '"': - return '\\"' - return ch - - -def write_c_file(path: str, output: str, width: int, height: int, bytes_per_row: int, glyphs: dict): - glyph_count = GLYPH_LAST - GLYPH_FIRST + 1 - glyph_bytes = height * bytes_per_row - total_bytes = glyph_count * glyph_bytes - name, size_digits = split_name(output) - bitmap_name = f"{output}_glyph_bitmap" - struct_name = f"{name}_{size_digits}_font" - config_macro = f"CONFIG_TT_FONT_{name.upper()}_{size_digits}" - with open(path, "w") as f: - f.write(f"/*\n * {os.path.basename(path)} - {output} FixedWidthFont\n") - f.write(f" *\n * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py.\n") - f.write(f" * Each glyph is {width} pixels wide and {height} pixels tall, stored as {height} rows of\n") - f.write(f" * {bytes_per_row} byte{'s' if bytes_per_row != 1 else ''} each (bit 7 of the first byte = leftmost pixel).\n */\n\n") - f.write(f"#include \n\n") - f.write("#ifdef ESP_PLATFORM\n") - f.write("#include \n") - f.write("#endif\n\n") - f.write(f"// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating\n") - f.write(f"// this font's Kconfig entry) is treated the same as enabled.\n") - f.write(f"#if !defined({config_macro}) || {config_macro}\n\n") - f.write(f"// Glyph bitmap data: {glyph_count} characters (0x20-0x7E), {glyph_bytes} bytes each = {total_bytes} bytes\n") - f.write(f"static const uint8_t {bitmap_name}[] = {{\n") - for cp in range(GLYPH_FIRST, GLYPH_LAST + 1): - f.write(f' /* U+{cp:04X} "{escape_char(chr(cp))}" */\n') - data = glyphs[cp] - f.write(" " + ", ".join(f"0x{b:X}" for b in data) + ",\n") - f.write("};\n\n") - f.write(f"const FixedWidthFont {struct_name} = {{\n") - f.write(f" .glyph_width = {width},\n") - f.write(f" .glyph_height = {height},\n") - f.write(f" .glyph_bytes_per_row = {bytes_per_row},\n") - f.write(f" .first_codepoint = 0x{GLYPH_FIRST:02X},\n") - f.write(f" .last_codepoint = 0x{GLYPH_LAST:02X},\n") - f.write(f" .glyph_bitmap = {bitmap_name},\n") - f.write("};\n\n") - f.write(f"#endif // {config_macro}\n") - - -def write_h_file(path: str, output: str): - name, size_digits = split_name(output) - struct_name = f"{name}_{size_digits}_font" - with open(path, "w") as f: - f.write("// SPDX-License-Identifier: Apache-2.0\n") - f.write("#pragma once\n\n") - f.write("#include \n\n") - f.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n") - f.write(f"extern const FixedWidthFont {struct_name};\n\n") - f.write("#ifdef __cplusplus\n}\n#endif\n") - - -def generate(mono_url: str, size: int, output: str): - ttf_filename = os.path.basename(mono_url) - download_file(mono_url, ttf_filename) - - face = freetype.Face(ttf_filename) - natural_width = measure_advance_width(face, size) - if natural_width <= 0: - raise RuntimeError("Font reported a non-positive advance width") - width = round(natural_width) - - bytes_per_row = math.ceil(width / 8) - baseline_y = measure_baseline(face, size) - glyphs = {cp: render_glyph(face, cp, width, size, baseline_y, bytes_per_row) for cp in range(GLYPH_FIRST, GLYPH_LAST + 1)} - - c_path = os.path.join(SOURCE_DIR, f"{output}.c") - h_path = os.path.join(INCLUDE_DIR, f"{output}.h") - print(f"Generating {h_path}") - write_h_file(h_path, output) - print(f"Generating {c_path}") - write_c_file(c_path, output, width, size, bytes_per_row, glyphs) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--url", required=True, help="URL of the monospace TTF to download") - parser.add_argument("--size", type=int, required=True, help="Glyph height in pixels") - parser.add_argument("--output", required=True, help="Output file base name (no extension)") - args = parser.parse_args() - - generate(args.url, args.size, args.output) diff --git a/Modules/graphics-module/source/ibmplexmono12.c b/Modules/graphics-module/source/ibmplexmono12.c deleted file mode 100644 index 1e1e6c3b4..000000000 --- a/Modules/graphics-module/source/ibmplexmono12.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono12.c - ibmplexmono12 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 7 pixels wide and 12 pixels tall, stored as 12 rows of - * 1 byte each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_12) || CONFIG_TT_FONT_IBMPLEXMONO_12 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 12 bytes each = 1140 bytes -static const uint8_t ibmplexmono12_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0x28, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0x34, 0x28, 0x6E, 0x28, 0x28, 0xEC, 0x48, 0x50, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0x38, 0x56, 0x50, 0x70, 0x1C, 0x12, 0xD4, 0x3C, 0x10, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x62, 0x94, 0x94, 0x68, 0x2C, 0x52, 0x52, 0x8C, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0x30, 0x48, 0x40, 0x26, 0x74, 0x98, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0xC, 0x0, 0x0, - /* U+0029 ")" */ - 0x20, 0x10, 0x10, 0x8, 0x8, 0x8, 0x10, 0x10, 0x20, 0x60, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x10, 0x10, 0xFE, 0x10, 0x28, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x10, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x10, 0x10, 0x20, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x4, 0x8, 0x8, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x0, 0x0, - /* U+0030 "0" */ - 0x38, 0x44, 0x44, 0x54, 0x54, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0x30, 0x70, 0x50, 0x10, 0x10, 0x10, 0x10, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0x38, 0x44, 0x4, 0x4, 0x8, 0x30, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0x38, 0x44, 0x4, 0x38, 0xC, 0x4, 0xC4, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0x8, 0x18, 0x28, 0x48, 0x48, 0xFE, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x7C, 0x40, 0x40, 0x78, 0x44, 0x4, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0x18, 0x20, 0x40, 0x78, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x7C, 0x44, 0x4, 0x8, 0x8, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0x3C, 0x44, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0x38, 0x44, 0x44, 0x44, 0x3C, 0x4, 0x8, 0x30, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x18, 0x10, 0x10, 0x20, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x4, 0x8, 0x30, 0x40, 0x30, 0x8, 0x4, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x7C, 0x0, 0x7C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x40, 0x20, 0x18, 0x4, 0x18, 0x20, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x38, 0x44, 0x4, 0x18, 0x10, 0x0, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x38, 0x44, 0x5C, 0x54, 0x64, 0x64, 0x5C, 0x40, 0x38, 0x0, 0x0, 0x0, - /* U+0041 "A" */ - 0x10, 0x28, 0x28, 0x28, 0x44, 0x7C, 0x44, 0xC6, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0x38, 0x44, 0x40, 0x40, 0x40, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x7C, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x7C, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x38, 0x44, 0x40, 0x40, 0x5C, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0x3C, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4C, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x46, 0x48, 0x58, 0x50, 0x78, 0x48, 0x44, 0x46, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x44, 0x6C, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x44, 0x64, 0x64, 0x54, 0x54, 0x4C, 0x4C, 0x4C, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x7C, 0x44, 0x44, 0x44, 0x7C, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x10, 0x1C, 0x0, 0x0, - /* U+0052 "R" */ - 0x7C, 0x44, 0x44, 0x44, 0x7C, 0x48, 0x48, 0x46, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0x38, 0x44, 0x40, 0x70, 0xC, 0x4, 0xC4, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0xC6, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x82, 0x82, 0x94, 0xB4, 0x6C, 0x6C, 0x6C, 0x6C, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0xC6, 0x44, 0x28, 0x10, 0x18, 0x28, 0x44, 0xC6, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0xC2, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x7C, 0x4, 0x8, 0x10, 0x30, 0x20, 0x40, 0xFC, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x0, 0x0, - /* U+005C "\\" */ - 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x8, 0x8, 0x8, 0x4, 0x0, 0x0, - /* U+005D "]" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x0, 0x0, - /* U+005E "^" */ - 0x10, 0x28, 0x28, 0x44, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7C, 0x0, 0x0, - /* U+0060 "`" */ - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x38, 0x4C, 0x4, 0x7C, 0x44, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x78, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x38, 0x44, 0x40, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x4, 0x4, 0x34, 0x4C, 0x44, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x38, 0x44, 0x7C, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x6, 0x38, 0x44, 0x44, 0x38, 0x40, 0x3C, 0x42, 0x7C, 0x0, 0x0, - /* U+0068 "h" */ - 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0x18, 0x0, 0x70, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0x8, 0x0, 0x78, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x78, 0x0, 0x0, - /* U+006B "k" */ - 0x40, 0x40, 0x46, 0x48, 0x50, 0x68, 0x4C, 0x46, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x6C, 0x54, 0x54, 0x54, 0x54, 0x54, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x58, 0x64, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x0, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x34, 0x4C, 0x44, 0x44, 0x44, 0x3C, 0x4, 0x4, 0x0, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x7E, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x38, 0x44, 0x70, 0xC, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x20, 0x1C, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x44, 0x44, 0x44, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x92, 0xB2, 0xAC, 0x6C, 0x6C, 0x6C, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x44, 0x44, 0x28, 0x28, 0x30, 0x10, 0x10, 0x60, 0x0, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x7C, 0xC, 0x10, 0x20, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0x10, 0x10, 0x10, 0x8, 0x70, 0x18, 0x10, 0x10, 0x10, 0x1C, 0x0, 0x0, - /* U+007C "|" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, - /* U+007D "}" */ - 0x10, 0x10, 0x20, 0x20, 0x1C, 0x30, 0x20, 0x10, 0x10, 0x70, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x64, 0x54, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_12_font = { - .glyph_width = 7, - .glyph_height = 12, - .glyph_bytes_per_row = 1, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono12_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_12 diff --git a/Modules/graphics-module/source/ibmplexmono14.c b/Modules/graphics-module/source/ibmplexmono14.c deleted file mode 100644 index 108704149..000000000 --- a/Modules/graphics-module/source/ibmplexmono14.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono14.c - ibmplexmono14 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 8 pixels wide and 14 pixels tall, stored as 14 rows of - * 1 byte each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_14) || CONFIG_TT_FONT_IBMPLEXMONO_14 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 14 bytes each = 1330 bytes -static const uint8_t ibmplexmono14_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0x18, 0x18, 0x18, 0x18, 0x10, 0x10, 0x10, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0x24, 0x24, 0x24, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0x12, 0x14, 0x14, 0x67, 0x24, 0x24, 0xE6, 0x28, 0x28, 0x48, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0x3C, 0x4A, 0x49, 0x48, 0x38, 0xE, 0xA, 0xB, 0x4A, 0x3C, 0x8, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x71, 0x92, 0x92, 0x94, 0x70, 0xE, 0x29, 0x49, 0x49, 0x8E, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0x38, 0x44, 0x40, 0x40, 0x23, 0x52, 0x8C, 0x8C, 0xC6, 0x7B, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x8, 0x8, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x8, 0x8, 0x6, 0x0, 0x0, - /* U+0029 ")" */ - 0x10, 0x10, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x10, 0x10, 0x60, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x0, 0x18, 0x18, 0x5A, 0xBD, 0x18, 0x24, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x0, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x10, 0x10, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x0, 0x0, - /* U+0030 "0" */ - 0x3C, 0x66, 0x42, 0x42, 0x5A, 0x5A, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0x18, 0x28, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x7F, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0x3C, 0x46, 0x42, 0x2, 0x6, 0xC, 0x18, 0x30, 0x60, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0x3C, 0x46, 0x2, 0x4, 0x38, 0x6, 0x2, 0x2, 0xC6, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0xC, 0xC, 0x14, 0x24, 0x24, 0x44, 0x44, 0xFF, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x7E, 0x40, 0x40, 0x40, 0x5C, 0x66, 0x2, 0x2, 0x46, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0xC, 0x10, 0x20, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x7E, 0x42, 0x46, 0x4, 0x4, 0x8, 0x8, 0x18, 0x10, 0x30, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x66, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x2, 0x4, 0x8, 0x30, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x10, 0x10, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x0, 0x2, 0xC, 0x18, 0x60, 0x60, 0x18, 0xE, 0x2, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x0, 0x7E, 0x0, 0x0, 0x7E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x0, 0x40, 0x70, 0x18, 0x6, 0x6, 0x18, 0x30, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x3C, 0x66, 0x42, 0x2, 0x4, 0x18, 0x10, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x3C, 0x66, 0x42, 0x4E, 0x52, 0x52, 0x52, 0x52, 0x5E, 0x40, 0x60, 0x3C, 0x0, 0x0, - /* U+0041 "A" */ - 0x18, 0x18, 0x3C, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x7C, 0x42, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0x3C, 0x22, 0x42, 0x40, 0x40, 0x40, 0x40, 0x44, 0x22, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x7C, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x7C, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x7E, 0x40, 0x40, 0x40, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x7E, 0x40, 0x40, 0x40, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x3C, 0x66, 0x44, 0x40, 0x40, 0x4E, 0x42, 0x42, 0x66, 0x3A, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0x3E, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x43, 0x46, 0x4C, 0x48, 0x58, 0x68, 0x4C, 0x44, 0x42, 0x43, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x42, 0x66, 0x66, 0x5A, 0x5A, 0x5A, 0x52, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x62, 0x62, 0x72, 0x52, 0x52, 0x4A, 0x4A, 0x4A, 0x46, 0x46, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x3C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x3C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x18, 0xE, 0x0, 0x0, - /* U+0052 "R" */ - 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x46, 0x43, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0x3C, 0x42, 0x40, 0x40, 0x78, 0xE, 0x2, 0x2, 0xC2, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0xC3, 0x42, 0x42, 0x62, 0x24, 0x24, 0x24, 0x3C, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x81, 0x81, 0xC1, 0x5A, 0x5A, 0x5A, 0x5A, 0x66, 0x66, 0x66, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0xC3, 0x62, 0x24, 0x1C, 0x18, 0x18, 0x3C, 0x24, 0x42, 0xC3, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0xC3, 0x42, 0x66, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x7E, 0x2, 0x4, 0x8, 0x18, 0x10, 0x20, 0x60, 0x40, 0xFE, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x0, 0x0, - /* U+005C "\\" */ - 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x8, 0x8, 0x4, 0x4, 0x4, 0x2, 0x0, 0x0, - /* U+005D "]" */ - 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x78, 0x0, 0x0, - /* U+005E "^" */ - 0x18, 0x18, 0x24, 0x66, 0x42, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x0, 0x0, - /* U+0060 "`" */ - 0x30, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x0, 0x3C, 0x44, 0x6, 0x7E, 0x46, 0x4A, 0x7B, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x40, 0x40, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x62, 0x5C, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x0, 0x3C, 0x62, 0x40, 0x40, 0x40, 0x62, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x2, 0x2, 0x2, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x0, 0x3C, 0x66, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0xE, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x0, 0x3, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x40, 0x3E, 0x43, 0x43, 0x7E, 0x0, - /* U+0068 "h" */ - 0x40, 0x40, 0x40, 0x5C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0x8, 0x8, 0x0, 0x78, 0x8, 0x8, 0x8, 0x8, 0x8, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0xC, 0xC, 0x0, 0x7C, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x78, 0x0, - /* U+006B "k" */ - 0x40, 0x40, 0x40, 0x43, 0x4C, 0x58, 0x78, 0x44, 0x46, 0x43, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x0, 0x76, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x0, 0x5C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x0, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x0, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x62, 0x5C, 0x40, 0x40, 0x40, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x0, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x2, 0x2, 0x2, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x0, 0x77, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x0, 0x3C, 0x42, 0x40, 0x3C, 0x2, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x0, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3A, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x0, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x0, 0x99, 0x99, 0x5A, 0x6A, 0x66, 0x66, 0x66, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x0, 0x42, 0x24, 0x18, 0x18, 0x18, 0x24, 0x42, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x0, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x10, 0x10, 0x60, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x0, 0x7E, 0x4, 0x8, 0x18, 0x30, 0x60, 0x7E, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0x10, 0x10, 0x18, 0x8, 0x8, 0x70, 0x8, 0x8, 0x18, 0x10, 0x10, 0x1E, 0x0, 0x0, - /* U+007C "|" */ - 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, - /* U+007D "}" */ - 0x8, 0x8, 0x18, 0x10, 0x10, 0xE, 0x10, 0x10, 0x18, 0x8, 0x8, 0x78, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x72, 0x5A, 0x4E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_14_font = { - .glyph_width = 8, - .glyph_height = 14, - .glyph_bytes_per_row = 1, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono14_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_14 diff --git a/Modules/graphics-module/source/ibmplexmono16.c b/Modules/graphics-module/source/ibmplexmono16.c deleted file mode 100644 index c833bb81a..000000000 --- a/Modules/graphics-module/source/ibmplexmono16.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono16.c - ibmplexmono16 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 10 pixels wide and 16 pixels tall, stored as 16 rows of - * 2 bytes each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_16) || CONFIG_TT_FONT_IBMPLEXMONO_16 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 32 bytes each = 3040 bytes -static const uint8_t ibmplexmono16_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0x9, 0x0, 0x9, 0x0, 0x1B, 0x0, 0x73, 0xC0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xF3, 0x80, 0x36, 0x0, 0x24, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0x1F, 0x0, 0x25, 0x80, 0x64, 0x0, 0x64, 0x0, 0x34, 0x0, 0x1F, 0x0, 0x5, 0x80, 0x4, 0x80, 0x44, 0x80, 0x65, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x70, 0xC0, 0x48, 0x80, 0xC9, 0x0, 0x4B, 0x0, 0x72, 0x0, 0x0, 0x0, 0x13, 0x80, 0x24, 0x80, 0x24, 0x80, 0x44, 0x80, 0xC3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0x1C, 0x0, 0x22, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0x0, 0x39, 0x80, 0x49, 0x0, 0x45, 0x0, 0x42, 0x0, 0x65, 0x0, 0x39, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x6, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x18, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0029 ")" */ - 0x18, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x4C, 0x80, 0x7F, 0x80, 0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x1, 0x0, 0x2, 0x0, 0x2, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x10, 0x0, 0x10, 0x0, 0x10, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0030 "0" */ - 0x1E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x61, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x40, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0x1C, 0x0, 0x34, 0x0, 0x64, 0x0, 0x44, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0x1E, 0x0, 0x23, 0x0, 0x61, 0x0, 0x1, 0x0, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x8, 0x0, 0x10, 0x0, 0x20, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0x1E, 0x0, 0x23, 0x0, 0x41, 0x0, 0x1, 0x0, 0x3, 0x0, 0x1C, 0x0, 0x3, 0x0, 0x1, 0x0, 0x41, 0x0, 0x63, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0x7, 0x0, 0x7, 0x0, 0xB, 0x0, 0x1B, 0x0, 0x13, 0x0, 0x23, 0x0, 0x23, 0x0, 0x43, 0x0, 0x7F, 0x80, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x1, 0x80, 0x1, 0x80, 0x41, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0x6, 0x0, 0x18, 0x0, 0x10, 0x0, 0x20, 0x0, 0x3E, 0x0, 0x61, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x7F, 0x80, 0x41, 0x80, 0x41, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x40, 0x80, 0x40, 0x80, 0x61, 0x80, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x80, 0x1F, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0, 0xC, 0x0, 0x30, 0x0, 0x60, 0x0, 0x30, 0x0, 0xC, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0xC, 0x0, 0x3, 0x0, 0x1, 0x80, 0x3, 0x0, 0xC, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x1E, 0x0, 0x21, 0x0, 0x61, 0x0, 0x1, 0x0, 0x3, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x1E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x67, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x6F, 0x80, 0x20, 0x0, 0x30, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0041 "A" */ - 0xC, 0x0, 0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x12, 0x0, 0x33, 0x0, 0x23, 0x0, 0x3F, 0x0, 0x61, 0x80, 0x61, 0x80, 0x40, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x3E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x3E, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0x1E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x20, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x21, 0x0, 0x31, 0x80, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x3E, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x0, 0x23, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x1E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x67, 0x80, 0x61, 0x80, 0x61, 0x80, 0x31, 0x80, 0x1F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x7F, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x3F, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0x3F, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x23, 0x0, 0x62, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x21, 0x80, 0x23, 0x0, 0x22, 0x0, 0x24, 0x0, 0x2C, 0x0, 0x3C, 0x0, 0x36, 0x0, 0x22, 0x0, 0x23, 0x0, 0x21, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x61, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x6D, 0x80, 0x6D, 0x80, 0x6D, 0x80, 0x69, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x29, 0x80, 0x29, 0x80, 0x2D, 0x80, 0x25, 0x80, 0x27, 0x80, 0x23, 0x80, 0x23, 0x80, 0x23, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x3F, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1E, 0x0, 0xC, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0052 "R" */ - 0x3F, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x24, 0x0, 0x22, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0x1F, 0x0, 0x21, 0x80, 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, 0x1F, 0x0, 0x1, 0x80, 0x1, 0x80, 0x41, 0x80, 0x61, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0x40, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x33, 0x0, 0x12, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x5E, 0x80, 0x72, 0x80, 0x73, 0x80, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1A, 0x0, 0xC, 0x0, 0xC, 0x0, 0xE, 0x0, 0x12, 0x0, 0x33, 0x0, 0x21, 0x0, 0x40, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0xC0, 0xC0, 0x61, 0x80, 0x31, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x7F, 0x80, 0x1, 0x80, 0x3, 0x0, 0x2, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x10, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005C "\\" */ - 0x20, 0x0, 0x10, 0x0, 0x10, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005D "]" */ - 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005E "^" */ - 0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, - /* U+0060 "`" */ - 0x8, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x23, 0x0, 0x1, 0x0, 0x3F, 0x0, 0x61, 0x0, 0x61, 0x0, 0x67, 0x0, 0x3D, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x31, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x31, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1D, 0x0, 0x23, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x21, 0x80, 0x7F, 0x80, 0x60, 0x0, 0x61, 0x0, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x21, 0x0, 0x13, 0x0, 0x3E, 0x0, 0x20, 0x0, 0x1F, 0x0, 0x60, 0x80, 0x60, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0068 "h" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006B "k" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x21, 0x80, 0x22, 0x0, 0x24, 0x0, 0x2C, 0x0, 0x36, 0x0, 0x22, 0x0, 0x21, 0x0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5B, 0x80, 0x6C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x31, 0x0, 0x2E, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1D, 0x0, 0x23, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7B, 0x80, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x20, 0x0, 0x3C, 0x0, 0x7, 0x0, 0x1, 0x80, 0x61, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x52, 0x80, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x33, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x16, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x12, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x1, 0x0, 0x2, 0x0, 0x4, 0x0, 0x8, 0x0, 0x10, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x4, 0x0, 0x38, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007C "|" */ - 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007D "}" */ - 0x4, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x80, 0x6D, 0x80, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_16_font = { - .glyph_width = 10, - .glyph_height = 16, - .glyph_bytes_per_row = 2, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono16_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_16 diff --git a/Modules/graphics-module/source/ibmplexmono18.c b/Modules/graphics-module/source/ibmplexmono18.c deleted file mode 100644 index 9b4ac4f52..000000000 --- a/Modules/graphics-module/source/ibmplexmono18.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono18.c - ibmplexmono18 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 11 pixels wide and 18 pixels tall, stored as 18 rows of - * 2 bytes each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_18) || CONFIG_TT_FONT_IBMPLEXMONO_18 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 36 bytes each = 3420 bytes -static const uint8_t ibmplexmono18_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0xC, 0x80, 0x9, 0x80, 0x9, 0x0, 0x9, 0x0, 0x79, 0xE0, 0x19, 0x0, 0x1B, 0x0, 0x13, 0x0, 0xF3, 0xC0, 0x12, 0x0, 0x32, 0x0, 0x32, 0x0, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0x1F, 0x0, 0x34, 0xC0, 0x24, 0x80, 0x64, 0x0, 0x24, 0x0, 0x34, 0x0, 0xF, 0x0, 0x4, 0xC0, 0x4, 0xC0, 0x4, 0x40, 0x44, 0xC0, 0x74, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x38, 0x60, 0x4C, 0xC0, 0xC4, 0x80, 0xC5, 0x80, 0x4D, 0x0, 0x7A, 0x0, 0x0, 0x0, 0x3, 0x80, 0x1E, 0x40, 0x34, 0x60, 0x24, 0x60, 0x66, 0x40, 0xC3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0x1E, 0x0, 0x33, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0x0, 0x10, 0x0, 0x38, 0xC0, 0x6C, 0x80, 0x46, 0x80, 0x43, 0x0, 0x41, 0x0, 0x62, 0x80, 0x3C, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0029 ")" */ - 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x75, 0xC0, 0x1F, 0x0, 0xE, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x1, 0x80, 0x1, 0x0, 0x1, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x10, 0x0, 0x10, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0030 "0" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x6E, 0xC0, 0x6E, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0xE, 0x0, 0x1E, 0x0, 0x36, 0x0, 0x66, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0x1F, 0x0, 0x31, 0x80, 0x60, 0x80, 0x0, 0x80, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0x2, 0x0, 0x4, 0x0, 0x8, 0x0, 0x10, 0x0, 0x60, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0x1F, 0x0, 0x31, 0x80, 0x61, 0x80, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0xE, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x80, 0x40, 0x80, 0x61, 0x80, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0x3, 0x0, 0x7, 0x0, 0x5, 0x0, 0x9, 0x0, 0x19, 0x0, 0x11, 0x0, 0x31, 0x0, 0x61, 0x0, 0x41, 0x0, 0x7F, 0xC0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x0, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x20, 0x80, 0x71, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0x7, 0x0, 0xC, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x2F, 0x0, 0x71, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x7F, 0xC0, 0x60, 0xC0, 0x60, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0xE, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x31, 0xC0, 0x1E, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x1, 0x80, 0x6, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x30, 0x0, 0x1C, 0x0, 0x6, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0xC, 0x0, 0x7, 0x0, 0x1, 0x80, 0x1, 0x80, 0x7, 0x0, 0xC, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x40, 0x80, 0x1, 0x80, 0x1, 0x80, 0xF, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x67, 0xC0, 0x6C, 0xC0, 0x68, 0xC0, 0x68, 0xC0, 0x68, 0xC0, 0x6C, 0xC0, 0x67, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x10, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0041 "A" */ - 0xE, 0x0, 0xE, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x11, 0x0, 0x31, 0x80, 0x3F, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x3F, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0xF, 0x0, 0x11, 0x80, 0x30, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0xC0, 0x11, 0x80, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x3F, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x3F, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x67, 0x80, 0x60, 0x80, 0x60, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x7F, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x3F, 0x80, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0x1F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x61, 0x80, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x20, 0xC0, 0x21, 0x80, 0x21, 0x0, 0x23, 0x0, 0x26, 0x0, 0x2C, 0x0, 0x3E, 0x0, 0x36, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x20, 0xC0, 0x20, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x60, 0xC0, 0x71, 0xC0, 0x71, 0xC0, 0x7B, 0xC0, 0x6A, 0xC0, 0x6A, 0xC0, 0x64, 0xC0, 0x64, 0xC0, 0x64, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x28, 0xC0, 0x28, 0xC0, 0x2C, 0xC0, 0x24, 0xC0, 0x26, 0xC0, 0x22, 0xC0, 0x22, 0xC0, 0x23, 0xC0, 0x21, 0xC0, 0x21, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, - /* U+0052 "R" */ - 0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x26, 0x0, 0x23, 0x0, 0x23, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0x1F, 0x0, 0x30, 0xC0, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, 0xF, 0x0, 0x1, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x40, 0xC0, 0x61, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0x40, 0x40, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x31, 0x80, 0x11, 0x0, 0x11, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x4E, 0x40, 0x4A, 0x40, 0x6A, 0xC0, 0x6A, 0xC0, 0x6A, 0xC0, 0x7B, 0xC0, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x19, 0x0, 0xB, 0x0, 0xE, 0x0, 0x6, 0x0, 0xE, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0xC0, 0x60, 0x60, 0xC0, 0x30, 0x80, 0x31, 0x80, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x7F, 0xC0, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005C "\\" */ - 0x30, 0x0, 0x10, 0x0, 0x10, 0x0, 0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005D "]" */ - 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005E "^" */ - 0xE, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, - /* U+0060 "`" */ - 0xC, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x3E, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x31, 0x80, 0x2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x11, 0x80, 0x21, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x80, 0x31, 0x80, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x1E, 0x80, 0x31, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x7F, 0xC0, 0x60, 0x0, 0x20, 0x0, 0x30, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0x7, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x40, 0x60, 0x40, 0x60, 0xC0, 0x3F, 0x80, 0x0, 0x0, - /* U+0068 "h" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3E, 0x0, 0x0, 0x0, - /* U+006B "k" */ - 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0xC0, 0x21, 0x0, 0x26, 0x0, 0x2C, 0x0, 0x3E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x21, 0x80, 0x20, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0x3C, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x59, 0x80, 0x66, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x31, 0x80, 0x2F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x80, 0x31, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7D, 0xC0, 0xE, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x30, 0x80, 0x20, 0x0, 0x30, 0x0, 0x1F, 0x0, 0x0, 0x80, 0x0, 0xC0, 0x60, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0xC0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x11, 0x0, 0x11, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xA, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x40, 0x4E, 0x40, 0x4A, 0x40, 0x4A, 0x40, 0x6A, 0x40, 0x2A, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x31, 0x80, 0x1B, 0x0, 0xE, 0x0, 0x4, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x20, 0x80, 0x30, 0x80, 0x31, 0x80, 0x11, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x38, 0x0, 0x0, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x80, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0x8, 0x0, 0x18, 0x0, 0x30, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0xC, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3C, 0x0, 0x6, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007C "|" */ - 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007D "}" */ - 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7, 0x80, 0xC, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x40, 0x2C, 0x40, 0x46, 0x80, 0x43, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_18_font = { - .glyph_width = 11, - .glyph_height = 18, - .glyph_bytes_per_row = 2, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono18_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_18 diff --git a/Modules/graphics-module/source/ibmplexmono24.c b/Modules/graphics-module/source/ibmplexmono24.c deleted file mode 100644 index 092902923..000000000 --- a/Modules/graphics-module/source/ibmplexmono24.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono24.c - ibmplexmono24 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 14 pixels wide and 24 pixels tall, stored as 24 rows of - * 2 bytes each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_24) || CONFIG_TT_FONT_IBMPLEXMONO_24 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 48 bytes each = 4560 bytes -static const uint8_t ibmplexmono24_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0x6, 0x30, 0x6, 0x20, 0x6, 0x60, 0x6, 0x60, 0x4, 0x60, 0x7C, 0x7C, 0x7C, 0x7C, 0xC, 0x40, 0xC, 0xC0, 0x8, 0xC0, 0xF8, 0xF8, 0xF8, 0xF8, 0x18, 0x80, 0x19, 0x80, 0x19, 0x80, 0x11, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0xF, 0xC0, 0x1F, 0xF0, 0x39, 0x38, 0x31, 0x10, 0x31, 0x0, 0x31, 0x0, 0x39, 0x0, 0x1F, 0x80, 0xF, 0xE0, 0x1, 0xF0, 0x1, 0x38, 0x1, 0x18, 0x1, 0x18, 0x61, 0x18, 0x39, 0x38, 0x1F, 0xF0, 0xF, 0xC0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x3C, 0xC, 0x7E, 0x18, 0xC6, 0x10, 0xC2, 0x30, 0xC2, 0x20, 0xC6, 0x60, 0x7E, 0x40, 0x3C, 0x80, 0x0, 0x0, 0x0, 0xF0, 0xD, 0xF8, 0x19, 0x8C, 0x11, 0xC, 0x31, 0xC, 0x21, 0x8C, 0x61, 0xF8, 0xC0, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0xF, 0x0, 0x1F, 0x80, 0x38, 0xC0, 0x30, 0x80, 0x30, 0x0, 0x30, 0x0, 0x18, 0x0, 0x1C, 0x38, 0x3E, 0x38, 0x76, 0x20, 0x63, 0x20, 0xC1, 0xA0, 0xC1, 0xE0, 0xE0, 0xE0, 0x70, 0xF0, 0x7F, 0x30, 0x1E, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x0, 0xC0, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x0, 0xC0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0029 ")" */ - 0xC, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0xC, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x73, 0x38, 0x3F, 0xF0, 0x7, 0x80, 0x7, 0x80, 0xC, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xE0, 0xF, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x40, 0x0, 0xC0, 0x0, 0xC0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0xC, 0x0, 0x18, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0030 "0" */ - 0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0x7, 0x80, 0xF, 0x80, 0x1D, 0x80, 0x39, 0x80, 0x71, 0x80, 0x21, 0x80, 0x41, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0xF8, 0x3F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0xF, 0x80, 0x1F, 0xE0, 0x38, 0x60, 0x30, 0x30, 0x60, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0xE0, 0x1, 0xC0, 0x3, 0x80, 0x7, 0x0, 0xE, 0x0, 0x18, 0x0, 0x30, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0xF, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0xF, 0xC0, 0xF, 0xC0, 0x0, 0x60, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x60, 0x30, 0x70, 0x70, 0x3F, 0xE0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0x0, 0xE0, 0x1, 0xE0, 0x3, 0x60, 0x3, 0x60, 0x6, 0x60, 0x4, 0x60, 0xC, 0x60, 0x18, 0x60, 0x18, 0x60, 0x30, 0x60, 0x20, 0x60, 0x60, 0x60, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x1F, 0xF0, 0x1F, 0xF0, 0x10, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x37, 0xC0, 0x3F, 0xE0, 0x38, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x18, 0x0, 0x38, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0x1, 0xC0, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x18, 0x0, 0x18, 0x0, 0x33, 0xC0, 0x3F, 0xE0, 0x38, 0x70, 0x70, 0x30, 0x60, 0x18, 0x60, 0x18, 0x20, 0x18, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x7F, 0xF8, 0x7F, 0xF8, 0x60, 0x30, 0x60, 0x30, 0x60, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xC0, 0x0, 0xC0, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0xF, 0xC0, 0xF, 0xC0, 0x38, 0x70, 0x70, 0x38, 0x60, 0x18, 0x60, 0x18, 0x70, 0x38, 0x38, 0x70, 0x3F, 0xF0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0xF, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x10, 0x60, 0x18, 0x60, 0x18, 0x30, 0x38, 0x38, 0x70, 0x1F, 0xF0, 0xF, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0xC0, 0x1, 0x80, 0x3, 0x80, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x30, 0x0, 0xE0, 0x3, 0xC0, 0x7, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x30, 0x0, 0x1C, 0x0, 0x7, 0x0, 0x3, 0xC0, 0x0, 0xF0, 0x0, 0x30, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0x3C, 0x0, 0xF, 0x0, 0x3, 0x80, 0x0, 0xE0, 0x0, 0x30, 0x0, 0x30, 0x0, 0xE0, 0x3, 0x80, 0xF, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x7, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x60, 0x1, 0xC0, 0x3, 0x80, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x7, 0xC0, 0x1F, 0xE0, 0x18, 0x70, 0x30, 0x30, 0x30, 0x30, 0x21, 0xD0, 0x63, 0xD0, 0x66, 0x30, 0x66, 0x10, 0x66, 0x10, 0x66, 0x10, 0x66, 0x10, 0x66, 0x30, 0x63, 0xD0, 0x23, 0xD0, 0x30, 0x0, 0x30, 0x0, 0x18, 0x0, 0x1F, 0xE0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0041 "A" */ - 0x3, 0x80, 0x7, 0x80, 0x7, 0x80, 0x5, 0x80, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x3F, 0xC0, 0x3F, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x3F, 0xC0, 0x3F, 0xE0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0x7, 0xC0, 0xF, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30, 0x28, 0x30, 0x0, 0x30, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x20, 0x38, 0x38, 0x1C, 0x70, 0xF, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x3F, 0x80, 0x3F, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x3F, 0xE0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x3F, 0xF8, 0x3F, 0xF8, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x20, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x61, 0xF0, 0x61, 0xF0, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xF0, 0xF, 0xB0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x3F, 0xF0, 0x3F, 0xF0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0x1F, 0xE0, 0x1F, 0xE0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x30, 0x60, 0x38, 0xE0, 0x1F, 0xC0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x30, 0x18, 0x30, 0x30, 0x30, 0x60, 0x30, 0xE0, 0x31, 0xC0, 0x31, 0x80, 0x33, 0x0, 0x37, 0x0, 0x3F, 0x0, 0x3D, 0x80, 0x39, 0xC0, 0x30, 0xC0, 0x30, 0x60, 0x30, 0x70, 0x30, 0x30, 0x30, 0x38, 0x30, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x1F, 0xF8, 0x1F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x70, 0x38, 0x78, 0x78, 0x78, 0x78, 0x68, 0x58, 0x6C, 0xD8, 0x6C, 0xD8, 0x66, 0x98, 0x67, 0x98, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x62, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x38, 0x30, 0x38, 0x30, 0x3C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x26, 0x30, 0x26, 0x30, 0x22, 0x30, 0x23, 0x30, 0x23, 0x30, 0x21, 0xB0, 0x21, 0xB0, 0x20, 0xB0, 0x20, 0xF0, 0x20, 0xF0, 0x20, 0x70, 0x20, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x3F, 0xC0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xE0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x3, 0x0, 0x3, 0x0, 0x3, 0xF0, 0x1, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0052 "R" */ - 0x3F, 0xC0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xC0, 0x31, 0x80, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x18, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x3F, 0x80, 0xF, 0xE0, 0x0, 0xF0, 0x0, 0x38, 0x0, 0x18, 0x0, 0x18, 0x60, 0x38, 0x78, 0x70, 0x3F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0xFF, 0xFC, 0xFF, 0xFC, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0x60, 0x18, 0x60, 0x18, 0x70, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x40, 0x8, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x63, 0x18, 0x63, 0x18, 0x67, 0x98, 0x67, 0x98, 0x66, 0x98, 0x64, 0x98, 0x64, 0x98, 0x2C, 0xD0, 0x2C, 0xD0, 0x2C, 0xD0, 0x28, 0x50, 0x38, 0x70, 0x38, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0x60, 0x18, 0x30, 0x38, 0x30, 0x30, 0x18, 0x60, 0xC, 0xE0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x7, 0x80, 0x7, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0xE0, 0x1C, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x60, 0x1C, 0xE0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x30, 0x0, 0x70, 0x0, 0xE0, 0x0, 0xC0, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x1C, 0x0, 0x18, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x7, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005C "\\" */ - 0x30, 0x0, 0x18, 0x0, 0x18, 0x0, 0x8, 0x0, 0xC, 0x0, 0xC, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x3, 0x0, 0x1, 0x80, 0x1, 0x80, 0x0, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005D "]" */ - 0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005E "^" */ - 0x3, 0x0, 0x7, 0x80, 0x5, 0x80, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0060 "`" */ - 0x6, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x80, 0x1F, 0xC0, 0x30, 0x60, 0x20, 0x60, 0x0, 0x60, 0x1F, 0xE0, 0x3F, 0xE0, 0x70, 0x60, 0x60, 0x60, 0x30, 0xA0, 0x3F, 0xB8, 0x1F, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x38, 0x70, 0x37, 0xE0, 0x33, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xC0, 0x1F, 0xE0, 0x18, 0x70, 0x30, 0x20, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x30, 0x18, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0xF, 0x30, 0x1F, 0xB0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xC0, 0x1F, 0xE0, 0x38, 0x30, 0x30, 0x30, 0x3F, 0xF8, 0x7F, 0xF8, 0x60, 0x0, 0x30, 0x0, 0x30, 0x20, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0x3, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF8, 0x3F, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x78, 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x38, 0x60, 0x1F, 0xE0, 0xF, 0x80, 0x10, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x1F, 0xF8, 0x30, 0x18, 0x60, 0x18, 0x70, 0x18, 0x3F, 0xF0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, - /* U+0068 "h" */ - 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0x3, 0x80, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x80, 0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0xF8, 0x3F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0x0, 0xE0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xC0, 0x3F, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x3F, 0xC0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, - /* U+006B "k" */ - 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x38, 0x30, 0x60, 0x30, 0xC0, 0x31, 0x80, 0x33, 0x0, 0x37, 0x0, 0x3D, 0x80, 0x30, 0xC0, 0x30, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0x3F, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E, 0x70, 0x7E, 0xF8, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x10, 0x60, 0x18, 0x60, 0x18, 0x60, 0x10, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x38, 0x70, 0x37, 0xE0, 0x33, 0xC0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x30, 0x1F, 0xB0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x78, 0x3E, 0xF8, 0x6, 0x80, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xC0, 0x1F, 0xF0, 0x38, 0x30, 0x30, 0x0, 0x38, 0x0, 0x1F, 0xC0, 0x7, 0xF0, 0x0, 0x30, 0x0, 0x30, 0x30, 0x30, 0x7F, 0xF0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7F, 0xF0, 0x7F, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x20, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0xC, 0x43, 0x8, 0x67, 0x98, 0x67, 0x98, 0x64, 0x98, 0x64, 0x98, 0x24, 0x90, 0x2C, 0xD0, 0x2C, 0xD0, 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x38, 0x18, 0x60, 0x1C, 0x60, 0xC, 0xC0, 0x7, 0x80, 0x3, 0x0, 0x7, 0x80, 0x7, 0x80, 0xC, 0xC0, 0x18, 0x60, 0x38, 0x70, 0x70, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x10, 0x30, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0x4, 0x80, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3E, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x70, 0x0, 0xE0, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x18, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0x7, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x0, 0x3F, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007C "|" */ - 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007D "}" */ - 0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3, 0xF0, 0x3, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0x18, 0x3E, 0x18, 0x37, 0x18, 0x63, 0xB0, 0x61, 0xF0, 0x60, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_24_font = { - .glyph_width = 14, - .glyph_height = 24, - .glyph_bytes_per_row = 2, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono24_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_24 diff --git a/Modules/graphics-module/source/ibmplexmono28.c b/Modules/graphics-module/source/ibmplexmono28.c deleted file mode 100644 index 654f8a3bb..000000000 --- a/Modules/graphics-module/source/ibmplexmono28.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * ibmplexmono28.c - ibmplexmono28 FixedWidthFont - * - * Rasterized from a TTF with Modules/graphics-module/scripts/generate.py. - * Each glyph is 17 pixels wide and 28 pixels tall, stored as 28 rows of - * 3 bytes each (bit 7 of the first byte = leftmost pixel). - */ - -#include - -#ifdef ESP_PLATFORM -#include -#endif - -// See Modules/graphics-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating -// this font's Kconfig entry) is treated the same as enabled. -#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_28) || CONFIG_TT_FONT_IBMPLEXMONO_28 - -// Glyph bitmap data: 95 characters (0x20-0x7E), 84 bytes each = 7980 bytes -static const uint8_t ibmplexmono28_glyph_bitmap[] = { - /* U+0020 " " */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0021 "!" */ - 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0022 "\"" */ - 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0023 "#" */ - 0x1, 0x8C, 0x0, 0x3, 0xC, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3F, 0x1F, 0x0, 0x3E, 0x3F, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7E, 0x3E, 0x0, 0x7C, 0x7E, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0x18, 0x60, 0x0, 0x18, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0024 "$" */ - 0x7, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0xDE, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xC0, 0x0, 0x30, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x18, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0xF, 0xF0, 0x0, 0x1, 0xFC, 0x0, 0x0, 0xDE, 0x0, 0x0, 0xC6, 0x0, 0x0, 0xC6, 0x0, 0x0, 0xC7, 0x0, 0x20, 0xC6, 0x0, 0x30, 0xC6, 0x0, 0x7C, 0xDE, 0x0, 0x1F, 0xFC, 0x0, 0x7, 0xF0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0025 "%" */ - 0x1E, 0x3, 0x0, 0x3F, 0x3, 0x0, 0x63, 0x86, 0x0, 0x61, 0x8E, 0x0, 0x61, 0x8C, 0x0, 0x61, 0x98, 0x0, 0x61, 0x98, 0x0, 0x63, 0xB0, 0x0, 0x3F, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0x7E, 0x0, 0x6, 0xE3, 0x0, 0xC, 0xC3, 0x0, 0xC, 0xC3, 0x0, 0x18, 0xC3, 0x0, 0x30, 0xC3, 0x0, 0x30, 0xE3, 0x0, 0x60, 0x7E, 0x0, 0x60, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0026 "&" */ - 0x7, 0xC0, 0x0, 0xF, 0xE0, 0x0, 0x1C, 0x70, 0x0, 0x18, 0x20, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0x0, 0x0, 0xE, 0x0, 0x0, 0xE, 0xF, 0x0, 0x3B, 0xF, 0x0, 0x33, 0x8C, 0x0, 0x71, 0xCC, 0x0, 0x60, 0xE8, 0x0, 0x60, 0x78, 0x0, 0x60, 0x38, 0x0, 0x70, 0x38, 0x0, 0x38, 0x6C, 0x0, 0x3F, 0xCE, 0x0, 0xF, 0x87, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0027 "'" */ - 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0028 "(" */ - 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0029 ")" */ - 0x6, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002A "*" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x21, 0xC2, 0x0, 0x7D, 0xDF, 0x0, 0x3F, 0xFE, 0x0, 0x7, 0xF0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002B "+" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002C "," */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002D "-" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xF8, 0x0, 0xF, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002E "." */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+002F "/" */ - 0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0030 "0" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0031 "1" */ - 0x3, 0xC0, 0x0, 0x7, 0xC0, 0x0, 0xE, 0xC0, 0x0, 0x1C, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x30, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x3F, 0xFF, 0x0, 0x3F, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0032 "2" */ - 0x7, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x30, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x7, 0x0, 0x0, 0xE, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0033 "3" */ - 0x7, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x10, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x7, 0xE0, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x38, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xE, 0x0, 0x20, 0xE, 0x0, 0x30, 0xC, 0x0, 0x78, 0x3C, 0x0, 0x1F, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0034 "4" */ - 0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xD8, 0x0, 0x1, 0xD8, 0x0, 0x1, 0x98, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x6, 0x18, 0x0, 0xE, 0x18, 0x0, 0xC, 0x18, 0x0, 0x18, 0x18, 0x0, 0x38, 0x18, 0x0, 0x30, 0x18, 0x0, 0x60, 0x18, 0x0, 0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0035 "5" */ - 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x8, 0xE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x10, 0xE, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0036 "6" */ - 0x0, 0xF0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xE, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x3B, 0xF8, 0x0, 0x34, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0037 "7" */ - 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x30, 0xE, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0038 "8" */ - 0x7, 0xF0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0x7, 0xF0, 0x0, 0x7, 0xF0, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0039 "9" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x16, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003A ":" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003B ";" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0xC, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xF0, 0x0, 0x1, 0xE0, 0x0, 0x7, 0x80, 0x0, 0x1E, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x7, 0x80, 0x0, 0x1, 0xE0, 0x0, 0x0, 0xF0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xC, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003D "=" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003E ">" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x7, 0x80, 0x0, 0x3, 0xC0, 0x0, 0x0, 0xF0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xF0, 0x0, 0x3, 0xC0, 0x0, 0x7, 0x80, 0x0, 0x1E, 0x0, 0x0, 0x18, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+003F "?" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x78, 0x0, 0x1, 0xF0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0040 "@" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0xC, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0xE6, 0x0, 0x31, 0xF6, 0x0, 0x31, 0x8E, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x8E, 0x0, 0x31, 0xFE, 0x0, 0x30, 0xF6, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0x0, 0x0, 0xE, 0x0, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0041 "A" */ - 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x7, 0x70, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x1C, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x70, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0042 "B" */ - 0x1F, 0xF0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0x1C, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xC, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0043 "C" */ - 0x3, 0xF0, 0x0, 0x7, 0xF8, 0x0, 0xE, 0x1C, 0x0, 0x1C, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x6, 0x0, 0x1C, 0xE, 0x0, 0xE, 0x1C, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0044 "D" */ - 0x1F, 0xE0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x3C, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0x1C, 0x0, 0x18, 0x3C, 0x0, 0x1F, 0xF8, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0045 "E" */ - 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0046 "F" */ - 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0047 "G" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0xFE, 0x0, 0x30, 0xFE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x16, 0x0, 0xF, 0xF6, 0x0, 0x3, 0xC6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0048 "H" */ - 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0049 "I" */ - 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004A "J" */ - 0xF, 0xFC, 0x0, 0xF, 0xFC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x10, 0x18, 0x0, 0x38, 0x18, 0x0, 0x1C, 0x38, 0x0, 0xF, 0xF0, 0x0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004B "K" */ - 0x38, 0x7, 0x0, 0x38, 0xE, 0x0, 0x38, 0x1C, 0x0, 0x38, 0x38, 0x0, 0x38, 0x30, 0x0, 0x38, 0x70, 0x0, 0x38, 0xE0, 0x0, 0x39, 0xC0, 0x0, 0x3B, 0x80, 0x0, 0x3B, 0xC0, 0x0, 0x3E, 0xE0, 0x0, 0x3E, 0xE0, 0x0, 0x3C, 0x70, 0x0, 0x38, 0x30, 0x0, 0x38, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x38, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0x6, 0x0, 0x38, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004C "L" */ - 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004D "M" */ - 0x38, 0xE, 0x0, 0x3C, 0x1E, 0x0, 0x3C, 0x1E, 0x0, 0x3C, 0x1E, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x33, 0x26, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x30, 0x86, 0x0, 0x30, 0x86, 0x0, 0x30, 0x86, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004E "N" */ - 0x3C, 0x6, 0x0, 0x3C, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3B, 0x6, 0x0, 0x3B, 0x6, 0x0, 0x3B, 0x86, 0x0, 0x39, 0x86, 0x0, 0x39, 0x86, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xE6, 0x0, 0x38, 0x66, 0x0, 0x38, 0x66, 0x0, 0x38, 0x36, 0x0, 0x38, 0x36, 0x0, 0x38, 0x3E, 0x0, 0x38, 0x1E, 0x0, 0x38, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+004F "O" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0050 "P" */ - 0x1F, 0xF0, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0051 "Q" */ - 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0xFC, 0x0, 0x0, 0x7C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0052 "R" */ - 0x1F, 0xF0, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x18, 0xE0, 0x0, 0x18, 0x60, 0x0, 0x18, 0x70, 0x0, 0x18, 0x30, 0x0, 0x18, 0x38, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0053 "S" */ - 0x7, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0x1E, 0x0, 0x38, 0x6, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1F, 0x0, 0x0, 0xF, 0xF0, 0x0, 0x3, 0xFC, 0x0, 0x0, 0x1E, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x20, 0x6, 0x0, 0x70, 0xE, 0x0, 0x3C, 0x1C, 0x0, 0x1F, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0054 "T" */ - 0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0055 "U" */ - 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0056 "V" */ - 0x70, 0x7, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xE, 0x38, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0057 "W" */ - 0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x70, 0x3, 0x0, 0x31, 0xC7, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x32, 0x26, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x16, 0x0, 0x1C, 0x1E, 0x0, 0x1C, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0058 "X" */ - 0x70, 0x7, 0x0, 0x38, 0x6, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xE, 0x18, 0x0, 0x6, 0x38, 0x0, 0x7, 0x30, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x70, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0059 "Y" */ - 0x70, 0x7, 0x0, 0x70, 0x7, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xE, 0x38, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005A "Z" */ - 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005B "[" */ - 0x3, 0xFC, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0xFC, 0x0, 0x3, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005C "\\" */ - 0x18, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005D "]" */ - 0x1F, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x1F, 0xE0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005E "^" */ - 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x7, 0x70, 0x0, 0x6, 0x30, 0x0, 0xC, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x20, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+005F "_" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0060 "`" */ - 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0061 "a" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xE0, 0x0, 0xF, 0xF0, 0x0, 0x1C, 0x38, 0x0, 0x30, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0xF, 0xF8, 0x0, 0x1F, 0xF8, 0x0, 0x38, 0x18, 0x0, 0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0x38, 0x38, 0x0, 0x1F, 0xCF, 0x0, 0xF, 0x8F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0062 "b" */ - 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0x1B, 0xF8, 0x0, 0x19, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0063 "c" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xF0, 0x0, 0x7, 0xF8, 0x0, 0xE, 0x1C, 0x0, 0x1C, 0xC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x8, 0x0, 0x1C, 0xC, 0x0, 0xE, 0x1E, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0064 "d" */ - 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x7, 0xCC, 0x0, 0xF, 0xEC, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0065 "e" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0xC, 0x0, 0xF, 0xFE, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0066 "f" */ - 0x0, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0067 "g" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x1F, 0x0, 0x3, 0xF0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0x1C, 0x0, 0xC, 0x18, 0x0, 0x7, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0xF, 0xFE, 0x0, 0x18, 0x7, 0x0, 0x30, 0x3, 0x0, 0x30, 0x3, 0x0, 0x38, 0xE, 0x0, 0x1F, 0xFE, 0x0, 0xF, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0068 "h" */ - 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0069 "i" */ - 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xE0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006A "j" */ - 0x0, 0x38, 0x0, 0x0, 0x78, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xF0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006B "k" */ - 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0xE, 0x0, 0x18, 0x1C, 0x0, 0x18, 0x38, 0x0, 0x18, 0x70, 0x0, 0x18, 0xE0, 0x0, 0x19, 0x80, 0x0, 0x1F, 0xC0, 0x0, 0x1E, 0xE0, 0x0, 0x1C, 0x70, 0x0, 0x18, 0x38, 0x0, 0x18, 0x18, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006C "l" */ - 0x3F, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006D "m" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x37, 0x1C, 0x0, 0x3F, 0xBE, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006E "n" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+006F "o" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0070 "p" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0x1B, 0xF8, 0x0, 0x19, 0xF0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0071 "q" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xCC, 0x0, 0xF, 0xEC, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0072 "r" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x9F, 0x0, 0x3F, 0xBF, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3F, 0xFC, 0x0, 0x3F, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0073 "s" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0x1E, 0x0, 0x18, 0x8, 0x0, 0x18, 0x0, 0x0, 0x1E, 0x0, 0x0, 0xF, 0xF0, 0x0, 0x3, 0xFC, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x10, 0xE, 0x0, 0x3C, 0x1C, 0x0, 0x1F, 0xFC, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0074 "t" */ - 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x7F, 0xFE, 0x0, 0x7F, 0xFE, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0xFE, 0x0, 0x1, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0075 "u" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x3C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0076 "v" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0077 "w" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xC3, 0x0, 0x61, 0xC3, 0x0, 0x61, 0x43, 0x0, 0x21, 0x43, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x32, 0x26, 0x0, 0x32, 0x36, 0x0, 0x36, 0x36, 0x0, 0x16, 0x34, 0x0, 0x1E, 0x34, 0x0, 0x1C, 0x1C, 0x0, 0x1C, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0078 "x" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x7, 0x70, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+0079 "y" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xE, 0x18, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007A "z" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007B "{" */ - 0x1, 0xFC, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x1F, 0xC0, 0x0, 0x1F, 0x80, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0xFC, 0x0, 0x1, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007C "|" */ - 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007D "}" */ - 0x1F, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xFC, 0x0, 0x0, 0xFC, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x2, 0x0, 0x1F, 0x6, 0x0, 0x39, 0x86, 0x0, 0x30, 0xCE, 0x0, 0x30, 0xFC, 0x0, 0x20, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -}; - -const FixedWidthFont ibmplexmono_28_font = { - .glyph_width = 17, - .glyph_height = 28, - .glyph_bytes_per_row = 3, - .first_codepoint = 0x20, - .last_codepoint = 0x7E, - .glyph_bitmap = ibmplexmono28_glyph_bitmap, -}; - -#endif // CONFIG_TT_FONT_IBMPLEXMONO_28 diff --git a/Modules/graphics-module/source/module.c b/Modules/graphics-module/source/module.c index 3d48ae697..e05aa4669 100644 --- a/Modules/graphics-module/source/module.c +++ b/Modules/graphics-module/source/module.c @@ -1,12 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 -#include - #include #include static const struct ModuleSymbol SYMBOLS[] = { - // font - DEFINE_MODULE_SYMBOL(font_render_char_pixel_buffer_rgb565), // pixel_buffer DEFINE_MODULE_SYMBOL(pixel_buffer_create), DEFINE_MODULE_SYMBOL(pixel_buffer_create_with_policy), diff --git a/Modules/graphics-module/source/render.cpp b/Modules/graphics-module/source/render.cpp deleted file mode 100644 index 143c292d1..000000000 --- a/Modules/graphics-module/source/render.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#include -#include -#include - -extern "C" { - -void font_render_char_pixel_buffer_rgb565( - PixelBuffer* buffer, - int x, - int y, - const FixedWidthFont* font, - char character, - uint16_t fg, - uint16_t bg, - PixelBufferConversion conversion -) { - const auto raw = static_cast(character); - const unsigned char glyphChar = (raw >= font->first_codepoint && raw <= font->last_codepoint) ? raw : ' '; - const uint8_t* glyph = &font->glyph_bitmap[(glyphChar - font->first_codepoint) * font->glyph_height * font->glyph_bytes_per_row]; - - for (int row = 0; row < font->glyph_height; row++) { - const uint8_t* bits = &glyph[row * font->glyph_bytes_per_row]; - - for (int col = 0; col < font->glyph_width; col++) { - // The font stores the leftmost pixel of each row byte in the most significant bit. - const bool covered = (bits[col / 8] & (0x80U >> (col % 8))) != 0; - pixel_buffer_set_pixel_rgb565(buffer, x + col, y + row, covered ? fg : bg, conversion); - } - } -} - -} diff --git a/Modules/lvgl-module/CMakeLists.txt b/Modules/lvgl-module/CMakeLists.txt index 93d09deb3..6c1f79af0 100644 --- a/Modules/lvgl-module/CMakeLists.txt +++ b/Modules/lvgl-module/CMakeLists.txt @@ -1,41 +1,7 @@ cmake_minimum_required(VERSION 3.20) -# #################################### -# Read sdkconfig properties -# #################################### - include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/properties.cmake") -if (DEFINED ENV{ESP_IDF_VERSION}) - GET_PROPERTY_FILE_CONTENT("${CMAKE_CURRENT_LIST_DIR}/../../sdkconfig" sdkconfig_text) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_FONT_SIZE_SMALL" font_size_small) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_FONT_SIZE_DEFAULT" font_size_default) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_FONT_SIZE_LARGE" font_size_large) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE" statusbar_symbol_size) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE" launcher_symbol_size) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_LVGL_SHARED_ICON_SIZE" shared_symbol_size) - math(EXPR shared_symbol_2x_size "${shared_symbol_size} * 2") -else () - # Default values for simulator - set(font_size_small 10) - set(font_size_default 14) - set(font_size_large 18) - set(statusbar_symbol_size 20) - set(launcher_symbol_size 36) - set(shared_symbol_size 16) - set(shared_symbol_2x_size 32) -endif () - -message("Font sizes:") -message(" - small: ${font_size_small}") -message(" - default: ${font_size_default}") -message(" - large: ${font_size_large}") -message("Icon sizes:") -message(" - statusbar: ${statusbar_symbol_size}") -message(" - launcher: ${launcher_symbol_size}") -message(" - shared: ${shared_symbol_size}") -message(" - shared_2x: ${shared_symbol_2x_size}") - # #################################### # Read device properties # #################################### @@ -106,18 +72,6 @@ tactility_get_module_name("lvgl-module" MODULE_NAME) target_compile_definitions(${MODULE_NAME} PUBLIC # Ensure it loads "-DLV_LVGL_H_INCLUDE_SIMPLE" - # Text fonts - "-DTT_LVGL_TEXT_FONT_SMALL_SIZE=${font_size_small}" - "-DTT_LVGL_TEXT_FONT_SMALL_SYMBOL=lv_font_montserrat_${font_size_small}" - "-DTT_LVGL_TEXT_FONT_DEFAULT_SIZE=${font_size_default}" - "-DTT_LVGL_TEXT_FONT_DEFAULT_SYMBOL=lv_font_montserrat_${font_size_default}" - "-DTT_LVGL_TEXT_FONT_LARGE_SIZE=${font_size_large}" - "-DTT_LVGL_TEXT_FONT_LARGE_SYMBOL=lv_font_montserrat_${font_size_large}" - # Icon fonts - "-DTT_LVGL_STATUSBAR_FONT_ICON_SIZE=${statusbar_symbol_size}" - "-DTT_LVGL_LAUNCHER_FONT_ICON_SIZE=${launcher_symbol_size}" - "-DTT_LVGL_SHARED_FONT_ICON_SIZE=${shared_symbol_size}" - "-DTT_LVGL_SHARED_FONT_ICON_2X_SIZE=${shared_symbol_2x_size}" # UiDensity "-DTT_LVGL_UI_DENSITY=${ui_density_variable}" ) diff --git a/Modules/lvgl-module/README.md b/Modules/lvgl-module/README.md index aa74b87bb..2273e5747 100644 --- a/Modules/lvgl-module/README.md +++ b/Modules/lvgl-module/README.md @@ -16,11 +16,13 @@ The module supports two main categories of fonts: ### Text Fonts -Standard text rendering uses the **Montserrat** font. Three sizes are pre-configured: +Text uses the **Adwaita Sans** font in three sizes: - `FONT_SIZE_SMALL` - `FONT_SIZE_DEFAULT` - `FONT_SIZE_LARGE` +Until Tactility registers these fonts with `lvgl_set_text_font()`, the getters return LVGL's built-in default font (Montserrat). + ### Icon Fonts Icons are provided by the **Material Symbols** font, divided into three usage-specific sets: @@ -30,10 +32,11 @@ Icons are provided by the **Material Symbols** font, divided into three usage-sp ## How to update the fonts -Font sizes and symbols are configurable: +All font sizes derive from one default text size: `font.defaultSize` in `device.properties` (`CONFIG_TT_FONT_DEFAULT_SIZE`, 14 on the simulator). +Tactility calculates the other text and icon sizes from it in `Tactility/Source/lvgl/FontSizes.cpp`. -- **On ESP32 (IDF)**: Sizes can be updated via `menuconfig` or by editing `sdkconfig`. Look for `CONFIG_TT_LVGL_FONT_SIZE_*` and `CONFIG_TT_LVGL_*_ICON_SIZE` parameters. -- **On Simulator/POSIX**: Default sizes are defined in `Modules/lvgl-module/CMakeLists.txt`. +Text fonts are rasterized on device at startup from `Data/system/fonts/AdwaitaSans.ttf` and cached as `.bin` files in the data path. +`Tactility/Fonts/generate.py` creates that TTF subset from `Tactility/Fonts/AdwaitaSans-Regular.ttf` (requires `pip install fonttools`). Icon fonts are rasterized on device at startup from `Data/system/fonts/MaterialSymbolsRounded.ttf` (a subset with only the used icons) and cached as `.bin` files in the data path, so any icon size works. The icons per font are listed by name and resolved through `Data/system/fonts/MaterialSymbolsRounded.codepoints`. diff --git a/Modules/lvgl-module/generate-icons.py b/Modules/lvgl-module/generate-icons.py index 4d794fc4e..2306ae811 100755 --- a/Modules/lvgl-module/generate-icons.py +++ b/Modules/lvgl-module/generate-icons.py @@ -162,6 +162,7 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam "more_vert", "music_note", "note_add", + "palette", "power_settings_new", # Power off for T-Lora Pager "refresh", # e.g. App Hub reload button "search", diff --git a/Modules/lvgl-module/include/lvgl/fonts.h b/Modules/lvgl-module/include/lvgl/fonts.h index 3efc17651..b22cf77a5 100644 --- a/Modules/lvgl-module/include/lvgl/fonts.h +++ b/Modules/lvgl-module/include/lvgl/fonts.h @@ -21,11 +21,23 @@ enum LvglIconFont { LVGL_ICON_FONT_SHARED_2X, }; +/** + * @brief Sets the font that is returned by the getter of a text font. + * Until a text font is set, its getter returns LVGL's default font. + * @param[in] font_size the text font to set + * @param[in] font the font + * @param[in] height the font size in pixels, returned by lvgl_get_text_font_height() + */ +void lvgl_set_text_font(enum LvglFontSize font_size, const lv_font_t* font, uint32_t height); + /** * @brief Sets the font that is returned by the getter of an icon font. - * Until an icon font is set, its getter returns the default text font. + * Until an icon font is set, its getter returns LVGL's default font. + * @param[in] icon_font the icon font to set + * @param[in] font the font + * @param[in] height the font size in pixels, returned by the matching height getter */ -void lvgl_set_icon_font(enum LvglIconFont icon_font, const lv_font_t* font); +void lvgl_set_icon_font(enum LvglIconFont icon_font, const lv_font_t* font, uint32_t height); const lv_font_t* lvgl_get_shared_icon_font(void); uint32_t lvgl_get_shared_icon_font_height(void); diff --git a/Modules/lvgl-module/include/lvgl/icons/names.h b/Modules/lvgl-module/include/lvgl/icons/names.h index 59b8a0001..688a98965 100644 --- a/Modules/lvgl-module/include/lvgl/icons/names.h +++ b/Modules/lvgl-module/include/lvgl/icons/names.h @@ -9,7 +9,7 @@ extern "C" { #endif /** Changes whenever the icon TTF subset, its codepoints file or the icon name lists change */ -#define LVGL_ICON_FONT_VERSION 0x977A6A66u +#define LVGL_ICON_FONT_VERSION 0xEE67835Du // Icon names per icon font, resolved through the .codepoints file next to the TTF extern const char* const lvgl_icon_shared_names[]; diff --git a/Modules/lvgl-module/include/lvgl/icons/shared.h b/Modules/lvgl-module/include/lvgl/icons/shared.h index 7c745beff..19b8e2399 100644 --- a/Modules/lvgl-module/include/lvgl/icons/shared.h +++ b/Modules/lvgl-module/include/lvgl/icons/shared.h @@ -35,6 +35,7 @@ #define LVGL_ICON_SHARED_MORE_VERT "\xEE\x97\x94" #define LVGL_ICON_SHARED_MUSIC_NOTE "\xEE\x90\x85" #define LVGL_ICON_SHARED_NOTE_ADD "\xEE\xA2\x9C" +#define LVGL_ICON_SHARED_PALETTE "\xEE\x90\x8A" #define LVGL_ICON_SHARED_POWER_SETTINGS_NEW "\xEF\xA3\x87" #define LVGL_ICON_SHARED_REFRESH "\xEE\x97\x95" #define LVGL_ICON_SHARED_SEARCH "\xEE\xBD\xBA" diff --git a/Modules/lvgl-module/source/fonts.c b/Modules/lvgl-module/source/fonts.c index 1c2b42cb3..c6c432c49 100644 --- a/Modules/lvgl-module/source/fonts.c +++ b/Modules/lvgl-module/source/fonts.c @@ -1,54 +1,47 @@ // SPDX-License-Identifier: Apache-2.0 #include #include -#include -// The preprocessor definitions that are used below are defined in the CMakeLists.txt from this module. +struct RegisteredFont { + const lv_font_t* font; + uint32_t height; +}; -extern const lv_font_t TT_LVGL_TEXT_FONT_SMALL_SYMBOL; -extern const lv_font_t TT_LVGL_TEXT_FONT_DEFAULT_SYMBOL; -extern const lv_font_t TT_LVGL_TEXT_FONT_LARGE_SYMBOL; +static struct RegisteredFont text_fonts[FONT_SIZE_LARGE + 1]; +static struct RegisteredFont icon_fonts[LVGL_ICON_FONT_SHARED_2X + 1]; -static const lv_font_t* icon_fonts[LVGL_ICON_FONT_SHARED_2X + 1]; - -void lvgl_set_icon_font(enum LvglIconFont icon_font, const lv_font_t* font) { - icon_fonts[icon_font] = font; +void lvgl_set_text_font(enum LvglFontSize font_size, const lv_font_t* font, uint32_t height) { + text_fonts[font_size] = (struct RegisteredFont) { .font = font, .height = height }; } -static const lv_font_t* get_icon_font(enum LvglIconFont icon_font) { - const lv_font_t* font = icon_fonts[icon_font]; - return font != NULL ? font : &TT_LVGL_TEXT_FONT_DEFAULT_SYMBOL; +void lvgl_set_icon_font(enum LvglIconFont icon_font, const lv_font_t* font, uint32_t height) { + icon_fonts[icon_font] = (struct RegisteredFont) { .font = font, .height = height }; } -uint32_t lvgl_get_text_font_height(enum LvglFontSize font_size) { - switch (font_size) { - case FONT_SIZE_SMALL: return TT_LVGL_TEXT_FONT_SMALL_SIZE; - case FONT_SIZE_DEFAULT: return TT_LVGL_TEXT_FONT_DEFAULT_SIZE; - case FONT_SIZE_LARGE: return TT_LVGL_TEXT_FONT_LARGE_SIZE; - default: check(false); - } +static const lv_font_t* get_font(const struct RegisteredFont* registered) { + return registered->font != NULL ? registered->font : LV_FONT_DEFAULT; } -const lv_font_t* lvgl_get_text_font(enum LvglFontSize font_size) { - switch (font_size) { - case FONT_SIZE_SMALL: return &TT_LVGL_TEXT_FONT_SMALL_SYMBOL; - case FONT_SIZE_DEFAULT: return &TT_LVGL_TEXT_FONT_DEFAULT_SYMBOL; - case FONT_SIZE_LARGE: return &TT_LVGL_TEXT_FONT_LARGE_SYMBOL; - default: check(false); - } + +static uint32_t get_height(const struct RegisteredFont* registered) { + return registered->font != NULL ? registered->height : (uint32_t)lv_font_get_line_height(LV_FONT_DEFAULT); } -uint32_t lvgl_get_shared_icon_font_height() { return TT_LVGL_SHARED_FONT_ICON_SIZE; } +const lv_font_t* lvgl_get_text_font(enum LvglFontSize font_size) { return get_font(&text_fonts[font_size]); } + +uint32_t lvgl_get_text_font_height(enum LvglFontSize font_size) { return get_height(&text_fonts[font_size]); } + +const lv_font_t* lvgl_get_shared_icon_font() { return get_font(&icon_fonts[LVGL_ICON_FONT_SHARED]); } -const lv_font_t* lvgl_get_shared_icon_font() { return get_icon_font(LVGL_ICON_FONT_SHARED); } +uint32_t lvgl_get_shared_icon_font_height() { return get_height(&icon_fonts[LVGL_ICON_FONT_SHARED]); } -uint32_t lvgl_get_shared_icon_font_2x_height() { return TT_LVGL_SHARED_FONT_ICON_SIZE * 2; } +const lv_font_t* lvgl_get_shared_icon_font_2x() { return get_font(&icon_fonts[LVGL_ICON_FONT_SHARED_2X]); } -const lv_font_t* lvgl_get_shared_icon_font_2x() { return get_icon_font(LVGL_ICON_FONT_SHARED_2X); } +uint32_t lvgl_get_shared_icon_font_2x_height() { return get_height(&icon_fonts[LVGL_ICON_FONT_SHARED_2X]); } -uint32_t lvgl_get_launcher_icon_font_height() { return TT_LVGL_LAUNCHER_FONT_ICON_SIZE; } +const lv_font_t* lvgl_get_launcher_icon_font() { return get_font(&icon_fonts[LVGL_ICON_FONT_LAUNCHER]); } -const lv_font_t* lvgl_get_launcher_icon_font() { return get_icon_font(LVGL_ICON_FONT_LAUNCHER); } +uint32_t lvgl_get_launcher_icon_font_height() { return get_height(&icon_fonts[LVGL_ICON_FONT_LAUNCHER]); } -uint32_t lvgl_get_statusbar_icon_font_height() { return TT_LVGL_STATUSBAR_FONT_ICON_SIZE; } +const lv_font_t* lvgl_get_statusbar_icon_font() { return get_font(&icon_fonts[LVGL_ICON_FONT_STATUSBAR]); } -const lv_font_t* lvgl_get_statusbar_icon_font() { return get_icon_font(LVGL_ICON_FONT_STATUSBAR); } +uint32_t lvgl_get_statusbar_icon_font_height() { return get_height(&icon_fonts[LVGL_ICON_FONT_STATUSBAR]); } diff --git a/Modules/lvgl-module/source/icon_names.c b/Modules/lvgl-module/source/icon_names.c index c39be6eac..ddc878bb7 100644 --- a/Modules/lvgl-module/source/icon_names.c +++ b/Modules/lvgl-module/source/icon_names.c @@ -37,6 +37,7 @@ const char* const lvgl_icon_shared_names[] = { "more_vert", "music_note", "note_add", + "palette", "power_settings_new", "refresh", "search", diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index 49df9c427..f5830d1c5 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -1,5 +1,13 @@ # Third-Party Notices +### Adwaita + +Adwaita Sans and Mono fonts are used. + +Website: https://github.com/GNOME/adwaita-fonts + +License: [SIL Open Font License 1.1](https://raw.githubusercontent.com/GNOME/adwaita-fonts/refs/heads/main/LICENSE) + ### BreezyBox This project used code from the BreezyBox project. diff --git a/Tactility/CMakeLists.txt b/Tactility/CMakeLists.txt index 0f5f177ed..82a334d2b 100644 --- a/Tactility/CMakeLists.txt +++ b/Tactility/CMakeLists.txt @@ -219,19 +219,18 @@ target_include_directories(${COMPONENT_LIB} PRIVATE "${GENERATED_DIR}") add_dependencies(${COMPONENT_LIB} Generated) # -# Terminal font +# Fonts # if (DEFINED ENV{ESP_IDF_VERSION}) GET_PROPERTY_FILE_CONTENT("${CMAKE_CURRENT_LIST_DIR}/../sdkconfig" sdkconfig_text) - GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_TERMINAL_FONT_SIZE" terminal_font_size) + GET_PROPERTY_VALUE(sdkconfig_text "CONFIG_TT_FONT_DEFAULT_SIZE" font_default_size) else () - # Default values for simulator - set(terminal_font_size 14) + # Default value for simulator + set(font_default_size 14) endif () -message("Terminal font size: ${terminal_font_size}") +message("Default font size: ${font_default_size}") target_compile_definitions(${COMPONENT_LIB} PUBLIC - "-DTT_TERMINAL_FONT_SIZE=${terminal_font_size}" - "-DTT_TERMINAL_FONT_SYMBOL=ibmplexmono_${terminal_font_size}_font" + "-DTT_FONT_DEFAULT_SIZE=${font_default_size}" ) diff --git a/Tactility/Fonts/AdwaitaMono-Regular.ttf b/Tactility/Fonts/AdwaitaMono-Regular.ttf new file mode 100644 index 000000000..89363f253 Binary files /dev/null and b/Tactility/Fonts/AdwaitaMono-Regular.ttf differ diff --git a/Tactility/Fonts/AdwaitaSans-Regular.ttf b/Tactility/Fonts/AdwaitaSans-Regular.ttf new file mode 100644 index 000000000..6fcafd9b0 Binary files /dev/null and b/Tactility/Fonts/AdwaitaSans-Regular.ttf differ diff --git a/Tactility/Fonts/generate.py b/Tactility/Fonts/generate.py new file mode 100644 index 000000000..27b0ddadb --- /dev/null +++ b/Tactility/Fonts/generate.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Generates the font resources: +- Data/system/fonts/AdwaitaSans.ttf: text font TTF subset with the supported characters +- Data/system/fonts/AdwaitaMono.ttf: monospace font TTF subset for the terminal (ASCII) +- Tactility/Private/Tactility/lvgl/FontVersions.h: versions of the subsets, for font cache invalidation + +The fonts are rasterized from the TTF subsets on device. The text fonts include every character of +their subset, so TEXT_CODEPOINT_RANGES determines the supported characters. + +Requires the fonttools package: pip install fonttools +""" +import os +import zlib + +from fontTools import subset +from fontTools.ttLib import TTFont +from fontTools.varLib import instancer + +# Variable font weight of the text font: 100 (Thin) to 900 (Black), 400 is Regular +TEXT_WEIGHT = 550 + +# Inclusive ranges +TEXT_CODEPOINT_RANGES = [ + (0x0020, 0x007E), # ASCII + (0x00A0, 0x00FF), # Latin-1 Supplement + (0x2010, 0x2027), # Dashes, quotes, bullet, ellipsis + (0x2030, 0x203A), # Per mille, primes, angle quotes + (0x20AC, 0x20AC), # Euro sign +] + +MONO_CODEPOINT_RANGES = [ + (0x0020, 0x007E), # ASCII +] + +base_dir = os.path.dirname(os.path.abspath(__file__)) +output_dir = os.path.join(base_dir, "..", "..", "Data", "system", "fonts") +version_header_path = os.path.join(base_dir, "..", "Private", "Tactility", "lvgl", "FontVersions.h") + +def generate_subset(source_file: str, output_file: str, codepoint_ranges: list, weight=None) -> int: + """Writes a TTF subset and returns its version (crc32)""" + output_path = os.path.join(output_dir, output_file) + print(f"Generating {output_path}") + font = TTFont(os.path.join(base_dir, source_file), recalcTimestamp=False) + if "fvar" in font: + # Pin the weight axis and all other axes to their defaults + axis_values = {axis.axisTag: None for axis in font["fvar"].axes} + if weight is not None: + axis_values["wght"] = weight + font = instancer.instantiateVariableFont(font, axis_values) + options = subset.Options() + options.layout_features = [] + options.drop_tables += ["GSUB", "GPOS", "GDEF"] + options.hinting = False + options.notdef_outline = True + subsetter = subset.Subsetter(options) + subsetter.populate(unicodes=[cp for first, last in codepoint_ranges for cp in range(first, last + 1)]) + subsetter.subset(font) + os.makedirs(output_dir, exist_ok=True) + font.save(output_path) + with open(output_path, "rb") as f: + return zlib.crc32(f.read()) & 0xFFFFFFFF + +text_version = generate_subset("AdwaitaSans-Regular.ttf", "AdwaitaSans.ttf", TEXT_CODEPOINT_RANGES, TEXT_WEIGHT) +mono_version = generate_subset("AdwaitaMono-Regular.ttf", "AdwaitaMono.ttf", MONO_CODEPOINT_RANGES) + +print(f"Generating {version_header_path}") +with open(version_header_path, "w") as f: + f.write("#pragma once\n\n") + f.write("// Generated by Tactility/Fonts/generate.py\n") + f.write("// The versions change whenever the TTF subsets change\n") + f.write(f"#define TT_TEXT_FONT_VERSION 0x{text_version:08X}u\n") + f.write(f"#define TT_MONO_FONT_VERSION 0x{mono_version:08X}u\n") diff --git a/Tactility/Include/Tactility/settings/AppearanceSettings.h b/Tactility/Include/Tactility/settings/AppearanceSettings.h new file mode 100644 index 000000000..437b590cd --- /dev/null +++ b/Tactility/Include/Tactility/settings/AppearanceSettings.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace tt::settings::appearance { + +struct AppearanceSettings { + /** Default text font size in pixels, or 0 for the device's default size */ + uint16_t fontSize = 0; + /** TrueType font for regular text, or empty for the system font */ + std::string regularFontPath; + /** TrueType font for monospace text, or empty for the system font */ + std::string monoFontPath; + + bool operator==(const AppearanceSettings&) const = default; +}; + +bool load(AppearanceSettings& settings); + +AppearanceSettings loadOrGetDefault(); + +bool save(const AppearanceSettings& settings); + +} diff --git a/Tactility/Include/Tactility/settings/LedStripSettings.h b/Tactility/Include/Tactility/settings/LedStripSettings.h index 035e0eb35..d7c587c94 100644 --- a/Tactility/Include/Tactility/settings/LedStripSettings.h +++ b/Tactility/Include/Tactility/settings/LedStripSettings.h @@ -14,7 +14,7 @@ enum class Pattern : uint8_t { struct LedStripSettings { bool enabled = true; Pattern pattern = Pattern::Alternating; - uint8_t brightness = 77; + uint8_t brightness = 24; uint8_t primaryPreset = 6; uint8_t secondaryPreset = 7; struct LedRgb primaryCustom { 255, 165, 0 }; //Orange diff --git a/Tactility/Kconfig b/Tactility/Kconfig index 50b032451..2c7866f10 100644 --- a/Tactility/Kconfig +++ b/Tactility/Kconfig @@ -28,48 +28,12 @@ menu "Tactility App" The applications that gives access to other application. This is the first thing that starts after the boot screen. The user can override it with a boot.properties file - config TT_TERMINAL_FONT_SIZE - int "Terminal font size" - default 14 - range 12 28 - help - Terminal font size in pixels - config TT_LVGL_FONT_SIZE_SMALL - int "Small font size" - default 10 - range 8 200 - help - Small font size in pixels - config TT_LVGL_FONT_SIZE_DEFAULT + config TT_FONT_DEFAULT_SIZE int "Default font size" default 14 - range 8 200 - help - Default font size in pixels - config TT_LVGL_FONT_SIZE_LARGE - int "Large font size" - default 18 - range 8 200 - help - Large font size in pixels - config TT_LVGL_STATUSBAR_ICON_SIZE - int "Statusbar icon size" - default 20 - range 0 200 - help - Statusbar icon size in pixels - config TT_LVGL_LAUNCHER_ICON_SIZE - int "Launcher icon size" - default 20 - range 0 200 - help - Launcher icon size in pixels - config TT_LVGL_SHARED_ICON_SIZE - int "Shared icon size" - default 16 - range 0 200 + range 10 32 help - Shared icon size in pixels + Default text font size in pixels. Other text and icon font sizes are derived from it. config TT_LVGL_STATUSBAR_COLORS_INVERTED bool "Statusbar colors inverted" default n diff --git a/Tactility/Private/Tactility/app/boot/BootScreen.h b/Tactility/Private/Tactility/app/boot/BootScreen.h index 6351b4f51..bb5c78131 100644 --- a/Tactility/Private/Tactility/app/boot/BootScreen.h +++ b/Tactility/Private/Tactility/app/boot/BootScreen.h @@ -3,6 +3,7 @@ #include #include +struct BinFont; struct Device; struct PixelBuffer; @@ -23,6 +24,8 @@ class BootScreen { /** Second hardware frame buffer, kept in sync with target */ PixelBuffer* secondFrameBuffer = nullptr; int bandHeight = 0; + /** Monospace font, loaded on the first show() with text */ + BinFont* textFont = nullptr; int logicalWidth() const { return (rotation % 2 == 0) ? panelWidth : panelHeight; } int logicalHeight() const { return (rotation % 2 == 0) ? panelHeight : panelWidth; } @@ -34,7 +37,7 @@ class BootScreen { /** @return false when there is no usable display */ bool begin(); - /** Releases the display, so LVGL can take over. */ + /** Releases the display and the font, so LVGL can take over. */ void end(); /** @return the smallest logical display dimension, or 0 when there is no display */ diff --git a/Tactility/Private/Tactility/app/files/View.h b/Tactility/Private/Tactility/app/files/View.h index 51c34a41b..6483cd6b6 100644 --- a/Tactility/Private/Tactility/app/files/View.h +++ b/Tactility/Private/Tactility/app/files/View.h @@ -55,6 +55,7 @@ class View final { void onNavigateUpPressed(); void onDirEntryPressed(uint32_t index); void onDirEntryLongPressed(int32_t index); + void onDirEntryKeyPressed(int32_t index, uint32_t key); void onRenamePressed(); void onDeletePressed(); void onNewFilePressed(); diff --git a/Tactility/Private/Tactility/app/terminal/TerminalRenderer.h b/Tactility/Private/Tactility/app/terminal/TerminalRenderer.h index b1552a261..b6e6ee297 100644 --- a/Tactility/Private/Tactility/app/terminal/TerminalRenderer.h +++ b/Tactility/Private/Tactility/app/terminal/TerminalRenderer.h @@ -5,6 +5,7 @@ #include +struct BinFont; struct Device; struct PixelBuffer; @@ -27,6 +28,12 @@ class TerminalRenderer { public: virtual ~TerminalRenderer() = default; + /** + * Sets the monospace font to draw with. The cell size is the advance width of 'M' by the font's + * line height. Must be called before begin(), and the font must outlive end(). + */ + void setFont(BinFont* font) { this->font = font; } + /** Allocates buffers. Glyphs are drawn at native size, never scaled. */ virtual bool begin(Device* display) = 0; @@ -162,8 +169,14 @@ class TerminalRenderer { int cols = 0; int rowCount = 0; - // Cell size on screen. Glyphs are drawn at native size, so this equals TT_TERMINAL_FONT_SYMBOL's - // glyph_width/glyph_height (see TerminalRenderer.cpp). + BinFont* font = nullptr; + /** Alpha (0-255) of each printable ASCII glyph, cellWidth x cellHeight per glyph */ + uint8_t* glyphMasks = nullptr; + + /** Rasterizes the printable ASCII glyphs into glyphMasks */ + bool createGlyphMasks(); + + // Cell size on screen. Glyphs are drawn at native size, so this is derived from the font metrics. int cellWidth = 0; int cellHeight = 0; diff --git a/Tactility/Private/Tactility/lvgl/FontCache.h b/Tactility/Private/Tactility/lvgl/FontCache.h new file mode 100644 index 000000000..223202bc2 --- /dev/null +++ b/Tactility/Private/Tactility/lvgl/FontCache.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +struct BinFont; + +namespace tt::lvgl { + +/** @return the path of a font file in the system partition */ +std::string getSystemFontPath(const char* fileName); + +/** @return 1 for monochrome displays, otherwise 4 when PSRAM is available, otherwise 2 */ +uint8_t getGeneratedFontBpp(); + +/** @return the cache file name for a generated font */ +std::string getCachedFontFileName(const char* prefix, const char* name, uint16_t size, uint8_t bpp, uint32_t version); + +/** Deletes the cached fonts that start with prefix, except for the ones in currentFileNames. */ +void deleteStaleCachedFonts(const char* prefix, const std::vector& currentFileNames); + +/** + * Opens a font from the font cache in the data path. When it's not cached, it's rasterized from + * the TTF and written to the cache. Without a data path, the font is only kept in memory. + * @param[in] fileName the cache file name, see getCachedFontFileName() + * @param[in] ttfPath the TrueType font to rasterize from + * @param[in] size font size in pixels + * @param[in] bpp bits per pixel + * @param[in] getCodepoints provides the codepoints to rasterize, only called when the font is generated. + * An empty list rasterizes every codepoint in the TTF. + * @return the font, or nullptr when it couldn't be loaded or generated + */ +BinFont* loadOrGenerateFont(const std::string& fileName, const std::string& ttfPath, uint16_t size, uint8_t bpp, const std::function()>& getCodepoints); + +/** + * Generates a font and writes it to the font cache, unless it's cached already. + * Without a data path there is no cache: the font is generated and discarded, to verify that it can be. + * @return false when the font couldn't be generated or written + */ +bool ensureCachedFont(const std::string& fileName, const std::string& ttfPath, uint16_t size, uint8_t bpp, const std::function()>& getCodepoints); + +/** @return a version for a font file that changes when the file is replaced, or 0 when it doesn't exist */ +uint32_t getFontFileVersion(const std::string& path); + +} diff --git a/Tactility/Private/Tactility/lvgl/FontSizes.h b/Tactility/Private/Tactility/lvgl/FontSizes.h new file mode 100644 index 000000000..527029b21 --- /dev/null +++ b/Tactility/Private/Tactility/lvgl/FontSizes.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include + +namespace tt::lvgl { + +/** @return the size in pixels of a text font, derived from the default font size */ +uint16_t getTextFontSize(uint16_t defaultSize, LvglFontSize fontSize); + +/** @return the size in pixels of an icon font, derived from the default font size */ +uint16_t getIconFontSize(uint16_t defaultSize, LvglIconFont iconFont); + +} diff --git a/Tactility/Private/Tactility/lvgl/FontVersions.h b/Tactility/Private/Tactility/lvgl/FontVersions.h new file mode 100644 index 000000000..b590152cd --- /dev/null +++ b/Tactility/Private/Tactility/lvgl/FontVersions.h @@ -0,0 +1,6 @@ +#pragma once + +// Generated by Tactility/Fonts/generate.py +// The versions change whenever the TTF subsets change +#define TT_TEXT_FONT_VERSION 0x53B8B701u +#define TT_MONO_FONT_VERSION 0x8A59431Du diff --git a/Tactility/Private/Tactility/lvgl/Fonts.h b/Tactility/Private/Tactility/lvgl/Fonts.h new file mode 100644 index 000000000..70fdeb5da --- /dev/null +++ b/Tactility/Private/Tactility/lvgl/Fonts.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +struct BinFont; + +namespace tt::lvgl { + +/** Determines all generated fonts: text, icon and monospace */ +struct FontConfiguration { + /** Default text font size in pixels, other font sizes are derived from it */ + uint16_t defaultSize; + /** TrueType font for regular text, or empty for the system font */ + std::string regularFontPath; + /** TrueType font for monospace text, or empty for the system font */ + std::string monoFontPath; + + bool operator==(const FontConfiguration&) const = default; +}; + +/** + * Fonts with more characters than this can take long to generate and use a lot of memory, as all + * characters of a TTF are rasterized. + */ +constexpr size_t LARGE_FONT_CHARACTER_COUNT = 1000; + +/** @return the number of characters in a TrueType font, or 0 when it can't be read */ +size_t getTtfCharacterCount(const std::string& path); + +/** @return the configuration from the appearance settings, with the device defaults for unset values */ +FontConfiguration loadFontConfiguration(); + +/** @return the configuration of the loaded fonts, or loadFontConfiguration() before fonts are loaded */ +FontConfiguration getFontConfiguration(); + +/** + * Generates the cached fonts for a configuration that aren't cached yet. Doesn't affect the loaded fonts. + * @return false when a font couldn't be generated, e.g. because a TTF file is invalid + */ +bool updateFontCache(const FontConfiguration& configuration); + +/** + * Loads the text and icon fonts for a configuration and registers them with lvgl-module, replacing + * the previously loaded fonts. Fonts that aren't cached are generated. A custom TTF that fails is + * replaced by the system font. Cached fonts of other configurations are deleted. + * LVGL must not be running. + */ +void loadFonts(const FontConfiguration& configuration); + +/** + * Loads the monospace font of the current configuration (ASCII), generating and caching it when needed. + * @return the font, to be released with binfont_close(), or nullptr when it couldn't be loaded + */ +BinFont* loadMonoFont(); + +} diff --git a/Tactility/Private/Tactility/lvgl/IconFonts.h b/Tactility/Private/Tactility/lvgl/IconFonts.h deleted file mode 100644 index 56da2d0fa..000000000 --- a/Tactility/Private/Tactility/lvgl/IconFonts.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace tt::lvgl { - -/** - * Loads the icon fonts and registers them with lvgl_set_icon_font(). - * A font is rasterized from the system TTF when it's not cached in the data path yet. - * Must be called before LVGL starts. - */ -void initIconFonts(); - -} diff --git a/Tactility/Source/InitApps.cpp b/Tactility/Source/InitApps.cpp index d4c568759..ec362a8b4 100644 --- a/Tactility/Source/InitApps.cpp +++ b/Tactility/Source/InitApps.cpp @@ -39,6 +39,7 @@ namespace app { namespace addgps { extern const ::AppManifest manifest; } namespace alertdialog { extern const ::AppManifest manifest; } namespace apphub { extern const ::AppManifest manifest; } + namespace appearancesettings { extern const ::AppManifest manifest; } namespace apphubdetails { extern const ::AppManifest manifest; } namespace apppackagedetails { extern const ::AppManifest manifest; } namespace applist { extern const ::AppManifest manifest; } @@ -115,6 +116,7 @@ static void registerInternalApps() { app_manager_add(&app::audiosettings::manifest); } if (device_exists_of_type(&DISPLAY_TYPE)) { + app_manager_add(&app::appearancesettings::manifest); app_manager_add(&app::display::manifest); } if (device_exists_of_type(&LED_STRIP_TYPE)) { diff --git a/Tactility/Source/app/AppGrid.cpp b/Tactility/Source/app/AppGrid.cpp index 6a53850b0..f81a38fc8 100644 --- a/Tactility/Source/app/AppGrid.cpp +++ b/Tactility/Source/app/AppGrid.cpp @@ -14,6 +14,8 @@ namespace { constexpr int32_t TILE_GAP = 6; constexpr uint32_t ICON_COLOR_SELECTED = 0x33BBFF; constexpr uint32_t ICON_COLOR_HIGHLIGHTED = 0xF876E9; +// Minimum label width, as a multiple of the label's font size +constexpr uint32_t MIN_LABEL_WIDTH_IN_FONT_SIZES = 6; struct PageLayout { int32_t iconSize; @@ -29,7 +31,9 @@ PageLayout computePageLayout(lv_obj_t* grid) { const auto pad = icon_size / 16; const auto gap = TILE_GAP; const auto text_height = lv_font_get_line_height(lvgl_get_text_font(FONT_SIZE_SMALL)); - const auto tile_min_width = 2 * icon_size + 2 * pad; + // The label needs room for a few characters, also when the icon font is smaller (e.g. a fallback) + const auto text_min_width = static_cast(MIN_LABEL_WIDTH_IN_FONT_SIZES * lvgl_get_text_font_height(FONT_SIZE_SMALL)); + const auto tile_min_width = std::max(2 * icon_size, text_min_width) + 2 * pad; const auto tile_height = 2 * pad + icon_size + pad / 2 + text_height; const auto available_width = lv_obj_get_content_width(grid); const auto available_height = lv_obj_get_content_height(grid); diff --git a/Tactility/Source/app/appearancesettings/AppearanceSettings.cpp b/Tactility/Source/app/appearancesettings/AppearanceSettings.cpp new file mode 100644 index 000000000..0c64cf4b2 --- /dev/null +++ b/Tactility/Source/app/appearancesettings/AppearanceSettings.cpp @@ -0,0 +1,485 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace tt::app::appearancesettings { + +constexpr auto* TAG = "AppearanceSettings"; + +extern const ::AppManifest manifest; + +namespace { + +constexpr uint16_t MIN_FONT_SIZE = 10; +constexpr uint16_t MAX_FONT_SIZE = 32; +constexpr size_t APPLY_THREAD_STACK_SIZE = 8192; + +enum class FontSlot { + Regular, + Mono +}; + +struct FontRowWidgets { + lv_obj_t* defaultButton = nullptr; + lv_obj_t* fileLabel = nullptr; + lv_obj_t* warningLabel = nullptr; +}; + +struct Context { + uint32_t appInstanceId = 0; + TaskEventGroup* eventGroup = nullptr; + uint32_t selectRegularBit = 0; + uint32_t selectMonoBit = 0; + uint32_t applyBit = 0; + uint32_t cacheUpdatedBit = 0; + + settings::appearance::AppearanceSettings savedSettings; + /** Accessed with the LVGL lock held */ + settings::appearance::AppearanceSettings pendingSettings; + /** Characters in the pending font files, accessed with the LVGL lock held */ + size_t regularCharacterCount = 0; + size_t monoCharacterCount = 0; + bool applyFailed = false; + std::atomic applying = false; + + Thread* applyThread = nullptr; + lvgl::FontConfiguration applyConfiguration; + std::atomic cacheUpdateSucceeded = false; + + uint32_t selectLaunchId = 0; + FontSlot selectSlot = FontSlot::Regular; + AppStream selectStream {}; + uint8_t selectBuffer[256] {}; + + // Valid while the window is shown + lv_obj_t* applyButton = nullptr; + lv_obj_t* spinner = nullptr; + FontRowWidgets regularRow; + FontRowWidgets monoRow; + lv_obj_t* errorLabel = nullptr; +}; + +lvgl::FontConfiguration toFontConfiguration(const settings::appearance::AppearanceSettings& settings) { + return { + .defaultSize = settings.fontSize != 0 ? settings.fontSize : static_cast(TT_FONT_DEFAULT_SIZE), + .regularFontPath = settings.regularFontPath, + .monoFontPath = settings.monoFontPath, + }; +} + +std::string& getFontPath(settings::appearance::AppearanceSettings& settings, FontSlot slot) { + return slot == FontSlot::Regular ? settings.regularFontPath : settings.monoFontPath; +} + +size_t& getCharacterCount(Context* ctx, FontSlot slot) { + return slot == FontSlot::Regular ? ctx->regularCharacterCount : ctx->monoCharacterCount; +} + +size_t getCharacterCount(const std::string& path) { + return path.empty() ? 0 : lvgl::getTtfCharacterCount(path); +} + +void setHidden(lv_obj_t* object, bool hidden) { + if (hidden) { + lv_obj_add_flag(object, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_remove_flag(object, LV_OBJ_FLAG_HIDDEN); + } +} + +void updateFontRow(const FontRowWidgets& row, const std::string& path, size_t characterCount) { + lv_label_set_text(row.fileLabel, path.empty() ? "System font" : file::getLastPathSegment(path).c_str()); + setHidden(row.defaultButton, path.empty()); + const bool large = !path.empty() && characterCount > lvgl::LARGE_FONT_CHARACTER_COUNT; + if (large) { + lv_label_set_text(row.warningLabel, std::format("Contains {} characters: creating the fonts can take long and use a lot of memory.", characterCount).c_str()); + } + setHidden(row.warningLabel, !large); +} + +/** Updates the widgets to the pending settings. Requires the LVGL lock. */ +void updateWidgets(Context* ctx) { + if (ctx->applyButton == nullptr) { + return; + } + const bool applying = ctx->applying; + setHidden(ctx->applyButton, applying || ctx->pendingSettings == ctx->savedSettings); + setHidden(ctx->spinner, !applying); + updateFontRow(ctx->regularRow, ctx->pendingSettings.regularFontPath, ctx->regularCharacterCount); + updateFontRow(ctx->monoRow, ctx->pendingSettings.monoFontPath, ctx->monoCharacterCount); + setHidden(ctx->errorLabel, !ctx->applyFailed); +} + +void onBackPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + app_event_emit_close(ctx->appInstanceId); +} + +void onApplyPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + task_event_group_signal(ctx->eventGroup, ctx->applyBit); +} + +void onFontSizeChanged(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + auto* spinbox = static_cast(lv_event_get_target(event)); + const auto size = static_cast(lv_spinbox_get_value(spinbox)); + // The device's default size is stored as "unset", so it follows the device default + ctx->pendingSettings.fontSize = size == TT_FONT_DEFAULT_SIZE ? 0 : size; + updateWidgets(ctx); +} + +void onFontSizeDecrementPressed(lv_event_t* event) { + lv_spinbox_decrement(static_cast(lv_event_get_user_data(event))); +} + +void onFontSizeIncrementPressed(lv_event_t* event) { + lv_spinbox_increment(static_cast(lv_event_get_user_data(event))); +} + +lv_obj_t* createStepButton(lv_obj_t* parent, const char* symbol, lv_event_cb_t callback, lv_obj_t* spinbox) { + auto* button = lv_button_create(parent); + auto* label = lv_label_create(button); + lv_label_set_text(label, symbol); + lv_obj_center(label); + lv_obj_add_event_cb(button, callback, LV_EVENT_SHORT_CLICKED, spinbox); + lv_obj_add_event_cb(button, callback, LV_EVENT_LONG_PRESSED_REPEAT, spinbox); + return button; +} + +void onSelectRegularPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + task_event_group_signal(ctx->eventGroup, ctx->selectRegularBit); +} + +void onSelectMonoPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + task_event_group_signal(ctx->eventGroup, ctx->selectMonoBit); +} + +void onDefaultRegularPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + ctx->pendingSettings.regularFontPath.clear(); + ctx->regularCharacterCount = 0; + updateWidgets(ctx); +} + +void onDefaultMonoPressed(lv_event_t* event) { + auto* ctx = static_cast(lv_event_get_user_data(event)); + ctx->pendingSettings.monoFontPath.clear(); + ctx->monoCharacterCount = 0; + updateWidgets(ctx); +} + +lv_obj_t* createRow(lv_obj_t* parent) { + auto* row = lv_obj_create(parent); + lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(row, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_style_pad_all(row, 0, LV_STATE_DEFAULT); + // Room for the focus outline of the buttons, which is clipped to the row in compact mode + lv_obj_set_style_pad_ver(row, 3, LV_STATE_DEFAULT); + lv_obj_set_style_pad_hor(row, 3, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(row, 0, LV_STATE_DEFAULT); + lv_obj_remove_flag(row, LV_OBJ_FLAG_SCROLLABLE); + return row; +} + +lv_obj_t* createButton(lv_obj_t* parent, const char* text, lv_event_cb_t callback, Context* ctx) { + auto* button = lv_button_create(parent); + auto* label = lv_label_create(button); + lv_label_set_text(label, text); + lv_obj_add_event_cb(button, callback, LV_EVENT_SHORT_CLICKED, ctx); + return button; +} + +FontRowWidgets createFontRow(lv_obj_t* parent, const char* title, lv_event_cb_t onSelect, lv_event_cb_t onDefault, Context* ctx) { + FontRowWidgets widgets; + // "Title [Default]" + auto* title_row = createRow(parent); + auto* label = lv_label_create(title_row); + lv_label_set_text(label, title); + lv_obj_set_flex_grow(label, 1); + lv_obj_set_style_pad_ver(label, 0, LV_STATE_DEFAULT); + widgets.defaultButton = createButton(title_row, "Default", onDefault, ctx); + + // " file.ttf [Select]" + auto* file_row = createRow(parent); + widgets.fileLabel = lv_label_create(file_row); + lv_obj_set_flex_grow(widgets.fileLabel, 1); + lv_label_set_long_mode(widgets.fileLabel, LV_LABEL_LONG_MODE_DOTS); + lv_obj_set_style_pad_left(widgets.fileLabel, 12, LV_STATE_DEFAULT); + createButton(file_row, "Select", onSelect, ctx); + + widgets.warningLabel = lv_label_create(parent); + lv_obj_set_width(widgets.warningLabel, LV_PCT(100)); + lv_label_set_long_mode(widgets.warningLabel, LV_LABEL_LONG_MODE_WRAP); + lv_obj_set_style_text_color(widgets.warningLabel, lv_palette_main(LV_PALETTE_ORANGE), LV_STATE_DEFAULT); + return widgets; +} + +void createWidgets(lv_obj_t* parent, void* userData) { + auto* ctx = static_cast(userData); + lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT); + + auto* toolbar = lvgl_toolbar_create(parent, "Appearance"); + lvgl_toolbar_set_nav_action(toolbar, LV_SYMBOL_CLOSE, onBackPressed, ctx); + ctx->spinner = lvgl_toolbar_add_spinner_action(toolbar); + ctx->applyButton = lvgl_toolbar_add_image_button_action(toolbar, LV_SYMBOL_OK, onApplyPressed, ctx); + + auto* content = lv_obj_create(parent); + lv_obj_set_width(content, LV_PCT(100)); + lv_obj_set_flex_grow(content, 1); + lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_border_width(content, 0, LV_STATE_DEFAULT); + + auto* font_size_row = createRow(content); + auto* font_size_label = lv_label_create(font_size_row); + lv_label_set_text(font_size_label, "Font size"); + lv_obj_set_flex_grow(font_size_label, 1); + // [-] [size] [+] + auto* font_size_spinbox = lv_spinbox_create(font_size_row); + lv_spinbox_set_range(font_size_spinbox, MIN_FONT_SIZE, MAX_FONT_SIZE); + lv_spinbox_set_digit_format(font_size_spinbox, 2, 0); + lv_spinbox_set_step(font_size_spinbox, 1); + const uint16_t font_size = ctx->pendingSettings.fontSize != 0 ? ctx->pendingSettings.fontSize : static_cast(TT_FONT_DEFAULT_SIZE); + lv_spinbox_set_value(font_size_spinbox, font_size); + lv_obj_set_width(font_size_spinbox, lv_font_get_line_height(lv_obj_get_style_text_font(font_size_spinbox, LV_PART_MAIN)) * 3); + lv_obj_set_style_text_align(font_size_spinbox, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); + // The value is changed with the buttons, so the digit cursor isn't shown + lv_obj_set_style_bg_opa(font_size_spinbox, LV_OPA_TRANSP, LV_PART_CURSOR); + lv_obj_add_event_cb(font_size_spinbox, onFontSizeChanged, LV_EVENT_VALUE_CHANGED, ctx); + auto* decrement_button = createStepButton(font_size_row, LV_SYMBOL_MINUS, onFontSizeDecrementPressed, font_size_spinbox); + lv_obj_move_to_index(decrement_button, lv_obj_get_index(font_size_spinbox)); + createStepButton(font_size_row, LV_SYMBOL_PLUS, onFontSizeIncrementPressed, font_size_spinbox); + + ctx->regularRow = createFontRow(content, "Regular font", onSelectRegularPressed, onDefaultRegularPressed, ctx); + ctx->monoRow = createFontRow(content, "Mono font", onSelectMonoPressed, onDefaultMonoPressed, ctx); + + ctx->errorLabel = lv_label_create(content); + lv_obj_set_width(ctx->errorLabel, LV_PCT(100)); + lv_label_set_long_mode(ctx->errorLabel, LV_LABEL_LONG_MODE_WRAP); + lv_label_set_text(ctx->errorLabel, "Failed to create the fonts. Check that the selected files are TrueType fonts."); + lv_obj_set_style_text_color(ctx->errorLabel, lv_palette_main(LV_PALETTE_RED), LV_STATE_DEFAULT); + + updateWidgets(ctx); +} + +void destroyWidgets(void* userData) { + auto* ctx = static_cast(userData); + ctx->applyButton = nullptr; + ctx->spinner = nullptr; + ctx->regularRow = {}; + ctx->monoRow = {}; + ctx->errorLabel = nullptr; +} + +int32_t applyThreadMain(void* context) { + auto* ctx = static_cast(context); + ctx->cacheUpdateSucceeded = lvgl::updateFontCache(ctx->applyConfiguration); + task_event_group_signal(ctx->eventGroup, ctx->cacheUpdatedBit); + return 0; +} + +/** Ends an apply without a font error, keeping the changes pending */ +void cancelApply(Context* ctx) { + lvgl_lock(); + ctx->applying = false; + updateWidgets(ctx); + lvgl_unlock(); +} + +void startApply(Context* ctx) { + if (ctx->applying || ctx->applyThread != nullptr) { + return; + } + + lvgl_lock(); + ctx->applyConfiguration = toFontConfiguration(ctx->pendingSettings); + ctx->applying = true; + ctx->applyFailed = false; + updateWidgets(ctx); + lvgl_unlock(); + + ctx->applyThread = thread_alloc(); + if (ctx->applyThread == nullptr) { + LOG_E(TAG, "Failed to create thread"); + cancelApply(ctx); + return; + } + thread_set_name(ctx->applyThread, "font_cache"); + thread_set_stack_size(ctx->applyThread, APPLY_THREAD_STACK_SIZE); + thread_set_main_function(ctx->applyThread, applyThreadMain, ctx); + if (thread_start(ctx->applyThread) != ERROR_NONE) { + LOG_E(TAG, "Failed to start thread"); + thread_free(ctx->applyThread); + ctx->applyThread = nullptr; + cancelApply(ctx); + } +} + +void joinApplyThread(Context* ctx) { + if (ctx->applyThread != nullptr) { + thread_join(ctx->applyThread, portMAX_DELAY, pdMS_TO_TICKS(10)); + thread_free(ctx->applyThread); + ctx->applyThread = nullptr; + } +} + +void finishApply(Context* ctx) { + joinApplyThread(ctx); + + if (!ctx->cacheUpdateSucceeded) { + LOG_E(TAG, "Failed to update the font cache"); + lvgl_lock(); + ctx->applying = false; + ctx->applyFailed = true; + updateWidgets(ctx); + lvgl_unlock(); + return; + } + + lvgl_lock(); + const auto applied_settings = ctx->pendingSettings; + lvgl_unlock(); + if (!settings::appearance::save(applied_settings)) { + // Fonts that aren't saved would revert on the next boot: keep the changes pending for a retry + LOG_E(TAG, "Failed to save settings"); + cancelApply(ctx); + return; + } + lvgl_lock(); + ctx->savedSettings = applied_settings; + ctx->applying = false; + lvgl_unlock(); + + // The window is rebuilt from the saved settings when LVGL starts again + LOG_I(TAG, "Restarting LVGL with the new fonts"); + lvgl::stop(); + lvgl::loadFonts(ctx->applyConfiguration); + lvgl::start(); +} + +void startFileSelection(Context* ctx, FontSlot slot) { + if (ctx->selectLaunchId != 0 || ctx->applying) { + return; + } + ctx->selectSlot = slot; + ctx->selectLaunchId = fileselection::startForExistingFile(ctx->appInstanceId, ctx->selectStream, ctx->selectBuffer, sizeof(ctx->selectBuffer), ctx->eventGroup); +} + +void onFileSelectionResult(Context* ctx, const AppEvent& event) { + ctx->selectLaunchId = 0; + if (event.result.result == 0 /* Ok */) { + char path[sizeof(ctx->selectBuffer)]; + const size_t length = app_stream_read(&ctx->selectStream, path, sizeof(path)); + app_stream_unsubscribe(&ctx->selectStream); + if (length > 0) { + const auto selected_path = std::string(path, length); + const size_t character_count = getCharacterCount(selected_path); + lvgl_lock(); + getFontPath(ctx->pendingSettings, ctx->selectSlot) = selected_path; + getCharacterCount(ctx, ctx->selectSlot) = character_count; + updateWidgets(ctx); + lvgl_unlock(); + } + } else { + app_stream_unsubscribe(&ctx->selectStream); + } + app_manager_stop(event.result.launch_id); +} + +int32_t appMain(int argc, char* argv[]) { + Context ctx; + ctx.appInstanceId = app_scheduler_current_app_id(); + ctx.savedSettings = settings::appearance::loadOrGetDefault(); + ctx.pendingSettings = ctx.savedSettings; + ctx.regularCharacterCount = getCharacterCount(ctx.pendingSettings.regularFontPath); + ctx.monoCharacterCount = getCharacterCount(ctx.pendingSettings.monoFontPath); + + TaskEventGroup event_group {}; + task_event_group_construct(&event_group); + ctx.eventGroup = &event_group; + check(task_event_group_claim_bit(&event_group, &ctx.selectRegularBit) == ERROR_NONE); + check(task_event_group_claim_bit(&event_group, &ctx.selectMonoBit) == ERROR_NONE); + check(task_event_group_claim_bit(&event_group, &ctx.applyBit) == ERROR_NONE); + check(task_event_group_claim_bit(&event_group, &ctx.cacheUpdatedBit) == ERROR_NONE); + + AppEventSubscription sub {}; + check(app_event_subscribe(&sub, &event_group) == ERROR_NONE); + + WindowId window = window_manager_create_ext(ctx.appInstanceId, createWidgets, destroyWidgets, &ctx); + + bool should_close = false; + while (!should_close) { + uint32_t flags = 0; + task_event_group_wait_any(&event_group, &flags, portMAX_DELAY); + + if (flags & ctx.selectRegularBit) { + startFileSelection(&ctx, FontSlot::Regular); + } + if (flags & ctx.selectMonoBit) { + startFileSelection(&ctx, FontSlot::Mono); + } + if (flags & ctx.applyBit) { + startApply(&ctx); + } + if (flags & ctx.cacheUpdatedBit) { + finishApply(&ctx); + } + + AppEvent event {}; + while (app_event_poll(&sub, &event) == ERROR_NONE) { + if (event.type == APP_EVENT_CLOSE) { + should_close = true; + } else if (event.type == APP_EVENT_RESULT && event.result.launch_id == ctx.selectLaunchId) { + onFileSelectionResult(&ctx, event); + } + } + } + + // The thread uses the context + joinApplyThread(&ctx); + + window_manager_remove(window); + check(app_event_unsubscribe(&sub) == ERROR_NONE); + task_event_group_destruct(&event_group); + return 0; +} + +} // namespace + +extern const ::AppManifest manifest = { + .id = "tactility.appearance", + .name = "Appearance", + .category = APP_CATEGORY_SETTINGS, + .location = { APP_LOCATION_MEMORY, reinterpret_cast(appMain) }, + .flags = 0, + .stack = {} +}; + +} // namespace tt::app::appearancesettings diff --git a/Tactility/Source/app/apppackagelist/AppPackageList.cpp b/Tactility/Source/app/apppackagelist/AppPackageList.cpp index e7d416125..07de5951f 100644 --- a/Tactility/Source/app/apppackagelist/AppPackageList.cpp +++ b/Tactility/Source/app/apppackagelist/AppPackageList.cpp @@ -150,7 +150,7 @@ extern const ::AppManifest manifest = { .category = APP_CATEGORY_SETTINGS, .location = { .type = APP_LOCATION_MEMORY, .location = reinterpret_cast(appMain) }, .flags = 0, - .stack = { .depth = 2400, .desired_memory_capability = 0 }, + .stack = { .depth = 3072, .desired_memory_capability = 0 }, }; } // namespace diff --git a/Tactility/Source/app/boot/BootInit.cpp b/Tactility/Source/app/boot/BootInit.cpp index e4df53403..9238cfc74 100644 --- a/Tactility/Source/app/boot/BootInit.cpp +++ b/Tactility/Source/app/boot/BootInit.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -269,8 +269,8 @@ bool bootInit(TickType_t startTime) { return false; } - LOG_I(TAG, "Loading icon fonts"); - lvgl::initIconFonts(); + LOG_I(TAG, "Loading fonts"); + lvgl::loadFonts(lvgl::loadFontConfiguration()); screen.end(); diff --git a/Tactility/Source/app/boot/BootScreen.cpp b/Tactility/Source/app/boot/BootScreen.cpp index b7ef775bb..d04859156 100644 --- a/Tactility/Source/app/boot/BootScreen.cpp +++ b/Tactility/Source/app/boot/BootScreen.cpp @@ -2,7 +2,9 @@ #include -#include +#include + +#include #include #include @@ -20,7 +22,6 @@ namespace tt::app::boot { constexpr auto* TAG = "BootScreen"; constexpr int BAND_HEIGHT = 16; -constexpr uint16_t TEXT_COLOR = 0xFFFF; namespace { @@ -118,6 +119,10 @@ bool BootScreen::begin() { } void BootScreen::end() { + if (textFont != nullptr) { + binfont_close(textFont); + textFont = nullptr; + } pixel_buffer_free(target); pixel_buffer_free(secondFrameBuffer); target = nullptr; @@ -150,20 +155,36 @@ void BootScreen::show(const std::string& logoPath, const std::vector((reference.advance_x16 + 8) >> 4)) : 1; + const int line_height = has_font ? metrics.line_height : 0; const int logical_width = logicalWidth(); const int logical_height = logicalHeight(); - const size_t max_characters = std::max(1, logical_width / font.glyph_width - 2); std::vector wrapped_lines; - for (const auto& line : lines) { - wrapLine(line, max_characters, wrapped_lines); + if (has_font) { + const size_t max_characters = std::max(1, logical_width / character_width - 2); + for (const auto& line : lines) { + wrapLine(line, max_characters, wrapped_lines); + } } - const int text_height = static_cast(wrapped_lines.size()) * font.glyph_height; - const int gap = (logo.height > 0 && !wrapped_lines.empty()) ? font.glyph_height : 0; + const int text_height = static_cast(wrapped_lines.size()) * line_height; + const int gap = (logo.height > 0 && !wrapped_lines.empty()) ? line_height : 0; const int content_top = (logical_height - static_cast(logo.height) - gap - text_height) / 2; const int logo_left = (logical_width - static_cast(logo.width)) / 2; const int text_top = content_top + static_cast(logo.height) + gap; + std::vector glyph_bitmap; for (int band_top = 0; band_top < panelHeight; band_top += bandHeight) { const int band_rows = std::min(bandHeight, panelHeight - band_top); pixel_buffer_clear(target); @@ -197,20 +218,25 @@ void BootScreen::show(const std::string& logoPath, const std::vector(line.size()) * font.glyph_width) / 2; - const int line_top = text_top + static_cast(line_index) * font.glyph_height; + const int line_left = (logical_width - static_cast(line.size()) * character_width) / 2; + const int baseline = text_top + static_cast(line_index) * line_height + metrics.ascent; for (size_t character_index = 0; character_index < line.size(); character_index++) { - const auto character = static_cast(line[character_index]); - if (character < font.first_codepoint || character > font.last_codepoint) { + BinFontGlyph glyph; + if (!binfont_get_glyph(textFont, static_cast(line[character_index]), &glyph) || glyph.width == 0 || glyph.height == 0) { + continue; + } + glyph_bitmap.resize(static_cast(glyph.width) * glyph.height); + if (binfont_get_glyph_bitmap(textFont, &glyph, glyph_bitmap.data(), glyph.width) != ERROR_NONE) { continue; } - const uint8_t* glyph = &font.glyph_bitmap[(character - font.first_codepoint) * font.glyph_height * font.glyph_bytes_per_row]; - const int glyph_left = line_left + static_cast(character_index) * font.glyph_width; - for (int row = 0; row < font.glyph_height; row++) { - const uint8_t* bits = &glyph[row * font.glyph_bytes_per_row]; - for (int column = 0; column < font.glyph_width; column++) { - if (bits[column / 8] & (0x80U >> (column % 8))) { - plot(glyph_left + column, line_top + row, TEXT_COLOR, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + const int glyph_left = line_left + static_cast(character_index) * character_width + glyph.x; + const int glyph_top = baseline - glyph.y - glyph.height; + for (int row = 0; row < glyph.height; row++) { + for (int column = 0; column < glyph.width; column++) { + const uint8_t alpha = glyph_bitmap[row * glyph.width + column]; + if (alpha != 0) { + // White blended onto the black background + plot(glyph_left + column, glyph_top + row, toRgb565(alpha, alpha, alpha), PIXEL_BUFFER_CONVERSION_LUMA_THRESHOLD); } } } diff --git a/Tactility/Source/app/files/View.cpp b/Tactility/Source/app/files/View.cpp index 5c689e6c0..90e8840e4 100644 --- a/Tactility/Source/app/files/View.cpp +++ b/Tactility/Source/app/files/View.cpp @@ -59,6 +59,12 @@ static void onDirEntryLongPressedCallback(lv_event_t* event) { view->onDirEntryLongPressed(index); } +static void onDirEntryKeyCallback(lv_event_t* event) { + auto* view = static_cast(lv_event_get_user_data(event)); + auto* button = lv_event_get_target_obj(event); + view->onDirEntryKeyPressed(lv_obj_get_index(button), lv_event_get_key(event)); +} + static void onRenamePressedCallback(lv_event_t* event) { auto* view = static_cast(lv_event_get_user_data(event)); view->onRenamePressed(); @@ -353,6 +359,31 @@ void View::createDirEntryWidget(lv_obj_t* list, dirent& dir_entry) { lv_obj_t* button = lv_list_add_button(list, symbol, label_text.c_str()); lv_obj_add_event_cb(button, &onDirEntryPressedCallback, LV_EVENT_SHORT_CLICKED, this); lv_obj_add_event_cb(button, &onDirEntryLongPressedCallback, LV_EVENT_LONG_PRESSED, this); + lv_obj_add_event_cb(button, &onDirEntryKeyCallback, LV_EVENT_KEY, this); +} + +void View::onDirEntryKeyPressed(int32_t index, uint32_t key) { + // Keyboards report their delete key as either delete or backspace (e.g. Cardputer's "del" key) + const bool is_delete = key == LV_KEY_DEL || key == LV_KEY_BACKSPACE; + const bool is_rename = key == 'r' || key == 'R'; + if (!is_delete && !is_rename) { + return; + } + + dirent dir_entry; + if (!resolveDirentFromListIndex(index, dir_entry)) { + return; + } + // Same rules as the long-press actions: root entries are mount points, links have no actions + if (state->getCurrentPath() == "/" || dir_entry.d_type == file::TT_DT_LNK) { + return; + } + state->setSelectedChildEntry(dir_entry.d_name); + if (is_delete) { + onDeletePressed(); + } else { + onRenamePressed(); + } } void View::onBackPressed() { diff --git a/Tactility/Source/app/settings/Settings.cpp b/Tactility/Source/app/settings/Settings.cpp index f4b94d6e5..6c25f9be4 100644 --- a/Tactility/Source/app/settings/Settings.cpp +++ b/Tactility/Source/app/settings/Settings.cpp @@ -28,6 +28,7 @@ struct IconEntry { }; constexpr IconEntry ICONS[] = { + {"tactility.appearance", LVGL_ICON_SHARED_PALETTE}, {"tactility.apppackagelist", LVGL_ICON_SHARED_DEPLOYED_CODE}, {"tactility.audiosettings", LVGL_ICON_SHARED_MUSIC_NOTE}, {"tactility.btmanage", LVGL_ICON_SHARED_BLUETOOTH}, diff --git a/Tactility/Source/app/terminal/Terminal.cpp b/Tactility/Source/app/terminal/Terminal.cpp index c4c85591c..59d0183f1 100644 --- a/Tactility/Source/app/terminal/Terminal.cpp +++ b/Tactility/Source/app/terminal/Terminal.cpp @@ -4,6 +4,9 @@ #include #include #include +#include + +#include #include #include @@ -15,6 +18,7 @@ #include #include +#include #ifdef ESP_PLATFORM #include @@ -192,6 +196,13 @@ void runTerminal(Device* display, TerminalRenderer& renderer, bool touchToExit) KeyboardInput keyboards; TouchInput touch; + std::unique_ptr font(tt::lvgl::loadMonoFont(), binfont_close); + if (font == nullptr) { + LOG_E(TAG, "Failed to load font"); + return; + } + renderer.setFont(font.get()); + if (vterm_init() != ERROR_NONE) { LOG_E(TAG, "vterm_init failed"); return; diff --git a/Tactility/Source/app/terminal/TerminalRenderer.cpp b/Tactility/Source/app/terminal/TerminalRenderer.cpp index 7e7825ed3..7701aa1b4 100644 --- a/Tactility/Source/app/terminal/TerminalRenderer.cpp +++ b/Tactility/Source/app/terminal/TerminalRenderer.cpp @@ -2,23 +2,16 @@ #include -#include -#include - +#include #include -// The font struct to use, e.g. ibmplexmono_14_font (see font/fonts.h) - set per device/build via -// a compile definition; that font's Kconfig entry (Modules/graphics-module/Kconfig) must be enabled. -#ifndef TT_TERMINAL_FONT_SYMBOL -#error TT_TERMINAL_FONT_SYMBOL is not set -#endif - #include #include #include #include #include +#include extern "C" { #include @@ -38,6 +31,17 @@ inline uint16_t paletteColour(uint8_t index) { return vterm_get_palette()[index & 0x0F]; } +constexpr char FIRST_GLYPH = 0x20; +constexpr char LAST_GLYPH = 0x7E; + +uint16_t blendRgb565(uint16_t foreground, uint16_t background, uint8_t alpha) { + const uint32_t inverse = 255U - alpha; + const uint32_t r = (((foreground >> 11) & 0x1FU) * alpha + ((background >> 11) & 0x1FU) * inverse + 127U) / 255U; + const uint32_t g = (((foreground >> 5) & 0x3FU) * alpha + ((background >> 5) & 0x3FU) * inverse + 127U) / 255U; + const uint32_t b = ((foreground & 0x1FU) * alpha + (background & 0x1FU) * inverse + 127U) / 255U; + return static_cast((r << 11) | (g << 5) | b); +} + } // namespace bool TerminalRenderer::allocateCommon(Device* displayDevice) { @@ -48,8 +52,23 @@ bool TerminalRenderer::allocateCommon(Device* displayDevice, enum DisplayColorFo display = displayDevice; monochrome = display_get_color_format(display) == DISPLAY_COLOR_FORMAT_MONOCHROME; - cellWidth = TT_TERMINAL_FONT_SYMBOL.glyph_width; - cellHeight = TT_TERMINAL_FONT_SYMBOL.glyph_height; + if (font == nullptr) { + LOG_E(TAG, "No font set"); + return false; + } + BinFontMetrics metrics; + binfont_get_metrics(font, &metrics); + BinFontGlyph reference; + if (!binfont_get_glyph(font, 'M', &reference)) { + LOG_E(TAG, "Font has no 'M' glyph"); + return false; + } + cellWidth = static_cast((reference.advance_x16 + 8) >> 4); + cellHeight = metrics.line_height; + if (cellWidth <= 0 || cellHeight <= 0) { + LOG_E(TAG, "Invalid cell size %dx%d", cellWidth, cellHeight); + return false; + } cols = frameWidth / cellWidth; rowCount = frameHeight / cellHeight; @@ -83,6 +102,55 @@ bool TerminalRenderer::allocateCommon(Device* displayDevice, enum DisplayColorFo return false; } + if (!createGlyphMasks()) { + LOG_E(TAG, "Failed to rasterize glyphs"); + free(shadow); + shadow = nullptr; + pixel_buffer_free(frameBuffer); + frameBuffer = nullptr; + return false; + } + + return true; +} + +bool TerminalRenderer::createGlyphMasks() { + BinFontMetrics metrics; + binfont_get_metrics(font, &metrics); + const size_t mask_size = static_cast(cellWidth) * cellHeight; + glyphMasks = static_cast(calloc(static_cast(LAST_GLYPH - FIRST_GLYPH + 1), mask_size)); + if (glyphMasks == nullptr) { + return false; + } + + // Glyphs are cropped to their cell + std::vector bitmap; + for (char character = FIRST_GLYPH; character <= LAST_GLYPH; character++) { + BinFontGlyph glyph; + if (!binfont_get_glyph(font, static_cast(character), &glyph) || glyph.width == 0 || glyph.height == 0) { + continue; + } + bitmap.resize(static_cast(glyph.width) * glyph.height); + if (binfont_get_glyph_bitmap(font, &glyph, bitmap.data(), glyph.width) != ERROR_NONE) { + free(glyphMasks); + glyphMasks = nullptr; + return false; + } + uint8_t* mask = glyphMasks + (character - FIRST_GLYPH) * mask_size; + const int top = metrics.ascent - (glyph.y + glyph.height); + for (int row = 0; row < glyph.height; row++) { + const int cell_row = top + row; + if (cell_row < 0 || cell_row >= cellHeight) { + continue; + } + for (int column = 0; column < glyph.width; column++) { + const int cell_column = glyph.x + column; + if (cell_column >= 0 && cell_column < cellWidth) { + mask[cell_row * cellWidth + cell_column] = bitmap[row * glyph.width + column]; + } + } + } + } return true; } @@ -99,6 +167,8 @@ void TerminalRenderer::freeCommon() { fullFrameDirty = false; free(shadow); shadow = nullptr; + free(glyphMasks); + glyphMasks = nullptr; usingHwFrameBuffer = false; pixel_buffer_free(hwFrameBuffers[0]); pixel_buffer_free(hwFrameBuffers[1]); @@ -212,7 +282,16 @@ void TerminalRenderer::paintCell(int row, int col, char ch, uint8_t attr) { const int pixelY = originY + row * cellHeight - currentRowYOffset; const int pixelX = originX + col * cellWidth; - font_render_char_pixel_buffer_rgb565(frameBuffer, pixelX, pixelY, &TT_TERMINAL_FONT_SYMBOL, ch, fg, bg, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + // Characters without a glyph render as a space + const char glyph = (ch >= FIRST_GLYPH && ch <= LAST_GLYPH) ? ch : ' '; + const uint8_t* mask = glyphMasks + (glyph - FIRST_GLYPH) * cellWidth * cellHeight; + for (int y = 0; y < cellHeight; y++) { + for (int x = 0; x < cellWidth; x++) { + const uint8_t alpha = mask[y * cellWidth + x]; + const uint16_t colour = alpha == 0 ? bg : (alpha == 255 ? fg : blendRgb565(fg, bg, alpha)); + pixel_buffer_set_pixel_rgb565(frameBuffer, pixelX + x, pixelY + y, colour, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + } + } } void TerminalRenderer::paintCursor(int row, int col) { diff --git a/Tactility/Source/lvgl/FontCache.cpp b/Tactility/Source/lvgl/FontCache.cpp new file mode 100644 index 000000000..543ce6898 --- /dev/null +++ b/Tactility/Source/lvgl/FontCache.cpp @@ -0,0 +1,183 @@ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace tt::lvgl { + +constexpr auto* TAG = "FontCache"; + +/** @return the font cache directory, or an empty string when there is no data path */ +static const std::string& getCacheDirectory() { + static const std::string directory = [] { + char data_path[FILE_MAX_PATH_STRING_LENGTH]; + if (paths_get_data_path(data_path, sizeof(data_path)) != ERROR_NONE) { + LOG_W(TAG, "No data path available, generated fonts won't be cached"); + return std::string(); + } + auto path = std::format("{}/cache/fonts", data_path); + if (!file::findOrCreateDirectory(path, 0777)) { + LOG_W(TAG, "Failed to create %s", path.c_str()); + return std::string(); + } + return path; + }(); + return directory; +} + +std::string getSystemFontPath(const char* fileName) { + return std::format("{}/fonts/{}", file::MOUNT_POINT_SYSTEM, fileName); +} + +uint8_t getGeneratedFontBpp() { + Device* display = nullptr; + if (device_get_first_by_type(&DISPLAY_TYPE, &display) == ERROR_NONE) { + const bool monochrome = display_get_color_format(display) == DISPLAY_COLOR_FORMAT_MONOCHROME; + device_put(display); + if (monochrome) { + return 1; + } + } + return memory_external_total() > 0 ? 4 : 2; +} + +std::string getCachedFontFileName(const char* prefix, const char* name, uint16_t size, uint8_t bpp, uint32_t version) { + return std::format("{}{}_{}_{}bpp_{:08x}.bin", prefix, name, size, bpp, version); +} + +void deleteStaleCachedFonts(const char* prefix, const std::vector& currentFileNames) { + const auto& directory = getCacheDirectory(); + if (directory.empty()) { + return; + } + std::vector stale; + file::listDirectory(directory, [&](const dirent& entry) { + const std::string name = entry.d_name; + if (name.starts_with(prefix) && std::find(currentFileNames.begin(), currentFileNames.end(), name) == currentFileNames.end()) { + stale.push_back(name); + } + }); + for (const auto& name : stale) { + LOG_I(TAG, "Deleting stale %s", name.c_str()); + file::deleteFile(file::getChildPath(directory, name)); + } +} + +static bool writeCacheFile(const std::string& path, const uint8_t* data, size_t size) { + FILE* file = fopen(path.c_str(), "wb"); + bool written = file != nullptr && fwrite(data, 1, size, file) == size; + if (file != nullptr && fclose(file) != 0) { + LOG_W(TAG, "Failed to close %s", path.c_str()); + written = false; + } + if (!written) { + LOG_W(TAG, "Failed to write %s", path.c_str()); + file::deleteFile(path); + } + return written; +} + +/** Rasterizes a font, see binfont_generate() */ +static bool generateFont(const std::string& fileName, const std::string& ttfPath, uint16_t size, uint8_t bpp, const std::function()>& getCodepoints, uint8_t*& data, size_t& dataSize) { + const auto codepoints = getCodepoints(); + const BinFontGeneratorConfig config = { + .ttf_path = ttfPath.c_str(), + .size = size, + .bpp = bpp, + .codepoints = codepoints.empty() ? nullptr : codepoints.data(), + .codepoint_count = codepoints.size(), + }; + + const auto start_time = get_millis(); + const error_t error = binfont_generate(&config, &data, &dataSize); + if (error != ERROR_NONE) { + LOG_E(TAG, "Failed to generate %s from %s (%s)", fileName.c_str(), ttfPath.c_str(), error_to_string(error)); + return false; + } + LOG_I(TAG, "Generated %s (%zu bytes) in %zu ms", fileName.c_str(), dataSize, get_millis() - start_time); + return true; +} + +BinFont* loadOrGenerateFont(const std::string& fileName, const std::string& ttfPath, uint16_t size, uint8_t bpp, const std::function()>& getCodepoints) { + const auto& directory = getCacheDirectory(); + const auto cache_path = directory.empty() ? std::string() : file::getChildPath(directory, fileName); + + BinFont* font = nullptr; + if (!cache_path.empty() && file::isFile(cache_path)) { + if (binfont_open_file(cache_path.c_str(), &font) == ERROR_NONE) { + return font; + } + LOG_W(TAG, "Failed to open %s, regenerating", cache_path.c_str()); + } + + uint8_t* data = nullptr; + size_t data_size = 0; + if (!generateFont(fileName, ttfPath, size, bpp, getCodepoints, data, data_size)) { + return nullptr; + } + + if (!cache_path.empty()) { + writeCacheFile(cache_path, data, data_size); + } + + if (binfont_open_memory(data, data_size, true, &font) != ERROR_NONE) { + LOG_E(TAG, "Failed to open generated %s", fileName.c_str()); + return nullptr; + } + return font; +} + +bool ensureCachedFont(const std::string& fileName, const std::string& ttfPath, uint16_t size, uint8_t bpp, const std::function()>& getCodepoints) { + const auto& directory = getCacheDirectory(); + const auto cache_path = directory.empty() ? std::string() : file::getChildPath(directory, fileName); + if (!cache_path.empty() && file::isFile(cache_path)) { + return true; + } + + uint8_t* data = nullptr; + size_t data_size = 0; + if (!generateFont(fileName, ttfPath, size, bpp, getCodepoints, data, data_size)) { + return false; + } + // Without a cache, the font is only generated to verify that it can be + const bool written = cache_path.empty() || writeCacheFile(cache_path, data, data_size); + memory_free(data); + return written; +} + +uint32_t getFontFileVersion(const std::string& path) { + struct stat file_stat; + if (stat(path.c_str(), &file_stat) != 0) { + return 0; + } + // FNV-1a over the path, size and modification time + uint32_t hash = 2166136261u; + auto add = [&hash](const void* data, size_t size) { + const auto* bytes = static_cast(data); + for (size_t i = 0; i < size; i++) { + hash = (hash ^ bytes[i]) * 16777619u; + } + }; + add(path.data(), path.size()); + const auto file_size = static_cast(file_stat.st_size); + const auto modified = static_cast(file_stat.st_mtime); + add(&file_size, sizeof(file_size)); + add(&modified, sizeof(modified)); + return hash != 0 ? hash : 1; +} + +} diff --git a/Tactility/Source/lvgl/FontSizes.cpp b/Tactility/Source/lvgl/FontSizes.cpp new file mode 100644 index 000000000..ecf38cda1 --- /dev/null +++ b/Tactility/Source/lvgl/FontSizes.cpp @@ -0,0 +1,30 @@ +#include + +#include + +namespace tt::lvgl { + +static uint16_t scale(uint16_t size, float factor) { + return static_cast(std::lround(size * factor)); +} + +uint16_t getTextFontSize(uint16_t defaultSize, LvglFontSize fontSize) { + switch (fontSize) { + case FONT_SIZE_SMALL: return scale(defaultSize, 0.75f); + case FONT_SIZE_LARGE: return scale(defaultSize, 1.25f); + case FONT_SIZE_DEFAULT: + default: return defaultSize; + } +} + +uint16_t getIconFontSize(uint16_t defaultSize, LvglIconFont iconFont) { + switch (iconFont) { + case LVGL_ICON_FONT_LAUNCHER: return scale(defaultSize, 2.6f); + case LVGL_ICON_FONT_SHARED_2X: return getIconFontSize(defaultSize, LVGL_ICON_FONT_SHARED) * 2; + case LVGL_ICON_FONT_STATUSBAR: + case LVGL_ICON_FONT_SHARED: + default: return scale(defaultSize, 1.15f); + } +} + +} diff --git a/Tactility/Source/lvgl/Fonts.cpp b/Tactility/Source/lvgl/Fonts.cpp new file mode 100644 index 000000000..163bf0ce1 --- /dev/null +++ b/Tactility/Source/lvgl/Fonts.cpp @@ -0,0 +1,342 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace tt::lvgl { + +constexpr auto* TAG = "Fonts"; +constexpr auto* TEXT_CACHE_PREFIX = "text_"; +constexpr auto* MONO_CACHE_PREFIX = "mono_"; +constexpr auto* ICON_CACHE_PREFIX = "material_symbols_"; + +using CodepointProvider = std::function()>; + +/** A TTF and the codepoints to rasterize from it */ +struct FontSource { + std::string ttfPath; + uint32_t version; + /** An empty list rasterizes all codepoints of the TTF */ + CodepointProvider getCodepoints; + bool custom; +}; + +/** A font in the font cache */ +struct FontRequest { + std::string fileName; + std::string ttfPath; + uint16_t size; + uint8_t bpp; + CodepointProvider getCodepoints; +}; + +struct TextFontDefinition { + LvglFontSize id; + const char* name; +}; + +struct IconFontDefinition { + LvglIconFont id; + const char* name; + const char* const* iconNames; + size_t iconNameCount; +}; + +constexpr TextFontDefinition TEXT_FONTS[] = { + { FONT_SIZE_SMALL, "small" }, + { FONT_SIZE_DEFAULT, "default" }, + { FONT_SIZE_LARGE, "large" }, +}; + +static const IconFontDefinition ICON_FONTS[] = { + { LVGL_ICON_FONT_STATUSBAR, "statusbar", lvgl_icon_statusbar_names, lvgl_icon_statusbar_name_count }, + { LVGL_ICON_FONT_LAUNCHER, "launcher", lvgl_icon_launcher_names, lvgl_icon_launcher_name_count }, + { LVGL_ICON_FONT_SHARED, "shared", lvgl_icon_shared_names, lvgl_icon_shared_name_count }, + { LVGL_ICON_FONT_SHARED_2X, "shared2x", lvgl_icon_shared_names, lvgl_icon_shared_name_count }, +}; + +struct LoadedFont { + BinFont* binFont; + lv_font_t* lvFont; +}; + +/** ESP32 devices without PSRAM skip the large fonts to save memory */ +static bool hasLimitedMemory() { +#ifdef ESP_PLATFORM + return memory_external_total() == 0; +#else + return false; +#endif +} + +/** The default text font replaces the large one when it isn't generated */ +static bool isTextFontGenerated(LvglFontSize fontSize) { + return fontSize != FONT_SIZE_LARGE || !hasLimitedMemory(); +} + +/** The shared icon font replaces the 2x one when it isn't generated */ +static bool isIconFontGenerated(LvglIconFont iconFont) { + return iconFont != LVGL_ICON_FONT_SHARED_2X || !hasLimitedMemory(); +} + +static std::vector loadedFonts; +static std::optional activeConfiguration; + +static Mutex& getConfigurationMutex() { + static Mutex mutex = [] { + Mutex result; + mutex_construct(&result); + return result; + }(); + return mutex; +} + +size_t getTtfCharacterCount(const std::string& path) { + uint32_t* codepoints = nullptr; + size_t count = 0; + if (binfont_get_ttf_codepoints(path.c_str(), &codepoints, &count) != ERROR_NONE) { + return 0; + } + memory_free(codepoints); + return count; +} + +static FontSource getSystemSource(const char* systemFileName, uint32_t systemVersion) { + return { getSystemFontPath(systemFileName), systemVersion, [] { return std::vector(); }, false }; +} + +static FontSource getSource(const std::string& customPath, const char* systemFileName, uint32_t systemVersion) { + if (!customPath.empty()) { + const uint32_t version = getFontFileVersion(customPath); + if (version != 0) { + auto get_codepoints = [customPath] { + const size_t count = getTtfCharacterCount(customPath); + if (count > LARGE_FONT_CHARACTER_COUNT) { + LOG_W(TAG, "%s has %zu characters, generating it can take long and use a lot of memory", customPath.c_str(), count); + } + return std::vector(); + }; + return { customPath, version, get_codepoints, true }; + } + LOG_W(TAG, "%s not found, using the system font", customPath.c_str()); + } + return getSystemSource(systemFileName, systemVersion); +} + +static FontSource getTextSource(const FontConfiguration& configuration) { + return getSource(configuration.regularFontPath, "AdwaitaSans.ttf", TT_TEXT_FONT_VERSION); +} + +static FontSource getMonoSource(const FontConfiguration& configuration) { + return getSource(configuration.monoFontPath, "AdwaitaMono.ttf", TT_MONO_FONT_VERSION); +} + +static FontRequest getTextRequest(const FontConfiguration& configuration, const FontSource& source, const TextFontDefinition& definition, uint8_t bpp) { + const uint16_t size = getTextFontSize(configuration.defaultSize, definition.id); + return { getCachedFontFileName(TEXT_CACHE_PREFIX, definition.name, size, bpp, source.version), source.ttfPath, size, bpp, source.getCodepoints }; +} + +static FontRequest getMonoRequest(const FontConfiguration& configuration, const FontSource& source, uint8_t bpp) { + return { getCachedFontFileName(MONO_CACHE_PREFIX, "mono", configuration.defaultSize, bpp, source.version), source.ttfPath, configuration.defaultSize, bpp, source.getCodepoints }; +} + +/** Parses a .codepoints file: one " " pair per line */ +static std::unordered_map loadIconCodepoints() { + std::unordered_map codepoints; + file::readLines(getSystemFontPath("MaterialSymbolsRounded.codepoints"), true, [&codepoints](const char* line) { + const char* separator = strchr(line, ' '); + if (separator != nullptr) { + codepoints[std::string(line, separator - line)] = static_cast(strtoul(separator + 1, nullptr, 16)); + } + }); + return codepoints; +} + +static FontRequest getIconRequest(const FontConfiguration& configuration, const IconFontDefinition& definition, uint8_t bpp) { + const uint16_t size = getIconFontSize(configuration.defaultSize, definition.id); + auto get_codepoints = [&definition] { + static const auto codepoint_map = loadIconCodepoints(); + std::vector codepoints; + codepoints.reserve(definition.iconNameCount); + for (size_t i = 0; i < definition.iconNameCount; i++) { + const auto entry = codepoint_map.find(definition.iconNames[i]); + if (entry != codepoint_map.end()) { + codepoints.push_back(entry->second); + } else { + LOG_W(TAG, "No codepoint for icon %s", definition.iconNames[i]); + } + } + return codepoints; + }; + return { + getCachedFontFileName(ICON_CACHE_PREFIX, definition.name, size, bpp, LVGL_ICON_FONT_VERSION), + getSystemFontPath("MaterialSymbolsRounded.ttf"), + size, + bpp, + get_codepoints + }; +} + +static BinFont* load(const FontRequest& request) { + return loadOrGenerateFont(request.fileName, request.ttfPath, request.size, request.bpp, request.getCodepoints); +} + +static bool ensureCached(const FontRequest& request) { + return ensureCachedFont(request.fileName, request.ttfPath, request.size, request.bpp, request.getCodepoints); +} + +static lv_font_t* createLvglFont(BinFont* font) { + lv_font_t* lv_font = lvgl_binfont_create(font); + if (lv_font == nullptr) { + LOG_E(TAG, "Failed to create LVGL font"); + binfont_close(font); + return nullptr; + } + loadedFonts.push_back({ font, lv_font }); + return lv_font; +} + +static void unloadFonts() { + for (const auto& definition : TEXT_FONTS) { + lvgl_set_text_font(definition.id, nullptr, 0); + } + for (const auto& definition : ICON_FONTS) { + lvgl_set_icon_font(definition.id, nullptr, 0); + } + for (const auto& loaded : loadedFonts) { + lvgl_binfont_destroy(loaded.lvFont); + binfont_close(loaded.binFont); + } + loadedFonts.clear(); +} + +FontConfiguration loadFontConfiguration() { + const auto settings = settings::appearance::loadOrGetDefault(); + return { + .defaultSize = settings.fontSize != 0 ? settings.fontSize : static_cast(TT_FONT_DEFAULT_SIZE), + .regularFontPath = settings.regularFontPath, + .monoFontPath = settings.monoFontPath, + }; +} + +FontConfiguration getFontConfiguration() { + auto& mutex = getConfigurationMutex(); + mutex_lock(&mutex); + const std::optional active = activeConfiguration; + mutex_unlock(&mutex); + return active.has_value() ? *active : loadFontConfiguration(); +} + +bool updateFontCache(const FontConfiguration& configuration) { + const uint8_t bpp = getGeneratedFontBpp(); + + const auto text_source = getTextSource(configuration); + for (const auto& definition : TEXT_FONTS) { + if (isTextFontGenerated(definition.id) && !ensureCached(getTextRequest(configuration, text_source, definition, bpp))) { + return false; + } + } + for (const auto& definition : ICON_FONTS) { + if (isIconFontGenerated(definition.id) && !ensureCached(getIconRequest(configuration, definition, bpp))) { + return false; + } + } + return ensureCached(getMonoRequest(configuration, getMonoSource(configuration), bpp)); +} + +void loadFonts(const FontConfiguration& configuration) { + unloadFonts(); + const uint8_t bpp = getGeneratedFontBpp(); + + std::vector text_file_names; + const auto text_source = getTextSource(configuration); + for (const auto& definition : TEXT_FONTS) { + if (!isTextFontGenerated(definition.id)) { + continue; + } + auto request = getTextRequest(configuration, text_source, definition, bpp); + BinFont* font = load(request); + if (font == nullptr && text_source.custom) { + LOG_W(TAG, "Falling back to the system font for %s text", definition.name); + request = getTextRequest(configuration, getSystemSource("AdwaitaSans.ttf", TT_TEXT_FONT_VERSION), definition, bpp); + font = load(request); + } + if (font == nullptr) { + continue; + } + text_file_names.push_back(request.fileName); + lv_font_t* lv_font = createLvglFont(font); + if (lv_font != nullptr) { + // Glyphs that the font lacks, such as LV_SYMBOL_*, come from LVGL's built-in font + lv_font->fallback = LV_FONT_DEFAULT; + lvgl_set_text_font(definition.id, lv_font, request.size); + } + } + + if (!isTextFontGenerated(FONT_SIZE_LARGE)) { + lvgl_set_text_font(FONT_SIZE_LARGE, lvgl_get_text_font(FONT_SIZE_DEFAULT), lvgl_get_text_font_height(FONT_SIZE_DEFAULT)); + } + + std::vector icon_file_names; + for (const auto& definition : ICON_FONTS) { + if (!isIconFontGenerated(definition.id)) { + continue; + } + const auto request = getIconRequest(configuration, definition, bpp); + BinFont* font = load(request); + if (font == nullptr) { + continue; + } + icon_file_names.push_back(request.fileName); + lv_font_t* lv_font = createLvglFont(font); + if (lv_font != nullptr) { + lvgl_set_icon_font(definition.id, lv_font, request.size); + } + } + + if (!isIconFontGenerated(LVGL_ICON_FONT_SHARED_2X)) { + lvgl_set_icon_font(LVGL_ICON_FONT_SHARED_2X, lvgl_get_shared_icon_font(), lvgl_get_shared_icon_font_height()); + } + + deleteStaleCachedFonts(TEXT_CACHE_PREFIX, text_file_names); + deleteStaleCachedFonts(ICON_CACHE_PREFIX, icon_file_names); + deleteStaleCachedFonts(MONO_CACHE_PREFIX, { getMonoRequest(configuration, getMonoSource(configuration), bpp).fileName }); + + auto& mutex = getConfigurationMutex(); + mutex_lock(&mutex); + activeConfiguration = configuration; + mutex_unlock(&mutex); +} + +BinFont* loadMonoFont() { + const auto configuration = getFontConfiguration(); + const uint8_t bpp = getGeneratedFontBpp(); + const auto source = getMonoSource(configuration); + BinFont* font = load(getMonoRequest(configuration, source, bpp)); + if (font == nullptr && source.custom) { + LOG_W(TAG, "Falling back to the system monospace font"); + font = load(getMonoRequest(configuration, getSystemSource("AdwaitaMono.ttf", TT_MONO_FONT_VERSION), bpp)); + } + return font; +} + +} diff --git a/Tactility/Source/lvgl/IconFonts.cpp b/Tactility/Source/lvgl/IconFonts.cpp deleted file mode 100644 index 8505f99cc..000000000 --- a/Tactility/Source/lvgl/IconFonts.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace tt::lvgl { - -constexpr auto* TAG = "IconFonts"; -constexpr uint8_t ICON_FONT_BPP = 2; -constexpr auto* CACHE_FILE_PREFIX = "material_symbols_"; - -struct IconFontDefinition { - LvglIconFont id; - const char* name; - uint16_t size; - const char* const* iconNames; - size_t iconNameCount; -}; - -static std::string getSystemFontPath(const char* fileName) { - return std::format("{}/fonts/{}", file::MOUNT_POINT_SYSTEM, fileName); -} - -static std::string getCacheDirectory() { - char data_path[FILE_MAX_PATH_STRING_LENGTH]; - if (paths_get_data_path(data_path, sizeof(data_path)) != ERROR_NONE) { - return ""; - } - auto directory = std::format("{}/cache/fonts", data_path); - if (!file::findOrCreateDirectory(directory, 0777)) { - LOG_W(TAG, "Failed to create %s", directory.c_str()); - return ""; - } - return directory; -} - -static std::string getCacheFileName(const IconFontDefinition& definition) { - return std::format("{}{}_{}_{:08x}.bin", CACHE_FILE_PREFIX, definition.name, definition.size, LVGL_ICON_FONT_VERSION); -} - -static void deleteStaleCacheFiles(const std::string& directory, const std::vector& currentFileNames) { - std::vector stale; - file::listDirectory(directory, [&](const dirent& entry) { - const std::string name = entry.d_name; - if (name.starts_with(CACHE_FILE_PREFIX) && std::find(currentFileNames.begin(), currentFileNames.end(), name) == currentFileNames.end()) { - stale.push_back(name); - } - }); - for (const auto& name : stale) { - LOG_I(TAG, "Deleting stale %s", name.c_str()); - file::deleteFile(file::getChildPath(directory, name)); - } -} - -/** Parses a .codepoints file: one " " pair per line */ -static std::unordered_map loadCodepoints(const std::string& path) { - std::unordered_map codepoints; - file::readLines(path, true, [&codepoints](const char* line) { - const char* separator = strchr(line, ' '); - if (separator != nullptr) { - codepoints[std::string(line, separator - line)] = static_cast(strtoul(separator + 1, nullptr, 16)); - } - }); - return codepoints; -} - -static BinFont* generateFont(const IconFontDefinition& definition, const std::unordered_map& codepointMap, const std::string& cachePath) { - std::vector codepoints; - codepoints.reserve(definition.iconNameCount); - for (size_t i = 0; i < definition.iconNameCount; i++) { - const auto entry = codepointMap.find(definition.iconNames[i]); - if (entry != codepointMap.end()) { - codepoints.push_back(entry->second); - } else { - LOG_W(TAG, "No codepoint for icon %s", definition.iconNames[i]); - } - } - - const auto ttf_path = getSystemFontPath("MaterialSymbolsRounded.ttf"); - const BinFontGeneratorConfig config = { - .ttf_path = ttf_path.c_str(), - .size = definition.size, - .bpp = ICON_FONT_BPP, - .codepoints = codepoints.data(), - .codepoint_count = codepoints.size(), - }; - - const auto start_time = get_millis(); - uint8_t* data = nullptr; - size_t size = 0; - const error_t error = binfont_generate(&config, &data, &size); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to generate %s font from %s (%s)", definition.name, ttf_path.c_str(), error_to_string(error)); - return nullptr; - } - LOG_I(TAG, "Generated %s font (%zu bytes) in %zu ms", definition.name, size, get_millis() - start_time); - - if (!cachePath.empty()) { - FILE* file = fopen(cachePath.c_str(), "wb"); - const bool written = file != nullptr && fwrite(data, 1, size, file) == size; - if (file != nullptr && fclose(file) != 0) { - LOG_W(TAG, "Failed to close %s", cachePath.c_str()); - } - if (!written) { - LOG_W(TAG, "Failed to write %s", cachePath.c_str()); - file::deleteFile(cachePath); - } - } - - BinFont* font = nullptr; - if (binfont_open_memory(data, size, true, &font) != ERROR_NONE) { - LOG_E(TAG, "Failed to open generated %s font", definition.name); - return nullptr; - } - return font; -} - -void initIconFonts() { - const IconFontDefinition definitions[] = { - { LVGL_ICON_FONT_STATUSBAR, "statusbar", TT_LVGL_STATUSBAR_FONT_ICON_SIZE, lvgl_icon_statusbar_names, lvgl_icon_statusbar_name_count }, - { LVGL_ICON_FONT_LAUNCHER, "launcher", TT_LVGL_LAUNCHER_FONT_ICON_SIZE, lvgl_icon_launcher_names, lvgl_icon_launcher_name_count }, - { LVGL_ICON_FONT_SHARED, "shared", TT_LVGL_SHARED_FONT_ICON_SIZE, lvgl_icon_shared_names, lvgl_icon_shared_name_count }, - { LVGL_ICON_FONT_SHARED_2X, "shared2x", TT_LVGL_SHARED_FONT_ICON_2X_SIZE, lvgl_icon_shared_names, lvgl_icon_shared_name_count }, - }; - - const auto cache_directory = getCacheDirectory(); - if (cache_directory.empty()) { - LOG_W(TAG, "No data path available, icon fonts won't be cached"); - } else { - std::vector file_names; - for (const auto& definition : definitions) { - file_names.push_back(getCacheFileName(definition)); - } - deleteStaleCacheFiles(cache_directory, file_names); - } - - std::unordered_map codepoint_map; - for (const auto& definition : definitions) { - const auto cache_path = cache_directory.empty() ? std::string() : file::getChildPath(cache_directory, getCacheFileName(definition)); - - BinFont* font = nullptr; - if (!cache_path.empty() && file::isFile(cache_path)) { - if (binfont_open_file(cache_path.c_str(), &font) != ERROR_NONE) { - LOG_W(TAG, "Failed to open %s, regenerating", cache_path.c_str()); - font = nullptr; - } - } - - if (font == nullptr) { - if (codepoint_map.empty()) { - codepoint_map = loadCodepoints(getSystemFontPath("MaterialSymbolsRounded.codepoints")); - } - font = generateFont(definition, codepoint_map, cache_path); - if (font == nullptr) { - continue; - } - } - - lv_font_t* lv_font = lvgl_binfont_create(font); - if (lv_font == nullptr) { - LOG_E(TAG, "Failed to create LVGL font for %s", definition.name); - binfont_close(font); - continue; - } - lvgl_set_icon_font(definition.id, lv_font); - } -} - -} diff --git a/Tactility/Source/lvgl/Lvgl.cpp b/Tactility/Source/lvgl/Lvgl.cpp index 6bf3d4bc8..9a34ed553 100644 --- a/Tactility/Source/lvgl/Lvgl.cpp +++ b/Tactility/Source/lvgl/Lvgl.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -134,6 +135,10 @@ static void onLvglStarted() { auto displaySettings = settings::display::loadOrGetDefault(); lv_display_set_rotation(display, settings::display::toLvglDisplayRotation(displaySettings.orientation)); } + // The theme uses LVGL's built-in default font, the generated text font replaces it for every widget that inherits it + const lv_font_t* text_font = lvgl_get_text_font(FONT_SIZE_DEFAULT); + lv_obj_set_style_text_font(lv_screen_active(), text_font, LV_STATE_DEFAULT); + lv_obj_set_style_text_font(lv_layer_top(), text_font, LV_STATE_DEFAULT); lvgl_unlock(); window_manager_configure(windowManagerScreenInit); diff --git a/Tactility/Source/service/displayidle/MatrixRainScreensaver.cpp b/Tactility/Source/service/displayidle/MatrixRainScreensaver.cpp index d8eadd9f8..b113f1421 100644 --- a/Tactility/Source/service/displayidle/MatrixRainScreensaver.cpp +++ b/Tactility/Source/service/displayidle/MatrixRainScreensaver.cpp @@ -1,6 +1,9 @@ #ifdef ESP_PLATFORM #include "MatrixRainScreensaver.h" + +#include + #include #include #include @@ -71,7 +74,7 @@ void MatrixRainScreensaver::createRainCharLabels(RainChar& rc, int trailIndex, i rc.label = nullptr; return; } - lv_obj_set_style_text_font(rc.glowLabel, &lv_font_montserrat_14, 0); + lv_obj_set_style_text_font(rc.glowLabel, lvgl_get_text_font(FONT_SIZE_DEFAULT), 0); lv_obj_set_style_text_color(rc.glowLabel, lv_color_hex(COLOR_GLOW), 0); lv_obj_set_style_opa(rc.glowLabel, LV_OPA_70, 0); @@ -82,7 +85,7 @@ void MatrixRainScreensaver::createRainCharLabels(RainChar& rc, int trailIndex, i rc.glowLabel = nullptr; return; } - lv_obj_set_style_text_font(rc.label, &lv_font_montserrat_14, 0); + lv_obj_set_style_text_font(rc.label, lvgl_get_text_font(FONT_SIZE_DEFAULT), 0); lv_obj_set_style_text_color(rc.label, getTrailColor(trailIndex, trailLength), 0); char text[2] = {rc.ch, '\0'}; diff --git a/Tactility/Source/settings/AppearanceSettings.cpp b/Tactility/Source/settings/AppearanceSettings.cpp new file mode 100644 index 000000000..968fda084 --- /dev/null +++ b/Tactility/Source/settings/AppearanceSettings.cpp @@ -0,0 +1,69 @@ +#include + +#include +#include + +#include + +#include +#include + +namespace tt::settings::appearance { + +constexpr auto* SETTINGS_KEY_FONT_SIZE = "fontSize"; +constexpr auto* SETTINGS_KEY_REGULAR_FONT_PATH = "regularFontPath"; +constexpr auto* SETTINGS_KEY_MONO_FONT_PATH = "monoFontPath"; + +static std::string getSettingsFilePath() { + char path[256]; + if (app_paths_get_user_data_path("tactility.appearance", "appearance.properties", path, sizeof(path)) != ERROR_NONE) { + return ""; + } + return path; +} + +bool load(AppearanceSettings& settings) { + const auto settings_path = getSettingsFilePath(); + if (settings_path.empty() || !file::isFile(settings_path)) { + return false; + } + + std::map map; + if (!file::loadPropertiesFile(settings_path, map)) { + return false; + } + + settings = AppearanceSettings(); + if (const auto entry = map.find(SETTINGS_KEY_FONT_SIZE); entry != map.end()) { + settings.fontSize = static_cast(std::strtoul(entry->second.c_str(), nullptr, 10)); + } + if (const auto entry = map.find(SETTINGS_KEY_REGULAR_FONT_PATH); entry != map.end()) { + settings.regularFontPath = entry->second; + } + if (const auto entry = map.find(SETTINGS_KEY_MONO_FONT_PATH); entry != map.end()) { + settings.monoFontPath = entry->second; + } + return true; +} + +AppearanceSettings loadOrGetDefault() { + AppearanceSettings settings; + if (!load(settings)) { + settings = AppearanceSettings(); + } + return settings; +} + +bool save(const AppearanceSettings& settings) { + const auto settings_path = getSettingsFilePath(); + if (settings_path.empty() || !file::findOrCreateParentDirectory(settings_path, 0755)) { + return false; + } + std::map map; + map[SETTINGS_KEY_FONT_SIZE] = std::to_string(settings.fontSize); + map[SETTINGS_KEY_REGULAR_FONT_PATH] = settings.regularFontPath; + map[SETTINGS_KEY_MONO_FONT_PATH] = settings.monoFontPath; + return file::savePropertiesFile(settings_path, map); +} + +} diff --git a/Tactility/Tests/CMakeLists.txt b/Tactility/Tests/CMakeLists.txt index 418f4b9cd..cf77978fa 100644 --- a/Tactility/Tests/CMakeLists.txt +++ b/Tactility/Tests/CMakeLists.txt @@ -17,12 +17,13 @@ target_include_directories(TactilityTests PRIVATE ${DOCTESTINC}) target_include_directories(TactilityTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../Include) target_include_directories(TactilityTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../Private) -# TerminalRenderer*.cpp needs this; Tactility's own CMakeLists.txt derives it from sdkconfig, but -# this target only ever builds for the POSIX simulator (see Tests/tests.md), so it just hardcodes -# that same file's own POSIX default rather than reimplementing the sdkconfig lookup here too. +# Tactility's own CMakeLists.txt derives this from sdkconfig, but this target only ever builds for +# the POSIX simulator (see Tests/tests.md), so it just hardcodes that same file's own POSIX default +# rather than reimplementing the sdkconfig lookup here too. target_compile_definitions(TactilityTests PRIVATE - "-DTT_TERMINAL_FONT_SIZE=14" - "-DTT_TERMINAL_FONT_SYMBOL=ibmplexmono_14_font" + "-DTT_FONT_DEFAULT_SIZE=14" + "-DTACTILITY_TEST_DATA_DIR=\"${CMAKE_CURRENT_LIST_DIR}/../../Data\"" + "-DTACTILITY_TEST_FONTS_DIR=\"${CMAKE_CURRENT_LIST_DIR}/../Fonts\"" ) add_test(NAME TactilityTests COMMAND TactilityTests) diff --git a/Tactility/Tests/Source/FontsTest.cpp b/Tactility/Tests/Source/FontsTest.cpp new file mode 100644 index 000000000..8ae8e7f0c --- /dev/null +++ b/Tactility/Tests/Source/FontsTest.cpp @@ -0,0 +1,93 @@ +#include "doctest.h" + +#include + +#include +#include + +#include + +using namespace tt; + +namespace { + +/** System font paths are relative to the simulator's working directory, Data/ */ +class DataDirectory { + char previous[512] = {}; + +public: + DataDirectory() { + REQUIRE(getcwd(previous, sizeof(previous)) != nullptr); + REQUIRE(chdir(TACTILITY_TEST_DATA_DIR) == 0); + } + + ~DataDirectory() { chdir(previous); } +}; + +} // namespace + +TEST_CASE("loadMonoFont loads the system monospace font with the printable ASCII glyphs") { + DataDirectory data_directory; + BinFont* font = lvgl::loadMonoFont(); + REQUIRE(font != nullptr); + + BinFontMetrics metrics; + binfont_get_metrics(font, &metrics); + CHECK(metrics.line_height >= 14); + CHECK(metrics.line_height <= 20); + + BinFontGlyph reference; + REQUIRE(binfont_get_glyph(font, 'M', &reference)); + for (uint32_t codepoint = 0x20; codepoint <= 0x7E; codepoint++) { + CAPTURE(codepoint); + BinFontGlyph glyph; + REQUIRE(binfont_get_glyph(font, codepoint, &glyph)); + // Monospace: every glyph has the same advance + CHECK_EQ(glyph.advance_x16, reference.advance_x16); + } + + BinFontGlyph glyph; + CHECK_FALSE(binfont_get_glyph(font, 0xE9, &glyph)); + + binfont_close(font); +} + +TEST_CASE("updateFontCache and loadFonts use a custom regular font and size") { + DataDirectory data_directory; + const lvgl::FontConfiguration configuration = { + .defaultSize = 16, + .regularFontPath = TACTILITY_TEST_FONTS_DIR "/AdwaitaSans-Regular.ttf", + .monoFontPath = "", + }; + CHECK(lvgl::updateFontCache(configuration)); + + lvgl::loadFonts(configuration); + CHECK(lvgl::getFontConfiguration() == configuration); + CHECK_EQ(lvgl_get_text_font_height(FONT_SIZE_SMALL), 12); + CHECK_EQ(lvgl_get_text_font_height(FONT_SIZE_DEFAULT), 16); + CHECK_EQ(lvgl_get_text_font_height(FONT_SIZE_LARGE), 20); + CHECK(lvgl_get_text_font(FONT_SIZE_DEFAULT) != LV_FONT_DEFAULT); + CHECK_EQ(lvgl_get_shared_icon_font_height(), 18); + CHECK(lvgl_get_shared_icon_font() != LV_FONT_DEFAULT); + + // All characters of a custom TTF are rasterized, not just the ones of the system font + lv_font_glyph_dsc_t glyph; + CHECK(lv_font_get_glyph_dsc(lvgl_get_text_font(FONT_SIZE_DEFAULT), &glyph, 0x0416 /* Ж */, 0)); +} + +TEST_CASE("getTtfCharacterCount counts the characters of a TTF") { + DataDirectory data_directory; + CHECK(lvgl::getTtfCharacterCount(TACTILITY_TEST_FONTS_DIR "/AdwaitaSans-Regular.ttf") > lvgl::LARGE_FONT_CHARACTER_COUNT); + CHECK(lvgl::getTtfCharacterCount("system/fonts/AdwaitaSans.ttf") < lvgl::LARGE_FONT_CHARACTER_COUNT); + CHECK_EQ(lvgl::getTtfCharacterCount("system/fonts/missing.ttf"), 0); +} + +TEST_CASE("updateFontCache fails for a file that is not a TrueType font") { + DataDirectory data_directory; + const lvgl::FontConfiguration configuration = { + .defaultSize = 14, + .regularFontPath = "system/timezones.csv", + .monoFontPath = "", + }; + CHECK_FALSE(lvgl::updateFontCache(configuration)); +} diff --git a/device.py b/device.py index edec31043..75773ee85 100755 --- a/device.py +++ b/device.py @@ -268,15 +268,11 @@ def write_lvgl_variable_placeholders(output_file): output_file.write("CONFIG_LV_DPI_DEF=100\n") output_file.write("CONFIG_LV_FONT_MONTSERRAT_8=y\n") output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=8\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=8\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=8\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=12\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=30\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=12\n") - # Terminal fonts are currently tied to LVGL settings - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_12=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=12\n") + output_file.write("CONFIG_TT_FONT_DEFAULT_SIZE=8\n") + +def get_montserrat_size(font_size: int) -> int: + # LVGL's built-in Montserrat fonts exist in even sizes from 8 to 48 + return max(8, min(48, (font_size + 1) // 2 * 2)) def write_lvgl_variables(output_file, device_properties: dict): output_file.write("# LVGL\n") @@ -310,86 +306,14 @@ def write_lvgl_variables(output_file, device_properties: dict): output_file.write("CONFIG_LV_USE_THEME_SIMPLE=n\n") else: exit_with_error(f"Unknown theme: {theme}") - font_height_text = get_property_or_default(device_properties, "lvgl.fontSize", "14") - font_height = safe_int(font_height_text, f"Font height must be an integer, but was: '{font_height_text}'") - if font_height <= 12: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_12=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=12\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_8=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_12=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_16=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=8\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=12\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=16\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=12\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=30\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=12\n") - elif font_height <= 14: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_14=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=14\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_10=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_14=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_18=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=10\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=14\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=18\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=16\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=36\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=16\n") - elif font_height <= 16: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_16=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=16\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_12=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_16=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_22=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=12\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=16\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=22\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=16\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=42\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=16\n") - elif font_height <= 18: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_18=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=18\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_14=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_18=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_24=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=14\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=18\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=24\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=20\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=48\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=20\n") - elif font_height <= 24: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_24=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=24\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_18=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_24=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_30=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=18\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=24\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=30\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=20\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=64\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=24\n") - else: - output_file.write("CONFIG_TT_FONT_IBMPLEXMONO_28=y\n") - output_file.write("CONFIG_TT_TERMINAL_FONT_SIZE=28\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_20=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_28=y\n") - output_file.write("CONFIG_LV_FONT_MONTSERRAT_36=y\n") - output_file.write("CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28=y\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_SMALL=20\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_DEFAULT=28\n") - output_file.write("CONFIG_TT_LVGL_FONT_SIZE_LARGE=36\n") - output_file.write("CONFIG_TT_LVGL_STATUSBAR_ICON_SIZE=30\n") - output_file.write("CONFIG_TT_LVGL_LAUNCHER_ICON_SIZE=72\n") - output_file.write("CONFIG_TT_LVGL_SHARED_ICON_SIZE=32\n") + font_size_text = get_property_or_none(device_properties, "font.defaultSize") + if font_size_text is None: + font_size_text = get_property_or_default(device_properties, "lvgl.fontSize", "14") + font_size = safe_int(font_size_text, f"Font size must be an integer, but was: '{font_size_text}'") + output_file.write(f"CONFIG_TT_FONT_DEFAULT_SIZE={font_size}\n") + montserrat_size = get_montserrat_size(font_size) + output_file.write(f"CONFIG_LV_FONT_MONTSERRAT_{montserrat_size}=y\n") + output_file.write(f"CONFIG_LV_FONT_DEFAULT_MONTSERRAT_{montserrat_size}=y\n") def write_touch_calibration_variables(output_file, device_properties: dict): calibration_supported = get_property_or_none(device_properties, "touch.calibrationSupported") diff --git a/lv_conf.h b/lv_conf.h index 3ad79800c..a9f933c9d 100644 --- a/lv_conf.h +++ b/lv_conf.h @@ -367,11 +367,11 @@ /*Montserrat fonts with ASCII range and some symbols using bpp = 4 *https://fonts.google.com/specimen/Montserrat*/ #define LV_FONT_MONTSERRAT_8 0 -#define LV_FONT_MONTSERRAT_10 1 +#define LV_FONT_MONTSERRAT_10 0 #define LV_FONT_MONTSERRAT_12 0 #define LV_FONT_MONTSERRAT_14 1 #define LV_FONT_MONTSERRAT_16 0 -#define LV_FONT_MONTSERRAT_18 1 +#define LV_FONT_MONTSERRAT_18 0 #define LV_FONT_MONTSERRAT_20 0 #define LV_FONT_MONTSERRAT_22 0 #define LV_FONT_MONTSERRAT_24 0 diff --git a/partitions-16mb-no-sd-dev.csv b/partitions-16mb-no-sd-dev.csv index 503609ee2..d6fe4a7df 100644 --- a/partitions-16mb-no-sd-dev.csv +++ b/partitions-16mb-no-sd-dev.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 6M, -system, data, fat, , 128k, +system, data, fat, , 192k, data, data, fat, , 1000k, diff --git a/partitions-16mb-no-sd.csv b/partitions-16mb-no-sd.csv index 761e9f011..28ec04007 100644 --- a/partitions-16mb-no-sd.csv +++ b/partitions-16mb-no-sd.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 6M, -system, data, fat, , 128k, +system, data, fat, , 192k, data, data, fat, , 9800k, diff --git a/partitions-16mb-with-sd.csv b/partitions-16mb-with-sd.csv index 5da41e2b3..d4f56f9da 100644 --- a/partitions-16mb-with-sd.csv +++ b/partitions-16mb-with-sd.csv @@ -3,4 +3,4 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 6M, -system, data, fat, , 128k, +system, data, fat, , 192k, diff --git a/partitions-32mb-no-sd-dev.csv b/partitions-32mb-no-sd-dev.csv index 503609ee2..d6fe4a7df 100644 --- a/partitions-32mb-no-sd-dev.csv +++ b/partitions-32mb-no-sd-dev.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 6M, -system, data, fat, , 128k, +system, data, fat, , 192k, data, data, fat, , 1000k, diff --git a/partitions-32mb-no-sd.csv b/partitions-32mb-no-sd.csv index a4e7e15f8..b204a7f68 100644 --- a/partitions-32mb-no-sd.csv +++ b/partitions-32mb-no-sd.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 6M, -system, data, fat, , 128k, +system, data, fat, , 192k, data, data, fat, , 25M, diff --git a/partitions-4mb-with-sd.csv b/partitions-4mb-with-sd.csv index 5b9085582..475936d70 100644 --- a/partitions-4mb-with-sd.csv +++ b/partitions-4mb-with-sd.csv @@ -3,4 +3,4 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 3800k, -system, data, fat, , 128k, +system, data, fat, , 192k, diff --git a/partitions-8mb-no-sd-dev.csv b/partitions-8mb-no-sd-dev.csv index 2a508da19..37bf2e4a7 100644 --- a/partitions-8mb-no-sd-dev.csv +++ b/partitions-8mb-no-sd-dev.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 4M, -system, data, fat, , 128k, +system, data, fat, , 192k, data, data, fat, , 1000k, diff --git a/partitions-8mb-no-sd.csv b/partitions-8mb-no-sd.csv index 87c19cf6a..01b559389 100644 --- a/partitions-8mb-no-sd.csv +++ b/partitions-8mb-no-sd.csv @@ -3,5 +3,5 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 4M, -system, data, fat, , 128k, -data, data, fat, , 3800k, +system, data, fat, , 192k, +data, data, fat, , 3736k, diff --git a/partitions-8mb-with-sd.csv b/partitions-8mb-with-sd.csv index f5795298c..722a96baf 100644 --- a/partitions-8mb-with-sd.csv +++ b/partitions-8mb-with-sd.csv @@ -3,4 +3,4 @@ nvs, data, nvs, , 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, , 4M, -system, data, fat, , 128k, +system, data, fat, , 192k,