diff --git a/Buildscripts/sdkconfig/default.properties b/Buildscripts/sdkconfig-default.properties similarity index 99% rename from Buildscripts/sdkconfig/default.properties rename to Buildscripts/sdkconfig-default.properties index e9993bd35..3a6cdf62f 100644 --- a/Buildscripts/sdkconfig/default.properties +++ b/Buildscripts/sdkconfig-default.properties @@ -36,7 +36,7 @@ CONFIG_LV_USE_FS_STDIO=y CONFIG_LV_FS_STDIO_LETTER=65 CONFIG_LV_FS_STDIO_PATH="" CONFIG_LV_FS_STDIO_CACHE_SIZE=4096 -CONFIG_LV_USE_LODEPNG=y +CONFIG_LV_USE_LODEPNG=n CONFIG_LV_USE_BUILTIN_MALLOC=n # Routes lv_malloc/realloc/free through Modules/lvgl-module/source/lv_mem_custom.c, which prefers # PSRAM (falls back to internal RAM automatically) instead of a fixed-size pool or plain malloc. diff --git a/CMakeLists.txt b/CMakeLists.txt index f1fc9fa75..7c0a581f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,8 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION}) add_subdirectory(Libraries/minmea) add_subdirectory(Modules/lvgl-module) add_subdirectory(Modules/audio-decoder-module) + add_subdirectory(Modules/binfont-module) + add_subdirectory(Modules/lodepng-module) add_subdirectory(Modules/c-symbols-module) add_subdirectory(Modules/cjson-module) add_subdirectory(Modules/cpp-symbols-module) diff --git a/Data/system/app/Boot/assets/logo_large.png b/Data/system/app/Boot/assets/logo_large.png new file mode 100644 index 000000000..f3cc7819f Binary files /dev/null and b/Data/system/app/Boot/assets/logo_large.png differ diff --git a/Data/system/app/Boot/assets/logo_usb_large.png b/Data/system/app/Boot/assets/logo_usb_large.png new file mode 100644 index 000000000..96bba1f01 Binary files /dev/null and b/Data/system/app/Boot/assets/logo_usb_large.png differ diff --git a/Data/system/app/Boot/assets/logo_usb_small.png b/Data/system/app/Boot/assets/logo_usb_small.png new file mode 100644 index 000000000..8608c382a Binary files /dev/null and b/Data/system/app/Boot/assets/logo_usb_small.png differ diff --git a/Data/system/fonts/MaterialSymbolsRounded.codepoints b/Data/system/fonts/MaterialSymbolsRounded.codepoints new file mode 100644 index 000000000..19433809a --- /dev/null +++ b/Data/system/fonts/MaterialSymbolsRounded.codepoints @@ -0,0 +1,69 @@ +add e145 +app_registration ef40 +apps e5c3 +area_chart e770 +battery_android_frame_1 f257 +battery_android_frame_2 f256 +battery_android_frame_3 f255 +battery_android_frame_4 f254 +battery_android_frame_5 f253 +battery_android_frame_6 f252 +battery_android_frame_bolt f250 +battery_android_frame_full f24f +bluetooth e1a7 +bluetooth_connected e1a8 +bluetooth_disabled e1a9 +bluetooth_searching e60f +cable efe6 +calendar_month ebcc +camera e3af +check e668 +circle ef4a +close e5cd +cloud f15c +delete e92e +deployed_code f720 +devices e326 +display_settings eb97 +download f090 +edit_note e745 +electric_bolt ec1c +folder e2c7 +forum e8af +gamepad e30f +help e8fd +hub e9f4 +image e3f4 +keyboard_alt f028 +keyboard_arrow_up e316 +language ea07 +lightbulb e90f +lightstrip fff75 +lists e9b9 +location_on f1db +logo_dev ead6 +mail e159 +memory e322 +menu e5d2 +mop e28d +more_vert e5d4 +music_note e405 +navigation e55d +network_wifi_1_bar ebe4 +network_wifi_2_bar ebd6 +network_wifi_3_bar ebe1 +note_add e89c +power_settings_new f8c7 +refresh e5d5 +sd_card e623 +sd_card_alert f057 +search ef7a +settings e8b8 +signal_wifi_0_bar f0b0 +signal_wifi_4_bar f065 +signal_wifi_bad f064 +signal_wifi_off e1da +terminal eb8e +toolbar e9f7 +usb e1e0 +wifi e63e diff --git a/Data/system/fonts/MaterialSymbolsRounded.ttf b/Data/system/fonts/MaterialSymbolsRounded.ttf new file mode 100644 index 000000000..3be21646d Binary files /dev/null and b/Data/system/fonts/MaterialSymbolsRounded.ttf differ diff --git a/Data/system_sources/App Icons.svg b/Data/system_sources/App Icons.svg deleted file mode 100644 index 160d79e1a..000000000 --- a/Data/system_sources/App Icons.svg +++ /dev/null @@ -1,306 +0,0 @@ - -Android O icon templateVenceslas DUETA collection of keylines and guides used to make adaptive icons for android O2021-02-14Android Icon Adaptive Keylines diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_calculator.png b/Data/system_sources/Old Light Mode Icons/app_icon_calculator.png deleted file mode 100644 index 6500d82c7..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_calculator.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_chat.png b/Data/system_sources/Old Light Mode Icons/app_icon_chat.png deleted file mode 100644 index 69945f1d1..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_chat.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_display_settings.png b/Data/system_sources/Old Light Mode Icons/app_icon_display_settings.png deleted file mode 100644 index b92c3a653..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_display_settings.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_fallback.png b/Data/system_sources/Old Light Mode Icons/app_icon_fallback.png deleted file mode 100644 index b37a9039d..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_fallback.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_files.png b/Data/system_sources/Old Light Mode Icons/app_icon_files.png deleted file mode 100644 index 84949beda..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_files.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_gpio.png b/Data/system_sources/Old Light Mode Icons/app_icon_gpio.png deleted file mode 100644 index 962093a4a..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_gpio.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_i2c.png b/Data/system_sources/Old Light Mode Icons/app_icon_i2c.png deleted file mode 100644 index 3969f4ae6..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_i2c.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_notes.png b/Data/system_sources/Old Light Mode Icons/app_icon_notes.png deleted file mode 100644 index fce91d6c8..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_notes.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_power_settings.png b/Data/system_sources/Old Light Mode Icons/app_icon_power_settings.png deleted file mode 100644 index 41ba02daa..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_power_settings.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_settings.png b/Data/system_sources/Old Light Mode Icons/app_icon_settings.png deleted file mode 100644 index 83554ccd3..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_settings.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_system_info.png b/Data/system_sources/Old Light Mode Icons/app_icon_system_info.png deleted file mode 100644 index 8f85e639b..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_system_info.png and /dev/null differ diff --git a/Data/system_sources/Old Light Mode Icons/app_icon_time_date_settings.png b/Data/system_sources/Old Light Mode Icons/app_icon_time_date_settings.png deleted file mode 100644 index ea0be2846..000000000 Binary files a/Data/system_sources/Old Light Mode Icons/app_icon_time_date_settings.png and /dev/null differ diff --git a/Data/system_sources/Statusbar Battery.kra b/Data/system_sources/Statusbar Battery.kra deleted file mode 100644 index 13249f3a3..000000000 Binary files a/Data/system_sources/Statusbar Battery.kra and /dev/null differ diff --git a/Data/system_sources/Statusbar sdcard.kra b/Data/system_sources/Statusbar sdcard.kra deleted file mode 100644 index ca75f74fa..000000000 Binary files a/Data/system_sources/Statusbar sdcard.kra and /dev/null differ diff --git a/Data/system_sources/app/Launcher/apps.svg b/Data/system_sources/app/Launcher/apps.svg deleted file mode 100644 index 3d4efc504..000000000 --- a/Data/system_sources/app/Launcher/apps.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/app/Launcher/folder.svg b/Data/system_sources/app/Launcher/folder.svg deleted file mode 100644 index 298363eeb..000000000 --- a/Data/system_sources/app/Launcher/folder.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/app/Launcher/settings.svg b/Data/system_sources/app/Launcher/settings.svg deleted file mode 100644 index 45925e903..000000000 --- a/Data/system_sources/app/Launcher/settings.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/app/TimeZone/search.svg b/Data/system_sources/app/TimeZone/search.svg deleted file mode 100644 index 11c909ddb..000000000 --- a/Data/system_sources/app/TimeZone/search.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/app/WifiManage/lock.svg b/Data/system_sources/app/WifiManage/lock.svg deleted file mode 100644 index 0711d52fd..000000000 --- a/Data/system_sources/app/WifiManage/lock.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/app/WifiManage/signal_medium.svg b/Data/system_sources/app/WifiManage/signal_medium.svg deleted file mode 100644 index b110e3915..000000000 --- a/Data/system_sources/app/WifiManage/signal_medium.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - diff --git a/Data/system_sources/app/WifiManage/signal_strong.svg b/Data/system_sources/app/WifiManage/signal_strong.svg deleted file mode 100644 index 4b4279b06..000000000 --- a/Data/system_sources/app/WifiManage/signal_strong.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - diff --git a/Data/system_sources/app/WifiManage/signal_weak.svg b/Data/system_sources/app/WifiManage/signal_weak.svg deleted file mode 100644 index 1890b0a18..000000000 --- a/Data/system_sources/app/WifiManage/signal_weak.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - diff --git a/Data/system_sources/app_icon_calculator.svg b/Data/system_sources/app_icon_calculator.svg deleted file mode 100644 index fc18d18c3..000000000 --- a/Data/system_sources/app_icon_calculator.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Data/system_sources/app_icon_chat.svg b/Data/system_sources/app_icon_chat.svg deleted file mode 100644 index d62f2916b..000000000 --- a/Data/system_sources/app_icon_chat.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Data/system_sources/app_icon_gpio.svg b/Data/system_sources/app_icon_gpio.svg deleted file mode 100644 index 650e5ba2c..000000000 --- a/Data/system_sources/app_icon_gpio.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Data/system_sources/app_icon_notes.svg b/Data/system_sources/app_icon_notes.svg deleted file mode 100644 index d5d7cc44e..000000000 --- a/Data/system_sources/app_icon_notes.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - note-line - - - \ No newline at end of file diff --git a/Data/system_sources/app_icon_time_date_settings.svg b/Data/system_sources/app_icon_time_date_settings.svg deleted file mode 100644 index 200affaac..000000000 --- a/Data/system_sources/app_icon_time_date_settings.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/location.svg b/Data/system_sources/location.svg deleted file mode 100644 index 97b675d47..000000000 --- a/Data/system_sources/location.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/Data/system_sources/wifi_off_white.svg b/Data/system_sources/wifi_off_white.svg deleted file mode 100644 index 2fe696b8e..000000000 --- a/Data/system_sources/wifi_off_white.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - diff --git a/Data/system_sources/wifi_scan_white.svg b/Data/system_sources/wifi_scan_white.svg deleted file mode 100644 index a3da6b29d..000000000 --- a/Data/system_sources/wifi_scan_white.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - diff --git a/Data/system_sources/wifi_signal_medium_white.svg b/Data/system_sources/wifi_signal_medium_white.svg deleted file mode 100644 index fb4692cf5..000000000 --- a/Data/system_sources/wifi_signal_medium_white.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - diff --git a/Data/system_sources/wifi_signal_strong_white.svg b/Data/system_sources/wifi_signal_strong_white.svg deleted file mode 100644 index 51b325cbe..000000000 --- a/Data/system_sources/wifi_signal_strong_white.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - diff --git a/Data/system_sources/wifi_signal_weak_white.svg b/Data/system_sources/wifi_signal_weak_white.svg deleted file mode 100644 index 2d9db58ec..000000000 --- a/Data/system_sources/wifi_signal_weak_white.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - diff --git a/Devices/m5stack-tab5/m5stack,tab5.dts b/Devices/m5stack-tab5/m5stack,tab5.dts index 59452d951..470bbd632 100644 --- a/Devices/m5stack-tab5/m5stack,tab5.dts +++ b/Devices/m5stack-tab5/m5stack,tab5.dts @@ -67,7 +67,7 @@ i2c_internal: i2c0 { compatible = "espressif,esp32-i2c-master"; port = ; - clock-frequency = <100000>; + clock-frequency = <400000>; pin-sda = <&gpio0 31 GPIO_FLAG_PULL_UP>; pin-scl = <&gpio0 32 GPIO_FLAG_PULL_UP>; diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 79bb1e8f5..28f10e2e2 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -32,7 +32,7 @@ - Improve Setup: Show "Step done" screen - Make it more clear to end-users that an SD card is required to run Tactility - Warn if file operations are done from prohibited tasks (e.g. lvgl task) -- stopAppFromToolbar() in Tactility.cpp stops the top-most app. Change it so the toolbar knows for which app id it is created, so it can rely on that. +- stopAppFromToolbar() in lvgl/Lvgl.cpp stops the top-most app. Change it so the toolbar knows for which app id it is created, so it can rely on that. - Consider not unpacking `.app` files and executing them directly. Might want to cache file offsets. Cache file must be pinned to app version. - lvgl-module's spinner relies on hard-coded spinner asset from Tactility main project. - esp_lvgl_port settings has a large stack size (~9kB) to fix stackoverflow when LVGL events (e.g. button click) do actions like file operations do actions like file operations. Can we reduce the callstack? diff --git a/Libraries/lv_screenshot/CMakeLists.txt b/Libraries/lv_screenshot/CMakeLists.txt index feee75d3b..4748ef560 100644 --- a/Libraries/lv_screenshot/CMakeLists.txt +++ b/Libraries/lv_screenshot/CMakeLists.txt @@ -5,7 +5,7 @@ if (DEFINED ENV{ESP_IDF_VERSION}) SRC_DIRS "Source/" INCLUDE_DIRS "Source/" PRIV_INCLUDE_DIRS "Private/" - REQUIRES lvgl + REQUIRES lvgl lodepng-module ) else() @@ -25,6 +25,6 @@ else() ) target_link_libraries(lv_screenshot - PUBLIC lvgl + PUBLIC lvgl lodepng-module ) endif() \ No newline at end of file diff --git a/Libraries/lv_screenshot/Source/save_png.c b/Libraries/lv_screenshot/Source/save_png.c index 3be555f79..5b89d4f09 100644 --- a/Libraries/lv_screenshot/Source/save_png.c +++ b/Libraries/lv_screenshot/Source/save_png.c @@ -1,11 +1,32 @@ -#include "src/libs/lodepng/lodepng.h" +#include "save_png.h" + +#include +#include bool lv_screenshot_save_png_file(const uint8_t* image, uint32_t w, uint32_t h, uint32_t bpp, const char* filename) { + unsigned char* png = NULL; + size_t png_size = 0; + unsigned error; if (bpp == 32) { - return lodepng_encode32_file(filename, image, w, h) == 0; + error = lodepng_encode32(&png, &png_size, image, w, h); } else if (bpp == 24) { - return lodepng_encode24_file(filename, image, w, h) == 0; + error = lodepng_encode24(&png, &png_size, image, w, h); } else { return false; } + if (error) { + lodepng_free(png); + return false; + } + + // Written through lv_fs, so LVGL drive letter paths ("A:...") work + bool success = false; + lv_fs_file_t file; + if (lv_fs_open(&file, filename, LV_FS_MODE_WR) == LV_FS_RES_OK) { + uint32_t written = 0; + success = lv_fs_write(&file, png, png_size, &written) == LV_FS_RES_OK && written == png_size; + lv_fs_close(&file); + } + lodepng_free(png); + return success; } diff --git a/Modules/binfont-module/CMakeLists.txt b/Modules/binfont-module/CMakeLists.txt new file mode 100644 index 000000000..c68445826 --- /dev/null +++ b/Modules/binfont-module/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.20) + +include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake") + +file(GLOB_RECURSE SOURCE_FILES "source/*.c*") + +list(APPEND REQUIRES_LIST + TactilityKernel + graphics-module +) + +tactility_add_module(binfont-module + SRCS ${SOURCE_FILES} + INCLUDE_DIRS include/ + PRIV_INCLUDE_DIRS private/ + REQUIRES ${REQUIRES_LIST} +) diff --git a/Modules/binfont-module/LICENSE-Apache-2.0.md b/Modules/binfont-module/LICENSE-Apache-2.0.md new file mode 100644 index 000000000..f5f4b8b5e --- /dev/null +++ b/Modules/binfont-module/LICENSE-Apache-2.0.md @@ -0,0 +1,195 @@ +Apache License +============== + +_Version 2.0, January 2004_ +_<>_ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, “control” means **(i)** the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the +outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising +permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +“Object” form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +“submitted” means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of +this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You +changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +_END OF TERMS AND CONDITIONS_ + +### APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets `[]` replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same “printed page” as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Modules/binfont-module/README.md b/Modules/binfont-module/README.md new file mode 100644 index 000000000..600974d6b --- /dev/null +++ b/Modules/binfont-module/README.md @@ -0,0 +1,14 @@ +# binfont-module + +Bitmap fonts in the [lv_font_conv](https://github.com/lvgl/lv_font_conv) binary format (`--format bin`), usable with and without LVGL. + +- ``: load fonts and decode glyphs +- ``: rasterize a TTF into the binary format on device +- ``: draw glyphs and text into a `PixelBuffer` + +For LVGL, see `lvgl_binfont_create()` in lvgl-module's ``. + +## License + +This module is licensed under the [Apache v2.0](LICENSE-Apache-2.0.md) license. +Uses [stb_truetype](https://github.com/nothings/stb) (public domain). diff --git a/Modules/binfont-module/include/binfont/binfont.h b/Modules/binfont-module/include/binfont/binfont.h new file mode 100644 index 000000000..019d84c90 --- /dev/null +++ b/Modules/binfont-module/include/binfont/binfont.h @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A bitmap font in the lv_font_conv binary format (lv_font_conv --format bin). + * Thread-safe: a font can be used from multiple tasks at the same time. + */ +struct BinFont; + +typedef struct BinFontMetrics { + /** Font size in pixels, as passed to the converter */ + uint16_t size; + /** Pixels above the baseline */ + int16_t ascent; + /** Pixels below the baseline (negative) */ + int16_t descent; + /** ascent - descent */ + uint16_t line_height; + /** Distance from the bottom of the line to the baseline (-descent) */ + int16_t base_line; + int16_t underline_position; + uint16_t underline_thickness; + /** Bits per pixel of the stored bitmaps (1-4) */ + uint8_t bpp; +} BinFontMetrics; + +typedef struct BinFontGlyph { + uint32_t glyph_id; + /** Horizontal advance in 1/16th pixels */ + uint32_t advance_x16; + /** Bounding box left, relative to the pen position */ + int16_t x; + /** Bounding box bottom, relative to the baseline (positive is up) */ + int16_t y; + uint16_t width; + uint16_t height; +} BinFontGlyph; + +/** + * @brief Opens a font file. + * The whole file is loaded into external memory (PSRAM) when available, otherwise into internal memory. + * When that allocation fails, only the lookup tables are loaded and glyph data is read from the file + * on demand: the file is opened and closed for every glyph lookup, unless it's kept open with + * binfont_begin()/binfont_end(). + * @param[in] path the file path + * @param[out] out the opened font + * @retval ERROR_NONE on success + * @retval ERROR_NOT_FOUND when the file can't be opened + * @retval ERROR_NOT_SUPPORTED when the file is not a valid or supported font + * @retval ERROR_OUT_OF_MEMORY when memory allocation failed + */ +error_t binfont_open_file(const char* path, struct BinFont** out); + +/** + * @brief Opens a font from memory. + * @param[in] data the font file contents, which must stay valid until binfont_close() + * @param[in] size the size of data in bytes + * @param[in] take_ownership when true, data is released with memory_free() by binfont_close() (also on failure) + * @param[out] out the opened font + * @retval ERROR_NONE on success + * @retval ERROR_NOT_SUPPORTED when the data is not a valid or supported font + * @retval ERROR_OUT_OF_MEMORY when memory allocation failed + */ +error_t binfont_open_memory(const void* data, size_t size, bool take_ownership, struct BinFont** out); + +/** Releases the font and all its resources. */ +void binfont_close(struct BinFont* font); + +/** + * @brief Keeps the font file open until the matching binfont_end(), so rendering many glyphs + * doesn't open and close the file for each of them. Calls can be nested and used from multiple tasks. + * Does nothing for fonts that are fully loaded in memory. + * @retval ERROR_NONE on success + * @retval ERROR_NOT_FOUND when the file can't be opened + */ +error_t binfont_begin(struct BinFont* font); + +/** Ends a binfont_begin() session. The file is closed when no sessions remain. */ +void binfont_end(struct BinFont* font); + +void binfont_get_metrics(const struct BinFont* font, BinFontMetrics* out); + +/** + * @param[in] font the font + * @param[in] codepoint the Unicode codepoint + * @param[out] out the glyph info + * @return false when the font has no glyph for this codepoint + */ +bool binfont_get_glyph(struct BinFont* font, uint32_t codepoint, BinFontGlyph* out); + +/** @return the kerning adjustment for a glyph pair in 1/16th pixels, or 0 when there is none */ +int32_t binfont_get_kerning_x16(struct BinFont* font, uint32_t left_glyph_id, uint32_t right_glyph_id); + +/** + * @brief Decodes a glyph bitmap as 8-bit alpha (0 = transparent, 255 = opaque). + * @param[in] font the font + * @param[in] glyph a glyph from binfont_get_glyph() + * @param[out] out the destination: glyph->height rows of glyph->width bytes + * @param[in] stride bytes per row in out (at least glyph->width) + * @retval ERROR_NONE on success + * @retval ERROR_INVALID_ARGUMENT when stride is too small + * @retval ERROR_RESOURCE when the glyph data can't be read + */ +error_t binfont_get_glyph_bitmap(struct BinFont* font, const BinFontGlyph* glyph, uint8_t* out, size_t stride); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/binfont-module/include/binfont/generator.h b/Modules/binfont-module/include/binfont/generator.h new file mode 100644 index 000000000..f25fc2a64 --- /dev/null +++ b/Modules/binfont-module/include/binfont/generator.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BinFontGeneratorConfig { + /** Path to a TrueType (.ttf) file */ + const char* ttf_path; + /** Font size in pixels (em height) */ + 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. */ + const uint32_t* codepoints; + size_t codepoint_count; +} BinFontGeneratorConfig; + +/** + * @brief Rasterizes a TrueType font into the lv_font_conv binary format. + * @param[in] config the generator configuration + * @param[out] out_data the generated font file contents, to be released with memory_free() + * @param[out] out_size the size of out_data in bytes + * @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_OUT_OF_MEMORY when memory allocation failed + */ +error_t binfont_generate(const BinFontGeneratorConfig* config, uint8_t** out_data, size_t* out_size); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/binfont-module/include/binfont/module.h b/Modules/binfont-module/include/binfont/module.h new file mode 100644 index 000000000..c47796938 --- /dev/null +++ b/Modules/binfont-module/include/binfont/module.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct Module binfont_module; + +#ifdef __cplusplus +} +#endif diff --git a/Modules/binfont-module/include/binfont/render.h b/Modules/binfont-module/include/binfont/render.h new file mode 100644 index 000000000..d3b703e14 --- /dev/null +++ b/Modules/binfont-module/include/binfont/render.h @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Alpha-blends one glyph over the existing pixels of a PixelBuffer. + * @param[out] buffer destination, in any pixel format + * @param[in] x pen position x + * @param[in] baseline_y pen position y (the baseline) + * @param[in] font the font + * @param[in] codepoint the Unicode codepoint + * @param[in] color glyph colour as RGB565 + * @param[in] conversion how colours reduce into the buffer's native format (see PixelBufferConversion) + * @return the horizontal advance in pixels, or 0 when the font has no glyph for the codepoint + */ +int binfont_draw_glyph_rgb565( + struct PixelBuffer* buffer, + int x, + int baseline_y, + struct BinFont* font, + uint32_t codepoint, + uint16_t color, + enum PixelBufferConversion conversion +); + +/** + * @brief Alpha-blends a UTF-8 string over the existing pixels of a PixelBuffer, applying kerning. + * @param[out] buffer destination, in any pixel format + * @param[in] x pen position x + * @param[in] baseline_y pen position y (the baseline) + * @param[in] font the font + * @param[in] text UTF-8 encoded, null-terminated text + * @param[in] color glyph colour as RGB565 + * @param[in] conversion how colours reduce into the buffer's native format (see PixelBufferConversion) + * @return the total advance in pixels + */ +int binfont_draw_text_rgb565( + struct PixelBuffer* buffer, + int x, + int baseline_y, + struct BinFont* font, + const char* text, + uint16_t color, + enum PixelBufferConversion conversion +); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/binfont-module/private/binfont_private.h b/Modules/binfont-module/private/binfont_private.h new file mode 100644 index 000000000..aca4b0d8c --- /dev/null +++ b/Modules/binfont-module/private/binfont_private.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Opens a font file without loading it into memory: only the lookup tables are loaded and + * glyph data is read from the file on demand. binfont_open_file() falls back to this when the file + * doesn't fit in memory. + */ +error_t binfont_open_file_streaming(const char* path, struct BinFont** out); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/binfont-module/private/stb_truetype.h b/Modules/binfont-module/private/stb_truetype.h new file mode 100644 index 000000000..90a5c2e2b --- /dev/null +++ b/Modules/binfont-module/private/stb_truetype.h @@ -0,0 +1,5079 @@ +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) Yakov Galka +// +// VERSION HISTORY +// +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start, last; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = (sy1 - sy0) * e->direction; + STBTT_assert(x >= 0 && x < len); + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, y_final, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; + + sign = e->direction; + + // area of the rectangle covered from sy0..y_crossing + area = sign * (y_crossing-sy0); + + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 + area += step; + } + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); + + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + + // the rest of the line is filled based on the total height of the line segment in this pixel + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + // distance from singular values (in the same units as the pixel grid) + const float eps = 1./1024, eps2 = eps*eps; + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 >= eps2) + precompute[i] = 1.0f / len2; + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear + if (STBTT_fabs(b) >= eps2) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Modules/binfont-module/source/binfont.cpp b/Modules/binfont-module/source/binfont.cpp new file mode 100644 index 000000000..732bea9c3 --- /dev/null +++ b/Modules/binfont-module/source/binfont.cpp @@ -0,0 +1,803 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace { + +constexpr size_t RECORD_HEADER_SIZE = 8; +constexpr size_t HEAD_MIN_SIZE = 48; +constexpr size_t CMAP_SUBTABLE_HEADER_SIZE = 16; +constexpr size_t GLYPH_HEADER_MAX_BYTES = 16; + +enum CmapFormat : uint8_t { + CMAP_FORMAT_0 = 0, + CMAP_FORMAT_SPARSE = 1, + CMAP_FORMAT_0_TINY = 2, + CMAP_FORMAT_SPARSE_TINY = 3, +}; + +enum Compression : uint8_t { + COMPRESSION_NONE = 0, + COMPRESSION_RLE_PREFILTER = 1, + COMPRESSION_RLE = 2, +}; + +uint16_t read_u16(const uint8_t* p) { + return static_cast(p[0] | (p[1] << 8)); +} + +int16_t read_i16(const uint8_t* p) { + return static_cast(read_u16(p)); +} + +uint32_t read_u32(const uint8_t* p) { + return static_cast(p[0]) | (static_cast(p[1]) << 8) | (static_cast(p[2]) << 16) | (static_cast(p[3]) << 24); +} + +bool has_marker(const uint8_t* record, const char* marker) { + return memcmp(record + 4, marker, 4) == 0; +} + +/** MSB-first bit reader. Bits past the end read as 0. */ +class BitReader { + const uint8_t* data; + size_t sizeBits; + size_t position; + +public: + BitReader(const uint8_t* data, size_t size, size_t bitOffset = 0) : data(data), sizeBits(size * 8), position(bitOffset) {} + + uint32_t read(uint8_t bits) { + uint32_t value = 0; + for (uint8_t i = 0; i < bits; i++) { + value <<= 1; + if (position < sizeBits) { + value |= (data[position >> 3] >> (7 - (position & 7))) & 1U; + } + position++; + } + return value; + } + + int32_t readSigned(uint8_t bits) { + if (bits == 0) { + return 0; + } + const uint32_t value = read(bits); + if (value & (1U << (bits - 1))) { + return static_cast(value | (~0U << bits)); + } + return static_cast(value); + } +}; + +/** Decoder for the modified I3BN RLE stream of lv_font_conv. */ +class RleReader { + enum class State { Single, Repeated, Counter }; + + BitReader& bits; + uint8_t bpp; + State state = State::Single; + bool first = true; + uint8_t previous = 0; + uint32_t count = 0; + + uint8_t readSingle() { + previous = static_cast(bits.read(bpp)); + state = State::Single; + return previous; + } + +public: + RleReader(BitReader& bits, uint8_t bpp) : bits(bits), bpp(bpp) {} + + uint8_t next() { + switch (state) { + case State::Single: { + const auto value = static_cast(bits.read(bpp)); + if (!first && value == previous) { + count = 0; + state = State::Repeated; + } + first = false; + previous = value; + return value; + } + case State::Repeated: { + count++; + if (bits.read(1) == 0) { + return readSingle(); + } + if (count == 11) { + count = bits.read(6); + if (count != 0) { + state = State::Counter; + } else { + return readSingle(); + } + } + return previous; + } + case State::Counter: + count--; + if (count == 0) { + return readSingle(); + } + return previous; + } + return 0; + } +}; + +struct Header { + uint16_t fontSize; + int16_t ascent; + int16_t descent; + uint16_t defaultAdvanceWidth; + uint16_t kerningScale; + uint8_t indexToLocFormat; + uint8_t glyphIdFormat; + uint8_t advanceWidthFormat; + uint8_t bpp; + uint8_t xyBits; + uint8_t whBits; + uint8_t advanceWidthBits; + uint8_t compression; + uint8_t subpixelMode; + int16_t underlinePosition; + uint16_t underlineThickness; +}; + +} // namespace + +struct BinFont { + Header header; + /** The whole file in memory mode, nullptr in stream mode */ + const uint8_t* data; + bool ownsData; + /** Stream mode only: the file path, and the file while it's open (guarded by mutex) */ + char* path; + FILE* file; + uint32_t sessionCount; + Mutex mutex; + /** Owned copy of the cmap/loca/kern records in stream mode */ + uint8_t* tables; + /** Each record pointer includes its 8-byte record header */ + const uint8_t* cmap; + size_t cmapSize; + const uint8_t* loca; + size_t locaSize; + uint32_t locaCount; + const uint8_t* kern; + size_t kernSize; + size_t glyfOffset; + size_t glyfSize; +}; + +namespace { + +bool read_at(BinFont* font, size_t offset, uint8_t* out, size_t size) { + if (fseek(font->file, static_cast(offset), SEEK_SET) != 0) { + return false; + } + return fread(out, 1, size, font->file) == size; +} + +bool parse_header(const uint8_t* record, size_t size, Header& header) { + if (size < HEAD_MIN_SIZE || !has_marker(record, "head")) { + return false; + } + header.fontSize = read_u16(record + 14); + header.ascent = read_i16(record + 16); + header.descent = read_i16(record + 18); + header.defaultAdvanceWidth = read_u16(record + 30); + header.kerningScale = read_u16(record + 32); + header.indexToLocFormat = record[34]; + header.glyphIdFormat = record[35]; + header.advanceWidthFormat = record[36]; + header.bpp = record[37]; + header.xyBits = record[38]; + header.whBits = record[39]; + header.advanceWidthBits = record[40]; + header.compression = record[41]; + header.subpixelMode = record[42]; + header.underlinePosition = read_i16(record + 44); + header.underlineThickness = read_u16(record + 46); + + return header.bpp >= 1 && header.bpp <= 4 && + header.compression <= COMPRESSION_RLE && + header.subpixelMode == 0 && + header.indexToLocFormat <= 1 && + header.xyBits <= 16 && header.whBits <= 16 && header.advanceWidthBits <= 32; +} + +bool validate_cmap(const uint8_t* cmap, size_t size) { + if (size < 12) { + return false; + } + const uint32_t count = read_u32(cmap + 8); + if (count > (size - 12) / CMAP_SUBTABLE_HEADER_SIZE) { + return false; + } + for (uint32_t i = 0; i < count; i++) { + const uint8_t* subtable = cmap + 12 + i * CMAP_SUBTABLE_HEADER_SIZE; + const size_t data_offset = read_u32(subtable); + const size_t range_length = read_u16(subtable + 8); + const size_t entries = read_u16(subtable + 12); + size_t data_size; + switch (subtable[14]) { + case CMAP_FORMAT_0: data_size = range_length; break; + case CMAP_FORMAT_SPARSE: data_size = entries * 4; break; + case CMAP_FORMAT_0_TINY: data_size = 0; break; + case CMAP_FORMAT_SPARSE_TINY: data_size = entries * 2; break; + default: return false; + } + if (data_size > 0 && (data_offset > size || data_size > size - data_offset)) { + return false; + } + } + return true; +} + +bool validate_kern(const uint8_t* kern, size_t size, uint8_t glyphIdFormat) { + if (size < 16) { + return false; + } + const uint8_t format = kern[8]; + if (format == 0) { + const size_t count = read_u32(kern + 12); + const size_t entry_size = (glyphIdFormat ? 4 : 2) + 1; + return count <= (size - 16) / entry_size; + } else if (format == 3) { + const size_t glyph_count = read_u16(kern + 12); + const size_t left_count = kern[14]; + const size_t right_count = kern[15]; + return 16 + glyph_count * 2 + left_count * right_count <= size; + } + return false; +} + +/** + * Locates all tables. In memory mode the table pointers point into font->data, in stream mode + * the lookup tables are copied into font->tables. + */ +error_t parse_layout(BinFont* font, size_t fileSize) { + uint8_t record_header[RECORD_HEADER_SIZE]; + uint8_t head[64]; + + auto read = [font](size_t offset, uint8_t* out, size_t size) { + if (font->data != nullptr) { + memcpy(out, font->data + offset, size); + return true; + } + return read_at(font, offset, out, size); + }; + + // head + if (fileSize < RECORD_HEADER_SIZE || !read(0, record_header, RECORD_HEADER_SIZE)) { + return ERROR_NOT_SUPPORTED; + } + const size_t head_size = read_u32(record_header); + if (head_size < HEAD_MIN_SIZE || head_size > fileSize) { + return ERROR_NOT_SUPPORTED; + } + if (!read(0, head, HEAD_MIN_SIZE) || !parse_header(head, HEAD_MIN_SIZE, font->header)) { + return ERROR_NOT_SUPPORTED; + } + + // cmap, loca, glyf and optionally kern follow each other + size_t offsets[4] = {}; + size_t sizes[4] = {}; + const char* markers[4] = { "cmap", "loca", "glyf", "kern" }; + size_t offset = head_size; + for (int i = 0; i < 4; i++) { + if (offset > fileSize || fileSize - offset < RECORD_HEADER_SIZE || !read(offset, record_header, RECORD_HEADER_SIZE)) { + if (i == 3) { + break; // kern is optional + } + return ERROR_NOT_SUPPORTED; + } + const size_t size = read_u32(record_header); + if (!has_marker(record_header, markers[i]) || size < RECORD_HEADER_SIZE || size > fileSize - offset) { + if (i == 3) { + break; + } + return ERROR_NOT_SUPPORTED; + } + offsets[i] = offset; + sizes[i] = size; + offset += size; + } + + font->glyfOffset = offsets[2]; + font->glyfSize = sizes[2]; + + if (font->data != nullptr) { + font->cmap = font->data + offsets[0]; + font->loca = font->data + offsets[1]; + font->kern = sizes[3] ? font->data + offsets[3] : nullptr; + } else { + font->tables = static_cast(memory_alloc(sizes[0] + sizes[1] + sizes[3])); + if (font->tables == nullptr) { + return ERROR_OUT_OF_MEMORY; + } + uint8_t* cursor = font->tables; + for (int i : { 0, 1, 3 }) { + if (sizes[i] > 0 && !read_at(font, offsets[i], cursor, sizes[i])) { + return ERROR_NOT_SUPPORTED; + } + cursor += sizes[i]; + } + font->cmap = font->tables; + font->loca = font->tables + sizes[0]; + font->kern = sizes[3] ? font->tables + sizes[0] + sizes[1] : nullptr; + } + font->cmapSize = sizes[0]; + font->locaSize = sizes[1]; + font->kernSize = sizes[3]; + + if (!validate_cmap(font->cmap, font->cmapSize)) { + return ERROR_NOT_SUPPORTED; + } + + if (font->locaSize < 12) { + return ERROR_NOT_SUPPORTED; + } + font->locaCount = read_u32(font->loca + 8); + const size_t loca_entry_size = font->header.indexToLocFormat ? 4 : 2; + if (font->locaCount > (font->locaSize - 12) / loca_entry_size) { + return ERROR_NOT_SUPPORTED; + } + + if (font->kern != nullptr && !validate_kern(font->kern, font->kernSize, font->header.glyphIdFormat)) { + font->kern = nullptr; + font->kernSize = 0; + } + + return ERROR_NONE; +} + +BinFont* create_font() { + auto* font = static_cast(memory_calloc(1, sizeof(BinFont))); + if (font != nullptr) { + mutex_construct(&font->mutex); + } + return font; +} + +uint32_t find_glyph_id(const BinFont* font, uint32_t codepoint) { + const uint8_t* cmap = font->cmap; + const uint32_t count = read_u32(cmap + 8); + + // Find the last subtable that starts at or before the codepoint + uint32_t low = 0; + uint32_t high = count; + while (low < high) { + const uint32_t mid = (low + high) / 2; + if (read_u32(cmap + 12 + mid * CMAP_SUBTABLE_HEADER_SIZE + 4) <= codepoint) { + low = mid + 1; + } else { + high = mid; + } + } + if (low == 0) { + return 0; + } + + const uint8_t* subtable = cmap + 12 + (low - 1) * CMAP_SUBTABLE_HEADER_SIZE; + const uint32_t data_offset = read_u32(subtable); + const uint32_t range_start = read_u32(subtable + 4); + const uint16_t range_length = read_u16(subtable + 8); + const uint16_t glyph_id_start = read_u16(subtable + 10); + const uint16_t entries = read_u16(subtable + 12); + const uint32_t relative = codepoint - range_start; + if (relative >= range_length) { + return 0; + } + + switch (subtable[14]) { + case CMAP_FORMAT_0: + return glyph_id_start + cmap[data_offset + relative]; + case CMAP_FORMAT_0_TINY: + return glyph_id_start + relative; + case CMAP_FORMAT_SPARSE: + case CMAP_FORMAT_SPARSE_TINY: { + const uint8_t* list = cmap + data_offset; + uint32_t list_low = 0; + uint32_t list_high = entries; + while (list_low < list_high) { + const uint32_t mid = (list_low + list_high) / 2; + const uint16_t value = read_u16(list + mid * 2); + if (value == relative) { + if (subtable[14] == CMAP_FORMAT_SPARSE_TINY) { + return glyph_id_start + mid; + } + return glyph_id_start + read_u16(list + entries * 2 + mid * 2); + } else if (value < relative) { + list_low = mid + 1; + } else { + list_high = mid; + } + } + return 0; + } + default: + return 0; + } +} + +/** Gets the offset and size of a glyph record, relative to the glyf data (after its record header). */ +bool get_glyph_location(const BinFont* font, uint32_t glyphId, size_t& offset, size_t& size) { + if (glyphId == 0 || glyphId >= font->locaCount) { + return false; + } + const uint8_t* entries = font->loca + 12; + auto entry = [&](uint32_t index) -> size_t { + return font->header.indexToLocFormat ? read_u32(entries + index * 4) : read_u16(entries + index * 2); + }; + const size_t start = entry(glyphId); + const size_t end = (glyphId + 1 < font->locaCount) ? entry(glyphId + 1) : font->glyfSize; + if (start < RECORD_HEADER_SIZE || end < start || end > font->glyfSize) { + return false; + } + offset = start; + size = end - start; + return true; +} + +/** Reads from the font file in stream mode. Outside of a session, the file is opened for this read only. */ +bool read_glyph_data(BinFont* font, size_t offset, uint8_t* out, size_t size) { + mutex_lock(&font->mutex); + const bool temporary = font->file == nullptr; + if (temporary) { + font->file = fopen(font->path, "rb"); + } + const bool success = font->file != nullptr && read_at(font, offset, out, size); + if (temporary && font->file != nullptr) { + fclose(font->file); + font->file = nullptr; + } + mutex_unlock(&font->mutex); + return success; +} + +/** + * Provides the record of a glyph. In memory mode it points into the font data, in stream mode it + * is read into buffer (bufferSize bytes) or, when that is too small, into an allocation returned + * via allocated (to be freed by the caller). + */ +bool get_glyph_record(BinFont* font, uint32_t glyphId, size_t maxSize, uint8_t* buffer, size_t bufferSize, const uint8_t*& record, size_t& size, uint8_t*& allocated) { + size_t offset; + allocated = nullptr; + if (!get_glyph_location(font, glyphId, offset, size)) { + return false; + } + if (font->data != nullptr) { + record = font->data + font->glyfOffset + offset; + return true; + } + + if (size > maxSize) { + size = maxSize; + } + uint8_t* target = buffer; + if (size > bufferSize) { + allocated = static_cast(memory_alloc(size)); + if (allocated == nullptr) { + return false; + } + target = allocated; + } + + const bool success = read_glyph_data(font, font->glyfOffset + offset, target, size); + + if (!success) { + memory_free(allocated); + allocated = nullptr; + return false; + } + record = target; + return true; +} + +void parse_glyph(const Header& header, BitReader& reader, uint32_t glyphId, BinFontGlyph* out) { + uint32_t advance = header.advanceWidthBits ? reader.read(header.advanceWidthBits) : header.defaultAdvanceWidth; + if (header.advanceWidthFormat == 0) { + advance *= 16; + } + out->glyph_id = glyphId; + out->advance_x16 = advance; + out->x = static_cast(reader.readSigned(header.xyBits)); + out->y = static_cast(reader.readSigned(header.xyBits)); + out->width = static_cast(reader.read(header.whBits)); + out->height = static_cast(reader.read(header.whBits)); +} + +/** Opens a file for reading and determines its size */ +error_t open_file(const char* path, FILE*& file, size_t& size) { + file = fopen(path, "rb"); + if (file == nullptr) { + return ERROR_NOT_FOUND; + } + if (fseek(file, 0, SEEK_END) != 0) { + fclose(file); + return ERROR_NOT_SUPPORTED; + } + const long file_size = ftell(file); + if (file_size <= 0 || fseek(file, 0, SEEK_SET) != 0) { + fclose(file); + return ERROR_NOT_SUPPORTED; + } + size = static_cast(file_size); + return ERROR_NONE; +} + +/** Loads the lookup tables from an open file, then closes it. Glyph data is read on demand. */ +error_t open_streaming(const char* path, FILE* file, size_t size, BinFont** out) { + BinFont* font = create_font(); + if (font == nullptr) { + fclose(file); + return ERROR_OUT_OF_MEMORY; + } + font->file = file; + + const size_t path_size = strlen(path) + 1; + font->path = static_cast(memory_alloc(path_size)); + if (font->path == nullptr) { + binfont_close(font); + return ERROR_OUT_OF_MEMORY; + } + memcpy(font->path, path, path_size); + + const error_t error = parse_layout(font, size); + fclose(font->file); + font->file = nullptr; + if (error != ERROR_NONE) { + binfont_close(font); + return error; + } + *out = font; + return ERROR_NONE; +} + +} // namespace + +extern "C" { + +error_t binfont_open_memory(const void* data, size_t size, bool take_ownership, BinFont** out) { + BinFont* font = create_font(); + if (font == nullptr) { + if (take_ownership) { + memory_free(const_cast(data)); + } + return ERROR_OUT_OF_MEMORY; + } + font->data = static_cast(data); + font->ownsData = take_ownership; + + const error_t error = parse_layout(font, size); + if (error != ERROR_NONE) { + binfont_close(font); + return error; + } + *out = font; + return ERROR_NONE; +} + +error_t binfont_open_file(const char* path, BinFont** out) { + FILE* file; + size_t size; + const error_t open_error = open_file(path, file, size); + if (open_error != ERROR_NONE) { + return open_error; + } + + const uint16_t memory_capability = memory_external_total() > 0 ? MEMORY_CAPABILITY_EXTERNAL : MEMORY_CAPABILITY_INTERNAL; + const MemoryPolicy policy = { .required = memory_capability, .desired = 0, .alignment = 0 }; + auto* data = static_cast(memory_alloc_with_policy(size, &policy)); + if (data == nullptr) { + return open_streaming(path, file, size, out); + } + + const bool success = fread(data, 1, size, file) == size; + fclose(file); + if (!success) { + memory_free(data); + return ERROR_NOT_SUPPORTED; + } + return binfont_open_memory(data, size, true, out); +} + +error_t binfont_open_file_streaming(const char* path, BinFont** out) { + FILE* file; + size_t size; + const error_t open_error = open_file(path, file, size); + if (open_error != ERROR_NONE) { + return open_error; + } + return open_streaming(path, file, size, out); +} + +error_t binfont_begin(BinFont* font) { + if (font->data != nullptr) { + return ERROR_NONE; + } + mutex_lock(&font->mutex); + if (font->sessionCount == 0) { + font->file = fopen(font->path, "rb"); + if (font->file == nullptr) { + mutex_unlock(&font->mutex); + return ERROR_NOT_FOUND; + } + } + font->sessionCount++; + mutex_unlock(&font->mutex); + return ERROR_NONE; +} + +void binfont_end(BinFont* font) { + if (font->data != nullptr) { + return; + } + mutex_lock(&font->mutex); + if (font->sessionCount > 0) { + font->sessionCount--; + if (font->sessionCount == 0) { + fclose(font->file); + font->file = nullptr; + } + } + mutex_unlock(&font->mutex); +} + +void binfont_close(BinFont* font) { + if (font->ownsData) { + memory_free(const_cast(font->data)); + } + if (font->file != nullptr) { + fclose(font->file); + } + memory_free(font->path); + memory_free(font->tables); + mutex_destruct(&font->mutex); + memory_free(font); +} + +void binfont_get_metrics(const BinFont* font, BinFontMetrics* out) { + const Header& header = font->header; + out->size = header.fontSize; + out->ascent = header.ascent; + out->descent = header.descent; + out->line_height = static_cast(header.ascent - header.descent); + out->base_line = static_cast(-header.descent); + out->underline_position = header.underlinePosition; + out->underline_thickness = header.underlineThickness; + out->bpp = header.bpp; +} + +bool binfont_get_glyph(BinFont* font, uint32_t codepoint, BinFontGlyph* out) { + const uint32_t glyph_id = find_glyph_id(font, codepoint); + uint8_t buffer[GLYPH_HEADER_MAX_BYTES]; + const uint8_t* record; + size_t size; + uint8_t* allocated; + if (!get_glyph_record(font, glyph_id, sizeof(buffer), buffer, sizeof(buffer), record, size, allocated)) { + return false; + } + BitReader reader(record, size); + parse_glyph(font->header, reader, glyph_id, out); + return true; +} + +int32_t binfont_get_kerning_x16(BinFont* font, uint32_t left_glyph_id, uint32_t right_glyph_id) { + const uint8_t* kern = font->kern; + if (kern == nullptr) { + return 0; + } + + int8_t value = 0; + if (kern[8] == 0) { + const uint32_t count = read_u32(kern + 12); + const uint8_t* pairs = kern + 16; + const bool wide = font->header.glyphIdFormat != 0; + const size_t pair_size = wide ? 4 : 2; + const uint32_t key = (left_glyph_id << 16) | right_glyph_id; + uint32_t low = 0; + uint32_t high = count; + while (low < high) { + const uint32_t mid = (low + high) / 2; + const uint8_t* pair = pairs + mid * pair_size; + const uint32_t left = wide ? read_u16(pair) : pair[0]; + const uint32_t right = wide ? read_u16(pair + 2) : pair[1]; + const uint32_t mid_key = (left << 16) | right; + if (mid_key == key) { + value = static_cast(pairs[count * pair_size + mid]); + break; + } else if (mid_key < key) { + low = mid + 1; + } else { + high = mid; + } + } + } else { + const uint16_t glyph_count = read_u16(kern + 12); + const uint8_t right_count = kern[15]; + if (left_glyph_id >= glyph_count || right_glyph_id >= glyph_count) { + return 0; + } + const uint8_t* left_classes = kern + 16; + const uint8_t* right_classes = left_classes + glyph_count; + const uint8_t* values = right_classes + glyph_count; + const uint8_t left_class = left_classes[left_glyph_id]; + const uint8_t right_class = right_classes[right_glyph_id]; + if (left_class == 0 || right_class == 0 || left_class > kern[14] || right_class > right_count) { + return 0; + } + value = static_cast(values[(left_class - 1) * right_count + (right_class - 1)]); + } + + return (static_cast(value) * font->header.kerningScale) >> 4; +} + +error_t binfont_get_glyph_bitmap(BinFont* font, const BinFontGlyph* glyph, uint8_t* out, size_t stride) { + if (stride < glyph->width) { + return ERROR_INVALID_ARGUMENT; + } + if (glyph->width == 0 || glyph->height == 0) { + return ERROR_NONE; + } + + const uint8_t* record; + size_t size; + uint8_t* allocated; + if (!get_glyph_record(font, glyph->glyph_id, SIZE_MAX, nullptr, 0, record, size, allocated)) { + return ERROR_RESOURCE; + } + + const Header& header = font->header; + const uint8_t bpp = header.bpp; + const size_t header_bits = header.advanceWidthBits + 2U * header.xyBits + 2U * header.whBits; + BitReader reader(record, size, header_bits); + + // Raw pixel values first, so the XOR prefilter can work on the previous line + if (header.compression == COMPRESSION_NONE) { + for (uint16_t y = 0; y < glyph->height; y++) { + uint8_t* line = out + y * stride; + for (uint16_t x = 0; x < glyph->width; x++) { + line[x] = static_cast(reader.read(bpp)); + } + } + } else { + RleReader rle(reader, bpp); + const bool prefilter = header.compression == COMPRESSION_RLE_PREFILTER; + for (uint16_t y = 0; y < glyph->height; y++) { + uint8_t* line = out + y * stride; + const uint8_t* previous = line - stride; + for (uint16_t x = 0; x < glyph->width; x++) { + const uint8_t value = rle.next(); + line[x] = (prefilter && y > 0) ? (value ^ previous[x]) : value; + } + } + } + + const uint32_t max_value = (1U << bpp) - 1; + for (uint16_t y = 0; y < glyph->height; y++) { + uint8_t* line = out + y * stride; + for (uint16_t x = 0; x < glyph->width; x++) { + line[x] = static_cast(line[x] * 255U / max_value); + } + } + + memory_free(allocated); + return ERROR_NONE; +} + +} diff --git a/Modules/binfont-module/source/generator.cpp b/Modules/binfont-module/source/generator.cpp new file mode 100644 index 000000000..c16b0e7e2 --- /dev/null +++ b/Modules/binfont-module/source/generator.cpp @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: Apache-2.0 +#include + +#include + +#include +#include +#include +#include +#include + +#define STBTT_STATIC +#define STB_TRUETYPE_IMPLEMENTATION +#define STBTT_malloc(size, user) ((void)(user), memory_alloc(size)) +#define STBTT_free(pointer, user) ((void)(user), memory_free(pointer)) +#include "stb_truetype.h" + +namespace { + +constexpr size_t HEAD_SIZE = 48; +constexpr uint8_t CMAP_FORMAT_0_TINY = 2; +constexpr uint8_t CMAP_FORMAT_SPARSE_TINY = 3; +constexpr uint32_t CMAP_MAX_RANGE = 0xFFFF; + +constexpr MemoryPolicy EXTERNAL_PREFERRED = { .required = 0, .desired = MEMORY_CAPABILITY_EXTERNAL, .alignment = 0 }; + +class ByteBuffer { + uint8_t* data = nullptr; + size_t size = 0; + size_t capacity = 0; + bool failed = false; + + bool reserve(size_t required) { + if (failed) { + return false; + } + if (required <= capacity) { + return true; + } + size_t new_capacity = capacity ? capacity * 2 : 4096; + while (new_capacity < required) { + new_capacity *= 2; + } + auto* new_data = static_cast(memory_realloc_with_policy(data, new_capacity, &EXTERNAL_PREFERRED)); + if (new_data == nullptr) { + failed = true; + return false; + } + data = new_data; + capacity = new_capacity; + return true; + } + +public: + ~ByteBuffer() { memory_free(data); } + + size_t getSize() const { return size; } + bool hasFailed() const { return failed; } + + void append(const void* bytes, size_t count) { + if (reserve(size + count)) { + memcpy(data + size, bytes, count); + size += count; + } + } + + void appendZeros(size_t count) { + if (reserve(size + count)) { + memset(data + size, 0, count); + size += count; + } + } + + void appendU8(uint8_t value) { append(&value, 1); } + + void appendU16(uint16_t value) { + const uint8_t bytes[2] = { static_cast(value), static_cast(value >> 8) }; + append(bytes, 2); + } + + void appendU32(uint32_t value) { + const uint8_t bytes[4] = { static_cast(value), static_cast(value >> 8), static_cast(value >> 16), static_cast(value >> 24) }; + append(bytes, 4); + } + + void setU32(size_t offset, uint32_t value) { + if (!failed) { + data[offset] = static_cast(value); + data[offset + 1] = static_cast(value >> 8); + data[offset + 2] = static_cast(value >> 16); + data[offset + 3] = static_cast(value >> 24); + } + } + + void alignTo4() { appendZeros((4 - size % 4) % 4); } + + /** Starts a record and returns its offset, for endRecord(). */ + size_t beginRecord(const char* marker) { + const size_t offset = size; + appendU32(0); + append(marker, 4); + return offset; + } + + void endRecord(size_t offset) { setU32(offset, static_cast(size - offset)); } + + uint8_t* release() { + uint8_t* result = data; + data = nullptr; + size = 0; + capacity = 0; + return result; + } +}; + +/** MSB-first bit writer */ +class BitWriter { + ByteBuffer& buffer; + uint8_t current = 0; + uint8_t used = 0; + +public: + explicit BitWriter(ByteBuffer& buffer) : buffer(buffer) {} + + void write(uint32_t value, uint8_t bits) { + while (bits > 0) { + bits--; + current = static_cast((current << 1) | ((value >> bits) & 1U)); + used++; + if (used == 8) { + buffer.appendU8(current); + current = 0; + used = 0; + } + } + } + + void flush() { + if (used > 0) { + buffer.appendU8(static_cast(current << (8 - used))); + current = 0; + used = 0; + } + } +}; + +struct GlyphInfo { + uint32_t codepoint; + int ttfIndex; + uint32_t advanceX16; + int x0, y0, x1, y1; // stb_truetype bitmap box: y points down +}; + +uint8_t bits_for_unsigned(uint32_t value) { + uint8_t bits = 1; + while (bits < 32 && (value >> bits) != 0) { + bits++; + } + return bits; +} + +uint8_t bits_for_signed(int32_t min, int32_t max) { + uint8_t bits = 1; + while (bits < 32 && (min < -(1 << (bits - 1)) || max > (1 << (bits - 1)) - 1)) { + bits++; + } + return bits; +} + +int16_t scale_metric(int value, float scale) { + return static_cast(std::lround(static_cast(value) * scale)); +} + +uint8_t* read_file(const char* path, size_t& size) { + FILE* file = fopen(path, "rb"); + if (file == nullptr) { + return nullptr; + } + uint8_t* data = nullptr; + long file_size = 0; + if (fseek(file, 0, SEEK_END) == 0 && (file_size = ftell(file)) > 0 && fseek(file, 0, SEEK_SET) == 0) { + data = static_cast(memory_alloc_with_policy(static_cast(file_size), &EXTERNAL_PREFERRED)); + if (data != nullptr && fread(data, 1, static_cast(file_size), file) != static_cast(file_size)) { + memory_free(data); + data = nullptr; + } + } + fclose(file); + size = static_cast(file_size); + return data; +} + +void write_cmap(ByteBuffer& out, const GlyphInfo* glyphs, size_t count) { + // Glyph ids are 1..count in codepoint order, so every subtable can be a "tiny" format + struct Range { + size_t first; + size_t count; + bool contiguous; + }; + + auto next_range = [&](size_t first) { + Range range = { first, 1, true }; + while (first + range.count < count && range.count < CMAP_MAX_RANGE) { + const GlyphInfo& candidate = glyphs[first + range.count]; + if (candidate.codepoint - glyphs[first].codepoint >= CMAP_MAX_RANGE) { + break; + } + if (candidate.codepoint != glyphs[first].codepoint + range.count) { + range.contiguous = false; + } + range.count++; + } + return range; + }; + + uint32_t range_count = 0; + for (size_t i = 0; i < count; i += next_range(i).count) { + range_count++; + } + + const size_t record = out.beginRecord("cmap"); + out.appendU32(range_count); + + size_t data_offset = 12 + range_count * 16; + for (size_t i = 0; i < count;) { + const Range range = next_range(i); + const uint32_t range_start = glyphs[i].codepoint; + const uint32_t range_length = glyphs[i + range.count - 1].codepoint - range_start + 1; + out.appendU32(range.contiguous ? 0 : static_cast(data_offset)); + out.appendU32(range_start); + out.appendU16(static_cast(range_length)); + out.appendU16(static_cast(i + 1)); + out.appendU16(range.contiguous ? 0 : static_cast(range.count)); + out.appendU8(range.contiguous ? CMAP_FORMAT_0_TINY : CMAP_FORMAT_SPARSE_TINY); + out.appendU8(0); + if (!range.contiguous) { + data_offset += (range.count * 2 + 3) & ~static_cast(3); + } + i += range.count; + } + + for (size_t i = 0; i < count;) { + const Range range = next_range(i); + if (!range.contiguous) { + for (size_t j = 0; j < range.count; j++) { + out.appendU16(static_cast(glyphs[i + j].codepoint - glyphs[i].codepoint)); + } + out.alignTo4(); + } + i += range.count; + } + + out.endRecord(record); +} + +error_t generate(const BinFontGeneratorConfig* config, 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])); + if (index != 0) { + glyphs[count].codepoint = config->codepoints[i]; + glyphs[count].ttfIndex = index; + count++; + } + } + std::sort(glyphs, glyphs + count, [](const GlyphInfo& a, const GlyphInfo& b) { return a.codepoint < b.codepoint; }); + count = std::unique(glyphs, glyphs + count, [](const GlyphInfo& a, const GlyphInfo& b) { return a.codepoint == b.codepoint; }) - glyphs; + if (count == 0 || count >= 0xFFFF) { + return ERROR_NOT_SUPPORTED; + } + + int32_t min_xy = 0; + int32_t max_xy = 0; + uint32_t max_wh = 0; + uint32_t max_advance = 0; + // Like lv_font_conv, ascent and descent are the extents of the included glyphs + int32_t min_y = INT32_MAX; + int32_t max_y = INT32_MIN; + for (size_t i = 0; i < count; i++) { + GlyphInfo& glyph = glyphs[i]; + int advance; + int left_side_bearing; + stbtt_GetGlyphHMetrics(&info, glyph.ttfIndex, &advance, &left_side_bearing); + glyph.advanceX16 = static_cast(std::lround(static_cast(advance) * scale * 16.0f)); + stbtt_GetGlyphBitmapBox(&info, glyph.ttfIndex, scale, scale, &glyph.x0, &glyph.y0, &glyph.x1, &glyph.y1); + + const int32_t bottom = -glyph.y1; + min_xy = std::min({ min_xy, static_cast(glyph.x0), bottom }); + max_xy = std::max({ max_xy, static_cast(glyph.x0), bottom }); + max_wh = std::max({ max_wh, static_cast(glyph.x1 - glyph.x0), static_cast(glyph.y1 - glyph.y0) }); + max_advance = std::max(max_advance, glyph.advanceX16); + min_y = std::min(min_y, bottom); + max_y = std::max(max_y, static_cast(-glyph.y0)); + } + + const uint8_t xy_bits = bits_for_signed(min_xy, max_xy); + const uint8_t wh_bits = bits_for_unsigned(max_wh); + const uint8_t advance_bits = bits_for_unsigned(max_advance); + const uint32_t glyph_count = static_cast(count) + 1; + + int typo_ascent = 0; + int typo_descent = 0; + int typo_line_gap = 0; + stbtt_GetFontVMetricsOS2(&info, &typo_ascent, &typo_descent, &typo_line_gap); + int underline_position = 0; + int underline_thickness = 0; + const stbtt_uint32 post = stbtt__find_table(info.data, info.fontstart, "post"); + if (post != 0) { + underline_position = ttSHORT(info.data + post + 8); + underline_thickness = ttSHORT(info.data + post + 10); + } + + // head + const size_t head = out.beginRecord("head"); + out.appendU32(1); // version + out.appendU16(3); // additional tables: cmap, loca, glyf + out.appendU16(config->size); + out.appendU16(static_cast(max_y)); + out.appendU16(static_cast(min_y)); + out.appendU16(static_cast(scale_metric(typo_ascent, scale))); + out.appendU16(static_cast(scale_metric(typo_descent, scale))); + out.appendU16(static_cast(scale_metric(typo_line_gap, scale))); + out.appendU16(static_cast(min_y)); + out.appendU16(static_cast(max_y)); + out.appendU16(0); // default advance width + out.appendU16(16); // kerning scale 1.0 in FP12.4 + out.appendU8(1); // loca: Offset32 + out.appendU8(glyph_count > 256 ? 1 : 0); + out.appendU8(1); // advance width with 4 fractional bits + out.appendU8(config->bpp); + out.appendU8(xy_bits); + out.appendU8(wh_bits); + out.appendU8(advance_bits); + out.appendU8(0); // no compression + out.appendU8(0); // no subpixel rendering + out.appendU8(0); + out.appendU16(static_cast(scale_metric(underline_position, scale))); + out.appendU16(static_cast(scale_metric(underline_thickness, scale))); + out.endRecord(head); + + write_cmap(out, glyphs, count); + + const size_t loca = out.beginRecord("loca"); + out.appendU32(glyph_count); + const size_t loca_entries = out.getSize(); + out.appendZeros(glyph_count * 4); + out.endRecord(loca); + + const size_t glyf = out.beginRecord("glyf"); + uint8_t* bitmap = nullptr; + size_t bitmap_capacity = 0; + const uint32_t max_value = (1U << config->bpp) - 1; + for (uint32_t id = 0; id < glyph_count && !out.hasFailed(); id++) { + out.setU32(loca_entries + id * 4, static_cast(out.getSize() - glyf)); + BitWriter writer(out); + if (id == 0) { + writer.write(0, advance_bits); + writer.write(0, xy_bits); + writer.write(0, xy_bits); + writer.write(0, wh_bits); + writer.write(0, wh_bits); + writer.flush(); + continue; + } + + const GlyphInfo& glyph = glyphs[id - 1]; + const int width = glyph.x1 - glyph.x0; + const int height = glyph.y1 - glyph.y0; + writer.write(glyph.advanceX16, advance_bits); + writer.write(static_cast(glyph.x0), xy_bits); + writer.write(static_cast(-glyph.y1), xy_bits); + writer.write(static_cast(width), wh_bits); + writer.write(static_cast(height), wh_bits); + + const size_t pixel_count = static_cast(width) * height; + if (pixel_count > 0) { + if (pixel_count > bitmap_capacity) { + memory_free(bitmap); + bitmap = static_cast(memory_alloc_with_policy(pixel_count, &EXTERNAL_PREFERRED)); + if (bitmap == nullptr) { + return ERROR_OUT_OF_MEMORY; + } + bitmap_capacity = pixel_count; + } + stbtt_MakeGlyphBitmap(&info, bitmap, width, height, width, scale, scale, glyph.ttfIndex); + for (size_t i = 0; i < pixel_count; i++) { + writer.write((bitmap[i] * max_value + 127) / 255, config->bpp); + } + } + writer.flush(); + } + memory_free(bitmap); + out.alignTo4(); + out.endRecord(glyf); + + return out.hasFailed() ? ERROR_OUT_OF_MEMORY : ERROR_NONE; +} + +} // namespace + +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) { + return ERROR_INVALID_ARGUMENT; + } + + size_t ttf_size = 0; + uint8_t* ttf = read_file(config->ttf_path, ttf_size); + if (ttf == nullptr) { + return ERROR_NOT_FOUND; + } + + stbtt_fontinfo info; + const int font_offset = stbtt_GetFontOffsetForIndex(ttf, 0); + if (font_offset < 0 || stbtt_InitFont(&info, ttf, font_offset) == 0) { + memory_free(ttf); + return ERROR_NOT_SUPPORTED; + } + + auto* glyphs = static_cast(memory_alloc(config->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); + memory_free(glyphs); + memory_free(ttf); + if (error != ERROR_NONE) { + return error; + } + + *out_size = out.getSize(); + *out_data = out.release(); + return ERROR_NONE; +} + +} diff --git a/Modules/binfont-module/source/module.c b/Modules/binfont-module/source/module.c new file mode 100644 index 000000000..6a4740eb7 --- /dev/null +++ b/Modules/binfont-module/source/module.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include +#include +#include + +static const struct ModuleSymbol SYMBOLS[] = { + // binfont + DEFINE_MODULE_SYMBOL(binfont_open_file), + DEFINE_MODULE_SYMBOL(binfont_open_memory), + DEFINE_MODULE_SYMBOL(binfont_close), + DEFINE_MODULE_SYMBOL(binfont_begin), + DEFINE_MODULE_SYMBOL(binfont_end), + DEFINE_MODULE_SYMBOL(binfont_get_metrics), + DEFINE_MODULE_SYMBOL(binfont_get_glyph), + DEFINE_MODULE_SYMBOL(binfont_get_kerning_x16), + DEFINE_MODULE_SYMBOL(binfont_get_glyph_bitmap), + // generator + DEFINE_MODULE_SYMBOL(binfont_generate), + // render + DEFINE_MODULE_SYMBOL(binfont_draw_glyph_rgb565), + DEFINE_MODULE_SYMBOL(binfont_draw_text_rgb565), + MODULE_SYMBOL_TERMINATOR, +}; + +struct Module binfont_module = { + .name = "binfont", + .start = NULL, + .stop = NULL, + .drivers = NULL, + .symbols = SYMBOLS, + .internal = NULL, +}; diff --git a/Modules/binfont-module/source/render.cpp b/Modules/binfont-module/source/render.cpp new file mode 100644 index 000000000..1d3adc81d --- /dev/null +++ b/Modules/binfont-module/source/render.cpp @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: Apache-2.0 +#include + +#include + +namespace { + +constexpr size_t STACK_BITMAP_SIZE = 1024; + +uint16_t blend_rgb565(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); +} + +void draw_glyph(PixelBuffer* buffer, int x, int baselineY, BinFont* font, const BinFontGlyph& glyph, uint16_t color, PixelBufferConversion conversion) { + const size_t pixel_count = static_cast(glyph.width) * glyph.height; + if (pixel_count == 0) { + return; + } + + uint8_t stack_bitmap[STACK_BITMAP_SIZE]; + uint8_t* allocated = nullptr; + uint8_t* bitmap = stack_bitmap; + if (pixel_count > sizeof(stack_bitmap)) { + allocated = static_cast(memory_alloc(pixel_count)); + if (allocated == nullptr) { + return; + } + bitmap = allocated; + } + + if (binfont_get_glyph_bitmap(font, &glyph, bitmap, glyph.width) == ERROR_NONE) { + const int left = x + glyph.x; + const int top = baselineY - glyph.y - glyph.height; + for (int row = 0; row < glyph.height; row++) { + const uint8_t* line = bitmap + row * glyph.width; + for (int column = 0; column < glyph.width; column++) { + const uint8_t alpha = line[column]; + if (alpha == 0) { + continue; + } + const int pixel_x = left + column; + const int pixel_y = top + row; + const uint16_t pixel = (alpha == 255) ? color : blend_rgb565(color, pixel_buffer_get_pixel_rgb565(buffer, pixel_x, pixel_y), alpha); + pixel_buffer_set_pixel_rgb565(buffer, pixel_x, pixel_y, pixel, conversion); + } + } + } + + memory_free(allocated); +} + +/** Decodes one UTF-8 codepoint and advances text. Invalid sequences decode as U+FFFD. */ +uint32_t next_codepoint(const char*& text) { + const auto* bytes = reinterpret_cast(text); + const uint8_t lead = bytes[0]; + int length; + uint32_t codepoint; + if (lead < 0x80) { + length = 1; + codepoint = lead; + } else if ((lead & 0xE0) == 0xC0) { + length = 2; + codepoint = lead & 0x1FU; + } else if ((lead & 0xF0) == 0xE0) { + length = 3; + codepoint = lead & 0x0FU; + } else if ((lead & 0xF8) == 0xF0) { + length = 4; + codepoint = lead & 0x07U; + } else { + text++; + return 0xFFFD; + } + for (int i = 1; i < length; i++) { + if ((bytes[i] & 0xC0) != 0x80) { + text += i; + return 0xFFFD; + } + codepoint = (codepoint << 6) | (bytes[i] & 0x3FU); + } + text += length; + return codepoint; +} + +} // namespace + +extern "C" { + +int binfont_draw_glyph_rgb565(PixelBuffer* buffer, int x, int baseline_y, BinFont* font, uint32_t codepoint, uint16_t color, PixelBufferConversion conversion) { + BinFontGlyph glyph; + if (!binfont_get_glyph(font, codepoint, &glyph)) { + return 0; + } + draw_glyph(buffer, x, baseline_y, font, glyph, color, conversion); + return static_cast((glyph.advance_x16 + 8) >> 4); +} + +int binfont_draw_text_rgb565(PixelBuffer* buffer, int x, int baseline_y, BinFont* font, const char* text, uint16_t color, PixelBufferConversion conversion) { + // When the file can't be kept open, every glyph lookup opens it by itself + const bool session = binfont_begin(font) == ERROR_NONE; + int32_t pen_x16 = 0; + uint32_t previous_glyph_id = 0; + while (*text != '\0') { + BinFontGlyph glyph; + if (!binfont_get_glyph(font, next_codepoint(text), &glyph)) { + previous_glyph_id = 0; + continue; + } + if (previous_glyph_id != 0) { + pen_x16 += binfont_get_kerning_x16(font, previous_glyph_id, glyph.glyph_id); + } + draw_glyph(buffer, x + ((pen_x16 + 8) >> 4), baseline_y, font, glyph, color, conversion); + pen_x16 += static_cast(glyph.advance_x16); + previous_glyph_id = glyph.glyph_id; + } + if (session) { + binfont_end(font); + } + return (pen_x16 + 8) >> 4; +} + +} diff --git a/Modules/binfont-module/tests/CMakeLists.txt b/Modules/binfont-module/tests/CMakeLists.txt new file mode 100644 index 000000000..cad3d7a20 --- /dev/null +++ b/Modules/binfont-module/tests/CMakeLists.txt @@ -0,0 +1,23 @@ +project(BinFontModuleTests) + +enable_language(C CXX ASM) + +file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp) +add_executable(BinFontModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES}) + +target_include_directories(BinFontModuleTests PRIVATE ${DOCTESTINC} ${PROJECT_SOURCE_DIR}/../private) + +target_compile_definitions(BinFontModuleTests PRIVATE + "BINFONT_TEST_FIXTURES_DIR=\"${PROJECT_SOURCE_DIR}/fixtures\"" + "BINFONT_TEST_TEMP_DIR=\"${CMAKE_CURRENT_BINARY_DIR}\"" + "BINFONT_TEST_ICON_TTF=\"${CMAKE_SOURCE_DIR}/Data/system/fonts/MaterialSymbolsRounded.ttf\"" +) + +add_test(NAME BinFontModuleTests COMMAND BinFontModuleTests) + +target_link_libraries(BinFontModuleTests PUBLIC + binfont-module + graphics-module + TactilityKernel + freertos_kernel +) diff --git a/Modules/binfont-module/tests/fixtures/icons_raw_2.bin b/Modules/binfont-module/tests/fixtures/icons_raw_2.bin new file mode 100644 index 000000000..dcad40cb8 Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_raw_2.bin differ diff --git a/Modules/binfont-module/tests/fixtures/icons_raw_4.bin b/Modules/binfont-module/tests/fixtures/icons_raw_4.bin new file mode 100644 index 000000000..e9cfb0834 Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_raw_4.bin differ diff --git a/Modules/binfont-module/tests/fixtures/icons_rle_2.bin b/Modules/binfont-module/tests/fixtures/icons_rle_2.bin new file mode 100644 index 000000000..dc440c4da Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_rle_2.bin differ diff --git a/Modules/binfont-module/tests/fixtures/icons_rle_4.bin b/Modules/binfont-module/tests/fixtures/icons_rle_4.bin new file mode 100644 index 000000000..4114699ea Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_rle_4.bin differ diff --git a/Modules/binfont-module/tests/fixtures/icons_rlepf_2.bin b/Modules/binfont-module/tests/fixtures/icons_rlepf_2.bin new file mode 100644 index 000000000..26b613f8c Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_rlepf_2.bin differ diff --git a/Modules/binfont-module/tests/fixtures/icons_rlepf_4.bin b/Modules/binfont-module/tests/fixtures/icons_rlepf_4.bin new file mode 100644 index 000000000..a84f959b3 Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/icons_rlepf_4.bin differ diff --git a/Modules/binfont-module/tests/fixtures/text_kern_classes.bin b/Modules/binfont-module/tests/fixtures/text_kern_classes.bin new file mode 100644 index 000000000..627c09e9c Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/text_kern_classes.bin differ diff --git a/Modules/binfont-module/tests/fixtures/text_kern_pairs.bin b/Modules/binfont-module/tests/fixtures/text_kern_pairs.bin new file mode 100644 index 000000000..b0ba3cc67 Binary files /dev/null and b/Modules/binfont-module/tests/fixtures/text_kern_pairs.bin differ diff --git a/Modules/binfont-module/tests/source/binfont_test.cpp b/Modules/binfont-module/tests/source/binfont_test.cpp new file mode 100644 index 000000000..a5bb2bc0c --- /dev/null +++ b/Modules/binfont-module/tests/source/binfont_test.cpp @@ -0,0 +1,340 @@ +#include "doctest.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace { + +constexpr uint32_t ICON_CODEPOINTS[] = { 0xE5C3, 0xE8B8, 0xE2C7, 0xE63E, 0xE1A7 }; + +std::string fixture(const char* name) { + return std::string(BINFONT_TEST_FIXTURES_DIR) + "/" + name; +} + +/** Loads a file into memory allocated with memory_alloc() */ +uint8_t* load_file(const std::string& path, size_t& size) { + FILE* file = fopen(path.c_str(), "rb"); + REQUIRE(file != nullptr); + fseek(file, 0, SEEK_END); + size = static_cast(ftell(file)); + fseek(file, 0, SEEK_SET); + auto* data = static_cast(memory_alloc(size)); + REQUIRE(fread(data, 1, size, file) == size); + fclose(file); + return data; +} + +BinFont* open_fixture_in_memory(const char* name) { + size_t size; + uint8_t* data = load_file(fixture(name), size); + BinFont* font = nullptr; + REQUIRE(binfont_open_memory(data, size, true, &font) == ERROR_NONE); + return font; +} + +std::vector decode(BinFont* font, const BinFontGlyph& glyph) { + std::vector bitmap(static_cast(glyph.width) * glyph.height); + REQUIRE(binfont_get_glyph_bitmap(font, &glyph, bitmap.data(), glyph.width) == ERROR_NONE); + return bitmap; +} + +uint32_t sum(const std::vector& bitmap) { + uint32_t total = 0; + for (uint8_t value : bitmap) { + total += value; + } + return total; +} + +void check_same_glyph(const BinFontGlyph& a, const BinFontGlyph& b) { + CHECK_EQ(a.glyph_id, b.glyph_id); + CHECK_EQ(a.advance_x16, b.advance_x16); + CHECK_EQ(a.x, b.x); + CHECK_EQ(a.y, b.y); + CHECK_EQ(a.width, b.width); + CHECK_EQ(a.height, b.height); +} + +} // namespace + +TEST_CASE("binfont_open_file returns ERROR_NOT_FOUND for a missing file") { + BinFont* font = nullptr; + CHECK_EQ(binfont_open_file(fixture("missing.bin").c_str(), &font), ERROR_NOT_FOUND); +} + +TEST_CASE("binfont_open_memory rejects data that is not a font") { + const uint8_t data[64] = { 1, 2, 3, 4 }; + BinFont* font = nullptr; + CHECK_EQ(binfont_open_memory(data, sizeof(data), false, &font), ERROR_NOT_SUPPORTED); +} + +TEST_CASE("binfont reads metrics, glyphs and bitmaps that match lv_font_conv's C output") { + BinFont* font = open_fixture_in_memory("text_kern_pairs.bin"); + + BinFontMetrics metrics; + binfont_get_metrics(font, &metrics); + CHECK_EQ(metrics.size, 20); + CHECK_EQ(metrics.line_height, 20); + CHECK_EQ(metrics.base_line, 5); + CHECK_EQ(metrics.ascent, 15); + CHECK_EQ(metrics.descent, -5); + CHECK_EQ(metrics.underline_position, 1); + CHECK_EQ(metrics.underline_thickness, 0); + CHECK_EQ(metrics.bpp, 4); + + BinFontGlyph glyph; + REQUIRE(binfont_get_glyph(font, 'A', &glyph)); + CHECK_EQ(glyph.glyph_id, 1); + CHECK_EQ(glyph.advance_x16, 195); + CHECK_EQ(glyph.x, 0); + CHECK_EQ(glyph.y, 0); + CHECK_EQ(glyph.width, 13); + CHECK_EQ(glyph.height, 14); + + const auto bitmap = decode(font, glyph); + const std::vector first_row = { 0, 0, 0, 0, 0, 238, 255, 17, 0, 0, 0, 0, 0 }; + const std::vector last_row = { 221, 255, 0, 0, 0, 0, 0, 0, 0, 0, 238, 238, 0 }; + CHECK(std::vector(bitmap.begin(), bitmap.begin() + 13) == first_row); + CHECK(std::vector(bitmap.end() - 13, bitmap.end()) == last_row); + CHECK_EQ(sum(bitmap), 13974); + + REQUIRE(binfont_get_glyph(font, 'V', &glyph)); + CHECK_EQ(glyph.glyph_id, 22); + REQUIRE(binfont_get_glyph(font, 'z', &glyph)); + CHECK_EQ(glyph.glyph_id, 52); + + CHECK_FALSE(binfont_get_glyph(font, '0', &glyph)); + CHECK_FALSE(binfont_get_glyph(font, 0x5B, &glyph)); + CHECK_FALSE(binfont_get_glyph(font, 0x10FFFF, &glyph)); + + binfont_close(font); +} + +TEST_CASE("binfont kerning is the same for the pairs and the classes format") { + BinFont* pairs = open_fixture_in_memory("text_kern_pairs.bin"); + BinFont* classes = open_fixture_in_memory("text_kern_classes.bin"); + + CHECK_EQ(binfont_get_kerning_x16(pairs, 1, 22), -10); + CHECK_EQ(binfont_get_kerning_x16(classes, 1, 22), -10); + + int non_zero = 0; + for (uint32_t left = 1; left <= 52; left++) { + for (uint32_t right = 1; right <= 52; right++) { + const int32_t value = binfont_get_kerning_x16(pairs, left, right); + CHECK_EQ(value, binfont_get_kerning_x16(classes, left, right)); + if (value != 0) { + non_zero++; + } + } + } + CHECK(non_zero > 0); + CHECK_EQ(binfont_get_kerning_x16(pairs, 1, 1000), 0); + CHECK_EQ(binfont_get_kerning_x16(classes, 1, 1000), 0); + + binfont_close(pairs); + binfont_close(classes); +} + +TEST_CASE("binfont decodes identical bitmaps for raw, RLE and RLE with prefilter") { + for (const char* bpp : { "2", "4" }) { + CAPTURE(bpp); + BinFont* raw = open_fixture_in_memory((std::string("icons_raw_") + bpp + ".bin").c_str()); + BinFont* rle = open_fixture_in_memory((std::string("icons_rle_") + bpp + ".bin").c_str()); + BinFont* prefiltered = open_fixture_in_memory((std::string("icons_rlepf_") + bpp + ".bin").c_str()); + + for (uint32_t codepoint : ICON_CODEPOINTS) { + CAPTURE(codepoint); + BinFontGlyph raw_glyph, rle_glyph, prefiltered_glyph; + REQUIRE(binfont_get_glyph(raw, codepoint, &raw_glyph)); + REQUIRE(binfont_get_glyph(rle, codepoint, &rle_glyph)); + REQUIRE(binfont_get_glyph(prefiltered, codepoint, &prefiltered_glyph)); + check_same_glyph(raw_glyph, rle_glyph); + check_same_glyph(raw_glyph, prefiltered_glyph); + + const auto raw_bitmap = decode(raw, raw_glyph); + CHECK(sum(raw_bitmap) > 0); + CHECK(decode(rle, rle_glyph) == raw_bitmap); + CHECK(decode(prefiltered, prefiltered_glyph) == raw_bitmap); + } + + binfont_close(raw); + binfont_close(rle); + binfont_close(prefiltered); + } +} + +TEST_CASE("binfont gives the same results when streaming from a file") { + BinFont* memory_font = open_fixture_in_memory("icons_rlepf_4.bin"); + BinFont* file_font = nullptr; + REQUIRE(binfont_open_file_streaming(fixture("icons_rlepf_4.bin").c_str(), &file_font) == ERROR_NONE); + + for (uint32_t codepoint : ICON_CODEPOINTS) { + BinFontGlyph memory_glyph, file_glyph; + REQUIRE(binfont_get_glyph(memory_font, codepoint, &memory_glyph)); + REQUIRE(binfont_get_glyph(file_font, codepoint, &file_glyph)); + check_same_glyph(memory_glyph, file_glyph); + CHECK(decode(memory_font, memory_glyph) == decode(file_font, file_glyph)); + } + + binfont_close(memory_font); + binfont_close(file_font); +} + +TEST_CASE("binfont_open_file loads the font into memory") { + const std::string path = std::string(BINFONT_TEST_TEMP_DIR) + "/binfont_memory_test.bin"; + size_t size; + uint8_t* data = load_file(fixture("icons_rlepf_4.bin"), size); + FILE* copy = fopen(path.c_str(), "wb"); + REQUIRE(copy != nullptr); + REQUIRE(fwrite(data, 1, size, copy) == size); + fclose(copy); + memory_free(data); + + BinFont* font = nullptr; + REQUIRE(binfont_open_file(path.c_str(), &font) == ERROR_NONE); + REQUIRE(remove(path.c_str()) == 0); + + BinFontGlyph glyph; + CHECK(binfont_get_glyph(font, ICON_CODEPOINTS[0], &glyph)); + CHECK(sum(decode(font, glyph)) > 0); + + binfont_close(font); +} + +TEST_CASE("binfont only keeps a streamed font file open during a session") { + // An open file stays readable after it's deleted, so deleting it shows whether it's kept open + const std::string path = std::string(BINFONT_TEST_TEMP_DIR) + "/binfont_session_test.bin"; + size_t size; + uint8_t* data = load_file(fixture("icons_rlepf_4.bin"), size); + FILE* copy = fopen(path.c_str(), "wb"); + REQUIRE(copy != nullptr); + REQUIRE(fwrite(data, 1, size, copy) == size); + fclose(copy); + memory_free(data); + + BinFont* font = nullptr; + REQUIRE(binfont_open_file_streaming(path.c_str(), &font) == ERROR_NONE); + BinFontGlyph glyph; + REQUIRE(binfont_get_glyph(font, ICON_CODEPOINTS[0], &glyph)); + + REQUIRE(binfont_begin(font) == ERROR_NONE); + REQUIRE(binfont_begin(font) == ERROR_NONE); + REQUIRE(remove(path.c_str()) == 0); + binfont_end(font); + // Still open: one session remains + CHECK(binfont_get_glyph(font, ICON_CODEPOINTS[1], &glyph)); + CHECK_FALSE(decode(font, glyph).empty()); + binfont_end(font); + + // Closed: the deleted file can't be opened again + CHECK_FALSE(binfont_get_glyph(font, ICON_CODEPOINTS[2], &glyph)); + CHECK_EQ(binfont_begin(font), ERROR_NOT_FOUND); + + binfont_close(font); +} + +TEST_CASE("binfont_get_glyph_bitmap rejects a stride smaller than the glyph width") { + BinFont* font = open_fixture_in_memory("icons_raw_2.bin"); + BinFontGlyph glyph; + REQUIRE(binfont_get_glyph(font, ICON_CODEPOINTS[0], &glyph)); + std::vector bitmap(static_cast(glyph.width) * glyph.height); + CHECK_EQ(binfont_get_glyph_bitmap(font, &glyph, bitmap.data(), glyph.width - 1), ERROR_INVALID_ARGUMENT); + binfont_close(font); +} + +TEST_CASE("binfont_generate rasterizes a TTF close to lv_font_conv") { + uint32_t codepoints[] = { 0xE8B8, 0xE5C3, 0x41, 0xE1A7, 0xE2C7, 0xE63E, 0xE5C3 }; // unsorted, duplicate and missing entries + const BinFontGeneratorConfig config = { + .ttf_path = BINFONT_TEST_ICON_TTF, + .size = 24, + .bpp = 4, + .codepoints = codepoints, + .codepoint_count = sizeof(codepoints) / sizeof(codepoints[0]), + }; + uint8_t* data = nullptr; + size_t size = 0; + REQUIRE(binfont_generate(&config, &data, &size) == ERROR_NONE); + + BinFont* generated = nullptr; + REQUIRE(binfont_open_memory(data, size, true, &generated) == ERROR_NONE); + BinFont* reference = open_fixture_in_memory("icons_raw_4.bin"); + + BinFontMetrics generated_metrics, reference_metrics; + binfont_get_metrics(generated, &generated_metrics); + binfont_get_metrics(reference, &reference_metrics); + CHECK_EQ(generated_metrics.size, 24); + CHECK_EQ(generated_metrics.bpp, 4); + CHECK_EQ(generated_metrics.ascent, reference_metrics.ascent); + CHECK_EQ(generated_metrics.descent, reference_metrics.descent); + + BinFontGlyph glyph; + CHECK_FALSE(binfont_get_glyph(generated, 0x41, &glyph)); + + for (uint32_t codepoint : ICON_CODEPOINTS) { + CAPTURE(codepoint); + BinFontGlyph generated_glyph, reference_glyph; + REQUIRE(binfont_get_glyph(generated, codepoint, &generated_glyph)); + REQUIRE(binfont_get_glyph(reference, codepoint, &reference_glyph)); + CHECK(std::abs(static_cast(generated_glyph.advance_x16) - static_cast(reference_glyph.advance_x16)) <= 16); + CHECK(std::abs(generated_glyph.x - reference_glyph.x) <= 1); + CHECK(std::abs(generated_glyph.y - reference_glyph.y) <= 1); + CHECK(std::abs(generated_glyph.width - reference_glyph.width) <= 1); + CHECK(std::abs(generated_glyph.height - reference_glyph.height) <= 1); + + const auto generated_sum = static_cast(sum(decode(generated, generated_glyph))); + const auto reference_sum = static_cast(sum(decode(reference, reference_glyph))); + CHECK(generated_sum > reference_sum * 0.9); + CHECK(generated_sum < reference_sum * 1.1); + } + + binfont_close(generated); + binfont_close(reference); +} + +TEST_CASE("binfont_generate fails for a missing TTF") { + const uint32_t codepoint = 0xE5C3; + const BinFontGeneratorConfig config = { + .ttf_path = BINFONT_TEST_FIXTURES_DIR "/missing.ttf", + .size = 24, + .bpp = 2, + .codepoints = &codepoint, + .codepoint_count = 1, + }; + uint8_t* data = nullptr; + size_t size = 0; + CHECK_EQ(binfont_generate(&config, &data, &size), ERROR_NOT_FOUND); +} + +TEST_CASE("binfont draws glyphs and text into a PixelBuffer") { + BinFont* font = open_fixture_in_memory("text_kern_pairs.bin"); + PixelBuffer* buffer = pixel_buffer_create(DISPLAY_COLOR_FORMAT_RGB565, 64, 24); + REQUIRE(buffer != nullptr); + pixel_buffer_clear(buffer); + + const int advance = binfont_draw_glyph_rgb565(buffer, 0, 18, font, 'A', 0xFFFF, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + CHECK_EQ(advance, (195 + 8) >> 4); + // Top of 'A' (row 0 of the glyph, column 6 is fully opaque) sits 14 rows above the baseline + CHECK_EQ(pixel_buffer_get_pixel_rgb565(buffer, 6, 18 - 14), 0xFFFF); + CHECK_EQ(pixel_buffer_get_pixel_rgb565(buffer, 0, 0), 0x0000); + + CHECK_EQ(binfont_draw_glyph_rgb565(buffer, 0, 18, font, '0', 0xFFFF, PIXEL_BUFFER_CONVERSION_EXACT_BLACK), 0); + + // "AV" is kerned: 195 - 10 + V's advance + BinFontGlyph v; + REQUIRE(binfont_get_glyph(font, 'V', &v)); + pixel_buffer_clear(buffer); + const int width = binfont_draw_text_rgb565(buffer, 0, 18, font, "AV", 0xFFFF, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + CHECK_EQ(width, static_cast((195 - 10 + v.advance_x16 + 8) >> 4)); + + pixel_buffer_free(buffer); + binfont_close(font); +} diff --git a/Modules/binfont-module/tests/source/main.cpp b/Modules/binfont-module/tests/source/main.cpp new file mode 100644 index 000000000..beedf9f8b --- /dev/null +++ b/Modules/binfont-module/tests/source/main.cpp @@ -0,0 +1,64 @@ +#define DOCTEST_CONFIG_IMPLEMENT +#include "doctest.h" +#include +#include + +#include "FreeRTOS.h" +#include "task.h" + +typedef struct { + int argc; + char** argv; + int result; +} TestTaskData; + +void test_task(void* parameter) { + auto* data = (TestTaskData*)parameter; + + doctest::Context context; + + context.applyCommandLine(data->argc, data->argv); + + // overrides + context.setOption("no-breaks", true); // don't break in the debugger when assertions fail + + data->result = context.run(); + + vTaskEndScheduler(); + + vTaskDelete(nullptr); +} + +int main(int argc, char** argv) { + TestTaskData data = { + .argc = argc, + .argv = argv, + .result = 0 + }; + + BaseType_t task_result = xTaskCreate( + test_task, + "test_task", + 8192, + &data, + 1, + nullptr + ); + + if (task_result != pdPASS) { + return 1; + } + + vTaskStartScheduler(); + + return data.result; +} + +// NOTE: This is normally provided by the platform kernel module, but that's not loaded for binfont-module +extern "C" { +// Required for FreeRTOS +void vAssertCalled(unsigned long line, const char* const file) { + std::fprintf(stderr, "assert failed at %s:%lu\n", file, line); + std::abort(); +} +} diff --git a/Modules/lodepng-module/CMakeLists.txt b/Modules/lodepng-module/CMakeLists.txt new file mode 100644 index 000000000..7a5a48304 --- /dev/null +++ b/Modules/lodepng-module/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.20) + +include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake") + +file(GLOB_RECURSE SOURCE_FILES "source/*.c*") + +list(APPEND REQUIRES_LIST + TactilityKernel +) + +tactility_add_module(lodepng-module + SRCS ${SOURCE_FILES} + INCLUDE_DIRS include/ + REQUIRES ${REQUIRES_LIST} +) diff --git a/Modules/lodepng-module/LICENSE-Apache-2.0.md b/Modules/lodepng-module/LICENSE-Apache-2.0.md new file mode 100644 index 000000000..f5f4b8b5e --- /dev/null +++ b/Modules/lodepng-module/LICENSE-Apache-2.0.md @@ -0,0 +1,195 @@ +Apache License +============== + +_Version 2.0, January 2004_ +_<>_ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, “control” means **(i)** the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the +outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising +permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +“Object” form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +“submitted” means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of +this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You +changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +_END OF TERMS AND CONDITIONS_ + +### APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets `[]` replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same “printed page” as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Modules/lodepng-module/LICENSE-lodepng.txt b/Modules/lodepng-module/LICENSE-lodepng.txt new file mode 100644 index 000000000..c2b21cfb5 --- /dev/null +++ b/Modules/lodepng-module/LICENSE-lodepng.txt @@ -0,0 +1,25 @@ +/* +LodePNG version 20261001 + +Copyright (c) 2005-2026 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + diff --git a/Modules/lodepng-module/README.md b/Modules/lodepng-module/README.md new file mode 100644 index 000000000..ac2d88fc8 --- /dev/null +++ b/Modules/lodepng-module/README.md @@ -0,0 +1,10 @@ +# lodepng-module + +PNG decoding and encoding with [LodePNG](https://github.com/lvandeve/lodepng), usable with and without LVGL. + +Include `` and release decoded or encoded data with `lodepng_free()`. + +## License + +This module is licensed under the [Apache v2.0](LICENSE-Apache-2.0.md) license. +LodePNG is licensed under the [zlib](LICENSE-lodepng.txt) license. diff --git a/Modules/lodepng-module/include/lodepng/lodepng.h b/Modules/lodepng-module/include/lodepng/lodepng.h new file mode 100644 index 000000000..8a361b886 --- /dev/null +++ b/Modules/lodepng-module/include/lodepng/lodepng.h @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +// The C++ wrapper is not compiled: callers use the C API from C and C++ alike +#define LODEPNG_NO_COMPILE_CPP +// Allocations go through the kernel's memory API (see lodepng_malloc() below) +#define LODEPNG_NO_COMPILE_ALLOCATORS + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** Allocates memory, preferring external memory (PSRAM) */ +void* lodepng_malloc(size_t size); + +void* lodepng_realloc(void* ptr, size_t new_size); + +/** Releases memory from lodepng_malloc(), including images returned by the decode and encode functions */ +void lodepng_free(void* ptr); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/lodepng-module/include/lodepng/lodepng_upstream.h b/Modules/lodepng-module/include/lodepng/lodepng_upstream.h new file mode 100644 index 000000000..e1d05c800 --- /dev/null +++ b/Modules/lodepng-module/include/lodepng/lodepng_upstream.h @@ -0,0 +1,2188 @@ +/* +LodePNG version 20261001 + +Copyright (c) 2005-2026 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef LODEPNG_H +#define LODEPNG_H + +#include /*for size_t*/ + +extern const char* LODEPNG_VERSION_STRING; + +/* +The following #defines are used to create code sections. They can be disabled +to disable code sections, which can give faster compile time and smaller binary. +The "NO_COMPILE" defines are designed to be used to pass as defines to the +compiler command to disable them without modifying this header, e.g. +-DLODEPNG_NO_COMPILE_ZLIB for gcc or clang. +*/ +/*deflate & zlib. If disabled, you must specify alternative zlib functions in +the custom_zlib field of the compress and decompress settings*/ +#ifndef LODEPNG_NO_COMPILE_ZLIB +/*pass -DLODEPNG_NO_COMPILE_ZLIB to the compiler to disable this, or comment out LODEPNG_COMPILE_ZLIB below*/ +#define LODEPNG_COMPILE_ZLIB +#endif + +/*png encoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_PNG +/*pass -DLODEPNG_NO_COMPILE_PNG to the compiler to disable this, or comment out LODEPNG_COMPILE_PNG below*/ +#define LODEPNG_COMPILE_PNG +#endif + +/*deflate&zlib decoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_DECODER +/*pass -DLODEPNG_NO_COMPILE_DECODER to the compiler to disable this, or comment out LODEPNG_COMPILE_DECODER below*/ +#define LODEPNG_COMPILE_DECODER +#endif + +/*deflate&zlib encoder and png encoder*/ +#ifndef LODEPNG_NO_COMPILE_ENCODER +/*pass -DLODEPNG_NO_COMPILE_ENCODER to the compiler to disable this, or comment out LODEPNG_COMPILE_ENCODER below*/ +#define LODEPNG_COMPILE_ENCODER +#endif + +/*the optional built in harddisk file loading and saving functions*/ +#ifndef LODEPNG_NO_COMPILE_DISK +/*pass -DLODEPNG_NO_COMPILE_DISK to the compiler to disable this, or comment out LODEPNG_COMPILE_DISK below*/ +#define LODEPNG_COMPILE_DISK +#endif + +/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ +#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +/*pass -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS to the compiler to disable this, +or comment out LODEPNG_COMPILE_ANCILLARY_CHUNKS below*/ +#define LODEPNG_COMPILE_ANCILLARY_CHUNKS +#endif + +/*ability to convert error numerical codes to English text string*/ +#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT +/*pass -DLODEPNG_NO_COMPILE_ERROR_TEXT to the compiler to disable this, +or comment out LODEPNG_COMPILE_ERROR_TEXT below*/ +#define LODEPNG_COMPILE_ERROR_TEXT +#endif + +/*Compile the default allocators (C's free, malloc and realloc). If you disable this, +you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your +source files with custom allocators.*/ +#ifndef LODEPNG_NO_COMPILE_ALLOCATORS +/*pass -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler to disable the built-in ones, +or comment out LODEPNG_COMPILE_ALLOCATORS below*/ +#define LODEPNG_COMPILE_ALLOCATORS +#endif + +/*Disable built-in CRC function, in that case a custom implementation of +lodepng_crc32 must be defined externally so that it can be linked in. +The default built-in CRC code comes with 8KB of lookup tables, so for memory constrained environment you may want it +disabled and provide a much smaller implementation externally as said above. You can find such an example implementation +in a comment in the lodepng.c(pp) file in the 'else' case of the searchable LODEPNG_COMPILE_CRC section.*/ +#ifndef LODEPNG_NO_COMPILE_CRC +/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one, +or comment out LODEPNG_COMPILE_CRC below*/ +#define LODEPNG_COMPILE_CRC +#endif + +/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ +#ifdef __cplusplus +#ifndef LODEPNG_NO_COMPILE_CPP +/*pass -DLODEPNG_NO_COMPILE_CPP to the compiler to disable C++ (not needed if a C-only compiler), +or comment out LODEPNG_COMPILE_CPP below*/ +#define LODEPNG_COMPILE_CPP +#endif +#endif + +#ifdef LODEPNG_COMPILE_CPP +#include +#include +#endif /*LODEPNG_COMPILE_CPP*/ + +#ifdef LODEPNG_COMPILE_PNG +/*The PNG color types (also used for raw image).*/ +typedef enum LodePNGColorType { + LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ + LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ + /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid + byte value from 0 to 255 that could be present in an invalid PNG file header. Do + not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use + the valid color type names above, or numeric values like 1 or 7 when checking for + particular disallowed color type byte values, or cast to integer to print it.*/ + LCT_MAX_OCTET_VALUE = 255 +} LodePNGColorType; + +#ifdef LODEPNG_COMPILE_DECODER +/* +Converts PNG data in memory to raw pixel data. +out: Output parameter. Pointer to buffer that will contain the raw pixel data. + After decoding, its size is w * h * (bytes per pixel) bytes larger than + initially. Bytes per pixel depends on colortype and bitdepth. + Must be freed after usage with free(*out). + Note: for 16-bit per channel colors, uses big endian format like PNG does. +w: Output parameter. Pointer to width of pixel data. +h: Output parameter. Pointer to height of pixel data. +in: Memory buffer with the PNG file. +insize: size of the in buffer. +colortype: the desired color type for the raw output image. See explanation on PNG color types. +bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_DISK +/* +Load PNG from disk, from file with given name. +Same as the other decode functions, but instead takes a filename as input. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); + +/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Converts raw pixel data into a PNG image in memory. The colortype and bitdepth + of the output PNG image cannot be chosen, they are automatically determined + by the colortype, bitdepth and content of the input pixel data. + Note: for 16-bit per channel colors, needs big endian format like PNG does. +out: Output parameter. Pointer to buffer that will contain the PNG image data. + Must be freed after usage with free(*out). +outsize: Output parameter. Pointer to the size in bytes of the out buffer. +image: The raw pixel data to encode. The size of this buffer should be + w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. +w: width of the raw pixel data in pixels. +h: height of the raw pixel data in pixels. +colortype: the color type of the raw input image. See explanation on PNG color types. +bitdepth: the bit depth of the raw input image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DISK +/* +Converts raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. + +NOTE: This overwrites existing files without warning! + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode32_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode24_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng { +#ifdef LODEPNG_COMPILE_DECODER +/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype +is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts PNG file from disk to raw pixel data in memory. +Same as the other decode functions, but instead takes a filename as input. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::string& filename, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype +is that of the raw input data. The output PNG color type will be auto chosen.*/ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts 32-bit RGBA raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. + +NOTE: This overwrites existing files without warning! + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/*Returns an English description of the numerical error code.*/ +const char* lodepng_error_text(unsigned code); +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Settings for zlib decompression*/ +typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; +struct LodePNGDecompressSettings { + /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ + + /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, + return an error, output a data size > max_output_size and all the data up to that point. This is + not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is + ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. + Set to 0 to impose no limit (the default).*/ + size_t max_output_size; + + /*use custom zlib decoder instead of built in one (default: null). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_inflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Settings for zlib compression. Tweaking these settings tweaks the balance +between speed and compression ratio. +*/ +typedef struct LodePNGCompressSettings LodePNGCompressSettings; +struct LodePNGCompressSettings /*deflate = compress*/ { + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ + + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_deflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_PNG +/* +Color mode of an image. Contains all information required to decode the pixel +bits to RGBA colors. This information is the same as used in the PNG file +format, and is used both for PNG and raw image data in LodePNG. +*/ +typedef struct LodePNGColorMode { + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ + + /* + palette (PLTE and tRNS) + + Dynamically allocated with the colors of the palette, including alpha. + This field may not be allocated directly, use lodepng_color_mode_init first, + then lodepng_palette_add per color to correctly initialize it (to ensure size + of exactly 1024 bytes). + + The alpha channels must be set as well, set them to 255 for opaque images. + + When decoding, with the default settings you can ignore this palette, since + LodePNG already fills the palette colors in the pixels of the raw RGBA output, + but when decoding to the original PNG color mode it is needed to reconstruct + the colors. + + The palette is only supported for color type 3. + */ + unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ + size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ + + /* + transparent color key (tRNS) + + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For grayscale PNGs, r, g and b will all 3 be set to the same. + + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. + + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/grayscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ +} LodePNGColorMode; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_color_mode_init(LodePNGColorMode* info); +void lodepng_color_mode_cleanup(LodePNGColorMode* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); +/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); + +void lodepng_palette_clear(LodePNGColorMode* info); +/*add 1 color to the palette*/ +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info); +/*get the amount of color channels used, based on colortype in the struct. +If a palette is used, it counts as 1 channel.*/ +unsigned lodepng_get_channels(const LodePNGColorMode* info); +/*is it a grayscale type? (only colortype 0 or 4)*/ +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +/*has it got an alpha channel? (only colortype 2 or 6)*/ +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +/*has it got a palette? (only colortype 3)*/ +unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +/*only returns true if there is a palette and there is a value in the palette with alpha < 255. +Loops through the palette to check this.*/ +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +/* +Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. +Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). +Returns false if the image can only have opaque pixels. +In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, +or if "key_defined" is true. +*/ +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +/*Returns the byte size of a raw image buffer with given width, height and color mode*/ +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*The information of a Time chunk in PNG.*/ +typedef struct LodePNGTime { + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ +} LodePNGTime; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Information about the PNG image, except pixels, width and height.*/ +typedef struct LodePNGInfo { + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /* + Suggested background color chunk (bKGD) + + This uses the same color mode and bit depth as the PNG (except no alpha channel), + with values truncated to the bit depth in the unsigned integer. + + For grayscale and palette PNGs, the value is stored in background_r. The values + in background_g and background_b are then unused. The decoder will set them + equal to background_r, the encoder ignores them in this case. + + When decoding, you may get these in a different color mode than the one you requested + for the raw pixels: the colortype and bitdepth defined by info_png.color, that is the + ones defined in the header of the PNG image, are used. + + When encoding with auto_convert, you must use the color model defined in info_png.color for + these values. The encoder normally ignores info_png.color when auto_convert is on, but will + use it to interpret these values (and convert copies of them to its chosen color model). + + When encoding, avoid setting this to an expensive color, such as a non-gray value + when the image is gray, or the compression will be worse since it will be forced to + write the PNG with a more expensive color mode (when auto_convert is on). + + The decoder does not use this background color to edit the color of pixels. This is a + completely optional metadata feature. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red/gray/palette component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ + + /* + Non-international text chunks (tEXt and zTXt) + + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. + + All the string fields below including strings, keys, names and language tags are null terminated. + The PNG specification uses null characters for the keys, names and tags, and forbids null + characters to appear in the main text which is why we can use null termination everywhere here. + + A keyword is minimum 1 character and maximum 79 characters long (plus the + additional null terminator). It's discouraged to use a single line length + longer than 79 characters for texts. + + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. + + Standard text chunk keywords and strings are encoded using Latin-1. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char** text_strings; /*the actual text*/ + + /* + International text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys", and the following text encodings are used: + keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. + keys must be 1-79 characters (plus the additional null terminator), the other + strings are any length. + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char** itext_strings; /*the actual international text - UTF-8 string*/ + + /* + Optional exif metadata in exif_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_exif and lodepng_clear_exif. + The exif data is in exif-encoded form but without JPEG markers, starting with the 'II' or 'MM' marker that indicates + endianness. It's up to an exif handling library to encode/decode its information. + */ + unsigned exif_defined; /* Whether exif metadata is present, that is, the PNG image has an eXIf chunk */ + unsigned char* exif; /* The bytes of the exif metadata, if present */ + unsigned exif_size; /* The size of the exif data in bytes */ + + + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; + + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + + /* + Color profile related chunk types: cICP, iCPP, sRGB, gAMA, cHRM, sBIT + + LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color + profile values. It merely passes on the information. If you wish to use color profiles and convert colors, a separate + color management library should be used. There is also a limited library for this in lodepng_util.h. + + There are 4 types of (sets of) chunks providing color information. If multiple are present, each will be decoded by + LodePNG, but only one should be handled by the user, with the following order of priority depending on what the user + supports: + 1: cICP: Coding-independent code points (CICP) + 2: iCCP: ICC profile + 3: sRGB: indicates the image is in the sRGB color profile + 4: gAMA and cHRM: indicates a gamma and chromaticity value to define the color profile + */ + + /* + gAMA chunk: Image gamma + Optional, overridden by cICP, iCCP or sRGB if those are present. + Together with cHRM, this is a primitive way of specifying the image color profile. + */ + unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ + unsigned gama_gamma; /* Gamma exponent times 100000 */ + + /* + cHRM chunk: Primary chromaticities and white point + Optional, overridden by cICP, iCCP or sRGB if those are present. + Together with gAMA, this is a primitive way of specifying the image color profile. + */ + unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ + unsigned chrm_white_x; /* White Point x times 100000 */ + unsigned chrm_white_y; /* White Point y times 100000 */ + unsigned chrm_red_x; /* Red x times 100000 */ + unsigned chrm_red_y; /* Red y times 100000 */ + unsigned chrm_green_x; /* Green x times 100000 */ + unsigned chrm_green_y; /* Green y times 100000 */ + unsigned chrm_blue_x; /* Blue x times 100000 */ + unsigned chrm_blue_y; /* Blue y times 100000 */ + + /* + sRGB chunk: Indicates the image is in the sRGB color space. + Optional. Should not appear at the same time as iCCP. + If gAMA is also present gAMA must contain value 45455. + If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. + */ + unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ + unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ + + /* + iCCP chunk: Embedded ICC profile. + Optional. Should not appear at the same time as sRGB. + + Contains ICC profile, which can use any version of the ICC.1 specification by the International Color Consortium. See + its specification for more details. LodePNG does not parse or use the ICC profile (except its color space header + field for "RGB" or "GRAY", see below), a separate library to handle the ICC data format is needed to use it for color + management and conversions. + + For encoding, if iCCP is present, the PNG specification recommends to also add gAMA and cHRM chunks that approximate + the ICC profile, for compatibility with applications that don't use the ICC chunk. This is not required, and it's up + to the user to compute approximate values and set then in the appropriate gama_ and chrm_ fields, LodePNG does not do + this automatically since it does not interpret the ICC profile. + + For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray PNG color + types (types 2, 3 and 6) and a "GRAY" profile for gray PNG color types (types 1 and 4). If you disable auto_convert, + you must ensure the ICC profile type matches your requested color type, else the encoder gives an error. If + auto_convert is enabled (the default), and the ICC profile is not a correct match for the pixel data, this will result + in an encoder error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of + the pixel data if the pixels could be encoded as grayscale but the ICC profile is RGB. + + To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so + make sure you compute it carefully to avoid the above problems. + */ + unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ + char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ + /* + The ICC profile in iccp_profile_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_icc and lodepng_clear_icc. + */ + unsigned char* iccp_profile; + unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ + + /* + cICP chunk: Coding-independent code points for video signal type identification. + Optional. If present, and supported, overrides iCCP, sRGB, gAMA and cHRM. + The meaning of the values are as defined in the specification ITU-T-H.273. LodePNG does not + use these values, only passes on the metadata. The meaning of the values is they are enum + values representing certain color spaces, including HDR color spaces, such as Display P3, + PQ and HLG. The video full range flag value should typically be 1 for the use cases of PNG + images, but can be 0 for narrow-range images in certain video editing workflows. + */ + unsigned cicp_defined; /* Whether an cICP chunk is present (0 = not present, 1 = present). */ + unsigned cicp_color_primaries; /* Colour primaries value */ + unsigned cicp_transfer_function; /* Transfer characteristics value */ + unsigned cicp_matrix_coefficients; /* Matrix coefficients value */ + unsigned cicp_video_full_range_flag; /* Video full range flag value */ + + /* + mDCV chunk: Mastering Display Color Volume. + Optional, typically used in conjunction with certain HDR color spaces that can + be represented by the cICP chunk. + See the PNG specification, third edition, for more information on this chunk. + All the red, green, blue and white x and y values are encoded as 16-bit + integers and therefore must be in range 0-65536. The min and max luminance + values are 32-bit integers. + */ + unsigned mdcv_defined; /* Whether an mDCV chunk is present (0 = not present, 1 = present). */ + /* Mastering display color primary chromaticities (CIE 1931 x,y of R,G,B) */ + unsigned mdcv_red_x; /* Red x times 50000 */ + unsigned mdcv_red_y; /* Red y times 50000 */ + unsigned mdcv_green_x; /* Green x times 50000 */ + unsigned mdcv_green_y; /* Green y times 50000 */ + unsigned mdcv_blue_x; /* Blue x times 50000 */ + unsigned mdcv_blue_y; /* Blue y times 50000 */ + /* Mastering display white point chromaticity (CIE 1931 x,y) */ + unsigned mdcv_white_x; /* White Point x times 50000 */ + unsigned mdcv_white_y; /* White Point y times 50000 */ + /* Mastering display luminance */ + unsigned mdcv_max_luminance; /* Max luminance in cd/m^2 times 10000 */ + unsigned mdcv_min_luminance; /* Min luminance in cd/m^2 times 10000 */ + + /* + cLLI chunk: Content Light Level Information. + Optional, typically used in conjunction with certain HDR color spaces that can + be represented by the cICP chunk. + See the PNG specification, third edition, for more information on this chunk. + The clli_max_cll and clli_max_fall values are 32-bit integers. + */ + unsigned clli_defined; /* Whether a cLLI chunk is present (0 = not present, 1 = present). */ + unsigned clli_max_cll; /* Maximum Content Light Level (MaxCLL) in cd/m^2 times 10000 */ + unsigned clli_max_fall; /* Maximum Frame-Average Light Level (MaxFALL) in cd/m^2 times 10000 */ + + /* + sBIT chunk: significant bits. + Optional metadata, only set this if needed. + + If defined, these values give the bit depth of the original data. Since PNG only stores 1, 2, 4, 8 or 16-bit + per channel data, the significant bits value can be used to indicate the original encoded data has another + sample depth, such as 10 or 12. + + Encoders using this value, when storing the pixel data, should use the most significant bits + of the data to store the original bits, and use a good sample depth scaling method such as + "left bit replication" to fill in the least significant bits, rather than fill zeroes. + + Decoders using this value, if able to work with data that's e.g. 10-bit or 12-bit, should right + shift the data to go back to the original bit depth, but decoders are also allowed to ignore + sbit and work e.g. with the 8-bit or 16-bit data from the PNG directly, since thanks + to the encoder contract, the values encoded in PNG are in valid range for the PNG bit depth. + + For grayscale images, sbit_g and sbit_b are not used, and for images that don't use color + type RGBA or grayscale+alpha, sbit_a is not used (it's not used even for palette images with + translucent palette values, or images with color key). The values that are used must be + greater than zero and smaller than or equal to the PNG bit depth. + + The color type from the header in the PNG image defines these used and unused fields: if + decoding with a color mode conversion, such as always decoding to RGBA, this metadata still + only uses the color type of the original PNG, and may e.g. lack the alpha channel info + if the PNG was RGB. When encoding with auto_convert (as well as without), also always the + color model defined in info_png.color determines this. + + NOTE: enabling sbit can hurt compression, because the encoder can then not always use + auto_convert to choose a more optimal color mode for the data, because the PNG format has + strict requirements for the allowed sbit values in combination with color modes. + For example, setting these fields to 10-bit will force the encoder to keep using a 16-bit per channel + color mode, even if the pixel data would in fact fit in a more efficient 8-bit mode. + */ + unsigned sbit_defined; /*is significant bits given? if not, the values below are unused*/ + unsigned sbit_r; /*red or gray component of significant bits*/ + unsigned sbit_g; /*green component of significant bits*/ + unsigned sbit_b; /*blue component of significant bits*/ + unsigned sbit_a; /*alpha component of significant bits*/ + + /* End of color profile related chunks */ + + + /* + unknown chunks: chunks not known by LodePNG, passed on byte for byte. + + There are 3 buffers, one for each position in the PNG where unknown chunks can appear. + Each buffer contains all unknown chunks for that position consecutively. + The 3 positions are: + 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. + + For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag + above in here, since the encoder will blindly follow this and could then encode an invalid PNG file + (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use + this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), + or any non-standard PNG chunk. + + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char* unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGInfo; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_info_init(LodePNGInfo* info); +/*destructs the LodePNGInfo and brings it to invalid state, requiring lodepng_info_init again before reusing it*/ +void lodepng_info_cleanup(LodePNGInfo* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ +void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ +void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ + +/*replaces if exists*/ +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); +void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the profile again after you filled it in*/ + +/*replaces if exists*/ +unsigned lodepng_set_exif(LodePNGInfo* info, const unsigned char* exif, unsigned exif_size); +void lodepng_clear_exif(LodePNGInfo* info); /*use this to clear the exif metadata again after you filled it in*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/* +Converts raw buffer from one color type to another color type, based on +LodePNGColorMode structs to describe the input and output color type. +See the reference manual at the end of this header file to see which color conversions are supported. +return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) +The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel +of the output color type (lodepng_get_bpp). +For < 8 bpp images, there should not be padding bits at the end of scanlines. +For 16-bit per channel colors, uses big endian format like PNG does. +Return value is LodePNG error code +*/ +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DECODER +/* +Settings for the decoder. This contains settings for the PNG and the Zlib +decoder, but not the Info settings from the Info structs. +*/ +typedef struct LodePNGDecoderSettings { + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + + /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ + unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ + /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable + errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some + strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters + in string keys, invalid characters in chunk types names, etc... */ + + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; + + /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, + unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. + By default it is a value that prevents unreasonably large strings from hogging memory. */ + size_t max_text_size; + + /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to + 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any + legitimate profile could be to hog memory. */ + size_t max_icc_size; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGDecoderSettings; + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/*strategy to use to choose the PNG filter per scanline. Strategies 0-4 correspond +to each of the 5 filter types PNG supports, the next values are adaptive strategies*/ +typedef enum LodePNGFilterStrategy { + /*every filter at zero*/ + LFS_ZERO = 0, + /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ + LFS_ONE = 1, + LFS_TWO = 2, + LFS_THREE = 3, + LFS_FOUR = 4, + /*Use the filter out of the 5 above types that gives minimum sum, by trying each one. This is the adaptive filtering + suggested heuristic in the PNG standard chapter 'Filter selection'.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED +} LodePNGFilterStrategy; + +/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), +which helps decide which color model to use for encoding. +Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ +typedef struct LodePNGColorStats { + unsigned colored; /*not grayscale*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ + unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ + size_t numpixels; + + /*user settings for computing/using the stats*/ + unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ + unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ +} LodePNGColorStats; + +void lodepng_color_stats_init(LodePNGColorStats* stats); + +/*Get a LodePNGColorStats of the image. The stats must already have been inited. +Returns error code (e.g. alloc fail) or 0 if ok.*/ +unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); + +/*Settings for the encoder.*/ +typedef struct LodePNGEncoderSettings { + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ + + /*automatically choose output PNG color type. If false, must explicitly choose the output color + type in state.info_png.color.colortype, info_png.color.bitdepth and optionally its palette. + Default: true*/ + unsigned auto_convert; + + /*If true, follows the suggestion in the PNG standard in chapter 'Filter selection': if the PNG uses + a palette or lower than 8 bit depth, set all filters to zero. + In other cases this will use the heuristic from the chosen filter_strategy. The PNG standard + suggests LFS_MINSUM for those cases.*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char* predefined_filters; + + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is always created. If color type is explicitly set + to a grayscale type (1 or 4), this is not done and is ignored. If enabling this, + a palette must be present in the info_png. + NOTE: enabling this may worsen compression if auto_convert is used to choose + optimal color mode, because it cannot use grayscale color modes in this case*/ + unsigned force_palette; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGEncoderSettings; + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) +/*The settings, state and information for extended encoding and decoding. + +Using this struct requires using lodepng_state_init to initialize it +and using lodepng_state_cleanup to deconstruct it. If using C++, you can +use lodepng::State instead which does those things automatically with RAII. + +While a LodePNGState can be reused once in a chain of lodepng_decode followed by +lodepng_encode, it's not recommended to reuse it for multiple encode, decode +or inspect calls, and if any such function returns an error code, the +LodePNGState should not be reused at all as it can be in an unexpected state.. +*/ +typedef struct LodePNGState { +#ifdef LODEPNG_COMPILE_DECODER + LodePNGDecoderSettings decoder; /*the decoding settings*/ +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + LodePNGEncoderSettings encoder; /*the encoding settings*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; /*deprecated, use the return value of the encode/decode functions to check errors instead*/ +} LodePNGState; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_state_init(LodePNGState* state); +/*destructs the LodePNGState and brings it to invalid state, requiring lodepng_info_init again before reusing it*/ +void lodepng_state_cleanup(LodePNGState* state); +/*return value is error code (0 means no error)*/ +unsigned lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_DECODER +/* +Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and +getting much more information about the PNG image and color mode. +*/ +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); + +/* +Read the PNG header, but not the actual data. This returns only the information +that is in the IHDR chunk of the PNG, such as width, height and color type. The +information is placed in the info_png field of the LodePNGState. +*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* +Reads one metadata chunk (other than IHDR, which is handled by lodepng_inspect) +of the PNG file and outputs what it read in the state. Returns error code on failure. +Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const +to find the desired chunk type, and if non null use lodepng_inspect_chunk (with +chunk_pointer - start_of_file as pos). +Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...). +Ignores unsupported, unknown, non-metadata or IHDR chunks (without error). +Requirements: &in[pos] must point to start of a chunk, must use regular +lodepng_inspect first since format of most other chunks depends on IHDR, and if +there is a PLTE chunk, that one must be inspected before tRNS or bKGD. +*/ +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_ENCODER +/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* +The lodepng_chunk functions are normally not needed, except to traverse the +unknown chunks stored in the LodePNGInfo struct, or add new ones to it. +It also allows traversing the chunks of an encoded PNG file yourself. + +The chunk pointer always points to the beginning of the chunk itself, that is +the first byte of the 4 length bytes. + +In the PNG file format, chunks have the following format: +-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer) +-4 bytes chunk type (ASCII a-z,A-Z only, see below) +-length bytes of data (may be 0 bytes if length was 0) +-4 bytes of CRC, computed on chunk name + data + +The first chunk starts at the 8th byte of the PNG file, the entire rest of the file +exists out of concatenated chunks with the above format. + +PNG standard chunk ASCII naming conventions: +-First byte: uppercase = critical, lowercase = ancillary +-Second byte: uppercase = public, lowercase = private +-Third byte: must be uppercase +-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy +*/ + +/* +Gets the length of the data of the chunk. Total chunk length has 12 bytes more. +There must be at least 4 bytes to read from. If the result value is too large, +it may be corrupt data. +*/ +unsigned lodepng_chunk_length(const unsigned char* chunk); + +/*puts the 4-byte type in null terminated string*/ +void lodepng_chunk_type(char type[5], const unsigned char* chunk); + +/*check if the type is the given type*/ +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); + +/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); + +/*0: public, 1: private (see PNG standard)*/ +unsigned char lodepng_chunk_private(const unsigned char* chunk); + +/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); + +/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ +unsigned char* lodepng_chunk_data(unsigned char* chunk); +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); + +/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ +unsigned lodepng_chunk_check_crc(const unsigned char* chunk); + +/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ +void lodepng_chunk_generate_crc(unsigned char* chunk); + +/* +Iterate to next chunks, allows iterating through all chunks of the PNG file. +Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call, +or the 8th byte of a PNG file which always has the first chunk), or alternatively may +point to the first byte of the PNG file (which is not a chunk but the magic header, the +function will then skip over it and return the first real chunk). +Will output pointer to the start of the next chunk, or at or beyond end of the file if there +is no more chunk after this or possibly if the chunk is corrupt. +Start this process at the 8th byte of the PNG file. +In a non-corrupt PNG file, the last chunk should have name "IEND". +*/ +unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end); +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end); + +/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ +unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]); +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); + +/* +Appends chunk to the data in out. The given chunk should already have its chunk header. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk); + +/* +Appends new chunk to out. The chunk to append is given by giving its length, type +and data separately. The type is a 4-letter string. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, size_t length, + const char* type, const unsigned char* data); + + +/*Calculate CRC32 of buffer*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len); +#endif /*LODEPNG_COMPILE_PNG*/ + + +#ifdef LODEPNG_COMPILE_ZLIB +/* +This zlib part can be used independently to zlib compress and decompress a +buffer. It cannot be used to create gzip files however, and it only supports the +part of zlib that is required for PNG, it does not support dictionaries. +*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); + +/* +Decompresses Zlib data. Reallocates the out buffer and appends the data. The +data must be according to the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Compresses data with Zlib. Reallocates the out buffer and appends the data. +Zlib adds a small header and trailer around the deflate data. +The data is output in the format of the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +/* +Find length-limited Huffman code for given frequencies. This function is in the +public interface only for tests, it's used internally by lodepng_deflate. +*/ +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen); + +/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into buffer. The function allocates the out buffer, and +after usage you should free it. +out: output parameter, contains pointer to loaded buffer. +outsize: output parameter, size of the allocated out buffer +filename: the path to the file to load +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + +/* +Save a file from buffer to disk. Warning, if it exists, this function overwrites +the file without warning! +buffer: the buffer to write +buffersize: size of the buffer to write +filename: the path to the file to save to +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory +*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ + +#ifdef LODEPNG_COMPILE_CPP +/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ +namespace lodepng { +#ifdef LODEPNG_COMPILE_PNG +/* Wrapper around LodePNGState, which automatically calls lodepng_state_init in the constructor +and lodepng_state_cleanup in the desctructor.*/ +class State : public LodePNGState { + public: + State(); + State(const State& other); + ~State(); + State& operator=(const State& other); +}; + +#ifdef LODEPNG_COMPILE_DECODER +/* Same as other lodepng::decode, but using a State for more settings and information. */ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Same as other lodepng::encode, but using a State for more settings and information. */ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into an std::vector. +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory +*/ +unsigned load_file(std::vector& buffer, const std::string& filename); + +/* +Save the binary data in an std::vector to a file on disk. The file is overwritten +without warning. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory +*/ +unsigned save_file(const std::vector& buffer, const std::string& filename); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_PNG */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +/* Zlib-decompress an unsigned char buffer */ +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); + +/* Zlib-decompress an std::vector */ +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Zlib-compress an unsigned char buffer */ +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); + +/* Zlib-compress an std::vector */ +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +/* +TODO: +[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often +[.] check compatibility with various compilers - done but needs to be redone for every newer version +[X] converting color to 16-bit per channel types +[X] support color profile chunk types (but never let them touch RGB values by default) +[ ] support all second edition public PNG chunk types (almost done except sPLT and hIST) +[X] support non-animation third edition public PNG chunk types: eXIf, cICP, mDCV, cLLI +[ ] make sure encoder generates no chunks with size > (2^31)-1 +[ ] partial decoding (stream processing) +[X] let the "isFullyOpaque" function check color keys and transparent palettes too +[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" +[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58) +[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... +[ ] error messages with line numbers (and version) +[ ] errors in state instead of as return code? +[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk +[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes +[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +[ ] allow user to give data (void*) to custom allocator +[X] provide alternatives for C library functions not present on some platforms (memcpy, ...) +*/ + +#endif /*LODEPNG_H inclusion guard*/ + +/* +LodePNG Documentation +--------------------- + +0. table of contents +-------------------- + + 1. about + 1.1. supported features + 1.2. features not supported + 2. C and C++ version + 3. security + 4. decoding + 5. encoding + 6. color conversions + 6.1. PNG color types + 6.2. color conversions + 6.3. padding bits + 6.4. A note about 16-bits per channel and endianness + 7. error values + 8. chunks and PNG editing + 9. compiler support + 10. examples + 10.1. decoder C++ example + 10.2. decoder C example + 11. state settings reference + 12. changes + 13. contact information + + +1. about +-------- + +PNG is a file format to store raster images losslessly with good compression, +supporting different color types and alpha channel. + +LodePNG is a PNG codec according to the Portable Network Graphics (PNG) +Specification (Second Edition) - W3C Recommendation 10 November 2003. + +The specifications used are: + +*) Portable Network Graphics (PNG) Specification (Second Edition): + http://www.w3.org/TR/2003/REC-PNG-20031110 +*) RFC 1950 ZLIB Compressed Data Format version 3.3: + http://www.gzip.org/zlib/rfc-zlib.html +*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: + http://www.gzip.org/zlib/rfc-deflate.html + +The most recent version of LodePNG can currently be found at +http://lodev.org/lodepng/ + +LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds +extra functionality. + +LodePNG exists out of two files: +-lodepng.h: the header file for both C and C++ +-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage + +If you want to start using LodePNG right away without reading this doc, get the +examples from the LodePNG website to see how to use it in code, or check the +smaller examples in chapter 13 here. + +LodePNG is simple but only supports the basic requirements. To achieve +simplicity, the following design choices were made: There are no dependencies +on any external library. There are functions to decode and encode a PNG with +a single function call, and extended versions of these functions taking a +LodePNGState struct allowing to specify or get more information. By default +the colors of the raw image are always RGB or RGBA, no matter what color type +the PNG file uses. To read and write files, there are simple functions to +convert the files to/from buffers in memory. + +This all makes LodePNG suitable for loading textures in games, demos and small +programs, ... It's less suitable for full fledged image editors, loading PNGs +over network (it requires all the image data to be available before decoding can +begin), life-critical systems, ... + +1.1. supported features +----------------------- + +The following features are supported by the decoder: + +*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, + or the same color type as the PNG +*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image +*) Adam7 interlace and deinterlace for any color type +*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk +*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) zlib decompression (inflate) +*) zlib compression (deflate) +*) CRC32 and ADLER32 checksums +*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only, + plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system. +*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. +*) the following chunks are supported by both encoder and decoder: + IHDR: header information + PLTE: color palette + IDAT: pixel data + IEND: the final chunk + tRNS: transparency for palettized images + tEXt: textual information + zTXt: compressed textual information + iTXt: international textual information + bKGD: suggested background color + pHYs: physical dimensions + tIME: modification time + cHRM: RGB chromaticities + gAMA: RGB gamma correction + iCCP: ICC color profile + sRGB: rendering intent + sBIT: significant bits + +1.2. features not supported +--------------------------- + +The following features are not (yet) supported: + +*) some features needed to make a conformant PNG-Editor might be still missing. +*) partial loading/stream processing. All data must be available and is processed in one call. +*) The hIST and sPLT public chunks are not (yet) supported but treated as unknown chunks + + +2. C and C++ version +-------------------- + +The C version uses buffers allocated with alloc that you need to free() +yourself. You need to use init and cleanup functions for each struct whenever +using a struct from the C version to avoid exploits and memory leaks. + +The C++ version has extra functions with std::vectors in the interface and the +lodepng::State class which is a LodePNGState with constructor and destructor. + +These files work without modification for both C and C++ compilers because all +the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers +ignore it, and the C code is made to compile both with strict ISO C90 and C++. + +To use the C++ version, you need to rename the source file to lodepng.cpp +(instead of lodepng.c), and compile it with a C++ compiler. + +To use the C version, you need to rename the source file to lodepng.c (instead +of lodepng.cpp), and compile it with a C compiler. + + +3. Security +----------- + +Even if carefully designed, it's always possible that LodePNG contains possible +exploits. If you discover one, please let me know, and it will be fixed. + +When using LodePNG, care has to be taken with the C version of LodePNG, as well +as the C-style structs when working with C++. The following conventions are used +for all C-style structs: + +-if a struct has a corresponding init function, always call the init function when making a new one +-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks +-if a struct has a corresponding copy function, use the copy function instead of "=". + The destination must also be inited already. + + +4. Decoding +----------- + +Decoding converts a PNG compressed image to a raw pixel buffer. + +Most documentation on using the decoder is at its declarations in the header +above. For C, simple decoding can be done with functions such as +lodepng_decode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_decode. For C++, all decoding can be done with the +various lodepng::decode functions, and lodepng::State can be used for advanced +features. + +When using the LodePNGState, it uses the following fields for decoding: +*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here +*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get +*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use + +LodePNGInfo info_png +-------------------- + +After decoding, this contains extra information of the PNG image, except the actual +pixels, width and height because these are already gotten directly from the decoder +functions. + +It contains for example the original color type of the PNG image, text comments, +suggested background color, etc... More details about the LodePNGInfo struct are +at its declaration documentation. + +LodePNGColorMode info_raw +------------------------- + +When decoding, here you can specify which color type you want +the resulting raw image to be. If this is different from the colortype of the +PNG, then the decoder will automatically convert the result. This conversion +always works, except if you want it to convert a color PNG to grayscale or to +a palette with missing colors. + +By default, 32-bit color is used for the result. + +LodePNGDecoderSettings decoder +------------------------------ + +The settings can be used to ignore the errors created by invalid CRC and Adler32 +chunks, and to disable the decoding of tEXt chunks. + +There's also a setting color_convert, true by default. If false, no conversion +is done, the resulting data will be as it was in the PNG (after decompression) +and you'll have to puzzle the colors of the pixels together yourself using the +color type information in the LodePNGInfo. + + +5. Encoding +----------- + +Encoding converts a raw pixel buffer to a PNG compressed image. + +Most documentation on using the encoder is at its declarations in the header +above. For C, simple encoding can be done with functions such as +lodepng_encode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_encode. For C++, all encoding can be done with the +various lodepng::encode functions, and lodepng::State can be used for advanced +features. + +Like the decoder, the encoder can also give errors. However it gives less errors +since the encoder input is trusted, the decoder input (a PNG image that could +be forged by anyone) is not trusted. + +When using the LodePNGState, it uses the following fields for encoding: +*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. +*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has +*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use + +LodePNGInfo info_png +-------------------- + +When encoding, you use this the opposite way as when decoding: for encoding, +you fill in the values you want the PNG to have before encoding. By default it's +not needed to specify a color type for the PNG since it's automatically chosen, +but it's possible to choose it yourself given the right settings. + +The encoder will not always exactly match the LodePNGInfo struct you give, +it tries as close as possible. Some things are ignored by the encoder. The +encoder uses, for example, the following settings from it when applicable: +colortype and bitdepth, text chunks, time chunk, the color key, the palette, the +background color, the interlace method, unknown chunks, ... + +When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. +If the palette contains any colors for which the alpha channel is not 255 (so +there are translucent colors in the palette), it'll add a tRNS chunk. + +LodePNGColorMode info_raw +------------------------- + +You specify the color type of the raw image that you give to the input here, +including a possible transparent color key and palette you happen to be using in +your raw image data. + +By default, 32-bit color is assumed, meaning your input has to be in RGBA +format with 4 bytes (unsigned chars) per pixel. + +LodePNGEncoderSettings encoder +------------------------------ + +The following settings are supported (some are in sub-structs): +*) auto_convert: when this option is enabled, the encoder will +automatically choose the smallest possible color mode (including color key) that +can encode the colors of all pixels without information loss. +*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, + 2 = dynamic huffman tree (best compression). Should be 2 for proper + compression. +*) use_lz77: whether or not to use LZ77 for compressed block types. Should be + true for proper compression. +*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value + 2048 by default, but can be set to 32768 for better, but slow, compression. +*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE + chunk if force_palette is true. This can used as suggested palette to convert + to by viewers that don't support more than 256 colors (if those still exist) +*) add_id: add text chunk "Encoder: LodePNG " to the image. +*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. + zTXt chunks use zlib compression on the text. This gives a smaller result on + large texts but a larger result on small texts (such as a single program name). + It's all tEXt or all zTXt though, there's no separate setting per text yet. + + +6. color conversions +-------------------- + +An important thing to note about LodePNG, is that the color type of the PNG, and +the color type of the raw image, are completely independent. By default, when +you decode a PNG, you get the result as a raw image in the color type you want, +no matter whether the PNG was encoded with a palette, grayscale or RGBA color. +And if you encode an image, by default LodePNG will automatically choose the PNG +color type that gives good compression based on the values of colors and amount +of colors in the image. It can be configured to let you control it instead as +well, though. + +To be able to do this, LodePNG does conversions from one color mode to another. +It can convert from almost any color type to any other color type, except the +following conversions: RGB to grayscale is not supported, and converting to a +palette when the palette doesn't have a required color is not supported. This is +not supported on purpose: this is information loss which requires a color +reduction algorithm that is beyond the scope of a PNG encoder (yes, RGB to gray +is easy, but there are multiple ways if you want to give some channels more +weight). + +By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB +color, no matter what color type the PNG has. And by default when encoding, +LodePNG automatically picks the best color model for the output PNG, and expects +the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control +the color format of the images yourself, you can skip this chapter. + +6.1. PNG color types +-------------------- + +A PNG image can have many color types, ranging from 1-bit color to 64-bit color, +as well as palettized color modes. After the zlib decompression and unfiltering +in the PNG image is done, the raw pixel data will have that color type and thus +a certain amount of bits per pixel. If you want the output raw image after +decoding to have another color type, a conversion is done by LodePNG. + +The PNG specification gives the following color types: + +0: grayscale, bit depths 1, 2, 4, 8, 16 +2: RGB, bit depths 8 and 16 +3: palette, bit depths 1, 2, 4 and 8 +4: grayscale with alpha, bit depths 8 and 16 +6: RGBA, bit depths 8 and 16 + +Bit depth is the amount of bits per pixel per color channel. So the total amount +of bits per pixel is: amount of channels * bitdepth. + +6.2. color conversions +---------------------- + +As explained in the sections about the encoder and decoder, you can specify +color types and bit depths in info_png and info_raw to change the default +behaviour. + +If, when decoding, you want the raw image to be something else than the default, +you need to set the color type and bit depth you want in the LodePNGColorMode, +or the parameters colortype and bitdepth of the simple decoding function. + +If, when encoding, you use another color type than the default in the raw input +image, you need to specify its color type and bit depth in the LodePNGColorMode +of the raw image, or use the parameters colortype and bitdepth of the simple +encoding function. + +If, when encoding, you don't want LodePNG to choose the output PNG color type +but control it yourself, you need to set auto_convert in the encoder settings +to false, and specify the color type you want in the LodePNGInfo of the +encoder (including palette: it can generate a palette if auto_convert is true, +otherwise not). + +If the input and output color type differ (whether user chosen or auto chosen), +LodePNG will do a color conversion, which follows the rules below, and may +sometimes result in an error. + +To avoid some confusion: +-the decoder converts from PNG to raw image +-the encoder converts from raw image to PNG +-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image +-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG +-when encoding, the color type in LodePNGInfo is ignored if auto_convert + is enabled, it is automatically generated instead +-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original + PNG image, but it can be ignored since the raw image has the color type you requested instead +-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion + between the color types is done if the color types are supported. If it is not + supported, an error is returned. If the types are the same, no conversion is done. +-even though some conversions aren't supported, LodePNG supports loading PNGs from any + colortype and saving PNGs to any colortype, sometimes it just requires preparing + the raw image correctly before encoding. +-both encoder and decoder use the same color converter. + +The function lodepng_convert does the color conversion. It is available in the +interface but normally isn't needed since the encoder and decoder already call +it. + +Non supported color conversions: +-color to grayscale when non-gray pixels are present: no error is thrown, but +the result will look ugly because only the red channel is taken (it assumes all +three channels are the same in this case so ignores green and blue). The reason +no error is given is to allow converting from three-channel grayscale images to +one-channel even if there are numerical imprecisions. +-anything to palette when the palette does not have an exact match for a from-color +in it: in this case an error is thrown + +Supported color conversions: +-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA +-any gray or gray+alpha, to gray or gray+alpha +-anything to a palette, as long as the palette has the requested colors in it +-removing alpha channel +-higher to smaller bitdepth, and vice versa + +If you want no color conversion to be done (e.g. for speed or control): +-In the encoder, you can make it save a PNG with any color type by giving the +raw color mode and LodePNGInfo the same color mode, and setting auto_convert to +false. +-In the decoder, you can make it store the pixel data in the same color type +as the PNG has, by setting the color_convert setting to false. Settings in +info_raw are then ignored. + +6.3. padding bits +----------------- + +In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines +have a bit amount that isn't a multiple of 8, then padding bits are used so that each +scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. +The raw input image you give to the encoder, and the raw output image you get from the decoder +will NOT have these padding bits, e.g. in the case of a 1-bit image with a width +of 7 pixels, the first pixel of the second scanline will the 8th bit of the first byte, +not the first bit of a new byte. + +6.4. A note about 16-bits per channel and endianness +---------------------------------------------------- + +LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like +for any other color format. The 16-bit values are stored in big endian (most +significant byte first) in these arrays. This is the opposite order of the +little endian used by x86 CPU's. + +LodePNG always uses big endian because the PNG file format does so internally. +Conversions to other formats than PNG uses internally are not supported by +LodePNG on purpose, there are myriads of formats, including endianness of 16-bit +colors, the order in which you store R, G, B and A, and so on. Supporting and +converting to/from all that is outside the scope of LodePNG. + +This may mean that, depending on your use case, you may want to convert the big +endian output of LodePNG to little endian with a for loop. This is certainly not +always needed, many applications and libraries support big endian 16-bit colors +anyway, but it means you cannot simply cast the unsigned char* buffer to an +unsigned short* buffer on x86 CPUs. + + +7. error values +--------------- + +All functions in LodePNG that return an error code, return 0 if everything went +OK, or a non-zero code if there was an error. + +The meaning of the LodePNG error values can be retrieved with the function +lodepng_error_text: given the numerical error code, it returns a description +of the error in English as a string. + +Check the implementation of lodepng_error_text to see the meaning of each code. + +It is not recommended to use the numerical values to programmatically make +different decisions based on error types as the numbers are not guaranteed to +stay backwards compatible. They are for human consumption only. Programmatically +only 0 or non-0 matter. + + +8. chunks and PNG editing +------------------------- + +If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG +editor that should follow the rules about handling of unknown chunks, or if your +program is able to read other types of chunks than the ones handled by LodePNG, +then that's possible with the chunk functions of LodePNG. + +A PNG chunk has the following layout: + +4 bytes length +4 bytes type name +length bytes data +4 bytes CRC + +8.1. iterating through chunks +----------------------------- + +If you have a buffer containing the PNG image data, then the first chunk (the +IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the +signature of the PNG and are not part of a chunk. But if you start at byte 8 +then you have a chunk, and can check the following things of it. + +NOTE: none of these functions check for memory buffer boundaries. To avoid +exploits, always make sure the buffer contains all the data of the chunks. +When using lodepng_chunk_next, make sure the returned value is within the +allocated memory. + +unsigned lodepng_chunk_length(const unsigned char* chunk): + +Get the length of the chunk's data. The total chunk length is this length + 12. + +void lodepng_chunk_type(char type[5], const unsigned char* chunk): +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): + +Get the type of the chunk or compare if it's a certain type + +unsigned char lodepng_chunk_critical(const unsigned char* chunk): +unsigned char lodepng_chunk_private(const unsigned char* chunk): +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): + +Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). +Check if the chunk is private (public chunks are part of the standard, private ones not). +Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical +chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your +program doesn't handle that type of unknown chunk. + +unsigned char* lodepng_chunk_data(unsigned char* chunk): +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): + +Get a pointer to the start of the data of the chunk. + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk): +void lodepng_chunk_generate_crc(unsigned char* chunk): + +Check if the crc is correct or generate a correct one. + +unsigned char* lodepng_chunk_next(unsigned char* chunk): +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): + +Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these +functions do no boundary checking of the allocated data whatsoever, so make sure there is enough +data available in the buffer to be able to go to the next chunk. + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk): +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, + const char* type, const unsigned char* data): + +These functions are used to create new chunks that are appended to the data in *out that has +length *outsize. The append function appends an existing chunk to the new data. The create +function creates a new chunk with the given parameters and appends it. Type is the 4-letter +name of the chunk. + +8.2. chunks in info_png +----------------------- + +The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 +buffers (each with size) to contain 3 types of unknown chunks: +the ones that come before the PLTE chunk, the ones that come between the PLTE +and the IDAT chunks, and the ones that come after the IDAT chunks. +It's necessary to make the distinction between these 3 cases because the PNG +standard forces to keep the ordering of unknown chunks compared to the critical +chunks, but does not force any other ordering rules. + +info_png.unknown_chunks_data[0] is the chunks before PLTE +info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT +info_png.unknown_chunks_data[2] is the chunks after IDAT + +The chunks in these 3 buffers can be iterated through and read by using the same +way described in the previous subchapter. + +When using the decoder to decode a PNG, you can make it store all unknown chunks +if you set the option settings.remember_unknown_chunks to 1. By default, this +option is off (0). + +The encoder will always encode unknown chunks that are stored in the info_png. +If you need it to add a particular chunk that isn't known by LodePNG, you can +use lodepng_chunk_append or lodepng_chunk_create to the chunk data in +info_png.unknown_chunks_data[x]. + +Chunks that are known by LodePNG should not be added in that way. E.g. to make +LodePNG add a bKGD chunk, set background_defined to true and add the correct +parameters there instead. + + +9. compiler support +------------------- + +No libraries other than the current standard C library are needed to compile +LodePNG. For the C++ version, only the standard C++ library is needed on top. +Add the files lodepng.c(pp) and lodepng.h to your project, include +lodepng.h where needed, and your program can read/write PNG files. + +It is compatible with C90 and up, and C++03 and up. + +If performance is important, use optimization when compiling! For both the +encoder and decoder, this makes a large difference. + +Make sure that LodePNG is compiled with the same compiler of the same version +and with the same settings as the rest of the program, or the interfaces with +std::vectors and std::strings in C++ can be incompatible. + +CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. + +*) gcc and g++ + +LodePNG is developed in gcc so this compiler is natively supported. It gives no +warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ +version 4.7.1 on Linux, 32-bit and 64-bit. + +*) Clang + +Fully supported and warning-free. + +*) Mingw + +The Mingw compiler (a port of gcc for Windows) should be fully supported by +LodePNG. + +*) Visual Studio and Visual C++ Express Edition + +LodePNG should be warning-free with warning level W4. Two warnings were disabled +with pragmas though: warning 4244 about implicit conversions, and warning 4996 +where it wants to use a non-standard function fopen_s instead of the standard C +fopen. + +Visual Studio may want "stdafx.h" files to be included in each source file and +give an error "unexpected end of file while looking for precompiled header". +This is not standard C++ and will not be added to the stock LodePNG. You can +disable it for lodepng.cpp only by right clicking it, Properties, C/C++, +Precompiled Headers, and set it to Not Using Precompiled Headers there. + +NOTE: Modern versions of VS should be fully supported, but old versions, e.g. +VS6, are not guaranteed to work. + +*) Compilers on Macintosh + +LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for +C and C++. + +*) Other Compilers + +If you encounter problems on any compilers, feel free to let me know and I may +try to fix it if the compiler is modern and standards compliant. + + +10. examples +------------ + +This decoder example shows the most basic usage of LodePNG. More complex +examples can be found on the LodePNG website. + +NOTE: these examples do not support wide-character filenames, you can use an +external method to handle such files and encode or decode in-memory + +10.1. decoder C++ example +------------------------- + +#include "lodepng.h" +#include + +int main(int argc, char *argv[]) { + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector image; + unsigned width, height; + unsigned error = lodepng::decode(image, width, height, filename); + + //if there's an error, display it + if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; + + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... +} + +10.2. decoder C example +----------------------- + +#include "lodepng.h" + +int main(int argc, char *argv[]) { + unsigned error; + unsigned char* image; + size_t width, height; + const char* filename = argc > 1 ? argv[1] : "test.png"; + + error = lodepng_decode32_file(&image, &width, &height, filename); + + if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); + + / * use image here * / + + free(image); + return 0; +} + +11. state settings reference +---------------------------- + +A quick reference of some settings to set on the LodePNGState + +For decoding: + +state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums +state.decoder.zlibsettings.custom_...: use custom inflate function +state.decoder.ignore_crc: ignore CRC checksums +state.decoder.ignore_critical: ignore unknown critical chunks +state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors +state.decoder.color_convert: convert internal PNG color to chosen one +state.decoder.read_text_chunks: whether to read in text metadata chunks +state.decoder.remember_unknown_chunks: whether to read in unknown chunks +state.info_raw.colortype: desired color type for decoded image +state.info_raw.bitdepth: desired bit depth for decoded image +state.info_raw....: more color settings, see struct LodePNGColorMode +state.info_png....: no settings for decoder but output, see struct LodePNGInfo + +For encoding: + +state.encoder.zlibsettings.btype: disable compression by setting it to 0 +state.encoder.zlibsettings.use_lz77: use LZ77 in compression +state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize +state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match +state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching +state.encoder.zlibsettings.lazymatching: try one more LZ77 matching +state.encoder.zlibsettings.custom_...: use custom deflate function +state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png +state.encoder.filter_palette_zero: PNG filter strategy for palette +state.encoder.filter_strategy: PNG filter strategy to encode with +state.encoder.force_palette: add palette even if not encoding to one +state.encoder.add_id: add LodePNG identifier and version as a text chunk +state.encoder.text_compression: use compressed text chunks for metadata +state.info_raw.colortype: color type of raw input image you provide +state.info_raw.bitdepth: bit depth of raw input image you provide +state.info_raw: more color settings, see struct LodePNGColorMode +state.info_png.color.colortype: desired color type if auto_convert is false +state.info_png.color.bitdepth: desired bit depth if auto_convert is false +state.info_png.color....: more color settings, see struct LodePNGColorMode +state.info_png....: more PNG related settings, see struct LodePNGInfo + + +12. changes +----------- + +The version number of LodePNG is the date of the change given in the format +yyyymmdd. + +Some changes aren't backwards compatible. Those are indicated with a (!) +symbol. + +Not all changes are listed here, the commit history in github lists more: +https://github.com/lvandeve/lodepng + +*) 6 may 2025 (!): renamed mDCv to mDCV and cLLi to cLLI as per the recent + rename in the draft png third edition spec. Please note that as long as the + third edition is not finalized, backwards-incompatible changes to its + features are possible. +*) 23 dec 2024: added support for the mDCv and cLLi chunks (for png third + edition spec) +*) 22 dec 2024: added support for the cICP chunk (for png third edition spec) +*) 15 dec 2024: added support for the eXIf chunk (for png third edition spec) +*) 10 apr 2023: faster CRC32 implementation, but with larger lookup table. +*) 13 jun 2022: added support for the sBIT chunk. +*) 09 jan 2022: minor decoder speed improvements. +*) 27 jun 2021: added warnings that file reading/writing functions don't support + wide-character filenames (support for this is not planned, opening files is + not the core part of PNG decoding/decoding and is platform dependent). +*) 17 oct 2020: prevent decoding too large text/icc chunks by default. +*) 06 mar 2020: simplified some of the dynamic memory allocations. +*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct + overflow checks. +*) 14 aug 2019: around 25% faster decoding thanks to huffman lookup tables. +*) 15 jun 2019: (!) auto_choose_color API changed (for bugfix: don't use palette + if gray ICC profile) and non-ICC LodePNGColorProfile renamed to + LodePNGColorStats. +*) 30 dec 2018: code style changes only: removed newlines before opening braces. +*) 10 sep 2018: added way to inspect metadata chunks without full decoding. +*) 19 aug 2018: (!) fixed color mode bKGD is encoded with and made it use + palette index in case of palette. +*) 10 aug 2018: (!) added support for gAMA, cHRM, sRGB and iCCP chunks. This + change is backwards compatible unless you relied on unknown_chunks for those. +*) 11 jun 2018: less restrictive check for pixel size integer overflow +*) 14 jan 2018: allow optionally ignoring a few more recoverable errors +*) 17 sep 2017: fix memory leak for some encoder input error cases +*) 27 nov 2016: grey+alpha auto color model detection bugfix +*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). +*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within + the limits of pure C90). +*) 08 dec 2015: Made load_file function return error if file can't be opened. +*) 24 oct 2015: Bugfix with decoding to palette output. +*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. +*) 24 aug 2014: Moved to github +*) 23 aug 2014: Reduced needless memory usage of decoder. +*) 28 jun 2014: Removed fix_png setting, always support palette OOB for + simplicity. Made ColorProfile public. +*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. +*) 22 dec 2013: Power of two windowsize required for optimization. +*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. +*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). +*) 11 mar 2013: (!) Bugfix with custom free. Changed from "my" to "lodepng_" + prefix for the custom allocators and made it possible with a new #define to + use custom ones in your project without needing to change lodepng's code. +*) 28 jan 2013: Bugfix with color key. +*) 27 oct 2012: Tweaks in text chunk keyword length error handling. +*) 8 oct 2012: (!) Added new filter strategy (entropy) and new auto color mode. + (no palette). Better deflate tree encoding. New compression tweak settings. + Faster color conversions while decoding. Some internal cleanups. +*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. +*) 1 sep 2012: (!) Removed #define's for giving custom (de)compression functions + and made it work with function pointers instead. +*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc + and free functions and toggle #defines from compiler flags. Small fixes. +*) 6 may 2012: (!) Made plugging in custom zlib/deflate functions more flexible. +*) 22 apr 2012: (!) Made interface more consistent, renaming a lot. Removed + redundant C++ codec classes. Reduced amount of structs. Everything changed, + but it is cleaner now imho and functionality remains the same. Also fixed + several bugs and shrunk the implementation code. Made new samples. +*) 6 nov 2011: (!) By default, the encoder now automatically chooses the best + PNG color model and bit depth, based on the amount and type of colors of the + raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. +*) 9 oct 2011: simpler hash chain implementation for the encoder. +*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. +*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. + A bug with the PNG filtertype heuristic was fixed, so that it chooses much + better ones (it's quite significant). A setting to do an experimental, slow, + brute force search for PNG filter types is added. +*) 17 aug 2011: (!) changed some C zlib related function names. +*) 16 aug 2011: made the code less wide (max 120 characters per line). +*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. +*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. +*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman + to optimize long sequences of zeros. +*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and + LodePNG_InfoColor_canHaveAlpha functions for convenience. +*) 7 nov 2010: added LodePNG_error_text function to get error code description. +*) 30 oct 2010: made decoding slightly faster +*) 26 oct 2010: (!) changed some C function and struct names (more consistent). + Reorganized the documentation and the declaration order in the header. +*) 08 aug 2010: only changed some comments and external samples. +*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. +*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. +*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could + read by ignoring the problem but windows apps couldn't. +*) 06 jun 2008: added more error checks for out of memory cases. +*) 26 apr 2008: added a few more checks here and there to ensure more safety. +*) 06 mar 2008: crash with encoding of strings fixed +*) 02 feb 2008: support for international text chunks added (iTXt) +*) 23 jan 2008: small cleanups, and #defines to divide code in sections +*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. +*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. +*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added + Also various fixes, such as in the deflate and the padding bits code. +*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved + filtering code of encoder. +*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A + C++ wrapper around this provides an interface almost identical to before. + Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code + are together in these files but it works both for C and C++ compilers. +*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks +*) 30 aug 2007: bug fixed which makes this Borland C++ compatible +*) 09 aug 2007: some VS2005 warnings removed again +*) 21 jul 2007: deflate code placed in new namespace separate from zlib code +*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images +*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing + invalid std::vector element [0] fixed, and level 3 and 4 warnings removed +*) 02 jun 2007: made the encoder add a tag with version by default +*) 27 may 2007: zlib and png code separated (but still in the same file), + simple encoder/decoder functions added for more simple usage cases +*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), + moved some examples from here to lodepng_examples.cpp +*) 12 may 2007: palette decoding bug fixed +*) 24 apr 2007: changed the license from BSD to the zlib license +*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. +*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding + palettized PNG images. Plus little interface change with palette and texts. +*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. + Fixed a bug where the end code of a block had length 0 in the Huffman tree. +*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented + and supported by the encoder, resulting in smaller PNGs at the output. +*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. +*) 24 jan 2007: gave encoder an error interface. Added color conversion from any + greyscale type to 8-bit greyscale with or without alpha. +*) 21 jan 2007: (!) Totally changed the interface. It allows more color types + to convert to and is more uniform. See the manual for how it works now. +*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: + encode/decode custom tEXt chunks, separate classes for zlib & deflate, and + at last made the decoder give errors for incorrect Adler32 or Crc. +*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. +*) 29 dec 2006: Added support for encoding images without alpha channel, and + cleaned out code as well as making certain parts faster. +*) 28 dec 2006: Added "Settings" to the encoder. +*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. + Removed some code duplication in the decoder. Fixed little bug in an example. +*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. + Fixed a bug of the decoder with 16-bit per color. +*) 15 oct 2006: Changed documentation structure +*) 09 oct 2006: Encoder class added. It encodes a valid PNG image from the + given image buffer, however for now it's not compressed. +*) 08 sep 2006: (!) Changed to interface with a Decoder class +*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different + way. Renamed decodePNG to decodePNGGeneric. +*) 29 jul 2006: (!) Changed the interface: image info is now returned as a + struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. +*) 28 jul 2006: Cleaned the code and added new error checks. + Corrected terminology "deflate" into "inflate". +*) 23 jun 2006: Added SDL example in the documentation in the header, this + example allows easy debugging by displaying the PNG and its transparency. +*) 22 jun 2006: (!) Changed way to obtain error value. Added + loadFile function for convenience. Made decodePNG32 faster. +*) 21 jun 2006: (!) Changed type of info vector to unsigned. + Changed position of palette in info vector. Fixed an important bug that + happened on PNGs with an uncompressed block. +*) 16 jun 2006: Internally changed unsigned into unsigned where + needed, and performed some optimizations. +*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them + in LodePNG namespace. Changed the order of the parameters. Rewrote the + documentation in the header. Renamed files to lodepng.cpp and lodepng.h +*) 22 apr 2006: Optimized and improved some code +*) 07 sep 2005: (!) Changed to std::vector interface +*) 12 aug 2005: Initial release (C++, decoder only) +*/ diff --git a/Modules/lodepng-module/include/lodepng/module.h b/Modules/lodepng-module/include/lodepng/module.h new file mode 100644 index 000000000..7d35a208e --- /dev/null +++ b/Modules/lodepng-module/include/lodepng/module.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct Module lodepng_module; + +#ifdef __cplusplus +} +#endif diff --git a/Modules/lodepng-module/source/allocators.c b/Modules/lodepng-module/source/allocators.c new file mode 100644 index 000000000..3c334581a --- /dev/null +++ b/Modules/lodepng-module/source/allocators.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +#include + +#include + +static const struct MemoryPolicy EXTERNAL_PREFERRED = { + .required = 0, + .desired = MEMORY_CAPABILITY_EXTERNAL, + .alignment = 0, +}; + +void* lodepng_malloc(size_t size) { + return memory_alloc_with_policy(size, &EXTERNAL_PREFERRED); +} + +void* lodepng_realloc(void* ptr, size_t new_size) { + return memory_realloc_with_policy(ptr, new_size, &EXTERNAL_PREFERRED); +} + +void lodepng_free(void* ptr) { + memory_free(ptr); +} diff --git a/Modules/lodepng-module/source/lodepng.c b/Modules/lodepng-module/source/lodepng.c new file mode 100644 index 000000000..692596f8b --- /dev/null +++ b/Modules/lodepng-module/source/lodepng.c @@ -0,0 +1,7249 @@ +/* +LodePNG version 20261001 + +Copyright (c) 2005-2026 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +/* +The manual and changelog are in the header file "lodepng.h" +Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. +*/ + +/* +Modified for Tactility: renamed from lodepng.cpp and includes (a wrapper +around the original lodepng.h, which is renamed to lodepng_upstream.h). +*/ + +#include + +#ifdef LODEPNG_COMPILE_DISK +#include /* LONG_MAX */ +#include /* file handling */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +#include /* allocations */ +#endif /* LODEPNG_COMPILE_ALLOCATORS */ + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ +#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ +#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ +#endif /*_MSC_VER */ + +const char* LODEPNG_VERSION_STRING = "20261001"; + +/* +This source file is divided into the following large parts. The code sections +with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. +-Tools for C and common code for PNG and Zlib +-C Code for Zlib (huffman, deflate, ...) +-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) +-The C++ wrapper around all of the above +*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // Tools for C, and common code for PNG and Zlib. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*The malloc, realloc and free functions defined here with "lodepng_" in front +of the name, so that you can easily change them to others related to your +platform if needed. Everything else in the code calls these. Pass +-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out +#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and +define them in your own project's source files without needing to change +lodepng source code. Don't forget to remove "static" if you copypaste them +from here.*/ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +static void* lodepng_malloc(size_t size) { +#ifdef LODEPNG_MAX_ALLOC + if(size > LODEPNG_MAX_ALLOC) return 0; +#endif + return malloc(size); +} + +/* NOTE: when realloc returns NULL, it leaves the original memory untouched */ +static void* lodepng_realloc(void* ptr, size_t new_size) { +#ifdef LODEPNG_MAX_ALLOC + if(new_size > LODEPNG_MAX_ALLOC) return 0; +#endif + return realloc(ptr, new_size); +} + +static void lodepng_free(void* ptr) { + free(ptr); +} +#else /*LODEPNG_COMPILE_ALLOCATORS*/ +/* TODO: support giving additional void* payload to the custom allocators */ +void* lodepng_malloc(size_t size); +void* lodepng_realloc(void* ptr, size_t new_size); +void lodepng_free(void* ptr); +#endif /*LODEPNG_COMPILE_ALLOCATORS*/ + +/* convince the compiler to inline a function, for use when this measurably improves performance */ +/* inline is not available in C90, but use it when supported by the compiler */ +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) +#define LODEPNG_INLINE inline +#else +#define LODEPNG_INLINE /* not available */ +#endif + +/* restrict is not available in C90, but use it when supported by the compiler */ +#if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus)) +#define LODEPNG_RESTRICT __restrict +#else +#define LODEPNG_RESTRICT /* not available */ +#endif + +/* Replacements for C library functions such as memcpy and strlen, to support platforms +where a full C library is not available. The compiler can recognize them and compile +to something as fast. */ + +static void lodepng_memcpy(void* LODEPNG_RESTRICT dst, + const void* LODEPNG_RESTRICT src, size_t size) { + size_t i; + for(i = 0; i < size; i++) ((char*)dst)[i] = ((const char*)src)[i]; +} + +static void lodepng_memset(void* LODEPNG_RESTRICT dst, + int value, size_t num) { + size_t i; + for(i = 0; i < num; i++) ((char*)dst)[i] = (char)value; +} + +/* does not check memory out of bounds, do not use on untrusted data */ +static size_t lodepng_strlen(const char* a) { + const char* orig = a; + /* avoid warning about unused function in case of disabled COMPILE... macros */ + (void)(&lodepng_strlen); + while(*a) a++; + return (size_t)(a - orig); +} + +#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER) +/* Safely check if adding two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_addofl(size_t a, size_t b, size_t* result) { + *result = a + b; /* Unsigned addition is well defined and safe in C90 */ + return *result < a; +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/ + +#ifdef LODEPNG_COMPILE_DECODER +/* Safely check if multiplying two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_mulofl(size_t a, size_t b, size_t* result) { + *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ + return (a != 0 && *result / a != b); +} + +#ifdef LODEPNG_COMPILE_ZLIB +/* Safely check if a + b > c, even if overflow could happen. */ +static int lodepng_gtofl(size_t a, size_t b, size_t c) { + size_t d; + if(lodepng_addofl(a, b, &d)) return 1; + return d > c; +} +#endif /*LODEPNG_COMPILE_ZLIB*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +/* +Often in case of an error a value is assigned to a variable and then it breaks +out of a loop (to go to the cleanup phase of a function). This macro does that. +It makes the error handling code shorter and more readable. + +Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83); +*/ +#define CERROR_BREAK(errorvar, code){\ + errorvar = code;\ + break;\ +} + +/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ +#define ERROR_BREAK(code) CERROR_BREAK(error, code) + +/*Set error var to the error code, and return it.*/ +#define CERROR_RETURN_ERROR(errorvar, code){\ + errorvar = code;\ + return code;\ +} + +/*Try the code, if it returns error, also return the error.*/ +#define CERROR_TRY_RETURN(call){\ + unsigned error_ = call;\ + if(error_) return error_;\ +} + +/*Set error var to the error code, and return from the void function.*/ +#define CERROR_RETURN(errorvar, code){\ + errorvar = code;\ + return;\ +} + +/* +About uivector, ucvector and string: +-All of them wrap dynamic arrays or text strings in a similar way. +-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. +-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. +-They're not used in the interface, only internally in this file as static functions. +-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. +*/ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER +/*dynamic vector of unsigned ints*/ +typedef struct uivector { + unsigned* data; + size_t size; /*size in number of unsigned longs*/ + size_t allocsize; /*allocated size in bytes*/ +} uivector; + +static void uivector_cleanup(void* p) { + ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; + lodepng_free(((uivector*)p)->data); + ((uivector*)p)->data = NULL; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_resize(uivector* p, size_t size) { + size_t allocsize = size * sizeof(unsigned); + if(allocsize > p->allocsize) { + size_t newsize = allocsize + (p->allocsize >> 1u); + void* data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned*)data; + } + else return 0; /*error: not enough memory*/ + } + p->size = size; + return 1; /*success*/ +} + +static void uivector_init(uivector* p) { + p->data = NULL; + p->size = p->allocsize = 0; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_push_back(uivector* p, unsigned c) { + if(!uivector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* /////////////////////////////////////////////////////////////////////////// */ + +/*dynamic vector of unsigned chars*/ +typedef struct ucvector { + unsigned char* data; + size_t size; /*used size*/ + size_t allocsize; /*allocated size*/ +} ucvector; + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_reserve(ucvector* p, size_t size) { + if(size > p->allocsize) { + size_t newsize = size + (p->allocsize >> 1u); + void* data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned char*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; /*success*/ +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_resize(ucvector* p, size_t size) { + p->size = size; + return ucvector_reserve(p, size); +} + +static ucvector ucvector_init(unsigned char* buffer, size_t size) { + ucvector v; + v.data = buffer; + v.allocsize = v.size = size; + return v; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +/*also appends null termination character*/ +static char* alloc_string_sized(const char* in, size_t insize) { + char* out = (char*)lodepng_malloc(insize + 1); + if(out) { + lodepng_memcpy(out, in, insize); + out[insize] = 0; + } + return out; +} + +/* dynamically allocates a new string with a copy of the null terminated input text */ +static char* alloc_string(const char* in) { + return alloc_string_sized(in, lodepng_strlen(in)); +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG) +static unsigned lodepng_read32bitInt(const unsigned char* buffer) { + return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | + ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); +} +#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/ + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) +/*buffer must have at least 4 allocated bytes available*/ +static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) { + buffer[0] = (unsigned char)((value >> 24) & 0xff); + buffer[1] = (unsigned char)((value >> 16) & 0xff); + buffer[2] = (unsigned char)((value >> 8) & 0xff); + buffer[3] = (unsigned char)((value ) & 0xff); +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / File IO / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DISK + +/* returns negative value on error. This should be pure C compatible, so no fstat. */ +static long lodepng_filesize(FILE* file) { + long size; + if(fseek(file, 0, SEEK_END) != 0) return -1; + size = ftell(file); + /* It may give LONG_MAX as directory size, this is invalid for us. */ + if(size == LONG_MAX) return -1; + if(fseek(file, 0, SEEK_SET) != 0) return -1; + return size; +} + +/* Allocates the output buffer to the file size and reads the file into it. Returns error code.*/ +static unsigned lodepng_load_file_(unsigned char** out, size_t* outsize, FILE* file) { + long size = lodepng_filesize(file); + if(size < 0) return 78; + *outsize = (size_t)size; + *out = (unsigned char*)lodepng_malloc((size_t)size); + if(!(*out) && size > 0) return 83; /*the above malloc failed*/ + if(fread(*out, 1, *outsize, file) != *outsize) return 78; + return 0; /*ok*/ +} + +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { + unsigned error; + FILE* file = fopen(filename, "rb"); + if(!file) return 78; + error = lodepng_load_file_(out, outsize, file); + fclose(file); + return error; +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) { + FILE* file = fopen(filename, "wb" ); + if(!file) return 79; + fwrite(buffer, 1, buffersize, file); + fclose(file); + return 0; +} + +#endif /*LODEPNG_COMPILE_DISK*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of common code and tools. Begin of Zlib related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER + +typedef struct { + ucvector* data; + unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/ +} LodePNGBitWriter; + +static void LodePNGBitWriter_init(LodePNGBitWriter* writer, ucvector* data) { + writer->data = data; + writer->bp = 0; +} + +/*TODO: this ignores potential out of memory errors*/ +#define WRITEBIT(writer, bit){\ + /* append new byte */\ + if(((writer->bp) & 7u) == 0) {\ + if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\ + writer->data->data[writer->data->size - 1] = 0;\ + }\ + (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\ + ++writer->bp;\ +} + +/* LSB of value is written first, and LSB of bytes is used first */ +static void writeBits(LodePNGBitWriter* writer, unsigned value, size_t nbits) { + if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */ + WRITEBIT(writer, value); + } else { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + size_t i; + for(i = 0; i != nbits; ++i) { + WRITEBIT(writer, (unsigned char)((value >> i) & 1)); + } + } +} + +/* This one is to use for adding huffman symbol, the value bits are written MSB first */ +static void writeBitsReversed(LodePNGBitWriter* writer, unsigned value, size_t nbits) { + size_t i; + for(i = 0; i != nbits; ++i) { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u)); + } +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +typedef struct { + const unsigned char* data; + size_t size; /*size of data in bytes*/ + size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/ + size_t bp; + unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/ +} LodePNGBitReader; + +/* data size argument is in bytes. Returns error if size too large causing overflow */ +static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned char* data, size_t size) { + size_t temp; + reader->data = data; + reader->size = size; + /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */ + if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105; + /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and + trying to ensure 32 more bits*/ + if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105; + reader->bp = 0; + reader->buffer = 0; + return 0; /*ok*/ +} + +/* +ensureBits functions: +Ensures the reader can at least read nbits bits in one or more readBits calls, +safely even if not enough bits are available. +The nbits parameter is unused but is given for documentation purposes, error +checking for amount of bits must be done beforehand. +*/ + +/*See ensureBits documentation above. This one ensures up to 9 bits */ +static LODEPNG_INLINE void ensureBits9(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 1u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer = reader->data[start + 0]; + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 17 bits */ +static LODEPNG_INLINE void ensureBits17(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 2u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 25 bits */ +static LODEPNG_INLINE void ensureBits25(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 3u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 32 bits */ +static LODEPNG_INLINE void ensureBits32(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 4u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u))); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */ +static LODEPNG_INLINE unsigned peekBits(LodePNGBitReader* reader, size_t nbits) { + /* The shift allows nbits to be only up to 31. */ + return reader->buffer & ((1u << nbits) - 1u); +} + +/* Must have enough bits available with ensureBits */ +static LODEPNG_INLINE void advanceBits(LodePNGBitReader* reader, size_t nbits) { + reader->buffer >>= nbits; + reader->bp += nbits; +} + +/* Must have enough bits available with ensureBits */ +static LODEPNG_INLINE unsigned readBits(LodePNGBitReader* reader, size_t nbits) { + unsigned result = peekBits(reader, nbits); + advanceBits(reader, nbits); + return result; +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +static unsigned reverseBits(unsigned bits, unsigned num) { + /*TODO: implement faster lookup table based version when needed*/ + unsigned i, result = 0; + for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i; + return result; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflate - Huffman / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define FIRST_LENGTH_CODE_INDEX 257 +#define LAST_LENGTH_CODE_INDEX 285 +/*256 literals, the end code, some length codes, and 2 unused codes*/ +#define NUM_DEFLATE_CODE_SYMBOLS 288 +/*the distance codes have their own symbols, 30 used, 2 unused*/ +#define NUM_DISTANCE_SYMBOLS 32 +/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ +#define NUM_CODE_LENGTH_CODES 19 + +/*the base lengths represented by codes 257-285*/ +static const unsigned LENGTHBASE[29] + = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, + 67, 83, 99, 115, 131, 163, 195, 227, 258}; + +/*the extra bits used by codes 257-285 (added to base length)*/ +static const unsigned LENGTHEXTRA[29] + = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 0}; + +/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ +static const unsigned DISTANCEBASE[30] + = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, + 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; + +/*the extra bits of backwards distances (added to base)*/ +static const unsigned DISTANCEEXTRA[30] + = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + +/*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman +tree of the dynamic huffman tree lengths is generated*/ +static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] + = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Huffman tree struct, containing multiple representations of the tree +*/ +typedef struct HuffmanTree { + unsigned* codes; /*the huffman codes (bit patterns representing the symbols)*/ + unsigned* lengths; /*the lengths of the huffman codes*/ + unsigned maxbitlen; /*maximum number of bits a single code can get*/ + unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ + /* for reading only */ + unsigned char* table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/ + unsigned short* table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/ +} HuffmanTree; + +static void HuffmanTree_init(HuffmanTree* tree) { + tree->codes = 0; + tree->lengths = 0; + tree->table_len = 0; + tree->table_value = 0; +} + +static void HuffmanTree_cleanup(HuffmanTree* tree) { + lodepng_free(tree->codes); + lodepng_free(tree->lengths); + lodepng_free(tree->table_len); + lodepng_free(tree->table_value); +} + +/* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/ +/* values 8u and 9u work the fastest */ +#define FIRSTBITS 9u + +/* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination, +which is possible in case of only 0 or 1 present symbols. */ +#define INVALIDSYMBOL 65535u + +/* make table for huffman decoding */ +static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { + static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ + static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; + size_t i, numpresent, pointer, size; /*total table size*/ + unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned)); + if(!maxlens) return 83; /*alloc fail*/ + + /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/ + lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens)); + for(i = 0; i < tree->numcodes; i++) { + unsigned symbol = tree->codes[i]; + unsigned l = tree->lengths[i]; + unsigned index; + if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/ + /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/ + index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS); + maxlens[index] = LODEPNG_MAX(maxlens[index], l); + } + /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */ + size = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l > FIRSTBITS) size += (((size_t)1) << (l - FIRSTBITS)); + } + tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len)); + tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value)); + if(!tree->table_len || !tree->table_value) { + lodepng_free(maxlens); + /* freeing tree->table values is done at a higher scope */ + return 83; /*alloc fail*/ + } + /*initialize with an invalid length to indicate unused entries*/ + for(i = 0; i < size; ++i) tree->table_len[i] = 16; + + /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/ + pointer = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l <= FIRSTBITS) continue; + tree->table_len[i] = l; + tree->table_value[i] = (unsigned short)pointer; + pointer += (((size_t)1) << (l - FIRSTBITS)); + } + lodepng_free(maxlens); + + /*fill in the first table for short symbols, or secondary table for long symbols*/ + numpresent = 0; + for(i = 0; i < tree->numcodes; ++i) { + unsigned l = tree->lengths[i]; + unsigned symbol, reverse; + if(l == 0) continue; + symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/ + /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/ + reverse = reverseBits(symbol, l); + numpresent++; + + if(l <= FIRSTBITS) { + /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/ + unsigned num = 1u << (FIRSTBITS - l); + unsigned j; + for(j = 0; j < num; ++j) { + /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/ + unsigned index = reverse | (j << l); + if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + tree->table_len[index] = l; + tree->table_value[index] = (unsigned short)i; + } + } else { + /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ + /*the FIRSTBITS MSBs of the symbol are the first table index*/ + unsigned index = reverse & mask; + unsigned maxlen = tree->table_len[index]; + /*log2 of secondary table length, should be >= l - FIRSTBITS*/ + unsigned tablelen = maxlen - FIRSTBITS; + unsigned start = tree->table_value[index]; /*starting index in secondary table*/ + unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/ + unsigned j; + if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + for(j = 0; j < num; ++j) { + unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ + unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); + tree->table_len[index2] = l; + tree->table_value[index2] = (unsigned short)i; + } + } + } + + if(numpresent < 2) { + /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits, + but deflate uses 1 bit instead. In case of 0 symbols, no symbols can + appear at all, but such huffman tree could still exist (e.g. if distance + codes are never used). In both cases, not all symbols of the table will be + filled in. Fill them in with an invalid symbol value so returning them from + huffmanDecodeSymbol will cause error. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) { + /* As length, use a value smaller than FIRSTBITS for the head table, + and a value larger than FIRSTBITS for the secondary table, to ensure + valid behavior for advanceBits when reading this symbol. */ + tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1); + tree->table_value[i] = INVALIDSYMBOL; + } + } + } else { + /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. + If that is not the case (due to too long length codes), the table will not + have been fully used, and this is an error (not all bit combinations can be + decoded): an oversubscribed huffman tree, indicated by error 55. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) return 55; + } + } + + return 0; +} + +/* +Second step for the ...makeFromLengths and ...makeFromFrequencies functions. +numcodes, lengths and maxbitlen must already be filled in correctly. return +value is error. +*/ +static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) { + unsigned* blcount; + unsigned* nextcode; + unsigned error = 0; + unsigned bits, n; + + tree->codes = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); + blcount = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + nextcode = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/ + + if(!error) { + for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0; + /*step 1: count number of instances of each code length*/ + for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]]; + /*step 2: generate the nextcode values*/ + for(bits = 1; bits <= tree->maxbitlen; ++bits) { + nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u; + } + /*step 3: generate all the codes*/ + for(n = 0; n != tree->numcodes; ++n) { + if(tree->lengths[n] != 0) { + tree->codes[n] = nextcode[tree->lengths[n]]++; + /*remove superfluous bits from the code*/ + tree->codes[n] &= ((1u << tree->lengths[n]) - 1u); + } + } + } + + lodepng_free(blcount); + lodepng_free(nextcode); + + if(!error) error = HuffmanTree_makeTable(tree); + return error; +} + +/* +given the code lengths (as stored in the PNG file), generate the tree as defined +by Deflate. maxbitlen is the maximum bits that a code in the tree can have. +return value is error. +*/ +static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, + size_t numcodes, unsigned maxbitlen) { + unsigned i; + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->maxbitlen = maxbitlen; + return HuffmanTree_makeFromLengths2(tree); +} + +#ifdef LODEPNG_COMPILE_ENCODER + +/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", +Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ + +/*chain node for boundary package merge*/ +typedef struct BPMNode { + int weight; /*the sum of all weights in this chain*/ + unsigned index; /*index of this leaf node (called "count" in the paper)*/ + struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ + int in_use; +} BPMNode; + +/*lists of chains*/ +typedef struct BPMLists { + /*memory pool*/ + unsigned memsize; + BPMNode* memory; + unsigned numfree; + unsigned nextfree; + BPMNode** freelist; + /*two heads of lookahead chains per list*/ + unsigned listsize; + BPMNode** chains0; + BPMNode** chains1; +} BPMLists; + +/*creates a new chain node with the given parameters, from the memory in the lists */ +static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) { + unsigned i; + BPMNode* result; + + /*memory full, so garbage collect*/ + if(lists->nextfree >= lists->numfree) { + /*mark only those that are in use*/ + for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; + for(i = 0; i != lists->listsize; ++i) { + BPMNode* node; + for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; + for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; + } + /*collect those that are free*/ + lists->numfree = 0; + for(i = 0; i != lists->memsize; ++i) { + if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; + } + lists->nextfree = 0; + } + + result = lists->freelist[lists->nextfree++]; + result->weight = weight; + result->index = index; + result->tail = tail; + return result; +} + +/*sort the leaves with stable mergesort*/ +static void bpmnode_sort(BPMNode* leaves, size_t num) { + BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); + size_t width, counter = 0; + for(width = 1; width < num; width *= 2) { + BPMNode* a = (counter & 1) ? mem : leaves; + BPMNode* b = (counter & 1) ? leaves : mem; + size_t p; + for(p = 0; p < num; p += 2 * width) { + size_t q = (p + width > num) ? num : (p + width); + size_t r = (p + 2 * width > num) ? num : (p + 2 * width); + size_t i = p, j = q, k; + for(k = p; k < r; k++) { + if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; + else b[k] = a[j++]; + } + } + counter++; + } + if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num); + lodepng_free(mem); +} + +/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ +static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) { + unsigned lastindex = lists->chains1[c]->index; + + if(c == 0) { + if(lastindex >= numpresent) return; + lists->chains0[c] = lists->chains1[c]; + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); + } else { + /*sum of the weights of the head nodes of the previous lookahead chains.*/ + int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; + lists->chains0[c] = lists->chains1[c]; + if(lastindex < numpresent && sum > leaves[lastindex].weight) { + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); + return; + } + lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); + /*in the end we are only interested in the chain of the last list, so no + need to recurse if we're at the last one (this gives measurable speedup)*/ + if(num + 1 < (int)(2 * numpresent - 2)) { + boundaryPM(lists, leaves, numpresent, c - 1, num); + boundaryPM(lists, leaves, numpresent, c - 1, num); + } + } +} + +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen) { + unsigned error = 0; + unsigned i; + size_t numpresent = 0; /*number of symbols with non-zero frequency*/ + BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ + + if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ + if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ + + leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); + if(!leaves) return 83; /*alloc fail*/ + + for(i = 0; i != numcodes; ++i) { + if(frequencies[i] > 0) { + leaves[numpresent].weight = (int)frequencies[i]; + leaves[numpresent].index = i; + ++numpresent; + } + } + + lodepng_memset(lengths, 0, numcodes * sizeof(*lengths)); + + /*ensure at least two present symbols. There should be at least one symbol + according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To + make these work as well ensure there are at least two symbols. The + Package-Merge code below also doesn't work correctly if there's only one + symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/ + if(numpresent == 0) { + lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ + } else if(numpresent == 1) { + lengths[leaves[0].index] = 1; + lengths[leaves[0].index == 0 ? 1 : 0] = 1; + } else { + BPMLists lists; + BPMNode* node; + + bpmnode_sort(leaves, numpresent); + + lists.listsize = maxbitlen; + lists.memsize = 2 * maxbitlen * (maxbitlen + 1); + lists.nextfree = 0; + lists.numfree = lists.memsize; + lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); + lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); + lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ + + if(!error) { + for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; + + bpmnode_create(&lists, leaves[0].weight, 1, 0); + bpmnode_create(&lists, leaves[1].weight, 2, 0); + + for(i = 0; i != lists.listsize; ++i) { + lists.chains0[i] = &lists.memory[0]; + lists.chains1[i] = &lists.memory[1]; + } + + /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ + for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); + + for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) { + for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; + } + } + + lodepng_free(lists.memory); + lodepng_free(lists.freelist); + lodepng_free(lists.chains0); + lodepng_free(lists.chains1); + } + + lodepng_free(leaves); + return error; +} + +/*Create the Huffman tree given the symbol frequencies*/ +static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, + size_t mincodes, size_t numcodes, unsigned maxbitlen) { + unsigned error = 0; + while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + tree->maxbitlen = maxbitlen; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + + error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); + if(!error) error = HuffmanTree_makeFromLengths2(tree); + return error; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ +static unsigned generateFixedLitLenTree(HuffmanTree* tree) { + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ + for(i = 0; i <= 143; ++i) bitlen[i] = 8; + for(i = 144; i <= 255; ++i) bitlen[i] = 9; + for(i = 256; i <= 279; ++i) bitlen[i] = 7; + for(i = 280; i <= 287; ++i) bitlen[i] = 8; + + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static unsigned generateFixedDistanceTree(HuffmanTree* tree) { + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*there are 32 distance codes, but 30-31 are unused*/ + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* +returns the code. The bit reader must already have been ensured at least 15 bits +*/ +static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree* codetree) { + unsigned short code = peekBits(reader, FIRSTBITS); + unsigned short l = codetree->table_len[code]; + unsigned short value = codetree->table_value[code]; + if(l <= FIRSTBITS) { + advanceBits(reader, l); + return value; + } else { + advanceBits(reader, FIRSTBITS); + value += peekBits(reader, l - FIRSTBITS); + advanceBits(reader, codetree->table_len[value] - FIRSTBITS); + return codetree->table_value[value]; + } +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Inflator (Decompressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*get the tree of a deflated block with fixed tree, as specified in the deflate specification +Returns error code.*/ +static unsigned getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) { + unsigned error = generateFixedLitLenTree(tree_ll); + if(error) return error; + return generateFixedDistanceTree(tree_d); +} + +/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ +static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, + LodePNGBitReader* reader) { + /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ + unsigned error = 0; + unsigned n, HLIT, HDIST, HCLEN, i; + + /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ + unsigned* bitlen_ll = 0; /*lit,len code lengths*/ + unsigned* bitlen_d = 0; /*dist code lengths*/ + /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ + unsigned* bitlen_cl = 0; + HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ + + if(reader->bitsize - reader->bp < 14) return 49; /*error: the bit pointer is or will go past the memory*/ + ensureBits17(reader, 14); + + /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ + HLIT = readBits(reader, 5) + 257; + /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ + HDIST = readBits(reader, 5) + 1; + /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ + HCLEN = readBits(reader, 4) + 4; + + bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); + if(!bitlen_cl) return 83 /*alloc fail*/; + + HuffmanTree_init(&tree_cl); + + while(!error) { + /*read the code length codes out of 3 * (amount of code length codes) bits*/ + if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) { + ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/ + } + for(i = 0; i != HCLEN; ++i) { + ensureBits9(reader, 3); /*out of bounds already checked above */ + bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3); + } + for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) { + bitlen_cl[CLCL_ORDER[i]] = 0; + } + + error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*now we can use this tree to read the lengths for the tree that this function will return*/ + bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); + lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll)); + lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d)); + + /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ + i = 0; + while(i < HLIT + HDIST) { + unsigned code; + ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/ + code = huffmanDecodeSymbol(reader, &tree_cl); + if(code <= 15) /*a length code*/ { + if(i < HLIT) bitlen_ll[i] = code; + else bitlen_d[i - HLIT] = code; + ++i; + } else if(code == 16) /*repeat previous*/ { + unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ + unsigned value; /*set value to the previous code*/ + + if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ + + replength += readBits(reader, 2); + + if(i < HLIT + 1) value = bitlen_ll[i - 1]; + else value = bitlen_d[i - HLIT - 1]; + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ + if(i < HLIT) bitlen_ll[i] = value; + else bitlen_d[i - HLIT] = value; + ++i; + } + } else if(code == 17) /*repeat "0" 3-10 times*/ { + unsigned replength = 3; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 3); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } else if(code == 18) /*repeat "0" 11-138 times*/ { + unsigned replength = 11; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 7); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } else /*if(code == INVALIDSYMBOL)*/ { + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + } + } + if(error) break; + + if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ + + /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ + error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); + if(error) break; + error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); + + break; /*end of error-while*/ + } + + lodepng_free(bitlen_cl); + lodepng_free(bitlen_ll); + lodepng_free(bitlen_d); + HuffmanTree_cleanup(&tree_cl); + + return error; +} + +/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ +static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader, + unsigned btype, size_t max_output_size) { + unsigned error = 0; + HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ + HuffmanTree tree_d; /*the huffman tree for distance codes*/ + const size_t reserved_size = 260; /* must be at least 258 for max length, and a few extra for adding a few extra literals */ + int done = 0; + + if(!ucvector_reserve(out, out->size + reserved_size)) return 83; /*alloc fail*/ + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d); + else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader); + + + while(!error && !done) /*decode all symbols until end reached, breaks at end code*/ { + /*code_ll is literal, length or end code*/ + unsigned code_ll; + /* ensure enough bits for 2 huffman code reads (15 bits each): if the first is a literal, a second literal is read at once. This + appears to be slightly faster, than ensuring 20 bits here for 1 huffman symbol and the potential 5 extra bits for the length symbol.*/ + ensureBits32(reader, 30); + code_ll = huffmanDecodeSymbol(reader, &tree_ll); + if(code_ll <= 255) { + /*slightly faster code path if multiple literals in a row*/ + out->data[out->size++] = (unsigned char)code_ll; + code_ll = huffmanDecodeSymbol(reader, &tree_ll); + } + if(code_ll <= 255) /*literal symbol*/ { + out->data[out->size++] = (unsigned char)code_ll; + } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ { + unsigned code_d, distance; + unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ + size_t start, backward, length; + + /*part 1: get length base*/ + length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; + + /*part 2: get extra bits and add the value of that to length*/ + numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; + if(numextrabits_l != 0) { + /* bits already ensured above */ + ensureBits25(reader, 5); + length += readBits(reader, numextrabits_l); + } + + /*part 3: get distance code*/ + ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */ + code_d = huffmanDecodeSymbol(reader, &tree_d); + if(code_d > 29) { + if(code_d <= 31) { + ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/ + } else /* if(code_d == INVALIDSYMBOL) */{ + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + } + distance = DISTANCEBASE[code_d]; + + /*part 4: get extra bits from distance*/ + numextrabits_d = DISTANCEEXTRA[code_d]; + if(numextrabits_d != 0) { + /* bits already ensured above */ + distance += readBits(reader, numextrabits_d); + } + + /*part 5: fill in all the out[n] values based on the length and dist*/ + start = out->size; + if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ + backward = start - distance; + + out->size += length; + if(distance < length) { + size_t forward; + lodepng_memcpy(out->data + start, out->data + backward, distance); + start += distance; + for(forward = distance; forward < length; ++forward) { + out->data[start++] = out->data[backward++]; + } + } else { + lodepng_memcpy(out->data + start, out->data + backward, length); + } + } else if(code_ll == 256) { + done = 1; /*end code, finish the loop*/ + } else /*if(code_ll == INVALIDSYMBOL)*/ { + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + if(out->allocsize - out->size < reserved_size) { + if(!ucvector_reserve(out, out->size + reserved_size)) ERROR_BREAK(83); /*alloc fail*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ + } + if(max_output_size && out->size > max_output_size) { + ERROR_BREAK(109); /*error, larger than max size*/ + } + } + + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader, + const LodePNGDecompressSettings* settings) { + size_t bytepos; + size_t size = reader->size; + unsigned LEN, NLEN, error = 0; + + /*go to first boundary of byte*/ + bytepos = (reader->bp + 7u) >> 3u; + + /*read LEN (2 bytes) and NLEN (2 bytes)*/ + if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/ + LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; + NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; + + /*check if 16-bit NLEN is really the one's complement of LEN*/ + if(!settings->ignore_nlen && LEN + NLEN != 65535) { + return 21; /*error: NLEN is not one's complement of LEN*/ + } + + if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/ + + /*read the literal data: LEN bytes are now stored in the out buffer*/ + if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/ + + /*out->data can be NULL (when LEN is zero), and arithmetic on NULL ptr is undefined*/ + if (LEN) { + lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN); + bytepos += LEN; + } + + reader->bp = bytepos << 3u; + + return error; +} + +static unsigned lodepng_inflatev(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + unsigned BFINAL = 0; + LodePNGBitReader reader; + unsigned error = LodePNGBitReader_init(&reader, in, insize); + + if(error) return error; + + while(!BFINAL) { + unsigned BTYPE; + if(reader.bitsize - reader.bp < 3) return 52; /*error, bit pointer will jump past memory*/ + ensureBits9(&reader, 3); + BFINAL = readBits(&reader, 1); + BTYPE = readBits(&reader, 2); + + if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ + else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ + else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ + if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; + if(error) break; + } + + return error; +} + +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_inflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + if(settings->custom_inflate) { + unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); + out->allocsize = out->size; + if(error) { + /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && out->size > settings->max_output_size) error = 109; + } + return error; + } else { + return lodepng_inflatev(out, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflator (Compressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static const unsigned MAX_SUPPORTED_DEFLATE_LENGTH = 258; + +/*search the index in the array, that has the largest value smaller than or equal to the given value, +given array must be sorted (if no value is smaller, it returns the size of the given array)*/ +static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { + /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ + size_t left = 1; + size_t right = array_size - 1; + + while(left <= right) { + size_t mid = (left + right) >> 1; + if(array[mid] >= value) right = mid - 1; + else left = mid + 1; + } + if(left >= array_size || array[left] > value) left--; + return left; +} + +static void addLengthDistance(uivector* values, size_t length, size_t distance) { + /*values in encoded vector are those used by deflate: + 0-255: literal bytes + 256: end + 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) + 286-287: invalid*/ + + unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); + unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); + unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); + unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); + + size_t pos = values->size; + /*TODO: return error when this fails (out of memory)*/ + unsigned ok = uivector_resize(values, values->size + 4); + if(ok) { + values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX; + values->data[pos + 1] = extra_length; + values->data[pos + 2] = dist_code; + values->data[pos + 3] = extra_distance; + } +} + +/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 +bytes as input because 3 is the minimum match length for deflate*/ +static const unsigned HASH_NUM_VALUES = 65536; +static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ + +typedef struct Hash { + int* head; /*hash value to head circular pos - can be outdated if went around window*/ + /*circular pos to prev circular pos*/ + unsigned short* chain; + int* val; /*circular pos to hash value*/ + + /*TODO: do this not only for zeros but for any repeated byte. However for PNG + it's always going to be the zeros that dominate, so not important for PNG*/ + int* headz; /*similar to head, but for chainz*/ + unsigned short* chainz; /*those with same amount of zeros*/ + unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ +} Hash; + +static unsigned hash_init(Hash* hash, unsigned windowsize) { + unsigned i; + hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); + hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); + hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); + hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) { + return 83; /*alloc fail*/ + } + + /*initialize hash table*/ + for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; + for(i = 0; i != windowsize; ++i) hash->val[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ + + for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ + + return 0; +} + +static void hash_cleanup(Hash* hash) { + lodepng_free(hash->head); + lodepng_free(hash->val); + lodepng_free(hash->chain); + + lodepng_free(hash->zeros); + lodepng_free(hash->headz); + lodepng_free(hash->chainz); +} + + + +static unsigned getHash(const unsigned char* data, size_t size, size_t pos) { + unsigned result = 0; + if(pos + 2 < size) { + /*A simple shift and xor hash is used. Since the data of PNGs is dominated + by zeroes due to the filters, a better hash does not have a significant + effect on speed in traversing the chain, and causes more time spend on + calculating the hash.*/ + result ^= ((unsigned)data[pos + 0] << 0u); + result ^= ((unsigned)data[pos + 1] << 4u); + result ^= ((unsigned)data[pos + 2] << 8u); + } else { + size_t amount, i; + if(pos >= size) return 0; + amount = size - pos; + for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u)); + } + return result & HASH_BIT_MASK; +} + +static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) { + const unsigned char* start = data + pos; + const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; + if(end > data + size) end = data + size; + data = start; + while(data != end && *data == 0) ++data; + /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ + return (unsigned)(data - start); +} + +/*wpos = pos & (windowsize - 1)*/ +static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) { + hash->val[wpos] = (int)hashval; + if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; + hash->head[hashval] = (int)wpos; + + hash->zeros[wpos] = numzeros; + if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; + hash->headz[numzeros] = (int)wpos; +} + +/* +LZ77-encode the data. Return value is error code. The input are raw bytes, the output +is in the form of unsigned integers with codes representing for example literal bytes, or +length/distance pairs. +It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a +sliding window (of windowsize) is used, and all past bytes in that window can be used as +the "dictionary". A brute force search through all possible distances would be slow, and +this hash technique is one out of several ways to speed this up. +*/ +static unsigned encodeLZ77(uivector* out, Hash* hash, + const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, + unsigned minmatch, unsigned nicematch, unsigned lazymatching) { + size_t pos; + unsigned i, error = 0; + /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ + unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u; + unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; + + unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ + unsigned numzeros = 0; + + unsigned offset; /*the offset represents the distance in LZ77 terminology*/ + unsigned length; + unsigned lazy = 0; + unsigned lazylength = 0, lazyoffset = 0; + unsigned hashval; + unsigned current_offset, current_length; + unsigned prev_offset; + const unsigned char *lastptr, *foreptr, *backptr; + unsigned hashpos; + + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ + + if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; + + for(pos = inpos; pos < insize; ++pos) { + size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ + unsigned chainlength = 0; + + hashval = getHash(in, insize, pos); + + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } else { + numzeros = 0; + } + + updateHashChain(hash, wpos, hashval, numzeros); + + /*the length and offset found for the current position*/ + length = 0; + offset = 0; + + hashpos = hash->chain[wpos]; + + lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; + + /*search for the longest string*/ + prev_offset = 0; + for(;;) { + if(chainlength++ >= maxchainlength) break; + current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); + + if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ + prev_offset = current_offset; + if(current_offset > 0) { + /*test the next characters*/ + foreptr = &in[pos]; + backptr = &in[pos - current_offset]; + + /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ + if(numzeros >= 3) { + unsigned skip = hash->zeros[hashpos]; + if(skip > numzeros) skip = numzeros; + backptr += skip; + foreptr += skip; + } + + while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ { + ++backptr; + ++foreptr; + } + current_length = (unsigned)(foreptr - &in[pos]); + + if(current_length > length) { + length = current_length; /*the longest length*/ + offset = current_offset; /*the offset that is related to this longest length*/ + /*jump out once a length of max length is found (speed gain). This also jumps + out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ + if(current_length >= nicematch) break; + } + } + + if(hashpos == hash->chain[hashpos]) break; + + if(numzeros >= 3 && length > numzeros) { + hashpos = hash->chainz[hashpos]; + if(hash->zeros[hashpos] != numzeros) break; + } else { + hashpos = hash->chain[hashpos]; + /*outdated hash value, happens if particular value was not encountered in whole last window*/ + if(hash->val[hashpos] != (int)hashval) break; + } + } + + if(lazymatching) { + if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) { + lazy = 1; + lazylength = length; + lazyoffset = offset; + continue; /*try the next byte*/ + } + if(lazy) { + lazy = 0; + if(pos == 0) ERROR_BREAK(81); + if(length > lazylength + 1) { + /*push the previous character as literal*/ + if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); + } else { + length = lazylength; + offset = lazyoffset; + hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ + hash->headz[numzeros] = -1; /*idem*/ + --pos; + } + } + } + if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); + + /*encode it as length/distance pair or literal value*/ + if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } else if(length < minmatch || (length == 3 && offset > 4096)) { + /*compensate for the fact that longer offsets have more extra bits, a + length of only 3 may be not worth it then*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } else { + addLengthDistance(out, length, offset); + for(i = 1; i < length; ++i) { + ++pos; + wpos = pos & (windowsize - 1); + hashval = getHash(in, insize, pos); + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } else { + numzeros = 0; + } + updateHashChain(hash, wpos, hashval, numzeros); + } + } + } /*end of the loop through each character of input*/ + + return error; +} + +/* /////////////////////////////////////////////////////////////////////////// */ + +static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) { + /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, + 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ + + size_t i, numdeflateblocks = (datasize + 65534u) / 65535u; + size_t datapos = 0; + for(i = 0; i != numdeflateblocks; ++i) { + unsigned BFINAL, BTYPE, LEN, NLEN; + unsigned char firstbyte; + size_t pos = out->size; + + BFINAL = (i == numdeflateblocks - 1); + BTYPE = 0; + + LEN = 65535; + if(datasize - datapos < 65535u) LEN = (unsigned)datasize - (unsigned)datapos; + NLEN = 65535 - LEN; + + if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/ + + firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u)); + out->data[pos + 0] = firstbyte; + out->data[pos + 1] = (unsigned char)(LEN & 255); + out->data[pos + 2] = (unsigned char)(LEN >> 8u); + out->data[pos + 3] = (unsigned char)(NLEN & 255); + out->data[pos + 4] = (unsigned char)(NLEN >> 8u); + lodepng_memcpy(out->data + pos + 5, data + datapos, LEN); + datapos += LEN; + } + + return 0; +} + +/* +write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. +tree_ll: the tree for lit and len codes. +tree_d: the tree for distance codes. +*/ +static void writeLZ77data(LodePNGBitWriter* writer, const uivector* lz77_encoded, + const HuffmanTree* tree_ll, const HuffmanTree* tree_d) { + size_t i = 0; + for(i = 0; i != lz77_encoded->size; ++i) { + unsigned val = lz77_encoded->data[i]; + writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]); + if(val > 256) /*for a length code, 3 more things have to be added*/ { + unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; + unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; + unsigned length_extra_bits = lz77_encoded->data[++i]; + + unsigned distance_code = lz77_encoded->data[++i]; + + unsigned distance_index = distance_code; + unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; + unsigned distance_extra_bits = lz77_encoded->data[++i]; + + writeBits(writer, length_extra_bits, n_length_extra_bits); + writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]); + writeBits(writer, distance_extra_bits, n_distance_extra_bits); + } + } +} + +/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ +static unsigned deflateDynamic(LodePNGBitWriter* writer, Hash* hash, + const unsigned char* data, size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) { + unsigned error = 0; + + /* + A block is compressed as follows: The PNG data is lz77 encoded, resulting in + literal bytes and length/distance pairs. This is then huffman compressed with + two huffman trees. One huffman tree is used for the lit and len values ("ll"), + another huffman tree is used for the dist values ("d"). These two trees are + stored using their code lengths, and to compress even more these code lengths + are also run-length encoded and huffman compressed. This gives a huffman tree + of code lengths "cl". The code lengths used to describe this third tree are + the code length code lengths ("clcl"). + */ + + /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ + uivector lz77_encoded; + HuffmanTree tree_ll; /*tree for lit,len values*/ + HuffmanTree tree_d; /*tree for distance codes*/ + HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ + unsigned* frequencies_ll = 0; /*frequency of lit,len codes*/ + unsigned* frequencies_d = 0; /*frequency of dist codes*/ + unsigned* frequencies_cl = 0; /*frequency of code length codes*/ + unsigned* bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/ + unsigned* bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/ + size_t datasize = dataend - datapos; + + /* + If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent + tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are + some analogies: + bitlen_lld is to tree_cl what data is to tree_ll and tree_d. + bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. + bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. + */ + + unsigned BFINAL = final; + size_t i; + size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl; + unsigned HLIT, HDIST, HCLEN; + + uivector_init(&lz77_encoded); + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + HuffmanTree_init(&tree_cl); + /* could fit on stack, but >1KB is on the larger side so allocate instead */ + frequencies_ll = (unsigned*)lodepng_malloc(286 * sizeof(*frequencies_ll)); + frequencies_d = (unsigned*)lodepng_malloc(30 * sizeof(*frequencies_d)); + frequencies_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/ + + /*This while loop never loops due to a break at the end, it is here to + allow breaking out of it to the cleanup phase on error conditions.*/ + while(!error) { + lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll)); + lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d)); + lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(settings->use_lz77) { + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(error) break; + } else { + if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); + for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + } + + /*Count the frequencies of lit, len and dist codes*/ + for(i = 0; i != lz77_encoded.size; ++i) { + unsigned symbol = lz77_encoded.data[i]; + ++frequencies_ll[symbol]; + if(symbol > 256) { + unsigned dist = lz77_encoded.data[i + 2]; + ++frequencies_d[dist]; + i += 3; + } + } + frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ + + /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ + error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15); + if(error) break; + /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ + error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15); + if(error) break; + + numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286); + numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30); + /*store the code lengths of both generated trees in bitlen_lld*/ + numcodes_lld = numcodes_ll + numcodes_d; + bitlen_lld = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld)); + /*numcodes_lld_e never needs more size than bitlen_lld*/ + bitlen_lld_e = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e)); + if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/ + numcodes_lld_e = 0; + + for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i]; + for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i]; + + /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), + 17 (3-10 zeroes), 18 (11-138 zeroes)*/ + for(i = 0; i != numcodes_lld; ++i) { + unsigned j = 0; /*amount of repetitions*/ + while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j; + + if(bitlen_lld[i] == 0 && j >= 2) /*repeat code for zeroes*/ { + ++j; /*include the first zero*/ + if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ { + bitlen_lld_e[numcodes_lld_e++] = 17; + bitlen_lld_e[numcodes_lld_e++] = j - 3; + } else /*repeat code 18 supports max 138 zeroes*/ { + if(j > 138) j = 138; + bitlen_lld_e[numcodes_lld_e++] = 18; + bitlen_lld_e[numcodes_lld_e++] = j - 11; + } + i += (j - 1); + } else if(j >= 3) /*repeat code for value other than zero*/ { + size_t k; + unsigned num = j / 6u, rest = j % 6u; + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + for(k = 0; k < num; ++k) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = 6 - 3; + } + if(rest >= 3) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = rest - 3; + } + else j -= rest; + i += j; + } else /*too short to benefit from repeat code*/ { + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + } + } + + /*generate tree_cl, the huffmantree of huffmantrees*/ + for(i = 0; i != numcodes_lld_e; ++i) { + ++frequencies_cl[bitlen_lld_e[i]]; + /*after a repeat code come the bits that specify the number of repetitions, + those don't need to be in the frequencies_cl calculation*/ + if(bitlen_lld_e[i] >= 16) ++i; + } + + error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl, + NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*compute amount of code-length-code-lengths to output*/ + numcodes_cl = NUM_CODE_LENGTH_CODES; + /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/ + while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) { + numcodes_cl--; + } + + /* + Write everything into the output + + After the BFINAL and BTYPE, the dynamic block consists out of the following: + - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN + - (HCLEN+4)*3 bits code lengths of code length alphabet + - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - HDIST + 1 code lengths of distance alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - compressed data + - 256 (end code) + */ + + /*Write block type*/ + writeBits(writer, BFINAL, 1); + writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/ + writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/ + + /*write the HLIT, HDIST and HCLEN values*/ + /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies + or in the loop for numcodes_cl above, which saves space. */ + HLIT = (unsigned)(numcodes_ll - 257); + HDIST = (unsigned)(numcodes_d - 1); + HCLEN = (unsigned)(numcodes_cl - 4); + writeBits(writer, HLIT, 5); + writeBits(writer, HDIST, 5); + writeBits(writer, HCLEN, 4); + + /*write the code lengths of the code length alphabet ("bitlen_cl")*/ + for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3); + + /*write the lengths of the lit/len AND the dist alphabet*/ + for(i = 0; i != numcodes_lld_e; ++i) { + writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]); + /*extra bits of repeat codes*/ + if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2); + else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3); + else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7); + } + + /*write the compressed data symbols*/ + writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + /*error: the length of the end code 256 must be larger than 0*/ + if(tree_ll.lengths[256] == 0) ERROR_BREAK(64); + + /*write the end code*/ + writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); + + break; /*end of error-while*/ + } + + /*cleanup*/ + uivector_cleanup(&lz77_encoded); + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + HuffmanTree_cleanup(&tree_cl); + lodepng_free(frequencies_ll); + lodepng_free(frequencies_d); + lodepng_free(frequencies_cl); + lodepng_free(bitlen_lld); + lodepng_free(bitlen_lld_e); + + return error; +} + +static unsigned deflateFixed(LodePNGBitWriter* writer, Hash* hash, + const unsigned char* data, + size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) { + HuffmanTree tree_ll; /*tree for literal values and length codes*/ + HuffmanTree tree_d; /*tree for distance codes*/ + + unsigned BFINAL = final; + unsigned error = 0; + size_t i; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + error = generateFixedLitLenTree(&tree_ll); + if(!error) error = generateFixedDistanceTree(&tree_d); + + if(!error) { + writeBits(writer, BFINAL, 1); + writeBits(writer, 1, 1); /*first bit of BTYPE*/ + writeBits(writer, 0, 1); /*second bit of BTYPE*/ + + if(settings->use_lz77) /*LZ77 encoded*/ { + uivector lz77_encoded; + uivector_init(&lz77_encoded); + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + uivector_cleanup(&lz77_encoded); + } else /*no LZ77, but still will be Huffman compressed*/ { + for(i = datapos; i < dataend; ++i) { + writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]); + } + } + /*add END code*/ + if(!error) writeBitsReversed(writer,tree_ll.codes[256], tree_ll.lengths[256]); + } + + /*cleanup*/ + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + unsigned error = 0; + size_t i, blocksize, numdeflateblocks; + Hash hash; + LodePNGBitWriter writer; + + LodePNGBitWriter_init(&writer, out); + + if(settings->btype > 2) return 61; + else if(settings->btype == 0) return deflateNoCompression(out, in, insize); + else if(settings->btype == 1) blocksize = insize; + else /*if(settings->btype == 2)*/ { + /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ + blocksize = insize / 8u + 8; + if(blocksize < 65536) blocksize = 65536; + if(blocksize > 262144) blocksize = 262144; + } + + numdeflateblocks = (insize + blocksize - 1) / blocksize; + if(numdeflateblocks == 0) numdeflateblocks = 1; + + error = hash_init(&hash, settings->windowsize); + + if(!error) { + for(i = 0; i != numdeflateblocks && !error; ++i) { + unsigned final = (i == numdeflateblocks - 1); + size_t start = i * blocksize; + size_t end = start + blocksize; + if(end > insize) end = insize; + + if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final); + else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final); + } + } + + hash_cleanup(&hash); + + return error; +} + +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_deflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + if(settings->custom_deflate) { + unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); + /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } else { + return lodepng_deflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Adler32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned update_adler32(unsigned adler, const unsigned char* data, size_t len) { + unsigned s1 = adler & 0xffffu; + unsigned s2 = (adler >> 16u) & 0xffffu; + + while(len != 0u) { + size_t i; + /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ + size_t amount = len > 5552u ? 5552u : len; + len -= amount; + for(i = 0; i != amount; ++i) { + s1 += (*data++); + s2 += s1; + } + s1 %= 65521u; + s2 %= 65521u; + } + + return (s2 << 16u) | s1; +} + +/*Return the adler32 of the bytes data[0..len-1]*/ +static unsigned adler32(const unsigned char* data, size_t len) { + return update_adler32(1u, data, len); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Zlib / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DECODER + +static unsigned lodepng_zlib_decompressv(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + unsigned error = 0; + unsigned CM, CINFO, FDICT; + + if(insize < 2) return 53; /*error, size of zlib data too small*/ + /*read information from zlib header*/ + if((in[0] * 256 + in[1]) % 31 != 0) { + /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ + return 24; + } + + CM = in[0] & 15; + CINFO = (in[0] >> 4) & 15; + /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ + FDICT = (in[1] >> 5) & 1; + /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ + + if(CM != 8 || CINFO > 7) { + /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ + return 25; + } + if(FDICT != 0) { + /*error: the specification of PNG says about the zlib stream: + "The additional flags shall not specify a preset dictionary."*/ + return 26; + } + + error = inflatev(out, in + 2, insize - 2, settings); + if(error) return error; + + if(!settings->ignore_adler32) { + unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); + unsigned checksum = adler32(out->data, out->size); + if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ + } + + return 0; /*no error*/ +} + + +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, + const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { + unsigned error; + if(settings->custom_zlib) { + error = settings->custom_zlib(out, outsize, in, insize, settings); + if(error) { + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; + } + } else { + ucvector v = ucvector_init(*out, *outsize); + if(expected_size) { + /*reserve the memory to avoid intermediate reallocations*/ + ucvector_resize(&v, *outsize + expected_size); + v.size = *outsize; + } + error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + } + return error; +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + size_t i; + unsigned error; + unsigned char* deflatedata = 0; + size_t deflatesize = 0; + + error = deflate(&deflatedata, &deflatesize, in, insize, settings); + + *out = NULL; + *outsize = 0; + if(!error) { + *outsize = deflatesize + 6; + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!*out) error = 83; /*alloc fail*/ + } + + if(!error) { + unsigned ADLER32 = adler32(in, insize); + /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ + unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ + unsigned FLEVEL = 0; + unsigned FDICT = 0; + unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; + unsigned FCHECK = 31 - CMFFLG % 31; + CMFFLG += FCHECK; + + (*out)[0] = (unsigned char)(CMFFLG >> 8); + (*out)[1] = (unsigned char)(CMFFLG & 255); + for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i]; + lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32); + } + + lodepng_free(deflatedata); + return error; +} + +/* compress using the default or custom zlib function */ +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + if(settings->custom_zlib) { + unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } else { + return lodepng_zlib_compress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#else /*no LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DECODER +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, + const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + (void)expected_size; + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/*this is a good tradeoff between speed and compression ratio*/ +#define DEFAULT_WINDOWSIZE 2048 + +void lodepng_compress_settings_init(LodePNGCompressSettings* settings) { + /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ + settings->btype = 2; + settings->use_lz77 = 1; + settings->windowsize = DEFAULT_WINDOWSIZE; + settings->minmatch = 3; + settings->nicematch = 128; + settings->lazymatching = 1; + + settings->custom_zlib = 0; + settings->custom_deflate = 0; + settings->custom_context = 0; +} + +const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; + + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) { + settings->ignore_adler32 = 0; + settings->ignore_nlen = 0; + settings->max_output_size = 0; + + settings->custom_zlib = 0; + settings->custom_inflate = 0; + settings->custom_context = 0; +} + +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of Zlib related code. Begin of PNG related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / CRC32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +#ifdef LODEPNG_COMPILE_CRC + +static const unsigned lodepng_crc32_table0[256] = { + 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, + 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, + 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, + 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, + 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, + 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, + 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu, + 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du, + 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u, + 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, + 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, + 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, + 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, + 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, + 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu, + 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu, + 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u, + 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u, + 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, + 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, + 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, + 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, + 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, + 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, + 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u, + 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u, + 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u, + 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, + 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, + 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, + 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, + 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du +}; + +static const unsigned lodepng_crc32_table1[256] = { + 0x00000000u, 0x191b3141u, 0x32366282u, 0x2b2d53c3u, 0x646cc504u, 0x7d77f445u, 0x565aa786u, 0x4f4196c7u, + 0xc8d98a08u, 0xd1c2bb49u, 0xfaefe88au, 0xe3f4d9cbu, 0xacb54f0cu, 0xb5ae7e4du, 0x9e832d8eu, 0x87981ccfu, + 0x4ac21251u, 0x53d92310u, 0x78f470d3u, 0x61ef4192u, 0x2eaed755u, 0x37b5e614u, 0x1c98b5d7u, 0x05838496u, + 0x821b9859u, 0x9b00a918u, 0xb02dfadbu, 0xa936cb9au, 0xe6775d5du, 0xff6c6c1cu, 0xd4413fdfu, 0xcd5a0e9eu, + 0x958424a2u, 0x8c9f15e3u, 0xa7b24620u, 0xbea97761u, 0xf1e8e1a6u, 0xe8f3d0e7u, 0xc3de8324u, 0xdac5b265u, + 0x5d5daeaau, 0x44469febu, 0x6f6bcc28u, 0x7670fd69u, 0x39316baeu, 0x202a5aefu, 0x0b07092cu, 0x121c386du, + 0xdf4636f3u, 0xc65d07b2u, 0xed705471u, 0xf46b6530u, 0xbb2af3f7u, 0xa231c2b6u, 0x891c9175u, 0x9007a034u, + 0x179fbcfbu, 0x0e848dbau, 0x25a9de79u, 0x3cb2ef38u, 0x73f379ffu, 0x6ae848beu, 0x41c51b7du, 0x58de2a3cu, + 0xf0794f05u, 0xe9627e44u, 0xc24f2d87u, 0xdb541cc6u, 0x94158a01u, 0x8d0ebb40u, 0xa623e883u, 0xbf38d9c2u, + 0x38a0c50du, 0x21bbf44cu, 0x0a96a78fu, 0x138d96ceu, 0x5ccc0009u, 0x45d73148u, 0x6efa628bu, 0x77e153cau, + 0xbabb5d54u, 0xa3a06c15u, 0x888d3fd6u, 0x91960e97u, 0xded79850u, 0xc7cca911u, 0xece1fad2u, 0xf5facb93u, + 0x7262d75cu, 0x6b79e61du, 0x4054b5deu, 0x594f849fu, 0x160e1258u, 0x0f152319u, 0x243870dau, 0x3d23419bu, + 0x65fd6ba7u, 0x7ce65ae6u, 0x57cb0925u, 0x4ed03864u, 0x0191aea3u, 0x188a9fe2u, 0x33a7cc21u, 0x2abcfd60u, + 0xad24e1afu, 0xb43fd0eeu, 0x9f12832du, 0x8609b26cu, 0xc94824abu, 0xd05315eau, 0xfb7e4629u, 0xe2657768u, + 0x2f3f79f6u, 0x362448b7u, 0x1d091b74u, 0x04122a35u, 0x4b53bcf2u, 0x52488db3u, 0x7965de70u, 0x607eef31u, + 0xe7e6f3feu, 0xfefdc2bfu, 0xd5d0917cu, 0xcccba03du, 0x838a36fau, 0x9a9107bbu, 0xb1bc5478u, 0xa8a76539u, + 0x3b83984bu, 0x2298a90au, 0x09b5fac9u, 0x10aecb88u, 0x5fef5d4fu, 0x46f46c0eu, 0x6dd93fcdu, 0x74c20e8cu, + 0xf35a1243u, 0xea412302u, 0xc16c70c1u, 0xd8774180u, 0x9736d747u, 0x8e2de606u, 0xa500b5c5u, 0xbc1b8484u, + 0x71418a1au, 0x685abb5bu, 0x4377e898u, 0x5a6cd9d9u, 0x152d4f1eu, 0x0c367e5fu, 0x271b2d9cu, 0x3e001cddu, + 0xb9980012u, 0xa0833153u, 0x8bae6290u, 0x92b553d1u, 0xddf4c516u, 0xc4eff457u, 0xefc2a794u, 0xf6d996d5u, + 0xae07bce9u, 0xb71c8da8u, 0x9c31de6bu, 0x852aef2au, 0xca6b79edu, 0xd37048acu, 0xf85d1b6fu, 0xe1462a2eu, + 0x66de36e1u, 0x7fc507a0u, 0x54e85463u, 0x4df36522u, 0x02b2f3e5u, 0x1ba9c2a4u, 0x30849167u, 0x299fa026u, + 0xe4c5aeb8u, 0xfdde9ff9u, 0xd6f3cc3au, 0xcfe8fd7bu, 0x80a96bbcu, 0x99b25afdu, 0xb29f093eu, 0xab84387fu, + 0x2c1c24b0u, 0x350715f1u, 0x1e2a4632u, 0x07317773u, 0x4870e1b4u, 0x516bd0f5u, 0x7a468336u, 0x635db277u, + 0xcbfad74eu, 0xd2e1e60fu, 0xf9ccb5ccu, 0xe0d7848du, 0xaf96124au, 0xb68d230bu, 0x9da070c8u, 0x84bb4189u, + 0x03235d46u, 0x1a386c07u, 0x31153fc4u, 0x280e0e85u, 0x674f9842u, 0x7e54a903u, 0x5579fac0u, 0x4c62cb81u, + 0x8138c51fu, 0x9823f45eu, 0xb30ea79du, 0xaa1596dcu, 0xe554001bu, 0xfc4f315au, 0xd7626299u, 0xce7953d8u, + 0x49e14f17u, 0x50fa7e56u, 0x7bd72d95u, 0x62cc1cd4u, 0x2d8d8a13u, 0x3496bb52u, 0x1fbbe891u, 0x06a0d9d0u, + 0x5e7ef3ecu, 0x4765c2adu, 0x6c48916eu, 0x7553a02fu, 0x3a1236e8u, 0x230907a9u, 0x0824546au, 0x113f652bu, + 0x96a779e4u, 0x8fbc48a5u, 0xa4911b66u, 0xbd8a2a27u, 0xf2cbbce0u, 0xebd08da1u, 0xc0fdde62u, 0xd9e6ef23u, + 0x14bce1bdu, 0x0da7d0fcu, 0x268a833fu, 0x3f91b27eu, 0x70d024b9u, 0x69cb15f8u, 0x42e6463bu, 0x5bfd777au, + 0xdc656bb5u, 0xc57e5af4u, 0xee530937u, 0xf7483876u, 0xb809aeb1u, 0xa1129ff0u, 0x8a3fcc33u, 0x9324fd72u +}; + +static const unsigned lodepng_crc32_table2[256] = { + 0x00000000u, 0x01c26a37u, 0x0384d46eu, 0x0246be59u, 0x0709a8dcu, 0x06cbc2ebu, 0x048d7cb2u, 0x054f1685u, + 0x0e1351b8u, 0x0fd13b8fu, 0x0d9785d6u, 0x0c55efe1u, 0x091af964u, 0x08d89353u, 0x0a9e2d0au, 0x0b5c473du, + 0x1c26a370u, 0x1de4c947u, 0x1fa2771eu, 0x1e601d29u, 0x1b2f0bacu, 0x1aed619bu, 0x18abdfc2u, 0x1969b5f5u, + 0x1235f2c8u, 0x13f798ffu, 0x11b126a6u, 0x10734c91u, 0x153c5a14u, 0x14fe3023u, 0x16b88e7au, 0x177ae44du, + 0x384d46e0u, 0x398f2cd7u, 0x3bc9928eu, 0x3a0bf8b9u, 0x3f44ee3cu, 0x3e86840bu, 0x3cc03a52u, 0x3d025065u, + 0x365e1758u, 0x379c7d6fu, 0x35dac336u, 0x3418a901u, 0x3157bf84u, 0x3095d5b3u, 0x32d36beau, 0x331101ddu, + 0x246be590u, 0x25a98fa7u, 0x27ef31feu, 0x262d5bc9u, 0x23624d4cu, 0x22a0277bu, 0x20e69922u, 0x2124f315u, + 0x2a78b428u, 0x2bbade1fu, 0x29fc6046u, 0x283e0a71u, 0x2d711cf4u, 0x2cb376c3u, 0x2ef5c89au, 0x2f37a2adu, + 0x709a8dc0u, 0x7158e7f7u, 0x731e59aeu, 0x72dc3399u, 0x7793251cu, 0x76514f2bu, 0x7417f172u, 0x75d59b45u, + 0x7e89dc78u, 0x7f4bb64fu, 0x7d0d0816u, 0x7ccf6221u, 0x798074a4u, 0x78421e93u, 0x7a04a0cau, 0x7bc6cafdu, + 0x6cbc2eb0u, 0x6d7e4487u, 0x6f38fadeu, 0x6efa90e9u, 0x6bb5866cu, 0x6a77ec5bu, 0x68315202u, 0x69f33835u, + 0x62af7f08u, 0x636d153fu, 0x612bab66u, 0x60e9c151u, 0x65a6d7d4u, 0x6464bde3u, 0x662203bau, 0x67e0698du, + 0x48d7cb20u, 0x4915a117u, 0x4b531f4eu, 0x4a917579u, 0x4fde63fcu, 0x4e1c09cbu, 0x4c5ab792u, 0x4d98dda5u, + 0x46c49a98u, 0x4706f0afu, 0x45404ef6u, 0x448224c1u, 0x41cd3244u, 0x400f5873u, 0x4249e62au, 0x438b8c1du, + 0x54f16850u, 0x55330267u, 0x5775bc3eu, 0x56b7d609u, 0x53f8c08cu, 0x523aaabbu, 0x507c14e2u, 0x51be7ed5u, + 0x5ae239e8u, 0x5b2053dfu, 0x5966ed86u, 0x58a487b1u, 0x5deb9134u, 0x5c29fb03u, 0x5e6f455au, 0x5fad2f6du, + 0xe1351b80u, 0xe0f771b7u, 0xe2b1cfeeu, 0xe373a5d9u, 0xe63cb35cu, 0xe7fed96bu, 0xe5b86732u, 0xe47a0d05u, + 0xef264a38u, 0xeee4200fu, 0xeca29e56u, 0xed60f461u, 0xe82fe2e4u, 0xe9ed88d3u, 0xebab368au, 0xea695cbdu, + 0xfd13b8f0u, 0xfcd1d2c7u, 0xfe976c9eu, 0xff5506a9u, 0xfa1a102cu, 0xfbd87a1bu, 0xf99ec442u, 0xf85cae75u, + 0xf300e948u, 0xf2c2837fu, 0xf0843d26u, 0xf1465711u, 0xf4094194u, 0xf5cb2ba3u, 0xf78d95fau, 0xf64fffcdu, + 0xd9785d60u, 0xd8ba3757u, 0xdafc890eu, 0xdb3ee339u, 0xde71f5bcu, 0xdfb39f8bu, 0xddf521d2u, 0xdc374be5u, + 0xd76b0cd8u, 0xd6a966efu, 0xd4efd8b6u, 0xd52db281u, 0xd062a404u, 0xd1a0ce33u, 0xd3e6706au, 0xd2241a5du, + 0xc55efe10u, 0xc49c9427u, 0xc6da2a7eu, 0xc7184049u, 0xc25756ccu, 0xc3953cfbu, 0xc1d382a2u, 0xc011e895u, + 0xcb4dafa8u, 0xca8fc59fu, 0xc8c97bc6u, 0xc90b11f1u, 0xcc440774u, 0xcd866d43u, 0xcfc0d31au, 0xce02b92du, + 0x91af9640u, 0x906dfc77u, 0x922b422eu, 0x93e92819u, 0x96a63e9cu, 0x976454abu, 0x9522eaf2u, 0x94e080c5u, + 0x9fbcc7f8u, 0x9e7eadcfu, 0x9c381396u, 0x9dfa79a1u, 0x98b56f24u, 0x99770513u, 0x9b31bb4au, 0x9af3d17du, + 0x8d893530u, 0x8c4b5f07u, 0x8e0de15eu, 0x8fcf8b69u, 0x8a809decu, 0x8b42f7dbu, 0x89044982u, 0x88c623b5u, + 0x839a6488u, 0x82580ebfu, 0x801eb0e6u, 0x81dcdad1u, 0x8493cc54u, 0x8551a663u, 0x8717183au, 0x86d5720du, + 0xa9e2d0a0u, 0xa820ba97u, 0xaa6604ceu, 0xaba46ef9u, 0xaeeb787cu, 0xaf29124bu, 0xad6fac12u, 0xacadc625u, + 0xa7f18118u, 0xa633eb2fu, 0xa4755576u, 0xa5b73f41u, 0xa0f829c4u, 0xa13a43f3u, 0xa37cfdaau, 0xa2be979du, + 0xb5c473d0u, 0xb40619e7u, 0xb640a7beu, 0xb782cd89u, 0xb2cddb0cu, 0xb30fb13bu, 0xb1490f62u, 0xb08b6555u, + 0xbbd72268u, 0xba15485fu, 0xb853f606u, 0xb9919c31u, 0xbcde8ab4u, 0xbd1ce083u, 0xbf5a5edau, 0xbe9834edu +}; + +static const unsigned lodepng_crc32_table3[256] = { + 0x00000000u, 0xb8bc6765u, 0xaa09c88bu, 0x12b5afeeu, 0x8f629757u, 0x37def032u, 0x256b5fdcu, 0x9dd738b9u, + 0xc5b428efu, 0x7d084f8au, 0x6fbde064u, 0xd7018701u, 0x4ad6bfb8u, 0xf26ad8ddu, 0xe0df7733u, 0x58631056u, + 0x5019579fu, 0xe8a530fau, 0xfa109f14u, 0x42acf871u, 0xdf7bc0c8u, 0x67c7a7adu, 0x75720843u, 0xcdce6f26u, + 0x95ad7f70u, 0x2d111815u, 0x3fa4b7fbu, 0x8718d09eu, 0x1acfe827u, 0xa2738f42u, 0xb0c620acu, 0x087a47c9u, + 0xa032af3eu, 0x188ec85bu, 0x0a3b67b5u, 0xb28700d0u, 0x2f503869u, 0x97ec5f0cu, 0x8559f0e2u, 0x3de59787u, + 0x658687d1u, 0xdd3ae0b4u, 0xcf8f4f5au, 0x7733283fu, 0xeae41086u, 0x525877e3u, 0x40edd80du, 0xf851bf68u, + 0xf02bf8a1u, 0x48979fc4u, 0x5a22302au, 0xe29e574fu, 0x7f496ff6u, 0xc7f50893u, 0xd540a77du, 0x6dfcc018u, + 0x359fd04eu, 0x8d23b72bu, 0x9f9618c5u, 0x272a7fa0u, 0xbafd4719u, 0x0241207cu, 0x10f48f92u, 0xa848e8f7u, + 0x9b14583du, 0x23a83f58u, 0x311d90b6u, 0x89a1f7d3u, 0x1476cf6au, 0xaccaa80fu, 0xbe7f07e1u, 0x06c36084u, + 0x5ea070d2u, 0xe61c17b7u, 0xf4a9b859u, 0x4c15df3cu, 0xd1c2e785u, 0x697e80e0u, 0x7bcb2f0eu, 0xc377486bu, + 0xcb0d0fa2u, 0x73b168c7u, 0x6104c729u, 0xd9b8a04cu, 0x446f98f5u, 0xfcd3ff90u, 0xee66507eu, 0x56da371bu, + 0x0eb9274du, 0xb6054028u, 0xa4b0efc6u, 0x1c0c88a3u, 0x81dbb01au, 0x3967d77fu, 0x2bd27891u, 0x936e1ff4u, + 0x3b26f703u, 0x839a9066u, 0x912f3f88u, 0x299358edu, 0xb4446054u, 0x0cf80731u, 0x1e4da8dfu, 0xa6f1cfbau, + 0xfe92dfecu, 0x462eb889u, 0x549b1767u, 0xec277002u, 0x71f048bbu, 0xc94c2fdeu, 0xdbf98030u, 0x6345e755u, + 0x6b3fa09cu, 0xd383c7f9u, 0xc1366817u, 0x798a0f72u, 0xe45d37cbu, 0x5ce150aeu, 0x4e54ff40u, 0xf6e89825u, + 0xae8b8873u, 0x1637ef16u, 0x048240f8u, 0xbc3e279du, 0x21e91f24u, 0x99557841u, 0x8be0d7afu, 0x335cb0cau, + 0xed59b63bu, 0x55e5d15eu, 0x47507eb0u, 0xffec19d5u, 0x623b216cu, 0xda874609u, 0xc832e9e7u, 0x708e8e82u, + 0x28ed9ed4u, 0x9051f9b1u, 0x82e4565fu, 0x3a58313au, 0xa78f0983u, 0x1f336ee6u, 0x0d86c108u, 0xb53aa66du, + 0xbd40e1a4u, 0x05fc86c1u, 0x1749292fu, 0xaff54e4au, 0x322276f3u, 0x8a9e1196u, 0x982bbe78u, 0x2097d91du, + 0x78f4c94bu, 0xc048ae2eu, 0xd2fd01c0u, 0x6a4166a5u, 0xf7965e1cu, 0x4f2a3979u, 0x5d9f9697u, 0xe523f1f2u, + 0x4d6b1905u, 0xf5d77e60u, 0xe762d18eu, 0x5fdeb6ebu, 0xc2098e52u, 0x7ab5e937u, 0x680046d9u, 0xd0bc21bcu, + 0x88df31eau, 0x3063568fu, 0x22d6f961u, 0x9a6a9e04u, 0x07bda6bdu, 0xbf01c1d8u, 0xadb46e36u, 0x15080953u, + 0x1d724e9au, 0xa5ce29ffu, 0xb77b8611u, 0x0fc7e174u, 0x9210d9cdu, 0x2aacbea8u, 0x38191146u, 0x80a57623u, + 0xd8c66675u, 0x607a0110u, 0x72cfaefeu, 0xca73c99bu, 0x57a4f122u, 0xef189647u, 0xfdad39a9u, 0x45115eccu, + 0x764dee06u, 0xcef18963u, 0xdc44268du, 0x64f841e8u, 0xf92f7951u, 0x41931e34u, 0x5326b1dau, 0xeb9ad6bfu, + 0xb3f9c6e9u, 0x0b45a18cu, 0x19f00e62u, 0xa14c6907u, 0x3c9b51beu, 0x842736dbu, 0x96929935u, 0x2e2efe50u, + 0x2654b999u, 0x9ee8defcu, 0x8c5d7112u, 0x34e11677u, 0xa9362eceu, 0x118a49abu, 0x033fe645u, 0xbb838120u, + 0xe3e09176u, 0x5b5cf613u, 0x49e959fdu, 0xf1553e98u, 0x6c820621u, 0xd43e6144u, 0xc68bceaau, 0x7e37a9cfu, + 0xd67f4138u, 0x6ec3265du, 0x7c7689b3u, 0xc4caeed6u, 0x591dd66fu, 0xe1a1b10au, 0xf3141ee4u, 0x4ba87981u, + 0x13cb69d7u, 0xab770eb2u, 0xb9c2a15cu, 0x017ec639u, 0x9ca9fe80u, 0x241599e5u, 0x36a0360bu, 0x8e1c516eu, + 0x866616a7u, 0x3eda71c2u, 0x2c6fde2cu, 0x94d3b949u, 0x090481f0u, 0xb1b8e695u, 0xa30d497bu, 0x1bb12e1eu, + 0x43d23e48u, 0xfb6e592du, 0xe9dbf6c3u, 0x516791a6u, 0xccb0a91fu, 0x740cce7au, 0x66b96194u, 0xde0506f1u +}; + +static const unsigned lodepng_crc32_table4[256] = { + 0x00000000u, 0x3d6029b0u, 0x7ac05360u, 0x47a07ad0u, 0xf580a6c0u, 0xc8e08f70u, 0x8f40f5a0u, 0xb220dc10u, + 0x30704bc1u, 0x0d106271u, 0x4ab018a1u, 0x77d03111u, 0xc5f0ed01u, 0xf890c4b1u, 0xbf30be61u, 0x825097d1u, + 0x60e09782u, 0x5d80be32u, 0x1a20c4e2u, 0x2740ed52u, 0x95603142u, 0xa80018f2u, 0xefa06222u, 0xd2c04b92u, + 0x5090dc43u, 0x6df0f5f3u, 0x2a508f23u, 0x1730a693u, 0xa5107a83u, 0x98705333u, 0xdfd029e3u, 0xe2b00053u, + 0xc1c12f04u, 0xfca106b4u, 0xbb017c64u, 0x866155d4u, 0x344189c4u, 0x0921a074u, 0x4e81daa4u, 0x73e1f314u, + 0xf1b164c5u, 0xccd14d75u, 0x8b7137a5u, 0xb6111e15u, 0x0431c205u, 0x3951ebb5u, 0x7ef19165u, 0x4391b8d5u, + 0xa121b886u, 0x9c419136u, 0xdbe1ebe6u, 0xe681c256u, 0x54a11e46u, 0x69c137f6u, 0x2e614d26u, 0x13016496u, + 0x9151f347u, 0xac31daf7u, 0xeb91a027u, 0xd6f18997u, 0x64d15587u, 0x59b17c37u, 0x1e1106e7u, 0x23712f57u, + 0x58f35849u, 0x659371f9u, 0x22330b29u, 0x1f532299u, 0xad73fe89u, 0x9013d739u, 0xd7b3ade9u, 0xead38459u, + 0x68831388u, 0x55e33a38u, 0x124340e8u, 0x2f236958u, 0x9d03b548u, 0xa0639cf8u, 0xe7c3e628u, 0xdaa3cf98u, + 0x3813cfcbu, 0x0573e67bu, 0x42d39cabu, 0x7fb3b51bu, 0xcd93690bu, 0xf0f340bbu, 0xb7533a6bu, 0x8a3313dbu, + 0x0863840au, 0x3503adbau, 0x72a3d76au, 0x4fc3fedau, 0xfde322cau, 0xc0830b7au, 0x872371aau, 0xba43581au, + 0x9932774du, 0xa4525efdu, 0xe3f2242du, 0xde920d9du, 0x6cb2d18du, 0x51d2f83du, 0x167282edu, 0x2b12ab5du, + 0xa9423c8cu, 0x9422153cu, 0xd3826fecu, 0xeee2465cu, 0x5cc29a4cu, 0x61a2b3fcu, 0x2602c92cu, 0x1b62e09cu, + 0xf9d2e0cfu, 0xc4b2c97fu, 0x8312b3afu, 0xbe729a1fu, 0x0c52460fu, 0x31326fbfu, 0x7692156fu, 0x4bf23cdfu, + 0xc9a2ab0eu, 0xf4c282beu, 0xb362f86eu, 0x8e02d1deu, 0x3c220dceu, 0x0142247eu, 0x46e25eaeu, 0x7b82771eu, + 0xb1e6b092u, 0x8c869922u, 0xcb26e3f2u, 0xf646ca42u, 0x44661652u, 0x79063fe2u, 0x3ea64532u, 0x03c66c82u, + 0x8196fb53u, 0xbcf6d2e3u, 0xfb56a833u, 0xc6368183u, 0x74165d93u, 0x49767423u, 0x0ed60ef3u, 0x33b62743u, + 0xd1062710u, 0xec660ea0u, 0xabc67470u, 0x96a65dc0u, 0x248681d0u, 0x19e6a860u, 0x5e46d2b0u, 0x6326fb00u, + 0xe1766cd1u, 0xdc164561u, 0x9bb63fb1u, 0xa6d61601u, 0x14f6ca11u, 0x2996e3a1u, 0x6e369971u, 0x5356b0c1u, + 0x70279f96u, 0x4d47b626u, 0x0ae7ccf6u, 0x3787e546u, 0x85a73956u, 0xb8c710e6u, 0xff676a36u, 0xc2074386u, + 0x4057d457u, 0x7d37fde7u, 0x3a978737u, 0x07f7ae87u, 0xb5d77297u, 0x88b75b27u, 0xcf1721f7u, 0xf2770847u, + 0x10c70814u, 0x2da721a4u, 0x6a075b74u, 0x576772c4u, 0xe547aed4u, 0xd8278764u, 0x9f87fdb4u, 0xa2e7d404u, + 0x20b743d5u, 0x1dd76a65u, 0x5a7710b5u, 0x67173905u, 0xd537e515u, 0xe857cca5u, 0xaff7b675u, 0x92979fc5u, + 0xe915e8dbu, 0xd475c16bu, 0x93d5bbbbu, 0xaeb5920bu, 0x1c954e1bu, 0x21f567abu, 0x66551d7bu, 0x5b3534cbu, + 0xd965a31au, 0xe4058aaau, 0xa3a5f07au, 0x9ec5d9cau, 0x2ce505dau, 0x11852c6au, 0x562556bau, 0x6b457f0au, + 0x89f57f59u, 0xb49556e9u, 0xf3352c39u, 0xce550589u, 0x7c75d999u, 0x4115f029u, 0x06b58af9u, 0x3bd5a349u, + 0xb9853498u, 0x84e51d28u, 0xc34567f8u, 0xfe254e48u, 0x4c059258u, 0x7165bbe8u, 0x36c5c138u, 0x0ba5e888u, + 0x28d4c7dfu, 0x15b4ee6fu, 0x521494bfu, 0x6f74bd0fu, 0xdd54611fu, 0xe03448afu, 0xa794327fu, 0x9af41bcfu, + 0x18a48c1eu, 0x25c4a5aeu, 0x6264df7eu, 0x5f04f6ceu, 0xed242adeu, 0xd044036eu, 0x97e479beu, 0xaa84500eu, + 0x4834505du, 0x755479edu, 0x32f4033du, 0x0f942a8du, 0xbdb4f69du, 0x80d4df2du, 0xc774a5fdu, 0xfa148c4du, + 0x78441b9cu, 0x4524322cu, 0x028448fcu, 0x3fe4614cu, 0x8dc4bd5cu, 0xb0a494ecu, 0xf704ee3cu, 0xca64c78cu +}; + +static const unsigned lodepng_crc32_table5[256] = { + 0x00000000u, 0xcb5cd3a5u, 0x4dc8a10bu, 0x869472aeu, 0x9b914216u, 0x50cd91b3u, 0xd659e31du, 0x1d0530b8u, + 0xec53826du, 0x270f51c8u, 0xa19b2366u, 0x6ac7f0c3u, 0x77c2c07bu, 0xbc9e13deu, 0x3a0a6170u, 0xf156b2d5u, + 0x03d6029bu, 0xc88ad13eu, 0x4e1ea390u, 0x85427035u, 0x9847408du, 0x531b9328u, 0xd58fe186u, 0x1ed33223u, + 0xef8580f6u, 0x24d95353u, 0xa24d21fdu, 0x6911f258u, 0x7414c2e0u, 0xbf481145u, 0x39dc63ebu, 0xf280b04eu, + 0x07ac0536u, 0xccf0d693u, 0x4a64a43du, 0x81387798u, 0x9c3d4720u, 0x57619485u, 0xd1f5e62bu, 0x1aa9358eu, + 0xebff875bu, 0x20a354feu, 0xa6372650u, 0x6d6bf5f5u, 0x706ec54du, 0xbb3216e8u, 0x3da66446u, 0xf6fab7e3u, + 0x047a07adu, 0xcf26d408u, 0x49b2a6a6u, 0x82ee7503u, 0x9feb45bbu, 0x54b7961eu, 0xd223e4b0u, 0x197f3715u, + 0xe82985c0u, 0x23755665u, 0xa5e124cbu, 0x6ebdf76eu, 0x73b8c7d6u, 0xb8e41473u, 0x3e7066ddu, 0xf52cb578u, + 0x0f580a6cu, 0xc404d9c9u, 0x4290ab67u, 0x89cc78c2u, 0x94c9487au, 0x5f959bdfu, 0xd901e971u, 0x125d3ad4u, + 0xe30b8801u, 0x28575ba4u, 0xaec3290au, 0x659ffaafu, 0x789aca17u, 0xb3c619b2u, 0x35526b1cu, 0xfe0eb8b9u, + 0x0c8e08f7u, 0xc7d2db52u, 0x4146a9fcu, 0x8a1a7a59u, 0x971f4ae1u, 0x5c439944u, 0xdad7ebeau, 0x118b384fu, + 0xe0dd8a9au, 0x2b81593fu, 0xad152b91u, 0x6649f834u, 0x7b4cc88cu, 0xb0101b29u, 0x36846987u, 0xfdd8ba22u, + 0x08f40f5au, 0xc3a8dcffu, 0x453cae51u, 0x8e607df4u, 0x93654d4cu, 0x58399ee9u, 0xdeadec47u, 0x15f13fe2u, + 0xe4a78d37u, 0x2ffb5e92u, 0xa96f2c3cu, 0x6233ff99u, 0x7f36cf21u, 0xb46a1c84u, 0x32fe6e2au, 0xf9a2bd8fu, + 0x0b220dc1u, 0xc07ede64u, 0x46eaaccau, 0x8db67f6fu, 0x90b34fd7u, 0x5bef9c72u, 0xdd7beedcu, 0x16273d79u, + 0xe7718facu, 0x2c2d5c09u, 0xaab92ea7u, 0x61e5fd02u, 0x7ce0cdbau, 0xb7bc1e1fu, 0x31286cb1u, 0xfa74bf14u, + 0x1eb014d8u, 0xd5ecc77du, 0x5378b5d3u, 0x98246676u, 0x852156ceu, 0x4e7d856bu, 0xc8e9f7c5u, 0x03b52460u, + 0xf2e396b5u, 0x39bf4510u, 0xbf2b37beu, 0x7477e41bu, 0x6972d4a3u, 0xa22e0706u, 0x24ba75a8u, 0xefe6a60du, + 0x1d661643u, 0xd63ac5e6u, 0x50aeb748u, 0x9bf264edu, 0x86f75455u, 0x4dab87f0u, 0xcb3ff55eu, 0x006326fbu, + 0xf135942eu, 0x3a69478bu, 0xbcfd3525u, 0x77a1e680u, 0x6aa4d638u, 0xa1f8059du, 0x276c7733u, 0xec30a496u, + 0x191c11eeu, 0xd240c24bu, 0x54d4b0e5u, 0x9f886340u, 0x828d53f8u, 0x49d1805du, 0xcf45f2f3u, 0x04192156u, + 0xf54f9383u, 0x3e134026u, 0xb8873288u, 0x73dbe12du, 0x6eded195u, 0xa5820230u, 0x2316709eu, 0xe84aa33bu, + 0x1aca1375u, 0xd196c0d0u, 0x5702b27eu, 0x9c5e61dbu, 0x815b5163u, 0x4a0782c6u, 0xcc93f068u, 0x07cf23cdu, + 0xf6999118u, 0x3dc542bdu, 0xbb513013u, 0x700de3b6u, 0x6d08d30eu, 0xa65400abu, 0x20c07205u, 0xeb9ca1a0u, + 0x11e81eb4u, 0xdab4cd11u, 0x5c20bfbfu, 0x977c6c1au, 0x8a795ca2u, 0x41258f07u, 0xc7b1fda9u, 0x0ced2e0cu, + 0xfdbb9cd9u, 0x36e74f7cu, 0xb0733dd2u, 0x7b2fee77u, 0x662adecfu, 0xad760d6au, 0x2be27fc4u, 0xe0beac61u, + 0x123e1c2fu, 0xd962cf8au, 0x5ff6bd24u, 0x94aa6e81u, 0x89af5e39u, 0x42f38d9cu, 0xc467ff32u, 0x0f3b2c97u, + 0xfe6d9e42u, 0x35314de7u, 0xb3a53f49u, 0x78f9ececu, 0x65fcdc54u, 0xaea00ff1u, 0x28347d5fu, 0xe368aefau, + 0x16441b82u, 0xdd18c827u, 0x5b8cba89u, 0x90d0692cu, 0x8dd55994u, 0x46898a31u, 0xc01df89fu, 0x0b412b3au, + 0xfa1799efu, 0x314b4a4au, 0xb7df38e4u, 0x7c83eb41u, 0x6186dbf9u, 0xaada085cu, 0x2c4e7af2u, 0xe712a957u, + 0x15921919u, 0xdececabcu, 0x585ab812u, 0x93066bb7u, 0x8e035b0fu, 0x455f88aau, 0xc3cbfa04u, 0x089729a1u, + 0xf9c19b74u, 0x329d48d1u, 0xb4093a7fu, 0x7f55e9dau, 0x6250d962u, 0xa90c0ac7u, 0x2f987869u, 0xe4c4abccu +}; + +static const unsigned lodepng_crc32_table6[256] = { + 0x00000000u, 0xa6770bb4u, 0x979f1129u, 0x31e81a9du, 0xf44f2413u, 0x52382fa7u, 0x63d0353au, 0xc5a73e8eu, + 0x33ef4e67u, 0x959845d3u, 0xa4705f4eu, 0x020754fau, 0xc7a06a74u, 0x61d761c0u, 0x503f7b5du, 0xf64870e9u, + 0x67de9cceu, 0xc1a9977au, 0xf0418de7u, 0x56368653u, 0x9391b8ddu, 0x35e6b369u, 0x040ea9f4u, 0xa279a240u, + 0x5431d2a9u, 0xf246d91du, 0xc3aec380u, 0x65d9c834u, 0xa07ef6bau, 0x0609fd0eu, 0x37e1e793u, 0x9196ec27u, + 0xcfbd399cu, 0x69ca3228u, 0x582228b5u, 0xfe552301u, 0x3bf21d8fu, 0x9d85163bu, 0xac6d0ca6u, 0x0a1a0712u, + 0xfc5277fbu, 0x5a257c4fu, 0x6bcd66d2u, 0xcdba6d66u, 0x081d53e8u, 0xae6a585cu, 0x9f8242c1u, 0x39f54975u, + 0xa863a552u, 0x0e14aee6u, 0x3ffcb47bu, 0x998bbfcfu, 0x5c2c8141u, 0xfa5b8af5u, 0xcbb39068u, 0x6dc49bdcu, + 0x9b8ceb35u, 0x3dfbe081u, 0x0c13fa1cu, 0xaa64f1a8u, 0x6fc3cf26u, 0xc9b4c492u, 0xf85cde0fu, 0x5e2bd5bbu, + 0x440b7579u, 0xe27c7ecdu, 0xd3946450u, 0x75e36fe4u, 0xb044516au, 0x16335adeu, 0x27db4043u, 0x81ac4bf7u, + 0x77e43b1eu, 0xd19330aau, 0xe07b2a37u, 0x460c2183u, 0x83ab1f0du, 0x25dc14b9u, 0x14340e24u, 0xb2430590u, + 0x23d5e9b7u, 0x85a2e203u, 0xb44af89eu, 0x123df32au, 0xd79acda4u, 0x71edc610u, 0x4005dc8du, 0xe672d739u, + 0x103aa7d0u, 0xb64dac64u, 0x87a5b6f9u, 0x21d2bd4du, 0xe47583c3u, 0x42028877u, 0x73ea92eau, 0xd59d995eu, + 0x8bb64ce5u, 0x2dc14751u, 0x1c295dccu, 0xba5e5678u, 0x7ff968f6u, 0xd98e6342u, 0xe86679dfu, 0x4e11726bu, + 0xb8590282u, 0x1e2e0936u, 0x2fc613abu, 0x89b1181fu, 0x4c162691u, 0xea612d25u, 0xdb8937b8u, 0x7dfe3c0cu, + 0xec68d02bu, 0x4a1fdb9fu, 0x7bf7c102u, 0xdd80cab6u, 0x1827f438u, 0xbe50ff8cu, 0x8fb8e511u, 0x29cfeea5u, + 0xdf879e4cu, 0x79f095f8u, 0x48188f65u, 0xee6f84d1u, 0x2bc8ba5fu, 0x8dbfb1ebu, 0xbc57ab76u, 0x1a20a0c2u, + 0x8816eaf2u, 0x2e61e146u, 0x1f89fbdbu, 0xb9fef06fu, 0x7c59cee1u, 0xda2ec555u, 0xebc6dfc8u, 0x4db1d47cu, + 0xbbf9a495u, 0x1d8eaf21u, 0x2c66b5bcu, 0x8a11be08u, 0x4fb68086u, 0xe9c18b32u, 0xd82991afu, 0x7e5e9a1bu, + 0xefc8763cu, 0x49bf7d88u, 0x78576715u, 0xde206ca1u, 0x1b87522fu, 0xbdf0599bu, 0x8c184306u, 0x2a6f48b2u, + 0xdc27385bu, 0x7a5033efu, 0x4bb82972u, 0xedcf22c6u, 0x28681c48u, 0x8e1f17fcu, 0xbff70d61u, 0x198006d5u, + 0x47abd36eu, 0xe1dcd8dau, 0xd034c247u, 0x7643c9f3u, 0xb3e4f77du, 0x1593fcc9u, 0x247be654u, 0x820cede0u, + 0x74449d09u, 0xd23396bdu, 0xe3db8c20u, 0x45ac8794u, 0x800bb91au, 0x267cb2aeu, 0x1794a833u, 0xb1e3a387u, + 0x20754fa0u, 0x86024414u, 0xb7ea5e89u, 0x119d553du, 0xd43a6bb3u, 0x724d6007u, 0x43a57a9au, 0xe5d2712eu, + 0x139a01c7u, 0xb5ed0a73u, 0x840510eeu, 0x22721b5au, 0xe7d525d4u, 0x41a22e60u, 0x704a34fdu, 0xd63d3f49u, + 0xcc1d9f8bu, 0x6a6a943fu, 0x5b828ea2u, 0xfdf58516u, 0x3852bb98u, 0x9e25b02cu, 0xafcdaab1u, 0x09baa105u, + 0xfff2d1ecu, 0x5985da58u, 0x686dc0c5u, 0xce1acb71u, 0x0bbdf5ffu, 0xadcafe4bu, 0x9c22e4d6u, 0x3a55ef62u, + 0xabc30345u, 0x0db408f1u, 0x3c5c126cu, 0x9a2b19d8u, 0x5f8c2756u, 0xf9fb2ce2u, 0xc813367fu, 0x6e643dcbu, + 0x982c4d22u, 0x3e5b4696u, 0x0fb35c0bu, 0xa9c457bfu, 0x6c636931u, 0xca146285u, 0xfbfc7818u, 0x5d8b73acu, + 0x03a0a617u, 0xa5d7ada3u, 0x943fb73eu, 0x3248bc8au, 0xf7ef8204u, 0x519889b0u, 0x6070932du, 0xc6079899u, + 0x304fe870u, 0x9638e3c4u, 0xa7d0f959u, 0x01a7f2edu, 0xc400cc63u, 0x6277c7d7u, 0x539fdd4au, 0xf5e8d6feu, + 0x647e3ad9u, 0xc209316du, 0xf3e12bf0u, 0x55962044u, 0x90311ecau, 0x3646157eu, 0x07ae0fe3u, 0xa1d90457u, + 0x579174beu, 0xf1e67f0au, 0xc00e6597u, 0x66796e23u, 0xa3de50adu, 0x05a95b19u, 0x34414184u, 0x92364a30u +}; + +static const unsigned lodepng_crc32_table7[256] = { + 0x00000000u, 0xccaa009eu, 0x4225077du, 0x8e8f07e3u, 0x844a0efau, 0x48e00e64u, 0xc66f0987u, 0x0ac50919u, + 0xd3e51bb5u, 0x1f4f1b2bu, 0x91c01cc8u, 0x5d6a1c56u, 0x57af154fu, 0x9b0515d1u, 0x158a1232u, 0xd92012acu, + 0x7cbb312bu, 0xb01131b5u, 0x3e9e3656u, 0xf23436c8u, 0xf8f13fd1u, 0x345b3f4fu, 0xbad438acu, 0x767e3832u, + 0xaf5e2a9eu, 0x63f42a00u, 0xed7b2de3u, 0x21d12d7du, 0x2b142464u, 0xe7be24fau, 0x69312319u, 0xa59b2387u, + 0xf9766256u, 0x35dc62c8u, 0xbb53652bu, 0x77f965b5u, 0x7d3c6cacu, 0xb1966c32u, 0x3f196bd1u, 0xf3b36b4fu, + 0x2a9379e3u, 0xe639797du, 0x68b67e9eu, 0xa41c7e00u, 0xaed97719u, 0x62737787u, 0xecfc7064u, 0x205670fau, + 0x85cd537du, 0x496753e3u, 0xc7e85400u, 0x0b42549eu, 0x01875d87u, 0xcd2d5d19u, 0x43a25afau, 0x8f085a64u, + 0x562848c8u, 0x9a824856u, 0x140d4fb5u, 0xd8a74f2bu, 0xd2624632u, 0x1ec846acu, 0x9047414fu, 0x5ced41d1u, + 0x299dc2edu, 0xe537c273u, 0x6bb8c590u, 0xa712c50eu, 0xadd7cc17u, 0x617dcc89u, 0xeff2cb6au, 0x2358cbf4u, + 0xfa78d958u, 0x36d2d9c6u, 0xb85dde25u, 0x74f7debbu, 0x7e32d7a2u, 0xb298d73cu, 0x3c17d0dfu, 0xf0bdd041u, + 0x5526f3c6u, 0x998cf358u, 0x1703f4bbu, 0xdba9f425u, 0xd16cfd3cu, 0x1dc6fda2u, 0x9349fa41u, 0x5fe3fadfu, + 0x86c3e873u, 0x4a69e8edu, 0xc4e6ef0eu, 0x084cef90u, 0x0289e689u, 0xce23e617u, 0x40ace1f4u, 0x8c06e16au, + 0xd0eba0bbu, 0x1c41a025u, 0x92cea7c6u, 0x5e64a758u, 0x54a1ae41u, 0x980baedfu, 0x1684a93cu, 0xda2ea9a2u, + 0x030ebb0eu, 0xcfa4bb90u, 0x412bbc73u, 0x8d81bcedu, 0x8744b5f4u, 0x4beeb56au, 0xc561b289u, 0x09cbb217u, + 0xac509190u, 0x60fa910eu, 0xee7596edu, 0x22df9673u, 0x281a9f6au, 0xe4b09ff4u, 0x6a3f9817u, 0xa6959889u, + 0x7fb58a25u, 0xb31f8abbu, 0x3d908d58u, 0xf13a8dc6u, 0xfbff84dfu, 0x37558441u, 0xb9da83a2u, 0x7570833cu, + 0x533b85dau, 0x9f918544u, 0x111e82a7u, 0xddb48239u, 0xd7718b20u, 0x1bdb8bbeu, 0x95548c5du, 0x59fe8cc3u, + 0x80de9e6fu, 0x4c749ef1u, 0xc2fb9912u, 0x0e51998cu, 0x04949095u, 0xc83e900bu, 0x46b197e8u, 0x8a1b9776u, + 0x2f80b4f1u, 0xe32ab46fu, 0x6da5b38cu, 0xa10fb312u, 0xabcaba0bu, 0x6760ba95u, 0xe9efbd76u, 0x2545bde8u, + 0xfc65af44u, 0x30cfafdau, 0xbe40a839u, 0x72eaa8a7u, 0x782fa1beu, 0xb485a120u, 0x3a0aa6c3u, 0xf6a0a65du, + 0xaa4de78cu, 0x66e7e712u, 0xe868e0f1u, 0x24c2e06fu, 0x2e07e976u, 0xe2ade9e8u, 0x6c22ee0bu, 0xa088ee95u, + 0x79a8fc39u, 0xb502fca7u, 0x3b8dfb44u, 0xf727fbdau, 0xfde2f2c3u, 0x3148f25du, 0xbfc7f5beu, 0x736df520u, + 0xd6f6d6a7u, 0x1a5cd639u, 0x94d3d1dau, 0x5879d144u, 0x52bcd85du, 0x9e16d8c3u, 0x1099df20u, 0xdc33dfbeu, + 0x0513cd12u, 0xc9b9cd8cu, 0x4736ca6fu, 0x8b9ccaf1u, 0x8159c3e8u, 0x4df3c376u, 0xc37cc495u, 0x0fd6c40bu, + 0x7aa64737u, 0xb60c47a9u, 0x3883404au, 0xf42940d4u, 0xfeec49cdu, 0x32464953u, 0xbcc94eb0u, 0x70634e2eu, + 0xa9435c82u, 0x65e95c1cu, 0xeb665bffu, 0x27cc5b61u, 0x2d095278u, 0xe1a352e6u, 0x6f2c5505u, 0xa386559bu, + 0x061d761cu, 0xcab77682u, 0x44387161u, 0x889271ffu, 0x825778e6u, 0x4efd7878u, 0xc0727f9bu, 0x0cd87f05u, + 0xd5f86da9u, 0x19526d37u, 0x97dd6ad4u, 0x5b776a4au, 0x51b26353u, 0x9d1863cdu, 0x1397642eu, 0xdf3d64b0u, + 0x83d02561u, 0x4f7a25ffu, 0xc1f5221cu, 0x0d5f2282u, 0x079a2b9bu, 0xcb302b05u, 0x45bf2ce6u, 0x89152c78u, + 0x50353ed4u, 0x9c9f3e4au, 0x121039a9u, 0xdeba3937u, 0xd47f302eu, 0x18d530b0u, 0x965a3753u, 0x5af037cdu, + 0xff6b144au, 0x33c114d4u, 0xbd4e1337u, 0x71e413a9u, 0x7b211ab0u, 0xb78b1a2eu, 0x39041dcdu, 0xf5ae1d53u, + 0x2c8e0fffu, 0xe0240f61u, 0x6eab0882u, 0xa201081cu, 0xa8c40105u, 0x646e019bu, 0xeae10678u, 0x264b06e6u +}; + +/* Computes the cyclic redundancy check as used by PNG chunks*/ +unsigned lodepng_crc32(const unsigned char* data, size_t length) { + /*Using the Slicing by Eight algorithm*/ + unsigned r = 0xffffffffu; + while(length >= 8) { + r = lodepng_crc32_table7[(data[0] ^ (r & 0xffu))] ^ + lodepng_crc32_table6[(data[1] ^ ((r >> 8) & 0xffu))] ^ + lodepng_crc32_table5[(data[2] ^ ((r >> 16) & 0xffu))] ^ + lodepng_crc32_table4[(data[3] ^ ((r >> 24) & 0xffu))] ^ + lodepng_crc32_table3[data[4]] ^ + lodepng_crc32_table2[data[5]] ^ + lodepng_crc32_table1[data[6]] ^ + lodepng_crc32_table0[data[7]]; + data += 8; + length -= 8; + } + while(length--) { + r = lodepng_crc32_table0[(r ^ *data++) & 0xffu] ^ (r >> 8); + } + return r ^ 0xffffffffu; +} +#else /* LODEPNG_COMPILE_CRC */ +/*in this case, the function is only declared here, and must be defined externally +so that it will be linked in. + +Example implementation that uses a much smaller lookup table for memory constrained cases: + +unsigned lodepng_crc32(const unsigned char* data, size_t length) { + unsigned r = 0xffffffffu; + static const unsigned table[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + while(length--) { + r = table[(r ^ *data) & 0xf] ^ (r >> 4); + r = table[(r ^ (*data >> 4)) & 0xf] ^ (r >> 4); + data++; + } + return r ^ 0xffffffffu; +} +*/ +unsigned lodepng_crc32(const unsigned char* data, size_t length); +#endif /* LODEPNG_COMPILE_CRC */ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Reading and writing PNG color channel bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first, +so LodePNGBitWriter and LodePNGBitReader can't be used for those. */ + +static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) { + unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); + ++(*bitpointer); + return result; +} + +/* TODO: make this faster */ +static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { + unsigned result = 0; + size_t i; + for(i = 0 ; i < nbits; ++i) { + result <<= 1u; + result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); + } + return result; +} + +static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { + /*the current bit in bitstream may be 0 or 1 for this to work*/ + if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u)))); + else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u))); + ++(*bitpointer); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG chunks / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_chunk_length(const unsigned char* chunk) { + return lodepng_read32bitInt(chunk); +} + +void lodepng_chunk_type(char type[5], const unsigned char* chunk) { + unsigned i; + for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; + type[4] = 0; /*null termination char*/ +} + +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) { + if(lodepng_strlen(type) != 4) return 0; + return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); +} + +/* chunk type name must exist only out of alphabetic characters a-z or A-Z */ +static unsigned char lodepng_chunk_type_name_valid(const unsigned char* chunk) { + unsigned i; + for(i = 0; i != 4; ++i) { + char c = (char)chunk[4 + i]; + if(!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) { + return 0; /* not valid */ + } + } + return 1; /* valid */ +} + +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) { + return((chunk[4] & 32) != 0); +} + +unsigned char lodepng_chunk_private(const unsigned char* chunk) { + return((chunk[5] & 32) != 0); +} + +/* this is an error if it is reserved: the third character must be uppercase in the PNG standard, +lowercasing this character is reserved for possible future extension by the spec*/ +static unsigned char lodepng_chunk_reserved(const unsigned char* chunk) { + return((chunk[6] & 32) != 0); +} + +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) { + return((chunk[7] & 32) != 0); +} + +unsigned char* lodepng_chunk_data(unsigned char* chunk) { + return &chunk[8]; +} + +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) { + return &chunk[8]; +} + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk) { + unsigned length = lodepng_chunk_length(chunk); + unsigned crc = lodepng_read32bitInt(&chunk[length + 8]); + /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ + unsigned checksum = lodepng_crc32(&chunk[4], length + 4); + if(crc != checksum) return 1; + else return 0; +} + +void lodepng_chunk_generate_crc(unsigned char* chunk) { + unsigned length = lodepng_chunk_length(chunk); + unsigned crc = lodepng_crc32(&chunk[4], length + 4); + lodepng_set32bitInt(chunk + 8 + length, crc); +} + +unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) { + size_t available_size = (size_t)(end - chunk); + if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + size_t total_chunk_length; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + if(total_chunk_length > available_size) return end; /*outside of range*/ + return chunk + total_chunk_length; + } +} + +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) { + size_t available_size = (size_t)(end - chunk); + if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + size_t total_chunk_length; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + if(total_chunk_length > available_size) return end; /*outside of range*/ + return chunk + total_chunk_length; + } +} + +unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) { + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next(chunk, end); + } +} + +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) { + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next_const(chunk, end); + } +} + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) { + unsigned i; + size_t total_chunk_length, new_length; + unsigned char *chunk_start, *new_buffer; + + if(!lodepng_chunk_type_name_valid(chunk)) { + return 121; /* invalid chunk type name */ + } + if(lodepng_chunk_reserved(chunk)) { + return 122; /* invalid third lowercase character */ + } + + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77; + if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77; + + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outsize) = new_length; + chunk_start = &(*out)[new_length - total_chunk_length]; + + for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; + + return 0; +} + +/*Sets length and name and allocates the space for data and crc but does not +set data or crc yet. Returns the start of the chunk in chunk. The start of +the data is at chunk + 8. To finalize chunk, add the data, then use +lodepng_chunk_generate_crc */ +static unsigned lodepng_chunk_init(unsigned char** chunk, + ucvector* out, + size_t length, const char* type) { + size_t new_length = out->size; + if(lodepng_addofl(new_length, length, &new_length)) return 77; + if(lodepng_addofl(new_length, 12, &new_length)) return 77; + if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/ + *chunk = out->data + new_length - length - 12u; + + /*1: length*/ + lodepng_set32bitInt(*chunk, (unsigned)length); + + /*2: chunk name (4 letters)*/ + lodepng_memcpy(*chunk + 4, type, 4); + + return 0; +} + +/* like lodepng_chunk_create but with custom allocsize */ +static unsigned lodepng_chunk_createv(ucvector* out, + size_t length, const char* type, const unsigned char* data) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type)); + + /*3: the data*/ + lodepng_memcpy(chunk + 8, data, length); + + /*4: CRC (of the chunkname characters and the data)*/ + lodepng_chunk_generate_crc(chunk); + + return 0; +} + +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, + size_t length, const char* type, const unsigned char* data) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_chunk_createv(&v, length, type, data); + *out = v.data; + *outsize = v.size; + return error; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Color types, channels, bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*checks if the colortype is valid and the bitdepth bd is allowed for this colortype. +Return value is a LodePNG error code.*/ +static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) { + switch(colortype) { + case LCT_GREY: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; + case LCT_RGB: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_PALETTE: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; + case LCT_GREY_ALPHA: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_RGBA: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_MAX_OCTET_VALUE: return 31; /* invalid color type */ + default: return 31; /* invalid color type */ + } + return 0; /*allowed color type / bits combination*/ +} + +static unsigned getNumColorChannels(LodePNGColorType colortype) { + switch(colortype) { + case LCT_GREY: return 1; + case LCT_RGB: return 3; + case LCT_PALETTE: return 1; + case LCT_GREY_ALPHA: return 2; + case LCT_RGBA: return 4; + case LCT_MAX_OCTET_VALUE: return 0; /* invalid color type */ + default: return 0; /*invalid color type*/ + } +} + +static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) { + /*bits per pixel is amount of channels * bits per channel*/ + return getNumColorChannels(colortype) * bitdepth; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +void lodepng_color_mode_init(LodePNGColorMode* info) { + info->key_defined = 0; + info->key_r = info->key_g = info->key_b = 0; + info->colortype = LCT_RGBA; + info->bitdepth = 8; + info->palette = 0; + info->palettesize = 0; +} + +/*allocates palette memory if needed, and initializes all colors to black*/ +static void lodepng_color_mode_alloc_palette(LodePNGColorMode* info) { + size_t i; + /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/ + /*the palette must have room for up to 256 colors with 4 bytes each.*/ + if(!info->palette) info->palette = (unsigned char*)lodepng_malloc(1024); + if(!info->palette) return; /*alloc fail*/ + for(i = 0; i != 256; ++i) { + /*Initialize all unused colors with black, the value used for invalid palette indices. + This is an error according to the PNG spec, but common PNG decoders make it black instead. + That makes color conversion slightly faster due to no error handling needed.*/ + info->palette[i * 4 + 0] = 0; + info->palette[i * 4 + 1] = 0; + info->palette[i * 4 + 2] = 0; + info->palette[i * 4 + 3] = 255; + } +} + +void lodepng_color_mode_cleanup(LodePNGColorMode* info) { + lodepng_palette_clear(info); +} + +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) { + lodepng_color_mode_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGColorMode)); + if(source->palette) { + dest->palette = (unsigned char*)lodepng_malloc(1024); + if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ + lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4); + } + return 0; +} + +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) { + LodePNGColorMode result; + lodepng_color_mode_init(&result); + result.colortype = colortype; + result.bitdepth = bitdepth; + return result; +} + +static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) { + size_t i; + if(a->colortype != b->colortype) return 0; + if(a->bitdepth != b->bitdepth) return 0; + if(a->key_defined != b->key_defined) return 0; + if(a->key_defined) { + if(a->key_r != b->key_r) return 0; + if(a->key_g != b->key_g) return 0; + if(a->key_b != b->key_b) return 0; + } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) { + if(a->palette[i] != b->palette[i]) return 0; + } + return 1; +} + +void lodepng_palette_clear(LodePNGColorMode* info) { + if(info->palette) lodepng_free(info->palette); + info->palette = 0; + info->palettesize = 0; +} + +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + if(!info->palette) /*allocate palette if empty*/ { + lodepng_color_mode_alloc_palette(info); + if(!info->palette) return 83; /*alloc fail*/ + } + if(info->palettesize >= 256) { + return 108; /*too many palette values*/ + } + info->palette[4 * info->palettesize + 0] = r; + info->palette[4 * info->palettesize + 1] = g; + info->palette[4 * info->palettesize + 2] = b; + info->palette[4 * info->palettesize + 3] = a; + ++info->palettesize; + return 0; +} + +/*calculate bits per pixel out of colortype and bitdepth*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info) { + return lodepng_get_bpp_lct(info->colortype, info->bitdepth); +} + +unsigned lodepng_get_channels(const LodePNGColorMode* info) { + return getNumColorChannels(info->colortype); +} + +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) { + return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; +} + +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) { + return (info->colortype & 4) != 0; /*4 or 6*/ +} + +unsigned lodepng_is_palette_type(const LodePNGColorMode* info) { + return info->colortype == LCT_PALETTE; +} + +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) { + size_t i; + for(i = 0; i != info->palettesize; ++i) { + if(info->palette[i * 4 + 3] < 255) return 1; + } + return 0; +} + +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) { + return info->key_defined + || lodepng_is_alpha_type(info) + || lodepng_has_palette_alpha(info); +} + +static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = (size_t)w * (size_t)h; + return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; +} + +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { + return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); +} + + +#ifdef LODEPNG_COMPILE_PNG + +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, +and in addition has one extra byte per line: the filter byte. So this gives a larger +result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */ +static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) { + /* + 1 for the filter byte, and possibly plus padding bits per line. */ + /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */ + size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u; + return (size_t)h * line; +} + +#ifdef LODEPNG_COMPILE_DECODER +/*Safely checks whether size_t overflow can be caused due to amount of pixels. +This check is overcautious rather than precise. If this check indicates no overflow, +you can safely compute in a size_t (but not an unsigned): +-(size_t)w * (size_t)h * 8 +-amount of bytes in IDAT (including filter, padding and Adam7 bytes) +-amount of bytes in raw color model +Returns 1 if overflow possible, 0 if not. +*/ +static int lodepng_pixel_overflow(unsigned w, unsigned h, + const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) { + size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); + size_t numpixels, total; + size_t line; /* bytes per line in worst case */ + + if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; + if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ + + /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */ + if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1; + if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1; + + if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ + if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ + + return 0; /* no overflow */ +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static void LodePNGUnknownChunks_init(LodePNGInfo* info) { + unsigned i; + for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; + for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; +} + +static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) { + unsigned i; + for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); +} + +static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) { + unsigned i; + + LodePNGUnknownChunks_cleanup(dest); + + for(i = 0; i != 3; ++i) { + size_t j; + dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; + dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); + if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ + for(j = 0; j < src->unknown_chunks_size[i]; ++j) { + dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; + } + } + + return 0; +} + +/******************************************************************************/ + +static void LodePNGText_init(LodePNGInfo* info) { + info->text_num = 0; + info->text_keys = NULL; + info->text_strings = NULL; +} + +static void LodePNGText_cleanup(LodePNGInfo* info) { + size_t i; + for(i = 0; i != info->text_num; ++i) { + lodepng_free(info->text_keys[i]); + lodepng_free(info->text_strings[i]); + } + lodepng_free(info->text_keys); + lodepng_free(info->text_strings); +} + +static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + size_t i = 0; + dest->text_keys = NULL; + dest->text_strings = NULL; + dest->text_num = 0; + for(i = 0; i != source->text_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); + } + return 0; +} + +static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const char* str, size_t size) { + char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); + + if(new_keys) info->text_keys = new_keys; + if(new_strings) info->text_strings = new_strings; + + if(!new_keys || !new_strings) return 83; /*alloc fail*/ + + ++info->text_num; + info->text_keys[info->text_num - 1] = alloc_string(key); + info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); + if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ + + return 0; +} + +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) { + return lodepng_add_text_sized(info, key, str, lodepng_strlen(str)); +} + +void lodepng_clear_text(LodePNGInfo* info) { + LodePNGText_cleanup(info); + /*cleanup only deconstructs, need to init again to set appropriate pointers to NULL*/ + LodePNGText_init(info); +} + +/******************************************************************************/ + +static void LodePNGIText_init(LodePNGInfo* info) { + info->itext_num = 0; + info->itext_keys = NULL; + info->itext_langtags = NULL; + info->itext_transkeys = NULL; + info->itext_strings = NULL; +} + +static void LodePNGIText_cleanup(LodePNGInfo* info) { + size_t i; + for(i = 0; i != info->itext_num; ++i) { + lodepng_free(info->itext_keys[i]); + lodepng_free(info->itext_langtags[i]); + lodepng_free(info->itext_transkeys[i]); + lodepng_free(info->itext_strings[i]); + } + lodepng_free(info->itext_keys); + lodepng_free(info->itext_langtags); + lodepng_free(info->itext_transkeys); + lodepng_free(info->itext_strings); +} + +static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + size_t i = 0; + dest->itext_keys = NULL; + dest->itext_langtags = NULL; + dest->itext_transkeys = NULL; + dest->itext_strings = NULL; + dest->itext_num = 0; + for(i = 0; i != source->itext_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], + source->itext_transkeys[i], source->itext_strings[i])); + } + return 0; +} + +void lodepng_clear_itext(LodePNGInfo* info) { + LodePNGIText_cleanup(info); + /*cleanup only deconstructs, need to init again to set appropriate pointers to NULL*/ + LodePNGIText_init(info); +} + +static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str, size_t size) { + char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); + char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); + char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); + + if(new_keys) info->itext_keys = new_keys; + if(new_langtags) info->itext_langtags = new_langtags; + if(new_transkeys) info->itext_transkeys = new_transkeys; + if(new_strings) info->itext_strings = new_strings; + + if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/ + + ++info->itext_num; + + info->itext_keys[info->itext_num - 1] = alloc_string(key); + info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); + info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); + info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); + + return 0; +} + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str) { + return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str)); +} + +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { + if(info->iccp_defined) lodepng_clear_icc(info); + + if(profile_size == 0) return 123; /*invalid ICC profile size*/ + + info->iccp_name = alloc_string(name); + if(!info->iccp_name) return 83; /*alloc fail*/ + + info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); + if(!info->iccp_profile) { + lodepng_free(info->iccp_name); + return 83; /*alloc fail*/ + } + + lodepng_memcpy(info->iccp_profile, profile, profile_size); + info->iccp_profile_size = profile_size; + info->iccp_defined = 1; + + return 0; /*ok*/ +} + +static void lodepng_init_icc(LodePNGInfo* info) { + info->iccp_defined = 0; + info->iccp_name = NULL; + info->iccp_profile = NULL; + info->iccp_profile_size = 0; +} + +void lodepng_clear_icc(LodePNGInfo* info) { + lodepng_free(info->iccp_name); + lodepng_free(info->iccp_profile); + lodepng_init_icc(info); +} + +unsigned lodepng_set_exif(LodePNGInfo* info, const unsigned char* exif, unsigned exif_size) { + if(info->exif_defined) lodepng_clear_exif(info); + info->exif = (unsigned char*)lodepng_malloc(exif_size); + + if(!info->exif) return 83; /*alloc fail*/ + + lodepng_memcpy(info->exif, exif, exif_size); + info->exif_size = exif_size; + info->exif_defined = 1; + + return 0; /*ok*/ +} + +static void lodepng_init_exif(LodePNGInfo* info) { + info->exif_defined = 0; + info->exif = NULL; + info->exif_size = 0; +} + +void lodepng_clear_exif(LodePNGInfo* info) { + lodepng_free(info->exif); + lodepng_init_exif(info); +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +void lodepng_info_init(LodePNGInfo* info) { + lodepng_color_mode_init(&info->color); + info->interlace_method = 0; + info->compression_method = 0; + info->filter_method = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + info->background_defined = 0; + info->background_r = info->background_g = info->background_b = 0; + + LodePNGText_init(info); + LodePNGIText_init(info); + lodepng_init_icc(info); + lodepng_init_exif(info); + + info->time_defined = 0; + info->phys_defined = 0; + + info->gama_defined = 0; + info->chrm_defined = 0; + info->srgb_defined = 0; + info->cicp_defined = 0; + info->cicp_color_primaries = 0; + info->cicp_transfer_function = 0; + info->cicp_matrix_coefficients = 0; + info->cicp_video_full_range_flag = 0; + info->mdcv_defined = 0; + info->mdcv_red_x = 0; + info->mdcv_red_y = 0; + info->mdcv_green_x = 0; + info->mdcv_green_y = 0; + info->mdcv_blue_x = 0; + info->mdcv_blue_y = 0; + info->mdcv_white_x = 0; + info->mdcv_white_y = 0; + info->mdcv_max_luminance = 0; + info->mdcv_min_luminance = 0; + info->clli_defined = 0; + info->clli_max_cll = 0; + info->clli_max_fall = 0; + + info->sbit_defined = 0; + info->sbit_r = info->sbit_g = info->sbit_b = info->sbit_a = 0; + + LodePNGUnknownChunks_init(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +void lodepng_info_cleanup(LodePNGInfo* info) { + lodepng_color_mode_cleanup(&info->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_cleanup(info); + LodePNGIText_cleanup(info); + + lodepng_clear_icc(info); + lodepng_clear_exif(info); + + LodePNGUnknownChunks_cleanup(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + lodepng_info_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGInfo)); + + /*ensure to initialize all fields pointing to allocated data to NULL first*/ + lodepng_color_mode_init(&dest->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_init(dest); + LodePNGIText_init(dest); + lodepng_init_icc(dest); + lodepng_init_exif(dest); + LodePNGUnknownChunks_init(dest); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); + CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); + if(source->iccp_defined) { + CERROR_TRY_RETURN(lodepng_set_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); + } + if(source->exif_defined) { + CERROR_TRY_RETURN(lodepng_set_exif(dest, source->exif, source->exif_size)); + } + CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ +static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) { + unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ + /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ + unsigned p = index & m; + in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ + in = in << (bits * (m - p)); + if(p == 0) out[index * bits / 8u] = in; + else out[index * bits / 8u] |= in; +} + +typedef struct ColorTree ColorTree; + +/* +One node of a color tree +This is the data structure used to count the number of unique colors and to get a palette +index for a color. It's like an octree, but because the alpha channel is used too, each +node has 16 instead of 8 children. +*/ +struct ColorTree { + ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ + int index; /*the payload. Only has a meaningful value if this is in the last level*/ +}; + +static void color_tree_init(ColorTree* tree) { + lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children)); + tree->index = -1; +} + +static void color_tree_cleanup(ColorTree* tree) { + int i; + for(i = 0; i != 16; ++i) { + if(tree->children[i]) { + color_tree_cleanup(tree->children[i]); + lodepng_free(tree->children[i]); + } + } +} + +/*returns -1 if color not present, its index otherwise*/ +static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + int bit = 0; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) return -1; + else tree = tree->children[i]; + } + return tree ? tree->index : -1; +} + +#ifdef LODEPNG_COMPILE_ENCODER +static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + return color_tree_get(tree, r, g, b, a) >= 0; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*color is not allowed to already exist. +Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist") +Returns error code, or 0 if ok*/ +static unsigned color_tree_add(ColorTree* tree, + unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) { + int bit; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) { + tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); + if(!tree->children[i]) return 83; /*alloc fail*/ + color_tree_init(tree->children[i]); + } + tree = tree->children[i]; + } + tree->index = (int)index; + return 0; +} + +/*put a pixel, given its RGBA color, into image of any color type*/ +static unsigned rgba8ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + if(mode->colortype == LCT_GREY) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) out[i] = gray; + else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray; + else { + /*take the most significant bits of gray*/ + gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u); + addColorBits(out, i, mode->bitdepth, gray); + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + out[i * 3 + 0] = r; + out[i * 3 + 1] = g; + out[i * 3 + 2] = b; + } else { + out[i * 6 + 0] = out[i * 6 + 1] = r; + out[i * 6 + 2] = out[i * 6 + 3] = g; + out[i * 6 + 4] = out[i * 6 + 5] = b; + } + } else if(mode->colortype == LCT_PALETTE) { + int index = color_tree_get(tree, r, g, b, a); + if(index < 0) return 82; /*color not in palette*/ + if(mode->bitdepth == 8) out[i] = index; + else addColorBits(out, i, mode->bitdepth, (unsigned)index); + } else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) { + out[i * 2 + 0] = gray; + out[i * 2 + 1] = a; + } else if(mode->bitdepth == 16) { + out[i * 4 + 0] = out[i * 4 + 1] = gray; + out[i * 4 + 2] = out[i * 4 + 3] = a; + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + out[i * 4 + 0] = r; + out[i * 4 + 1] = g; + out[i * 4 + 2] = b; + out[i * 4 + 3] = a; + } else { + out[i * 8 + 0] = out[i * 8 + 1] = r; + out[i * 8 + 2] = out[i * 8 + 3] = g; + out[i * 8 + 4] = out[i * 8 + 5] = b; + out[i * 8 + 6] = out[i * 8 + 7] = a; + } + } + + return 0; /*no error*/ +} + +/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ +static void rgba16ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, + unsigned short r, unsigned short g, unsigned short b, unsigned short a) { + if(mode->colortype == LCT_GREY) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 2 + 0] = (gray >> 8) & 255; + out[i * 2 + 1] = gray & 255; + } else if(mode->colortype == LCT_RGB) { + out[i * 6 + 0] = (r >> 8) & 255; + out[i * 6 + 1] = r & 255; + out[i * 6 + 2] = (g >> 8) & 255; + out[i * 6 + 3] = g & 255; + out[i * 6 + 4] = (b >> 8) & 255; + out[i * 6 + 5] = b & 255; + } else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 4 + 0] = (gray >> 8) & 255; + out[i * 4 + 1] = gray & 255; + out[i * 4 + 2] = (a >> 8) & 255; + out[i * 4 + 3] = a & 255; + } else if(mode->colortype == LCT_RGBA) { + out[i * 8 + 0] = (r >> 8) & 255; + out[i * 8 + 1] = r & 255; + out[i * 8 + 2] = (g >> 8) & 255; + out[i * 8 + 3] = g & 255; + out[i * 8 + 4] = (b >> 8) & 255; + out[i * 8 + 5] = b & 255; + out[i * 8 + 6] = (a >> 8) & 255; + out[i * 8 + 7] = a & 255; + } +} + +/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ +static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, + unsigned char* b, unsigned char* a, + const unsigned char* in, size_t i, + const LodePNGColorMode* mode) { + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i]; + if(mode->key_defined && *r == mode->key_r) *a = 0; + else *a = 255; + } else if(mode->bitdepth == 16) { + *r = *g = *b = in[i * 2 + 0]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 255; + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = i * mode->bitdepth; + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + *r = *g = *b = (value * 255) / highest; + if(mode->key_defined && value == mode->key_r) *a = 0; + else *a = 255; + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; + if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; + else *a = 255; + } else { + *r = in[i * 6 + 0]; + *g = in[i * 6 + 2]; + *b = in[i * 6 + 4]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 255; + } + } else if(mode->colortype == LCT_PALETTE) { + unsigned index; + if(mode->bitdepth == 8) index = in[i]; + else { + size_t j = i * mode->bitdepth; + index = readBitsFromReversedStream(&j, in, mode->bitdepth); + } + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + *r = mode->palette[index * 4 + 0]; + *g = mode->palette[index * 4 + 1]; + *b = mode->palette[index * 4 + 2]; + *a = mode->palette[index * 4 + 3]; + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i * 2 + 0]; + *a = in[i * 2 + 1]; + } else { + *r = *g = *b = in[i * 4 + 0]; + *a = in[i * 4 + 2]; + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + *r = in[i * 4 + 0]; + *g = in[i * 4 + 1]; + *b = in[i * 4 + 2]; + *a = in[i * 4 + 3]; + } else { + *r = in[i * 8 + 0]; + *g = in[i * 8 + 2]; + *b = in[i * 8 + 4]; + *a = in[i * 8 + 6]; + } + } +} + +/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color +mode test cases, optimized to convert the colors much faster, when converting +to the common case of RGBA with 8 bit per channel. buffer must be RGBA with +enough memory.*/ +static void getPixelColorsRGBA8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char* LODEPNG_RESTRICT in, + const LodePNGColorMode* mode) { + unsigned num_channels = 4; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r) buffer[3] = 0; + } + } + } else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; + } + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; + } + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 3], 3); + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r && buffer[1]== mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0; + } + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + buffer[3] = mode->key_defined + && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; + } + } + } else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + buffer[3] = in[i * 2 + 1]; + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + buffer[3] = in[i * 4 + 2]; + } + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 4); + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + buffer[3] = in[i * 8 + 6]; + } + } + } +} + +/*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/ +static void getPixelColorsRGB8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char* LODEPNG_RESTRICT in, + const LodePNGColorMode* mode) { + const unsigned num_channels = 3; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + } + } else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + } + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + } + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 3); + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + } + } + } else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + } + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 4], 3); + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + } + } + } +} + +/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with +given color type, but the given color type must be 16-bit itself.*/ +static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, + const unsigned char* in, size_t i, const LodePNGColorMode* mode) { + if(mode->colortype == LCT_GREY) { + *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 65535; + } else if(mode->colortype == LCT_RGB) { + *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined + && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 65535; + } else if(mode->colortype == LCT_GREY_ALPHA) { + *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; + } else if(mode->colortype == LCT_RGBA) { + *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; + } +} + +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h) { + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) { + return 107; /* error: must provide palette if input mode is palette */ + } + + if(lodepng_color_mode_equal(mode_out, mode_in)) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + + if(mode_out->colortype == LCT_PALETTE) { + size_t palettesize = mode_out->palettesize; + const unsigned char* palette = mode_out->palette; + size_t palsize = (size_t)1u << mode_out->bitdepth; + /*if the user specified output palette but did not give the values, assume + they want the values of the input color type (assuming that one is palette). + Note that we never create a new palette ourselves.*/ + if(palettesize == 0) { + palettesize = mode_in->palettesize; + palette = mode_in->palette; + /*if the input was also palette with same bitdepth, then the color types are also + equal, so copy literally. This to preserve the exact indices that were in the PNG + even in case there are duplicate colors in the palette.*/ + if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + } + if(palettesize < palsize) palsize = palettesize; + color_tree_init(&tree); + for(i = 0; i != palsize; ++i) { + const unsigned char* p = &palette[i * 4]; + error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); + if(error) break; + } + } + + if(!error) { + if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) { + for(i = 0; i != numpixels; ++i) { + unsigned short r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + rgba16ToPixel(out, i, mode_out, r, g, b, a); + } + } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) { + getPixelColorsRGBA8(out, numpixels, in, mode_in); + } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) { + getPixelColorsRGB8(out, numpixels, in, mode_in); + } else { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); + if(error) break; + } + } + } + + if(mode_out->colortype == LCT_PALETTE) { + color_tree_cleanup(&tree); + } + + return error; +} + + +/* Converts a single rgb color without alpha from one type to another, color bits truncated to +their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow +function, do not use to process all pixels of an image. Alpha channel not supported on purpose: +this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the +specification it looks like bKGD should ignore the alpha values of the palette since it can use +any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ +unsigned lodepng_convert_rgb( + unsigned* r_out, unsigned* g_out, unsigned* b_out, + unsigned r_in, unsigned g_in, unsigned b_in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) { + unsigned r = 0, g = 0, b = 0; + unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ + unsigned shift = 16 - mode_out->bitdepth; + + if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) { + r = g = b = r_in * mul; + } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) { + r = r_in * mul; + g = g_in * mul; + b = b_in * mul; + } else if(mode_in->colortype == LCT_PALETTE) { + if(r_in >= mode_in->palettesize) return 82; + r = mode_in->palette[r_in * 4 + 0] * 257u; + g = mode_in->palette[r_in * 4 + 1] * 257u; + b = mode_in->palette[r_in * 4 + 2] * 257u; + } else { + return 31; + } + + /* now convert to output format */ + if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) { + *r_out = r >> shift ; + } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) { + *r_out = r >> shift ; + *g_out = g >> shift ; + *b_out = b >> shift ; + } else if(mode_out->colortype == LCT_PALETTE) { + unsigned i; + /* a 16-bit color cannot be in the palette */ + if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; + for(i = 0; i < mode_out->palettesize; i++) { + unsigned j = i * 4; + if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && + (b >> 8) == mode_out->palette[j + 2]) { + *r_out = i; + return 0; + } + } + return 82; + } else { + return 31; + } + + return 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER + +void lodepng_color_stats_init(LodePNGColorStats* stats) { + /*stats*/ + stats->colored = 0; + stats->key = 0; + stats->key_r = stats->key_g = stats->key_b = 0; + stats->alpha = 0; + stats->numcolors = 0; + stats->bits = 1; + stats->numpixels = 0; + /*settings*/ + stats->allow_palette = 1; + stats->allow_greyscale = 1; +} + +/*function used for debug purposes with C++*/ +/*void printColorStats(LodePNGColorStats* p) { + std::cout << "colored: " << (int)p->colored << ", "; + std::cout << "key: " << (int)p->key << ", "; + std::cout << "key_r: " << (int)p->key_r << ", "; + std::cout << "key_g: " << (int)p->key_g << ", "; + std::cout << "key_b: " << (int)p->key_b << ", "; + std::cout << "alpha: " << (int)p->alpha << ", "; + std::cout << "numcolors: " << (int)p->numcolors << ", "; + std::cout << "bits: " << (int)p->bits << std::endl; +}*/ + +/*Returns how many bits needed to represent given value (max 8 bit)*/ +static unsigned getValueRequiredBits(unsigned char value) { + if(value == 0 || value == 255) return 1; + /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ + if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; + return 8; +} + +/*stats must already have been inited. */ +unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, + const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* mode_in) { + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + /* mark things as done already if it would be impossible to have a more expensive case */ + unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; + unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; + unsigned numcolors_done = 0; + unsigned bpp = lodepng_get_bpp(mode_in); + unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0; + unsigned sixteen = 0; /* whether the input image is 16 bit */ + unsigned maxnumcolors = 257; + if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp)); + + stats->numpixels += numpixels; + + /*if palette not allowed, no need to compute numcolors*/ + if(!stats->allow_palette) numcolors_done = 1; + + color_tree_init(&tree); + + /*If the stats was already filled in from previous data, fill its palette in tree + and mark things as done already if we know they are the most expensive case already*/ + if(stats->alpha) alpha_done = 1; + if(stats->colored) colored_done = 1; + if(stats->bits == 16) numcolors_done = 1; + if(stats->bits >= bpp) bits_done = 1; + if(stats->numcolors >= maxnumcolors) numcolors_done = 1; + + if(!numcolors_done) { + for(i = 0; i < stats->numcolors; i++) { + const unsigned char* color = &stats->palette[i * 4]; + error = color_tree_add(&tree, color[0], color[1], color[2], color[3], (unsigned)i); + if(error) goto cleanup; + } + } + + /*Check if the 16-bit input is truly 16-bit*/ + if(mode_in->bitdepth == 16 && !sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || + (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ { + stats->bits = 16; + sixteen = 1; + bits_done = 1; + numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ + break; + } + } + } + + if(sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 65535 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } else if(a == 65535 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + } + } else /* < 16-bit */ { + unsigned char r = 0, g = 0, b = 0, a = 0; + unsigned char pr = 0, pg = 0, pb = 0, pa = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + + /*skip if color same as before, this speeds up large non-photographic + images with many same colors by avoiding 'color_tree_has' below */ + if(i != 0 && r == pr && g == pg && b == pb && a == pa) continue; + pr = r; + pg = g; + pb = b; + pa = a; + + if(!bits_done && stats->bits < 8) { + /*only r is checked, < 8 bits is only relevant for grayscale*/ + unsigned bits = getValueRequiredBits(r); + if(bits > stats->bits) stats->bits = bits; + } + bits_done = (stats->bits >= bpp); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 255 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } else if(a == 255 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + + if(!numcolors_done) { + if(!color_tree_has(&tree, r, g, b, a)) { + error = color_tree_add(&tree, r, g, b, a, stats->numcolors); + if(error) goto cleanup; + if(stats->numcolors < 256) { + unsigned char* p = stats->palette; + unsigned n = stats->numcolors; + p[n * 4 + 0] = r; + p[n * 4 + 1] = g; + p[n * 4 + 2] = b; + p[n * 4 + 3] = a; + } + ++stats->numcolors; + numcolors_done = stats->numcolors >= maxnumcolors; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + } + + /*make the stats's key always 16-bit for consistency - repeat each byte twice*/ + stats->key_r += (stats->key_r << 8); + stats->key_g += (stats->key_g << 8); + stats->key_b += (stats->key_b << 8); + } + +cleanup: + color_tree_cleanup(&tree); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit +(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for +all pixels of an image but only for a few additional values. */ +static unsigned lodepng_color_stats_add(LodePNGColorStats* stats, + unsigned r, unsigned g, unsigned b, unsigned a) { + unsigned error = 0; + unsigned char image[8]; + LodePNGColorMode mode; + lodepng_color_mode_init(&mode); + image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g; + image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a; + mode.bitdepth = 16; + mode.colortype = LCT_RGBA; + error = lodepng_compute_color_stats(stats, image, 1, 1, &mode); + lodepng_color_mode_cleanup(&mode); + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Computes a minimal PNG color model that can contain all colors as indicated by the stats. +The stats should be computed with lodepng_compute_color_stats. +mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant. +Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image, +e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ... +This is used if auto_convert is enabled (it is by default). +*/ +static unsigned auto_choose_color(LodePNGColorMode* mode_out, + const LodePNGColorMode* mode_in, + const LodePNGColorStats* stats) { + unsigned error = 0; + unsigned palettebits; + size_t i, n; + size_t numpixels = stats->numpixels; + unsigned palette_ok, gray_ok; + + unsigned alpha = stats->alpha; + unsigned key = stats->key; + unsigned bits = stats->bits; + + mode_out->key_defined = 0; + + if(key && numpixels <= 16) { + alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + key = 0; + if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + + gray_ok = !stats->colored; + if(!stats->allow_greyscale) gray_ok = 0; + if(!gray_ok && bits < 8) bits = 8; + + n = stats->numcolors; + palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); + palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/ + if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/ + if(!stats->allow_palette) palette_ok = 0; + + if(palette_ok) { + const unsigned char* p = stats->palette; + lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ + for(i = 0; i != stats->numcolors; ++i) { + error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); + if(error) break; + } + + mode_out->colortype = LCT_PALETTE; + mode_out->bitdepth = palettebits; + + if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize + && mode_in->bitdepth == mode_out->bitdepth) { + /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ + lodepng_color_mode_cleanup(mode_out); /*clears palette, keeps the above set colortype and bitdepth fields as-is*/ + lodepng_color_mode_copy(mode_out, mode_in); + } + } else /*8-bit or 16-bit per channel*/ { + mode_out->bitdepth = bits; + mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA) + : (gray_ok ? LCT_GREY : LCT_RGB); + if(key) { + unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ + mode_out->key_r = stats->key_r & mask; + mode_out->key_g = stats->key_g & mask; + mode_out->key_b = stats->key_b & mask; + mode_out->key_defined = 1; + } + } + + return error; +} + +#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ + +/*Paeth predictor, used by PNG filter type 4*/ +static unsigned char paethPredictor(unsigned char a, unsigned char b, unsigned char c) { + /* the subtractions of unsigned char cast it to a signed type. + With gcc, short is faster than int, with clang int is as fast (as of april 2023)*/ + short pa = (b - c) < 0 ? -(b - c) : (b - c); + short pb = (a - c) < 0 ? -(a - c) : (a - c); + /* writing it out like this compiles to something faster than introducing a temp variable*/ + short pc = (a + b - c - c) < 0 ? -(a + b - c - c) : (a + b - c - c); + /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ + if(pb < pa) { a = b; pa = pb; } + return (pc < pa) ? c : a; +} + +/*shared values used by multiple Adam7 related functions*/ + +static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ +static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ +static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ +static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ + +/* +Outputs various dimensions and positions in the image related to the Adam7 reduced images. +passw: output containing the width of the 7 passes +passh: output containing the height of the 7 passes +filter_passstart: output containing the index of the start and end of each + reduced image with filter bytes +padded_passstart output containing the index of the start and end of each + reduced image when without filter bytes but with padded scanlines +passstart: output containing the index of the start and end of each reduced + image without padding between scanlines, but still padding between the images +w, h: width and height of non-interlaced image +bpp: bits per pixel +"padded" is only relevant if bpp is less than 8 and a scanline or image does not + end at a full byte +*/ +static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], + size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) { + /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ + unsigned i; + + /*calculate width and height in pixels of each pass*/ + for(i = 0; i != 7; ++i) { + passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; + passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; + if(passw[i] == 0) passh[i] = 0; + if(passh[i] == 0) passw[i] = 0; + } + + filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; + for(i = 0; i != 7; ++i) { + /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ + filter_passstart[i + 1] = filter_passstart[i] + + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0); + /*bits padded if needed to fill full byte at end of each scanline*/ + padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u); + /*only padded at end of reduced image*/ + passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u; + } +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Decoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*read the information from the header and store it in the LodePNGInfo. return value is error*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, + const unsigned char* in, size_t insize) { + unsigned width, height; + LodePNGInfo* info = &state->info_png; + if(insize == 0 || in == 0) { + CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ + } + if(insize < 33) { + CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ + } + + /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ + /* TODO: remove this. One should use a new LodePNGState for new sessions */ + lodepng_info_cleanup(info); + lodepng_info_init(info); + + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 + || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { + CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ + } + if(lodepng_chunk_length(in + 8) != 13) { + CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ + } + if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { + CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ + } + + /*read the values given in the header*/ + width = lodepng_read32bitInt(&in[16]); + height = lodepng_read32bitInt(&in[20]); + /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/ + if(w) *w = width; + if(h) *h = height; + info->color.bitdepth = in[24]; + info->color.colortype = (LodePNGColorType)in[25]; + info->compression_method = in[26]; + info->filter_method = in[27]; + info->interlace_method = in[28]; + + /*errors returned only after the parsing so other values are still output*/ + + /*error: invalid image size*/ + if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93); + /*error: invalid colortype or bitdepth combination*/ + state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); + if(state->error) return state->error; + /*error: only compression method 0 is allowed in the specification*/ + if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); + /*error: only filter method 0 is allowed in the specification*/ + if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); + /*error: only interlace methods 0 and 1 exist in the specification*/ + if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); + + if(!state->decoder.ignore_crc) { + unsigned crc = lodepng_read32bitInt(&in[29]); + unsigned checksum = lodepng_crc32(&in[12], 17); + if(crc != checksum) { + CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ + } + } + + return state->error; +} + +static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, + size_t bytewidth, unsigned char filterType, size_t length) { + /* + For PNG filter method 0 + unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, + the filter works byte per byte (bytewidth = 1) + precon is the previous unfiltered scanline, recon the result, scanline the current one + the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead + recon and scanline MAY be the same memory address! precon must be disjoint. + */ + + size_t i; + switch(filterType) { + case 0: + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + break; + case 1: { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j]; + break; + } + case 2: + if(precon) { + for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; + } else { + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + } + break; + case 3: + if(precon) { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); + /* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds + too much code. Whether this speeds up anything depends on compiler and settings. */ + if(bytewidth >= 4) { + for(; i + 3 < length; i += 4, j += 4) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + recon[i + 2] = s2 + ((r2 + p2) >> 1u); + recon[i + 3] = s3 + ((r3 + p3) >> 1u); + } + } else if(bytewidth >= 3) { + for(; i + 2 < length; i += 3, j += 3) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + recon[i + 2] = s2 + ((r2 + p2) >> 1u); + } + } else if(bytewidth >= 2) { + for(; i + 1 < length; i += 2, j += 2) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + } + } + for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u); + } else { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u); + } + break; + case 4: + if(precon) { + /* Unroll independent paths of this predictor. Whether this speeds up + anything depends on compiler and settings. */ + if(bytewidth == 8) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; + unsigned char a6, b6 = 0, c6, d6 = 0, a7, b7 = 0, c7, d7 = 0; + for(i = 0; i + 7 < length; i += 8) { + c0 = b0; c1 = b1; c2 = b2; c3 = b3; + c4 = b4; c5 = b5; c6 = b6; c7 = b7; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; + b4 = precon[i + 4]; b5 = precon[i + 5]; b6 = precon[i + 6]; b7 = precon[i + 7]; + a0 = d0; a1 = d1; a2 = d2; a3 = d3; + a4 = d4; a5 = d5; a6 = d6; a7 = d7; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); + d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); + d6 = scanline[i + 6] + paethPredictor(a6, b6, c6); + d7 = scanline[i + 7] + paethPredictor(a7, b7, c7); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; + recon[i + 4] = d4; recon[i + 5] = d5; recon[i + 6] = d6; recon[i + 7] = d7; + } + } else if(bytewidth == 6) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; + for(i = 0; i + 5 < length; i += 6) { + c0 = b0; c1 = b1; c2 = b2; + c3 = b3; c4 = b4; c5 = b5; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; + b3 = precon[i + 3]; b4 = precon[i + 4]; b5 = precon[i + 5]; + a0 = d0; a1 = d1; a2 = d2; + a3 = d3; a4 = d4; a5 = d5; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); + d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; + recon[i + 3] = d3; recon[i + 4] = d4; recon[i + 5] = d5; + } + } else if(bytewidth == 4) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + for(i = 0; i + 3 < length; i += 4) { + c0 = b0; c1 = b1; c2 = b2; c3 = b3; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; + a0 = d0; a1 = d1; a2 = d2; a3 = d3; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; + } + } else if(bytewidth == 3) { + unsigned char a0, b0 = 0, c0, d0 = 0; + unsigned char a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0; + for(i = 0; i + 2 < length; i += 3) { + c0 = b0; c1 = b1; c2 = b2; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; + a0 = d0; a1 = d1; a2 = d2; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; + } + } else if(bytewidth == 2) { + unsigned char a0, b0 = 0, c0, d0 = 0; + unsigned char a1, b1 = 0, c1, d1 = 0; + for(i = 0; i + 1 < length; i += 2) { + c0 = b0; c1 = b1; + b0 = precon[i + 0]; + b1 = precon[i + 1]; + a0 = d0; a1 = d1; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + recon[i + 0] = d0; + recon[i + 1] = d1; + } + } else if(bytewidth == 1) { + unsigned char a, b = 0, c, d = 0; + for(i = 0; i != length; ++i) { + c = b; + b = precon[i]; + a = d; + d = scanline[i] + paethPredictor(a, b, c); + recon[i] = d; + } + } else { + /* Normally not a possible case, but this would handle it correctly */ + for(i = 0; i != bytewidth; ++i) { + recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ + } + } + /* finish any remaining bytes */ + for(; i != length; ++i) { + recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); + } + } else { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) { + recon[i] = scanline[i]; + } + for(i = bytewidth; i != length; ++i, ++j) { + /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ + recon[i] = (scanline[i] + recon[j]); + } + } + break; + default: return 36; /*error: invalid filter type given*/ + } + return 0; +} + +static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + /* + For PNG filter method 0 + this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) + out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline + w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel + in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) + */ + + unsigned y; + unsigned char* prevline = 0; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + for(y = 0; y < h; ++y) { + size_t outindex = linebytes * y; + size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + unsigned char filterType = in[inindex]; + + CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); + + prevline = &out[outindex]; + } + + return 0; +} + +/* +in: Adam7 interlaced image, with no padding bits between scanlines, but between + reduced images so that each reduced image starts at a byte. +out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h +bpp: bits per pixel +out has the following size in bits: w * h * bpp. +in is possibly bigger due to padding bits between reduced images. +out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation +(because that's likely a little bit faster) +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; + size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w + + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp; + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +static void removePaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) { + /* + After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need + to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers + for the Adam7 code, the color convert code and the output to the user. + in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must + have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits + also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 + only useful if (ilinebits - olinebits) is a value in the range 1..7 + */ + unsigned y; + size_t diff = ilinebits - olinebits; + size_t ibp = 0, obp = 0; /*input and output bit pointers*/ + for(y = 0; y < h; ++y) { + size_t x; + for(x = 0; x < olinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + ibp += diff; + } +} + +/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from +the IDAT chunks (with filter index bytes and possible padding bits) +return value is error*/ +static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, + unsigned w, unsigned h, const LodePNGInfo* info_png) { + /* + This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. + Steps: + *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8) + *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace + NOTE: the in buffer will be overwritten with intermediate data! + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + if(bpp == 0) return 31; /*error: invalid colortype*/ + + if(info_png->interlace_method == 0) { + if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { + CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); + removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h); + } + /*we can immediately filter into the out buffer, no other steps needed*/ + else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); + } else /*interlace_method is 1 (Adam7)*/ { + unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + for(i = 0; i != 7; ++i) { + CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); + /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, + move bytes instead of bits or move not at all*/ + if(bpp < 8) { + /*remove padding bits in scanlines; after this there still may be padding + bits between the different reduced images: each reduced image still starts nicely at a byte*/ + removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, + ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]); + } + } + + Adam7_deinterlace(out, in, w, h, bpp); + } + + return 0; +} + +static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { + unsigned pos = 0, i; + color->palettesize = chunkLength / 3u; + if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/ + lodepng_color_mode_alloc_palette(color); + if(!color->palette && color->palettesize) { + color->palettesize = 0; + return 83; /*alloc fail*/ + } + + for(i = 0; i != color->palettesize; ++i) { + color->palette[4 * i + 0] = data[pos++]; /*R*/ + color->palette[4 * i + 1] = data[pos++]; /*G*/ + color->palette[4 * i + 2] = data[pos++]; /*B*/ + color->palette[4 * i + 3] = 255; /*alpha*/ + } + + return 0; /* OK */ +} + +static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { + unsigned i; + if(color->colortype == LCT_PALETTE) { + /*error: more alpha values given than there are palette entries*/ + if(chunkLength > color->palettesize) return 39; + + for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; + } else if(color->colortype == LCT_GREY) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 30; + + color->key_defined = 1; + color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; + } else if(color->colortype == LCT_RGB) { + /*error: this chunk must be 6 bytes for RGB image*/ + if(chunkLength != 6) return 41; + + color->key_defined = 1; + color->key_r = 256u * data[0] + data[1]; + color->key_g = 256u * data[2] + data[3]; + color->key_b = 256u * data[4] + data[5]; + } + else return 42; /*error: tRNS chunk not allowed for other color models*/ + + return 0; /* OK */ +} + + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*background color chunk (bKGD)*/ +static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(info->color.colortype == LCT_PALETTE) { + /*error: this chunk must be 1 byte for indexed color image*/ + if(chunkLength != 1) return 43; + + /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ + if(data[0] >= info->color.palettesize) return 103; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = data[0]; + } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 44; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + /*error: this chunk must be 6 bytes for grayscale image*/ + if(chunkLength != 6) return 45; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = 256u * data[0] + data[1]; + info->background_g = 256u * data[2] + data[3]; + info->background_b = 256u * data[4] + data[5]; + } + + return 0; /* OK */ +} + +/*text chunk (tEXt)*/ +static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + char *key = 0, *str = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + unsigned length, string2_begin; + + length = 0; + while(length < chunkLength && data[length] != 0) ++length; + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + string2_begin = length + 1; /*skip keyword null terminator*/ + + length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); + str = (char*)lodepng_malloc(length + 1); + if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(str, data + string2_begin, length); + str[length] = 0; + + error = lodepng_add_text(info, key, str); + + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*compressed text chunk (zTXt)*/ +static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + char *key = 0; + unsigned char* str = 0; + size_t size = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[string2_begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(error) break; + error = lodepng_add_text_sized(info, key, (char*)str, size); + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*international text chunk (iTXt)*/ +static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + unsigned i; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, begin, compressed; + char *key = 0, *langtag = 0, *transkey = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + /*Quick check if the chunk length isn't too small. Even without check + it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ + if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ + + /*read the key*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + /*read the compression method*/ + compressed = data[length + 1]; + if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty for the next 3 texts*/ + + /*read the langtag*/ + begin = length + 3; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + langtag = (char*)lodepng_malloc(length + 1); + if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(langtag, data + begin, length); + langtag[length] = 0; + + /*read the transkey*/ + begin += length + 1; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + transkey = (char*)lodepng_malloc(length + 1); + if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(transkey, data + begin, length); + transkey[length] = 0; + + /*read the actual text*/ + begin += length + 1; + + length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; + + if(compressed) { + unsigned char* str = 0; + size_t size = 0; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size); + lodepng_free(str); + } else { + error = lodepng_add_itext_sized(info, key, langtag, transkey, (const char*)(data + begin), length); + } + + break; + } + + lodepng_free(key); + lodepng_free(langtag); + lodepng_free(transkey); + + return error; +} + +static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ + + info->time_defined = 1; + info->time.year = 256u * data[0] + data[1]; + info->time.month = data[2]; + info->time.day = data[3]; + info->time.hour = data[4]; + info->time.minute = data[5]; + info->time.second = data[6]; + + return 0; /* OK */ +} + +static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ + + info->phys_defined = 1; + info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + info->phys_unit = data[8]; + + return 0; /* OK */ +} + +static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ + + info->gama_defined = 1; + info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + + return 0; /* OK */ +} + +static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ + + info->chrm_defined = 1; + info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; + info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; + info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; + info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; + info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; + info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; + info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; + info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; + + return 0; /* OK */ +} + +static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ + + info->srgb_defined = 1; + info->srgb_intent = data[0]; + + return 0; /* OK */ +} + +static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + unsigned i; + size_t size = 0; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + + if(info->iccp_defined) lodepng_clear_icc(info); + + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ + if(length < 1 || length > 79) return 89; /*keyword too short or long*/ + + info->iccp_name = (char*)lodepng_malloc(length + 1); + if(!info->iccp_name) return 83; /*alloc fail*/ + + info->iccp_name[length] = 0; + for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; + + if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_icc_size; + error = zlib_decompress(&info->iccp_profile, &size, 0, + &data[string2_begin], + length, &zlibsettings); + /*error: ICC profile larger than decoder->max_icc_size*/ + if(error && size > zlibsettings.max_output_size) error = 113; + info->iccp_profile_size = (unsigned)size; + if(!error && !info->iccp_profile_size) error = 123; /*invalid ICC profile size*/ + + if(!error) info->iccp_defined = 1; + return error; +} + +static unsigned readChunk_cICP(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 4) return 117; /*invalid cICP chunk size*/ + + info->cicp_defined = 1; + /* No error checking for value ranges is done here, that is up to a CICP + handling library, not the PNG decoding. Just pass on the metadata. */ + info->cicp_color_primaries = data[0]; + info->cicp_transfer_function = data[1]; + info->cicp_matrix_coefficients = data[2]; + info->cicp_video_full_range_flag = data[3]; + + return 0; /* OK */ +} + +static unsigned readChunk_mDCV(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 24) return 119; /*invalid mDCV chunk size*/ + + info->mdcv_defined = 1; + info->mdcv_red_x = 256u * data[0] + data[1]; + info->mdcv_red_y = 256u * data[2] + data[3]; + info->mdcv_green_x = 256u * data[4] + data[5]; + info->mdcv_green_y = 256u * data[6] + data[7]; + info->mdcv_blue_x = 256u * data[8] + data[9]; + info->mdcv_blue_y = 256u * data[10] + data[11]; + info->mdcv_white_x = 256u * data[12] + data[13]; + info->mdcv_white_y = 256u * data[14] + data[15]; + info->mdcv_max_luminance = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; + info->mdcv_min_luminance = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; + + return 0; /* OK */ +} + +static unsigned readChunk_cLLI(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 8) return 120; /*invalid cLLI chunk size*/ + + info->clli_defined = 1; + info->clli_max_cll = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->clli_max_fall = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + + return 0; /* OK */ +} + +static unsigned readChunk_eXIf(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + return lodepng_set_exif(info, data, (unsigned)chunkLength); +} + +/*significant bits chunk (sBIT)*/ +static unsigned readChunk_sBIT(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; + if(info->color.colortype == LCT_GREY) { + /*error: this chunk must be 1 bytes for grayscale image*/ + if(chunkLength != 1) return 114; + if(data[0] == 0 || data[0] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { + /*error: this chunk must be 3 bytes for RGB and palette image*/ + if(chunkLength != 3) return 114; + if(data[0] == 0 || data[1] == 0 || data[2] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = data[0]; + info->sbit_g = data[1]; + info->sbit_b = data[2]; + } else if(info->color.colortype == LCT_GREY_ALPHA) { + /*error: this chunk must be 2 byte for grayscale with alpha image*/ + if(chunkLength != 2) return 114; + if(data[0] == 0 || data[1] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ + info->sbit_a = data[1]; + } else if(info->color.colortype == LCT_RGBA) { + /*error: this chunk must be 4 bytes for grayscale image*/ + if(chunkLength != 4) return 114; + if(data[0] == 0 || data[1] == 0 || data[2] == 0 || data[3] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth || data[3] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = data[0]; + info->sbit_g = data[1]; + info->sbit_b = data[2]; + info->sbit_a = data[3]; + } + + return 0; /* OK */ +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize) { + const unsigned char* chunk = in + pos; + unsigned chunkLength; + const unsigned char* data; + unsigned unhandled = 0; + unsigned error = 0; + + if(pos + 4 > insize) return 30; + chunkLength = lodepng_chunk_length(chunk); + if(chunkLength > 2147483647) return 63; + data = lodepng_chunk_data_const(chunk); + if(chunkLength + 12 > insize - pos) return 30; + + if(lodepng_chunk_type_equals(chunk, "PLTE")) { + error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + error = readChunk_tRNS(&state->info_png.color, data, chunkLength); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + error = readChunk_bKGD(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + error = readChunk_tEXt(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tIME")) { + error = readChunk_tIME(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + error = readChunk_pHYs(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + error = readChunk_gAMA(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + error = readChunk_cHRM(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + error = readChunk_sRGB(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "cICP")) { + error = readChunk_cICP(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "mDCV")) { + error = readChunk_mDCV(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "cLLI")) { + error = readChunk_cLLI(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "eXIf")) { + error = readChunk_eXIf(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { + error = readChunk_sBIT(&state->info_png, data, chunkLength); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else { + /* unhandled chunk is ok (is not an error) */ + unhandled = 1; + } + + if(!error && !unhandled && !state->decoder.ignore_crc) { + if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ + } + + return error; +} + +/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ +static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) { + unsigned char IEND = 0; + const unsigned char* chunk; /*points to beginning of next chunk*/ + unsigned char* idat; /*the data from idat chunks, zlib compressed*/ + size_t idatsize = 0; + unsigned char* scanlines = 0; + size_t scanlines_size = 0, expected_size = 0; + size_t outsize = 0; + + /*for unknown chunk order*/ + unsigned unknown = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + + state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ + if(state->error) return; + + if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { + CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ + } + + /*the input filesize is a safe upper bound for the sum of idat chunks size*/ + idat = (unsigned char*)lodepng_malloc(insize); + if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ + + chunk = &in[33]; /*first byte of the first chunk after the header*/ + + /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. + IDAT data is put at the start of the in buffer*/ + while(!IEND && !state->error) { + unsigned chunkLength; + const unsigned char* data; /*the data in the chunk*/ + size_t pos = (size_t)(chunk - in); + + /*error: next chunk out of bounds of the in buffer*/ + if(chunk < in || pos + 12 > insize) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 30); + } + + /*length of the data of the chunk, excluding the 12 bytes for length, chunk type and CRC*/ + chunkLength = lodepng_chunk_length(chunk); + /*error: chunk length larger than the max PNG chunk size*/ + if(chunkLength > 2147483647) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 63); + } + + if(pos + (size_t)chunkLength + 12 > insize || pos + (size_t)chunkLength + 12 < pos) { + CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk (or int overflow)*/ + } + + data = lodepng_chunk_data_const(chunk); + + unknown = 0; + + /*IDAT chunk, containing compressed image data*/ + if(lodepng_chunk_type_equals(chunk, "IDAT")) { + size_t newsize; + if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); + if(newsize > insize) CERROR_BREAK(state->error, 95); + lodepng_memcpy(idat + idatsize, data, chunkLength); + idatsize += chunkLength; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 3; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else if(lodepng_chunk_type_equals(chunk, "IEND")) { + /*IEND chunk*/ + IEND = 1; + } else if(lodepng_chunk_type_equals(chunk, "PLTE")) { + /*palette chunk (PLTE)*/ + state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 2; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled + in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that + affects the alpha channel of pixels. */ + state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*background color chunk (bKGD)*/ + } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + state->error = readChunk_bKGD(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + /*text chunk (tEXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_tEXt(&state->info_png, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + /*compressed text chunk (zTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + /*international text chunk (iTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "tIME")) { + state->error = readChunk_tIME(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + state->error = readChunk_pHYs(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + state->error = readChunk_gAMA(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + state->error = readChunk_cHRM(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + state->error = readChunk_sRGB(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "cICP")) { + state->error = readChunk_cICP(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "mDCV")) { + state->error = readChunk_mDCV(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "cLLI")) { + state->error = readChunk_cLLI(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "eXIf")) { + state->error = readChunk_eXIf(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { + state->error = readChunk_sBIT(&state->info_png, data, chunkLength); + if(state->error) break; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { + if(!lodepng_chunk_type_name_valid(chunk)) { + CERROR_BREAK(state->error, 121); /* invalid chunk type name */ + } + if(lodepng_chunk_reserved(chunk)) { + CERROR_BREAK(state->error, 122); /* invalid third lowercase character */ + } + + /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ + if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) { + CERROR_BREAK(state->error, 69); + } + + unknown = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->decoder.remember_unknown_chunks) { + state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], + &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + + if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ { + if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ + } + + if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); + } + + if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { + state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ + } + + if(!state->error) { + /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. + If the decompressed size does not match the prediction, the image must be corrupt.*/ + if(state->info_png.interlace_method == 0) { + unsigned bpp = lodepng_get_bpp(&state->info_png.color); + expected_size = lodepng_get_raw_size_idat(*w, *h, bpp); + } else { + unsigned bpp = lodepng_get_bpp(&state->info_png.color); + /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/ + expected_size = 0; + expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp); + if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp); + if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp); + if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp); + } + + state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, &state->decoder.zlibsettings); + } + if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/ + lodepng_free(idat); + + if(!state->error) { + outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!*out) state->error = 83; /*alloc fail*/ + } + if(!state->error) { + lodepng_memset(*out, 0, outsize); + state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png); + } + lodepng_free(scanlines); +} + +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) { + *out = 0; + decodeGeneric(out, w, h, state, in, insize); + if(state->error) return state->error; + if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) { + /*same color type, no copying or converting of data needed*/ + /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype + the raw image has to the end user*/ + if(!state->decoder.color_convert) { + state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); + if(state->error) return state->error; + } + } else { /*color conversion needed*/ + unsigned char* data = *out; + size_t outsize; + + /*TODO: check if this works according to the statement in the documentation: "The converter can convert + from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/ + if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) + && !(state->info_raw.bitdepth == 8)) { + return 56; /*unsupported color mode conversion*/ + } + + outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!(*out)) { + state->error = 83; /*alloc fail*/ + } + else state->error = lodepng_convert(*out, data, &state->info_raw, + &state->info_png.color, *w, *h); + lodepng_free(data); + } + return state->error; +} + +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) { + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*disable reading things that this function doesn't output*/ + state.decoder.read_text_chunks = 0; + state.decoder.remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + error = lodepng_decode(out, w, h, &state, in, insize); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); +} + +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer = 0; + size_t buffersize; + unsigned error; + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + error = lodepng_load_file(&buffer, &buffersize, filename); + if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { + return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); +} + +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { + return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) { + settings->color_convert = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->read_text_chunks = 1; + settings->remember_unknown_chunks = 0; + settings->max_text_size = 16777216; + settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + settings->ignore_crc = 0; + settings->ignore_critical = 0; + settings->ignore_end = 0; + lodepng_decompress_settings_init(&settings->zlibsettings); +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) + +void lodepng_state_init(LodePNGState* state) { +#ifdef LODEPNG_COMPILE_DECODER + lodepng_decoder_settings_init(&state->decoder); +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + lodepng_encoder_settings_init(&state->encoder); +#endif /*LODEPNG_COMPILE_ENCODER*/ + lodepng_color_mode_init(&state->info_raw); + lodepng_info_init(&state->info_png); + state->error = 1; +} + +void lodepng_state_cleanup(LodePNGState* state) { + lodepng_color_mode_cleanup(&state->info_raw); + lodepng_info_cleanup(&state->info_png); +} + +unsigned lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) { + lodepng_state_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->info_raw); + lodepng_info_init(&dest->info_png); + dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); + if(dest->error) return dest->error; + dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); + return dest->error; +} + +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Encoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +static unsigned writeSignature(ucvector* out) { + size_t pos = out->size; + const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10}; + /*8 bytes PNG signature, aka the magic bytes*/ + if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/ + lodepng_memcpy(out->data + pos, signature, 8); + return 0; +} + +static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) { + unsigned char *chunk, *data; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR")); + data = chunk + 8; + + lodepng_set32bitInt(data + 0, w); /*width*/ + lodepng_set32bitInt(data + 4, h); /*height*/ + data[8] = (unsigned char)bitdepth; /*bit depth*/ + data[9] = (unsigned char)colortype; /*color type*/ + data[10] = 0; /*compression method*/ + data[11] = 0; /*filter method*/ + data[12] = interlace_method; /*interlace method*/ + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +/* only adds the chunk if needed (there is a key or palette with alpha) */ +static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) { + unsigned char* chunk; + size_t i, j = 8; + + if(info->palettesize == 0 || info->palettesize > 256) { + return 68; /*invalid palette size, it is only allowed to be 1-256*/ + } + + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE")); + + for(i = 0; i != info->palettesize; ++i) { + /*add all channels except alpha channel*/ + chunk[j++] = info->palette[i * 4 + 0]; + chunk[j++] = info->palette[i * 4 + 1]; + chunk[j++] = info->palette[i * 4 + 2]; + } + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) { + unsigned char* chunk = 0; + + if(info->colortype == LCT_PALETTE) { + size_t i, amount = info->palettesize; + /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ + for(i = info->palettesize; i != 0; --i) { + if(info->palette[4 * (i - 1) + 3] != 255) break; + --amount; + } + if(amount) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS")); + /*add the alpha channel values from the palette*/ + for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3]; + } + } else if(info->colortype == LCT_GREY) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + } + } else if(info->colortype == LCT_RGB) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + chunk[10] = (unsigned char)(info->key_g >> 8); + chunk[11] = (unsigned char)(info->key_g & 255); + chunk[12] = (unsigned char)(info->key_b >> 8); + chunk[13] = (unsigned char)(info->key_b & 255); + } + } + + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, + const LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* zlib = 0; + size_t pos = 0; + size_t zlibsize = 0; + /* max chunk length allowed by the specification is 2147483647 bytes */ + const size_t max_chunk_length = 2147483647u; + + error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings); + while(!error) { + if(zlibsize - pos > max_chunk_length) { + error = lodepng_chunk_createv(out, max_chunk_length, "IDAT", zlib + pos); + pos += max_chunk_length; + } else { + error = lodepng_chunk_createv(out, zlibsize - pos, "IDAT", zlib + pos); + break; + } + } + lodepng_free(zlib); + return error; +} + +static unsigned addChunk_IEND(ucvector* out) { + return lodepng_chunk_createv(out, 0, "IEND", 0); +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) { + unsigned char* chunk = 0; + size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring); + size_t size = keysize + 1 + textsize; + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt")); + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + lodepng_memcpy(chunk + 9 + keysize, textstring, textsize); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, + const LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword); + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char*)textstring, textsize, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "zTXt"); + } + if(!error) { + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_iTXt(ucvector* out, unsigned compress, const char* keyword, const char* langtag, + const char* transkey, const char* textstring, const LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + if(compress) { + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char*)textstring, textsize, zlibsettings); + } + if(!error) { + size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize); + error = lodepng_chunk_init(&chunk, out, size, "iTXt"); + } + if(!error) { + size_t pos = 8; + lodepng_memcpy(chunk + pos, keyword, keysize); + pos += keysize; + chunk[pos++] = 0; /*null termination char*/ + chunk[pos++] = (compress ? 1 : 0); /*compression flag*/ + chunk[pos++] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + pos, langtag, langsize); + pos += langsize; + chunk[pos++] = 0; /*null termination char*/ + lodepng_memcpy(chunk + pos, transkey, transsize); + pos += transsize; + chunk[pos++] = 0; /*null termination char*/ + if(compress) { + lodepng_memcpy(chunk + pos, compressed, compressedsize); + } else { + lodepng_memcpy(chunk + pos, textstring, textsize); + } + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk = 0; + if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + chunk[10] = (unsigned char)(info->background_g >> 8); + chunk[11] = (unsigned char)(info->background_g & 255); + chunk[12] = (unsigned char)(info->background_b >> 8); + chunk[13] = (unsigned char)(info->background_b & 255); + } else if(info->color.colortype == LCT_PALETTE) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD")); + chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/ + } + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME")); + chunk[8] = (unsigned char)(time->year >> 8); + chunk[9] = (unsigned char)(time->year & 255); + chunk[10] = (unsigned char)time->month; + chunk[11] = (unsigned char)time->day; + chunk[12] = (unsigned char)time->hour; + chunk[13] = (unsigned char)time->minute; + chunk[14] = (unsigned char)time->second; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs")); + lodepng_set32bitInt(chunk + 8, info->phys_x); + lodepng_set32bitInt(chunk + 12, info->phys_y); + chunk[16] = info->phys_unit; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA")); + lodepng_set32bitInt(chunk + 8, info->gama_gamma); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM")); + lodepng_set32bitInt(chunk + 8, info->chrm_white_x); + lodepng_set32bitInt(chunk + 12, info->chrm_white_y); + lodepng_set32bitInt(chunk + 16, info->chrm_red_x); + lodepng_set32bitInt(chunk + 20, info->chrm_red_y); + lodepng_set32bitInt(chunk + 24, info->chrm_green_x); + lodepng_set32bitInt(chunk + 28, info->chrm_green_y); + lodepng_set32bitInt(chunk + 32, info->chrm_blue_x); + lodepng_set32bitInt(chunk + 36, info->chrm_blue_y); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) { + unsigned char data = info->srgb_intent; + return lodepng_chunk_createv(out, 1, "sRGB", &data); +} + +static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, const LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t keysize = lodepng_strlen(info->iccp_name); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + error = zlib_compress(&compressed, &compressedsize, + info->iccp_profile, info->iccp_profile_size, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "iCCP"); + } + if(!error) { + lodepng_memcpy(chunk + 8, info->iccp_name, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_cICP(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + /* Allow up to 255 since they are bytes. The ITU-R-BT.709 spec has a more + restricted set of valid values for each field, but that's up to the error + handling of a CICP library, not the PNG encoding/decoding, to manage. */ + if(info->cicp_color_primaries > 255) return 116; + if(info->cicp_transfer_function > 255) return 116; + if(info->cicp_matrix_coefficients > 255) return 116; + if(info->cicp_video_full_range_flag > 255) return 116; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "cICP")); + chunk[8 + 0] = (unsigned char)info->cicp_color_primaries; + chunk[8 + 1] = (unsigned char)info->cicp_transfer_function; + chunk[8 + 2] = (unsigned char)info->cicp_matrix_coefficients; + chunk[8 + 3] = (unsigned char)info->cicp_video_full_range_flag; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_mDCV(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + /* Allow up to 65535 since they are 16-bit ints. */ + if(info->mdcv_red_x > 65535) return 118; + if(info->mdcv_red_y > 65535) return 118; + if(info->mdcv_green_x > 65535) return 118; + if(info->mdcv_green_y > 65535) return 118; + if(info->mdcv_blue_x > 65535) return 118; + if(info->mdcv_blue_y > 65535) return 118; + if(info->mdcv_white_x > 65535) return 118; + if(info->mdcv_white_y > 65535) return 118; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 24, "mDCV")); + chunk[8 + 0] = (unsigned char)((info->mdcv_red_x) >> 8u); + chunk[8 + 1] = (unsigned char)(info->mdcv_red_x); + chunk[8 + 2] = (unsigned char)((info->mdcv_red_y) >> 8u); + chunk[8 + 3] = (unsigned char)(info->mdcv_red_y); + chunk[8 + 4] = (unsigned char)((info->mdcv_green_x) >> 8u); + chunk[8 + 5] = (unsigned char)(info->mdcv_green_x); + chunk[8 + 6] = (unsigned char)((info->mdcv_green_y) >> 8u); + chunk[8 + 7] = (unsigned char)(info->mdcv_green_y); + chunk[8 + 8] = (unsigned char)((info->mdcv_blue_x) >> 8u); + chunk[8 + 9] = (unsigned char)(info->mdcv_blue_x); + chunk[8 + 10] = (unsigned char)((info->mdcv_blue_y) >> 8u); + chunk[8 + 11] = (unsigned char)(info->mdcv_blue_y); + chunk[8 + 12] = (unsigned char)((info->mdcv_white_x) >> 8u); + chunk[8 + 13] = (unsigned char)(info->mdcv_white_x); + chunk[8 + 14] = (unsigned char)((info->mdcv_white_y) >> 8u); + chunk[8 + 15] = (unsigned char)(info->mdcv_white_y); + lodepng_set32bitInt(chunk + 8 + 16, info->mdcv_max_luminance); + lodepng_set32bitInt(chunk + 8 + 20, info->mdcv_min_luminance); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_cLLI(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 8, "cLLI")); + lodepng_set32bitInt(chunk + 8 + 0, info->clli_max_cll); + lodepng_set32bitInt(chunk + 8 + 4, info->clli_max_fall); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_eXIf(ucvector* out, const LodePNGInfo* info) { + return lodepng_chunk_createv(out, info->exif_size, "eXIf", info->exif); +} + +static unsigned addChunk_sBIT(ucvector* out, const LodePNGInfo* info) { + unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; + unsigned char* chunk = 0; + if(info->color.colortype == LCT_GREY) { + if(info->sbit_r == 0 || info->sbit_r > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "sBIT")); + chunk[8] = info->sbit_r; + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { + if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0) return 115; + if(info->sbit_r > bitdepth || info->sbit_g > bitdepth || info->sbit_b > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 3, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_g; + chunk[10] = info->sbit_b; + } else if(info->color.colortype == LCT_GREY_ALPHA) { + if(info->sbit_r == 0 || info->sbit_a == 0) return 115; + if(info->sbit_r > bitdepth || info->sbit_a > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_a; + } else if(info->color.colortype == LCT_RGBA) { + if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0 || info->sbit_a == 0 || + info->sbit_r > bitdepth || info->sbit_g > bitdepth || + info->sbit_b > bitdepth || info->sbit_a > bitdepth) { + return 115; + } + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_g; + chunk[10] = info->sbit_b; + chunk[11] = info->sbit_a; + } + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, + size_t length, size_t bytewidth, unsigned char filterType) { + size_t i; + switch(filterType) { + case 0: /*None*/ + for(i = 0; i != length; ++i) out[i] = scanline[i]; + break; + case 1: /*Sub*/ + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; + break; + case 2: /*Up*/ + if(prevline) { + for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; + } else { + for(i = 0; i != length; ++i) out[i] = scanline[i]; + } + break; + case 3: /*Average*/ + if(prevline) { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); + } else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); + } + break; + case 4: /*Paeth*/ + if(prevline) { + /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ + for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); + for(i = bytewidth; i < length; ++i) { + out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); + } + } else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ + for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); + } + break; + default: return; /*invalid filter type given*/ + } +} + +/* integer binary logarithm, max return value is 31 */ +static size_t ilog2(size_t i) { + size_t result = 0; + if(i >= 65536) { result += 16; i >>= 16; } + if(i >= 256) { result += 8; i >>= 8; } + if(i >= 16) { result += 4; i >>= 4; } + if(i >= 4) { result += 2; i >>= 2; } + if(i >= 2) { result += 1; /*i >>= 1;*/ } + return result; +} + +/* integer approximation for i * log2(i), helper function for LFS_ENTROPY */ +static size_t ilog2i(size_t i) { + size_t l; + if(i == 0) return 0; + l = ilog2(i); + /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) + linearly approximates the missing fractional part multiplied by i */ + return i * l + ((i - (((size_t)1) << l)) << 1u); +} + +static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) { + /* + For PNG filter method 0 + out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are + the scanlines with 1 extra byte per scanline + */ + + unsigned bpp = lodepng_get_bpp(color); + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + const unsigned char* prevline = 0; + unsigned x, y; + unsigned error = 0; + LodePNGFilterStrategy strategy = settings->filter_strategy; + + if(settings->filter_palette_zero && (color->colortype == LCT_PALETTE || color->bitdepth < 8)) { + /*if the filter_palette_zero setting is enabled, override the filter strategy with + zero for all scanlines for palette and less-than-8-bitdepth images*/ + strategy = LFS_ZERO; + } + + if(bpp == 0) return 31; /*error: invalid color type*/ + + if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { + unsigned char type = (unsigned char)strategy; + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } else if(strategy == LFS_MINSUM) { + /*adaptive filtering: independently for each row, try all five filter types and select the one that produces the + smallest sum of absolute values per row.*/ + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned char type, bestType = 0; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + + /*calculate the sum of the result*/ + if(type == 0) { + for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]); + } else { + for(x = 0; x != linebytes; ++x) { + /*For differences, each byte should be treated as signed, values above 127 are negative + (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. + This means filtertype 0 is almost never chosen, but that is justified.*/ + unsigned char s = attempt[type][x]; + sum += s < 128 ? s : (255U - s); + } + } + + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum < smallest) { + bestType = type; + smallest = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } else if(strategy == LFS_ENTROPY) { + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t bestSum = 0; + unsigned type, bestType = 0; + unsigned count[256]; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + lodepng_memset(count, 0, 256 * sizeof(*count)); + for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; + ++count[type]; /*the filter type itself is part of the scanline*/ + for(x = 0; x != 256; ++x) { + sum += ilog2i(count[x]); + } + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum > bestSum) { + bestType = type; + bestSum = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } else if(strategy == LFS_PREDEFINED) { + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + unsigned char type = settings->predefined_filters[y]; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } else if(strategy == LFS_BRUTE_FORCE) { + /*brute force filter chooser. + deflate the scanline after every filter attempt to see which one deflates best. + This is very slow and gives only slightly smaller, sometimes even larger, result*/ + size_t size[5]; + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned type = 0, bestType = 0; + unsigned char* dummy; + LodePNGCompressSettings zlibsettings; + lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings)); + /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, + to simulate the true case where the tree is the same for the whole image. Sometimes it gives + better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare + cases better compression. It does make this a bit less slow, so it's worth doing this.*/ + zlibsettings.btype = 1; + /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG + images only, so disable it*/ + zlibsettings.custom_zlib = 0; + zlibsettings.custom_deflate = 0; + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + if(!error) { + for(y = 0; y != h; ++y) /*try the 5 filter types*/ { + for(type = 0; type != 5; ++type) { + unsigned testsize = (unsigned)linebytes; + /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ + + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + size[type] = 0; + dummy = 0; + zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); + lodepng_free(dummy); + /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || size[type] < smallest) { + bestType = type; + smallest = size[type]; + } + } + prevline = &in[y * linebytes]; + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else return 88; /* unknown filter strategy */ + + return error; +} + +static void addPaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) { + /*The opposite of the removePaddingBits function + olinebits must be >= ilinebits*/ + unsigned y; + size_t diff = olinebits - ilinebits; + size_t obp = 0, ibp = 0; /*bit pointers*/ + for(y = 0; y != h; ++y) { + size_t x; + for(x = 0; x < ilinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + /*obp += diff; --> no, fill in some value in the padding bits too, to avoid + "Use of uninitialised value of size ###" warning from valgrind*/ + for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); + } +} + +/* +in: non-interlaced image with size w*h +out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with + no padding bits between scanlines, but between reduced images so that each + reduced image starts at a byte. +bpp: bits per pixel +there are no padding bits, not between scanlines, not between reduced images +in has the following size in bits: w * h * bpp. +out is possibly bigger due to padding bits between reduced images +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. +return value is error**/ +static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, + unsigned w, unsigned h, + const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) { + /* + This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: + *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter + *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter + */ + size_t bpp = lodepng_get_bpp(&info_png->color); + unsigned error = 0; + if(info_png->interlace_method == 0) { + /*image size plus an extra byte per scanline + possible padding bits*/ + *outsize = (size_t)h + ((size_t)h * (((size_t)w * bpp + 7u) / 8u)); + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ + + if(!error) { + /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ + if(bpp < 8 && (size_t)w * bpp != (((size_t)w * bpp + 7u) / 8u) * 8u) { + unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7u) / 8u)); + if(!padded) error = 83; /*alloc fail*/ + if(!error) { + addPaddingBits(padded, in, (((size_t)w * bpp + 7u) / 8u) * 8u, (size_t)w * bpp, h); + error = filter(*out, padded, w, h, &info_png->color, settings); + } + lodepng_free(padded); + } else { + /*we can immediately filter into the out buffer, no other steps needed*/ + error = filter(*out, in, w, h, &info_png->color, settings); + } + } + } else /*interlace_method is 1 (Adam7)*/ { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned char* adam7; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, (unsigned)bpp); + + *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out)) error = 83; /*alloc fail*/ + + adam7 = (unsigned char*)lodepng_malloc(passstart[7]); + if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ + + if(!error) { + unsigned i; + + Adam7_interlace(adam7, in, w, h, (unsigned)bpp); + for(i = 0; i != 7; ++i) { + if(bpp < 8) { + unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); + if(!padded) ERROR_BREAK(83); /*alloc fail*/ + addPaddingBits(padded, &adam7[passstart[i]], + (((size_t)passw[i] * bpp + 7u) / 8u) * 8u, (size_t)passw[i] * bpp, passh[i]); + error = filter(&(*out)[filter_passstart[i]], padded, + passw[i], passh[i], &info_png->color, settings); + lodepng_free(padded); + } else { + error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], + passw[i], passh[i], &info_png->color, settings); + } + + if(error) break; + } + } + + lodepng_free(adam7); + } + + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) { + unsigned char* inchunk = data; + while((size_t)(inchunk - data) < datasize) { + CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); + out->allocsize = out->size; /*fix the allocsize again*/ + inchunk = lodepng_chunk_next(inchunk, data + datasize); + } + return 0; +} + +static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) { + /* + It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 + are "RGB ". We do not perform any full parsing of the ICC profile here, other + than check those 4 bytes to grayscale profile. Other than that, validity of + the profile is not checked. This is needed only because the PNG specification + requires using a non-gray color model if there is an ICC profile with "RGB " + (sadly limiting compression opportunities if the input data is grayscale RGB + data), and requires using a gray color model if it is "GRAY". + */ + if(size < 20) return 0; + return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; +} + +static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) { + /* See comment in isGrayICCProfile*/ + if(size < 20) return 0; + return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state) { + unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ + size_t datasize = 0; + ucvector outv = ucvector_init(NULL, 0); + LodePNGInfo info; + const LodePNGInfo* info_png = &state->info_png; + LodePNGColorMode auto_color; + unsigned error = 0; + + lodepng_info_init(&info); + lodepng_color_mode_init(&auto_color); + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + + /*check input values validity*/ + if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette) + && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) { + /*this error is returned even if auto_convert is enabled and thus encoder could + generate the palette by itself: while allowing this could be possible in theory, + it may complicate the code or edge cases, and always requiring to give a palette + when setting this color type is a simpler contract*/ + error = 68; /*invalid palette size, it is only allowed to be 1-256*/ + goto cleanup; + } + if(state->encoder.zlibsettings.btype > 2) { + error = 61; /*error: invalid btype*/ + goto cleanup; + } + if(info_png->interlace_method > 1) { + error = 71; /*error: invalid interlace mode*/ + goto cleanup; + } + error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth); + if(error) goto cleanup; /*error: invalid color type given*/ + error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); + if(error) goto cleanup; /*error: invalid color type given*/ + + /* color convert and compute scanline filter types */ + CERROR_TRY_RETURN(lodepng_info_copy(&info, &state->info_png)); + if(state->encoder.auto_convert) { + LodePNGColorStats stats; + unsigned allow_convert = 1; + lodepng_color_stats_init(&stats); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined && + isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use palette with a GRAY ICC profile, even + if the palette has only gray colors, so disallow it.*/ + stats.allow_palette = 0; + } + if(info_png->iccp_defined && + isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/ + stats.allow_greyscale = 0; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw); + if(error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->background_defined) { + /*the background chunk's color must be taken into account as well*/ + unsigned r = 0, g = 0, b = 0; + LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); + lodepng_convert_rgb(&r, &g, &b, + info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color); + error = lodepng_color_stats_add(&stats, r, g, b, 65535); + if(error) goto cleanup; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + error = auto_choose_color(&auto_color, &state->info_raw, &stats); + if(error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->sbit_defined) { + /*if sbit is defined, due to strict requirements of which sbit values can be present for which color modes, + auto_convert can't be done in many cases. However, do support a few cases here. + TODO: more conversions may be possible, and it may also be possible to get a more appropriate color type out of + auto_choose_color if knowledge about sbit is used beforehand + */ + unsigned sbit_max = LODEPNG_MAX(LODEPNG_MAX(LODEPNG_MAX(info_png->sbit_r, info_png->sbit_g), + info_png->sbit_b), info_png->sbit_a); + unsigned equal = (!info_png->sbit_g || info_png->sbit_g == info_png->sbit_r) + && (!info_png->sbit_b || info_png->sbit_b == info_png->sbit_r) + && (!info_png->sbit_a || info_png->sbit_a == info_png->sbit_r); + allow_convert = 0; + if(info.color.colortype == LCT_PALETTE && + auto_color.colortype == LCT_PALETTE) { + /* input and output are palette, and in this case it may happen that palette data is + expected to be copied from info_raw into the info_png */ + allow_convert = 1; + } + /*going from 8-bit RGB to palette (or 16-bit as long as sbit_max <= 8) is possible + since both are 8-bit RGB for sBIT's purposes*/ + if(info.color.colortype == LCT_RGB && + auto_color.colortype == LCT_PALETTE && sbit_max <= 8) { + allow_convert = 1; + } + /*going from 8-bit RGBA to palette is also ok but only if sbit_a is exactly 8*/ + if(info.color.colortype == LCT_RGBA && auto_color.colortype == LCT_PALETTE && + info_png->sbit_a == 8 && sbit_max <= 8) { + allow_convert = 1; + } + /*going from 16-bit RGB(A) to 8-bit RGB(A) is ok if all sbit values are <= 8*/ + if((info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA) && info.color.bitdepth == 16 && + auto_color.colortype == info.color.colortype && auto_color.bitdepth == 8 && + sbit_max <= 8) { + allow_convert = 1; + } + /*going to less channels is ok if all bit values are equal (all possible values in sbit, + as well as the chosen bitdepth of the result). Due to how auto_convert works, + we already know that auto_color.colortype has less than or equal amount of channels than + info.colortype. Palette is not used here. This conversion is not allowed if + info_png->sbit_r < auto_color.bitdepth, because specifically for alpha, non-presence of + an sbit value heavily implies that alpha's bit depth is equal to the PNG bit depth (rather + than the bit depths set in the r, g and b sbit values, by how the PNG specification describes + handling tRNS chunk case with sBIT), so be conservative here about ignoring user input.*/ + if(info.color.colortype != LCT_PALETTE && auto_color.colortype != LCT_PALETTE && + equal && info_png->sbit_r == auto_color.bitdepth) { + allow_convert = 1; + } + } +#endif + if(state->encoder.force_palette) { + if(info.color.colortype != LCT_GREY && info.color.colortype != LCT_GREY_ALPHA && + (auto_color.colortype == LCT_GREY || auto_color.colortype == LCT_GREY_ALPHA)) { + /*user specifically forced a PLTE palette, so cannot convert to grayscale types because + the PNG specification only allows writing a suggested palette in PLTE for truecolor types*/ + allow_convert = 0; + } + } + if(allow_convert) { + lodepng_color_mode_copy(&info.color, &auto_color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*also convert the background chunk*/ + if(info_png->background_defined) { + if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, + info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) { + error = 104; + goto cleanup; + } + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + } + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined) { + unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; + if(!gray_icc && !rgb_icc) { + error = 100; /* Disallowed profile color type for PNG */ + goto cleanup; + } + if(gray_icc != gray_png) { + /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa, + or in case of auto_convert, it wasn't possible to find appropriate model*/ + error = state->encoder.auto_convert ? 102 : 101; + goto cleanup; + } + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { + unsigned char* converted; + size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; + + converted = (unsigned char*)lodepng_malloc(size); + if(!converted && size) error = 83; /*alloc fail*/ + if(!error) { + error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); + } + if(!error) { + error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); + } + lodepng_free(converted); + if(error) goto cleanup; + } else { + error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); + if(error) goto cleanup; + } + + /* output all PNG chunks */ { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + size_t i; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*write signature and chunks*/ + error = writeSignature(&outv); + if(error) goto cleanup; + /*IHDR*/ + error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); + if(error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*unknown chunks between IHDR and PLTE*/ + if(info.unknown_chunks_data[0]) { + error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); + if(error) goto cleanup; + } + /*color profile chunks must come before PLTE */ + if(info.cicp_defined) { + error = addChunk_cICP(&outv, &info); + if(error) goto cleanup; + } + if(info.mdcv_defined) { + error = addChunk_mDCV(&outv, &info); + if(error) goto cleanup; + } + if(info.clli_defined) { + error = addChunk_cLLI(&outv, &info); + if(error) goto cleanup; + } + if(info.iccp_defined) { + error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); + if(error) goto cleanup; + } + if(info.srgb_defined) { + error = addChunk_sRGB(&outv, &info); + if(error) goto cleanup; + } + if(info.gama_defined) { + error = addChunk_gAMA(&outv, &info); + if(error) goto cleanup; + } + if(info.chrm_defined) { + error = addChunk_cHRM(&outv, &info); + if(error) goto cleanup; + } + if(info_png->sbit_defined) { + error = addChunk_sBIT(&outv, &info); + if(error) goto cleanup; + } + if(info.exif_defined) { + error = addChunk_eXIf(&outv, &info); + if(error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*PLTE*/ + if(info.color.colortype == LCT_PALETTE) { + error = addChunk_PLTE(&outv, &info.color); + if(error) goto cleanup; + } + if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) { + /*force_palette means: write suggested palette for truecolor in PLTE chunk*/ + error = addChunk_PLTE(&outv, &info.color); + if(error) goto cleanup; + } + /*tRNS (this will only add if when necessary) */ + error = addChunk_tRNS(&outv, &info.color); + if(error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*bKGD (must come between PLTE and the IDAt chunks*/ + if(info.background_defined) { + error = addChunk_bKGD(&outv, &info); + if(error) goto cleanup; + } + /*pHYs (must come before the IDAT chunks)*/ + if(info.phys_defined) { + error = addChunk_pHYs(&outv, &info); + if(error) goto cleanup; + } + + /*unknown chunks between PLTE and IDAT*/ + if(info.unknown_chunks_data[1]) { + error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); + if(error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*IDAT (multiple IDAT chunks must be consecutive)*/ + error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); + if(error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*tIME*/ + if(info.time_defined) { + error = addChunk_tIME(&outv, &info.time); + if(error) goto cleanup; + } + /*tEXt and/or zTXt*/ + for(i = 0; i != info.text_num; ++i) { + if(lodepng_strlen(info.text_keys[i]) > 79) { + error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.text_keys[i]) < 1) { + error = 67; /*text chunk too small*/ + goto cleanup; + } + if(state->encoder.text_compression) { + error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); + if(error) goto cleanup; + } else { + error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); + if(error) goto cleanup; + } + } + /*LodePNG version id in text chunk*/ + if(state->encoder.add_id) { + unsigned already_added_id_text = 0; + for(i = 0; i != info.text_num; ++i) { + const char* k = info.text_keys[i]; + /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */ + if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' && + k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') { + already_added_id_text = 1; + break; + } + } + if(already_added_id_text == 0) { + error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ + if(error) goto cleanup; + } + } + /*iTXt*/ + for(i = 0; i != info.itext_num; ++i) { + if(lodepng_strlen(info.itext_keys[i]) > 79) { + error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.itext_keys[i]) < 1) { + error = 67; /*text chunk too small*/ + goto cleanup; + } + error = addChunk_iTXt( + &outv, state->encoder.text_compression, + info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], + &state->encoder.zlibsettings); + if(error) goto cleanup; + } + + /*unknown chunks between IDAT and IEND*/ + if(info.unknown_chunks_data[2]) { + error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); + if(error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + error = addChunk_IEND(&outv); + if(error) goto cleanup; + } + +cleanup: + lodepng_info_cleanup(&info); + lodepng_free(data); + lodepng_color_mode_cleanup(&auto_color); + + /*instead of cleaning the vector up, give it to the output*/ + *out = outv.data; + *outsize = outv.size; + + state->error = error; /*TODO: remove this and make input state const*/ + + return error; +} + +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, + unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + state.info_png.color.colortype = colortype; + state.info_png.color.bitdepth = bitdepth; + error = lodepng_encode(out, outsize, image, w, h, &state); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); + if(!error) error = lodepng_save_file(buffer, buffersize, filename); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) { + lodepng_compress_settings_init(&settings->zlibsettings); + settings->filter_palette_zero = 1; + settings->filter_strategy = LFS_MINSUM; + settings->auto_convert = 1; + settings->force_palette = 0; + settings->predefined_filters = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->add_id = 0; + settings->text_compression = 1; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/* +This returns the description of a numerical error code in English. This is also +the documentation of all the error codes. +*/ +const char* lodepng_error_text(unsigned code) { + switch(code) { + case 0: return "no error, everything went ok"; + case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ + case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ + case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ + case 13: return "problem while processing dynamic deflate block"; + case 14: return "problem while processing dynamic deflate block"; + case 15: return "problem while processing dynamic deflate block"; + /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/ + case 16: return "invalid code while processing dynamic deflate block"; + case 17: return "end of out buffer memory reached while inflating"; + case 18: return "invalid distance code while inflating"; + case 19: return "end of out buffer memory reached while inflating"; + case 20: return "invalid deflate block BTYPE encountered while decoding"; + case 21: return "NLEN is not ones complement of LEN in a deflate block"; + + /*end of out buffer memory reached while inflating: + This can happen if the inflated deflate data is longer than the amount of bytes required to fill up + all the pixels of the image, given the color depth and image dimensions. Something that doesn't + happen in a normal, well encoded, PNG image.*/ + case 22: return "end of out buffer memory reached while inflating"; + case 23: return "end of in buffer memory reached while inflating"; + case 24: return "invalid FCHECK in zlib header"; + case 25: return "invalid compression method in zlib header"; + case 26: return "FDICT encountered in zlib header while it's not used for PNG"; + case 27: return "PNG file is smaller than a PNG header"; + /*Checks the magic file header, the first 8 bytes of the PNG file*/ + case 28: return "incorrect PNG signature, it's no PNG or corrupted"; + case 29: return "first chunk is not the header chunk"; + case 30: return "chunk length too large, chunk broken off at end of file"; + case 31: return "illegal PNG color type or bpp"; + case 32: return "illegal PNG compression method"; + case 33: return "illegal PNG filter method"; + case 34: return "illegal PNG interlace method"; + case 35: return "chunk length of a chunk is too large or the chunk too small"; + case 36: return "illegal PNG filter type encountered"; + case 37: return "illegal bit depth for this color type given"; + case 38: return "the palette is too small or too big"; /*0, or more than 256 colors*/ + case 39: return "tRNS chunk before PLTE or has more entries than palette size"; + case 40: return "tRNS chunk has wrong size for grayscale image"; + case 41: return "tRNS chunk has wrong size for RGB image"; + case 42: return "tRNS chunk appeared while it was not allowed for this color type"; + case 43: return "bKGD chunk has wrong size for palette image"; + case 44: return "bKGD chunk has wrong size for grayscale image"; + case 45: return "bKGD chunk has wrong size for RGB image"; + case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; + case 49: return "jumped past memory while generating dynamic huffman tree"; + case 50: return "jumped past memory while generating dynamic huffman tree"; + case 51: return "jumped past memory while inflating huffman block"; + case 52: return "jumped past memory while inflating"; + case 53: return "size of zlib data too small"; + case 54: return "repeat symbol in tree while there was no value symbol yet"; + /*jumped past tree while generating huffman tree, this could be when the + tree will have more leaves than symbols after generating it out of the + given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ + case 55: return "jumped past tree while generating huffman tree"; + case 56: return "given output image colortype or bitdepth not supported for color conversion"; + case 57: return "invalid CRC encountered (checking CRC can be disabled)"; + case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; + case 59: return "requested color conversion not supported"; + case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; + case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; + /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/ + case 62: return "conversion from color to grayscale not supported"; + /*(2^31-1)*/ + case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; + /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ + case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; + case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; + case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; + case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; + case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; + case 71: return "invalid interlace mode given to encoder (must be 0 or 1)"; + case 72: return "while decoding, invalid compression method encountered in zTXt, iTXt or iCCP chunk (it must be 0)"; + case 73: return "invalid tIME chunk size"; + case 74: return "invalid pHYs chunk size"; + /*length could be wrong, or data chopped off*/ + case 75: return "no null termination char found while decoding text chunk"; + case 76: return "iTXt chunk too short to contain required bytes"; + case 77: return "integer overflow in buffer size"; + case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ + case 79: return "failed to open file for writing"; + case 80: return "tried creating a tree of 0 symbols"; + case 81: return "lazy matching at pos 0 is impossible"; + case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; + case 83: return "memory allocation failed"; + case 84: return "given image too small to contain all pixels to be encoded"; + case 86: return "impossible offset in lz77 encoding (internal bug)"; + case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; + case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; + case 89: return "text chunk keyword too short or long: must have size 1-79"; + /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ + case 90: return "windowsize must be a power of two"; + case 91: return "invalid decompressed idat size"; + case 92: return "integer overflow due to too many pixels"; + case 93: return "zero width or height is invalid"; + case 94: return "header chunk must have a size of 13 bytes"; + case 95: return "integer overflow with combined idat chunk size"; + case 96: return "invalid gAMA chunk size"; + case 97: return "invalid cHRM chunk size"; + case 98: return "invalid sRGB chunk size"; + case 99: return "invalid sRGB rendering intent"; + case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; + case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa"; + case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification"; + case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; + case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)"; + case 105: return "integer overflow of bitsize"; + case 106: return "PNG file must have PLTE chunk if color type is palette"; + case 107: return "color convert from palette mode requested without setting the palette data in it"; + case 108: return "tried to add more than 256 values to a palette"; + /*this limit can be configured in LodePNGDecompressSettings*/ + case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size"; + case 110: return "custom zlib or inflate decompression failed"; + case 111: return "custom zlib or deflate compression failed"; + /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large text sizes.*/ + case 112: return "compressed text unreasonably large"; + /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large ICC profile*/ + case 113: return "ICC profile unreasonably large"; + case 114: return "sBIT chunk has wrong size for the color type of the image"; + case 115: return "sBIT value out of range"; + case 116: return "cICP value out of range"; + case 117: return "invalid cICP chunk size"; + case 118: return "mDCV value out of range"; + case 119: return "invalid mDCV chunk size"; + case 120: return "invalid cLLI chunk size"; + case 121: return "invalid chunk type name: may only contain [a-zA-Z]"; + case 122: return "invalid chunk type name: third character must be uppercase"; + case 123: return "invalid ICC profile size"; + } + return "unknown error code"; +} +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // C++ Wrapper // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng { + +#ifdef LODEPNG_COMPILE_DISK +/* Resizes the vector to the file size and reads the file into it. Returns error code.*/ +static unsigned load_file_(std::vector& buffer, FILE* file) { + long size = lodepng_filesize(file); + if(size < 0) return 78; + buffer.resize((size_t)size); + if(size == 0) return 0; /*ok*/ + if(fread(&buffer[0], 1, buffer.size(), file) != buffer.size()) return 78; + return 0; /*ok*/ +} + +unsigned load_file(std::vector& buffer, const std::string& filename) { + unsigned error; + FILE* file = fopen(filename.c_str(), "rb"); + if(!file) return 78; + error = load_file_(buffer, file); + fclose(file); + return error; +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned save_file(const std::vector& buffer, const std::string& filename) { + return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); +} +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings) { + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings) { + return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings) { + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings) { + return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ + + +#ifdef LODEPNG_COMPILE_PNG + +State::State() { + lodepng_state_init(this); +} + +State::State(const State& other) { + lodepng_state_init(this); + lodepng_state_copy(this, &other); +} + +State::~State() { + lodepng_state_cleanup(this); +} + +State& State::operator=(const State& other) { + lodepng_state_copy(this, &other); + return *this; +} + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer = 0; + unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); + if(buffer && !error) { + State state; + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), buffer, &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) { + return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize) { + unsigned char* buffer = NULL; + unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); + if(buffer && !error) { + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), buffer, &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in) { + return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, + LodePNGColorType colortype, unsigned bitdepth) { + std::vector buffer; + /* safe output values in case error happens */ + w = h = 0; + unsigned error = load_file(buffer, filename); + if(error) return error; + return decode(out, w, h, buffer, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DECODER */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} + +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state) { + if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, state); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + std::vector buffer; + unsigned error = encode(buffer, in, w, h, colortype, bitdepth); + if(!error) error = save_file(buffer, filename); + return error; +} + +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_PNG */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ diff --git a/Modules/lodepng-module/source/module.c b/Modules/lodepng-module/source/module.c new file mode 100644 index 000000000..40af020d3 --- /dev/null +++ b/Modules/lodepng-module/source/module.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include + +static const struct ModuleSymbol SYMBOLS[] = { + // decode + DEFINE_MODULE_SYMBOL(lodepng_decode_memory), + DEFINE_MODULE_SYMBOL(lodepng_decode32), + DEFINE_MODULE_SYMBOL(lodepng_decode24), + DEFINE_MODULE_SYMBOL(lodepng_decode_file), + DEFINE_MODULE_SYMBOL(lodepng_decode32_file), + DEFINE_MODULE_SYMBOL(lodepng_decode24_file), + // encode + DEFINE_MODULE_SYMBOL(lodepng_encode_memory), + DEFINE_MODULE_SYMBOL(lodepng_encode32), + DEFINE_MODULE_SYMBOL(lodepng_encode24), + DEFINE_MODULE_SYMBOL(lodepng_encode_file), + DEFINE_MODULE_SYMBOL(lodepng_encode32_file), + DEFINE_MODULE_SYMBOL(lodepng_encode24_file), + // utilities + DEFINE_MODULE_SYMBOL(lodepng_error_text), + DEFINE_MODULE_SYMBOL(lodepng_load_file), + DEFINE_MODULE_SYMBOL(lodepng_save_file), + DEFINE_MODULE_SYMBOL(lodepng_malloc), + DEFINE_MODULE_SYMBOL(lodepng_realloc), + DEFINE_MODULE_SYMBOL(lodepng_free), + MODULE_SYMBOL_TERMINATOR, +}; + +struct Module lodepng_module = { + .name = "lodepng", + .start = NULL, + .stop = NULL, + .drivers = NULL, + .symbols = SYMBOLS, + .internal = NULL, +}; diff --git a/Modules/lodepng-module/tests/CMakeLists.txt b/Modules/lodepng-module/tests/CMakeLists.txt new file mode 100644 index 000000000..585cb9e6a --- /dev/null +++ b/Modules/lodepng-module/tests/CMakeLists.txt @@ -0,0 +1,20 @@ +project(LodePngModuleTests) + +enable_language(C CXX ASM) + +file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp) +add_executable(LodePngModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES}) + +target_include_directories(LodePngModuleTests PRIVATE ${DOCTESTINC}) + +target_compile_definitions(LodePngModuleTests PRIVATE + "LODEPNG_TEST_LOGO=\"${CMAKE_SOURCE_DIR}/Data/system/app/Boot/assets/logo.png\"" +) + +add_test(NAME LodePngModuleTests COMMAND LodePngModuleTests) + +target_link_libraries(LodePngModuleTests PUBLIC + lodepng-module + TactilityKernel + freertos_kernel +) diff --git a/Modules/lodepng-module/tests/source/lodepng_test.cpp b/Modules/lodepng-module/tests/source/lodepng_test.cpp new file mode 100644 index 000000000..c132f47a3 --- /dev/null +++ b/Modules/lodepng-module/tests/source/lodepng_test.cpp @@ -0,0 +1,47 @@ +#include "doctest.h" + +#include + +#include + +TEST_CASE("lodepng decodes a PNG file") { + unsigned char* image = nullptr; + unsigned width = 0; + unsigned height = 0; + REQUIRE_EQ(lodepng_decode32_file(&image, &width, &height, LODEPNG_TEST_LOGO), 0); + CHECK_EQ(width, 80); + CHECK_EQ(height, 103); + lodepng_free(image); +} + +TEST_CASE("lodepng returns an error for a missing file") { + unsigned char* image = nullptr; + unsigned width = 0; + unsigned height = 0; + CHECK_NE(lodepng_decode32_file(&image, &width, &height, "missing.png"), 0); + lodepng_free(image); +} + +TEST_CASE("lodepng encodes and decodes an image without changes") { + constexpr unsigned width = 3; + constexpr unsigned height = 2; + const unsigned char pixels[width * height * 4] = { + 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, + 0, 0, 0, 0, 255, 255, 255, 128, 10, 20, 30, 40, + }; + + unsigned char* png = nullptr; + size_t png_size = 0; + REQUIRE_EQ(lodepng_encode32(&png, &png_size, pixels, width, height), 0); + + unsigned char* decoded = nullptr; + unsigned decoded_width = 0; + unsigned decoded_height = 0; + REQUIRE_EQ(lodepng_decode32(&decoded, &decoded_width, &decoded_height, png, png_size), 0); + CHECK_EQ(decoded_width, width); + CHECK_EQ(decoded_height, height); + CHECK_EQ(memcmp(decoded, pixels, sizeof(pixels)), 0); + + lodepng_free(png); + lodepng_free(decoded); +} diff --git a/Modules/lodepng-module/tests/source/main.cpp b/Modules/lodepng-module/tests/source/main.cpp new file mode 100644 index 000000000..93a036fac --- /dev/null +++ b/Modules/lodepng-module/tests/source/main.cpp @@ -0,0 +1,64 @@ +#define DOCTEST_CONFIG_IMPLEMENT +#include "doctest.h" +#include +#include + +#include "FreeRTOS.h" +#include "task.h" + +typedef struct { + int argc; + char** argv; + int result; +} TestTaskData; + +void test_task(void* parameter) { + auto* data = (TestTaskData*)parameter; + + doctest::Context context; + + context.applyCommandLine(data->argc, data->argv); + + // overrides + context.setOption("no-breaks", true); // don't break in the debugger when assertions fail + + data->result = context.run(); + + vTaskEndScheduler(); + + vTaskDelete(nullptr); +} + +int main(int argc, char** argv) { + TestTaskData data = { + .argc = argc, + .argv = argv, + .result = 0 + }; + + BaseType_t task_result = xTaskCreate( + test_task, + "test_task", + 8192, + &data, + 1, + nullptr + ); + + if (task_result != pdPASS) { + return 1; + } + + vTaskStartScheduler(); + + return data.result; +} + +// NOTE: This is normally provided by the platform kernel module, but that's not loaded for lodepng-module +extern "C" { +// Required for FreeRTOS +void vAssertCalled(unsigned long line, const char* const file) { + std::fprintf(stderr, "assert failed at %s:%lu\n", file, line); + std::abort(); +} +} diff --git a/Modules/lvgl-module/CMakeLists.txt b/Modules/lvgl-module/CMakeLists.txt index 62d92db84..93d09deb3 100644 --- a/Modules/lvgl-module/CMakeLists.txt +++ b/Modules/lvgl-module/CMakeLists.txt @@ -70,14 +70,11 @@ endif () # Regular source files file(GLOB_RECURSE SOURCE_FILES "source/*.c*") -# Font source files -list(APPEND SOURCE_FILES "source-fonts/material_symbols_statusbar_${statusbar_symbol_size}.c") -list(APPEND SOURCE_FILES "source-fonts/material_symbols_launcher_${launcher_symbol_size}.c") -list(APPEND SOURCE_FILES "source-fonts/material_symbols_shared_${shared_symbol_size}.c") -list(APPEND SOURCE_FILES "source-fonts/material_symbols_shared_${shared_symbol_2x_size}.c") list(APPEND REQUIRES_LIST TactilityKernel + binfont-module + lodepng-module lvgl ) @@ -118,13 +115,9 @@ target_compile_definitions(${MODULE_NAME} PUBLIC "-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_STATUSBAR_FONT_ICON_SYMBOL=material_symbols_statusbar_${statusbar_symbol_size}" "-DTT_LVGL_LAUNCHER_FONT_ICON_SIZE=${launcher_symbol_size}" - "-DTT_LVGL_LAUNCHER_FONT_ICON_SYMBOL=material_symbols_launcher_${launcher_symbol_size}" "-DTT_LVGL_SHARED_FONT_ICON_SIZE=${shared_symbol_size}" - "-DTT_LVGL_SHARED_FONT_ICON_SYMBOL=material_symbols_shared_${shared_symbol_size}" "-DTT_LVGL_SHARED_FONT_ICON_2X_SIZE=${shared_symbol_2x_size}" - "-DTT_LVGL_SHARED_FONT_ICON_2X_SYMBOL=material_symbols_shared_${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 2db25aacb..aa74b87bb 100644 --- a/Modules/lvgl-module/README.md +++ b/Modules/lvgl-module/README.md @@ -35,7 +35,9 @@ Font sizes and symbols are configurable: - **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`. -If you change an icon font size, ensure that a corresponding C file exists in `source-fonts/` (e.g., `material_symbols_shared_24.c`). These files are generated from TTF/OTF fonts using the LVGL font converter. +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`. +To add an icon, add its name to `generate-icons.py` and run it (requires `pip install fonttools`). This regenerates the TTF subset, the codepoints file and the name lists. ## Custom memory allocator diff --git a/Modules/lvgl-module/generate-icons.py b/Modules/lvgl-module/generate-icons.py index 5123923ea..4d794fc4e 100755 --- a/Modules/lvgl-module/generate-icons.py +++ b/Modules/lvgl-module/generate-icons.py @@ -1,6 +1,22 @@ #!/usr/bin/env python3 +""" +Generates the Material Symbols icon resources: +- include/lvgl/icons/*.h: UTF-8 string defines per icon +- include/lvgl/icons/names.h and source/icon_names.c: icon name lists per icon font +- Data/system/fonts/MaterialSymbolsRounded.ttf: TTF subset with only the used icons +- Data/system/fonts/MaterialSymbolsRounded.codepoints: name to codepoint map of the used icons + +The icon fonts are rasterized from the TTF subset on device at startup. + +Requires the fonttools package: pip install fonttools +""" import os import urllib.request +import zlib + +from fontTools import subset +from fontTools.ttLib import TTFont +from fontTools.varLib import instancer def download_file(url: str, filename: str): if not os.path.exists(filename): @@ -9,15 +25,6 @@ def download_file(url: str, filename: str): else: print(f"{filename} already exists, skipping download.") -def generate(bpp, size, font_file: str, symbols: list, output: str): - output_file_name = f"{output}_{size}.c" - output_path = os.path.join("source-fonts", output_file_name) - print(f"Generating {output_file_name}") - cmd = "lv_font_conv --no-compress --no-prefilter --bpp {} --size {} --font {} -r {} --format lvgl -o {} --force-fast-kern-format".format(bpp, size, font_file, ",".join(symbols), output_path) - ret = os.system(cmd) - if ret != 0: - raise RuntimeError(f"Font generation failed for {output_file_name} (exit code {ret})") - def read_code_points_map(file_path: str): codepoints = {} with open(file_path, 'r') as f: @@ -40,9 +47,62 @@ def get_code_points(codepoints, names: list) -> list: result.append(f"0x{codepoints[safe_name].upper()}") return result -def generate_icon_fonts(font_file, font_sizes, symbols, output): - for size in font_sizes: - generate(2, size, font_file, symbols, output) +def generate_subset_ttf(font_file: str, codepoints: list, output_path: str) -> bytes: + print(f"Generating {output_path}") + font = TTFont(font_file, recalcTimestamp=False) + if "fvar" in font: + # Pin all axes to their defaults, which are the outlines lv_font_conv used to render + font = instancer.instantiateVariableFont(font, {axis.axisTag: None for axis in font["fvar"].axes}) + 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=codepoints) + subsetter.subset(font) + os.makedirs(os.path.dirname(output_path), exist_ok=True) + font.save(output_path) + with open(output_path, "rb") as f: + return f.read() + +def generate_codepoints_file(codepoint_map: dict, names: list, output_path: str) -> bytes: + print(f"Generating {output_path}") + content = "".join(f"{name} {codepoint_map[name]}\n" for name in names) + with open(output_path, "w") as f: + f.write(content) + return content.encode("utf-8") + +def generate_icon_name_lists(icon_sets: list, version_input: bytes): + version = zlib.crc32(version_input + repr(icon_sets).encode("utf-8")) & 0xFFFFFFFF + + header_path = os.path.join("include", "lvgl", "icons", "names.h") + print(f"Generating {header_path}") + with open(header_path, "w") as f: + f.write("// SPDX-License-Identifier: Apache-2.0\n\n") + f.write("#pragma once\n\n") + f.write("#include \n\n") + f.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n") + f.write("/** Changes whenever the icon TTF subset, its codepoints file or the icon name lists change */\n") + f.write(f"#define LVGL_ICON_FONT_VERSION 0x{version:08X}u\n\n") + f.write("// Icon names per icon font, resolved through the .codepoints file next to the TTF\n") + for name, _ in icon_sets: + f.write(f"extern const char* const lvgl_icon_{name}_names[];\n") + f.write(f"extern const size_t lvgl_icon_{name}_name_count;\n\n") + f.write("#ifdef __cplusplus\n}\n#endif\n") + + source_path = os.path.join("source", "icon_names.c") + print(f"Generating {source_path}") + with open(source_path, "w") as f: + f.write("// SPDX-License-Identifier: Apache-2.0\n") + f.write("// Generated by generate-icons.py\n\n") + f.write("#include \n\n") + for name, names in icon_sets: + f.write(f"const char* const lvgl_icon_{name}_names[] = {{\n") + for icon_name in names: + f.write(f" \"{icon_name.lower()}\",\n") + f.write("};\n\n") + f.write(f"const size_t lvgl_icon_{name}_name_count = sizeof(lvgl_icon_{name}_names) / sizeof(lvgl_icon_{name}_names[0]);\n\n") def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_name: str): filename = f"{variable_name}.h" @@ -161,33 +221,6 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam "settings" ] -shared_symbol_sizes = [ - 12, - 16, # T-Deck reference, with montserrat 14 in lv_list as icon with text - 20, - 24, - 32, - 40, - 48, - 64 -] - -statusbar_symbol_sizes = [ - 12, - 16, # T-Deck reference - 20, - 30 -] - -launcher_symbol_sizes = [ - 30, - 36, # T-Deck reference - 42, - 48, - 64, - 72 -] - # Resolve file path relative to this script so it can be executed from any CWD base_dir = os.path.dirname(__file__) if base_dir: @@ -198,6 +231,8 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam codepoints_filename = "MaterialSymbolsRounded.codepoints" ttf_filename = "MaterialSymbolsRounded.ttf" +subset_ttf_path = os.path.join("..", "..", "Data", "system", "fonts", "MaterialSymbolsRounded.ttf") +subset_codepoints_path = os.path.join("..", "..", "Data", "system", "fonts", "MaterialSymbolsRounded.codepoints") download_file(codepoints_url, codepoints_filename) download_file(ttf_url, ttf_filename) @@ -205,18 +240,17 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam codepoints_map_path = codepoints_filename codepoints_map = read_code_points_map(codepoints_map_path) -# Shared symbols -shared_symbol_code_points = get_code_points(codepoints_map, shared_symbol_code_point_names) -generate_icon_fonts(ttf_filename, shared_symbol_sizes, shared_symbol_code_points, "material_symbols_shared") -generate_icon_names(codepoints_map, shared_symbol_code_point_names, "shared") - -# Statusbar symbols -statusbar_symbol_code_points = get_code_points(codepoints_map, statusbar_symbol_code_point_names) -generate_icon_fonts(ttf_filename, statusbar_symbol_sizes, statusbar_symbol_code_points, "material_symbols_statusbar") -generate_icon_names(codepoints_map, statusbar_symbol_code_point_names, "statusbar") +icon_sets = [ + ("shared", shared_symbol_code_point_names), + ("statusbar", statusbar_symbol_code_point_names), + ("launcher", launcher_symbol_code_point_names), +] -# Launcher symbols -launcher_symbol_code_points = get_code_points(codepoints_map, launcher_symbol_code_point_names) -generate_icon_fonts(ttf_filename, launcher_symbol_sizes, launcher_symbol_code_points, "material_symbols_launcher") -generate_icon_names(codepoints_map, launcher_symbol_code_point_names, "launcher") +for variable_name, names in icon_sets: + generate_icon_names(codepoints_map, names, variable_name) +all_names = sorted({name.lower() for _, names in icon_sets for name in names}) +all_codepoints = [int(cp, 16) for cp in get_code_points(codepoints_map, all_names)] +subset_data = generate_subset_ttf(ttf_filename, all_codepoints, subset_ttf_path) +codepoints_data = generate_codepoints_file(codepoints_map, all_names, subset_codepoints_path) +generate_icon_name_lists(icon_sets, subset_data + codepoints_data) diff --git a/Modules/lvgl-module/include/lvgl/binfont.h b/Modules/lvgl-module/include/lvgl/binfont.h new file mode 100644 index 000000000..565fbefbd --- /dev/null +++ b/Modules/lvgl-module/include/lvgl/binfont.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct BinFont; + +/** + * @brief Creates an LVGL font that renders glyphs from a BinFont. + * @param[in] font the source font, which must outlive the returned font + * @return the LVGL font, or NULL when memory allocation failed + */ +lv_font_t* lvgl_binfont_create(struct BinFont* font); + +/** Destroys a font from lvgl_binfont_create(). The BinFont is not closed. */ +void lvgl_binfont_destroy(lv_font_t* font); + +#ifdef __cplusplus +} +#endif diff --git a/Modules/lvgl-module/include/lvgl/fonts.h b/Modules/lvgl-module/include/lvgl/fonts.h index c4cf25d9e..3efc17651 100644 --- a/Modules/lvgl-module/include/lvgl/fonts.h +++ b/Modules/lvgl-module/include/lvgl/fonts.h @@ -14,6 +14,19 @@ enum LvglFontSize { FONT_SIZE_LARGE, }; +enum LvglIconFont { + LVGL_ICON_FONT_STATUSBAR, + LVGL_ICON_FONT_LAUNCHER, + LVGL_ICON_FONT_SHARED, + LVGL_ICON_FONT_SHARED_2X, +}; + +/** + * @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. + */ +void lvgl_set_icon_font(enum LvglIconFont icon_font, const lv_font_t* font); + 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 new file mode 100644 index 000000000..59b8a0001 --- /dev/null +++ b/Modules/lvgl-module/include/lvgl/icons/names.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Changes whenever the icon TTF subset, its codepoints file or the icon name lists change */ +#define LVGL_ICON_FONT_VERSION 0x977A6A66u + +// Icon names per icon font, resolved through the .codepoints file next to the TTF +extern const char* const lvgl_icon_shared_names[]; +extern const size_t lvgl_icon_shared_name_count; + +extern const char* const lvgl_icon_statusbar_names[]; +extern const size_t lvgl_icon_statusbar_name_count; + +extern const char* const lvgl_icon_launcher_names[]; +extern const size_t lvgl_icon_launcher_name_count; + +#ifdef __cplusplus +} +#endif diff --git a/Modules/lvgl-module/private/png_decoder.h b/Modules/lvgl-module/private/png_decoder.h new file mode 100644 index 000000000..9fd13ba67 --- /dev/null +++ b/Modules/lvgl-module/private/png_decoder.h @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +/** Registers the PNG image decoder with LVGL. Must be called after lv_init(). */ +void lvgl_png_decoder_init(void); diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_30.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_30.c deleted file mode 100644 index 4e371498c..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_30.c +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 30 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_30.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_30 -#define MATERIAL_SYMBOLS_LAUNCHER_30 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_30 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0x1f, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7e, 0xaa, 0xaf, - 0xea, 0xaa, 0xa9, 0xb, 0xc0, 0x0, 0xbf, 0xff, - 0xff, 0xfc, 0xbc, 0x0, 0x2, 0xff, 0xff, 0xff, - 0xdb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xbc, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x3e, 0xbc, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xeb, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x3, 0xeb, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xbc, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xeb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0xbc, 0x0, 0x0, 0x0, 0x0, 0x3, 0xe7, 0xea, - 0xaa, 0xaa, 0xaa, 0xaa, 0xbd, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf4, - - /* U+E5C3 "" */ - 0x2e, 0x0, 0xbd, 0x1, 0xf4, 0xbf, 0x81, 0xff, - 0x3, 0xfd, 0xff, 0xc2, 0xff, 0x7, 0xfe, 0xbf, - 0x81, 0xff, 0x3, 0xfd, 0x2e, 0x0, 0xbd, 0x1, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0x40, 0xfe, 0x2, 0xf8, 0xff, 0xc2, 0xff, - 0x7, 0xfd, 0xff, 0xc2, 0xff, 0x7, 0xfd, 0xbf, - 0x81, 0xff, 0x3, 0xfc, 0x19, 0x0, 0x68, 0x0, - 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2e, 0x0, 0xbd, 0x1, 0xf4, - 0xbf, 0x81, 0xff, 0x3, 0xfd, 0xff, 0xc2, 0xff, - 0x7, 0xfe, 0xbf, 0x81, 0xff, 0x3, 0xfd, 0x2e, - 0x0, 0xbd, 0x1, 0xf4, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x1, 0xa4, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x3, 0xe0, 0xbc, - 0x0, 0x0, 0x0, 0x90, 0x3e, 0xb, 0xc0, 0x60, - 0x0, 0x3f, 0xff, 0xd0, 0x7f, 0xff, 0xc0, 0xb, - 0xff, 0xf8, 0x2, 0xff, 0xfe, 0x1, 0xf8, 0xbc, - 0x0, 0x3, 0xe2, 0xf4, 0x3f, 0x0, 0x0, 0x50, - 0x0, 0xf, 0xc3, 0xf4, 0x0, 0xbf, 0xe0, 0x1, - 0xfc, 0x1f, 0xe0, 0x2f, 0xff, 0x80, 0xbf, 0x40, - 0x7f, 0x43, 0xff, 0xfc, 0x1f, 0xd0, 0x1, 0xf0, - 0x7f, 0xff, 0xd0, 0xf4, 0x0, 0x1f, 0x7, 0xff, - 0xfd, 0xf, 0x40, 0x7, 0xf4, 0x3f, 0xff, 0xc1, - 0xfd, 0x1, 0xfe, 0x2, 0xff, 0xf8, 0xb, 0xf4, - 0x3f, 0x40, 0xb, 0xfe, 0x0, 0x1f, 0xc3, 0xf0, - 0x0, 0x5, 0x0, 0x0, 0xf8, 0x1f, 0x8b, 0xc0, - 0x0, 0x3e, 0x2f, 0x40, 0xbf, 0xff, 0x80, 0x2f, - 0xff, 0xe0, 0x3, 0xff, 0xfd, 0x7, 0xff, 0xfc, - 0x0, 0x9, 0x3, 0xe0, 0xbc, 0xa, 0x0, 0x0, - 0x0, 0x3e, 0xb, 0xc0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x40, 0x0, - 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 480, .box_w = 26, .box_h = 20, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 130, .adv_w = 480, .box_w = 20, .box_h = 20, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 230, .adv_w = 480, .box_w = 26, .box_h = 26, .ofs_x = 2, .ofs_y = 2} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_30 = { -#else -lv_font_t material_symbols_launcher_30 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 26, /*The maximum line height required by the font*/ - .base_line = -2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_30*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_36.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_36.c deleted file mode 100644 index 9d44dacda..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_36.c +++ /dev/null @@ -1,194 +0,0 @@ -/******************************************************************************* - * Size: 36 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 36 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_36.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_36 -#define MATERIAL_SYMBOLS_LAUNCHER_36 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_36 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0x2f, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0xb, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0xf, 0xc0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xf8, 0xfc, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xef, 0xc0, 0x0, - 0x2, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, - - /* U+E5C3 "" */ - 0x2f, 0x80, 0xb, 0xe0, 0x2, 0xf8, 0xbf, 0xe0, - 0x2f, 0xf8, 0xb, 0xfe, 0xff, 0xf0, 0x3f, 0xfc, - 0xf, 0xff, 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, - 0xbf, 0xe0, 0x2f, 0xf8, 0xb, 0xfe, 0x2f, 0x80, - 0xb, 0xe0, 0x2, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x80, - 0xb, 0xe0, 0x2, 0xf8, 0xbf, 0xe0, 0x2f, 0xf8, - 0xb, 0xfe, 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, - 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, 0xbf, 0xe0, - 0x2f, 0xf8, 0xb, 0xfe, 0x2f, 0x80, 0xb, 0xe0, - 0x2, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0x80, 0xb, 0xe0, - 0x2, 0xf8, 0xbf, 0xe0, 0x2f, 0xf8, 0xb, 0xfe, - 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, 0xff, 0xf0, - 0x3f, 0xfc, 0xf, 0xff, 0xbf, 0xe0, 0x2f, 0xf8, - 0xb, 0xfe, 0x2f, 0x80, 0xb, 0xe0, 0x2, 0xf8, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x1, 0xff, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbd, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x10, - 0xb, 0xd0, 0x7e, 0x0, 0x40, 0x0, 0x2f, 0xe7, - 0xfc, 0x3, 0xfd, 0xbf, 0x80, 0x7, 0xff, 0xff, - 0xc0, 0x3f, 0xff, 0xfd, 0x0, 0xff, 0xff, 0xe0, - 0x0, 0xbf, 0xff, 0xf0, 0x2f, 0xc2, 0xf0, 0x0, - 0x0, 0xf8, 0x3f, 0x83, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xfc, 0x3f, 0x40, 0x0, 0xbf, 0xe0, - 0x0, 0xf, 0xc3, 0xfe, 0x0, 0x3f, 0xff, 0xc0, - 0x7, 0xfc, 0xf, 0xfc, 0xb, 0xff, 0xfe, 0x2, - 0xff, 0x0, 0x2f, 0xc0, 0xff, 0xff, 0xf0, 0x3f, - 0xc0, 0x0, 0xfc, 0xf, 0xff, 0xff, 0x43, 0xf4, - 0x0, 0xf, 0xc0, 0xff, 0xff, 0xf4, 0x3f, 0x0, - 0x2, 0xfc, 0xf, 0xff, 0xff, 0x3, 0xf8, 0x0, - 0xff, 0x80, 0xbf, 0xff, 0xe0, 0x2f, 0xf0, 0x3f, - 0xd0, 0x3, 0xff, 0xfc, 0x0, 0x7f, 0xc3, 0xf4, - 0x0, 0xb, 0xfe, 0x0, 0x0, 0xfc, 0x3f, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc2, 0xfc, 0x2f, - 0x0, 0x0, 0xf, 0x83, 0xf8, 0xf, 0xff, 0xfe, - 0x0, 0xb, 0xff, 0xff, 0x0, 0x7f, 0xff, 0xfc, - 0x3, 0xff, 0xff, 0xd0, 0x2, 0xfe, 0x7f, 0xc0, - 0x3f, 0xdb, 0xf8, 0x0, 0x5, 0x0, 0xbd, 0x7, - 0xe0, 0x4, 0x0, 0x0, 0x0, 0xb, 0xd0, 0x7e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x40, 0x0, - 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 576, .box_w = 30, .box_h = 24, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 180, .adv_w = 576, .box_w = 24, .box_h = 24, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 324, .adv_w = 576, .box_w = 30, .box_h = 30, .ofs_x = 3, .ofs_y = 3} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_36 = { -#else -lv_font_t material_symbols_launcher_36 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 30, /*The maximum line height required by the font*/ - .base_line = -3, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_36*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_42.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_42.c deleted file mode 100644 index ce16f18b9..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_42.c +++ /dev/null @@ -1,220 +0,0 @@ -/******************************************************************************* - * Size: 42 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 42 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_42.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_42 -#define MATERIAL_SYMBOLS_LAUNCHER_42 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_42 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0xb, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xaa, 0xaa, 0xbf, 0xfa, - 0xaa, 0xaa, 0xaa, 0x40, 0xbf, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0xbf, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0x7f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, - - /* U+E5C3 "" */ - 0x1f, 0xd0, 0x0, 0xbe, 0x0, 0xb, 0xe0, 0x7f, - 0xf4, 0x3, 0xff, 0x80, 0x3f, 0xfc, 0xff, 0xfc, - 0xb, 0xff, 0xc0, 0x7f, 0xfd, 0xff, 0xfc, 0xb, - 0xff, 0xd0, 0x7f, 0xfe, 0xff, 0xfc, 0xb, 0xff, - 0xc0, 0x7f, 0xfd, 0x7f, 0xf4, 0x3, 0xff, 0x80, - 0x3f, 0xfc, 0x1f, 0xd0, 0x0, 0xbe, 0x0, 0xb, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xe0, 0x1, - 0xff, 0x0, 0xf, 0xf4, 0xbf, 0xf8, 0x3, 0xff, - 0xc0, 0x3f, 0xfc, 0xff, 0xfc, 0xb, 0xff, 0xc0, - 0x7f, 0xfd, 0xff, 0xfc, 0xb, 0xff, 0xc0, 0x7f, - 0xfe, 0xbf, 0xf8, 0x7, 0xff, 0xc0, 0x3f, 0xfd, - 0x3f, 0xf0, 0x3, 0xff, 0x40, 0x2f, 0xf8, 0xa, - 0x80, 0x0, 0x68, 0x0, 0x6, 0x90, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xd0, 0x0, 0xbe, 0x0, - 0xb, 0xe0, 0x7f, 0xf4, 0x3, 0xff, 0x80, 0x3f, - 0xfc, 0xff, 0xfc, 0xb, 0xff, 0xc0, 0x7f, 0xfd, - 0xff, 0xfc, 0xb, 0xff, 0xd0, 0x7f, 0xfe, 0xff, - 0xfc, 0xb, 0xff, 0xc0, 0x7f, 0xfd, 0x7f, 0xf4, - 0x3, 0xff, 0x80, 0x3f, 0xfc, 0x1f, 0xd0, 0x0, - 0xbe, 0x0, 0xb, 0xe0, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x6, 0xa9, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0x3, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x3f, - 0x40, 0x0, 0x0, 0x1, 0xfe, 0x7, 0xfc, 0x3, - 0xfd, 0xb, 0xf4, 0x0, 0x3f, 0xff, 0xff, 0xc0, - 0x3f, 0xff, 0xff, 0xc0, 0xf, 0xff, 0xff, 0xf8, - 0x2, 0xff, 0xff, 0xff, 0x1, 0xff, 0xff, 0xf8, - 0x0, 0x2, 0xff, 0xff, 0xf4, 0x3f, 0xc1, 0xbc, - 0x0, 0x0, 0x3, 0xe4, 0x3f, 0xc7, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbf, 0x0, - 0x0, 0xb, 0xfe, 0x0, 0x0, 0x1f, 0xe7, 0xfd, - 0x0, 0x3, 0xff, 0xfd, 0x0, 0x7, 0xfd, 0x3f, - 0xf8, 0x0, 0xff, 0xff, 0xf0, 0x2, 0xff, 0xc0, - 0xbf, 0xe0, 0x1f, 0xff, 0xff, 0x80, 0xbf, 0xe0, - 0x2, 0xfd, 0x3, 0xff, 0xff, 0xfc, 0xb, 0xf8, - 0x0, 0xf, 0xd0, 0x3f, 0xff, 0xff, 0xc0, 0x7f, - 0x0, 0x0, 0xfd, 0x3, 0xff, 0xff, 0xfc, 0x7, - 0xf0, 0x0, 0x2f, 0xd0, 0x3f, 0xff, 0xff, 0xc0, - 0xbf, 0x40, 0xb, 0xfe, 0x1, 0xff, 0xff, 0xf8, - 0xb, 0xfe, 0x3, 0xff, 0x80, 0xf, 0xff, 0xff, - 0x0, 0x2f, 0xfc, 0x7f, 0xd0, 0x0, 0x3f, 0xff, - 0xd0, 0x0, 0x7f, 0xdb, 0xf0, 0x0, 0x0, 0xbf, - 0xe0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xd3, 0xfc, 0x1b, 0xc0, - 0x0, 0x0, 0x3e, 0x43, 0xfc, 0x1f, 0xff, 0xff, - 0x40, 0x0, 0x1f, 0xff, 0xff, 0x40, 0xff, 0xff, - 0xff, 0x80, 0x2f, 0xff, 0xff, 0xe0, 0x3, 0xff, - 0xff, 0xfc, 0x3, 0xff, 0xff, 0xfc, 0x0, 0x1f, - 0xe0, 0x7f, 0xc0, 0x3f, 0xd0, 0xbf, 0x0, 0x0, - 0x0, 0x1, 0xfc, 0x3, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xc0, 0x3f, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6a, 0x90, 0x0, - 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 672, .box_w = 36, .box_h = 28, .ofs_x = 3, .ofs_y = 7}, - {.bitmap_index = 252, .adv_w = 672, .box_w = 28, .box_h = 28, .ofs_x = 7, .ofs_y = 7}, - {.bitmap_index = 448, .adv_w = 672, .box_w = 34, .box_h = 36, .ofs_x = 4, .ofs_y = 3} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_42 = { -#else -lv_font_t material_symbols_launcher_42 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 36, /*The maximum line height required by the font*/ - .base_line = -3, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_42*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_48.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_48.c deleted file mode 100644 index bfdc63c76..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_48.c +++ /dev/null @@ -1,246 +0,0 @@ -/******************************************************************************* - * Size: 48 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 48 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_48.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_48 -#define MATERIAL_SYMBOLS_LAUNCHER_48 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_48 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0xb, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xff, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+E5C3 "" */ - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x40, 0x2f, - 0xe0, 0xb, 0xf8, 0x1, 0xb4, 0x0, 0x0, 0xff, - 0xf9, 0xff, 0xe0, 0xb, 0xff, 0x6f, 0xff, 0x0, - 0x2, 0xff, 0xff, 0xff, 0xd0, 0x7, 0xff, 0xff, - 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0x80, 0x2, - 0xff, 0xff, 0xff, 0xc0, 0xb, 0xfd, 0xff, 0xf4, - 0x0, 0x0, 0x1f, 0xff, 0x7f, 0xe0, 0xf, 0xf4, - 0x1b, 0xc0, 0x0, 0x0, 0x3, 0xe4, 0x1f, 0xf0, - 0x2f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3f, 0xd0, 0x0, 0x0, 0x2f, 0xf8, - 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xf4, 0x0, 0x1, - 0xff, 0xff, 0x40, 0x0, 0x1f, 0xfc, 0x2f, 0xfe, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0xbf, 0xf8, - 0xb, 0xff, 0xc0, 0xf, 0xff, 0xff, 0xf0, 0x3, - 0xff, 0xe0, 0x1, 0xff, 0xd0, 0x1f, 0xff, 0xff, - 0xf8, 0x7, 0xff, 0x40, 0x0, 0x7f, 0xc0, 0x2f, - 0xff, 0xff, 0xfc, 0x3, 0xfd, 0x0, 0x0, 0x3f, - 0xc0, 0x3f, 0xff, 0xff, 0xfc, 0x3, 0xfc, 0x0, - 0x0, 0x3f, 0xc0, 0x3f, 0xff, 0xff, 0xfc, 0x3, - 0xfc, 0x0, 0x0, 0x7f, 0xc0, 0x2f, 0xff, 0xff, - 0xfc, 0x3, 0xfc, 0x0, 0x1, 0xff, 0xd0, 0x1f, - 0xff, 0xff, 0xf8, 0x7, 0xff, 0x40, 0xb, 0xff, - 0xc0, 0xf, 0xff, 0xff, 0xf0, 0x3, 0xff, 0xe0, - 0x2f, 0xfe, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0xbf, 0xf4, 0x3f, 0xf4, 0x0, 0x1, 0xff, 0xff, - 0x40, 0x0, 0x1f, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, - 0xf, 0xf4, 0x1b, 0xc0, 0x0, 0x0, 0x3, 0xe4, - 0x1f, 0xf0, 0xb, 0xfd, 0xff, 0xf4, 0x0, 0x0, - 0x1f, 0xff, 0x7f, 0xe0, 0x3, 0xff, 0xff, 0xff, - 0x80, 0x2, 0xff, 0xff, 0xff, 0xc0, 0x2, 0xff, - 0xff, 0xff, 0xd0, 0x7, 0xff, 0xff, 0xff, 0x40, - 0x0, 0xff, 0xf9, 0xff, 0xe0, 0xb, 0xff, 0x6f, - 0xfe, 0x0, 0x0, 0x2e, 0x40, 0x2f, 0xe0, 0xb, - 0xf8, 0x1, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 320, .adv_w = 768, .box_w = 32, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 576, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_48 = { -#else -lv_font_t material_symbols_launcher_48 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 40, /*The maximum line height required by the font*/ - .base_line = -4, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_48*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_64.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_64.c deleted file mode 100644 index 52054873b..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_64.c +++ /dev/null @@ -1,348 +0,0 @@ -/******************************************************************************* - * Size: 64 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 64 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_64.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_64 -#define MATERIAL_SYMBOLS_LAUNCHER_64 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_64 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x8f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x5f, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x54, 0x0, - - /* U+E5C3 "" */ - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfc, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xfd, - 0x0, 0x7f, 0xfc, 0x0, 0x3f, 0xfd, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x3f, 0xff, 0xe3, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xcb, 0xff, 0xfc, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x3, 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, - 0x6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xb, 0xff, - 0xaf, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xfa, 0xff, 0xe0, 0xf, 0xff, 0x1, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0x40, 0xff, 0xf0, - 0x2f, 0xfe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xe4, 0x0, 0xbf, 0xf8, 0x3f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfc, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x6, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x7f, - 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x3f, 0xfd, 0x3f, 0xff, 0x40, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x80, 0x0, 0x1, 0xff, - 0xfc, 0x2f, 0xff, 0xe0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0xb, 0xff, 0xf8, 0xb, 0xff, - 0xfc, 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x3f, 0xff, 0xe0, 0x1, 0xff, 0xff, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0xff, 0xff, 0x40, - 0x0, 0x7f, 0xfe, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0xbf, 0xfd, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, - 0xf0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xf0, 0x0, 0x0, - 0xf, 0xfd, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x7f, 0xf0, 0x0, 0x0, 0xf, 0xfd, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xf0, - 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xfc, 0x0, 0xbf, 0xf8, 0x0, 0x0, 0xff, - 0xfe, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0xbf, 0xfe, 0x0, 0x7, 0xff, 0xfe, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0xbf, 0xff, 0xc0, - 0xf, 0xff, 0xf4, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xc0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x3, - 0xff, 0xfc, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xbf, 0xfc, 0x7f, - 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x1f, 0xfd, 0x7f, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x59, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xfc, 0x3f, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x40, 0x0, 0x7f, 0xfc, 0x1f, 0xff, - 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x2, 0xfd, - 0x0, 0xff, 0xf4, 0xf, 0xff, 0x4b, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xe1, 0xff, 0xe0, - 0x3, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xff, 0xc0, 0x2, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x7f, 0xff, 0xfb, 0xff, 0xf8, 0x0, 0x2f, 0xff, - 0xef, 0xff, 0xfd, 0x0, 0x0, 0x1f, 0xff, 0x40, - 0xff, 0xfc, 0x0, 0x3f, 0xff, 0x1, 0xff, 0xf4, - 0x0, 0x0, 0x2, 0xa0, 0x0, 0x2f, 0xfc, 0x0, - 0x3f, 0xf8, 0x0, 0x1a, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfc, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x55, 0xbf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 594, .adv_w = 1024, .box_w = 44, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 1078, .adv_w = 1024, .box_w = 52, .box_h = 54, .ofs_x = 6, .ofs_y = 5} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_64 = { -#else -lv_font_t material_symbols_launcher_64 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 54, /*The maximum line height required by the font*/ - .base_line = -5, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_64*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_launcher_72.c b/Modules/lvgl-module/source-fonts/material_symbols_launcher_72.c deleted file mode 100644 index ee936c791..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_launcher_72.c +++ /dev/null @@ -1,397 +0,0 @@ -/******************************************************************************* - * Size: 72 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 72 --font MaterialSymbolsRounded.ttf -r 0xE5C3,0xE2C7,0xE8B8 --format lvgl -o source-fonts/material_symbols_launcher_72.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_LAUNCHER_72 -#define MATERIAL_SYMBOLS_LAUNCHER_72 1 -#endif - -#if MATERIAL_SYMBOLS_LAUNCHER_72 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E2C7 "" */ - 0x1, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x40, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, - - /* U+E5C3 "" */ - 0x1, 0xff, 0x40, 0x0, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0x1, 0xff, 0x40, 0xf, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x3f, 0xff, 0xfc, 0x0, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0x3f, 0xff, 0xfc, 0x7f, 0xff, 0xfd, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x7f, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xfd, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x7f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, 0x0, - 0x3, 0xff, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xfc, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0xf, 0xff, 0xf0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x1, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 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, 0xff, 0x40, 0x0, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0x1, 0xff, 0x40, 0xf, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x3f, 0xff, 0xfc, 0x0, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0x3f, 0xff, 0xfc, 0x7f, 0xff, 0xfd, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x7f, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xfd, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x7f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, 0x0, - 0x3, 0xff, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xfc, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0xf, 0xff, 0xf0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x1, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 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, 0xff, 0x40, 0x0, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0x1, 0xff, 0x40, 0xf, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x3f, 0xff, 0xfc, 0x0, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0x3f, 0xff, 0xfc, 0x7f, 0xff, 0xfd, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x7f, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xfd, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x7f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, 0x0, - 0x3, 0xff, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xfc, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0xf, 0xff, 0xf0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x1, 0xff, 0x40, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xc0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0xf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xf8, 0x0, 0x3f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xa8, - 0x0, 0x3, 0xff, 0xd0, 0x0, 0xff, 0xf4, 0x0, - 0x6, 0xe4, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x40, - 0x7f, 0xff, 0x40, 0x2, 0xff, 0xfc, 0x2, 0xff, - 0xf8, 0x0, 0x0, 0x3, 0xff, 0xff, 0xef, 0xff, - 0xfc, 0x0, 0xb, 0xff, 0xfe, 0xbf, 0xff, 0xfc, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xe4, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xef, 0xff, 0xc0, 0x3, 0xff, 0xf0, 0x6f, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x2, 0xff, 0xf8, - 0x1f, 0xff, 0x80, 0x2f, 0xff, 0x40, 0xb, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xfd, 0x0, 0x2f, - 0xff, 0x41, 0xff, 0xf8, 0x0, 0x1, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x3f, 0xff, - 0xb, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x15, - 0x40, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfc, 0x3f, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xf4, 0xbf, 0xfe, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xc1, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x2, 0xff, 0xff, 0x3, 0xff, 0xff, 0x40, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x3f, - 0xff, 0xf4, 0x3, 0xff, 0xff, 0x80, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x7, 0xff, 0xff, - 0x80, 0x3, 0xff, 0xff, 0xc0, 0x2, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x3f, 0xff, 0xf4, 0x0, - 0x2, 0xff, 0xfe, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0xff, 0xff, 0x40, 0x0, 0x1, - 0xff, 0xf4, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x3, 0xff, 0xe0, 0x0, 0x0, 0x2, 0xff, - 0xd0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, - 0xf, 0xff, 0x0, 0x0, 0x0, 0xb, 0xff, 0x40, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x3f, - 0xfd, 0x0, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0xbf, 0xf4, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x3, 0xff, 0xc0, 0x0, - 0x0, 0x7, 0xff, 0xd0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, - 0xbf, 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0xf, 0xff, - 0xff, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0xff, 0xff, 0xd0, 0x0, 0xff, 0xff, 0xe0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1, - 0xff, 0xff, 0xe0, 0xf, 0xff, 0xfd, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0xd0, 0x7f, 0xff, 0xc0, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xc2, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xf, - 0xff, 0x80, 0x0, 0x0, 0x0, 0xb, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x2f, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xf0, 0x7f, 0xfe, 0x0, - 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, - 0x0, 0xf, 0xff, 0x80, 0xbf, 0xfd, 0x0, 0x2f, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf4, 0x0, - 0xbf, 0xfc, 0x0, 0xff, 0xfc, 0x1b, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x7, 0xff, - 0xe0, 0x2, 0xff, 0xfb, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xbf, 0xff, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x7, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xbf, 0xff, 0xf0, 0x0, 0x2f, 0xff, 0xfa, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x1f, 0xff, 0xd0, 0x1f, - 0xff, 0xc0, 0x0, 0xbf, 0xff, 0x0, 0xbf, 0xfe, - 0x0, 0x0, 0x0, 0x6, 0xa0, 0x0, 0xf, 0xff, - 0x40, 0x3, 0xff, 0xd0, 0x0, 0x1b, 0x90, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfd, 0x0, - 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x3f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 1152, .box_w = 60, .box_h = 48, .ofs_x = 6, .ofs_y = 12}, - {.bitmap_index = 720, .adv_w = 1152, .box_w = 48, .box_h = 48, .ofs_x = 12, .ofs_y = 12}, - {.bitmap_index = 1296, .adv_w = 1152, .box_w = 59, .box_h = 60, .ofs_x = 6, .ofs_y = 6} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x2fc, 0x5f1 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 58055, .range_length = 1522, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_launcher_72 = { -#else -lv_font_t material_symbols_launcher_72 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 60, /*The maximum line height required by the font*/ - .base_line = -6, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_LAUNCHER_72*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_12.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_12.c deleted file mode 100644 index cd1c3b0fd..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_12.c +++ /dev/null @@ -1,415 +0,0 @@ -/******************************************************************************* - * Size: 12 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 12 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_12.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_12 -#define MATERIAL_SYMBOLS_SHARED_12 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_12 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x2, 0x40, 0x2, 0x40, 0x17, 0x54, - 0x6b, 0xe8, 0x2, 0x40, 0x2, 0x40, 0x1, 0x0, - - /* U+E159 "" */ - 0xff, 0xff, 0xfe, 0x0, 0xb, 0xdd, 0x7, 0x7c, - 0x2f, 0x83, 0xc0, 0x0, 0x3c, 0x0, 0x3, 0xc0, - 0x0, 0x3f, 0xff, 0xff, - - /* U+E1A7 "" */ - 0x1, 0x40, 0xb, 0x47, 0x2b, 0x7, 0xec, 0x7, - 0xc0, 0x1f, 0x1, 0xfb, 0x1c, 0x9d, 0x2, 0xd0, - 0x9, 0x0, - - /* U+E1E0 "" */ - 0x2, 0x0, 0x7, 0x80, 0x3, 0x0, 0x73, 0x3c, - 0xb3, 0x3c, 0x33, 0x18, 0x3f, 0xf4, 0x3, 0x0, - 0x3, 0x40, 0x3, 0x40, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x2, 0xf0, 0x0, 0xc, 0xc0, - 0x0, 0x33, 0x0, 0x0, 0xcc, 0x0, 0x1b, 0xba, - 0x42, 0xaa, 0xab, 0x9, 0x55, 0x5c, 0x3a, 0xaa, - 0xb4, 0xc4, 0x85, 0xa6, 0x67, 0x69, 0x8a, 0xaa, - 0xa9, - - /* U+E2C7 "" */ - 0xff, 0x40, 0xc, 0xf, 0xff, 0xc0, 0x0, 0x3c, - 0x0, 0x3, 0xc0, 0x0, 0x3c, 0x0, 0x3, 0xc0, - 0x0, 0x3f, 0xff, 0xff, - - /* U+E30F "" */ - 0x2, 0xf0, 0x0, 0x26, 0x40, 0x2, 0x74, 0x1, - 0xe, 0x4, 0xed, 0xb, 0xbd, 0xb0, 0xd7, 0xa8, - 0xe2, 0xa0, 0x2b, 0x0, 0x2, 0x64, 0x0, 0x2f, - 0x0, - - /* U+E316 "" */ - 0x5, 0x1, 0xf8, 0x70, 0xd4, 0x1, - - /* U+E326 "" */ - 0x7f, 0xff, 0xda, 0x0, 0x0, 0xa0, 0xf, 0xfa, - 0x0, 0xc3, 0xa0, 0xc, 0x37, 0xa4, 0xc3, 0x1a, - 0x4c, 0x3f, 0xfc, 0xff, - - /* U+E3AF "" */ - 0x6, 0xf9, 0x2, 0xd2, 0x78, 0x74, 0x50, 0xd9, - 0x8e, 0xaa, 0xc3, 0xf4, 0x3c, 0x1f, 0xc3, 0xaa, - 0xb2, 0x67, 0x5, 0x1d, 0x2d, 0x87, 0x80, 0x6f, - 0x90, - - /* U+E3F4 "" */ - 0x15, 0x55, 0xb, 0xaa, 0xac, 0x90, 0x0, 0xc9, - 0x0, 0xc, 0x90, 0x0, 0xc9, 0x1, 0xc, 0x97, - 0x3c, 0xc9, 0xaa, 0x8c, 0x95, 0x55, 0xc6, 0xaa, - 0xa8, - - /* U+E405 "" */ - 0x0, 0x40, 0x3f, 0x3, 0xa0, 0x30, 0x3, 0x0, - 0x30, 0xbf, 0xf, 0xf0, 0xff, 0x2, 0x80, - - /* U+E55D "" */ - 0x0, 0x0, 0x2, 0x80, 0x3, 0xc0, 0xa, 0xa0, - 0xc, 0x30, 0x18, 0x24, 0x30, 0xc, 0x77, 0xdd, - 0xf8, 0x2f, 0x40, 0x1, - - /* U+E5C3 "" */ - 0xf3, 0xcf, 0xf3, 0xcf, 0x0, 0x0, 0xf3, 0xcf, - 0xf3, 0xcf, 0x0, 0x0, 0xf3, 0xcf, 0xf3, 0xcf, - - /* U+E5CD "" */ - 0x10, 0x0, 0x34, 0x1c, 0xd, 0x70, 0x3, 0xc0, - 0x7, 0xd0, 0x1c, 0x34, 0x30, 0xc, 0x0, 0x0, - - /* U+E5D2 "" */ - 0xbf, 0xff, 0xc0, 0x0, 0x0, 0x15, 0x55, 0x46, - 0xaa, 0xa8, 0x0, 0x0, 0xb, 0xff, 0xfc, - - /* U+E5D4 "" */ - 0xff, 0xf, 0xf0, 0xff, - - /* U+E5D5 "" */ - 0xb, 0xe3, 0x34, 0x2f, 0x90, 0x1b, 0xc0, 0x6a, - 0xc0, 0x0, 0x90, 0x5, 0x34, 0x1c, 0xb, 0xe0, - - /* U+E63E "" */ - 0x6, 0xff, 0x80, 0x2f, 0xaa, 0xf8, 0xb4, 0x0, - 0x2d, 0x1, 0xfe, 0x40, 0xb, 0xeb, 0xd0, 0x0, - 0x0, 0x40, 0x0, 0x3c, 0x0, 0x0, 0x7c, 0x0, - 0x0, 0x14, 0x0, - - /* U+E668 "" */ - 0x0, 0x2, 0x0, 0xd, 0x0, 0x34, 0xa0, 0xd0, - 0x2b, 0x40, 0x9, 0x0, - - /* U+E745 "" */ - 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, - 0x4, 0xfd, 0xb, 0xc0, 0xa, 0xd0, 0x9, 0x90, - 0x2, 0xd0, - - /* U+E770 "" */ - 0x0, 0xa0, 0x0, 0x2a, 0xd0, 0x57, 0x6, 0xcb, - 0xd0, 0xc, 0x94, 0x90, 0xc9, 0x1f, 0x8c, 0xbb, - 0xff, 0xcb, 0xff, 0xfc, 0x0, 0x0, 0x0, - - /* U+E89C "" */ - 0xff, 0xd0, 0xc0, 0xb8, 0xc0, 0xbd, 0xc0, 0x2b, - 0xc1, 0x43, 0xc6, 0x93, 0xc6, 0x93, 0xc1, 0x43, - 0xc0, 0x3, 0xff, 0xff, - - /* U+E8AF "" */ - 0xff, 0xfc, 0xc, 0x0, 0x90, 0xc0, 0x9, 0x6c, - 0x0, 0x9b, 0xc5, 0x5d, 0xbf, 0xaa, 0x8b, 0x8a, - 0xaa, 0xf0, 0xff, 0xff, 0x0, 0x0, 0xb0, 0x0, - 0x0, - - /* U+E8B8 "" */ - 0x1, 0xf4, 0x1, 0x25, 0x84, 0x7e, 0xb, 0xda, - 0xa, 0xa, 0x36, 0xf9, 0xc3, 0x2f, 0x9c, 0xa0, - 0xa0, 0xa7, 0xe0, 0xbd, 0x12, 0x58, 0x40, 0x1f, - 0x40, - - /* U+E8FD "" */ - 0x6, 0xf9, 0x2, 0xd0, 0x78, 0x70, 0xf4, 0xd9, - 0x1, 0x86, 0xc0, 0x24, 0x3c, 0x6, 0x3, 0x90, - 0x0, 0x67, 0x9, 0xd, 0x2d, 0x7, 0x80, 0x6f, - 0x90, - - /* U+E90F "" */ - 0xb, 0xe0, 0x34, 0x1c, 0xa0, 0xa, 0x90, 0x6, - 0x90, 0x6, 0x70, 0xd, 0x1f, 0xf4, 0x6, 0x90, - 0x6, 0x90, 0x3, 0xc0, - - /* U+E92E "" */ - 0x2, 0x80, 0xff, 0xff, 0xa0, 0xa, 0xa5, 0x5a, - 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, - 0x65, 0x59, 0x2a, 0xa8, - - /* U+E9B9 "" */ - 0xf3, 0xff, 0xff, 0x3f, 0xff, 0x0, 0x0, 0xf, - 0x3f, 0xff, 0xf3, 0xff, 0xf0, 0x0, 0x0, 0xf3, - 0xff, 0xff, 0x3f, 0xff, - - /* U+E9F4 "" */ - 0x0, 0x7c, 0x0, 0x0, 0x9c, 0x0, 0x0, 0x38, - 0x0, 0x74, 0x20, 0x1d, 0xdc, 0xbd, 0x37, 0xbb, - 0xc3, 0xae, 0x1, 0x83, 0x0, 0x0, 0xea, 0x0, - 0x1, 0xab, 0x40, 0x1f, 0x2, 0xf4, 0x1b, 0x2, - 0xa4, 0xa, 0x0, 0xa0, - - /* U+E9F7 "" */ - 0x15, 0x55, 0x7, 0xaa, 0xac, 0xa0, 0x0, 0x9b, - 0xff, 0xfd, 0xa0, 0x0, 0x9a, 0x0, 0x9, 0xa0, - 0x0, 0x9a, 0x0, 0x9, 0x65, 0x55, 0xd2, 0xaa, - 0xa8, - - /* U+EA07 "" */ - 0x6, 0xf9, 0x2, 0xea, 0xb8, 0x73, 0x1c, 0xdb, - 0xff, 0xfe, 0xc3, 0xc, 0x3c, 0x30, 0xc3, 0xbf, - 0xff, 0xe7, 0x31, 0xcd, 0x2e, 0xab, 0x80, 0x6f, - 0x90, - - /* U+EAD6 "" */ - 0x15, 0x55, 0x7, 0xaa, 0xac, 0xa0, 0x0, 0x9a, - 0x4, 0x9, 0xa6, 0x86, 0x9a, 0x68, 0xd9, 0xa9, - 0x94, 0x9a, 0x0, 0x9, 0x65, 0x55, 0xd2, 0xaa, - 0xa8, - - /* U+EB8E "" */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x3c, - 0xa0, 0x3, 0xc3, 0x40, 0x3c, 0xa1, 0x93, 0xc0, - 0x19, 0x3f, 0xff, 0xff, - - /* U+EB97 "" */ - 0x15, 0x55, 0x4e, 0xaa, 0xab, 0xc0, 0x0, 0x3c, - 0xaa, 0x63, 0xc1, 0x0, 0x3c, 0xdf, 0xf3, 0xc1, - 0x0, 0x3d, 0x55, 0x57, 0x6b, 0xfe, 0x90, 0x2a, - 0x80, - - /* U+EBCC "" */ - 0x8, 0x2, 0x7, 0xff, 0xfc, 0x90, 0x0, 0xcb, - 0xff, 0xfc, 0x90, 0x0, 0xc9, 0x88, 0x8c, 0x90, - 0x0, 0xc9, 0x88, 0x8c, 0x90, 0x0, 0xc7, 0xff, - 0xfc, - - /* U+EC1C "" */ - 0x0, 0x30, 0x0, 0xe0, 0x3, 0xc0, 0xf, 0xc0, - 0x36, 0xfe, 0xbf, 0x9c, 0x3, 0xf0, 0x3, 0xc0, - 0xb, 0x0, 0xc, 0x0, - - /* U+EF40 "" */ - 0xf3, 0xcf, 0x3c, 0xf3, 0xc0, 0x0, 0x3, 0xcf, - 0x4, 0xf3, 0xcb, 0xc0, 0xa, 0xef, 0x6, 0xa3, - 0xc1, 0xe0, - - /* U+EF4A "" */ - 0x6, 0xf9, 0x2, 0xd0, 0x78, 0x70, 0x0, 0xd9, - 0x0, 0x6, 0xc0, 0x0, 0x3c, 0x0, 0x3, 0x90, - 0x0, 0x67, 0x0, 0xd, 0x2d, 0x7, 0x80, 0x6f, - 0x90, - - /* U+EF7A "" */ - 0x0, 0x0, 0x2, 0xfe, 0x0, 0x70, 0x34, 0x9, - 0x1, 0x80, 0x90, 0x18, 0x3, 0x47, 0x40, 0x1f, - 0xec, 0x0, 0x0, 0x70, 0x0, 0x1, 0xc0, 0x0, - 0x0, - - /* U+EFE6 "" */ - 0x0, 0x1, 0x1, 0xf8, 0x78, 0x24, 0xcf, 0xc2, - 0x4c, 0xfc, 0x24, 0xc3, 0x2, 0x4c, 0x30, 0x7c, - 0xc3, 0xb, 0xdc, 0x30, 0x7c, 0xa7, 0x2, 0x42, - 0x80, - - /* U+F028 "" */ - 0x7f, 0xff, 0xfc, 0x90, 0x0, 0xc, 0x98, 0x88, - 0x8c, 0x90, 0x0, 0xc, 0x98, 0x88, 0x8c, 0x90, - 0x54, 0xc, 0x90, 0x54, 0xc, 0x7f, 0xff, 0xfc, - - /* U+F090 "" */ - 0x2, 0x0, 0x2, 0x40, 0x2, 0x40, 0x1a, 0x70, - 0xb, 0xd0, 0x42, 0x41, 0xc0, 0x3, 0xff, 0xff, - - /* U+F15C "" */ - 0x0, 0xbd, 0x0, 0x3, 0x43, 0x40, 0x9, 0x0, - 0xc0, 0x38, 0x0, 0xd0, 0xa0, 0x0, 0x68, 0x90, - 0x0, 0xc, 0x70, 0x0, 0xc, 0x1f, 0xff, 0xf4, - - /* U+F720 "" */ - 0x1, 0xe0, 0x7, 0x8b, 0x47, 0x40, 0x3a, 0xf0, - 0x2f, 0x97, 0xb4, 0xe4, 0x30, 0x39, 0xc, 0xd, - 0xd3, 0xe, 0x1e, 0xed, 0x0, 0xb8, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x80, 0x0, 0x9, 0x0, 0x70, 0x91, 0xcd, - 0x9, 0xd, 0xc0, 0x90, 0xac, 0x4, 0x6, 0xd0, - 0x0, 0x97, 0x0, 0x1c, 0x2c, 0x7, 0x0, 0x7f, - 0x80, - - /* U+FFF75 "󿽵" */ - 0xff, 0xff, 0xec, 0x41, 0x13, 0xd5, 0x55, 0x7a, - 0xaf, 0xef, 0xb, 0xd1, 0x3b, 0x81, 0x2e, 0xd5, - 0x7f, 0x5e, 0xaa, 0xab, 0xc4, 0x11, 0x3b, 0xff, - 0xff -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 16, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 36, .adv_w = 192, .box_w = 7, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 54, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 74, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 107, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 127, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 152, .adv_w = 192, .box_w = 6, .box_h = 4, .ofs_x = 3, .ofs_y = 4}, - {.bitmap_index = 158, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 178, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 203, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 228, .adv_w = 192, .box_w = 6, .box_h = 10, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 243, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 263, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 279, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 295, .adv_w = 192, .box_w = 10, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 310, .adv_w = 192, .box_w = 2, .box_h = 8, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 314, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 330, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 357, .adv_w = 192, .box_w = 8, .box_h = 6, .ofs_x = 2, .ofs_y = 3}, - {.bitmap_index = 369, .adv_w = 192, .box_w = 9, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 387, .adv_w = 192, .box_w = 10, .box_h = 9, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 410, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 430, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 455, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 480, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 505, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 525, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 545, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 565, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 601, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 626, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 651, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 676, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 696, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 721, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 746, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 766, .adv_w = 192, .box_w = 9, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 784, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 809, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 834, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 859, .adv_w = 192, .box_w = 12, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 883, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 899, .adv_w = 192, .box_w = 12, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 923, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 946, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 971, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_12 = { -#else -lv_font_t material_symbols_shared_12 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 12, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_12*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_16.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_16.c deleted file mode 100644 index 6e9205b61..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_16.c +++ /dev/null @@ -1,521 +0,0 @@ -/******************************************************************************* - * Size: 16 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 16 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_16.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_16 -#define MATERIAL_SYMBOLS_SHARED_16 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_16 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0xe0, 0x0, - 0xe, 0x0, 0x15, 0xf5, 0x4b, 0xff, 0xfd, 0x0, - 0xe0, 0x0, 0xe, 0x0, 0x0, 0xe0, 0x0, 0x9, - 0x0, - - /* U+E159 "" */ - 0x15, 0x55, 0x55, 0xb, 0xff, 0xff, 0xfd, 0xf4, - 0x0, 0x2, 0xde, 0xe0, 0x1, 0xed, 0xd2, 0xd0, - 0xf4, 0xdd, 0x7, 0xf8, 0xd, 0xd0, 0x4, 0x0, - 0xdd, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, 0xdd, - 0x0, 0x0, 0xd, 0xbf, 0xff, 0xff, 0xd1, 0x55, - 0x55, 0x50, - - /* U+E1A7 "" */ - 0x0, 0x40, 0x0, 0x3c, 0x1, 0xf, 0xc1, 0xd3, - 0x6c, 0x1d, 0xef, 0x1, 0xff, 0x0, 0x1f, 0x0, - 0xf, 0xd0, 0xf, 0xfd, 0xf, 0x36, 0xcb, 0xe, - 0xe0, 0x3, 0xe0, 0x0, 0xe0, 0x0, 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0xe, 0x0, 0x2, 0xf0, 0x0, - 0xe, 0x0, 0x10, 0xd1, 0x5b, 0xcd, 0x3e, 0x78, - 0xd3, 0xe3, 0x4d, 0x1c, 0x39, 0xe6, 0xc2, 0xff, - 0xf4, 0x0, 0xd0, 0x0, 0xe, 0x0, 0x1, 0xf0, - 0x0, 0xe, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, - 0x0, 0xd, 0x70, 0x0, 0x0, 0xd, 0x70, 0x0, - 0x0, 0xd, 0x70, 0x0, 0x0, 0xd, 0x70, 0x0, - 0x0, 0xd, 0x70, 0x0, 0x6, 0xaf, 0xfa, 0x90, - 0xf, 0xaa, 0xaa, 0xf0, 0xd, 0x0, 0x0, 0x70, - 0xf, 0xff, 0xff, 0xf0, 0x1d, 0x55, 0x55, 0x74, - 0x28, 0xc2, 0x83, 0x28, 0x34, 0xd2, 0x87, 0x1c, - 0x3f, 0xff, 0xff, 0xfc, 0x5, 0x55, 0x55, 0x50, - - /* U+E2C7 "" */ - 0x15, 0x40, 0x0, 0xb, 0xff, 0x40, 0x0, 0xd0, - 0x2f, 0xff, 0xcd, 0x0, 0x55, 0x5d, 0xd0, 0x0, - 0x0, 0xdd, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, - 0xdd, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, 0xdd, - 0x0, 0x0, 0xd, 0xbf, 0xff, 0xff, 0xd1, 0x55, - 0x55, 0x50, - - /* U+E30F "" */ - 0x0, 0x15, 0x40, 0x0, 0x3, 0xfc, 0x0, 0x0, - 0x31, 0xc0, 0x0, 0x3, 0x2c, 0x0, 0x0, 0x3f, - 0x80, 0xf, 0xf4, 0xe2, 0xfd, 0xe6, 0xd0, 0xb5, - 0xde, 0x6d, 0xb, 0x5d, 0xff, 0x44, 0x2f, 0xd0, - 0x2, 0xf0, 0x0, 0x0, 0x36, 0xc0, 0x0, 0x3, - 0x1c, 0x0, 0x0, 0x3a, 0xc0, 0x0, 0x3, 0xf8, - 0x0, - - /* U+E316 "" */ - 0x0, 0x0, 0x7, 0xc0, 0x1e, 0xb0, 0x78, 0x2c, - 0xa0, 0xa, - - /* U+E326 "" */ - 0x5, 0x55, 0x55, 0x3, 0xff, 0xff, 0xfc, 0x34, - 0x0, 0x0, 0x3, 0x40, 0x1, 0x54, 0x34, 0x0, - 0xff, 0xd3, 0x40, 0xd, 0x4d, 0x34, 0x0, 0xd0, - 0xd3, 0x40, 0xd, 0xd, 0x3f, 0xfc, 0xd0, 0xd0, - 0x55, 0xd, 0xd, 0xbf, 0xfc, 0xff, 0xd1, 0x55, - 0x1, 0x54, - - /* U+E3AF "" */ - 0x0, 0x15, 0x40, 0x0, 0x1f, 0xff, 0x40, 0xb, - 0x42, 0x2e, 0x2, 0xd0, 0x50, 0x34, 0x36, 0xc, - 0x1, 0xcb, 0x1a, 0xfe, 0xad, 0xa0, 0xbf, 0xc0, - 0xea, 0x3, 0xfd, 0xe, 0xba, 0xbf, 0x60, 0xd7, - 0x0, 0x30, 0x9c, 0x3c, 0x9, 0xb, 0x80, 0xf4, - 0x80, 0xf0, 0x3, 0xfa, 0xfc, 0x0, 0x6, 0xf9, - 0x0, - - /* U+E3F4 "" */ - 0xbf, 0xff, 0xfe, 0xe5, 0x55, 0x5b, 0xd0, 0x0, - 0x7, 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xd0, - 0x0, 0x7, 0xd0, 0x2, 0x7, 0xd2, 0x8b, 0x87, - 0xd7, 0xef, 0xd7, 0xd1, 0x55, 0x47, 0xe5, 0x55, - 0x5b, 0xbf, 0xff, 0xfe, - - /* U+E405 "" */ - 0x0, 0xff, 0x0, 0xff, 0x0, 0xfa, 0x0, 0xd0, - 0x0, 0xd0, 0x0, 0xd0, 0x4, 0xd0, 0x3f, 0xd0, - 0xff, 0xd0, 0xff, 0xd0, 0xbf, 0xc0, 0x2f, 0x0, - - /* U+E55D "" */ - 0x0, 0x14, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x7d, - 0x0, 0x0, 0xeb, 0x0, 0x1, 0xc3, 0x40, 0x2, - 0x82, 0x80, 0x3, 0x41, 0xc0, 0xb, 0x0, 0xe0, - 0xd, 0x14, 0x70, 0x2d, 0xff, 0x78, 0x3f, 0x82, - 0xfc, 0x34, 0x0, 0x1c, - - /* U+E5C3 "" */ - 0x14, 0x14, 0x14, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, - 0x3c, 0x0, 0x0, 0x0, 0x14, 0x14, 0x14, 0x3d, - 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 0x0, 0x0, 0x0, - 0x14, 0x14, 0x14, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, - 0x3c, 0x0, 0x0, 0x0, - - /* U+E5CD "" */ - 0x20, 0x0, 0x43, 0xc0, 0x1d, 0xf, 0x7, 0x40, - 0x3e, 0xd0, 0x0, 0xf4, 0x0, 0x1f, 0xc0, 0x7, - 0x4f, 0x1, 0xd0, 0x3c, 0x34, 0x0, 0xd0, 0x0, - 0x0, - - /* U+E5D2 "" */ - 0xff, 0xff, 0xff, 0x15, 0x55, 0x54, 0x0, 0x0, - 0x0, 0x55, 0x55, 0x55, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x15, 0x55, 0x54, 0xff, 0xff, 0xff, - - /* U+E5D4 "" */ - 0x14, 0x3d, 0x3c, 0x0, 0x14, 0x3d, 0x3c, 0x0, - 0x14, 0x3d, 0x3c, 0x0, - - /* U+E5D5 "" */ - 0x0, 0x14, 0x0, 0x2, 0xff, 0x8d, 0xf, 0x41, - 0xfd, 0x2c, 0x0, 0x3d, 0x34, 0x3, 0xfd, 0x70, - 0x1, 0x54, 0x70, 0x0, 0x0, 0x34, 0x0, 0x4, - 0x2c, 0x0, 0x38, 0xf, 0x41, 0xf0, 0x2, 0xff, - 0x80, 0x0, 0x14, 0x0, - - /* U+E63E "" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x0, - 0xf, 0xff, 0xff, 0xe0, 0x7f, 0x40, 0x6, 0xfc, - 0xb8, 0x0, 0x0, 0x3d, 0x0, 0x7f, 0xf8, 0x0, - 0x2, 0xff, 0xff, 0x40, 0x2, 0xd0, 0xb, 0x40, - 0x0, 0x1, 0x0, 0x0, 0x0, 0xb, 0xc0, 0x0, - 0x0, 0xf, 0xd0, 0x0, 0x0, 0x7, 0xc0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x8, 0x0, 0x0, 0x3c, 0x0, 0x0, - 0xf0, 0x10, 0x3, 0xc0, 0x38, 0xf, 0x0, 0xe, - 0x3c, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x80, 0x0, - - /* U+E745 "" */ - 0x15, 0x55, 0x0, 0xf, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x55, 0x54, 0x0, 0x3f, 0xff, 0x0, - 0x0, 0x0, 0x1, 0x43, 0xfd, 0x1, 0xf8, 0x55, - 0x1, 0xfe, 0x0, 0x1, 0xce, 0x0, 0x0, 0xce, - 0x0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, - - /* U+E770 "" */ - 0x0, 0x4, 0x0, 0x0, 0x3f, 0x0, 0x0, 0xf3, - 0xd4, 0x82, 0xc0, 0xbf, 0xfb, 0x40, 0x7, 0xee, - 0x0, 0x7, 0xd0, 0x2c, 0x7, 0xd0, 0x7f, 0x47, - 0xf4, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x55, 0x55, 0x55, - - /* U+E89C "" */ - 0x15, 0x54, 0x0, 0x3f, 0xff, 0x40, 0x70, 0x7, - 0xd0, 0x70, 0x7, 0xf4, 0x70, 0x7, 0xfc, 0x70, - 0x0, 0xd, 0x70, 0x28, 0xd, 0x70, 0x28, 0xd, - 0x72, 0xff, 0x8d, 0x70, 0x28, 0xd, 0x70, 0x28, - 0xd, 0x70, 0x0, 0xd, 0x75, 0x55, 0x5d, 0x2f, - 0xff, 0xf8, - - /* U+E8AF "" */ - 0x15, 0x55, 0x40, 0xf, 0xff, 0xff, 0x0, 0xd0, - 0x0, 0x30, 0xd, 0x0, 0x3, 0x28, 0xd0, 0x0, - 0x33, 0xcd, 0x0, 0x3, 0x3c, 0xd5, 0x55, 0xb3, - 0xcf, 0xff, 0xfe, 0x3c, 0xf0, 0x0, 0x3, 0xc0, - 0x7f, 0xff, 0xfc, 0x3, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x3c, 0x0, 0x0, 0x0, 0x80, - - /* U+E8B8 "" */ - 0x0, 0x5, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x4, - 0x35, 0xc1, 0x2, 0xff, 0xf, 0xf8, 0x35, 0x40, - 0x15, 0xc3, 0x81, 0xf4, 0x2c, 0x1d, 0x3f, 0xc7, - 0x40, 0xd3, 0xfd, 0x70, 0x3c, 0x3f, 0xc3, 0xc7, - 0x0, 0x50, 0xd, 0x3f, 0xd0, 0x7f, 0xc0, 0xeb, - 0xe, 0xb0, 0x0, 0x3a, 0xc0, 0x0, 0x2, 0xf8, - 0x0, - - /* U+E8FD "" */ - 0x0, 0x15, 0x40, 0x0, 0x2f, 0xff, 0x40, 0xb, - 0x40, 0x2e, 0x2, 0xc1, 0xa4, 0x74, 0x34, 0x20, - 0xc1, 0xcb, 0x0, 0x1c, 0xd, 0xa0, 0x3, 0x40, - 0xea, 0x0, 0xa0, 0xe, 0xa0, 0x0, 0x0, 0xd7, - 0x0, 0x90, 0x1c, 0x38, 0xe, 0x3, 0x80, 0xe0, - 0x0, 0xf0, 0x3, 0xea, 0xbc, 0x0, 0x6, 0xf9, - 0x0, - - /* U+E90F "" */ - 0x0, 0x50, 0x0, 0xff, 0xf0, 0x3c, 0x3, 0xcb, - 0x0, 0xe, 0xd0, 0x0, 0x7d, 0x0, 0x7, 0xd0, - 0x0, 0x7b, 0x0, 0xe, 0x39, 0x57, 0xc0, 0xff, - 0xf0, 0x1, 0x54, 0x0, 0xbf, 0xd0, 0x0, 0x50, - 0x0, 0xe, 0x0, - - /* U+E92E "" */ - 0x15, 0xff, 0x54, 0x3f, 0xff, 0xfd, 0x28, 0x0, - 0x28, 0x28, 0x82, 0x28, 0x28, 0xd7, 0x28, 0x28, - 0xd7, 0x28, 0x28, 0xd7, 0x28, 0x28, 0xd7, 0x28, - 0x28, 0xd7, 0x28, 0x28, 0x0, 0x28, 0x2d, 0x55, - 0x68, 0x1f, 0xff, 0xf4, - - /* U+E9B9 "" */ - 0x10, 0x1a, 0xaa, 0x4b, 0xcb, 0xff, 0xfd, 0x78, - 0x7f, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x10, 0x1a, - 0xaa, 0x4b, 0xcb, 0xff, 0xfd, 0x78, 0x7f, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x10, 0x1a, 0xaa, 0x4b, - 0xcb, 0xff, 0xfd, 0x78, 0x7f, 0xff, 0xd0, 0x0, - 0x0, 0x0, - - /* U+E9F4 "" */ - 0x0, 0x7, 0xd0, 0x0, 0x0, 0xe, 0xb0, 0x0, - 0x0, 0xe, 0xb0, 0x0, 0x0, 0x7, 0xd0, 0x0, - 0x28, 0x2, 0x80, 0x28, 0xff, 0x3, 0xc0, 0xff, - 0xd7, 0x5f, 0xf5, 0xd7, 0xbe, 0xb8, 0x2e, 0xbe, - 0x0, 0x34, 0x1c, 0x0, 0x0, 0x3c, 0x3c, 0x0, - 0x0, 0x1f, 0xf4, 0x0, 0x1, 0x75, 0x5d, 0x40, - 0xb, 0xf0, 0xf, 0xe0, 0xd, 0x70, 0xd, 0x70, - 0xb, 0xe0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0x0, - - /* U+E9F7 "" */ - 0xbf, 0xff, 0xfe, 0xe5, 0x55, 0x5b, 0xd0, 0x0, - 0x7, 0xe5, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x7, 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, - 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xe5, 0x55, - 0x5b, 0xbf, 0xff, 0xfe, - - /* U+EA07 "" */ - 0x0, 0x15, 0x0, 0x0, 0x1f, 0xff, 0x40, 0xb, - 0xba, 0xee, 0x2, 0xc7, 0xc, 0x74, 0x39, 0xf5, - 0xe7, 0xcb, 0xff, 0xff, 0xfd, 0xa0, 0xd0, 0x70, - 0xea, 0xc, 0x7, 0xe, 0xb5, 0xe5, 0xb5, 0xd7, - 0xff, 0xff, 0xfc, 0x3c, 0xb0, 0xd3, 0x80, 0xe7, - 0x5c, 0xf0, 0x3, 0xff, 0xfc, 0x0, 0x6, 0xf9, - 0x0, - - /* U+EAD6 "" */ - 0xbf, 0xff, 0xfe, 0xe5, 0x55, 0x5b, 0xd0, 0x0, - 0x7, 0xd0, 0x0, 0x7, 0xdf, 0x7a, 0x27, 0xdc, - 0xa1, 0x77, 0xdc, 0xa0, 0xe7, 0xdf, 0x78, 0xc7, - 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xe5, 0x55, - 0x5b, 0xbf, 0xff, 0xfe, - - /* U+EB8E "" */ - 0x2a, 0xaa, 0xaa, 0x4f, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xde, 0x0, 0x0, 0xd, 0xd2, 0x40, - 0x0, 0xdd, 0x1d, 0x0, 0xd, 0xd0, 0xb0, 0x0, - 0xdd, 0x1e, 0x0, 0xd, 0xd2, 0x83, 0xf8, 0xdd, - 0x0, 0x15, 0xd, 0xbf, 0xff, 0xff, 0xd1, 0x55, - 0x55, 0x50, - - /* U+EB97 "" */ - 0x7f, 0xff, 0xff, 0xce, 0x55, 0x55, 0x5d, 0xd0, - 0x0, 0x0, 0xdd, 0x15, 0x53, 0x4d, 0xd1, 0x55, - 0x30, 0xdd, 0x8, 0x0, 0xd, 0xd3, 0xdf, 0xf8, - 0xdd, 0x1c, 0x55, 0xd, 0xd0, 0x0, 0x0, 0xde, - 0x55, 0x55, 0x5d, 0x7f, 0xff, 0xff, 0xc0, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EBCC "" */ - 0x8, 0x0, 0x20, 0x1e, 0x55, 0xb4, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x7, 0xe5, 0x55, 0x5b, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x7, 0xd3, 0x24, 0xc7, - 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xd3, 0x24, - 0xc7, 0xd0, 0x0, 0x7, 0xe5, 0x55, 0x5b, 0xbf, - 0xff, 0xfe, - - /* U+EC1C "" */ - 0x0, 0x0, 0x80, 0x0, 0x7, 0x80, 0x0, 0x1f, - 0x0, 0x0, 0x7e, 0x0, 0x1, 0xfc, 0x0, 0x7, - 0xbe, 0x50, 0x1e, 0x2b, 0xfc, 0x3f, 0xe8, 0x74, - 0x5, 0xbe, 0xd0, 0x0, 0x3f, 0x40, 0x0, 0xbd, - 0x0, 0x0, 0xf4, 0x0, 0x2, 0xd0, 0x0, 0x2, - 0x0, 0x0, - - /* U+EF40 "" */ - 0x14, 0x14, 0x14, 0xf, 0x4f, 0x4f, 0x43, 0xc3, - 0xc3, 0xc0, 0x0, 0x0, 0x0, 0x14, 0x14, 0x0, - 0xf, 0x4f, 0x42, 0x83, 0xc3, 0xc2, 0xf8, 0x0, - 0x2, 0xfd, 0x14, 0x2, 0x8d, 0xf, 0x40, 0xcd, - 0x3, 0xc0, 0x3d, 0x0, 0x0, 0x0, 0x0, - - /* U+EF4A "" */ - 0x0, 0x15, 0x40, 0x0, 0x2f, 0xff, 0x40, 0xb, - 0x40, 0x2e, 0x2, 0xc0, 0x0, 0x74, 0x34, 0x0, - 0x1, 0xcb, 0x0, 0x0, 0xd, 0xa0, 0x0, 0x0, - 0xea, 0x0, 0x0, 0xe, 0xa0, 0x0, 0x0, 0xd7, - 0x0, 0x0, 0x1c, 0x38, 0x0, 0x3, 0x80, 0xe0, - 0x0, 0xf0, 0x3, 0xea, 0xbc, 0x0, 0x6, 0xf9, - 0x0, - - /* U+EF7A "" */ - 0xb, 0xf4, 0x0, 0x3d, 0x6d, 0x0, 0xb0, 0x7, - 0x0, 0xe0, 0x3, 0x40, 0xd0, 0x3, 0x80, 0xe0, - 0x3, 0x40, 0xb0, 0xb, 0x0, 0x3e, 0xbf, 0x0, - 0x7, 0xe2, 0xc0, 0x0, 0x0, 0xb0, 0x0, 0x0, - 0x2c, 0x0, 0x0, 0x9, - - /* U+EFE6 "" */ - 0xb, 0xd0, 0x3c, 0x1d, 0xb0, 0xbe, 0x28, 0x34, - 0xff, 0x28, 0x34, 0xff, 0x28, 0x34, 0xbe, 0x28, - 0x34, 0x28, 0x28, 0x34, 0x28, 0xbe, 0x34, 0x28, - 0xff, 0x34, 0x28, 0xff, 0x38, 0x28, 0xbe, 0x2d, - 0xb4, 0x3c, 0xb, 0xd0, - - /* U+F028 "" */ - 0x5, 0x55, 0x55, 0x50, 0x3f, 0xff, 0xff, 0xfc, - 0x70, 0x0, 0x0, 0xd, 0x71, 0x48, 0x11, 0x4d, - 0x71, 0x48, 0x21, 0x4d, 0x70, 0x0, 0x0, 0xd, - 0x72, 0x8c, 0x72, 0x8d, 0x70, 0x0, 0x0, 0xd, - 0x70, 0x2f, 0xf8, 0xd, 0x70, 0x5, 0x50, 0xd, - 0x3f, 0xff, 0xff, 0xfc, 0x5, 0x55, 0x55, 0x50, - - /* U+F090 "" */ - 0x0, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x34, - 0x0, 0x0, 0x34, 0x0, 0x0, 0x34, 0x0, 0x3, - 0xbb, 0x80, 0x1, 0xff, 0x0, 0x0, 0xbc, 0x0, - 0x30, 0x10, 0xc, 0x70, 0x0, 0xd, 0x3f, 0xff, - 0xfc, 0x5, 0x55, 0x50, - - /* U+F15C "" */ - 0x0, 0x1, 0x40, 0x0, 0x0, 0x2f, 0xf4, 0x0, - 0x0, 0xb4, 0x2d, 0x0, 0x1, 0xc0, 0xb, 0x0, - 0x7, 0xc0, 0x3, 0x40, 0x2e, 0x0, 0x3, 0xd0, - 0x34, 0x0, 0x2, 0xb8, 0x70, 0x0, 0x0, 0x1c, - 0x30, 0x0, 0x0, 0xd, 0x3c, 0x0, 0x0, 0x2c, - 0xf, 0xff, 0xff, 0xf4, 0x0, 0x55, 0x55, 0x40, - - /* U+F720 "" */ - 0x0, 0x10, 0x0, 0x1, 0xfe, 0x0, 0xb, 0x87, - 0xd0, 0x7c, 0x0, 0xbc, 0xf8, 0x0, 0x3e, 0xef, - 0x42, 0xee, 0xd2, 0xff, 0x4e, 0xd0, 0x38, 0xe, - 0xd0, 0x34, 0xe, 0xd0, 0x34, 0xe, 0xb4, 0x34, - 0x2d, 0x2f, 0x36, 0xf0, 0x2, 0xff, 0x40, 0x0, - 0x78, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x4, 0x0, 0x0, 0x0, 0xd0, 0x0, 0x0, - 0xd, 0x0, 0x2, 0xc0, 0xd0, 0x70, 0x34, 0xd, - 0x3, 0x8b, 0x0, 0xd0, 0x1c, 0xa0, 0xd, 0x0, - 0xca, 0x0, 0x80, 0xc, 0xa0, 0x0, 0x0, 0xc7, - 0x0, 0x0, 0x2c, 0x38, 0x0, 0x3, 0x40, 0xe0, - 0x1, 0xe0, 0x3, 0xea, 0xf8, 0x0, 0x6, 0xf8, - 0x0, - - /* U+FFF75 "󿽵" */ - 0x55, 0x55, 0x55, 0xf, 0xff, 0xff, 0xfc, 0xd1, - 0x4, 0x4, 0xde, 0x55, 0x55, 0x5d, 0xff, 0xff, - 0xff, 0xd0, 0x7, 0xf4, 0xd, 0x1b, 0xe0, 0x21, - 0xd7, 0x90, 0x82, 0xf8, 0xe1, 0x7, 0xf8, 0xf, - 0xff, 0xff, 0xfd, 0xe5, 0x55, 0x55, 0xdd, 0x20, - 0x80, 0x8d, 0xb5, 0x55, 0x55, 0xd2, 0xff, 0xff, - 0xfd -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 256, .box_w = 10, .box_h = 10, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 25, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 67, .adv_w = 256, .box_w = 9, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 99, .adv_w = 256, .box_w = 10, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 134, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 198, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 240, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 289, .adv_w = 256, .box_w = 8, .box_h = 5, .ofs_x = 4, .ofs_y = 6}, - {.bitmap_index = 299, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 341, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 390, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 426, .adv_w = 256, .box_w = 8, .box_h = 12, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 450, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 486, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 522, .adv_w = 256, .box_w = 10, .box_h = 10, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 547, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 571, .adv_w = 256, .box_w = 4, .box_h = 12, .ofs_x = 6, .ofs_y = 2}, - {.bitmap_index = 583, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 619, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 667, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 691, .adv_w = 256, .box_w = 13, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 730, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 766, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 808, .adv_w = 256, .box_w = 14, .box_h = 13, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 854, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 903, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 952, .adv_w = 256, .box_w = 10, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 987, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1023, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1065, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1129, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1165, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1214, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1250, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1292, .adv_w = 256, .box_w = 14, .box_h = 13, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1338, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 1380, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 1422, .adv_w = 256, .box_w = 13, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1461, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1510, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1546, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1582, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 1630, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1666, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 1714, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 1756, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1805, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_16 = { -#else -lv_font_t material_symbols_shared_16 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 16, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_16*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_20.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_20.c deleted file mode 100644 index 9f8ca64e8..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_20.c +++ /dev/null @@ -1,644 +0,0 @@ -/******************************************************************************* - * Size: 20 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 20 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_20.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_20 -#define MATERIAL_SYMBOLS_SHARED_20 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_20 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x14, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, - 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x7f, - 0xff, 0xfd, 0xbf, 0xff, 0xfe, 0x0, 0x3c, 0x0, - 0x0, 0x3c, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x3c, - 0x0, 0x0, 0x28, 0x0, - - /* U+E159 "" */ - 0x1a, 0xaa, 0xaa, 0xaa, 0x83, 0xff, 0xff, 0xff, - 0xfd, 0x3d, 0x0, 0x0, 0x2, 0xe3, 0xfc, 0x0, - 0x1, 0xfe, 0x39, 0xf8, 0x0, 0xf8, 0xe3, 0x82, - 0xf4, 0xbc, 0xe, 0x38, 0x3, 0xfd, 0x0, 0xe3, - 0x80, 0x6, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, - 0xe3, 0x80, 0x0, 0x0, 0xe, 0x38, 0x0, 0x0, - 0x0, 0xe3, 0x80, 0x0, 0x0, 0xe, 0x3f, 0xff, - 0xff, 0xff, 0xd1, 0xaa, 0xaa, 0xaa, 0xa8, - - /* U+E1A7 "" */ - 0x0, 0x28, 0x0, 0x0, 0xf8, 0x1, 0x3, 0xf8, - 0x1e, 0xe, 0xb8, 0x2e, 0x38, 0xf0, 0x2e, 0xfb, - 0x80, 0x2f, 0xf8, 0x0, 0x2f, 0x80, 0x0, 0xbe, - 0x0, 0xb, 0xfe, 0x0, 0xbb, 0xee, 0xb, 0x8e, - 0x3c, 0x78, 0x3a, 0xe0, 0x40, 0xfe, 0x0, 0x3, - 0xe0, 0x0, 0xa, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x7d, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x38, 0x0, 0x10, - 0x38, 0x14, 0xbc, 0x38, 0x7f, 0xfd, 0x38, 0x7f, - 0x7c, 0x38, 0x7f, 0x38, 0x38, 0x2c, 0x3d, 0x7d, - 0x6c, 0x2f, 0xff, 0xfc, 0x5, 0x7d, 0x50, 0x0, - 0x38, 0x0, 0x0, 0x3c, 0x0, 0x0, 0xbe, 0x0, - 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xe0, - 0x0, 0x0, 0x0, 0x7f, 0xd0, 0x0, 0x0, 0x2, - 0xc3, 0x80, 0x0, 0x0, 0xb, 0xe, 0x0, 0x0, - 0x0, 0x2c, 0x38, 0x0, 0x0, 0x0, 0xb0, 0xe0, - 0x0, 0x0, 0x2, 0xc3, 0x80, 0x0, 0x0, 0xb, - 0xe, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf8, 0x2, - 0xff, 0xff, 0xff, 0xf8, 0xb, 0x0, 0x0, 0x0, - 0xe0, 0x2e, 0xaa, 0xaa, 0xab, 0x80, 0xff, 0xff, - 0xff, 0xff, 0x3, 0x80, 0x0, 0x0, 0x2c, 0x1d, - 0x34, 0x3c, 0x1c, 0x74, 0xb0, 0xe0, 0xf0, 0xb0, - 0xe2, 0xeb, 0xeb, 0xeb, 0xeb, 0xc7, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E2C7 "" */ - 0x1a, 0xa9, 0x0, 0x0, 0x3, 0xff, 0xf8, 0x0, - 0x0, 0x38, 0x2, 0xff, 0xff, 0xc3, 0x80, 0xa, - 0xaa, 0xae, 0x38, 0x0, 0x0, 0x0, 0xe3, 0x80, - 0x0, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, 0xe3, - 0x80, 0x0, 0x0, 0xe, 0x38, 0x0, 0x0, 0x0, - 0xe3, 0x80, 0x0, 0x0, 0xe, 0x38, 0x0, 0x0, - 0x0, 0xe3, 0x80, 0x0, 0x0, 0xe, 0x3f, 0xff, - 0xff, 0xff, 0xd1, 0xaa, 0xaa, 0xaa, 0xa8, - - /* U+E30F "" */ - 0x0, 0x1, 0xa8, 0x0, 0x0, 0x0, 0x3f, 0xe0, - 0x0, 0x0, 0x3, 0x8e, 0x0, 0x0, 0x0, 0x38, - 0xe0, 0x0, 0x0, 0x3, 0xce, 0x0, 0x0, 0x0, - 0x2f, 0xd0, 0x0, 0x2a, 0xa0, 0xb4, 0x2a, 0x83, - 0xff, 0x80, 0xf, 0xfe, 0x38, 0x2d, 0x3, 0xd0, - 0xe3, 0x82, 0xd0, 0x3d, 0xe, 0x3f, 0xf8, 0x20, - 0xff, 0xe1, 0xa9, 0xf, 0x82, 0xa8, 0x0, 0x3, - 0xfe, 0x0, 0x0, 0x0, 0x38, 0xe0, 0x0, 0x0, - 0x3, 0x8e, 0x0, 0x0, 0x0, 0x3e, 0xe0, 0x0, - 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E316 "" */ - 0x0, 0xe0, 0x0, 0x3f, 0x80, 0xf, 0x6e, 0x3, - 0xd0, 0xb8, 0xb4, 0x2, 0xd1, 0x0, 0x4, - - /* U+E326 "" */ - 0x6, 0xaa, 0xaa, 0xaa, 0x1, 0xff, 0xff, 0xff, - 0xf4, 0x2c, 0x0, 0x0, 0x0, 0x2, 0xc0, 0x0, - 0x1a, 0xa4, 0x2c, 0x0, 0x3, 0xff, 0xd2, 0xc0, - 0x0, 0x38, 0xe, 0x2c, 0x0, 0x3, 0x98, 0xe2, - 0xc0, 0x0, 0x38, 0xe, 0x2c, 0x0, 0x3, 0x80, - 0xe1, 0xea, 0xa4, 0x38, 0xe, 0xf, 0xff, 0xc3, - 0x80, 0xe0, 0x0, 0x0, 0x38, 0xe, 0x3f, 0xff, - 0xc3, 0xff, 0xe2, 0xaa, 0xa4, 0x1a, 0xa8, - - /* U+E3AF "" */ - 0x0, 0x1, 0x54, 0x0, 0x0, 0x2, 0xff, 0xfc, - 0x0, 0x1, 0xf9, 0x1e, 0xf4, 0x0, 0x7c, 0x2, - 0x3, 0xd0, 0xf, 0x80, 0x20, 0xf, 0x2, 0xd8, - 0x8, 0x0, 0x38, 0x3c, 0x21, 0xea, 0xab, 0xc3, - 0x82, 0x7f, 0xd0, 0x1d, 0x34, 0xf, 0xff, 0x1, - 0xd3, 0x40, 0xbf, 0xf4, 0x1d, 0x38, 0x7, 0xfc, - 0xc1, 0xc3, 0xea, 0xab, 0x46, 0x3c, 0x1d, 0x0, - 0x20, 0x3b, 0x80, 0xb0, 0x5, 0x1, 0xf0, 0x3, - 0xc0, 0x80, 0x7c, 0x0, 0xb, 0xaa, 0xbf, 0x0, - 0x0, 0x1b, 0xfe, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E3F4 "" */ - 0x1a, 0xaa, 0xaa, 0xa4, 0x7f, 0xff, 0xff, 0xfd, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x24, 0xe, 0xb0, 0x30, 0x7c, 0xe, - 0xb0, 0xf8, 0xfe, 0xe, 0xb1, 0xff, 0xff, 0x4e, - 0xb0, 0x55, 0x55, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0x7f, 0xff, 0xff, 0xfd, 0x1a, 0xaa, 0xaa, 0xa4, - - /* U+E405 "" */ - 0x0, 0x5, 0x40, 0x3, 0xff, 0x0, 0x3f, 0xf0, - 0x3, 0xff, 0x0, 0x38, 0x0, 0x3, 0x80, 0x0, - 0x38, 0x0, 0x3, 0x80, 0x0, 0x38, 0x2, 0xff, - 0x80, 0x7f, 0xf8, 0xf, 0xff, 0x80, 0xff, 0xf8, - 0xb, 0xff, 0x40, 0x3f, 0xe0, 0x0, 0x54, 0x0, - - /* U+E55D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, - 0x1f, 0x40, 0x0, 0x2, 0xf8, 0x0, 0x0, 0x3a, - 0xc0, 0x0, 0xb, 0xe, 0x0, 0x0, 0xf0, 0xf0, - 0x0, 0x1d, 0x7, 0x40, 0x3, 0xc0, 0x3c, 0x0, - 0x74, 0x1, 0xd0, 0xf, 0x0, 0xf, 0x1, 0xe0, - 0xa0, 0xb4, 0x2d, 0xff, 0xf7, 0x83, 0xfe, 0xb, - 0xfc, 0x7d, 0x0, 0x7, 0xd1, 0x0, 0x0, 0x4, - - /* U+E5C3 "" */ - 0x14, 0x5, 0x1, 0x4b, 0xd2, 0xf4, 0xbd, 0xbe, - 0x2f, 0x8b, 0xe3, 0x80, 0xe0, 0x38, 0x0, 0x0, - 0x0, 0x1, 0x40, 0x50, 0x14, 0xbd, 0x2f, 0x4b, - 0xdb, 0xe2, 0xf8, 0xbe, 0x38, 0xe, 0x3, 0x80, - 0x0, 0x0, 0x0, 0x14, 0x5, 0x1, 0x4b, 0xd2, - 0xf4, 0xbd, 0xbe, 0x2f, 0x8b, 0xe3, 0x80, 0xe0, - 0x38, - - /* U+E5CD "" */ - 0x20, 0x0, 0x9, 0x3c, 0x0, 0x2e, 0x1f, 0x0, - 0xb8, 0x7, 0xc2, 0xe0, 0x1, 0xfb, 0x80, 0x0, - 0x7e, 0x0, 0x0, 0xbf, 0x0, 0x2, 0xe7, 0xc0, - 0xb, 0x81, 0xf0, 0x2e, 0x0, 0x7c, 0x38, 0x0, - 0x1e, 0x0, 0x0, 0x0, - - /* U+E5D2 "" */ - 0xbf, 0xff, 0xff, 0xfc, 0x6a, 0xaa, 0xaa, 0xa8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6a, 0xaa, 0xaa, 0xa8, 0x7f, 0xff, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6a, 0xaa, 0xaa, 0xa8, 0xbf, 0xff, 0xff, 0xfc, - - /* U+E5D4 "" */ - 0x14, 0xbd, 0xbe, 0x38, 0x0, 0x14, 0xbd, 0xbe, - 0x38, 0x0, 0x14, 0xbd, 0xbe, 0x38, - - /* U+E5D5 "" */ - 0x0, 0x1a, 0x40, 0x50, 0x2f, 0xff, 0x8e, 0xf, - 0x80, 0x6f, 0xe2, 0xd0, 0x0, 0x7e, 0x38, 0x0, - 0xab, 0xe7, 0x0, 0xf, 0xfe, 0xb0, 0x0, 0x0, - 0xb, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x3, - 0x80, 0x0, 0x2c, 0x2d, 0x0, 0x7, 0x80, 0xf8, - 0x6, 0xf0, 0x2, 0xff, 0xf8, 0x0, 0x1, 0xa4, - 0x0, - - /* U+E63E "" */ - 0x0, 0x1, 0x6a, 0x40, 0x0, 0x0, 0x7f, 0xff, - 0xfe, 0x0, 0x7, 0xff, 0xff, 0xff, 0xe0, 0x2f, - 0xf4, 0x0, 0x1b, 0xfc, 0x3f, 0x40, 0x0, 0x0, - 0xbe, 0x28, 0x0, 0x6a, 0x40, 0x18, 0x0, 0x1f, - 0xff, 0xf8, 0x0, 0x0, 0xbf, 0xff, 0xff, 0x0, - 0x0, 0xbd, 0x0, 0x6f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x3d, 0x0, - 0x0, 0xf, 0x40, 0x0, 0x3, 0xd0, 0x10, 0x0, - 0xf4, 0x7, 0xc0, 0x3d, 0x0, 0x2f, 0xf, 0x40, - 0x0, 0xbf, 0xd0, 0x0, 0x2, 0xf4, 0x0, 0x0, - 0x5, 0x0, 0x0, - - /* U+E745 "" */ - 0x6a, 0xaa, 0x80, 0x0, 0x7f, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2a, 0xaa, 0x80, 0x0, - 0xbf, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb4, 0x7f, 0xf0, 0x2, 0xfc, - 0x6a, 0xa0, 0xb, 0xfc, 0x0, 0x0, 0x2d, 0xf8, - 0x0, 0x0, 0x74, 0xe0, 0x0, 0x0, 0xd3, 0x80, - 0x0, 0x0, 0xde, 0x0, 0x0, 0x0, 0xf8, 0x0, - - /* U+E770 "" */ - 0x0, 0x1, 0x80, 0x0, 0x0, 0x7, 0xf4, 0x0, - 0x0, 0xf, 0x7e, 0x0, 0x0, 0x3d, 0xb, 0xfc, - 0xb4, 0xb8, 0x1, 0xae, 0xbf, 0xf0, 0x0, 0xe, - 0xbb, 0xc0, 0x0, 0xe, 0xb1, 0x42, 0xc0, 0xe, - 0xb0, 0x7, 0xf4, 0xe, 0xb4, 0xf, 0xfe, 0xe, - 0xbe, 0x3f, 0xff, 0xce, 0xbf, 0xff, 0xff, 0xfe, - 0xbf, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfd, - - /* U+E89C "" */ - 0x1a, 0xaa, 0x40, 0xb, 0xff, 0xfe, 0x0, 0xb0, - 0x1, 0xf8, 0xb, 0x0, 0xf, 0xe0, 0xb0, 0x0, - 0xff, 0x8b, 0x0, 0xf, 0xfd, 0xb0, 0x0, 0x15, - 0xeb, 0x0, 0xa0, 0xe, 0xb0, 0xf, 0x0, 0xeb, - 0x5, 0xf5, 0xe, 0xb0, 0xff, 0xf0, 0xeb, 0x1, - 0xf4, 0xe, 0xb0, 0xf, 0x0, 0xeb, 0x0, 0x50, - 0xe, 0xb0, 0x0, 0x0, 0xeb, 0xaa, 0xaa, 0xae, - 0x7f, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - - /* U+E8AF "" */ - 0xa, 0xaa, 0xaa, 0x40, 0x3, 0xff, 0xff, 0xfd, - 0x0, 0x38, 0x0, 0x0, 0xe0, 0x3, 0x80, 0x0, - 0xe, 0x0, 0x38, 0x0, 0x0, 0xe3, 0xc3, 0x80, - 0x0, 0xe, 0x3e, 0x38, 0x0, 0x0, 0xe3, 0xe3, - 0x80, 0x0, 0xe, 0x3e, 0x3a, 0xaa, 0xaa, 0xe3, - 0xe3, 0xff, 0xff, 0xfc, 0x3e, 0x3e, 0x0, 0x0, - 0x3, 0xe3, 0x86, 0xaa, 0xaa, 0xfe, 0x0, 0xbf, - 0xff, 0xff, 0xe0, 0x7, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x3, 0xe0, 0x0, 0x0, 0x0, 0x1d, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E8B8 "" */ - 0x0, 0x6, 0x90, 0x0, 0x0, 0x7, 0xfd, 0x0, - 0x0, 0x2, 0xc3, 0x80, 0x0, 0x79, 0xf0, 0xf6, - 0xd0, 0x3f, 0xf4, 0x1f, 0xfc, 0x2c, 0x10, 0x0, - 0x43, 0x8f, 0x40, 0xbe, 0x1, 0xf0, 0xf4, 0xbf, - 0xe1, 0xf0, 0x1d, 0x3f, 0xfc, 0x74, 0xb, 0x8b, - 0xff, 0x2d, 0xb, 0xc1, 0xff, 0x43, 0xe3, 0xc0, - 0xa, 0x40, 0x3c, 0x7a, 0xd0, 0x7, 0xad, 0xf, - 0xff, 0xf, 0xff, 0x0, 0x92, 0xc3, 0x86, 0x0, - 0x0, 0x7a, 0xd0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E8FD "" */ - 0x0, 0x1, 0x54, 0x0, 0x0, 0x2, 0xff, 0xfc, - 0x0, 0x1, 0xf9, 0x6, 0xf4, 0x0, 0x7c, 0x0, - 0x3, 0xd0, 0xf, 0x2, 0xfc, 0xf, 0x2, 0xd0, - 0x7a, 0xf0, 0x38, 0x3c, 0x1, 0xb, 0x2, 0xc3, - 0x80, 0x0, 0xe0, 0x1d, 0x34, 0x0, 0x3c, 0x1, - 0xd3, 0x40, 0xb, 0x0, 0x1d, 0x38, 0x0, 0x60, - 0x1, 0xc3, 0xc0, 0x0, 0x0, 0x3c, 0x1e, 0x0, - 0xf0, 0x7, 0x80, 0xf4, 0xa, 0x0, 0xf0, 0x3, - 0xe0, 0x0, 0x7c, 0x0, 0xb, 0xea, 0xbf, 0x0, - 0x0, 0x1b, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E90F "" */ - 0x0, 0x15, 0x40, 0x0, 0x1f, 0xff, 0x40, 0xb, - 0xd0, 0x7e, 0x1, 0xe0, 0x0, 0xb4, 0x3c, 0x0, - 0x3, 0xc3, 0x80, 0x0, 0x2c, 0x34, 0x0, 0x1, - 0xc3, 0x80, 0x0, 0x2c, 0x3c, 0x0, 0x3, 0xc2, - 0xd0, 0x0, 0x78, 0xf, 0xaa, 0xaf, 0x0, 0x2f, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x40, 0x0, 0xaa, 0xa0, 0x0, 0x1, 0xa4, 0x0, - 0x0, 0xf, 0x40, 0x0, 0x0, 0x0, 0x0, - - /* U+E92E "" */ - 0x0, 0x1a, 0x40, 0x6, 0xaf, 0xff, 0xa8, 0xbf, - 0xff, 0xff, 0xd3, 0xc0, 0x0, 0x3c, 0x3c, 0x0, - 0x3, 0xc3, 0xc7, 0xd, 0x3c, 0x3c, 0x70, 0xd3, - 0xc3, 0xc7, 0xd, 0x3c, 0x3c, 0x70, 0xd3, 0xc3, - 0xc7, 0xd, 0x3c, 0x3c, 0x70, 0xd3, 0xc3, 0xc7, - 0xd, 0x3c, 0x3c, 0x0, 0x3, 0xc3, 0xc0, 0x0, - 0x3c, 0x2f, 0xff, 0xff, 0x80, 0xaa, 0xaa, 0xa0, - - /* U+E9B9 "" */ - 0x4, 0x1, 0x55, 0x55, 0x43, 0xf0, 0xff, 0xff, - 0xfc, 0x7f, 0xf, 0xff, 0xff, 0xd2, 0xd0, 0xbf, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, - 0x15, 0x55, 0x54, 0x3f, 0xf, 0xff, 0xff, 0xc7, - 0xf0, 0xff, 0xff, 0xfd, 0x2d, 0xb, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1, 0x55, - 0x55, 0x43, 0xf0, 0xff, 0xff, 0xfc, 0x7f, 0xf, - 0xff, 0xff, 0xd2, 0xd0, 0xbf, 0xff, 0xf8, - - /* U+E9F4 "" */ - 0x0, 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x1, 0xd7, 0x40, 0x0, 0x0, - 0x1, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7d, 0x0, - 0x0, 0x15, 0x0, 0x28, 0x0, 0x54, 0x7f, 0x40, - 0x28, 0x1, 0xfd, 0xf7, 0xc1, 0xff, 0x3, 0xdf, - 0xf3, 0xe7, 0xeb, 0xdb, 0xcf, 0x7f, 0xaf, 0x0, - 0xfa, 0xfd, 0x15, 0xb, 0x0, 0xe0, 0x54, 0x0, - 0xb, 0x0, 0xe0, 0x0, 0x0, 0x3, 0xeb, 0xc0, - 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x1, 0xae, - 0x0, 0xba, 0x40, 0x3, 0xfc, 0x0, 0x3f, 0xc0, - 0x7, 0x5d, 0x0, 0x75, 0xd0, 0x7, 0xfd, 0x0, - 0x7f, 0xd0, 0x2, 0xf8, 0x0, 0x2f, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E9F7 "" */ - 0x1a, 0xaa, 0xaa, 0xa4, 0x7f, 0xff, 0xff, 0xfd, - 0x70, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xba, 0xaa, 0xaa, 0xae, 0xbf, 0xff, 0xff, 0xfe, - 0xb4, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0x70, 0x0, 0x0, 0xe, - 0x7f, 0xff, 0xff, 0xfd, 0x1a, 0xaa, 0xaa, 0xa4, - - /* U+EA07 "" */ - 0x0, 0x1, 0x64, 0x0, 0x0, 0x2, 0xff, 0xfc, - 0x0, 0x1, 0xff, 0xef, 0xf4, 0x0, 0x7c, 0xb4, - 0xe3, 0xd0, 0xf, 0xf, 0xb, 0xf, 0x2, 0xfa, - 0xfa, 0xba, 0xb8, 0x3f, 0xff, 0xff, 0xff, 0xc3, - 0x82, 0xc0, 0x3c, 0x1d, 0x34, 0x2c, 0x3, 0xc1, - 0xd3, 0x42, 0xc0, 0x3c, 0x1d, 0x3e, 0xbe, 0xab, - 0xea, 0xc2, 0xff, 0xff, 0xff, 0xfc, 0x1e, 0xe, - 0xb, 0x4b, 0x80, 0xb4, 0xf0, 0xf1, 0xf0, 0x3, - 0xe7, 0x9e, 0xbc, 0x0, 0xb, 0xff, 0xff, 0x0, - 0x0, 0x1b, 0xfe, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+EAD6 "" */ - 0x1a, 0xaa, 0xaa, 0xa4, 0x7f, 0xff, 0xff, 0xfd, - 0x70, 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb2, 0x92, 0x84, 0x4e, - 0xb3, 0xbb, 0x8c, 0xce, 0xb3, 0x3a, 0xc, 0xce, - 0xb3, 0x3b, 0x4a, 0x8e, 0xb3, 0x3a, 0x7, 0x4e, - 0xb2, 0x92, 0x82, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0x70, 0x0, 0x0, 0xe, - 0x7f, 0xff, 0xff, 0xfd, 0x1a, 0xaa, 0xaa, 0xa4, - - /* U+EB8E "" */ - 0x5, 0x55, 0x55, 0x55, 0x43, 0xff, 0xff, 0xff, - 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, - 0xff, 0xfe, 0x38, 0x0, 0x0, 0x0, 0xe3, 0x87, - 0x40, 0x0, 0xe, 0x38, 0x3d, 0x0, 0x0, 0xe3, - 0x80, 0xf4, 0x0, 0xe, 0x38, 0xf, 0x0, 0x0, - 0xe3, 0x83, 0xc0, 0x69, 0xe, 0x38, 0x20, 0x2f, - 0xf0, 0xe3, 0x80, 0x0, 0x0, 0xe, 0x3f, 0xff, - 0xff, 0xff, 0xd1, 0xaa, 0xaa, 0xaa, 0xa8, - - /* U+EB97 "" */ - 0xa, 0xaa, 0xaa, 0xaa, 0x43, 0xff, 0xff, 0xff, - 0xfd, 0x38, 0x0, 0x0, 0x0, 0xe3, 0x80, 0x0, - 0x0, 0xe, 0x38, 0x0, 0x1, 0xc0, 0xe3, 0x8b, - 0xff, 0xdf, 0xe, 0x38, 0x0, 0x0, 0xc0, 0xe3, - 0x81, 0x40, 0x0, 0xe, 0x38, 0xb8, 0xff, 0xf0, - 0xe3, 0x87, 0x8a, 0xaa, 0xe, 0x38, 0x4, 0x0, - 0x0, 0xe3, 0x80, 0x0, 0x0, 0xe, 0x3e, 0xaa, - 0xaa, 0xaa, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0xf, 0xff, 0x80, 0x0, 0x0, 0xaa, 0xa0, 0x0, - - /* U+EBCC "" */ - 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x2, 0xc0, - 0x2b, 0xea, 0xab, 0xe8, 0x7f, 0xff, 0xff, 0xfd, - 0xb0, 0x0, 0x0, 0xe, 0xba, 0xaa, 0xaa, 0xae, - 0xbf, 0xff, 0xff, 0xfe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xb0, 0xd2, 0x87, 0xe, - 0xb0, 0x81, 0x42, 0xe, 0xb0, 0x0, 0x0, 0xe, - 0xb0, 0x81, 0x42, 0xe, 0xb0, 0xd2, 0x87, 0xe, - 0xb0, 0x0, 0x0, 0xe, 0xba, 0xaa, 0xaa, 0xae, - 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - - /* U+EC1C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x80, 0x0, - 0x1, 0xf0, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x1f, - 0xc0, 0x0, 0xb, 0xf8, 0x0, 0x2, 0xff, 0x0, - 0x0, 0xb9, 0xff, 0xa4, 0x2e, 0x6, 0xbf, 0xd7, - 0xfe, 0x90, 0xb8, 0x1a, 0xff, 0x6e, 0x0, 0x0, - 0xff, 0x80, 0x0, 0x2f, 0xe0, 0x0, 0x3, 0xf4, - 0x0, 0x0, 0xbd, 0x0, 0x0, 0xf, 0x40, 0x0, - 0x2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EF40 "" */ - 0x14, 0x5, 0x1, 0x40, 0xbd, 0x2f, 0x4b, 0xd0, - 0xbe, 0x2f, 0x8b, 0xe0, 0x38, 0xe, 0x3, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x14, 0x5, 0x0, 0x0, - 0xbd, 0x2f, 0x40, 0x60, 0xbe, 0x2f, 0x81, 0xfc, - 0x38, 0xe, 0x7, 0xfc, 0x0, 0x0, 0x1e, 0xf8, - 0x14, 0x0, 0x74, 0xe0, 0xbd, 0x0, 0xd3, 0x80, - 0xbe, 0x1, 0xde, 0x0, 0x38, 0x0, 0xf8, 0x0, - - /* U+EF4A "" */ - 0x0, 0x1, 0x54, 0x0, 0x0, 0x2, 0xff, 0xfc, - 0x0, 0x1, 0xf9, 0x6, 0xf4, 0x0, 0x7c, 0x0, - 0x3, 0xd0, 0xf, 0x0, 0x0, 0xf, 0x2, 0xd0, - 0x0, 0x0, 0x38, 0x3c, 0x0, 0x0, 0x2, 0xc3, - 0x80, 0x0, 0x0, 0x1d, 0x34, 0x0, 0x0, 0x1, - 0xd3, 0x40, 0x0, 0x0, 0x1d, 0x38, 0x0, 0x0, - 0x1, 0xc3, 0xc0, 0x0, 0x0, 0x3c, 0x1e, 0x0, - 0x0, 0x7, 0x80, 0xf4, 0x0, 0x0, 0xf0, 0x3, - 0xe0, 0x0, 0x7c, 0x0, 0xb, 0xea, 0xbf, 0x0, - 0x0, 0x1b, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+EF7A "" */ - 0x0, 0x55, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x1f, 0x41, 0xf4, 0x0, 0x3c, 0x0, 0x3c, 0x0, - 0x74, 0x0, 0x2c, 0x0, 0x70, 0x0, 0x1d, 0x0, - 0x74, 0x0, 0x1d, 0x0, 0x38, 0x0, 0x2c, 0x0, - 0x3d, 0x0, 0x78, 0x0, 0xf, 0xeb, 0xfc, 0x0, - 0x2, 0xff, 0x5f, 0x0, 0x0, 0x0, 0x7, 0xc0, - 0x0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0x0, 0x7c, - 0x0, 0x0, 0x0, 0x1c, - - /* U+EFE6 "" */ - 0x0, 0x54, 0x1, 0x90, 0x3, 0xfe, 0x3, 0xf0, - 0xb, 0x8b, 0x4b, 0xf8, 0xf, 0x3, 0x8f, 0xfc, - 0xf, 0x3, 0x8f, 0xfc, 0xf, 0x3, 0x8f, 0xfc, - 0xf, 0x3, 0x81, 0xe0, 0xf, 0x3, 0x81, 0xd0, - 0xf, 0x3, 0x81, 0xd0, 0x1f, 0x43, 0x81, 0xd0, - 0xbf, 0xc3, 0x81, 0xd0, 0xbf, 0xd3, 0x81, 0xd0, - 0xbf, 0xd3, 0x81, 0xd0, 0x7f, 0xc2, 0xd3, 0xc0, - 0x2f, 0x80, 0xff, 0x40, 0xa, 0x0, 0x14, 0x0, - - /* U+F028 "" */ - 0xa, 0xaa, 0xaa, 0xaa, 0xa0, 0x3f, 0xff, 0xff, - 0xff, 0xfc, 0x38, 0x0, 0x0, 0x0, 0x2c, 0x38, - 0x0, 0x0, 0x0, 0x2c, 0x38, 0xb1, 0xc3, 0x4a, - 0x2c, 0x38, 0x0, 0x0, 0x0, 0x2c, 0x38, 0x50, - 0x81, 0x5, 0x2c, 0x38, 0xb1, 0xc3, 0x4a, 0x2c, - 0x38, 0x0, 0x0, 0x0, 0x2c, 0x38, 0x2, 0xaa, - 0x80, 0x2c, 0x38, 0x3, 0xff, 0xc0, 0x2c, 0x38, - 0x0, 0x0, 0x0, 0x2c, 0x3f, 0xff, 0xff, 0xff, - 0xfc, 0xa, 0xaa, 0xaa, 0xaa, 0xa0, - - /* U+F090 "" */ - 0x0, 0x5, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, - 0xe, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0xe, - 0x0, 0x0, 0x14, 0xe2, 0x40, 0x3, 0xde, 0xb8, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x3f, 0x80, 0x1, - 0x0, 0xe0, 0x4, 0xb0, 0x0, 0x0, 0xeb, 0x0, - 0x0, 0xe, 0xbf, 0xff, 0xff, 0xe2, 0xaa, 0xaa, - 0xa8, - - /* U+F15C "" */ - 0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xd0, 0x0, 0x0, 0x2f, 0x41, 0xf4, 0x0, 0x0, - 0x3c, 0x0, 0x3c, 0x0, 0x0, 0xb0, 0x0, 0x1d, - 0x0, 0x7, 0xf0, 0x0, 0xe, 0x0, 0x1f, 0x40, - 0x0, 0xf, 0x80, 0x3c, 0x0, 0x0, 0xf, 0xf0, - 0x38, 0x0, 0x0, 0x0, 0x3c, 0x38, 0x0, 0x0, - 0x0, 0x2c, 0x3c, 0x0, 0x0, 0x0, 0x2c, 0x1e, - 0x0, 0x0, 0x0, 0x7c, 0xb, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0xaa, 0xaa, 0xaa, 0x80, - - /* U+F720 "" */ - 0x0, 0x1, 0x40, 0x0, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0xfd, 0xbe, 0x0, 0xb, 0xe0, 0xb, 0xe0, - 0x3e, 0x0, 0x0, 0xfc, 0xbe, 0x0, 0x0, 0xfd, - 0xbb, 0xe0, 0xb, 0xed, 0xb0, 0xfd, 0x7e, 0x1d, - 0xb0, 0x1f, 0xf4, 0x1d, 0xb0, 0x3, 0xc0, 0x1d, - 0xb0, 0x3, 0x80, 0x1d, 0xb0, 0x3, 0x80, 0x1d, - 0x78, 0x3, 0x80, 0x3d, 0x2f, 0x43, 0x82, 0xf8, - 0x7, 0xf7, 0xdf, 0xc0, 0x0, 0x7f, 0xfd, 0x0, - 0x0, 0xb, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x0, - 0x0, 0x0, 0x0, 0xb0, 0x0, 0x0, 0x10, 0xb, - 0x0, 0x50, 0xf, 0x0, 0xb0, 0xf, 0x1, 0xd0, - 0xb, 0x0, 0x78, 0x3c, 0x0, 0xb0, 0x2, 0xc3, - 0x80, 0xb, 0x0, 0x1d, 0x34, 0x0, 0xb0, 0x1, - 0xd3, 0x40, 0x6, 0x0, 0x1d, 0x38, 0x0, 0x0, - 0x1, 0xc3, 0xc0, 0x0, 0x0, 0x3c, 0x1d, 0x0, - 0x0, 0x7, 0x80, 0xf4, 0x0, 0x0, 0xf0, 0x3, - 0xe0, 0x0, 0x7c, 0x0, 0xb, 0xea, 0xbf, 0x0, - 0x0, 0x1b, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+FFF75 "󿽵" */ - 0x2a, 0xaa, 0xaa, 0xa9, 0x3, 0xff, 0xff, 0xff, - 0xfc, 0x38, 0x0, 0x0, 0x1, 0xd3, 0x89, 0x7, - 0x3, 0xe, 0x38, 0x0, 0x0, 0x0, 0xe3, 0xff, - 0xff, 0xff, 0xfe, 0x2a, 0xab, 0xff, 0xab, 0xe0, - 0x1, 0xff, 0x44, 0xe, 0x6, 0xfe, 0x0, 0x82, - 0xd2, 0xf9, 0x2, 0x6, 0xf8, 0x38, 0x30, 0x1b, - 0xf8, 0x3, 0xea, 0xaf, 0xfe, 0xa9, 0x3f, 0xff, - 0xff, 0xff, 0xe3, 0x80, 0x0, 0x1, 0xe, 0x38, - 0x90, 0x20, 0x20, 0xe3, 0xea, 0xaa, 0xaa, 0xae, - 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 320, .box_w = 12, .box_h = 12, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 36, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 99, .adv_w = 320, .box_w = 11, .box_h = 16, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 143, .adv_w = 320, .box_w = 12, .box_h = 18, .ofs_x = 4, .ofs_y = 1}, - {.bitmap_index = 197, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 292, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 355, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 436, .adv_w = 320, .box_w = 10, .box_h = 6, .ofs_x = 5, .ofs_y = 7}, - {.bitmap_index = 451, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 514, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 595, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 659, .adv_w = 320, .box_w = 10, .box_h = 16, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 699, .adv_w = 320, .box_w = 14, .box_h = 16, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 755, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 804, .adv_w = 320, .box_w = 12, .box_h = 12, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 840, .adv_w = 320, .box_w = 16, .box_h = 10, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 880, .adv_w = 320, .box_w = 4, .box_h = 14, .ofs_x = 8, .ofs_y = 3}, - {.bitmap_index = 894, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 943, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 1018, .adv_w = 320, .box_w = 14, .box_h = 10, .ofs_x = 3, .ofs_y = 5}, - {.bitmap_index = 1053, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 1109, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = 3}, - {.bitmap_index = 1165, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 1228, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1305, .adv_w = 320, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 1382, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1463, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 1526, .adv_w = 320, .box_w = 14, .box_h = 16, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 1582, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 1645, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1745, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1809, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 1890, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1954, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 2017, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 2089, .adv_w = 320, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 2161, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 2224, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 2280, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 2361, .adv_w = 320, .box_w = 16, .box_h = 15, .ofs_x = 2, .ofs_y = 3}, - {.bitmap_index = 2421, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 2485, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 2555, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 2604, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 2674, .adv_w = 320, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 2746, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 2827, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_20 = { -#else -lv_font_t material_symbols_shared_20 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 20, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_20*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_24.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_24.c deleted file mode 100644 index 005cb209f..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_24.c +++ /dev/null @@ -1,748 +0,0 @@ -/******************************************************************************* - * Size: 24 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 24 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_24.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_24 -#define MATERIAL_SYMBOLS_SHARED_24 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_24 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0xf, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, - 0xf, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xf, - 0x0, 0x0, 0x0, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0x0, 0x0, - 0x0, 0xf0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, - 0xf0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0xf0, - 0x0, - - /* U+E159 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0x40, 0x0, 0x1, 0xff, 0xf7, 0xf0, 0x0, 0xf, - 0xdf, 0xf0, 0xbe, 0x0, 0xbe, 0xf, 0xf0, 0xf, - 0xd7, 0xf0, 0xf, 0xf0, 0x1, 0xff, 0x40, 0xf, - 0xf0, 0x0, 0x28, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, - - /* U+E1A7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, - 0xfd, 0x0, 0x40, 0x3f, 0xd0, 0xb8, 0xf, 0xbd, - 0xf, 0x83, 0xcb, 0xc0, 0xf8, 0xf2, 0xf0, 0xf, - 0xbe, 0xf0, 0x0, 0xff, 0xf0, 0x0, 0xf, 0xf0, - 0x0, 0x2, 0xf8, 0x0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0xf8, 0x2, 0xf3, 0xcf, 0x82, 0xf0, 0xf1, - 0xf1, 0xf0, 0x3c, 0xf8, 0x60, 0xf, 0xf8, 0x0, - 0x3, 0xf8, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x28, - 0x0, - - /* U+E1E0 "" */ - 0x0, 0x5, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0x7, 0xfd, 0x0, 0x0, 0xf, - 0x0, 0x0, 0x0, 0xf0, 0x0, 0x7d, 0xf, 0xf, - 0xff, 0xf0, 0xf0, 0xff, 0xff, 0xf, 0xf, 0xf7, - 0xd0, 0xf0, 0xff, 0x3c, 0xf, 0x3, 0xc3, 0xc0, - 0xf0, 0x3c, 0x3f, 0xff, 0xff, 0xc1, 0xff, 0xff, - 0xf4, 0x0, 0xf, 0x0, 0x0, 0x0, 0xf0, 0x0, - 0x0, 0xf, 0x40, 0x0, 0x3, 0xfc, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0x1, 0xf4, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x2f, 0x80, 0x0, 0x0, 0x0, 0xb, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xf0, 0x0, - 0x0, 0x0, 0xf, 0xf, 0x0, 0x0, 0x0, 0x0, - 0xf0, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf, 0x0, - 0x0, 0x0, 0x0, 0xf0, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xf, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xfd, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0xf, 0x0, 0x0, 0x0, 0xf, 0x0, - 0xf0, 0x0, 0x0, 0x0, 0xf0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0x1, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x2d, 0x0, 0x0, 0x0, 0x7, 0x83, 0xc3, 0xc0, - 0xf0, 0x3c, 0x3c, 0x3c, 0x3c, 0xf, 0x3, 0xc3, - 0xc7, 0x83, 0xc0, 0xf0, 0x3c, 0x2d, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xd2, 0xff, 0xff, 0xff, 0xff, - 0xf8, - - /* U+E2C7 "" */ - 0x7f, 0xff, 0x40, 0x0, 0x0, 0xff, 0xff, 0xe0, - 0x0, 0x0, 0xf0, 0x1, 0xff, 0xff, 0xfd, 0xf0, - 0x0, 0x7f, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, - - /* U+E30F "" */ - 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x3, 0xff, - 0xc0, 0x0, 0x0, 0x3, 0xc3, 0xc0, 0x0, 0x0, - 0x3, 0xc3, 0xc0, 0x0, 0x0, 0x3, 0xc3, 0xc0, - 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0xf0, 0x3c, 0xf, 0xff, - 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xf0, 0x3f, 0x0, - 0xfc, 0xf, 0xf0, 0x3f, 0x0, 0xfc, 0xf, 0xff, - 0xfc, 0x0, 0x3f, 0xff, 0xff, 0xf0, 0x3c, 0xf, - 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xc0, 0x0, 0x0, 0x3, 0xc3, 0xc0, 0x0, - 0x0, 0x3, 0xc3, 0xc0, 0x0, 0x0, 0x3, 0xc3, - 0xc0, 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, - - /* U+E316 "" */ - 0x0, 0x14, 0x0, 0x0, 0xbd, 0x0, 0x2, 0xff, - 0x40, 0xb, 0xc7, 0xd0, 0x2f, 0x1, 0xf4, 0xbc, - 0x0, 0x7c, 0xb0, 0x0, 0x1c, - - /* U+E326 "" */ - 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, - 0xff, 0xfc, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x3c, - 0x0, 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0xbf, - 0xfe, 0x3c, 0x0, 0x0, 0xff, 0xff, 0x3c, 0x0, - 0x0, 0xf0, 0xf, 0x3c, 0x0, 0x0, 0xf2, 0x8f, - 0x3c, 0x0, 0x0, 0xf0, 0xf, 0x3c, 0x0, 0x0, - 0xf0, 0xf, 0x3c, 0x0, 0x0, 0xf0, 0xf, 0x3f, - 0xff, 0xf0, 0xf0, 0xf, 0x1f, 0xff, 0xf0, 0xf0, - 0xf, 0x0, 0x0, 0x0, 0xf0, 0xf, 0xff, 0xff, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xbf, 0xfe, - - /* U+E3AF "" */ - 0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x2, 0xfd, 0x3, 0x7f, 0x80, 0xb, - 0xd0, 0x9, 0x7, 0xe0, 0x1f, 0x80, 0x1c, 0x1, - 0xf4, 0x3e, 0xc0, 0x34, 0x0, 0x7c, 0x7c, 0x60, - 0x70, 0x0, 0x3d, 0xb4, 0x30, 0xff, 0xff, 0xfe, - 0xf0, 0x1f, 0xff, 0xc0, 0xf, 0xf0, 0xb, 0xff, - 0xc0, 0xf, 0xf0, 0x3, 0xff, 0xe0, 0xf, 0xf0, - 0x3, 0xff, 0xf4, 0xf, 0xbf, 0xff, 0xff, 0xc, - 0x1e, 0x7c, 0x0, 0xd, 0x9, 0x3d, 0x3d, 0x0, - 0x1c, 0x3, 0xbc, 0x1f, 0x40, 0x34, 0x2, 0xf4, - 0xb, 0xd0, 0x60, 0x7, 0xe0, 0x2, 0xfd, 0xc0, - 0x7f, 0x80, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x6, 0xff, 0x90, 0x0, - - /* U+E3F4 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x10, 0xf, 0xf0, 0x14, 0xf, - 0x40, 0xff, 0x3, 0xc2, 0xfc, 0xf, 0xf0, 0xff, - 0x7f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0x4f, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, - 0xfd, - - /* U+E405 "" */ - 0x0, 0xf, 0xff, 0x0, 0xf, 0xff, 0x0, 0xf, - 0xff, 0x0, 0xf, 0xff, 0x0, 0xf, 0x0, 0x0, - 0xf, 0x0, 0x0, 0xf, 0x0, 0x0, 0xf, 0x0, - 0x0, 0xf, 0x0, 0x0, 0xf, 0x0, 0xb, 0xef, - 0x0, 0x3f, 0xff, 0x0, 0xbf, 0xff, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xff, 0x0, 0xbf, 0xfe, 0x0, - 0x3f, 0xfc, 0x0, 0xb, 0xe0, 0x0, - - /* U+E55D "" */ - 0x0, 0x1, 0x40, 0x0, 0x0, 0x3, 0xc0, 0x0, - 0x0, 0xb, 0xe0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x1e, 0xb4, 0x0, 0x0, 0x3d, 0x7c, 0x0, - 0x0, 0x7c, 0x3d, 0x0, 0x0, 0xf4, 0x1f, 0x0, - 0x0, 0xf0, 0xf, 0x0, 0x2, 0xe0, 0xb, 0x80, - 0x3, 0xc0, 0x3, 0xc0, 0xb, 0x80, 0x2, 0xe0, - 0xf, 0x0, 0x0, 0xf0, 0x1e, 0xb, 0xe0, 0xb4, - 0x3e, 0xbf, 0xfe, 0xbc, 0x7f, 0xf8, 0x2f, 0xfd, - 0xbf, 0x40, 0x1, 0xfe, 0x64, 0x0, 0x0, 0x19, - - /* U+E5C3 "" */ - 0x7d, 0x7, 0xd0, 0x7d, 0xff, 0xf, 0xf0, 0xff, - 0xff, 0xf, 0xf0, 0xff, 0x7d, 0x7, 0xd0, 0x7d, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7d, 0x7, 0xd0, 0x7d, 0xff, 0xf, 0xf0, 0xff, - 0xff, 0xf, 0xf0, 0xff, 0x7d, 0x7, 0xd0, 0x7d, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7d, 0x7, 0xd0, 0x7d, 0xff, 0xf, 0xf0, 0xff, - 0xff, 0xf, 0xf0, 0xff, 0x7d, 0x7, 0xd0, 0x7d, - - /* U+E5CD "" */ - 0x10, 0x0, 0x0, 0x4b, 0x40, 0x0, 0x3d, 0x7d, - 0x0, 0xf, 0xc1, 0xf4, 0x3, 0xf0, 0x7, 0xd0, - 0xfc, 0x0, 0x1f, 0xbf, 0x0, 0x0, 0x7f, 0xc0, - 0x0, 0x3, 0xf8, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x3f, 0x1f, 0x40, 0xf, 0xc0, 0x7d, 0x3, 0xf0, - 0x1, 0xf4, 0xbc, 0x0, 0x7, 0xd6, 0x0, 0x0, - 0x18, - - /* U+E5D2 "" */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - - /* U+E5D4 "" */ - 0x7d, 0xff, 0xff, 0x7d, 0x0, 0x0, 0x7d, 0xff, - 0xff, 0x7d, 0x0, 0x0, 0x7d, 0xff, 0xff, 0x7d, - - /* U+E5D5 "" */ - 0x0, 0x2f, 0xf8, 0xf, 0x2, 0xff, 0xff, 0x8f, - 0xf, 0xe0, 0xb, 0xef, 0x2f, 0x0, 0x0, 0xff, - 0x3c, 0x0, 0x0, 0x3f, 0xb8, 0x0, 0x3f, 0xff, - 0xf0, 0x0, 0x3f, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xf0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, - 0xb8, 0x0, 0x0, 0x18, 0x3c, 0x0, 0x0, 0x3c, - 0x2f, 0x0, 0x0, 0xf8, 0xf, 0xe0, 0xb, 0xe0, - 0x2, 0xff, 0xff, 0x80, 0x0, 0x2f, 0xf8, 0x0, - - /* U+E63E "" */ - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xf9, 0x0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0xf, 0xff, 0x90, 0x1, 0xbf, 0xf4, - 0x3f, 0xe0, 0x0, 0x0, 0xb, 0xfd, 0x3f, 0x40, - 0x0, 0x0, 0x0, 0xfd, 0x4, 0x0, 0x6f, 0xf9, - 0x0, 0x14, 0x0, 0x7, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x3f, - 0xd0, 0x7, 0xfc, 0x0, 0x0, 0x19, 0x0, 0x0, - 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x3e, - 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x3, 0xf0, - 0x0, 0x0, 0xf, 0xc0, 0x60, 0x0, 0x3f, 0x0, - 0xbc, 0x0, 0xfc, 0x0, 0x3f, 0x3, 0xf0, 0x0, - 0xf, 0xcf, 0xc0, 0x0, 0x3, 0xff, 0x0, 0x0, - 0x0, 0xfc, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, - - /* U+E745 "" */ - 0xff, 0xff, 0xfc, 0x0, 0xf, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xfc, 0x0, 0xf, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb8, 0xff, 0xfc, 0x0, 0x2f, - 0xef, 0xff, 0xc0, 0xb, 0xff, 0x0, 0x0, 0x2, - 0xff, 0xe0, 0x0, 0x0, 0xb8, 0xf8, 0x0, 0x0, - 0x2e, 0x2e, 0x0, 0x0, 0x3, 0x8b, 0x80, 0x0, - 0x0, 0x3e, 0xe0, 0x0, 0x0, 0x3, 0xf8, 0x0, - - /* U+E770 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x7c, - 0xbd, 0x0, 0x0, 0xf, 0x42, 0xff, 0xdf, 0x3, - 0xe0, 0x7, 0xff, 0xfd, 0xbc, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf7, 0xd0, 0x0, 0x0, - 0xff, 0x8, 0xb, 0x40, 0xf, 0xf0, 0x1, 0xfe, - 0x0, 0xff, 0x0, 0x3f, 0xfc, 0xf, 0xfc, 0xf, - 0xff, 0xf0, 0xff, 0xf6, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, - - /* U+E89C "" */ - 0x7f, 0xff, 0xf4, 0x0, 0xff, 0xff, 0xfe, 0x0, - 0xf0, 0x0, 0x3f, 0x80, 0xf0, 0x0, 0x3f, 0xe0, - 0xf0, 0x0, 0x3f, 0xf8, 0xf0, 0x0, 0x3f, 0xfd, - 0xf0, 0x0, 0x3f, 0xff, 0xf0, 0x0, 0x0, 0xf, - 0xf0, 0x3, 0xc0, 0xf, 0xf0, 0x3, 0xc0, 0xf, - 0xf0, 0x3, 0xc0, 0xf, 0xf0, 0xff, 0xff, 0xf, - 0xf0, 0xff, 0xff, 0xf, 0xf0, 0x3, 0xc0, 0xf, - 0xf0, 0x3, 0xc0, 0xf, 0xf0, 0x3, 0xc0, 0xf, - 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfd, - - /* U+E8AF "" */ - 0x7f, 0xff, 0xff, 0xf4, 0x0, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0xf0, 0x0, 0x0, 0x3c, 0x0, 0xf0, - 0x0, 0x0, 0x3c, 0x0, 0xf0, 0x0, 0x0, 0x3c, - 0x3d, 0xf0, 0x0, 0x0, 0x3c, 0x3f, 0xf0, 0x0, - 0x0, 0x3c, 0x3f, 0xf0, 0x0, 0x0, 0x3c, 0x3f, - 0xf0, 0x0, 0x0, 0x3c, 0x3f, 0xf7, 0xff, 0xff, - 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xf4, 0x3f, 0xfd, - 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, - 0xbf, 0x50, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x5, - - /* U+E8B8 "" */ - 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x80, 0x0, 0x0, 0x7, 0x83, 0xc0, 0x0, 0xb, - 0x9f, 0x83, 0xd6, 0xd0, 0x2f, 0xff, 0x43, 0xff, - 0xf0, 0x3d, 0xb8, 0x0, 0x7d, 0xb8, 0xb8, 0x0, - 0x14, 0x0, 0x3c, 0xbd, 0x2, 0xff, 0x40, 0xbc, - 0x2f, 0x47, 0xff, 0xc3, 0xf4, 0xf, 0x4b, 0xff, - 0xd3, 0xd0, 0xf, 0x4b, 0xff, 0xd3, 0xd0, 0x2f, - 0x47, 0xff, 0xc3, 0xf4, 0xbd, 0x2, 0xff, 0x40, - 0xbc, 0xb8, 0x0, 0x14, 0x0, 0x3c, 0x3d, 0xb8, - 0x0, 0x7d, 0xb8, 0x2f, 0xff, 0x43, 0xff, 0xf0, - 0xb, 0x9f, 0x83, 0xd6, 0xd0, 0x0, 0x7, 0x83, - 0xc0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, - 0x2, 0xff, 0x0, 0x0, - - /* U+E8FD "" */ - 0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x2, 0xfd, 0x0, 0x7f, 0x80, 0xb, - 0xd0, 0x0, 0x7, 0xe0, 0x1f, 0x0, 0xbe, 0x0, - 0xf4, 0x3d, 0x3, 0xff, 0xc0, 0x7c, 0x7c, 0x3, - 0x42, 0xd0, 0x3d, 0xb4, 0x0, 0x1, 0xd0, 0x1e, - 0xf0, 0x0, 0x3, 0xc0, 0xf, 0xf0, 0x0, 0xf, - 0x0, 0xf, 0xf0, 0x0, 0x2d, 0x0, 0xf, 0xf0, - 0x0, 0x3c, 0x0, 0xf, 0xb4, 0x0, 0x0, 0x0, - 0x1e, 0x7c, 0x0, 0x14, 0x0, 0x3d, 0x3d, 0x0, - 0x3c, 0x0, 0x7c, 0x1f, 0x0, 0x3c, 0x0, 0xf4, - 0xb, 0xd0, 0x0, 0x7, 0xe0, 0x2, 0xfd, 0x0, - 0x7f, 0x80, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x6, 0xff, 0x90, 0x0, - - /* U+E90F "" */ - 0x0, 0x6f, 0xf4, 0x0, 0x2, 0xff, 0xff, 0x40, - 0xf, 0xd0, 0x1b, 0xd0, 0x2f, 0x0, 0x2, 0xf0, - 0x3c, 0x0, 0x0, 0xb8, 0x78, 0x0, 0x0, 0x3c, - 0xb4, 0x0, 0x0, 0x3c, 0xb4, 0x0, 0x0, 0x3c, - 0xb4, 0x0, 0x0, 0x3c, 0x78, 0x0, 0x0, 0x3c, - 0x3c, 0x0, 0x0, 0xb8, 0x2f, 0x0, 0x2, 0xf0, - 0xb, 0xff, 0xff, 0xd0, 0x2, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, - 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xe0, 0x0, 0x0, 0x7, 0xc0, 0x0, - - /* U+E92E "" */ - 0x0, 0x3f, 0xfc, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3c, 0x0, 0x0, 0x3c, - 0x3c, 0x0, 0x0, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x0, 0x0, 0x3c, 0x3c, 0x0, 0x0, 0x3c, - 0x3f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xf4, - - /* U+E9B9 "" */ - 0x7d, 0x7, 0xff, 0xff, 0xfd, 0xff, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0x7d, - 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, 0x7, - 0xff, 0xff, 0xfd, 0xff, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0x7d, 0x7, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7d, 0x7, 0xff, 0xff, - 0xfd, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf, - 0xff, 0xff, 0xff, 0x7d, 0x7, 0xff, 0xff, 0xfd, - - /* U+E9F4 "" */ - 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x7c, - 0x0, 0x0, 0x0, 0x0, 0x3c, 0x7c, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0x0, 0x5, 0x0, 0x3, 0x80, - 0x0, 0x50, 0x3f, 0xc0, 0x3, 0x80, 0x3, 0xfc, - 0xbf, 0xe0, 0xb, 0xd0, 0xb, 0xfe, 0xf0, 0xf0, - 0x3f, 0xfc, 0xf, 0xf, 0xfa, 0xfe, 0xf9, 0x7f, - 0xbf, 0xaf, 0x7f, 0xeb, 0xf0, 0xf, 0xeb, 0xfd, - 0x1a, 0x41, 0xe0, 0xb, 0x41, 0xa4, 0x0, 0x1, - 0xe0, 0xb, 0x40, 0x0, 0x0, 0x0, 0xf4, 0x1f, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xfb, 0xef, 0x0, 0x0, 0x0, 0xbf, - 0xc0, 0x3, 0xfe, 0x0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0x80, 0x3, 0xc3, 0xc0, 0x3, 0xc3, 0xc0, - 0x3, 0xc3, 0xc0, 0x3, 0xc3, 0xc0, 0x2, 0xff, - 0x80, 0x2, 0xff, 0x80, 0x0, 0xbe, 0x0, 0x0, - 0xbe, 0x0, - - /* U+E9F7 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, - 0xfd, - - /* U+EA07 "" */ - 0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x2, 0xff, 0xef, 0xff, 0x80, 0xb, - 0xd7, 0xc7, 0xcb, 0xe0, 0x1f, 0xb, 0x43, 0xd1, - 0xf4, 0x3d, 0xf, 0x2, 0xe0, 0xbc, 0x7f, 0xff, - 0xff, 0xff, 0xfd, 0xbf, 0xff, 0xff, 0xff, 0xfe, - 0xf0, 0x2d, 0x0, 0xf0, 0xf, 0xf0, 0x2d, 0x0, - 0xb4, 0xf, 0xf0, 0x2d, 0x0, 0xb4, 0xf, 0xf0, - 0x2d, 0x0, 0xf0, 0xf, 0xbf, 0xff, 0xff, 0xff, - 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x3d, 0xf, - 0x2, 0xe0, 0xbc, 0x1f, 0xb, 0x43, 0xd1, 0xf4, - 0xb, 0xd7, 0xc7, 0xcb, 0xe0, 0x2, 0xff, 0xef, - 0xff, 0x80, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x6, 0xff, 0x90, 0x0, - - /* U+EAD6 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xf3, 0xf3, 0xf3, 0xc, 0xff, - 0x32, 0x74, 0x35, 0xcf, 0xf3, 0x27, 0x82, 0xa8, - 0xff, 0x32, 0x78, 0x1f, 0x4f, 0xf3, 0x27, 0x40, - 0xf0, 0xff, 0x3f, 0x3f, 0xa, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, - 0xfd, - - /* U+EB8E "" */ - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x20, 0x0, 0x0, 0xf, 0xf0, 0x7c, - 0x0, 0x0, 0xf, 0xf0, 0x3f, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xc0, 0x0, 0xf, 0xf0, 0xf, 0xc0, - 0x0, 0xf, 0xf0, 0x3f, 0x0, 0x0, 0xf, 0xf0, - 0x7c, 0xf, 0xff, 0xf, 0xf0, 0x20, 0xf, 0xff, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, - - /* U+EB97 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x34, - 0xf, 0xf0, 0xaa, 0xaa, 0x3e, 0xf, 0xf0, 0xaa, - 0xaa, 0x3e, 0xf, 0xf0, 0x0, 0x0, 0x34, 0xf, - 0xf0, 0x1c, 0x0, 0x0, 0xf, 0xf0, 0xbc, 0xaa, - 0xaa, 0xf, 0xf0, 0xbc, 0xaa, 0xaa, 0xf, 0xf0, - 0x1c, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, - 0xf0, 0x0, - - /* U+EBCC "" */ - 0x3, 0xc0, 0x0, 0x3c, 0x0, 0x3c, 0x0, 0x3, - 0xc0, 0x7f, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf0, 0xf0, - 0xf0, 0xff, 0xf, 0xf, 0xf, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf0, 0xf0, 0xf0, 0xff, 0xf, 0xf, 0xf, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, - 0xff, 0xfd, - - /* U+EC1C "" */ - 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x2f, 0x0, - 0x0, 0x0, 0xbe, 0x0, 0x0, 0x2, 0xfc, 0x0, - 0x0, 0xb, 0xf8, 0x0, 0x0, 0x2f, 0xf0, 0x0, - 0x0, 0xbf, 0xe0, 0x0, 0x3, 0xf7, 0xe4, 0x0, - 0xf, 0xcf, 0xff, 0xfd, 0x3f, 0x1, 0x6b, 0xfe, - 0xbf, 0xe9, 0x40, 0xfc, 0x7f, 0xff, 0xf3, 0xf0, - 0x0, 0x1b, 0xdf, 0xc0, 0x0, 0xb, 0xfe, 0x0, - 0x0, 0xf, 0xf8, 0x0, 0x0, 0x2f, 0xe0, 0x0, - 0x0, 0x3f, 0x80, 0x0, 0x0, 0xbe, 0x0, 0x0, - 0x0, 0xf8, 0x0, 0x0, 0x1, 0xe0, 0x0, 0x0, - - /* U+EF40 "" */ - 0x7d, 0x7, 0xd0, 0x7d, 0xf, 0xf0, 0xff, 0xf, - 0xf0, 0xff, 0xf, 0xf0, 0xff, 0x7, 0xd0, 0x7d, - 0x7, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7d, 0x7, 0xd0, 0x0, 0xf, - 0xf0, 0xff, 0x0, 0xb8, 0xff, 0xf, 0xf0, 0x2f, - 0xe7, 0xd0, 0x7d, 0xb, 0xff, 0x0, 0x0, 0x2, - 0xff, 0xe0, 0x0, 0x0, 0xb8, 0xf8, 0x7d, 0x0, - 0x2e, 0x2e, 0xf, 0xf0, 0x3, 0x8b, 0x80, 0xff, - 0x0, 0x3e, 0xe0, 0x7, 0xd0, 0x3, 0xf8, 0x0, - - /* U+EF4A "" */ - 0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x2, 0xfd, 0x0, 0x7f, 0x80, 0xb, - 0xd0, 0x0, 0x7, 0xe0, 0x1f, 0x0, 0x0, 0x0, - 0xf4, 0x3d, 0x0, 0x0, 0x0, 0x7c, 0x7c, 0x0, - 0x0, 0x0, 0x3d, 0xb4, 0x0, 0x0, 0x0, 0x1e, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xb4, 0x0, 0x0, 0x0, - 0x1e, 0x7c, 0x0, 0x0, 0x0, 0x3d, 0x3d, 0x0, - 0x0, 0x0, 0x7c, 0x1f, 0x0, 0x0, 0x0, 0xf4, - 0xb, 0xd0, 0x0, 0x7, 0xe0, 0x2, 0xfd, 0x0, - 0x7f, 0x80, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x6, 0xff, 0x90, 0x0, - - /* U+EF7A "" */ - 0x1, 0xbf, 0x90, 0x0, 0x0, 0xbf, 0xff, 0x80, - 0x0, 0x2f, 0x40, 0x7e, 0x0, 0x7, 0xc0, 0x0, - 0xf4, 0x0, 0xb4, 0x0, 0x7, 0x80, 0xf, 0x0, - 0x0, 0x3c, 0x0, 0xf0, 0x0, 0x3, 0xc0, 0xf, - 0x0, 0x0, 0x3c, 0x0, 0xb4, 0x0, 0x7, 0x80, - 0x7, 0xc0, 0x0, 0xf0, 0x0, 0x2f, 0x40, 0x7f, - 0x0, 0x0, 0xbf, 0xff, 0xfc, 0x0, 0x1, 0xbf, - 0x83, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x0, - 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0xfc, - 0x0, 0x0, 0x0, 0x3, 0xe0, 0x0, 0x0, 0x0, - 0x8, - - /* U+EFE6 "" */ - 0x0, 0xbe, 0x0, 0x3f, 0xc0, 0x3f, 0xfc, 0x3, - 0xfc, 0xb, 0x82, 0xe0, 0xbf, 0xe0, 0xf0, 0xf, - 0xf, 0xff, 0xf, 0x0, 0xf0, 0xff, 0xf0, 0xf0, - 0xf, 0xf, 0xff, 0xf, 0x0, 0xf0, 0xff, 0xf0, - 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, - 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, - 0xf, 0xf, 0xff, 0xf, 0x0, 0xf0, 0xff, 0xf0, - 0xf0, 0xf, 0xf, 0xff, 0xf, 0x0, 0xf0, 0xff, - 0xf0, 0xf0, 0xf, 0xb, 0xfe, 0xb, 0x82, 0xe0, - 0x3f, 0xc0, 0x3f, 0xfc, 0x3, 0xfc, 0x0, 0xbe, - 0x0, - - /* U+F028 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xff, 0xf, 0xf, 0xf, 0xf, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x5, - 0x5, 0x5, 0x5, 0xf, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xff, 0x5, 0x5, 0x5, 0x5, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x3f, 0xff, - 0xc0, 0xf, 0xf0, 0x3, 0xff, 0xfc, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F090 "" */ - 0x0, 0x3, 0xc0, 0x0, 0x0, 0x3, 0xc0, 0x0, - 0x0, 0x3, 0xc0, 0x0, 0x0, 0x3, 0xc0, 0x0, - 0x0, 0x3, 0xc0, 0x0, 0x0, 0x3, 0xc0, 0x0, - 0x1, 0xd3, 0xc7, 0x40, 0x1, 0xf7, 0xdf, 0x40, - 0x0, 0xbf, 0xfd, 0x0, 0x0, 0x2f, 0xf4, 0x0, - 0x0, 0xb, 0xd0, 0x0, 0xf0, 0x1, 0x40, 0xf, - 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfd, - - /* U+F15C "" */ - 0x0, 0x0, 0xbf, 0xe0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xd0, 0x0, 0x0, 0x1f, 0x80, 0x2f, 0x40, - 0x0, 0x3, 0xd0, 0x0, 0x7c, 0x0, 0x0, 0xb8, - 0x0, 0x2, 0xe0, 0x0, 0x2f, 0x0, 0x0, 0xf, - 0x0, 0x1f, 0xf0, 0x0, 0x0, 0xf0, 0x3, 0xe0, - 0x0, 0x0, 0xf, 0xe0, 0xb8, 0x0, 0x0, 0x0, - 0xff, 0xcf, 0x0, 0x0, 0x0, 0x0, 0x7e, 0xf0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xb8, 0x0, 0x0, 0x0, 0x1, 0xf3, - 0xe0, 0x0, 0x0, 0x0, 0x7e, 0x1f, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x2f, 0xff, 0xff, 0xff, 0xe0, - - /* U+F720 "" */ - 0x0, 0x1, 0xf4, 0x0, 0x0, 0x1, 0xff, 0xf4, - 0x0, 0x0, 0xbf, 0x5f, 0xe0, 0x0, 0xbf, 0x40, - 0x1f, 0xe0, 0x3f, 0x80, 0x0, 0x2f, 0xcf, 0xe0, - 0x0, 0x0, 0xbf, 0xff, 0xc0, 0x0, 0x3f, 0xff, - 0x7f, 0x80, 0x2f, 0xdf, 0xf0, 0xbf, 0x5f, 0xe0, - 0xff, 0x0, 0xbf, 0xe0, 0xf, 0xf0, 0x1, 0xf4, - 0x0, 0xff, 0x0, 0xf, 0x0, 0xf, 0xf0, 0x0, - 0xf0, 0x0, 0xff, 0x0, 0xf, 0x0, 0xf, 0xfc, - 0x0, 0xf0, 0x3, 0xf7, 0xf8, 0xf, 0x2, 0xfd, - 0xb, 0xf4, 0xf1, 0xfe, 0x0, 0xb, 0xff, 0xfe, - 0x0, 0x0, 0x1f, 0xff, 0x40, 0x0, 0x0, 0x1f, - 0x40, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x3c, - 0x0, 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x5, - 0x0, 0x3c, 0x0, 0x50, 0x1f, 0x0, 0x3c, 0x0, - 0xf4, 0x3d, 0x0, 0x3c, 0x0, 0x7c, 0x7c, 0x0, - 0x3c, 0x0, 0x3d, 0xb4, 0x0, 0x3c, 0x0, 0x1e, - 0xf0, 0x0, 0x3c, 0x0, 0xf, 0xf0, 0x0, 0x3c, - 0x0, 0xf, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xb4, 0x0, 0x0, 0x0, - 0x1e, 0x7c, 0x0, 0x0, 0x0, 0x3d, 0x3d, 0x0, - 0x0, 0x0, 0x7c, 0x1f, 0x0, 0x0, 0x0, 0xf4, - 0xb, 0xd0, 0x0, 0x7, 0xe0, 0x2, 0xfd, 0x0, - 0x7f, 0x80, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x6, 0xff, 0x90, 0x0, - - /* U+FFF75 "󿽵" */ - 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xd0, 0x28, 0x7, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x2, 0xff, 0x80, 0xf, - 0x0, 0x7f, 0xf4, 0x28, 0xf, 0xb, 0xfe, 0x0, - 0x0, 0x2f, 0x7f, 0x90, 0x28, 0x7, 0xfd, 0xf8, - 0x34, 0x1, 0xbf, 0xe0, 0xf0, 0x10, 0x6f, 0xf9, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xd0, 0x28, 0x7, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x2f, - 0xff, 0xff, 0xff, 0xff -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 384, .box_w = 14, .box_h = 14, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 49, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 129, .adv_w = 384, .box_w = 13, .box_h = 20, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 194, .adv_w = 384, .box_w = 14, .box_h = 20, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 264, .adv_w = 384, .box_w = 22, .box_h = 22, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 385, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 465, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 565, .adv_w = 384, .box_w = 12, .box_h = 7, .ofs_x = 6, .ofs_y = 9}, - {.bitmap_index = 586, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 666, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 766, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 847, .adv_w = 384, .box_w = 12, .box_h = 18, .ofs_x = 6, .ofs_y = 3}, - {.bitmap_index = 901, .adv_w = 384, .box_w = 16, .box_h = 18, .ofs_x = 4, .ofs_y = 3}, - {.bitmap_index = 973, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 1037, .adv_w = 384, .box_w = 14, .box_h = 14, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 1086, .adv_w = 384, .box_w = 18, .box_h = 12, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 1140, .adv_w = 384, .box_w = 4, .box_h = 16, .ofs_x = 10, .ofs_y = 4}, - {.bitmap_index = 1156, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 1220, .adv_w = 384, .box_w = 24, .box_h = 17, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 1322, .adv_w = 384, .box_w = 16, .box_h = 12, .ofs_x = 4, .ofs_y = 6}, - {.bitmap_index = 1370, .adv_w = 384, .box_w = 18, .box_h = 16, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 1442, .adv_w = 384, .box_w = 18, .box_h = 17, .ofs_x = 3, .ofs_y = 4}, - {.bitmap_index = 1519, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 1599, .adv_w = 384, .box_w = 20, .box_h = 19, .ofs_x = 2, .ofs_y = 3}, - {.bitmap_index = 1694, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1794, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1894, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 1974, .adv_w = 384, .box_w = 16, .box_h = 18, .ofs_x = 4, .ofs_y = 3}, - {.bitmap_index = 2046, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 2126, .adv_w = 384, .box_w = 24, .box_h = 23, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 2264, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 2345, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 2445, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 2526, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 2606, .adv_w = 384, .box_w = 20, .box_h = 18, .ofs_x = 2, .ofs_y = 3}, - {.bitmap_index = 2696, .adv_w = 384, .box_w = 18, .box_h = 20, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 2786, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 2866, .adv_w = 384, .box_w = 18, .box_h = 16, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 2938, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 3038, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 3119, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 3200, .adv_w = 384, .box_w = 22, .box_h = 16, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 3288, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 3352, .adv_w = 384, .box_w = 22, .box_h = 16, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 3440, .adv_w = 384, .box_w = 18, .box_h = 20, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 3530, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 3630, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_24 = { -#else -lv_font_t material_symbols_shared_24 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 23, /*The maximum line height required by the font*/ - .base_line = -1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_24*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_32.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_32.c deleted file mode 100644 index 5ec207f01..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_32.c +++ /dev/null @@ -1,1158 +0,0 @@ -/******************************************************************************* - * Size: 32 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 32 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_32.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_32 -#define MATERIAL_SYMBOLS_SHARED_32 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_32 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x3d, - 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, - 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, - 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, - 0x3d, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, - 0x1a, 0xaa, 0xbe, 0xaa, 0xa4, 0x3f, 0xff, 0xff, - 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, - 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, - 0x3d, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, - 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x3d, - 0x0, 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E159 "" */ - 0x6, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xbe, 0x3f, 0xf0, 0x0, 0x0, - 0x0, 0x7, 0xfe, 0x3f, 0xfe, 0x0, 0x0, 0x0, - 0x3f, 0xfe, 0x3e, 0x7f, 0xd0, 0x0, 0x2, 0xfe, - 0x3e, 0x3e, 0xb, 0xf8, 0x0, 0x1f, 0xf0, 0x3e, - 0x3e, 0x0, 0xff, 0x40, 0xbf, 0x40, 0x3e, 0x3e, - 0x0, 0x1f, 0xfb, 0xf8, 0x0, 0x3e, 0x3e, 0x0, - 0x2, 0xff, 0xd0, 0x0, 0x3e, 0x3e, 0x0, 0x0, - 0x7e, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x6, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa0, - - /* U+E1A7 "" */ - 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x3f, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x3, 0xff, - 0x0, 0x24, 0x0, 0xff, 0xf0, 0x2f, 0x80, 0x3e, - 0xff, 0x3, 0xf8, 0xf, 0x8b, 0xf0, 0x7f, 0x83, - 0xe0, 0xfc, 0x7, 0xf8, 0xf8, 0xfe, 0x0, 0x7f, - 0xbe, 0xfe, 0x0, 0x7, 0xff, 0xfe, 0x0, 0x0, - 0x7f, 0xfe, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, - 0x0, 0xff, 0x80, 0x0, 0x0, 0xff, 0xf8, 0x0, - 0x0, 0xff, 0xff, 0x80, 0x0, 0xfe, 0xff, 0xf8, - 0x0, 0xfe, 0x3e, 0x7f, 0x80, 0xfe, 0xf, 0x87, - 0xf0, 0xfe, 0x3, 0xe2, 0xfc, 0xbe, 0x0, 0xfa, - 0xfc, 0xe, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0xf, - 0xfc, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, - 0xfc, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x40, 0x0, 0x0, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x3, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x0, 0x0, 0x1, 0x0, 0x3e, 0x1, 0x54, - 0x2f, 0xc0, 0x3e, 0xf, 0xfd, 0x3f, 0xf0, 0x3e, - 0xf, 0xfd, 0x7f, 0xf0, 0x3e, 0xf, 0xfd, 0x3f, - 0xe0, 0x3e, 0xf, 0xfd, 0xf, 0xc0, 0x3e, 0xf, - 0xfc, 0xf, 0x80, 0x3e, 0x2, 0xf0, 0xf, 0x80, - 0x3e, 0x2, 0xf0, 0xf, 0xd5, 0x7e, 0x57, 0xf0, - 0xf, 0xff, 0xff, 0xff, 0xf0, 0x3, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x55, 0x7e, 0x55, 0x0, 0x0, - 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0, - 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, 0x0, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x1a, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xe0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0xb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xe0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0xb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xe0, - 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xe0, 0xbc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xe0, 0xbc, 0x0, - 0x0, 0x0, 0x1, 0x55, 0x7f, 0x5f, 0xd5, 0x54, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x3, 0xf5, 0x55, 0x55, 0x55, 0x55, 0xfc, 0x0, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0xb, 0xc0, 0x3, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0xbc, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0xbe, 0xaa, - 0xaa, 0xaa, 0xaa, 0xab, 0xe0, 0xf, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0x0, 0xf8, 0x2d, 0x0, - 0xf0, 0x7, 0x82, 0xf0, 0x1f, 0x43, 0xe0, 0x1f, - 0x40, 0xbc, 0x1f, 0x42, 0xf0, 0x3e, 0x1, 0xf4, - 0xb, 0xc0, 0xf8, 0x3f, 0x3, 0xe0, 0x1f, 0x40, - 0xbc, 0xf, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x6a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0x90, - - /* U+E2C7 "" */ - 0x6, 0xaa, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xf4, 0x3e, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xfd, 0x3e, 0x0, 0x0, 0x2a, 0xaa, - 0xaa, 0xbe, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x6, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa0, - - /* U+E30F "" */ - 0x0, 0x0, 0x2, 0xaa, 0x90, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xc2, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc2, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc2, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xc2, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xe7, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x40, 0x0, 0x0, 0x2f, 0xff, - 0x80, 0x3d, 0x1, 0xff, 0xfc, 0x3f, 0xff, 0xe0, - 0x0, 0x7, 0xff, 0xfe, 0x3f, 0xab, 0xf8, 0x0, - 0x1f, 0xea, 0xbe, 0x3e, 0x0, 0xfe, 0x0, 0x3f, - 0x40, 0x3e, 0x3e, 0x0, 0xfe, 0x0, 0x3f, 0x40, - 0x3e, 0x3f, 0xab, 0xf8, 0x0, 0x1f, 0xea, 0xbe, - 0x3f, 0xff, 0xe0, 0x18, 0x7, 0xff, 0xfe, 0x2f, - 0xff, 0x80, 0x7f, 0x1, 0xff, 0xfd, 0x0, 0x0, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xd3, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc2, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xc2, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xc2, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xeb, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E316 "" */ - 0x0, 0x2, 0x80, 0x0, 0x0, 0xb, 0xf0, 0x0, - 0x0, 0x2f, 0xfc, 0x0, 0x0, 0xbf, 0xbf, 0x0, - 0x2, 0xfc, 0x2f, 0xc0, 0xb, 0xf0, 0xb, 0xf0, - 0x2f, 0xc0, 0x2, 0xfc, 0x3f, 0x0, 0x0, 0xbe, - 0x3c, 0x0, 0x0, 0x2d, - - /* U+E326 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x90, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x6, - 0xaa, 0xa4, 0xf, 0x80, 0x0, 0x0, 0x3f, 0xff, - 0xfd, 0xf, 0x80, 0x0, 0x0, 0x3f, 0xff, 0xfe, - 0xf, 0x80, 0x0, 0x0, 0x3e, 0x0, 0x3e, 0xf, - 0x80, 0x0, 0x0, 0x3e, 0x4, 0x3e, 0xf, 0x80, - 0x0, 0x0, 0x3e, 0x2c, 0x3e, 0xf, 0x80, 0x0, - 0x0, 0x3e, 0x18, 0x3e, 0xf, 0x80, 0x0, 0x0, - 0x3e, 0x0, 0x3e, 0xf, 0x80, 0x0, 0x0, 0x3e, - 0x0, 0x3e, 0xf, 0x80, 0x0, 0x0, 0x3e, 0x0, - 0x3e, 0xf, 0xff, 0xff, 0xe0, 0x3e, 0x0, 0x3e, - 0x7, 0xff, 0xff, 0xf0, 0x3e, 0x0, 0x3e, 0x1, - 0xaa, 0xaa, 0x90, 0x3e, 0x0, 0x3e, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0x0, 0x3e, 0x3f, 0xff, 0xff, - 0xe0, 0x3f, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0xfd, 0x2a, 0xaa, 0xaa, 0x90, 0xa, - 0xaa, 0xa4, - - /* U+E3AF "" */ - 0x0, 0x0, 0x1, 0x55, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x1f, 0xfe, - 0x42, 0xef, 0xf4, 0x0, 0x0, 0x7f, 0xd0, 0x3, - 0x42, 0xfe, 0x0, 0x1, 0xfe, 0x0, 0xb, 0x0, - 0x7f, 0x40, 0x3, 0xfc, 0x0, 0x1d, 0x0, 0x1f, - 0xc0, 0xb, 0xfd, 0x0, 0x38, 0x0, 0x7, 0xe0, - 0xf, 0xcb, 0x0, 0x70, 0x0, 0x3, 0xf4, 0x2f, - 0x43, 0x40, 0xf0, 0x0, 0x1, 0xf8, 0x3f, 0x2, - 0xc2, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x0, 0xe3, - 0xff, 0xf5, 0x55, 0xbc, 0x3e, 0x0, 0x7f, 0xff, - 0xf0, 0x0, 0x7d, 0x3d, 0x0, 0x3f, 0xff, 0xf4, - 0x0, 0x7d, 0x3d, 0x0, 0xf, 0xff, 0xfc, 0x0, - 0x7d, 0x3e, 0x0, 0xb, 0xff, 0xfe, 0x0, 0x7d, - 0x3f, 0x55, 0x5b, 0xff, 0xd7, 0x0, 0xbc, 0x2f, - 0xff, 0xff, 0xff, 0x83, 0xc0, 0xfc, 0x1f, 0x40, - 0x0, 0xf, 0x0, 0xd1, 0xf8, 0xf, 0xc0, 0x0, - 0xe, 0x0, 0xb3, 0xf0, 0x7, 0xe0, 0x0, 0x2c, - 0x0, 0x3f, 0xe0, 0x2, 0xf8, 0x0, 0x34, 0x0, - 0x2f, 0xc0, 0x0, 0xfe, 0x0, 0xe0, 0x0, 0xbf, - 0x0, 0x0, 0x3f, 0xd1, 0xc0, 0x7, 0xfc, 0x0, - 0x0, 0xb, 0xff, 0xea, 0xff, 0xf0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E3F4 "" */ - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xaa, 0xaa, 0xaa, - 0xaa, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x5, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0xf, 0x0, 0x2f, 0xf8, 0x3, 0xc0, 0x3f, - 0xc0, 0x2f, 0xf8, 0xb, 0xe0, 0xbf, 0xe0, 0x2f, - 0xf8, 0x1f, 0xf5, 0xff, 0xf4, 0x2f, 0xf8, 0x3f, - 0xff, 0xff, 0xfc, 0x2f, 0xf8, 0x2a, 0xaa, 0xaa, - 0xa8, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfe, 0xaa, - 0xaa, 0xaa, 0xaa, 0xbf, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+E405 "" */ - 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xfd, 0x54, - 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0xf8, 0x0, - 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0xf8, 0x0, - 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0xf8, 0x0, - 0x0, 0x0, 0xf8, 0x0, 0x1, 0xa8, 0xf8, 0x0, - 0xf, 0xff, 0xf8, 0x0, 0x3f, 0xff, 0xf8, 0x0, - 0xbf, 0xff, 0xf8, 0x0, 0xff, 0xff, 0xf8, 0x0, - 0xff, 0xff, 0xf8, 0x0, 0xff, 0xff, 0xf8, 0x0, - 0xbf, 0xff, 0xf4, 0x0, 0x3f, 0xff, 0xf0, 0x0, - 0x1f, 0xff, 0xc0, 0x0, 0x2, 0xfe, 0x0, 0x0, - - /* U+E55D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x80, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xe0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, - 0x0, 0x0, 0x1, 0xf5, 0xf4, 0x0, 0x0, 0x0, - 0x3f, 0xf, 0xc0, 0x0, 0x0, 0x7, 0xe0, 0xbd, - 0x0, 0x0, 0x0, 0xfc, 0x3, 0xf0, 0x0, 0x0, - 0x1f, 0x80, 0x2f, 0x40, 0x0, 0x2, 0xf0, 0x0, - 0xf8, 0x0, 0x0, 0x3e, 0x0, 0xf, 0xc0, 0x0, - 0xb, 0xd0, 0x0, 0x7e, 0x0, 0x0, 0xfc, 0x0, - 0x3, 0xf0, 0x0, 0x1f, 0x40, 0x0, 0x1f, 0x40, - 0x3, 0xf0, 0x0, 0x0, 0xfc, 0x0, 0x7e, 0x1, - 0xa4, 0xb, 0xd0, 0xf, 0xc1, 0xff, 0xf4, 0x3f, - 0x1, 0xfe, 0xff, 0xff, 0xfb, 0xf4, 0x2f, 0xff, - 0xe0, 0xbf, 0xff, 0x83, 0xff, 0xd0, 0x0, 0x7f, - 0xfc, 0x7f, 0xd0, 0x0, 0x0, 0x7f, 0xd2, 0x80, - 0x0, 0x0, 0x0, 0x28, - - /* U+E5C3 "" */ - 0x5, 0x0, 0x5, 0x0, 0x5, 0x3, 0xfc, 0x3, - 0xfc, 0x3, 0xfc, 0xbf, 0xd0, 0xbf, 0xd0, 0xbf, - 0xdb, 0xfe, 0xb, 0xfe, 0xb, 0xfe, 0x7f, 0xc0, - 0x7f, 0xc0, 0x7f, 0xc1, 0xe4, 0x1, 0xe4, 0x1, - 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, - 0x5, 0x3, 0xfc, 0x3, 0xfc, 0x3, 0xfc, 0xbf, - 0xd0, 0xbf, 0xd0, 0xbf, 0xdb, 0xfe, 0xb, 0xfe, - 0xb, 0xfe, 0x7f, 0xc0, 0x7f, 0xc0, 0x7f, 0xc1, - 0xe4, 0x1, 0xe4, 0x1, 0xe4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x0, 0x5, 0x0, 0x5, 0x3, 0xfc, 0x3, - 0xfc, 0x3, 0xfc, 0xbf, 0xd0, 0xbf, 0xd0, 0xbf, - 0xdb, 0xfe, 0xb, 0xfe, 0xb, 0xfe, 0x7f, 0xc0, - 0x7f, 0xc0, 0x7f, 0xc1, 0xe4, 0x1, 0xe4, 0x1, - 0xe4, - - /* U+E5CD "" */ - 0x24, 0x0, 0x0, 0x1, 0x8b, 0xd0, 0x0, 0x0, - 0x7e, 0x7f, 0x40, 0x0, 0x1f, 0xd1, 0xfd, 0x0, - 0x7, 0xf4, 0x7, 0xf4, 0x1, 0xfd, 0x0, 0x1f, - 0xd0, 0x7f, 0x40, 0x0, 0x7f, 0x5f, 0xd0, 0x0, - 0x1, 0xff, 0xf4, 0x0, 0x0, 0x7, 0xfd, 0x0, - 0x0, 0x0, 0x7f, 0xd0, 0x0, 0x0, 0x1f, 0xff, - 0x40, 0x0, 0x7, 0xf5, 0xfd, 0x0, 0x1, 0xfd, - 0x7, 0xf4, 0x0, 0x7f, 0x40, 0x1f, 0xd0, 0x1f, - 0xd0, 0x0, 0x7f, 0x47, 0xf4, 0x0, 0x1, 0xfd, - 0xbd, 0x0, 0x0, 0x7, 0xe7, 0x40, 0x0, 0x0, - 0x1d, - - /* U+E5D2 "" */ - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x6a, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2a, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 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, 0x6a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa9, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, - - /* U+E5D4 "" */ - 0x5, 0x3, 0xfc, 0xbf, 0xdb, 0xfe, 0x7f, 0xc1, - 0xe4, 0x0, 0x0, 0x0, 0x5, 0x3, 0xfc, 0xbf, - 0xdb, 0xfe, 0x7f, 0xc1, 0xe4, 0x0, 0x0, 0x0, - 0x5, 0x3, 0xfc, 0xbf, 0xdb, 0xfe, 0x7f, 0xc1, - 0xe4, - - /* U+E5D5 "" */ - 0x0, 0x0, 0x6a, 0x90, 0x1, 0x80, 0x0, 0xbf, - 0xff, 0xe0, 0x3e, 0x0, 0x7f, 0xff, 0xff, 0xd3, - 0xe0, 0x2f, 0xf4, 0x1, 0xff, 0x7e, 0x7, 0xf4, - 0x0, 0x1, 0xff, 0xe0, 0xfc, 0x0, 0x0, 0x7, - 0xfe, 0x2f, 0x40, 0x0, 0x0, 0x1f, 0xe3, 0xf0, - 0x0, 0x7, 0xff, 0xfe, 0x7d, 0x0, 0x0, 0xbf, - 0xff, 0xeb, 0xc0, 0x0, 0x2, 0xaa, 0xa8, 0xbc, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, - 0x0, 0xb, 0x42, 0xf4, 0x0, 0x0, 0x1, 0xf8, - 0xf, 0xc0, 0x0, 0x0, 0x7f, 0x0, 0x7f, 0x40, - 0x0, 0x1f, 0xd0, 0x2, 0xff, 0x40, 0x1f, 0xf8, - 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, 0xb, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x6, 0xa9, 0x0, - 0x0, - - /* U+E63E "" */ - 0x0, 0x0, 0x1, 0xaf, 0xfa, 0x40, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x7, 0xff, 0xfe, 0x50, 0x5, 0xbf, 0xff, 0xd0, - 0x2f, 0xff, 0xd0, 0x0, 0x0, 0x7, 0xff, 0xf8, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, - 0x3f, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, - 0x1a, 0x0, 0x0, 0x6b, 0xe9, 0x0, 0x0, 0xa4, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x7, 0xff, 0xd4, 0x17, 0xff, 0xd0, 0x0, - 0x0, 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0x0, 0x90, 0x0, 0x0, 0x6, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, - 0x0, 0x0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xc0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, - 0x0, 0x2, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0x40, 0x0, 0x0, 0x0, 0x2f, 0xd0, 0x3, 0xc0, - 0x0, 0xb, 0xf4, 0x0, 0x7f, 0x0, 0x2, 0xfd, - 0x0, 0x2, 0xfc, 0x0, 0xbf, 0x40, 0x0, 0xb, - 0xf0, 0x2f, 0xd0, 0x0, 0x0, 0x2f, 0xcb, 0xf4, - 0x0, 0x0, 0x0, 0xbf, 0xfd, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x40, 0x0, 0x0, 0x0, 0xb, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, - - /* U+E745 "" */ - 0x2a, 0xaa, 0xaa, 0xa0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, - 0xaa, 0xaa, 0xa8, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x1, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0x81, 0xff, 0xff, 0x0, - 0x0, 0x3f, 0xf8, 0xbf, 0xff, 0xe0, 0x0, 0x3f, - 0xff, 0xa, 0xaa, 0xa0, 0x0, 0x2f, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x2f, 0xbf, 0xd0, 0x0, 0x0, - 0x0, 0x2f, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x2f, - 0x7, 0xe0, 0x0, 0x0, 0x0, 0x2f, 0x7, 0xe0, - 0x0, 0x0, 0x0, 0xf, 0x7, 0xe0, 0x0, 0x0, - 0x0, 0x3, 0xc7, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, - 0x0, 0x0, - - /* U+E770 "" */ - 0x0, 0x0, 0x2, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x3f, 0x2f, 0xe0, 0x0, - 0x0, 0x0, 0xfd, 0x7, 0xfe, 0xa4, 0x10, 0x2, - 0xf8, 0x0, 0xff, 0xfd, 0xfc, 0x7, 0xf0, 0x0, - 0x3f, 0xff, 0xff, 0x4f, 0xc0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x2f, 0xf9, 0xfc, 0x0, 0x40, - 0x0, 0x2f, 0xf8, 0x34, 0x3, 0xe0, 0x0, 0x2f, - 0xf8, 0x0, 0xb, 0xf8, 0x0, 0x2f, 0xf8, 0x0, - 0x1f, 0xff, 0x0, 0x2f, 0xfc, 0x0, 0x3f, 0xff, - 0xd0, 0x2f, 0xff, 0x0, 0xbf, 0xff, 0xf8, 0x2f, - 0xff, 0xd1, 0xff, 0xff, 0xff, 0x2f, 0xff, 0xfb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, - - /* U+E89C "" */ - 0x6, 0xaa, 0xaa, 0x90, 0x0, 0x3, 0xff, 0xff, - 0xff, 0x80, 0x0, 0xbf, 0xff, 0xff, 0xfe, 0x0, - 0xb, 0xc0, 0x0, 0xb, 0xf8, 0x0, 0xbc, 0x0, - 0x0, 0xbf, 0xe0, 0xb, 0xc0, 0x0, 0xb, 0xff, - 0x80, 0xbc, 0x0, 0x0, 0xbf, 0xfe, 0xb, 0xc0, - 0x0, 0xb, 0xff, 0xf8, 0xbc, 0x0, 0x0, 0xbf, - 0xff, 0xdb, 0xc0, 0x0, 0x2, 0xff, 0xfe, 0xbc, - 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, 0xa0, - 0x0, 0x3e, 0xbc, 0x0, 0x1f, 0x40, 0x3, 0xeb, - 0xc0, 0x1, 0xf4, 0x0, 0x3e, 0xbc, 0x0, 0x1f, - 0x40, 0x3, 0xeb, 0xc0, 0xbf, 0xff, 0xe0, 0x3e, - 0xbc, 0x1f, 0xff, 0xff, 0x43, 0xeb, 0xc0, 0xbf, - 0xff, 0xe0, 0x3e, 0xbc, 0x0, 0x1f, 0x40, 0x3, - 0xeb, 0xc0, 0x1, 0xf4, 0x0, 0x3e, 0xbc, 0x0, - 0x1f, 0x40, 0x3, 0xeb, 0xc0, 0x0, 0xa0, 0x0, - 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, - 0x0, 0x0, 0x0, 0x3e, 0xbe, 0xaa, 0xaa, 0xaa, - 0xab, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E8AF "" */ - 0x6, 0xaa, 0xaa, 0xaa, 0xa4, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x3e, 0x0, 0x0, - 0x0, 0xf, 0xc0, 0x0, 0x3e, 0x0, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0xf, - 0xc0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0xf, 0xc0, - 0xfc, 0x3e, 0x0, 0x0, 0x0, 0xf, 0xc0, 0xfe, - 0x3e, 0x0, 0x0, 0x0, 0xf, 0xc0, 0xfe, 0x3e, - 0x0, 0x0, 0x0, 0xf, 0xc0, 0xff, 0x3e, 0x0, - 0x0, 0x0, 0xf, 0xc0, 0xff, 0x3e, 0x0, 0x0, - 0x0, 0xf, 0xc0, 0xff, 0x3e, 0x2a, 0xaa, 0xaa, - 0xaf, 0xc0, 0xff, 0x3e, 0xff, 0xff, 0xff, 0xff, - 0x80, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0xff, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x3f, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0x28, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x6, 0xa9, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x3, 0xe0, 0xbc, - 0x0, 0x0, 0x1, 0x40, 0x7e, 0x7, 0xc0, 0x14, - 0x0, 0xbf, 0xaf, 0xd0, 0x7f, 0xaf, 0xe0, 0xf, - 0xff, 0xfc, 0x3, 0xff, 0xff, 0x3, 0xfb, 0xfd, - 0x0, 0x7, 0xfe, 0xfc, 0x7e, 0x2, 0x0, 0x0, - 0x8, 0xb, 0xdb, 0xd0, 0x0, 0x2f, 0x80, 0x0, - 0x7e, 0x7f, 0x40, 0x1f, 0xff, 0x40, 0x1f, 0xd2, - 0xfe, 0x3, 0xff, 0xfc, 0xb, 0xf8, 0x7, 0xf0, - 0x7f, 0xff, 0xe0, 0xfd, 0x0, 0x3e, 0xb, 0xff, - 0xfe, 0xb, 0xc0, 0x3, 0xe0, 0xbf, 0xff, 0xe0, - 0xbc, 0x0, 0xff, 0x7, 0xff, 0xfd, 0xf, 0xf0, - 0x3f, 0xc0, 0x2f, 0xff, 0xc0, 0x3f, 0xcb, 0xe0, - 0x0, 0xbf, 0xe0, 0x0, 0xbe, 0xbd, 0x0, 0x0, - 0x50, 0x0, 0x7, 0xe3, 0xf0, 0xb8, 0x0, 0x1, - 0xe0, 0xfc, 0x2f, 0xff, 0xf4, 0x1, 0xff, 0xff, - 0x40, 0xff, 0xff, 0xd0, 0x7f, 0xff, 0xf0, 0x3, - 0xe4, 0xbd, 0x7, 0xe1, 0xbc, 0x0, 0x0, 0x3, - 0xe0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xaf, - 0xc0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E8FD "" */ - 0x0, 0x0, 0x1, 0x55, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x1f, 0xfd, - 0x41, 0x6f, 0xf4, 0x0, 0x0, 0x7f, 0x80, 0x0, - 0x2, 0xfe, 0x0, 0x1, 0xfd, 0x0, 0x0, 0x0, - 0x7f, 0x40, 0x3, 0xf4, 0x1, 0xff, 0x80, 0xf, - 0xc0, 0xb, 0xd0, 0x7, 0xff, 0xf0, 0x7, 0xf0, - 0xf, 0xc0, 0xf, 0xd6, 0xf8, 0x2, 0xf4, 0x2f, - 0x40, 0xb, 0x0, 0xfc, 0x0, 0xf8, 0x3f, 0x0, - 0x0, 0x0, 0xf8, 0x0, 0xfc, 0x3e, 0x0, 0x0, - 0x1, 0xf4, 0x0, 0x7c, 0x3e, 0x0, 0x0, 0x3, - 0xe0, 0x0, 0x7d, 0x3d, 0x0, 0x0, 0xf, 0xc0, - 0x0, 0x7d, 0x3d, 0x0, 0x0, 0x3f, 0x0, 0x0, - 0x7d, 0x3e, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x7d, - 0x3f, 0x0, 0x0, 0x28, 0x0, 0x0, 0xbc, 0x2f, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x1f, 0x40, - 0x0, 0x0, 0x0, 0x1, 0xf8, 0xf, 0xc0, 0x0, - 0x7d, 0x0, 0x3, 0xf0, 0x7, 0xf0, 0x0, 0xbe, - 0x0, 0xb, 0xe0, 0x3, 0xf8, 0x0, 0x28, 0x0, - 0x2f, 0xc0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xbf, - 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x7, 0xfd, 0x0, - 0x0, 0xb, 0xff, 0xaa, 0xff, 0xf0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E90F "" */ - 0x0, 0x0, 0x55, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xf4, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x3, - 0xfe, 0x41, 0xbf, 0xc0, 0xf, 0xe0, 0x0, 0xb, - 0xf0, 0x2f, 0x80, 0x0, 0x2, 0xf8, 0x3f, 0x0, - 0x0, 0x0, 0xfc, 0xbd, 0x0, 0x0, 0x0, 0x7e, - 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, - 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xfc, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x3f, 0xbd, 0x0, 0x0, 0x0, 0x7e, 0x3f, 0x0, - 0x0, 0x0, 0xfc, 0x2f, 0xc0, 0x0, 0x2, 0xf8, - 0xf, 0xfa, 0xaa, 0xaf, 0xf0, 0x3, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0xbf, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xaa, 0xa4, - 0x0, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x0, 0x3f, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0x1, 0xff, - 0x40, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E92E "" */ - 0x0, 0x2, 0xff, 0xf8, 0x0, 0x2, 0xaa, 0xbf, - 0xff, 0xea, 0xa8, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xe7, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x1f, 0x40, - 0x0, 0x0, 0x1f, 0x41, 0xf4, 0x0, 0x0, 0x1, - 0xf4, 0x1f, 0x40, 0x40, 0x10, 0x1f, 0x41, 0xf4, - 0x3e, 0xb, 0xc1, 0xf4, 0x1f, 0x43, 0xe0, 0xbc, - 0x1f, 0x41, 0xf4, 0x3e, 0xb, 0xc1, 0xf4, 0x1f, - 0x43, 0xe0, 0xbc, 0x1f, 0x41, 0xf4, 0x3e, 0xb, - 0xc1, 0xf4, 0x1f, 0x43, 0xe0, 0xbc, 0x1f, 0x41, - 0xf4, 0x3e, 0xb, 0xc1, 0xf4, 0x1f, 0x43, 0xe0, - 0xbc, 0x1f, 0x41, 0xf4, 0x3e, 0xb, 0xc1, 0xf4, - 0x1f, 0x43, 0xe0, 0xbc, 0x1f, 0x41, 0xf4, 0x3e, - 0xb, 0xc1, 0xf4, 0x1f, 0x41, 0x80, 0x24, 0x1f, - 0x41, 0xf4, 0x0, 0x0, 0x1, 0xf4, 0x1f, 0x40, - 0x0, 0x0, 0x1f, 0x41, 0xfe, 0xaa, 0xaa, 0xab, - 0xf0, 0xf, 0xff, 0xff, 0xff, 0xff, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xc0, - - /* U+E9B9 "" */ - 0x5, 0x0, 0x5, 0x55, 0x55, 0x55, 0x50, 0x2f, - 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xf0, - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x7f, 0xf0, 0x3f, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xe0, 0x3f, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0x80, 0xb, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x0, 0x5, 0x55, 0x55, 0x55, 0x50, 0x2f, - 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xf0, - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x7f, 0xf0, 0x3f, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xe0, 0x3f, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0x80, 0xb, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x0, 0x5, 0x55, 0x55, 0x55, 0x50, 0x2f, - 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xf0, - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x7f, 0xf0, 0x3f, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xe0, 0x3f, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0x80, 0xb, 0xff, 0xff, - 0xff, 0xe0, - - /* U+E9F4 "" */ - 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfc, 0x3f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfc, 0x3f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, - 0x1, 0x40, 0x0, 0x3, 0xc0, 0x0, 0x1, 0x40, - 0x1f, 0xf4, 0x0, 0x3, 0xc0, 0x0, 0x1f, 0xf4, - 0x7f, 0xfd, 0x0, 0x3, 0xc0, 0x0, 0x7f, 0xfd, - 0xfd, 0x7f, 0x0, 0x2f, 0xf8, 0x0, 0xfd, 0x7f, - 0xf8, 0x2f, 0x1, 0xff, 0xff, 0x40, 0xf8, 0x2f, - 0xfc, 0x3f, 0xe7, 0xf9, 0x6f, 0xdb, 0xfc, 0x3f, - 0xbf, 0xff, 0xff, 0xe0, 0xb, 0xff, 0xff, 0xfe, - 0x3f, 0xf8, 0x2f, 0xc0, 0x3, 0xf8, 0x2f, 0xf8, - 0x6, 0x90, 0xf, 0x80, 0x2, 0xf0, 0x6, 0x90, - 0x0, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xd0, 0x7, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xf4, 0x1f, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x1, 0x5f, 0x45, 0x51, 0xf5, 0x40, 0x0, - 0x0, 0x2f, 0xfe, 0x0, 0x0, 0xbf, 0xf8, 0x0, - 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x7f, 0xfd, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0xfd, 0x7f, 0x0, - 0x0, 0xf8, 0x2f, 0x0, 0x0, 0xf8, 0x2f, 0x0, - 0x0, 0xfc, 0x3f, 0x0, 0x0, 0xfc, 0x3f, 0x0, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0xbf, 0xfe, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x6, 0x90, 0x0, 0x0, 0x6, 0x90, 0x0, - - /* U+E9F7 "" */ - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xaa, 0xaa, 0xaa, - 0xaa, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xfe, 0xaa, 0xaa, 0xaa, - 0xaa, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfe, 0xaa, - 0xaa, 0xaa, 0xaa, 0xbf, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+EA07 "" */ - 0x0, 0x0, 0x1, 0x69, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x1f, 0xff, - 0xfb, 0xff, 0xf4, 0x0, 0x0, 0x7f, 0x8b, 0xd3, - 0xf2, 0xfe, 0x0, 0x1, 0xfd, 0xf, 0x82, 0xf4, - 0x7f, 0x40, 0x3, 0xf4, 0x2f, 0x40, 0xfc, 0xf, - 0xc0, 0xb, 0xe0, 0x3f, 0x0, 0xbc, 0x7, 0xf0, - 0xf, 0xea, 0xbf, 0xaa, 0xfe, 0xab, 0xf4, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x0, 0xfc, - 0x0, 0x3f, 0x0, 0xbc, 0x3e, 0x0, 0xfc, 0x0, - 0x2f, 0x0, 0x7d, 0x3d, 0x0, 0xfc, 0x0, 0x2f, - 0x0, 0x7d, 0x3d, 0x0, 0xfc, 0x0, 0x2f, 0x0, - 0x7d, 0x3e, 0x0, 0xfc, 0x0, 0x2f, 0x0, 0x7d, - 0x3f, 0xaa, 0xfe, 0xaa, 0xbf, 0xaa, 0xfc, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf, 0xd0, 0x3f, - 0x0, 0xbd, 0x3, 0xf0, 0x7, 0xf0, 0x3f, 0x0, - 0xfc, 0xb, 0xe0, 0x2, 0xfc, 0x1f, 0x41, 0xf8, - 0x2f, 0xc0, 0x0, 0xff, 0xf, 0xc3, 0xf0, 0xbf, - 0x0, 0x0, 0x3f, 0xeb, 0xe7, 0xfb, 0xfc, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+EAD6 "" */ - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xaa, 0xaa, 0xaa, - 0xaa, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0xff, 0x4f, 0xe7, 0x7, 0x2f, 0xf8, 0xe7, - 0xdd, 0x47, 0x4b, 0x2f, 0xf8, 0xd3, 0xdc, 0x3, - 0x8e, 0x2f, 0xf8, 0xd3, 0xdf, 0x82, 0xcd, 0x2f, - 0xf8, 0xd3, 0xde, 0x1, 0xec, 0x2f, 0xf8, 0xd3, - 0xdc, 0x0, 0xfc, 0x2f, 0xf8, 0xfb, 0xdf, 0x90, - 0xf8, 0x2f, 0xf8, 0xff, 0x4f, 0xe0, 0x70, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfe, 0xaa, - 0xaa, 0xaa, 0xaa, 0xbf, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+EB8E "" */ - 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x1f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3e, 0x3, 0xe0, 0x0, 0x0, 0x0, 0x3e, 0x3e, - 0x3, 0xf8, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, - 0xfe, 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x3f, - 0x80, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x1f, 0xc0, - 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x7f, 0x40, 0x0, - 0x0, 0x3e, 0x3e, 0x1, 0xfd, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x3, 0xf4, 0x7, 0xff, 0xf0, 0x3e, - 0x3e, 0x3, 0xd0, 0xb, 0xff, 0xf0, 0x3e, 0x3e, - 0x0, 0x0, 0x2, 0xaa, 0x90, 0x3e, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x6, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa0, - - /* U+EB97 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xbe, 0x3e, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x6, - 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0xf, 0x0, - 0x3e, 0x3e, 0xb, 0xff, 0xff, 0x8f, 0xf0, 0x3e, - 0x3e, 0xb, 0xff, 0xff, 0x8f, 0xf0, 0x3e, 0x3e, - 0x0, 0x0, 0x0, 0xf, 0x0, 0x3e, 0x3e, 0x0, - 0x10, 0x0, 0x1, 0x0, 0x3e, 0x3e, 0x0, 0xf0, - 0x0, 0x0, 0x0, 0x3e, 0x3e, 0x7, 0xf0, 0xff, - 0xff, 0xf0, 0x3e, 0x3e, 0xb, 0xf1, 0xff, 0xff, - 0xf0, 0x3e, 0x3e, 0x0, 0xf0, 0x0, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x60, 0x0, 0x0, 0x0, 0x3e, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x3f, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xbe, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x3f, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, - - /* U+EBCC "" */ - 0x0, 0x10, 0x0, 0x0, 0x4, 0x0, 0x0, 0xf8, - 0x0, 0x0, 0x2f, 0x0, 0x0, 0xf8, 0x0, 0x0, - 0x2f, 0x0, 0x1a, 0xfe, 0xaa, 0xaa, 0xbf, 0xa4, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x1e, 0x3, 0xc0, - 0xb4, 0x2f, 0xf8, 0x2f, 0x3, 0xd0, 0xf8, 0x2f, - 0xf8, 0x9, 0x1, 0x80, 0x60, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x9, 0x1, 0x80, 0x60, 0x2f, - 0xf8, 0x2f, 0x3, 0xd0, 0xf8, 0x2f, 0xf8, 0x1e, - 0x3, 0xc0, 0xb4, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xbf, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EC1C "" */ - 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x80, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x0, - 0xf, 0xff, 0x0, 0x0, 0x0, 0x3, 0xff, 0xd0, - 0x0, 0x0, 0x1, 0xfe, 0xfc, 0x0, 0x0, 0x0, - 0x7f, 0xaf, 0x80, 0x0, 0x0, 0x1f, 0xe3, 0xff, - 0xfe, 0x90, 0x7, 0xf8, 0xbf, 0xff, 0xff, 0xc1, - 0xfd, 0x0, 0x16, 0xbf, 0xfc, 0x3f, 0xfa, 0x50, - 0x0, 0x7f, 0x43, 0xff, 0xff, 0xfe, 0x2f, 0xd0, - 0x6, 0xbf, 0xff, 0xcb, 0xf4, 0x0, 0x0, 0x2, - 0xfa, 0xfd, 0x0, 0x0, 0x0, 0x3f, 0xbf, 0x40, - 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x2f, 0xfc, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x2, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, - 0x0, 0x0, - - /* U+EF40 "" */ - 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xb, 0xfd, 0xb, 0xfd, - 0xb, 0xfd, 0x2, 0xff, 0x82, 0xff, 0x82, 0xff, - 0x80, 0x7f, 0xc0, 0x7f, 0xc0, 0x7f, 0xc0, 0x7, - 0x90, 0x7, 0x90, 0x7, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0xb, 0xfd, - 0xb, 0xfd, 0x0, 0x1f, 0x42, 0xff, 0x82, 0xff, - 0x80, 0x1f, 0xf4, 0x7f, 0xc0, 0x7f, 0xc0, 0x1f, - 0xff, 0x7, 0x90, 0x7, 0x90, 0x1f, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x1f, 0x4f, 0xe0, 0x5, 0x0, 0x0, 0x1f, - 0x43, 0xe0, 0xf, 0xf0, 0x0, 0x1f, 0x43, 0xe0, - 0xb, 0xfd, 0x0, 0xb, 0x43, 0xe0, 0x2, 0xff, - 0x80, 0x3, 0xd7, 0xe0, 0x0, 0x7f, 0xc0, 0x0, - 0xbf, 0xe0, 0x0, 0x7, 0x90, 0x0, 0x1f, 0xe0, - 0x0, 0x0, - - /* U+EF4A "" */ - 0x0, 0x0, 0x1, 0x55, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x1f, 0xfd, - 0x41, 0x6f, 0xf4, 0x0, 0x0, 0x7f, 0x80, 0x0, - 0x2, 0xfe, 0x0, 0x1, 0xfd, 0x0, 0x0, 0x0, - 0x7f, 0x40, 0x3, 0xf4, 0x0, 0x0, 0x0, 0xf, - 0xc0, 0xb, 0xd0, 0x0, 0x0, 0x0, 0x7, 0xf0, - 0xf, 0xc0, 0x0, 0x0, 0x0, 0x2, 0xf4, 0x2f, - 0x40, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3f, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfc, 0x3e, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7c, 0x3e, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7d, 0x3d, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7d, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7d, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, - 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbc, 0x2f, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x1f, 0x40, - 0x0, 0x0, 0x0, 0x1, 0xf8, 0xf, 0xc0, 0x0, - 0x0, 0x0, 0x3, 0xf0, 0x7, 0xf0, 0x0, 0x0, - 0x0, 0xb, 0xe0, 0x3, 0xf8, 0x0, 0x0, 0x0, - 0x2f, 0xc0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xbf, - 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x7, 0xfd, 0x0, - 0x0, 0xb, 0xff, 0xaa, 0xff, 0xf0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+EF7A "" */ - 0x0, 0x1b, 0xfe, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x7, 0xff, 0xaf, 0xfc, - 0x0, 0x0, 0x1f, 0xe0, 0x1, 0xfe, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0x3f, 0x40, 0x0, 0x7e, 0x0, - 0x0, 0xf, 0xc0, 0x0, 0xbc, 0x0, 0x0, 0xb, - 0xc0, 0x0, 0xfc, 0x0, 0x0, 0x7, 0xd0, 0x0, - 0xf8, 0x0, 0x0, 0x7, 0xd0, 0x0, 0xfc, 0x0, - 0x0, 0x7, 0xd0, 0x0, 0xfc, 0x0, 0x0, 0xb, - 0xc0, 0x0, 0x7d, 0x0, 0x0, 0xf, 0xc0, 0x0, - 0x3f, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x1f, 0xd0, - 0x0, 0xff, 0x0, 0x0, 0xb, 0xfe, 0xaf, 0xff, - 0x80, 0x0, 0x1, 0xff, 0xff, 0xef, 0xe0, 0x0, - 0x0, 0x2f, 0xfe, 0x3, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EFE6 "" */ - 0x0, 0x1b, 0xf4, 0x0, 0x1f, 0xf4, 0x0, 0xbf, - 0xff, 0x0, 0x2f, 0xf8, 0x1, 0xff, 0xbf, 0x80, - 0x2f, 0xf8, 0x3, 0xf0, 0xf, 0xc0, 0xbf, 0xfe, - 0x3, 0xe0, 0x7, 0xd0, 0xff, 0xff, 0x7, 0xd0, - 0x3, 0xe0, 0xff, 0xff, 0x7, 0xd0, 0x3, 0xe0, - 0xff, 0xff, 0x7, 0xd0, 0x3, 0xe0, 0xff, 0xff, - 0x7, 0xd0, 0x3, 0xe0, 0xff, 0xff, 0x7, 0xd0, - 0x3, 0xe0, 0x1b, 0xe4, 0x7, 0xd0, 0x3, 0xe0, - 0x7, 0xd0, 0x7, 0xd0, 0x3, 0xe0, 0x7, 0xd0, - 0x7, 0xd0, 0x3, 0xe0, 0x7, 0xd0, 0x7, 0xd0, - 0x3, 0xe0, 0x7, 0xd0, 0x1b, 0xe4, 0x3, 0xe0, - 0x7, 0xd0, 0xff, 0xff, 0x3, 0xe0, 0x7, 0xd0, - 0xff, 0xff, 0x3, 0xe0, 0x7, 0xd0, 0xff, 0xff, - 0x3, 0xe0, 0x7, 0xd0, 0xff, 0xff, 0x3, 0xe0, - 0x7, 0xd0, 0xff, 0xff, 0x3, 0xe0, 0xb, 0xc0, - 0xbf, 0xfe, 0x3, 0xf4, 0xf, 0xc0, 0x2f, 0xf8, - 0x1, 0xff, 0xff, 0x80, 0x2f, 0xf8, 0x0, 0x7f, - 0xfe, 0x0, 0x1f, 0xf4, 0x0, 0x1b, 0xf4, 0x0, - - /* U+F028 "" */ - 0xa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xbc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, - 0x4, 0x1, 0x0, 0x0, 0x3e, 0xbc, 0xf, 0x3, - 0xe0, 0x7c, 0xf, 0x3, 0xeb, 0xc0, 0xf0, 0x3e, - 0x7, 0xc0, 0xf0, 0x3e, 0xbc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3e, 0xbc, 0xa, 0x1, 0xd0, 0x34, - 0xa, 0x3, 0xeb, 0xc1, 0xf4, 0x3e, 0xb, 0xc1, - 0xf4, 0x3e, 0xbc, 0xf, 0x2, 0xd0, 0x38, 0xf, - 0x3, 0xeb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xeb, 0xc0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x3e, - 0xbc, 0x0, 0x1f, 0xff, 0xff, 0x40, 0x3, 0xeb, - 0xc0, 0x0, 0xaa, 0xaa, 0xa0, 0x0, 0x3e, 0xbc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xeb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, - - /* U+F090 "" */ - 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, - 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0xf, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x0, - 0x0, 0xf8, 0x0, 0x0, 0x0, 0x18, 0xf, 0x82, - 0x80, 0x0, 0x3, 0xf0, 0xf8, 0xbd, 0x0, 0x0, - 0x2f, 0xdf, 0xaf, 0xc0, 0x0, 0x0, 0xbf, 0xff, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xc0, 0x0, 0x7, 0x80, 0x0, 0xb0, 0x0, 0x2d, - 0xbc, 0x0, 0x0, 0x0, 0x3, 0xeb, 0xc0, 0x0, - 0x0, 0x0, 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x3, - 0xeb, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0xaa, 0xaa, 0xaa, 0xaa, - 0xa0, - - /* U+F15C "" */ - 0x0, 0x0, 0x0, 0x6a, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x1, 0xff, 0x0, 0x0, 0x0, 0x2, - 0xfc, 0x0, 0x2, 0xfc, 0x0, 0x0, 0x0, 0x7f, - 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0xb, 0xc0, - 0x0, 0x0, 0x3f, 0x0, 0x0, 0x6, 0xfc, 0x0, - 0x0, 0x1, 0xf4, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0xf, 0x40, 0x0, 0xff, 0xe4, 0x0, 0x0, - 0x0, 0xf8, 0x0, 0x2f, 0xc0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf0, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x5, - 0x7f, 0xcb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xeb, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x7e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xe3, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbd, 0x1f, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xc0, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x1, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa9, 0x0, - - /* U+F720 "" */ - 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf9, 0xff, 0xd0, - 0x0, 0x0, 0xbf, 0xe0, 0x7, 0xff, 0x0, 0x1, - 0xff, 0xd0, 0x0, 0x2f, 0xf8, 0x3, 0xff, 0x40, - 0x0, 0x0, 0xbf, 0xd3, 0xfe, 0x0, 0x0, 0x0, - 0x7, 0xfc, 0xff, 0xe0, 0x0, 0x0, 0x7, 0xff, - 0x7f, 0xff, 0x40, 0x0, 0xb, 0xff, 0xdf, 0x9f, - 0xfd, 0x0, 0x2f, 0xf9, 0xf7, 0xe0, 0xbf, 0xe0, - 0x7f, 0xf0, 0x3d, 0xf8, 0x2, 0xff, 0xff, 0xd0, - 0xf, 0x7e, 0x0, 0xf, 0xff, 0x40, 0x3, 0xdf, - 0x80, 0x0, 0x7f, 0x0, 0x0, 0xf7, 0xe0, 0x0, - 0xf, 0x80, 0x0, 0x3d, 0xf8, 0x0, 0x3, 0xe0, - 0x0, 0xf, 0x7e, 0x0, 0x0, 0xf8, 0x0, 0x3, - 0xdf, 0x80, 0x0, 0x3e, 0x0, 0x0, 0xf7, 0xf4, - 0x0, 0xf, 0x80, 0x0, 0xfd, 0xbf, 0xd0, 0x3, - 0xe0, 0x2, 0xff, 0x7, 0xff, 0x0, 0xf8, 0xb, - 0xfe, 0x0, 0x2f, 0xf8, 0x3e, 0x1f, 0xfd, 0x0, - 0x0, 0xbf, 0xef, 0xbf, 0xf4, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x0, 0x0, 0x0, 0x1, 0xe0, 0x0, 0x3e, 0x0, - 0x3, 0xc0, 0x3, 0xf0, 0x0, 0x3e, 0x0, 0xb, - 0xe0, 0xb, 0xe0, 0x0, 0x3e, 0x0, 0x3, 0xf0, - 0xf, 0xc0, 0x0, 0x3e, 0x0, 0x1, 0xf8, 0x1f, - 0x40, 0x0, 0x3e, 0x0, 0x0, 0xfc, 0x3f, 0x0, - 0x0, 0x3e, 0x0, 0x0, 0x7d, 0x3e, 0x0, 0x0, - 0x3e, 0x0, 0x0, 0x3e, 0x3e, 0x0, 0x0, 0x3e, - 0x0, 0x0, 0x3e, 0x3d, 0x0, 0x0, 0x3e, 0x0, - 0x0, 0x3e, 0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0, - 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, 0x2f, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbc, 0x1f, 0x80, - 0x0, 0x0, 0x0, 0x0, 0xfc, 0xf, 0xc0, 0x0, - 0x0, 0x0, 0x2, 0xf4, 0x7, 0xf0, 0x0, 0x0, - 0x0, 0x7, 0xf0, 0x2, 0xf8, 0x0, 0x0, 0x0, - 0x1f, 0xd0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x7f, - 0x40, 0x0, 0x3f, 0xe0, 0x0, 0x7, 0xfd, 0x0, - 0x0, 0xb, 0xff, 0xaa, 0xbf, 0xf4, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+FFF75 "󿽵" */ - 0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x40, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbd, 0x3e, 0x7, 0x0, 0x1c, - 0x0, 0x70, 0x3e, 0x3e, 0xb, 0x0, 0x2c, 0x0, - 0x70, 0x3e, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xbe, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x6, 0xff, 0xf8, 0x0, 0x7e, 0x0, 0x0, 0xbf, - 0xfe, 0x42, 0x40, 0x3e, 0x0, 0x1f, 0xff, 0xd0, - 0x3, 0x80, 0x3e, 0x2, 0xff, 0xf8, 0x1c, 0x0, - 0x1, 0xfd, 0xf, 0xfe, 0x40, 0x2c, 0x0, 0x6f, - 0xf8, 0x3f, 0xe0, 0xd0, 0x0, 0xb, 0xff, 0xe0, - 0x3e, 0x1, 0xd0, 0x2, 0xff, 0xfd, 0x0, 0x3f, - 0x0, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xbe, 0x3e, 0x1, 0x0, 0x4, 0x0, - 0x10, 0x3e, 0x3e, 0xb, 0x0, 0x2c, 0x0, 0xb4, - 0x3e, 0x3e, 0x1, 0x0, 0x4, 0x0, 0x10, 0x3e, - 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xbe, 0x1f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 512, .box_w = 20, .box_h = 20, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 100, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 254, .adv_w = 512, .box_w = 17, .box_h = 26, .ofs_x = 7, .ofs_y = 3}, - {.bitmap_index = 365, .adv_w = 512, .box_w = 20, .box_h = 27, .ofs_x = 6, .ofs_y = 2}, - {.bitmap_index = 500, .adv_w = 512, .box_w = 30, .box_h = 30, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 725, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 879, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1075, .adv_w = 512, .box_w = 16, .box_h = 9, .ofs_x = 8, .ofs_y = 12}, - {.bitmap_index = 1111, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 1265, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1461, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 1605, .adv_w = 512, .box_w = 16, .box_h = 24, .ofs_x = 8, .ofs_y = 4}, - {.bitmap_index = 1701, .adv_w = 512, .box_w = 22, .box_h = 24, .ofs_x = 5, .ofs_y = 4}, - {.bitmap_index = 1833, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 1954, .adv_w = 512, .box_w = 18, .box_h = 18, .ofs_x = 7, .ofs_y = 7}, - {.bitmap_index = 2035, .adv_w = 512, .box_w = 24, .box_h = 16, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 2131, .adv_w = 512, .box_w = 6, .box_h = 22, .ofs_x = 13, .ofs_y = 5}, - {.bitmap_index = 2164, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 2285, .adv_w = 512, .box_w = 32, .box_h = 23, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 2469, .adv_w = 512, .box_w = 22, .box_h = 16, .ofs_x = 5, .ofs_y = 8}, - {.bitmap_index = 2557, .adv_w = 512, .box_w = 25, .box_h = 22, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 2695, .adv_w = 512, .box_w = 24, .box_h = 22, .ofs_x = 4, .ofs_y = 5}, - {.bitmap_index = 2827, .adv_w = 512, .box_w = 22, .box_h = 28, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 2981, .adv_w = 512, .box_w = 28, .box_h = 26, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 3163, .adv_w = 512, .box_w = 26, .box_h = 28, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 3345, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 3541, .adv_w = 512, .box_w = 20, .box_h = 28, .ofs_x = 6, .ofs_y = 2}, - {.bitmap_index = 3681, .adv_w = 512, .box_w = 22, .box_h = 24, .ofs_x = 5, .ofs_y = 4}, - {.bitmap_index = 3813, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 3967, .adv_w = 512, .box_w = 32, .box_h = 31, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 4215, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 4359, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 4555, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 4699, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5}, - {.bitmap_index = 4853, .adv_w = 512, .box_w = 28, .box_h = 24, .ofs_x = 2, .ofs_y = 4}, - {.bitmap_index = 5021, .adv_w = 512, .box_w = 24, .box_h = 28, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 5189, .adv_w = 512, .box_w = 22, .box_h = 28, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 5343, .adv_w = 512, .box_w = 25, .box_h = 22, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 5481, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 5677, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 5821, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 5965, .adv_w = 512, .box_w = 30, .box_h = 22, .ofs_x = 1, .ofs_y = 5}, - {.bitmap_index = 6130, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 6251, .adv_w = 512, .box_w = 30, .box_h = 22, .ofs_x = 1, .ofs_y = 5}, - {.bitmap_index = 6416, .adv_w = 512, .box_w = 25, .box_h = 28, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 6591, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 6787, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_32 = { -#else -lv_font_t material_symbols_shared_32 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 31, /*The maximum line height required by the font*/ - .base_line = -1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_32*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_40.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_40.c deleted file mode 100644 index ae335b8c0..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_40.c +++ /dev/null @@ -1,1632 +0,0 @@ -/******************************************************************************* - * Size: 40 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 40 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_40.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_40 -#define MATERIAL_SYMBOLS_SHARED_40 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_40 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xe0, 0x0, 0x0, 0x15, 0x55, 0x5f, 0xf5, - 0x55, 0x54, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0xf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x0, 0x0, - - /* U+E159 "" */ - 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xdf, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xfd, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xdf, 0xef, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xfe, 0xfd, 0xfd, 0x2f, 0xf8, 0x0, - 0x0, 0x7, 0xff, 0x4f, 0xdf, 0xd0, 0x3f, 0xf4, - 0x0, 0x2, 0xff, 0x80, 0xfd, 0xfd, 0x0, 0x7f, - 0xe0, 0x1, 0xff, 0xc0, 0xf, 0xdf, 0xd0, 0x0, - 0xbf, 0xd0, 0xff, 0xd0, 0x0, 0xfd, 0xfd, 0x0, - 0x1, 0xff, 0xff, 0xe0, 0x0, 0xf, 0xdf, 0xd0, - 0x0, 0x2, 0xff, 0xf4, 0x0, 0x0, 0xfd, 0xfd, - 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0xf, 0xdf, - 0xd0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xfd, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x15, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x0, - - /* U+E1A7 "" */ - 0x0, 0x0, 0x7, 0xc0, 0x0, 0x0, 0x0, 0x3, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xc0, 0xb, 0x80, 0x3, 0xff, 0xfc, 0x3, - 0xf8, 0x0, 0xfd, 0xbf, 0xc0, 0xff, 0x80, 0x3f, - 0x4b, 0xfc, 0xf, 0xf8, 0xf, 0xd0, 0xbf, 0x80, - 0xff, 0x83, 0xf4, 0x3f, 0xd0, 0xf, 0xf8, 0xfd, - 0x3f, 0xe0, 0x0, 0xff, 0xbf, 0xbf, 0xe0, 0x0, - 0xf, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0xf, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x80, 0x0, 0x0, - 0x3f, 0xff, 0xf8, 0x0, 0x0, 0x3f, 0xff, 0xff, - 0x80, 0x0, 0x3f, 0xef, 0xef, 0xf8, 0x0, 0x3f, - 0xe3, 0xf4, 0xff, 0x80, 0x3f, 0xe0, 0xfd, 0xf, - 0xf4, 0x3f, 0xe0, 0x3f, 0x42, 0xfe, 0x3f, 0xe0, - 0xf, 0xd2, 0xff, 0xf, 0xe0, 0x3, 0xf6, 0xff, - 0x2, 0xe0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xf0, 0x0, 0x0, 0x6, 0x80, 0xb, 0xf0, - 0x1a, 0xa8, 0x3f, 0xf0, 0xb, 0xf0, 0x3f, 0xfe, - 0x7f, 0xf8, 0xb, 0xf0, 0x3f, 0xfe, 0xbf, 0xfc, - 0xb, 0xf0, 0x3f, 0xfe, 0xbf, 0xfc, 0xb, 0xf0, - 0x3f, 0xfe, 0x3f, 0xf4, 0xb, 0xf0, 0x3f, 0xfe, - 0xf, 0xd0, 0xb, 0xf0, 0x3f, 0xfd, 0xf, 0xd0, - 0xb, 0xf0, 0x7, 0xf0, 0xf, 0xd0, 0xb, 0xf0, - 0x7, 0xf0, 0xf, 0xd0, 0xb, 0xf0, 0x7, 0xf0, - 0xf, 0xfa, 0xaf, 0xfa, 0xaf, 0xf0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0xaa, 0xaf, 0xfa, 0xaa, 0x0, - 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x90, 0x0, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xc3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x41, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x41, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0x41, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x2a, 0xaa, 0xbf, 0xeb, 0xfe, 0xaa, - 0xa8, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x3, 0xfe, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xbf, 0xc0, 0x3, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x3, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x3, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0xf, 0xe5, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xf0, 0xf, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xf0, 0x1f, 0xc0, 0x78, - 0x0, 0x3c, 0x0, 0x2d, 0x3, 0xf4, 0x2f, 0xc0, - 0xfd, 0x0, 0xbe, 0x0, 0x7f, 0x3, 0xf8, 0x3f, - 0x80, 0xfd, 0x0, 0xbe, 0x0, 0x7f, 0x2, 0xfc, - 0x3f, 0x40, 0xfd, 0x0, 0xbe, 0x0, 0x7f, 0x1, - 0xfc, 0x7f, 0x0, 0xfd, 0x0, 0xbe, 0x0, 0x7f, - 0x0, 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, - - /* U+E2C7 "" */ - 0x1, 0x55, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xff, 0xfe, 0xf, 0xd0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xfd, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xd0, 0x0, 0x0, 0x15, - 0x55, 0x55, 0x55, 0xfd, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xdf, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x15, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x0, - - /* U+E30F "" */ - 0x0, 0x0, 0x0, 0x15, 0x55, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x7f, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x7, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, - 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf6, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xe0, 0x3, 0xfc, 0x0, 0xff, 0xff, 0xcf, 0xff, - 0xff, 0x80, 0xa, 0x0, 0x3f, 0xff, 0xfd, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0xf, 0xff, 0xff, 0xdf, - 0xe5, 0x5f, 0xf8, 0x0, 0x3, 0xfe, 0x55, 0xfd, - 0xfd, 0x0, 0x3f, 0xd0, 0x0, 0xbf, 0x80, 0xf, - 0xdf, 0xd0, 0x3, 0xfd, 0x0, 0xb, 0xf8, 0x0, - 0xfd, 0xfe, 0x55, 0xff, 0x80, 0x0, 0x3f, 0xe5, - 0x5f, 0xdf, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xff, 0xfd, 0xff, 0xff, 0xf8, 0x0, 0xa0, 0x3, - 0xff, 0xff, 0xd7, 0xff, 0xfe, 0x0, 0x3f, 0xc0, - 0xf, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xbf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfc, 0x7, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xc0, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfc, 0x7, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xc0, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0x5b, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0xfd, 0x0, 0x0, - 0x0, - - /* U+E316 "" */ - 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x40, 0x0, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x0, - 0xf, 0xff, 0xf4, 0x0, 0x0, 0x3f, 0xe7, 0xfd, - 0x0, 0x0, 0xff, 0x81, 0xff, 0x40, 0x3, 0xfe, - 0x0, 0x7f, 0xd0, 0xf, 0xf8, 0x0, 0x1f, 0xf4, - 0x3f, 0xe0, 0x0, 0x7, 0xfc, 0x3f, 0x80, 0x0, - 0x1, 0xfd, 0x2e, 0x0, 0x0, 0x0, 0x78, - - /* U+E326 "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x55, 0x50, 0xf, 0xd0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0xc0, 0xfd, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xfd, 0xf, 0xd0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xd0, 0xfd, 0x0, - 0x0, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xf, 0xd0, - 0x0, 0x0, 0x0, 0xfd, 0x4, 0xf, 0xd0, 0xfd, - 0x0, 0x0, 0x0, 0xf, 0xd1, 0xf0, 0xfd, 0xf, - 0xd0, 0x0, 0x0, 0x0, 0xfd, 0xa, 0xf, 0xd0, - 0xfd, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0xfd, - 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0xf, - 0xd0, 0xfd, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, - 0xfd, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfd, 0x0, - 0xf, 0xd0, 0xff, 0xff, 0xff, 0xf4, 0xf, 0xd0, - 0x0, 0xfd, 0xb, 0xff, 0xff, 0xff, 0xc0, 0xfd, - 0x0, 0xf, 0xd0, 0x2f, 0xff, 0xff, 0xf8, 0xf, - 0xd0, 0x0, 0xfd, 0x0, 0x15, 0x55, 0x55, 0x0, - 0xfd, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xd0, 0x0, 0xfd, 0x3f, 0xff, 0xff, 0xff, - 0x40, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, - 0xfc, 0xf, 0xff, 0xff, 0xfd, 0x7f, 0xff, 0xff, - 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x55, 0x55, - 0x55, 0x50, 0x0, 0x55, 0x55, 0x40, - - /* U+E3AF "" */ - 0x0, 0x0, 0x0, 0x5, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0xb, 0xff, 0x90, 0xb, 0xaf, - 0xfe, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0xf0, - 0x2f, 0xf8, 0x0, 0x0, 0xbf, 0xc0, 0x0, 0x2c, - 0x0, 0x3f, 0xe0, 0x0, 0x2f, 0xf0, 0x0, 0x7, - 0x80, 0x0, 0xff, 0x40, 0x3, 0xff, 0x0, 0x0, - 0xf0, 0x0, 0x3, 0xfc, 0x0, 0xff, 0x78, 0x0, - 0x2d, 0x0, 0x0, 0xf, 0xe0, 0x1f, 0xd2, 0xd0, - 0x3, 0xc0, 0x0, 0x0, 0xbf, 0x2, 0xfc, 0xf, - 0x0, 0xb8, 0x0, 0x0, 0x3, 0xf8, 0x3f, 0x40, - 0x74, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xf0, - 0x3, 0xc3, 0xff, 0xff, 0xaa, 0xaa, 0xfc, 0xbf, - 0x0, 0x1f, 0xbf, 0xff, 0xd0, 0x0, 0xf, 0xdb, - 0xe0, 0x0, 0xbf, 0xff, 0xff, 0x0, 0x0, 0xfd, - 0xbe, 0x0, 0x3, 0xff, 0xff, 0xf4, 0x0, 0xf, - 0xeb, 0xe0, 0x0, 0x2f, 0xff, 0xff, 0xc0, 0x0, - 0xfe, 0xbe, 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, - 0xf, 0xeb, 0xf0, 0x0, 0xb, 0xff, 0xfe, 0xf0, - 0x0, 0xfd, 0x7f, 0xaa, 0xaa, 0xff, 0xff, 0x83, - 0x80, 0x1f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x2d, 0x2, 0xfc, 0x3f, 0xc0, 0x0, 0x0, 0x3e, - 0x0, 0xf0, 0x3f, 0x82, 0xfd, 0x0, 0x0, 0x3, - 0xc0, 0xb, 0x4b, 0xf4, 0xf, 0xf0, 0x0, 0x0, - 0xb4, 0x0, 0x3d, 0xff, 0x0, 0x7f, 0x80, 0x0, - 0xf, 0x0, 0x1, 0xff, 0xd0, 0x3, 0xfe, 0x0, - 0x3, 0xd0, 0x0, 0xf, 0xf8, 0x0, 0xf, 0xf8, - 0x0, 0x78, 0x0, 0x3, 0xff, 0x0, 0x0, 0x7f, - 0xf4, 0xf, 0x0, 0x1, 0xff, 0xc0, 0x0, 0x1, - 0xff, 0xf6, 0xe0, 0x1, 0xff, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xfe, 0xab, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xe4, 0x0, 0x0, - 0x0, - - /* U+E3F4 "" */ - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, - 0x55, 0x55, 0x55, 0x55, 0x55, 0xbf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x7f, - 0xfd, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x7, 0xff, - 0xd0, 0x2, 0x80, 0x3, 0xf8, 0x0, 0x7f, 0xfd, - 0x0, 0x7d, 0x0, 0xff, 0xd0, 0x7, 0xff, 0xd0, - 0xf, 0xf0, 0x2f, 0xff, 0x0, 0x7f, 0xfd, 0x3, - 0xff, 0xc7, 0xff, 0xfc, 0x7, 0xff, 0xd0, 0xbf, - 0xfe, 0xff, 0xff, 0xe0, 0x7f, 0xfd, 0xf, 0xff, - 0xff, 0xff, 0xff, 0x7, 0xff, 0xd0, 0x15, 0x55, - 0x55, 0x55, 0x40, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, - - /* U+E405 "" */ - 0x0, 0x0, 0x7, 0xff, 0xfd, 0x0, 0x0, 0xf, - 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, - 0xf, 0xfa, 0xa8, 0x0, 0x0, 0xf, 0xd0, 0x0, - 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xf, - 0xd0, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, - 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xf, 0xd0, - 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, - 0xf, 0xd0, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, - 0x0, 0x4, 0xf, 0xd0, 0x0, 0x2, 0xff, 0xef, - 0xd0, 0x0, 0xf, 0xff, 0xff, 0xd0, 0x0, 0x3f, - 0xff, 0xff, 0xd0, 0x0, 0x7f, 0xff, 0xff, 0xd0, - 0x0, 0xbf, 0xff, 0xff, 0xd0, 0x0, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0xbf, 0xff, 0xff, - 0xc0, 0x0, 0x3f, 0xff, 0xff, 0x80, 0x0, 0x2f, - 0xff, 0xff, 0x0, 0x0, 0xb, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0xbf, 0x90, 0x0, 0x0, - - /* U+E55D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xeb, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xc3, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0x82, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x1, 0xfd, 0x0, - 0x7f, 0x40, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x3f, - 0xc0, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x1f, 0xc0, - 0x0, 0x0, 0xb, 0xf0, 0x0, 0xf, 0xe0, 0x0, - 0x0, 0xf, 0xe0, 0x0, 0xb, 0xf0, 0x0, 0x0, - 0x2f, 0xc0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x3f, - 0x80, 0x0, 0x2, 0xfc, 0x0, 0x0, 0x7f, 0x0, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x1, 0xfd, 0x0, 0x14, 0x0, - 0x7f, 0x40, 0x3, 0xfc, 0x2, 0xff, 0x80, 0x3f, - 0xc0, 0x3, 0xf4, 0x6f, 0xff, 0xf9, 0x1f, 0xc0, - 0xb, 0xfb, 0xff, 0xff, 0xff, 0xef, 0xe0, 0xf, - 0xff, 0xff, 0x82, 0xff, 0xff, 0xf0, 0x2f, 0xff, - 0xf4, 0x0, 0x1f, 0xff, 0xf8, 0x3f, 0xff, 0x40, - 0x0, 0x1, 0xff, 0xfc, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0x19, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x64, - - /* U+E5C3 "" */ - 0x1, 0x40, 0x0, 0x14, 0x0, 0x1, 0x40, 0x1f, - 0xf4, 0x1, 0xff, 0x40, 0x1f, 0xf4, 0x3f, 0xfc, - 0x3, 0xff, 0xc0, 0x3f, 0xfc, 0x3f, 0xfd, 0x3, - 0xff, 0xd0, 0x3f, 0xfd, 0x3f, 0xfd, 0x3, 0xff, - 0xd0, 0x3f, 0xfd, 0x2f, 0xfc, 0x2, 0xff, 0xc0, - 0x2f, 0xfc, 0xb, 0xf0, 0x0, 0xbf, 0x0, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, - 0x0, 0x14, 0x0, 0x1, 0x40, 0x1f, 0xf4, 0x1, - 0xff, 0x40, 0x1f, 0xf4, 0x3f, 0xfc, 0x3, 0xff, - 0xc0, 0x3f, 0xfc, 0x3f, 0xfd, 0x3, 0xff, 0xd0, - 0x3f, 0xfd, 0x3f, 0xfd, 0x3, 0xff, 0xd0, 0x3f, - 0xfd, 0x2f, 0xfc, 0x2, 0xff, 0xc0, 0x2f, 0xfc, - 0xb, 0xf0, 0x0, 0xbf, 0x0, 0xb, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x14, - 0x0, 0x1, 0x40, 0x1f, 0xf4, 0x1, 0xff, 0x40, - 0x1f, 0xf4, 0x3f, 0xfc, 0x3, 0xff, 0xc0, 0x3f, - 0xfc, 0x3f, 0xfd, 0x3, 0xff, 0xd0, 0x3f, 0xfd, - 0x3f, 0xfd, 0x3, 0xff, 0xd0, 0x3f, 0xfd, 0x2f, - 0xfc, 0x2, 0xff, 0xc0, 0x2f, 0xfc, 0xb, 0xf0, - 0x0, 0xbf, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E5CD "" */ - 0x78, 0x0, 0x0, 0x0, 0x2, 0xdf, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0xbf, 0xc0, 0x0, 0x0, 0x3f, - 0xe3, 0xff, 0x0, 0x0, 0xf, 0xfc, 0xf, 0xfc, - 0x0, 0x3, 0xff, 0x0, 0x3f, 0xf0, 0x0, 0xff, - 0xc0, 0x0, 0xff, 0xc0, 0x3f, 0xf0, 0x0, 0x3, - 0xff, 0xf, 0xfc, 0x0, 0x0, 0xf, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x3f, 0xf0, - 0xff, 0xc0, 0x0, 0xf, 0xfc, 0x3, 0xff, 0x0, - 0x3, 0xff, 0x0, 0xf, 0xfc, 0x0, 0xff, 0xc0, - 0x0, 0x3f, 0xf0, 0x3f, 0xf0, 0x0, 0x0, 0xff, - 0xcb, 0xfc, 0x0, 0x0, 0x3, 0xfe, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xf7, 0x80, 0x0, 0x0, 0x0, - 0x2d, - - /* U+E5D2 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x15, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x4f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x4b, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+E5D4 "" */ - 0x1, 0x40, 0x1f, 0xf4, 0x3f, 0xfc, 0x3f, 0xfd, - 0x3f, 0xfd, 0x2f, 0xfc, 0xb, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x1f, 0xf4, - 0x3f, 0xfc, 0x3f, 0xfd, 0x3f, 0xfd, 0x2f, 0xfc, - 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x40, 0x1f, 0xf4, 0x3f, 0xfc, 0x3f, 0xfd, - 0x3f, 0xfd, 0x2f, 0xfc, 0xb, 0xf0, 0x0, 0x0, - - /* U+E5D5 "" */ - 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x10, 0x0, - 0x0, 0x2f, 0xff, 0xf8, 0x0, 0xbc, 0x0, 0x2, - 0xff, 0xff, 0xff, 0x80, 0xfd, 0x0, 0x1f, 0xff, - 0xff, 0xff, 0xf0, 0xfd, 0x0, 0x7f, 0xf9, 0x0, - 0x6f, 0xfd, 0xfd, 0x1, 0xff, 0x80, 0x0, 0x2, - 0xff, 0xfd, 0x3, 0xfd, 0x0, 0x0, 0x0, 0x7f, - 0xfd, 0xb, 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xfd, - 0xf, 0xe0, 0x0, 0x0, 0x0, 0xb, 0xfd, 0x2f, - 0xc0, 0x0, 0x0, 0xbf, 0xff, 0xfd, 0x3f, 0x80, - 0x0, 0x1, 0xff, 0xff, 0xfd, 0x3f, 0x40, 0x0, - 0x0, 0xff, 0xff, 0xfc, 0x3f, 0x0, 0x0, 0x0, - 0x15, 0x55, 0x50, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xc0, - 0x0, 0x0, 0x0, 0x3, 0xe0, 0xf, 0xe0, 0x0, - 0x0, 0x0, 0xb, 0xf0, 0xb, 0xf4, 0x0, 0x0, - 0x0, 0x1f, 0xe0, 0x3, 0xfd, 0x0, 0x0, 0x0, - 0x7f, 0xc0, 0x1, 0xff, 0x80, 0x0, 0x2, 0xff, - 0x40, 0x0, 0x7f, 0xf9, 0x0, 0x6f, 0xfd, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x14, 0x0, 0x0, 0x0, - - /* U+E63E "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, 0xf9, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x6f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0xf, 0xff, 0xff, 0xe4, 0x0, 0x1, 0xbf, - 0xff, 0xff, 0x3, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xfc, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xbf, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xe1, 0x90, 0x0, 0x1, 0xbf, 0xff, 0xe4, 0x0, - 0x0, 0x64, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x3, 0xff, 0xf9, 0x0, 0x6, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x2, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, - 0x0, 0x2, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x80, - 0x0, 0x0, 0x0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0x40, 0x7, 0xc0, 0x0, 0x0, 0x7f, 0xd0, - 0x0, 0xff, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0xb, - 0xfc, 0x0, 0x7, 0xfd, 0x0, 0x0, 0x2f, 0xf0, - 0x1, 0xff, 0x40, 0x0, 0x0, 0xbf, 0xc0, 0x7f, - 0xd0, 0x0, 0x0, 0x2, 0xff, 0x1f, 0xf4, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E745 "" */ - 0x5, 0x55, 0x55, 0x55, 0x50, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xb, - 0xff, 0xff, 0xff, 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, 0x1, 0x55, - 0x55, 0x55, 0x54, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0x2, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x1f, 0xff, 0xf, 0xff, 0xff, 0xd0, - 0x0, 0x1, 0xff, 0xfd, 0x3f, 0xff, 0xff, 0x0, - 0x0, 0x1f, 0xff, 0xf8, 0x15, 0x55, 0x50, 0x0, - 0x1, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xdf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xfc, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xc0, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfd, - 0xb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xd0, - 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x50, 0x0, - 0x0, - - /* U+E770 "" */ - 0x0, 0x0, 0x0, 0x6, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0x41, 0xff, 0xd5, 0x40, 0x0, 0x0, 0x1f, - 0xe0, 0x3, 0xff, 0xff, 0x82, 0x40, 0x3, 0xfc, - 0x0, 0xb, 0xff, 0xfe, 0xfe, 0x0, 0xff, 0x40, - 0x0, 0x1f, 0xff, 0xff, 0xfc, 0x2f, 0xe0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xfb, 0xfc, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xfe, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xd3, 0xf8, 0x0, 0x10, 0x0, 0x0, - 0x7f, 0xfd, 0xb, 0x0, 0xf, 0x80, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x7f, - 0xfd, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x7, 0xff, - 0xd0, 0x0, 0xf, 0xff, 0xf8, 0x0, 0x7f, 0xfe, - 0x0, 0x3, 0xff, 0xff, 0xf0, 0x7, 0xff, 0xf8, - 0x0, 0xbf, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xf0, - 0x1f, 0xff, 0xff, 0xff, 0x47, 0xff, 0xff, 0xd3, - 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf5, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, - - /* U+E89C "" */ - 0x1, 0x55, 0x55, 0x55, 0x40, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x7f, 0x0, 0x0, 0x1, - 0xff, 0xd0, 0x0, 0x7f, 0x0, 0x0, 0x1, 0xff, - 0xf4, 0x0, 0x7f, 0x0, 0x0, 0x1, 0xff, 0xfd, - 0x0, 0x7f, 0x0, 0x0, 0x1, 0xff, 0xff, 0x40, - 0x7f, 0x0, 0x0, 0x1, 0xff, 0xff, 0xd0, 0x7f, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xf4, 0x7f, 0x0, - 0x0, 0x1, 0xff, 0xff, 0xfc, 0x7f, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xfc, 0x7f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x7d, 0x0, 0x0, - 0xfd, 0x7f, 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, - 0x7f, 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, 0x7f, - 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, 0x7f, 0x0, - 0x0, 0xbe, 0x0, 0x0, 0xfd, 0x7f, 0x1, 0xff, - 0xff, 0xff, 0x40, 0xfd, 0x7f, 0x2, 0xff, 0xff, - 0xff, 0x80, 0xfd, 0x7f, 0x1, 0xff, 0xff, 0xff, - 0x40, 0xfd, 0x7f, 0x0, 0x0, 0xbe, 0x0, 0x0, - 0xfd, 0x7f, 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, - 0x7f, 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, 0x7f, - 0x0, 0x0, 0xbe, 0x0, 0x0, 0xfd, 0x7f, 0x0, - 0x0, 0x7d, 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x7f, 0x55, 0x55, 0x55, 0x55, 0x55, - 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - - /* U+E8AF "" */ - 0x5, 0x55, 0x55, 0x55, 0x55, 0x54, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xc0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0xfc, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0xfc, 0xb, 0x90, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xc0, 0xff, 0x4f, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0xfc, 0xf, 0xfc, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xc0, 0xff, 0xcf, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0xfc, 0xf, 0xfc, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xc0, 0xff, 0xcf, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xfc, 0xf, 0xfc, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0xff, 0xcf, - 0xd1, 0x55, 0x55, 0x55, 0x56, 0xfc, 0xf, 0xfc, - 0xfd, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, - 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0xff, 0xcf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfc, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xcf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xfc, 0x7c, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x5, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x7, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x3f, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x87, 0xfc, 0x3, - 0xfd, 0x2f, 0xf0, 0x0, 0x2f, 0xff, 0xff, 0xc0, - 0x3f, 0xff, 0xff, 0x80, 0x7, 0xff, 0xff, 0xf4, - 0x1, 0xff, 0xff, 0xfd, 0x0, 0xff, 0x6f, 0xf0, - 0x0, 0x1, 0xff, 0x9f, 0xf0, 0x1f, 0xd0, 0x18, - 0x0, 0x0, 0x2, 0x80, 0x7f, 0x43, 0xfc, 0x0, - 0x0, 0x1a, 0x40, 0x0, 0x3, 0xfc, 0x3f, 0xd0, - 0x0, 0x1f, 0xff, 0x40, 0x0, 0x7f, 0xc1, 0xff, - 0x80, 0x7, 0xff, 0xfe, 0x0, 0x2f, 0xf4, 0xb, - 0xff, 0x0, 0xff, 0xff, 0xf0, 0xf, 0xfe, 0x0, - 0x1f, 0xf0, 0x1f, 0xff, 0xff, 0x80, 0xff, 0x40, - 0x0, 0x7f, 0x2, 0xff, 0xff, 0xfc, 0xf, 0xd0, - 0x0, 0x7, 0xf0, 0x2f, 0xff, 0xff, 0xc0, 0xfd, - 0x0, 0x0, 0xbf, 0x2, 0xff, 0xff, 0xfc, 0xf, - 0xe0, 0x0, 0x3f, 0xf0, 0x1f, 0xff, 0xff, 0x40, - 0xff, 0xc0, 0xf, 0xfd, 0x0, 0xbf, 0xff, 0xf0, - 0x7, 0xff, 0x2, 0xff, 0x0, 0x3, 0xff, 0xfc, - 0x0, 0xf, 0xf8, 0x3f, 0xc0, 0x0, 0x7, 0xfe, - 0x0, 0x0, 0x3f, 0xc2, 0xfc, 0x0, 0x40, 0x0, - 0x0, 0x0, 0x3, 0xf8, 0xf, 0xf0, 0xbd, 0x0, - 0x0, 0x7, 0xe0, 0xff, 0x0, 0xbf, 0xff, 0xfd, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x3, 0xff, 0xff, - 0xfc, 0x3, 0xff, 0xff, 0xfc, 0x0, 0x1f, 0xfe, - 0xff, 0xc0, 0x3f, 0xfb, 0xff, 0x0, 0x0, 0x29, - 0x2, 0xfc, 0x3, 0xf8, 0x6, 0x80, 0x0, 0x0, - 0x0, 0xf, 0xc0, 0x3f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0x5b, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xf4, 0x0, 0x0, - 0x0, - - /* U+E8FD "" */ - 0x0, 0x0, 0x0, 0x5, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0xb, 0xff, 0x90, 0x0, 0x6f, - 0xfe, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x3f, 0xe0, 0x0, 0x2f, 0xe0, 0x0, 0x6f, - 0x90, 0x0, 0xff, 0x40, 0x7, 0xfc, 0x0, 0x3f, - 0xff, 0xc0, 0x3, 0xfc, 0x0, 0xff, 0x0, 0xf, - 0xff, 0xff, 0x0, 0xf, 0xe0, 0x1f, 0xd0, 0x1, - 0xfd, 0x7, 0xf8, 0x0, 0xbf, 0x3, 0xfc, 0x0, - 0xb, 0x0, 0x2f, 0xc0, 0x3, 0xf8, 0x3f, 0x40, - 0x0, 0x0, 0x1, 0xfc, 0x0, 0x2f, 0xc7, 0xf0, - 0x0, 0x0, 0x0, 0x2f, 0x80, 0x1, 0xfc, 0xbf, - 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0xf, 0xdb, - 0xe0, 0x0, 0x0, 0x1, 0xfd, 0x0, 0x0, 0xfd, - 0xbe, 0x0, 0x0, 0x0, 0x7f, 0x40, 0x0, 0xf, - 0xeb, 0xe0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, - 0xfe, 0xbe, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, - 0xf, 0xeb, 0xf0, 0x0, 0x0, 0x2f, 0x40, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x90, 0x0, - 0x0, 0xf, 0xc3, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xfc, 0x3f, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x82, 0xfc, 0x0, 0x0, 0x2f, - 0x40, 0x0, 0x7, 0xf4, 0xf, 0xe0, 0x0, 0x3, - 0xfc, 0x0, 0x0, 0xff, 0x0, 0x7f, 0x80, 0x0, - 0x3f, 0xc0, 0x0, 0x2f, 0xd0, 0x3, 0xfd, 0x0, - 0x2, 0xf4, 0x0, 0xb, 0xf8, 0x0, 0xf, 0xf4, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x1, - 0xff, 0xe0, 0x0, 0x1, 0xbf, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xfa, 0xaa, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xe4, 0x0, 0x0, - 0x0, - - /* U+E90F "" */ - 0x0, 0x0, 0x1, 0x54, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xfe, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0x0, 0xff, 0xe0, 0x0, 0xbf, 0xf0, - 0x0, 0x3f, 0xe0, 0x0, 0x0, 0xbf, 0xc0, 0xb, - 0xf8, 0x0, 0x0, 0x2, 0xfe, 0x0, 0xfe, 0x0, - 0x0, 0x0, 0xb, 0xf0, 0x2f, 0xc0, 0x0, 0x0, - 0x0, 0x3f, 0x83, 0xf8, 0x0, 0x0, 0x0, 0x2, - 0xfc, 0x3f, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc7, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x7f, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xd7, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xd3, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xfc, - 0x3f, 0x80, 0x0, 0x0, 0x0, 0x2f, 0xc2, 0xfc, - 0x0, 0x0, 0x0, 0x3, 0xf8, 0xf, 0xe0, 0x0, - 0x0, 0x0, 0xbf, 0x0, 0xbf, 0x80, 0x0, 0x0, - 0x2f, 0xe0, 0x3, 0xfe, 0x55, 0x55, 0x5b, 0xfc, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x15, 0x55, 0x55, 0x40, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x55, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0x40, 0x0, 0x0, - - /* U+E92E "" */ - 0x0, 0x0, 0x1f, 0xff, 0xf4, 0x0, 0x0, 0x5, - 0x55, 0x7f, 0xff, 0xfd, 0x55, 0x50, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0xe0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0xb, - 0xe0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0xb, 0xe0, - 0xb, 0xe0, 0x9, 0x0, 0x60, 0xb, 0xe0, 0xb, - 0xe0, 0x3f, 0x0, 0xfc, 0xb, 0xe0, 0xb, 0xe0, - 0x3f, 0x41, 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, - 0x41, 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, 0x41, - 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, 0x41, 0xfc, - 0xb, 0xe0, 0xb, 0xe0, 0x3f, 0x41, 0xfc, 0xb, - 0xe0, 0xb, 0xe0, 0x3f, 0x41, 0xfc, 0xb, 0xe0, - 0xb, 0xe0, 0x3f, 0x41, 0xfc, 0xb, 0xe0, 0xb, - 0xe0, 0x3f, 0x41, 0xfc, 0xb, 0xe0, 0xb, 0xe0, - 0x3f, 0x41, 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, - 0x41, 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, 0x41, - 0xfc, 0xb, 0xe0, 0xb, 0xe0, 0x3f, 0x41, 0xfc, - 0xb, 0xe0, 0xb, 0xe0, 0x2f, 0x0, 0xf8, 0xb, - 0xe0, 0xb, 0xe0, 0x4, 0x0, 0x10, 0xb, 0xe0, - 0xb, 0xe0, 0x0, 0x0, 0x0, 0xb, 0xe0, 0xb, - 0xe0, 0x0, 0x0, 0x0, 0xb, 0xe0, 0xb, 0xf5, - 0x55, 0x55, 0x55, 0x5b, 0xe0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0x0, - - /* U+E9B9 "" */ - 0x5, 0x40, 0x0, 0x5a, 0xaa, 0xaa, 0xaa, 0xa4, - 0x2, 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x7f, 0xf8, 0x7, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xdb, 0xff, 0xc0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xbf, 0xfc, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd3, 0xff, 0x40, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x1f, 0xe0, 0x1, 0xff, 0xff, - 0xff, 0xff, 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, 0x0, 0x5, 0x40, 0x0, - 0x5a, 0xaa, 0xaa, 0xaa, 0xa4, 0x2, 0xff, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xf8, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xc0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xbf, - 0xfc, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, - 0xff, 0x40, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x1f, 0xe0, 0x1, 0xff, 0xff, 0xff, 0xff, 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, 0x0, 0x5, 0x40, 0x0, 0x5a, 0xaa, 0xaa, - 0xaa, 0xa4, 0x2, 0xff, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x7f, 0xf8, 0x7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdb, 0xff, 0xc0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xbf, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0xff, 0x40, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xe0, 0x1, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E9F4 "" */ - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xfe, 0x7f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xf8, 0x1f, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x1f, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xfe, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfd, - 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x7f, 0xd0, - 0x2f, 0xff, 0x80, 0x0, 0x3, 0xd0, 0x0, 0x2, - 0xff, 0xf8, 0x7f, 0xff, 0xd0, 0x0, 0x7, 0xe0, - 0x0, 0x7, 0xff, 0xfd, 0xff, 0x5f, 0xf0, 0x0, - 0xbf, 0xff, 0x0, 0xf, 0xf5, 0xff, 0xfd, 0x7, - 0xf0, 0x3, 0xff, 0xff, 0xc0, 0xf, 0xd0, 0x7f, - 0xfe, 0xb, 0xf9, 0xf, 0xfe, 0xbf, 0xf0, 0x6f, - 0xe0, 0xbf, 0xbf, 0xaf, 0xff, 0xff, 0xe0, 0xb, - 0xff, 0xff, 0xfa, 0xfe, 0x3f, 0xff, 0xef, 0xff, - 0x80, 0x2, 0xff, 0xfb, 0xff, 0xfc, 0x1f, 0xff, - 0x41, 0xff, 0x0, 0x0, 0xff, 0x41, 0xff, 0xf4, - 0x2, 0xf8, 0x0, 0x7f, 0x0, 0x0, 0xfd, 0x0, - 0x2f, 0x80, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xc0, 0x2, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xe0, 0xb, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xbf, 0xfe, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0xbe, 0x5, 0x50, 0xbe, 0x14, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, - 0x3f, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x2f, - 0xff, 0xf8, 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, - 0x0, 0x3f, 0x82, 0xfc, 0x0, 0x0, 0x3f, 0x82, - 0xfc, 0x0, 0x0, 0x3f, 0x41, 0xfc, 0x0, 0x0, - 0x3f, 0x41, 0xfc, 0x0, 0x0, 0x3f, 0xc3, 0xfc, - 0x0, 0x0, 0x3f, 0xc3, 0xfc, 0x0, 0x0, 0x2f, - 0xff, 0xf8, 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, - 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x14, 0x0, - 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, - - /* U+E9F7 "" */ - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, - 0x55, 0x55, 0x55, 0x55, 0x55, 0xbf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, - - /* U+EA07 "" */ - 0x0, 0x0, 0x0, 0x5, 0x54, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0xb, 0xff, 0xff, 0xaf, 0xff, - 0xfe, 0x0, 0x0, 0x3, 0xff, 0x8f, 0xf0, 0xfe, - 0x2f, 0xf8, 0x0, 0x0, 0xbf, 0xc1, 0xfd, 0xb, - 0xf0, 0x7f, 0xe0, 0x0, 0x2f, 0xf0, 0x2f, 0xc0, - 0x3f, 0x80, 0xff, 0x40, 0x3, 0xfc, 0x3, 0xf4, - 0x2, 0xfc, 0x3, 0xfc, 0x0, 0xff, 0x0, 0x7f, - 0x0, 0x1f, 0xc0, 0x1f, 0xe0, 0x1f, 0xf5, 0x5f, - 0xf5, 0x55, 0xfe, 0x55, 0xff, 0x2, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, - 0x0, 0x1f, 0xc0, 0x0, 0x3f, 0x0, 0xf, 0xdb, - 0xe0, 0x1, 0xfc, 0x0, 0x3, 0xf4, 0x0, 0xfd, - 0xbe, 0x0, 0x2f, 0xc0, 0x0, 0x3f, 0x40, 0xf, - 0xef, 0xe0, 0x2, 0xfc, 0x0, 0x3, 0xf4, 0x0, - 0xfe, 0xbe, 0x0, 0x2f, 0xc0, 0x0, 0x3f, 0x40, - 0xf, 0xeb, 0xf0, 0x1, 0xfc, 0x0, 0x3, 0xf4, - 0x0, 0xfd, 0x7f, 0x55, 0x6f, 0xd5, 0x55, 0xbf, - 0x95, 0x6f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x82, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0xf, 0xf0, 0x7, 0xf0, - 0x0, 0xfd, 0x0, 0xff, 0x0, 0x7f, 0x80, 0x3f, - 0x40, 0x1f, 0xc0, 0x2f, 0xd0, 0x3, 0xfd, 0x3, - 0xf8, 0x3, 0xf8, 0xb, 0xf8, 0x0, 0xf, 0xf4, - 0x1f, 0xc0, 0x7f, 0x42, 0xff, 0x0, 0x0, 0x7f, - 0xe0, 0xfe, 0xf, 0xf0, 0xff, 0xc0, 0x0, 0x1, - 0xff, 0xeb, 0xf5, 0xfe, 0xbf, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xe4, 0x0, 0x0, - 0x0, - - /* U+EAD6 "" */ - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, - 0x55, 0x55, 0x55, 0x55, 0x55, 0xbf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfd, 0x2f, 0xf4, 0xff, 0xcb, - 0x2, 0xc7, 0xff, 0xd3, 0xff, 0xcf, 0xfc, 0xb4, - 0x3c, 0x7f, 0xfd, 0x3c, 0x3c, 0xf0, 0x7, 0x83, - 0xc7, 0xff, 0xd3, 0xc3, 0xcf, 0x0, 0x3c, 0x78, - 0x7f, 0xfd, 0x3c, 0x3c, 0xfe, 0x3, 0xcb, 0x47, - 0xff, 0xd3, 0xc3, 0xcf, 0xe0, 0x2d, 0xf0, 0x7f, - 0xfd, 0x3c, 0x3c, 0xf0, 0x1, 0xff, 0x7, 0xff, - 0xd3, 0xc3, 0xcf, 0x0, 0xf, 0xd0, 0x7f, 0xfd, - 0x3f, 0xfc, 0xff, 0xc0, 0xfc, 0x7, 0xff, 0xd2, - 0xff, 0x4f, 0xfc, 0x7, 0x80, 0x7f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, - - /* U+EB8E "" */ - 0x6, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa4, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x1, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, 0x0, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x1f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, 0x0, - 0xbf, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xdf, 0xd0, - 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, - 0x0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0xf, 0xdf, - 0xd0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0xfd, - 0xfd, 0x0, 0xb, 0xfc, 0x0, 0x0, 0x0, 0xf, - 0xdf, 0xd0, 0x2, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0xfd, 0x0, 0xbf, 0xc0, 0x0, 0x0, 0x0, - 0xf, 0xdf, 0xd0, 0xf, 0xf0, 0x2, 0xff, 0xff, - 0x40, 0xfd, 0xfd, 0x0, 0xfc, 0x0, 0x3f, 0xff, - 0xf8, 0xf, 0xdf, 0xd0, 0x6, 0x0, 0x3, 0xff, - 0xff, 0x80, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x5, - 0x55, 0x40, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x15, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x0, - - /* U+EB97 "" */ - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xdf, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0xf0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0xf, 0x40, 0xf, 0xdf, 0xd0, 0x3f, 0xff, - 0xff, 0xf0, 0xff, 0x80, 0xfd, 0xfd, 0x3, 0xff, - 0xff, 0xff, 0xf, 0xf8, 0xf, 0xdf, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0xf4, 0x0, 0xfd, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0xf, 0x0, 0xf, 0xdf, 0xd0, - 0x1, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfd, - 0x0, 0x2f, 0x0, 0x0, 0x0, 0x0, 0xf, 0xdf, - 0xd0, 0x2f, 0xf0, 0xbf, 0xff, 0xfe, 0x0, 0xfd, - 0xfd, 0x3, 0xff, 0x2f, 0xff, 0xff, 0xf8, 0xf, - 0xdf, 0xd0, 0x3f, 0xf1, 0xff, 0xff, 0xff, 0x40, - 0xfd, 0xfd, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xdf, 0xd0, 0x2, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xdf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xdf, 0xe5, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0xfd, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EBCC "" */ - 0x0, 0x9, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, - 0x3, 0xf0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x17, - 0xf9, 0x55, 0x55, 0x56, 0xfd, 0x40, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xd0, 0x2d, 0x1, 0xf0, 0x7, 0x80, 0x7f, 0xfd, - 0x7, 0xf0, 0x2f, 0x80, 0xfd, 0x7, 0xff, 0xd0, - 0x3e, 0x1, 0xf4, 0xb, 0xc0, 0x7f, 0xfd, 0x0, - 0x40, 0x0, 0x0, 0x10, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x4, 0x0, - 0x0, 0x1, 0x0, 0x7f, 0xfd, 0x3, 0xe0, 0x1f, - 0x40, 0xbc, 0x7, 0xff, 0xd0, 0x7f, 0x2, 0xf8, - 0xf, 0xd0, 0x7f, 0xfd, 0x2, 0xd0, 0x1f, 0x0, - 0x78, 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5b, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd1, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, - - /* U+EC1C "" */ - 0x0, 0x0, 0x0, 0x0, 0x2, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xbf, 0x40, 0x0, 0x0, 0x0, 0xb, 0xfd, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf1, 0xff, 0xfe, - 0x94, 0x0, 0x0, 0xbf, 0xc3, 0xff, 0xff, 0xff, - 0xf4, 0x3, 0xff, 0x6, 0xff, 0xff, 0xff, 0xfc, - 0xf, 0xfc, 0x0, 0x0, 0x5a, 0xff, 0xf8, 0x2f, - 0xff, 0xa5, 0x0, 0x0, 0x3f, 0xf0, 0x3f, 0xff, - 0xff, 0xff, 0x80, 0xff, 0xc0, 0x1f, 0xff, 0xff, - 0xff, 0xc3, 0xfe, 0x0, 0x0, 0x16, 0xbf, 0xff, - 0x4f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3f, - 0xe0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, - - /* U+EF40 "" */ - 0x1, 0x40, 0x0, 0x14, 0x0, 0x1, 0x40, 0x0, - 0x7f, 0xd0, 0x7, 0xfd, 0x0, 0x7f, 0xd0, 0x3, - 0xff, 0xc0, 0x3f, 0xfc, 0x3, 0xff, 0xc0, 0xf, - 0xff, 0x40, 0xff, 0xf4, 0xf, 0xff, 0x40, 0x3f, - 0xfd, 0x3, 0xff, 0xd0, 0x3f, 0xfd, 0x0, 0xbf, - 0xf0, 0xb, 0xff, 0x0, 0xbf, 0xf0, 0x0, 0xbf, - 0x0, 0xb, 0xf0, 0x0, 0xbf, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, - 0x1, 0x40, 0x0, 0x0, 0x0, 0x7, 0xfd, 0x0, - 0x7f, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x3, - 0xff, 0xc0, 0x0, 0x1e, 0x0, 0xff, 0xf4, 0xf, - 0xff, 0x40, 0x2, 0xff, 0x3, 0xff, 0xd0, 0x3f, - 0xfd, 0x0, 0x2f, 0xff, 0xb, 0xff, 0x0, 0xbf, - 0xf0, 0x2, 0xff, 0xfe, 0xb, 0xf0, 0x0, 0xbf, - 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xdf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xfc, 0x1f, 0xe0, 0x1, 0x40, 0x0, 0x0, 0x2f, - 0xc0, 0xfe, 0x0, 0x7f, 0xd0, 0x0, 0x2, 0xfc, - 0xf, 0xe0, 0x3, 0xff, 0xc0, 0x0, 0xf, 0xc0, - 0xfe, 0x0, 0xf, 0xff, 0x40, 0x0, 0x3d, 0xf, - 0xe0, 0x0, 0x3f, 0xfd, 0x0, 0x0, 0xf9, 0xfe, - 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x3, 0xff, 0xe0, - 0x0, 0x0, 0xbf, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+EF4A "" */ - 0x0, 0x0, 0x0, 0x5, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0xb, 0xff, 0x90, 0x0, 0x6f, - 0xfe, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x3f, 0xe0, 0x0, 0x2f, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x40, 0x7, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xe0, 0x1f, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0x3, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x3f, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xc7, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xbf, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xdb, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xeb, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfe, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xeb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xc3, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xfc, 0x3f, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x82, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xf4, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x7f, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xd0, 0x3, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xf8, 0x0, 0xf, 0xf4, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x1, - 0xff, 0xe0, 0x0, 0x1, 0xbf, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xfa, 0xaa, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xe4, 0x0, 0x0, - 0x0, - - /* U+EF7A "" */ - 0x0, 0x1, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3f, - 0xf9, 0x5b, 0xff, 0x80, 0x0, 0x0, 0xf, 0xf8, - 0x0, 0x7, 0xfe, 0x0, 0x0, 0x2, 0xfe, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x3f, 0x80, 0x0, - 0x0, 0x3f, 0x80, 0x0, 0x7, 0xf0, 0x0, 0x0, - 0x2, 0xfc, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, - 0xf, 0xd0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, - 0xfd, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0xf, - 0xe0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfe, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0xf, 0xd0, - 0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0xfc, 0x0, - 0x0, 0x7f, 0x0, 0x0, 0x0, 0x2f, 0xc0, 0x0, - 0x3, 0xfc, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, - 0x2f, 0xe0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0xff, 0xd0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x3, - 0xff, 0xea, 0xbf, 0xff, 0x80, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xfe, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x1a, - 0xf9, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x10, - - /* U+EFE6 "" */ - 0x0, 0x2, 0xff, 0x40, 0x0, 0xb, 0xfe, 0x0, - 0x1, 0xff, 0xff, 0x0, 0x1, 0xff, 0xf4, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x1f, 0xff, 0x40, 0xf, - 0xf9, 0x7f, 0xe0, 0x2, 0xff, 0xf8, 0x1, 0xfe, - 0x0, 0xbf, 0x0, 0xff, 0xff, 0xf0, 0x2f, 0xc0, - 0x3, 0xf4, 0xf, 0xff, 0xff, 0x2, 0xf8, 0x0, - 0x3f, 0x40, 0xff, 0xff, 0xf0, 0x2f, 0x80, 0x3, - 0xf4, 0xf, 0xff, 0xff, 0x2, 0xf8, 0x0, 0x3f, - 0x40, 0xff, 0xff, 0xf0, 0x2f, 0x80, 0x3, 0xf4, - 0xf, 0xff, 0xff, 0x2, 0xf8, 0x0, 0x3f, 0x40, - 0xff, 0xff, 0xf0, 0x2f, 0x80, 0x3, 0xf4, 0x2, - 0xbf, 0xe8, 0x2, 0xf8, 0x0, 0x3f, 0x40, 0x2, - 0xf8, 0x0, 0x2f, 0x80, 0x3, 0xf4, 0x0, 0x2f, - 0x80, 0x2, 0xf8, 0x0, 0x3f, 0x40, 0x2, 0xf8, - 0x0, 0x2f, 0x80, 0x3, 0xf4, 0x0, 0x2f, 0x80, - 0x2, 0xf8, 0x0, 0x3f, 0x40, 0x2, 0xf8, 0x0, - 0x2f, 0x80, 0x3, 0xf4, 0x0, 0x2f, 0x80, 0x2b, - 0xfe, 0x80, 0x3f, 0x40, 0x2, 0xf8, 0xf, 0xff, - 0xff, 0x3, 0xf4, 0x0, 0x2f, 0x80, 0xff, 0xff, - 0xf0, 0x3f, 0x40, 0x2, 0xf8, 0xf, 0xff, 0xff, - 0x3, 0xf4, 0x0, 0x2f, 0x80, 0xff, 0xff, 0xf0, - 0x3f, 0x40, 0x2, 0xf8, 0xf, 0xff, 0xff, 0x3, - 0xf4, 0x0, 0x2f, 0x80, 0xff, 0xff, 0xf0, 0x3f, - 0x80, 0x3, 0xf8, 0xf, 0xff, 0xff, 0x2, 0xfd, - 0x0, 0xbf, 0x40, 0x2f, 0xff, 0x80, 0xf, 0xf9, - 0x7f, 0xf0, 0x1, 0xff, 0xf4, 0x0, 0x7f, 0xff, - 0xfc, 0x0, 0x1f, 0xff, 0x40, 0x1, 0xff, 0xff, - 0x0, 0x0, 0xbf, 0xe0, 0x0, 0x2, 0xff, 0x40, - 0x0, - - /* U+F028 "" */ - 0x0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x50, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xd7, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xd7, 0xf0, 0xa, 0x0, 0x24, 0x1, - 0x80, 0xa, 0x0, 0xfd, 0x7f, 0x2, 0xf8, 0xf, - 0xc0, 0x7f, 0x2, 0xf8, 0xf, 0xd7, 0xf0, 0x2f, - 0x80, 0xfc, 0x7, 0xf0, 0x2f, 0x80, 0xfd, 0x7f, - 0x0, 0xa0, 0x2, 0x40, 0x18, 0x0, 0xa0, 0xf, - 0xd7, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xd7, 0xf0, 0xa, 0x0, 0x78, - 0x2, 0xd0, 0xa, 0x0, 0xfd, 0x7f, 0x2, 0xf8, - 0xf, 0xc0, 0x7f, 0x2, 0xf8, 0xf, 0xd7, 0xf0, - 0x1f, 0x40, 0xfc, 0x3, 0xf0, 0x1f, 0x40, 0xfd, - 0x7f, 0x0, 0x50, 0x1, 0x0, 0x14, 0x0, 0x50, - 0xf, 0xd7, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xd7, 0xf0, 0x0, 0x3, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0xfd, 0x7f, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xe0, 0x0, 0xf, 0xd7, - 0xf0, 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0xfd, 0x7f, 0x0, 0x0, 0x5, 0x55, 0x55, 0x0, - 0x0, 0xf, 0xd7, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x0, - - /* U+F090 "" */ - 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x0, 0xfd, 0x1, 0x0, 0x0, 0x0, 0xb, 0xd0, - 0xfd, 0xb, 0xc0, 0x0, 0x0, 0xf, 0xf4, 0xfd, - 0x3f, 0xd0, 0x0, 0x0, 0x7, 0xfd, 0xfd, 0xff, - 0xc0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x0, - 0x7c, 0x0, 0x0, 0x78, 0x7f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x0, - - /* U+F15C "" */ - 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x90, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xfe, 0x40, 0x1f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0x40, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x7f, - 0xc0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, - 0x1, 0xfd, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x6f, - 0xc0, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, - 0x7f, 0xfc, 0x0, 0x0, 0x0, 0x3, 0xf4, 0x0, - 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x3f, - 0x40, 0x0, 0x7, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x3, 0xfd, 0x0, 0x0, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x2f, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x3, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0xff, 0xf0, - 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0x87, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xfc, 0x7f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xc3, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x3f, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xd2, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xfc, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xc0, 0xbf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xf4, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x40, 0x0, - - /* U+F720 "" */ - 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xe1, 0xff, 0xf4, 0x0, 0x0, 0x2, 0xff, - 0xf0, 0x1, 0xff, 0xf4, 0x0, 0x1, 0xff, 0xf4, - 0x0, 0x2, 0xff, 0xe0, 0x0, 0xff, 0xf8, 0x0, - 0x0, 0x3, 0xff, 0xe0, 0x7f, 0xf8, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xcf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xef, 0xff, 0xf4, 0x0, 0x0, 0x2, - 0xff, 0xfe, 0xfe, 0xff, 0xf0, 0x0, 0x2, 0xff, - 0xff, 0xef, 0xd2, 0xff, 0xe0, 0x1, 0xff, 0xf4, - 0xfe, 0xfd, 0x3, 0xff, 0xd0, 0xff, 0xf8, 0xf, - 0xef, 0xd0, 0x7, 0xff, 0xff, 0xf8, 0x0, 0xfe, - 0xfd, 0x0, 0xb, 0xff, 0xfd, 0x0, 0xf, 0xef, - 0xd0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0xfe, 0xfd, - 0x0, 0x0, 0x3f, 0x40, 0x0, 0xf, 0xef, 0xd0, - 0x0, 0x3, 0xf4, 0x0, 0x0, 0xfe, 0xfd, 0x0, - 0x0, 0x3f, 0x40, 0x0, 0xf, 0xef, 0xd0, 0x0, - 0x3, 0xf4, 0x0, 0x0, 0xfe, 0xfd, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0xf, 0xef, 0xd0, 0x0, 0x3, - 0xf4, 0x0, 0x0, 0xfe, 0xff, 0x80, 0x0, 0x3f, - 0x40, 0x0, 0x3f, 0xdb, 0xff, 0x40, 0x3, 0xf4, - 0x0, 0x2f, 0xfc, 0x2f, 0xff, 0x0, 0x3f, 0x40, - 0x1f, 0xff, 0x0, 0x3f, 0xfe, 0x3, 0xf4, 0xf, - 0xff, 0x80, 0x0, 0x7f, 0xfd, 0x3f, 0x4b, 0xff, - 0x80, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xe4, 0x0, 0x0, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x40, - 0x0, 0x0, 0x0, 0x0, 0xf4, 0x0, 0x3, 0xf4, - 0x0, 0x2, 0xd0, 0x0, 0x2f, 0xc0, 0x0, 0x3f, - 0x40, 0x0, 0x7f, 0x0, 0x7, 0xf8, 0x0, 0x3, - 0xf4, 0x0, 0x3, 0xfc, 0x0, 0xff, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0x2f, 0xd0, 0x1f, 0xd0, 0x0, - 0x3, 0xf4, 0x0, 0x0, 0xff, 0x3, 0xfc, 0x0, - 0x0, 0x3f, 0x40, 0x0, 0x7, 0xf0, 0x3f, 0x40, - 0x0, 0x3, 0xf4, 0x0, 0x0, 0x3f, 0x87, 0xf0, - 0x0, 0x0, 0x3f, 0x40, 0x0, 0x2, 0xfc, 0xbf, - 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0x1f, 0xcb, - 0xe0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0xfc, - 0xbe, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xf, - 0xcf, 0xe0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, - 0xfc, 0xbe, 0x0, 0x0, 0x1, 0xe0, 0x0, 0x0, - 0xf, 0xcb, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xfc, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xc3, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xf8, 0x3f, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x42, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xf0, 0xf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xfe, 0x0, 0x7f, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x3, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf4, 0x0, 0xf, 0xf4, - 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0, 0x1, - 0xff, 0xe0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, - 0x3, 0xff, 0xfa, 0xab, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xe4, 0x0, 0x0, - 0x0, - - /* U+FFF75 "󿽵" */ - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xdf, 0xd0, 0x3c, 0x0, 0xf, 0x0, - 0x7, 0x40, 0xfd, 0xfd, 0x3, 0xc0, 0x1, 0xf0, - 0x0, 0xb8, 0xf, 0xdf, 0xd0, 0x14, 0x0, 0x4, - 0x0, 0x1, 0x0, 0xfd, 0xfe, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x4f, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xf4, 0x0, 0x1f, 0xd0, 0x0, - 0x0, 0x7f, 0xff, 0xe0, 0x10, 0x0, 0xfd, 0x0, - 0x1, 0xbf, 0xff, 0x90, 0xb, 0x80, 0xf, 0xd0, - 0x1, 0xff, 0xff, 0x80, 0x0, 0xb4, 0x0, 0xfd, - 0x2, 0xff, 0xfe, 0x40, 0xe0, 0x0, 0x0, 0xbf, - 0xc1, 0xff, 0xfd, 0x0, 0x1f, 0x0, 0x1, 0xff, - 0xf8, 0x7f, 0xf8, 0x10, 0x0, 0x90, 0x7, 0xff, - 0xfe, 0xb, 0xf4, 0x7, 0xc0, 0x0, 0x1b, 0xff, - 0xfe, 0x0, 0xfe, 0x0, 0x78, 0x0, 0x2f, 0xff, - 0xf9, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x7f, 0xff, - 0xf4, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xe5, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0xfd, 0xfd, 0x1, 0x40, - 0x0, 0x40, 0x0, 0x10, 0xf, 0xdf, 0xd0, 0x3c, - 0x0, 0x1f, 0x0, 0xb, 0x80, 0xfd, 0xfd, 0x3, - 0xc0, 0x0, 0xf0, 0x0, 0x78, 0xf, 0xdf, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xbf, - 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5f, 0xd3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 640, .box_w = 24, .box_h = 24, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 144, .adv_w = 640, .box_w = 34, .box_h = 28, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 382, .adv_w = 640, .box_w = 21, .box_h = 32, .ofs_x = 8, .ofs_y = 4}, - {.bitmap_index = 550, .adv_w = 640, .box_w = 24, .box_h = 34, .ofs_x = 8, .ofs_y = 3}, - {.bitmap_index = 754, .adv_w = 640, .box_w = 36, .box_h = 38, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 1096, .adv_w = 640, .box_w = 34, .box_h = 28, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 1334, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 1623, .adv_w = 640, .box_w = 20, .box_h = 11, .ofs_x = 10, .ofs_y = 15}, - {.bitmap_index = 1678, .adv_w = 640, .box_w = 34, .box_h = 28, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 1916, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 2205, .adv_w = 640, .box_w = 30, .box_h = 30, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 2430, .adv_w = 640, .box_w = 20, .box_h = 30, .ofs_x = 10, .ofs_y = 5}, - {.bitmap_index = 2580, .adv_w = 640, .box_w = 28, .box_h = 30, .ofs_x = 6, .ofs_y = 5}, - {.bitmap_index = 2790, .adv_w = 640, .box_w = 28, .box_h = 28, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 2986, .adv_w = 640, .box_w = 22, .box_h = 22, .ofs_x = 9, .ofs_y = 9}, - {.bitmap_index = 3107, .adv_w = 640, .box_w = 30, .box_h = 20, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 3257, .adv_w = 640, .box_w = 8, .box_h = 28, .ofs_x = 16, .ofs_y = 6}, - {.bitmap_index = 3313, .adv_w = 640, .box_w = 28, .box_h = 28, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 3509, .adv_w = 640, .box_w = 38, .box_h = 29, .ofs_x = 1, .ofs_y = 5}, - {.bitmap_index = 3785, .adv_w = 640, .box_w = 26, .box_h = 20, .ofs_x = 7, .ofs_y = 10}, - {.bitmap_index = 3915, .adv_w = 640, .box_w = 31, .box_h = 28, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 4132, .adv_w = 640, .box_w = 30, .box_h = 28, .ofs_x = 5, .ofs_y = 6}, - {.bitmap_index = 4342, .adv_w = 640, .box_w = 28, .box_h = 34, .ofs_x = 6, .ofs_y = 3}, - {.bitmap_index = 4580, .adv_w = 640, .box_w = 34, .box_h = 32, .ofs_x = 3, .ofs_y = 5}, - {.bitmap_index = 4852, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 5141, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 5430, .adv_w = 640, .box_w = 26, .box_h = 34, .ofs_x = 7, .ofs_y = 3}, - {.bitmap_index = 5651, .adv_w = 640, .box_w = 28, .box_h = 30, .ofs_x = 6, .ofs_y = 5}, - {.bitmap_index = 5861, .adv_w = 640, .box_w = 34, .box_h = 28, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 6099, .adv_w = 640, .box_w = 40, .box_h = 39, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 6489, .adv_w = 640, .box_w = 30, .box_h = 30, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 6714, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 7003, .adv_w = 640, .box_w = 30, .box_h = 30, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 7228, .adv_w = 640, .box_w = 34, .box_h = 28, .ofs_x = 3, .ofs_y = 6}, - {.bitmap_index = 7466, .adv_w = 640, .box_w = 34, .box_h = 31, .ofs_x = 3, .ofs_y = 4}, - {.bitmap_index = 7730, .adv_w = 640, .box_w = 30, .box_h = 34, .ofs_x = 5, .ofs_y = 3}, - {.bitmap_index = 7985, .adv_w = 640, .box_w = 28, .box_h = 34, .ofs_x = 6, .ofs_y = 3}, - {.bitmap_index = 8223, .adv_w = 640, .box_w = 31, .box_h = 28, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 8440, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 8729, .adv_w = 640, .box_w = 30, .box_h = 30, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 8954, .adv_w = 640, .box_w = 30, .box_h = 30, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 9179, .adv_w = 640, .box_w = 38, .box_h = 28, .ofs_x = 1, .ofs_y = 6}, - {.bitmap_index = 9445, .adv_w = 640, .box_w = 28, .box_h = 28, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 9641, .adv_w = 640, .box_w = 38, .box_h = 28, .ofs_x = 1, .ofs_y = 6}, - {.bitmap_index = 9907, .adv_w = 640, .box_w = 30, .box_h = 34, .ofs_x = 5, .ofs_y = 3}, - {.bitmap_index = 10162, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 10451, .adv_w = 640, .box_w = 34, .box_h = 34, .ofs_x = 3, .ofs_y = 3} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_40 = { -#else -lv_font_t material_symbols_shared_40 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 39, /*The maximum line height required by the font*/ - .base_line = -1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_40*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_48.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_48.c deleted file mode 100644 index 2e187cea4..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_48.c +++ /dev/null @@ -1,2130 +0,0 @@ -/******************************************************************************* - * Size: 48 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 48 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_48.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_48 -#define MATERIAL_SYMBOLS_SHARED_48 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_48 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7d, 0x0, 0x0, 0x0, - - /* U+E159 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0x7f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xfd, 0xff, 0xff, 0xb, 0xff, 0x80, 0x0, 0x0, - 0x2, 0xff, 0xe0, 0xff, 0xff, 0x0, 0xff, 0xf4, - 0x0, 0x0, 0x1f, 0xff, 0x0, 0xff, 0xff, 0x0, - 0x1f, 0xff, 0x0, 0x0, 0xff, 0xf4, 0x0, 0xff, - 0xff, 0x0, 0x2, 0xff, 0xe0, 0xb, 0xff, 0x80, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x7f, 0xfd, 0x7f, - 0xfd, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xb, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x2, 0x80, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+E1A7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0x80, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xf8, 0x0, 0xbd, 0x0, 0x3, 0xff, - 0xff, 0x80, 0x3f, 0xd0, 0x0, 0xff, 0x3f, 0xf8, - 0xf, 0xfd, 0x0, 0x3f, 0xc3, 0xff, 0x81, 0xff, - 0xd0, 0xf, 0xf0, 0x3f, 0xf4, 0x1f, 0xfd, 0x3, - 0xfc, 0x7, 0xfe, 0x1, 0xff, 0xd0, 0xff, 0x7, - 0xff, 0x0, 0x1f, 0xfd, 0x3f, 0xc7, 0xff, 0x40, - 0x1, 0xff, 0xdf, 0xf7, 0xff, 0x40, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0x40, 0x0, 0x1, 0xff, 0xff, - 0xff, 0x40, 0x0, 0x0, 0x1f, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x1, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x7, 0xff, 0x7f, - 0xdf, 0xfd, 0x0, 0x7, 0xff, 0x4f, 0xf1, 0xff, - 0xd0, 0x7, 0xff, 0x43, 0xfc, 0x1f, 0xfc, 0x7, - 0xff, 0x40, 0xff, 0x1, 0xff, 0x87, 0xff, 0x40, - 0x3f, 0xc0, 0xff, 0xd3, 0xff, 0x40, 0xf, 0xf0, - 0xff, 0xd0, 0xff, 0x40, 0x3, 0xfc, 0xff, 0xd0, - 0x2f, 0x40, 0x0, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0xff, - 0x0, 0xff, 0xff, 0x3f, 0xfc, 0x0, 0xff, 0x0, - 0xff, 0xff, 0xbf, 0xfe, 0x0, 0xff, 0x0, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xbf, - 0xfe, 0x0, 0xff, 0x0, 0xff, 0xff, 0x3f, 0xfc, - 0x0, 0xff, 0x0, 0xff, 0xff, 0xf, 0xf0, 0x0, - 0xff, 0x0, 0xff, 0xff, 0xf, 0xf0, 0x0, 0xff, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0xff, 0x0, - 0xf, 0xf0, 0xf, 0xf0, 0x0, 0xff, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x3, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x82, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x40, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xc0, 0x7, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xd0, 0xb, 0xf4, - 0x7, 0xd0, 0x0, 0x7d, 0x0, 0x7, 0xd0, 0x1f, - 0xe0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0xff, 0x0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0x0, 0xff, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x1f, - 0xe0, 0xf, 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf0, - 0xb, 0xf4, 0x2f, 0xd0, 0xf, 0xf0, 0x0, 0xff, - 0x0, 0xf, 0xf0, 0x7, 0xf8, 0x3f, 0xc0, 0xf, - 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf0, 0x3, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+E2C7 "" */ - 0xb, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xff, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+E30F "" */ - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfc, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfd, 0x0, - 0x2f, 0xf4, 0x0, 0x7f, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0x80, 0x7, 0xd0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x7f, 0xf0, 0x0, 0xff, 0xff, 0x0, - 0x3, 0xff, 0x0, 0x0, 0xff, 0xc0, 0x0, 0xff, - 0xff, 0x0, 0x3, 0xff, 0x0, 0x0, 0xff, 0xc0, - 0x0, 0xff, 0xff, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x7f, 0xf0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x7, 0xd0, 0x2, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xfd, 0x0, 0x1f, 0xf8, - 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x3f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - - /* U+E316 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0x80, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x1f, 0xfc, 0x3f, - 0xf8, 0x0, 0x0, 0x7f, 0xf0, 0xf, 0xfe, 0x0, - 0x1, 0xff, 0xc0, 0x3, 0xff, 0x80, 0x7, 0xff, - 0x0, 0x0, 0xff, 0xe0, 0x1f, 0xfc, 0x0, 0x0, - 0x3f, 0xf4, 0x3f, 0xf0, 0x0, 0x0, 0xf, 0xfc, - 0x3f, 0xc0, 0x0, 0x0, 0x3, 0xfc, 0x1f, 0x0, - 0x0, 0x0, 0x0, 0xf4, - - /* U+E326 "" */ - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xf8, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xfe, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0xff, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x3, 0xc0, 0xff, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x7, 0xd0, 0xff, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3, - 0xc0, 0xff, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0xff, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0xf, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0xff, 0x0, 0x0, 0xff, 0xb, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x3, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0xbf, 0xff, 0xff, 0xfd, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0xbf, 0xff, 0xff, 0xfe, 0x7f, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x2f, 0xff, 0xff, 0xf8, - - /* U+E3AF "" */ - 0x0, 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xfe, 0x40, 0xf, 0xff, 0xff, - 0x80, 0x0, 0x0, 0xb, 0xff, 0xd0, 0x0, 0x2f, - 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2f, 0xfe, 0x0, - 0x0, 0x3c, 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xbf, - 0xf4, 0x0, 0x0, 0xb8, 0x0, 0xf, 0xfe, 0x0, - 0x1, 0xff, 0xc0, 0x0, 0x1, 0xf0, 0x0, 0x3, - 0xff, 0x40, 0x3, 0xff, 0xd0, 0x0, 0x3, 0xd0, - 0x0, 0x0, 0xff, 0xc0, 0xb, 0xfe, 0xf0, 0x0, - 0x7, 0xc0, 0x0, 0x0, 0x3f, 0xe0, 0xf, 0xf8, - 0xf4, 0x0, 0xf, 0x40, 0x0, 0x0, 0x1f, 0xf0, - 0x2f, 0xf0, 0x7c, 0x0, 0x2e, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3f, 0xd0, 0x2e, 0x0, 0x3f, 0x0, - 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xc0, 0xf, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0x80, - 0xb, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xbf, 0x40, 0x3, 0xd3, 0xff, 0xff, 0xe0, 0x0, - 0x1, 0xfe, 0xff, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xf8, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0x40, 0x0, 0xff, 0xbf, 0x40, - 0x0, 0xb, 0xff, 0xff, 0xc7, 0xc0, 0x1, 0xfe, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x43, 0xe0, - 0x2, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xf0, 0x3, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x0, 0xfc, 0x0, 0xb8, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0x0, 0xf8, 0x0, 0x3d, 0xf, 0xf8, - 0xf, 0xf4, 0x0, 0x0, 0x1, 0xf0, 0x0, 0x1f, - 0x2f, 0xf0, 0xb, 0xfc, 0x0, 0x0, 0x3, 0xd0, - 0x0, 0xf, 0xbf, 0xe0, 0x3, 0xff, 0x0, 0x0, - 0x7, 0xc0, 0x0, 0x7, 0xff, 0xc0, 0x1, 0xff, - 0xc0, 0x0, 0xf, 0x40, 0x0, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x0, 0x2e, 0x0, 0x0, 0x1f, - 0xfe, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0x3c, 0x0, - 0x0, 0xbf, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xd0, - 0xf8, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2, - 0xff, 0xfe, 0xf0, 0x1, 0xbf, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x0, - - /* U+E3F4 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x4, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x2e, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0x40, 0x0, 0xff, 0xff, 0x0, 0x3, - 0xc0, 0x0, 0xff, 0xc0, 0x0, 0xff, 0xff, 0x0, - 0xf, 0xf0, 0x3, 0xff, 0xf0, 0x0, 0xff, 0xff, - 0x0, 0x2f, 0xf8, 0xb, 0xff, 0xf8, 0x0, 0xff, - 0xff, 0x0, 0x7f, 0xfd, 0x1f, 0xff, 0xfd, 0x0, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x7f, 0xff, 0xff, - 0x0, 0xff, 0xff, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0xff, 0xff, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, - - /* U+E405 "" */ - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0xff, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xf8, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - - /* U+E55D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xfe, 0xbf, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xfc, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf4, 0x1f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xf0, 0xf, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xd0, 0x7, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xc0, 0x3, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x80, 0x2, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x2, 0xfe, 0x0, 0x0, 0xbf, 0x80, 0x0, - 0x0, 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0xb, 0xfc, 0x0, 0x0, 0x3f, 0xe0, 0x0, - 0x0, 0xf, 0xf4, 0x0, 0x0, 0x1f, 0xf0, 0x0, - 0x0, 0x1f, 0xf0, 0x0, 0x0, 0xf, 0xf4, 0x0, - 0x0, 0x3f, 0xd0, 0x0, 0x0, 0x7, 0xfc, 0x0, - 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x3, 0xfd, 0x0, - 0x0, 0xff, 0x80, 0x0, 0x0, 0x2, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x2, 0xfe, 0x0, 0x1f, 0xf4, 0x0, 0xbf, 0x80, - 0x3, 0xfc, 0x1, 0xff, 0xff, 0x40, 0x3f, 0xc0, - 0xb, 0xfc, 0x2f, 0xff, 0xff, 0xf8, 0x3f, 0xe0, - 0xf, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf0, - 0x1f, 0xff, 0xff, 0xf8, 0x2f, 0xff, 0xff, 0xf4, - 0x3f, 0xff, 0xff, 0x40, 0x1, 0xff, 0xff, 0xfc, - 0x7f, 0xff, 0xf4, 0x0, 0x0, 0x1f, 0xff, 0xfd, - 0xbf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, - 0x7f, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfd, - 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, - - /* U+E5C3 "" */ - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, - 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - - /* U+E5CD "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0x40, 0x0, 0x0, 0x0, 0x1, 0xf8, 0x3f, 0xd0, - 0x0, 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0x1f, 0xfc, 0x1f, 0xfd, 0x0, 0x0, - 0x0, 0x7f, 0xf4, 0x7, 0xff, 0x40, 0x0, 0x1, - 0xff, 0xd0, 0x1, 0xff, 0xd0, 0x0, 0x7, 0xff, - 0x40, 0x0, 0x7f, 0xf4, 0x0, 0x1f, 0xfd, 0x0, - 0x0, 0x1f, 0xfd, 0x0, 0x7f, 0xf4, 0x0, 0x0, - 0x7, 0xff, 0x41, 0xff, 0xd0, 0x0, 0x0, 0x1, - 0xff, 0xd7, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xd7, 0xff, 0x40, 0x0, 0x0, 0x7, - 0xff, 0x41, 0xff, 0xd0, 0x0, 0x0, 0x1f, 0xfd, - 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x7f, 0xf4, 0x0, - 0x1f, 0xfd, 0x0, 0x1, 0xff, 0xd0, 0x0, 0x7, - 0xff, 0x40, 0x7, 0xff, 0x40, 0x0, 0x1, 0xff, - 0xd0, 0x1f, 0xfd, 0x0, 0x0, 0x0, 0x7f, 0xf4, - 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x3f, - 0xd0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0x40, - 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E5D2 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 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, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 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, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+E5D4 "" */ - 0xb, 0xe0, 0x3f, 0xfc, 0xbf, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x3f, 0xfc, 0xb, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x3f, 0xfc, 0xbf, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x3f, 0xfc, 0xb, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x3f, 0xfc, 0xbf, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x3f, 0xfc, 0xb, 0xe0, - - /* U+E5D5 "" */ - 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x7d, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf8, 0x0, 0xff, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, - 0x0, 0x3f, 0xff, 0x90, 0x6, 0xff, 0xfc, 0xff, - 0x0, 0xff, 0xf4, 0x0, 0x0, 0x1f, 0xff, 0xff, - 0x3, 0xff, 0x80, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0x2f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x3f, 0xd0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, - 0x7f, 0xc0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xbf, 0x80, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0x40, 0x0, 0x0, 0x7, 0xff, 0xff, 0xfd, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, - 0x3f, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, - 0x2f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf4, - 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf0, - 0xb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xe0, - 0x3, 0xff, 0x80, 0x0, 0x0, 0x2, 0xff, 0xc0, - 0x0, 0xff, 0xf4, 0x0, 0x0, 0x1f, 0xff, 0x0, - 0x0, 0x3f, 0xff, 0x90, 0x6, 0xff, 0xfc, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, - - /* U+E63E "" */ - 0x0, 0x0, 0x0, 0x0, 0x6b, 0xff, 0xfe, 0x90, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, - 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xe4, 0x0, 0x1, 0xbf, 0xff, 0xff, 0xfc, - 0x1, 0xff, 0xff, 0xfe, 0x40, 0x0, 0x0, 0x0, - 0x1b, 0xff, 0xff, 0xf4, 0x3f, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xcb, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xfe, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xe7, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xfd, 0x1f, 0x80, 0x0, 0x0, 0x1a, 0xff, - 0xfa, 0x40, 0x0, 0x0, 0x2f, 0x40, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xf9, 0x0, 0x6, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xf4, 0x0, - 0x0, 0x1, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xf4, 0x0, 0x0, 0x0, 0x1, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 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, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, - 0x4, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, - 0x3f, 0x40, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, - 0x7f, 0xd0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, - 0x3f, 0xf4, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, - 0x1f, 0xfd, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, - 0x7, 0xff, 0x40, 0xf, 0xfe, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xd0, 0x3f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf4, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E745 "" */ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 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, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, - 0x7f, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x2, 0xff, - 0xfc, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0xb, - 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xf9, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xe0, 0x7f, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0x80, 0xbf, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xfe, 0x2, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xf8, 0xb, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, - 0x2f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xc0, 0xbf, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xc2, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0x80, 0x0, 0x0, - - /* U+E770 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xf5, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xe0, 0x3f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xc0, 0xb, 0xff, 0xff, 0xe0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x2, 0xff, 0xff, - 0xfc, 0x7d, 0x0, 0x7, 0xfd, 0x0, 0x0, 0x7f, - 0xff, 0xfe, 0xff, 0x80, 0xf, 0xf8, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xfd, 0xbf, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x7f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xf, 0xf4, 0x0, 0x18, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x2, 0xe0, 0x0, 0x3f, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x40, 0x0, 0xff, 0xd0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x7, - 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xc0, 0x0, 0xff, 0xff, 0x40, - 0x0, 0x2f, 0xff, 0xff, 0xf4, 0x0, 0xff, 0xff, - 0xe0, 0x0, 0x7f, 0xff, 0xff, 0xfe, 0x0, 0xff, - 0xff, 0xfc, 0x0, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0xff, 0xff, 0xff, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, - - /* U+E89C "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0x80, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xe0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xf8, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, 0x0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x80, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xe0, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf4, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xfd, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+E8AF "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0xf, 0xfc, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0xf, 0xfe, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0xf, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xf, 0xff, 0xff, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x0, 0xf, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0x7d, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x40, 0x2f, - 0xe0, 0xb, 0xf8, 0x1, 0xb4, 0x0, 0x0, 0xff, - 0xf9, 0xff, 0xe0, 0xb, 0xff, 0x6f, 0xff, 0x0, - 0x2, 0xff, 0xff, 0xff, 0xd0, 0x7, 0xff, 0xff, - 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0x80, 0x2, - 0xff, 0xff, 0xff, 0xc0, 0xb, 0xfd, 0xff, 0xf4, - 0x0, 0x0, 0x1f, 0xff, 0x7f, 0xe0, 0xf, 0xf4, - 0x1b, 0xc0, 0x0, 0x0, 0x3, 0xe4, 0x1f, 0xf0, - 0x2f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3f, 0xd0, 0x0, 0x0, 0x2f, 0xf8, - 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xf4, 0x0, 0x1, - 0xff, 0xff, 0x40, 0x0, 0x1f, 0xfc, 0x2f, 0xfe, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0xbf, 0xf8, - 0xb, 0xff, 0xc0, 0xf, 0xff, 0xff, 0xf0, 0x3, - 0xff, 0xe0, 0x1, 0xff, 0xd0, 0x1f, 0xff, 0xff, - 0xf8, 0x7, 0xff, 0x40, 0x0, 0x7f, 0xc0, 0x2f, - 0xff, 0xff, 0xfc, 0x3, 0xfd, 0x0, 0x0, 0x3f, - 0xc0, 0x3f, 0xff, 0xff, 0xfc, 0x3, 0xfc, 0x0, - 0x0, 0x3f, 0xc0, 0x3f, 0xff, 0xff, 0xfc, 0x3, - 0xfc, 0x0, 0x0, 0x7f, 0xc0, 0x2f, 0xff, 0xff, - 0xfc, 0x3, 0xfc, 0x0, 0x1, 0xff, 0xd0, 0x1f, - 0xff, 0xff, 0xf8, 0x7, 0xff, 0x40, 0xb, 0xff, - 0xc0, 0xf, 0xff, 0xff, 0xf0, 0x3, 0xff, 0xe0, - 0x2f, 0xfe, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0xbf, 0xf4, 0x3f, 0xf4, 0x0, 0x1, 0xff, 0xff, - 0x40, 0x0, 0x1f, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, - 0xf, 0xf4, 0x1b, 0xc0, 0x0, 0x0, 0x3, 0xe4, - 0x1f, 0xf0, 0xb, 0xfd, 0xff, 0xf4, 0x0, 0x0, - 0x1f, 0xff, 0x7f, 0xe0, 0x3, 0xff, 0xff, 0xff, - 0x80, 0x2, 0xff, 0xff, 0xff, 0xc0, 0x2, 0xff, - 0xff, 0xff, 0xd0, 0x7, 0xff, 0xff, 0xff, 0x40, - 0x0, 0xff, 0xf9, 0xff, 0xe0, 0xb, 0xff, 0x6f, - 0xfe, 0x0, 0x0, 0x2e, 0x40, 0x2f, 0xe0, 0xb, - 0xf8, 0x1, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - - /* U+E8FD "" */ - 0x0, 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xfe, 0x40, 0x1, 0xbf, 0xff, - 0x80, 0x0, 0x0, 0xb, 0xff, 0xd0, 0x0, 0x0, - 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xbf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x1, 0xff, 0xc0, 0x0, 0x2f, 0xf9, 0x0, 0x3, - 0xff, 0x40, 0x3, 0xff, 0x0, 0x1, 0xff, 0xff, - 0x80, 0x0, 0xff, 0xc0, 0xb, 0xfc, 0x0, 0x7, - 0xff, 0xff, 0xf0, 0x0, 0x3f, 0xe0, 0xf, 0xf4, - 0x0, 0xf, 0xfd, 0x6f, 0xf8, 0x0, 0x1f, 0xf0, - 0x2f, 0xf0, 0x0, 0xf, 0xe0, 0x7, 0xfc, 0x0, - 0xf, 0xf8, 0x3f, 0xd0, 0x0, 0xb, 0x40, 0x3, - 0xfc, 0x0, 0x7, 0xfc, 0x3f, 0xc0, 0x0, 0x0, - 0x0, 0x3, 0xfc, 0x0, 0x3, 0xfc, 0x7f, 0x80, - 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x2, 0xfd, - 0xbf, 0x40, 0x0, 0x0, 0x0, 0xb, 0xf4, 0x0, - 0x1, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xe0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xc0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0xb, 0xf4, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xbf, 0x40, - 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0x1, 0xfe, - 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xfd, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0xb, 0xd0, 0x0, 0x0, 0xf, 0xf8, - 0xf, 0xf4, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, - 0x1f, 0xf0, 0xb, 0xfc, 0x0, 0x0, 0x2f, 0xf4, - 0x0, 0x0, 0x3f, 0xe0, 0x3, 0xff, 0x0, 0x0, - 0x1f, 0xf0, 0x0, 0x0, 0xff, 0xc0, 0x1, 0xff, - 0xc0, 0x0, 0xb, 0xd0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xd0, - 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2, - 0xff, 0xfe, 0x40, 0x1, 0xbf, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x0, - - /* U+E90F "" */ - 0x0, 0x0, 0x6, 0xff, 0xf9, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0xbf, - 0xfe, 0x40, 0x1b, 0xff, 0xe0, 0x0, 0x2f, 0xfd, - 0x0, 0x0, 0x7, 0xff, 0x80, 0x7, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x0, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x3f, 0xf0, 0x2f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x83, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xfc, 0x7f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xdb, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xfe, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xbf, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xe7, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xfd, 0x3f, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc1, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf4, 0xf, 0xfc, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xf8, 0x0, 0x0, 0x0, - - /* U+E92E "" */ - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x7, 0xd0, 0x7, 0xd0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, - 0xf, 0xf0, 0x7, 0xd0, 0x7, 0xd0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - - /* U+E9B9 "" */ - 0xb, 0xe0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xfc, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xfe, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xfc, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xe0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xfc, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xfe, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xfc, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xe0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xe0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xfc, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xfe, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xfc, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xe0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+E9F4 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x3f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0xb, 0xd0, 0x0, 0x0, 0x1, 0xff, 0x40, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0xb, 0xd0, 0x0, - 0x0, 0xf, 0xff, 0xf0, 0x3f, 0xff, 0xfc, 0x0, - 0x0, 0xb, 0xd0, 0x0, 0x0, 0x3f, 0xff, 0xfc, - 0x7f, 0xff, 0xfd, 0x0, 0x0, 0x6f, 0xf8, 0x0, - 0x0, 0x7f, 0xff, 0xfd, 0xff, 0x82, 0xff, 0x0, - 0x3, 0xff, 0xff, 0x80, 0x0, 0xff, 0x82, 0xff, - 0xff, 0x0, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x40, - 0x3f, 0xff, 0xff, 0xfc, 0x1, 0xff, 0x0, 0xff, - 0xff, 0x82, 0xff, 0xf9, 0xbf, 0xe0, 0x1b, 0xfe, - 0x6f, 0xff, 0x82, 0xff, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0x40, 0x2, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x3f, 0xff, 0xfd, 0xbf, 0xfe, 0x0, 0x0, 0xbf, - 0xfe, 0x7f, 0xff, 0xfc, 0xf, 0xff, 0xf0, 0x7, - 0xfc, 0x0, 0x0, 0x7f, 0xd0, 0xf, 0xff, 0xf0, - 0x1, 0xff, 0x40, 0x3, 0xfc, 0x0, 0x0, 0x3f, - 0xc0, 0x1, 0xff, 0x40, 0x0, 0x0, 0x0, 0x3, - 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x7f, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xfe, 0x0, 0x0, 0xbf, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x40, 0x2, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xe0, 0x1b, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xfc, 0x6f, 0xf8, 0x3f, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfb, 0xf4, 0x0, 0x0, 0x1f, - 0xef, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0xb, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0xf, 0xf8, 0x2f, 0xf0, 0x0, 0x0, 0xf, - 0xf8, 0x2f, 0xf0, 0x0, 0x0, 0xf, 0xf0, 0xf, - 0xf0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, - 0x0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0xf, - 0xf0, 0xf, 0xf0, 0x0, 0x0, 0xf, 0xf8, 0x2f, - 0xf0, 0x0, 0x0, 0xf, 0xf8, 0x2f, 0xf0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, - - /* U+E9F7 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, - - /* U+EA07 "" */ - 0x0, 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, - 0x80, 0x0, 0x0, 0xb, 0xff, 0xdb, 0xfc, 0x3f, - 0xe7, 0xff, 0xe0, 0x0, 0x0, 0x2f, 0xfd, 0xf, - 0xf4, 0x1f, 0xf0, 0x7f, 0xf8, 0x0, 0x0, 0xbf, - 0xf0, 0x1f, 0xf0, 0xf, 0xf4, 0xf, 0xfe, 0x0, - 0x1, 0xff, 0xc0, 0x3f, 0xd0, 0x7, 0xfc, 0x3, - 0xff, 0x40, 0x3, 0xff, 0x0, 0x3f, 0xc0, 0x3, - 0xfc, 0x0, 0xff, 0xc0, 0xb, 0xfd, 0x0, 0x7f, - 0x80, 0x2, 0xfd, 0x0, 0x7f, 0xe0, 0xf, 0xf8, - 0x0, 0xff, 0x40, 0x1, 0xff, 0x0, 0x2f, 0xf0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xbf, 0x40, 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, - 0x1, 0xfe, 0xff, 0x0, 0x3, 0xfc, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0xff, 0xff, 0x0, 0x3, 0xfc, - 0x0, 0x0, 0x3f, 0xc0, 0x0, 0xff, 0xff, 0x0, - 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0xff, - 0xff, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, - 0x0, 0xff, 0xff, 0x0, 0x3, 0xfc, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0xff, 0xff, 0x0, 0x3, 0xfc, - 0x0, 0x0, 0x3f, 0xc0, 0x0, 0xff, 0xbf, 0x40, - 0x3, 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x1, 0xfe, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xf, 0xf8, 0x0, 0xff, 0x40, 0x1, 0xfe, 0x0, - 0x2f, 0xf0, 0xb, 0xfd, 0x0, 0x7f, 0x80, 0x2, - 0xfd, 0x0, 0x7f, 0xe0, 0x3, 0xff, 0x0, 0x3f, - 0xc0, 0x3, 0xfc, 0x0, 0xff, 0xc0, 0x1, 0xff, - 0xc0, 0x3f, 0xd0, 0x7, 0xfc, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x1f, 0xf0, 0xf, 0xf4, 0xf, - 0xfe, 0x0, 0x0, 0x2f, 0xfd, 0xf, 0xf4, 0x1f, - 0xf0, 0x7f, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xdb, - 0xfc, 0x3f, 0xe7, 0xff, 0xe0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x0, - - /* U+EAD6 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xb, 0xff, 0x7, - 0xff, 0x4f, 0x0, 0xb0, 0xff, 0xff, 0xf, 0xff, - 0xcb, 0xff, 0x8f, 0x40, 0xf0, 0xff, 0xff, 0xf, - 0x97, 0xcf, 0xd5, 0xf, 0x81, 0xf0, 0xff, 0xff, - 0xf, 0x43, 0xcf, 0x80, 0xb, 0xc2, 0xe0, 0xff, - 0xff, 0xf, 0x43, 0xcf, 0x80, 0x7, 0xc3, 0xd0, - 0xff, 0xff, 0xf, 0x43, 0xcf, 0xfc, 0x3, 0xd3, - 0xc0, 0xff, 0xff, 0xf, 0x43, 0xcf, 0xfc, 0x3, - 0xe7, 0xc0, 0xff, 0xff, 0xf, 0x43, 0xcf, 0x80, - 0x1, 0xfb, 0x80, 0xff, 0xff, 0xf, 0x43, 0xcf, - 0x80, 0x0, 0xff, 0x40, 0xff, 0xff, 0xf, 0x83, - 0xcf, 0x80, 0x0, 0xff, 0x0, 0xff, 0xff, 0xf, - 0xff, 0xcb, 0xff, 0x80, 0xbf, 0x0, 0xff, 0xff, - 0xb, 0xff, 0x7, 0xff, 0x40, 0x3c, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xb, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, - - /* U+EB8E "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x1f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x3f, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x3, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x3f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x3f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x3f, 0xf4, - 0x0, 0x7f, 0xff, 0xfd, 0x0, 0xff, 0xff, 0x0, - 0x3f, 0xd0, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0x0, 0x1f, 0x40, 0x0, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xfd, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+EB97 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x80, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0xff, 0xff, 0x0, 0x15, 0x55, - 0x55, 0x54, 0xf, 0xd4, 0x0, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, - 0x0, 0xff, 0xff, 0x0, 0x15, 0x55, 0x55, 0x54, - 0xf, 0xd4, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xc0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0x80, 0x0, 0xff, - 0xff, 0x0, 0x2, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x3, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x17, 0xf0, - 0x15, 0x55, 0x55, 0x54, 0x0, 0xff, 0xff, 0x0, - 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0x0, 0x17, 0xf0, 0x15, 0x55, - 0x55, 0x54, 0x0, 0xff, 0xff, 0x0, 0x3, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x2, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - - /* U+EBCC "" */ - 0x0, 0x7, 0xd0, 0x0, 0x0, 0x0, 0x7, 0xd0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x7d, 0x0, - 0x7d, 0x0, 0x7d, 0x0, 0xff, 0xff, 0x0, 0xff, - 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, - 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, - 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x7d, 0x0, - 0x7d, 0x0, 0x7d, 0x0, 0xff, 0xff, 0x0, 0xff, - 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, - 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, - 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+EC1C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xef, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x9f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfe, 0x3f, 0xff, 0xa5, 0x0, 0x0, - 0x0, 0x7f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xa4, - 0x1, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x7, 0xff, 0x80, 0x5a, 0xff, 0xff, 0xff, 0xfe, - 0x1f, 0xfd, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xfd, - 0x7f, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x7f, 0xf4, - 0xbf, 0xff, 0xff, 0xff, 0xa5, 0x1, 0xff, 0xd0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xb, 0xff, 0x40, - 0x1a, 0xff, 0xff, 0xff, 0xfd, 0x2f, 0xfd, 0x0, - 0x0, 0x0, 0x5a, 0xff, 0xfc, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xf6, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xeb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EF40 "" */ - 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0x3f, - 0xfc, 0x0, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, - 0xbf, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, - 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, - 0xff, 0x0, 0xff, 0xff, 0x0, 0xbf, 0xfe, 0x0, - 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0x3f, 0xfc, - 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, 0xb, - 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xb, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0xb, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x1f, 0x80, 0xff, - 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xbf, 0xf0, - 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x2, 0xff, - 0xfc, 0xbf, 0xfe, 0x0, 0xbf, 0xfe, 0x0, 0xb, - 0xff, 0xfe, 0x3f, 0xfc, 0x0, 0x3f, 0xfc, 0x0, - 0x2f, 0xff, 0xff, 0xb, 0xe0, 0x0, 0xb, 0xe0, - 0x0, 0xbf, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xf9, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xe0, 0x7f, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0x80, 0xbf, 0x80, - 0xb, 0xe0, 0x0, 0x0, 0x2, 0xfe, 0x2, 0xfe, - 0x0, 0x3f, 0xfc, 0x0, 0x0, 0xb, 0xf8, 0xb, - 0xf8, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0xf, 0xe0, - 0x2f, 0xe0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xf, - 0xc0, 0xbf, 0x80, 0x0, 0xff, 0xff, 0x0, 0x0, - 0xf, 0xc2, 0xfe, 0x0, 0x0, 0xbf, 0xfe, 0x0, - 0x0, 0xf, 0xff, 0xf8, 0x0, 0x0, 0x3f, 0xfc, - 0x0, 0x0, 0xf, 0xff, 0xe0, 0x0, 0x0, 0xb, - 0xe0, 0x0, 0x0, 0x7, 0xff, 0x80, 0x0, 0x0, - - /* U+EF4A "" */ - 0x0, 0x0, 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xfe, 0x40, 0x1, 0xbf, 0xff, - 0x80, 0x0, 0x0, 0xb, 0xff, 0xd0, 0x0, 0x0, - 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xbf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xc0, 0xb, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0xf, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, - 0x2f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf8, 0x3f, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7f, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, - 0xbf, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xbf, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, - 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xfd, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, - 0xf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xf0, 0xb, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xe0, 0x3, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x1, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xd0, - 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2, - 0xff, 0xfe, 0x40, 0x1, 0xbf, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x0, - - /* U+EF7A "" */ - 0x0, 0x0, 0x2f, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xe4, 0x1, - 0xbf, 0xfc, 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xf8, - 0x0, 0x0, 0x2, 0xff, 0x40, 0x0, 0x0, 0x3f, - 0xf0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0xbf, 0x80, 0x0, 0x0, 0x0, 0x2f, 0xe0, - 0x0, 0x0, 0xff, 0x40, 0x0, 0x0, 0x0, 0x1f, - 0xf0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, - 0xbf, 0x80, 0x0, 0x0, 0x0, 0x2f, 0xd0, 0x0, - 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x3f, 0xc0, - 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0xff, - 0x80, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x2, - 0xff, 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, - 0xf, 0xfe, 0x0, 0x0, 0x0, 0x3, 0xff, 0xe4, - 0x1, 0xbf, 0xff, 0x40, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xbf, 0xf4, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xf8, 0x1f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xfe, 0x40, 0x7, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+EFE6 "" */ - 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x7, 0xff, - 0xd0, 0x0, 0x2, 0xff, 0xff, 0x80, 0x0, 0xf, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xff, 0xe0, 0x0, - 0xf, 0xff, 0xf0, 0x0, 0x2f, 0xff, 0xff, 0xf8, - 0x0, 0xf, 0xff, 0xf0, 0x0, 0x3f, 0xf4, 0x1f, - 0xfc, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0xbf, 0xc0, - 0x3, 0xfe, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, - 0x40, 0x1, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, - 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, - 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, - 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, - 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, - 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, - 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, - 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0xff, - 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, - 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, - 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, - 0xff, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, - 0x0, 0xff, 0x40, 0x1, 0xff, 0x0, 0xff, 0xff, - 0xff, 0x0, 0xbf, 0xc0, 0x3, 0xfe, 0x0, 0x2f, - 0xff, 0xf8, 0x0, 0x3f, 0xf4, 0x1f, 0xfc, 0x0, - 0xf, 0xff, 0xf0, 0x0, 0x2f, 0xff, 0xff, 0xf8, - 0x0, 0xf, 0xff, 0xf0, 0x0, 0xb, 0xff, 0xff, - 0xe0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x2, 0xff, - 0xff, 0x80, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, - - /* U+F028 "" */ - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, - 0x7d, 0x0, 0xff, 0xff, 0x0, 0xff, 0x0, 0xff, - 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, - 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, - 0xff, 0xff, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, - 0x0, 0x7d, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x7d, - 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0xff, - 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, - 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x0, 0xff, - 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, - 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, 0x7d, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+F090 "" */ - 0x0, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xf0, 0xf, 0xf0, 0xf, 0x40, 0x0, - 0x0, 0x3, 0xfc, 0xf, 0xf0, 0x3f, 0xc0, 0x0, - 0x0, 0x3, 0xff, 0xf, 0xf0, 0xff, 0xc0, 0x0, - 0x0, 0x1, 0xff, 0xcf, 0xf3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xf4, 0x0, 0x0, 0x0, - 0x7d, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0x7d, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - - /* U+F15C "" */ - 0x0, 0x0, 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xf9, 0x0, 0x6f, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x80, 0x0, 0x2, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0xb, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0x0, 0x3, 0xfd, 0x0, 0x0, 0x0, 0x1, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x2, 0xfe, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x1, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x3, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe4, 0x0, 0x1f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xd0, 0x7f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0xbf, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xfc, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xfd, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfe, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xbf, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0x3f, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xfe, 0x2f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xfd, 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xfc, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x1, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x0, - - /* U+F720 "" */ - 0x0, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xd7, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xfd, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0, 0x1f, - 0xff, 0xe0, 0x0, 0xb, 0xff, 0xf4, 0x0, 0x1, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0x40, - 0xb, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xe0, 0x3f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xfc, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfe, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x7f, - 0xff, 0x40, 0x0, 0x1, 0xff, 0xfd, 0xff, 0xff, - 0xb, 0xff, 0xf4, 0x0, 0x1f, 0xff, 0xe0, 0xff, - 0xff, 0x0, 0xff, 0xfe, 0x0, 0xbf, 0xff, 0x0, - 0xff, 0xff, 0x0, 0x1f, 0xff, 0xeb, 0xff, 0xf4, - 0x0, 0xff, 0xff, 0x0, 0x2, 0xff, 0xff, 0xff, - 0x80, 0x0, 0xff, 0xff, 0x0, 0x0, 0x2f, 0xff, - 0xf8, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0xff, 0x0, 0x0, 0x3, 0xff, 0xbf, 0xf8, 0x0, - 0x0, 0xff, 0x0, 0x0, 0x2f, 0xfe, 0x3f, 0xff, - 0x40, 0x0, 0xff, 0x0, 0x1, 0xff, 0xfc, 0xb, - 0xff, 0xf4, 0x0, 0xff, 0x0, 0x1f, 0xff, 0xe0, - 0x1, 0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, - 0x40, 0x0, 0x1f, 0xff, 0xe0, 0xff, 0xb, 0xff, - 0xf4, 0x0, 0x0, 0x2, 0xff, 0xfd, 0xff, 0x7f, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x14, 0x0, 0x0, 0xbe, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xbe, 0x0, - 0x1, 0xff, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0xff, 0x40, 0x3, 0xff, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0xff, 0xc0, 0xb, 0xfc, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x3f, 0xe0, 0xf, 0xf4, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x1f, 0xf0, - 0x2f, 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0xf, 0xf4, 0x3f, 0xd0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x7, 0xfc, 0x3f, 0xc0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x3, 0xfc, 0x7f, 0x80, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x2, 0xfd, - 0xbf, 0x40, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x1, 0xfe, 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x7, 0xd0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xbf, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, - 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xfd, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x2f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, - 0xf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xf0, 0xb, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xe0, 0x3, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x1, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xd0, - 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x2, - 0xff, 0xfe, 0x40, 0x1, 0xbf, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xfe, 0x40, 0x0, 0x0, 0x0, - - /* U+FFF75 "󿽵" */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0xfc, 0x0, - 0x7, 0xc0, 0x0, 0x3e, 0x0, 0xff, 0xff, 0x0, - 0xfc, 0x0, 0xb, 0xc0, 0x0, 0x3f, 0x0, 0xff, - 0xff, 0x0, 0x64, 0x0, 0x2, 0x40, 0x0, 0x18, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xff, 0xf8, 0x0, 0x2, 0xff, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfe, 0x40, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xe0, 0x7, 0xc0, - 0x0, 0xff, 0x0, 0x1, 0xbf, 0xff, 0xf9, 0x0, - 0xb, 0xc0, 0x0, 0xff, 0x0, 0x1f, 0xff, 0xff, - 0x40, 0x0, 0x7, 0xc0, 0x2, 0xff, 0x2, 0xff, - 0xff, 0xe4, 0x7, 0xc0, 0x0, 0x0, 0x1f, 0xfe, - 0x1f, 0xff, 0xfd, 0x0, 0xb, 0xc0, 0x0, 0x7, - 0xff, 0xfc, 0x3f, 0xff, 0x80, 0x0, 0x7, 0xc0, - 0x1, 0xbf, 0xff, 0xf0, 0xbf, 0xf4, 0xb, 0x40, - 0x0, 0x0, 0x6f, 0xff, 0xff, 0x80, 0xff, 0x40, - 0xf, 0xc0, 0x0, 0xb, 0xff, 0xff, 0xe4, 0x0, - 0xff, 0x0, 0xb, 0x40, 0x1, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x6f, 0xff, - 0xff, 0x80, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0xfc, 0x0, 0x7, 0xc0, 0x0, 0x3e, - 0x0, 0xff, 0xff, 0x0, 0xfc, 0x0, 0xb, 0xc0, - 0x0, 0x3f, 0x0, 0xff, 0xff, 0x0, 0x64, 0x0, - 0x2, 0x40, 0x0, 0x18, 0x0, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 768, .box_w = 28, .box_h = 28, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 196, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 516, .adv_w = 768, .box_w = 25, .box_h = 40, .ofs_x = 10, .ofs_y = 4}, - {.bitmap_index = 766, .adv_w = 768, .box_w = 28, .box_h = 40, .ofs_x = 10, .ofs_y = 4}, - {.bitmap_index = 1046, .adv_w = 768, .box_w = 44, .box_h = 44, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 1530, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 1850, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 2250, .adv_w = 768, .box_w = 24, .box_h = 14, .ofs_x = 12, .ofs_y = 18}, - {.bitmap_index = 2334, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 2654, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 3054, .adv_w = 768, .box_w = 36, .box_h = 36, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 3378, .adv_w = 768, .box_w = 24, .box_h = 36, .ofs_x = 12, .ofs_y = 6}, - {.bitmap_index = 3594, .adv_w = 768, .box_w = 32, .box_h = 36, .ofs_x = 8, .ofs_y = 6}, - {.bitmap_index = 3882, .adv_w = 768, .box_w = 32, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 4138, .adv_w = 768, .box_w = 28, .box_h = 28, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 4334, .adv_w = 768, .box_w = 36, .box_h = 24, .ofs_x = 6, .ofs_y = 12}, - {.bitmap_index = 4550, .adv_w = 768, .box_w = 8, .box_h = 32, .ofs_x = 20, .ofs_y = 8}, - {.bitmap_index = 4614, .adv_w = 768, .box_w = 32, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 4870, .adv_w = 768, .box_w = 46, .box_h = 34, .ofs_x = 1, .ofs_y = 6}, - {.bitmap_index = 5261, .adv_w = 768, .box_w = 32, .box_h = 24, .ofs_x = 8, .ofs_y = 12}, - {.bitmap_index = 5453, .adv_w = 768, .box_w = 36, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 5741, .adv_w = 768, .box_w = 36, .box_h = 33, .ofs_x = 6, .ofs_y = 8}, - {.bitmap_index = 6038, .adv_w = 768, .box_w = 32, .box_h = 40, .ofs_x = 8, .ofs_y = 4}, - {.bitmap_index = 6358, .adv_w = 768, .box_w = 40, .box_h = 38, .ofs_x = 4, .ofs_y = 6}, - {.bitmap_index = 6738, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 7138, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 7538, .adv_w = 768, .box_w = 30, .box_h = 40, .ofs_x = 9, .ofs_y = 4}, - {.bitmap_index = 7838, .adv_w = 768, .box_w = 32, .box_h = 36, .ofs_x = 8, .ofs_y = 6}, - {.bitmap_index = 8126, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 8446, .adv_w = 768, .box_w = 48, .box_h = 46, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 8998, .adv_w = 768, .box_w = 36, .box_h = 36, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 9322, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 9722, .adv_w = 768, .box_w = 36, .box_h = 36, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 10046, .adv_w = 768, .box_w = 40, .box_h = 32, .ofs_x = 4, .ofs_y = 8}, - {.bitmap_index = 10366, .adv_w = 768, .box_w = 40, .box_h = 36, .ofs_x = 4, .ofs_y = 6}, - {.bitmap_index = 10726, .adv_w = 768, .box_w = 36, .box_h = 40, .ofs_x = 6, .ofs_y = 4}, - {.bitmap_index = 11086, .adv_w = 768, .box_w = 32, .box_h = 40, .ofs_x = 8, .ofs_y = 4}, - {.bitmap_index = 11406, .adv_w = 768, .box_w = 36, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 11694, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 12094, .adv_w = 768, .box_w = 36, .box_h = 36, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 12418, .adv_w = 768, .box_w = 36, .box_h = 36, .ofs_x = 6, .ofs_y = 6}, - {.bitmap_index = 12742, .adv_w = 768, .box_w = 44, .box_h = 32, .ofs_x = 2, .ofs_y = 8}, - {.bitmap_index = 13094, .adv_w = 768, .box_w = 32, .box_h = 32, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 13350, .adv_w = 768, .box_w = 44, .box_h = 32, .ofs_x = 2, .ofs_y = 8}, - {.bitmap_index = 13702, .adv_w = 768, .box_w = 36, .box_h = 40, .ofs_x = 6, .ofs_y = 4}, - {.bitmap_index = 14062, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4}, - {.bitmap_index = 14462, .adv_w = 768, .box_w = 40, .box_h = 40, .ofs_x = 4, .ofs_y = 4} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_48 = { -#else -lv_font_t material_symbols_shared_48 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 46, /*The maximum line height required by the font*/ - .base_line = -2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_48*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_shared_64.c b/Modules/lvgl-module/source-fonts/material_symbols_shared_64.c deleted file mode 100644 index 7c45bef5e..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_shared_64.c +++ /dev/null @@ -1,3653 +0,0 @@ -/******************************************************************************* - * Size: 64 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 64 --font MaterialSymbolsRounded.ttf -r 0xE145,0xE5C3,0xE770,0xEF40,0xEBCC,0xEFE6,0xEF4A,0xE5CD,0xF15C,0xE668,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xEA07,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xEF7A,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7,0xEB8E,0xEAD6,0xE3AF,0xFFF75 --format lvgl -o source-fonts/material_symbols_shared_64.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_SHARED_64 -#define MATERIAL_SYMBOLS_SHARED_64 1 -#endif - -#if MATERIAL_SYMBOLS_SHARED_64 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E145 "" */ - 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x55, 0x55, 0x55, 0xff, 0xf5, 0x55, 0x55, - 0x55, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xf4, 0x0, 0x0, 0x0, - 0x0, - - /* U+E159 "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x40, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xdf, 0xff, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xfd, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xdf, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0xdf, 0xfe, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xef, 0xfd, 0xff, 0xd2, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf4, 0xff, 0xdf, - 0xfd, 0x3, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xf8, 0xf, 0xfd, 0xff, 0xd0, 0x7, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0xb, 0xff, 0xfc, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0xb, 0xff, 0xf8, - 0x0, 0x0, 0x7, 0xff, 0xfd, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x1f, 0xff, 0xf4, 0x0, 0x2, - 0xff, 0xfe, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x2f, 0xff, 0xe0, 0x1, 0xff, 0xff, 0x40, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x7f, - 0xff, 0xd0, 0xff, 0xff, 0x80, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x54, 0x0, - - /* U+E1A7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf8, 0x0, - 0x3f, 0x80, 0x0, 0x3, 0xff, 0xff, 0xfe, 0x0, - 0xbf, 0xf0, 0x0, 0x3, 0xff, 0xbf, 0xff, 0x80, - 0xbf, 0xfc, 0x0, 0x3, 0xff, 0x4f, 0xff, 0xe0, - 0x7f, 0xff, 0x0, 0x3, 0xff, 0x43, 0xff, 0xf8, - 0x2f, 0xff, 0xc0, 0x3, 0xff, 0x40, 0xbf, 0xfd, - 0xb, 0xff, 0xf0, 0x3, 0xff, 0x40, 0x3f, 0xff, - 0x2, 0xff, 0xfc, 0x3, 0xff, 0x40, 0x7f, 0xfe, - 0x0, 0xbf, 0xff, 0x3, 0xff, 0x41, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xc3, 0xff, 0x47, 0xff, 0xf4, - 0x0, 0xb, 0xff, 0xf3, 0xff, 0x5f, 0xff, 0xd0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x40, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x7, 0xff, 0xf7, 0xff, 0x6f, 0xff, 0xc0, - 0x0, 0x1f, 0xff, 0xd3, 0xff, 0x4b, 0xff, 0xf0, - 0x0, 0x7f, 0xff, 0x43, 0xff, 0x42, 0xff, 0xfc, - 0x1, 0xff, 0xfd, 0x3, 0xff, 0x40, 0xbf, 0xfe, - 0x7, 0xff, 0xf4, 0x3, 0xff, 0x40, 0x3f, 0xff, - 0x1f, 0xff, 0xd0, 0x3, 0xff, 0x40, 0x7f, 0xfe, - 0x3f, 0xff, 0x40, 0x3, 0xff, 0x41, 0xff, 0xfc, - 0xbf, 0xfd, 0x0, 0x3, 0xff, 0x47, 0xff, 0xf0, - 0xbf, 0xf4, 0x0, 0x3, 0xff, 0x5f, 0xff, 0xc0, - 0x7f, 0xd0, 0x0, 0x3, 0xff, 0xff, 0xff, 0x0, - 0x1a, 0x0, 0x0, 0x3, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xa, - 0x90, 0x0, 0xb, 0xff, 0x0, 0x1a, 0xaa, 0xa8, - 0xb, 0xff, 0xc0, 0x0, 0xbf, 0xf0, 0x3, 0xff, - 0xff, 0xe2, 0xff, 0xff, 0x0, 0xb, 0xff, 0x0, - 0x3f, 0xff, 0xfe, 0x3f, 0xff, 0xf8, 0x0, 0xbf, - 0xf0, 0x3, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xc0, - 0xb, 0xff, 0x0, 0x3f, 0xff, 0xfe, 0xbf, 0xff, - 0xfc, 0x0, 0xbf, 0xf0, 0x3, 0xff, 0xff, 0xeb, - 0xff, 0xff, 0xc0, 0xb, 0xff, 0x0, 0x3f, 0xff, - 0xfe, 0x7f, 0xff, 0xf8, 0x0, 0xbf, 0xf0, 0x3, - 0xff, 0xff, 0xe3, 0xff, 0xff, 0x0, 0xb, 0xff, - 0x0, 0x3f, 0xff, 0xfe, 0xf, 0xff, 0xc0, 0x0, - 0xbf, 0xf0, 0x3, 0xff, 0xff, 0xe0, 0x3f, 0xf4, - 0x0, 0xb, 0xff, 0x0, 0x2f, 0xff, 0xfd, 0x3, - 0xff, 0x40, 0x0, 0xbf, 0xf0, 0x0, 0x1f, 0xfc, - 0x0, 0x3f, 0xf4, 0x0, 0xb, 0xff, 0x0, 0x1, - 0xff, 0xc0, 0x3, 0xff, 0x40, 0x0, 0xbf, 0xf0, - 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xf4, 0x0, 0xb, - 0xff, 0x0, 0x1, 0xff, 0xc0, 0x3, 0xff, 0x40, - 0x0, 0xbf, 0xf0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, - 0xfe, 0xaa, 0xaf, 0xff, 0xaa, 0xab, 0xff, 0xc0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x6, - 0xaa, 0xaa, 0xff, 0xfa, 0xaa, 0xa9, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1a, 0x40, 0x0, 0x0, 0x0, 0x0, - - /* U+E28D "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfd, 0x7, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x80, 0x2f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x1, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x1f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x1, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x40, 0x1f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xf4, 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x40, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x1, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x1f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf4, 0x1, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x40, 0x1f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf4, 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, - 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x1, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x40, 0x1f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x1, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6, 0xaa, 0xaa, 0xab, 0xff, 0xea, 0xbf, - 0xfe, 0xaa, 0xaa, 0xa9, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x3f, 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xab, 0xff, 0xc0, 0x0, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x3f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xc0, 0x0, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xfc, 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, - 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x1f, 0xfd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x57, 0xff, 0x40, 0x2, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x3f, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xc0, 0x3, 0xff, 0x40, 0xb, 0xd0, - 0x0, 0x2, 0xf8, 0x0, 0x0, 0x7e, 0x0, 0x1f, - 0xfc, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x0, 0x0, - 0x7f, 0xd0, 0x0, 0xf, 0xf8, 0x0, 0xff, 0xd0, - 0xb, 0xff, 0x0, 0x3f, 0xf4, 0x0, 0xb, 0xfe, - 0x0, 0x1, 0xff, 0xc0, 0xf, 0xfe, 0x0, 0xff, - 0xe0, 0x3, 0xff, 0x40, 0x0, 0xbf, 0xe0, 0x0, - 0x1f, 0xfc, 0x0, 0xbf, 0xf0, 0xf, 0xfd, 0x0, - 0x3f, 0xf4, 0x0, 0xb, 0xfe, 0x0, 0x1, 0xff, - 0xc0, 0x7, 0xff, 0x1, 0xff, 0xc0, 0x3, 0xff, - 0x40, 0x0, 0xbf, 0xe0, 0x0, 0x1f, 0xfc, 0x0, - 0x3f, 0xf4, 0x2f, 0xfc, 0x0, 0x3f, 0xf4, 0x0, - 0xb, 0xfe, 0x0, 0x1, 0xff, 0xc0, 0x3, 0xff, - 0x83, 0xff, 0x80, 0x3, 0xff, 0x40, 0x0, 0xbf, - 0xe0, 0x0, 0x1f, 0xfc, 0x0, 0x2f, 0xfc, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x50, 0x0, - - /* U+E2C7 "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x8f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x5f, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x54, 0x0, - - /* U+E30F "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x55, 0x55, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, - 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x1, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x1f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf0, 0x1, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x3, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xf0, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x2f, 0xff, - 0x40, 0x0, 0x7f, 0xff, 0xff, 0xf4, 0xbf, 0xff, - 0xff, 0xff, 0x40, 0x0, 0xbf, 0xd0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xf4, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xe5, 0x55, 0x7f, - 0xff, 0x40, 0x0, 0x0, 0x2f, 0xff, 0xd5, 0x55, - 0xff, 0xdf, 0xfd, 0x0, 0x1, 0xff, 0xfc, 0x0, - 0x0, 0x7, 0xff, 0xf0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xfc, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x7f, 0xfe, 0x0, 0x0, 0xf, 0xff, 0xc0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x1f, 0xff, 0xc0, - 0x0, 0x0, 0x7f, 0xff, 0x0, 0x0, 0xff, 0xdf, - 0xfe, 0x55, 0x57, 0xff, 0xf4, 0x0, 0x0, 0x2, - 0xff, 0xfd, 0x55, 0x5f, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x1e, 0x40, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0xb, 0xfd, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xfc, 0x0, - 0x2, 0xff, 0xf4, 0x0, 0x7, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x1f, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x7f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x1f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf0, 0x1, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x1, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x0, 0x1f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf0, 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x95, 0x6f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E316 "" */ - 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0x5f, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, 0xd0, - 0x7f, 0xff, 0x0, 0x0, 0x3, 0xff, 0xf4, 0x1, - 0xff, 0xfc, 0x0, 0x0, 0xff, 0xfd, 0x0, 0x7, - 0xff, 0xf0, 0x0, 0x3f, 0xff, 0x40, 0x0, 0x1f, - 0xff, 0xc0, 0xf, 0xff, 0xd0, 0x0, 0x0, 0x7f, - 0xff, 0x3, 0xff, 0xf4, 0x0, 0x0, 0x1, 0xff, - 0xfc, 0xbf, 0xfd, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xef, 0xff, 0x40, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xbf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe2, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf8, - - /* U+E326 "" */ - 0x0, 0x0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x40, 0x0, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x3, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x55, 0x55, - 0x55, 0x40, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x3f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x3f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, - 0x0, 0xf, 0xfd, 0x3, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0xff, - 0xd0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x0, 0x50, 0xf, 0xfd, 0x3, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x3f, 0x40, 0xff, 0xd0, 0x3f, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x3, 0xf8, 0xf, - 0xfd, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x3f, 0x40, 0xff, 0xd0, 0x3f, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x40, 0xf, 0xfd, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0xff, 0xd0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x0, 0x0, 0xf, 0xfd, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x0, 0xff, 0xd0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0xf, 0xfd, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0xff, 0xd0, - 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x0, 0x0, 0xf, 0xfd, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0xff, 0xd0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xf, 0xfd, 0x0, 0x0, 0xf, 0xfd, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0xff, 0xd0, 0x0, 0x0, 0xff, 0xd0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf, 0xfd, 0x0, - 0x0, 0xf, 0xfd, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0xff, 0xd0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x5, 0x55, 0x55, 0x55, 0x54, 0x0, - 0xf, 0xfd, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0xf, - 0xfd, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x15, 0x55, 0x55, - 0x55, 0x55, 0x54, 0x0, 0x0, 0x15, 0x55, 0x55, - 0x55, 0x0, - - /* U+E3AF "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xe4, 0x0, - 0x1f, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x80, 0x0, 0x3, 0xf0, 0x6f, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x80, 0x0, 0x0, 0xbe, 0x0, 0x2f, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0, - 0xf, 0xff, 0xe0, 0x0, 0x0, 0x2, 0xf4, 0x0, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x2, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0x7f, 0xff, 0x40, 0x0, 0x0, - 0xf, 0xc0, 0x0, 0x0, 0xb, 0xff, 0xc0, 0x0, - 0xf, 0xff, 0xfc, 0x0, 0x0, 0x1, 0xf8, 0x0, - 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x2, 0xff, 0xfb, - 0xd0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf4, 0x0, 0x3f, 0xfc, 0x3f, 0x0, 0x0, - 0xb, 0xd0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, - 0xb, 0xff, 0x41, 0xf8, 0x0, 0x1, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0xff, 0xf0, - 0xf, 0xc0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0x1f, 0xfd, 0x0, 0x7f, 0x0, - 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0x2, 0xff, 0xc0, 0x2, 0xf4, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3f, 0xf8, - 0x0, 0xf, 0xc0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x83, 0xff, 0x40, 0x0, 0xbe, - 0x3, 0xff, 0xff, 0xff, 0xea, 0xaa, 0xaa, 0xbf, - 0xfc, 0x7f, 0xf0, 0x0, 0x3, 0xf4, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x1, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xe0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0xff, 0xdb, 0xfe, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfd, 0xbf, - 0xe0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xff, 0xef, 0xfe, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0xf, 0xfe, 0xbf, 0xe0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xff, 0xeb, - 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xfe, 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xf0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xd7, 0xff, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xfe, 0x1f, 0x80, 0x0, 0x1f, 0xfc, - 0x3f, 0xfa, 0xaa, 0xaa, 0xab, 0xff, 0xff, 0xff, - 0xc0, 0xfd, 0x0, 0x1, 0xff, 0xc3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3, 0xf0, - 0x0, 0x3f, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x2f, 0x40, 0x3, 0xff, - 0x81, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xd0, 0x0, 0xfc, 0x0, 0xbf, 0xf0, 0xf, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xf8, 0x0, 0x7, - 0xe0, 0xf, 0xff, 0x0, 0xbf, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x0, 0x0, 0x3f, 0x2, 0xff, - 0xd0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xb, - 0xe0, 0x0, 0x1, 0xfc, 0x7f, 0xfc, 0x0, 0x2f, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, - 0xf, 0xdf, 0xff, 0x80, 0x0, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0x3f, 0xff, - 0xf0, 0x0, 0xb, 0xff, 0xd0, 0x0, 0x0, 0x7, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0xfd, 0x0, 0x0, - 0x3f, 0xff, 0x40, 0x0, 0x0, 0xfd, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, 0xff, 0xfd, - 0x0, 0x0, 0x2f, 0x80, 0x0, 0x0, 0xb, 0xff, - 0xf0, 0x0, 0x0, 0x7, 0xff, 0xf8, 0x0, 0x3, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xf4, 0x0, 0xbe, 0x0, 0x0, - 0x1, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xf4, 0xf, 0xc0, 0x0, 0x1, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xfb, - 0xf4, 0x0, 0x6, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xaa, 0xaf, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6b, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E3F4 "" */ - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x1, - 0x40, 0x0, 0x2, 0xff, 0x80, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xff, - 0xd0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0xf, - 0xf0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x3f, 0xfc, 0x0, 0x3f, 0xff, - 0xfc, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0xbf, - 0xfe, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x1, 0xff, 0xff, 0x41, 0xff, 0xff, - 0xff, 0x40, 0x7, 0xff, 0xff, 0xd0, 0x3, 0xff, - 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc0, 0x7, 0xff, - 0xff, 0xd0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x7, 0xff, 0xff, 0xd0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7, 0xff, - 0xff, 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf4, 0x7, 0xff, 0xff, 0xd0, 0x5, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+E405 "" */ - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xfa, 0xaa, 0xa4, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xf8, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, - - /* U+E55D "" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0xa4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xaf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xf0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfe, 0xb, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xc0, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0x40, 0x1f, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x0, - 0x7, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xc0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x2, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, - 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xe0, 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfc, 0x0, 0x0, 0x3, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, - 0x2f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf4, - 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x7, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x0, - 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, - 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xc0, 0x0, 0xb, 0xff, 0x40, 0x0, 0xa, - 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0, 0xff, 0xf0, - 0x0, 0x1f, 0xff, 0x40, 0x0, 0xff, 0xf0, 0x0, - 0x1f, 0xfd, 0x0, 0x2f, 0xff, 0xff, 0x80, 0x7, - 0xff, 0x40, 0x3, 0xff, 0xc0, 0x2f, 0xff, 0xff, - 0xff, 0x80, 0x3f, 0xfc, 0x0, 0x7f, 0xf4, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xd1, 0xff, 0xd0, 0xf, - 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xbf, - 0xff, 0xff, 0xff, 0xf0, 0x2f, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0x83, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xfc, 0xbf, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xef, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xf7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xfd, 0x9, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, - - /* U+E5C3 "" */ - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0x0, 0x3, - 0xff, 0xd0, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0xf4, 0x0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x0, 0x2f, 0xff, 0xfc, - 0x0, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x0, - 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x3f, 0xff, - 0xfd, 0x0, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E5CD "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x40, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xf8, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xfc, 0xbf, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xfd, 0x7f, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xfc, 0x2f, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0xb, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xd0, 0x2, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x40, - 0x0, 0xbf, 0xff, 0x0, 0x0, 0x1, 0xff, 0xfd, - 0x0, 0x0, 0x2f, 0xff, 0xc0, 0x0, 0x7, 0xff, - 0xf4, 0x0, 0x0, 0xb, 0xff, 0xf0, 0x0, 0x1f, - 0xff, 0xd0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, - 0x7f, 0xff, 0x40, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0x1, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xc7, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xdb, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0x42, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xfd, 0x0, 0xbf, 0xff, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x2f, 0xff, - 0xc0, 0x0, 0x0, 0x1f, 0xff, 0xd0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0x0, 0x7f, 0xff, 0x40, 0x0, - 0x2, 0xff, 0xfc, 0x0, 0x1, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0x0, 0x7, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xc0, 0x1f, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xf0, 0x3f, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x2, 0xff, 0xf8, - 0xbf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xfc, 0xbf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xfc, 0x7f, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0x1a, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xa0, - - /* U+E5D2 "" */ - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x5, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x50, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+E5D4 "" */ - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x3, 0xff, 0xd0, 0xf, 0xff, - 0xf4, 0x2f, 0xff, 0xfc, 0x3f, 0xff, 0xfc, 0x3f, - 0xff, 0xfd, 0x3f, 0xff, 0xfd, 0x3f, 0xff, 0xfc, - 0x1f, 0xff, 0xf8, 0xb, 0xff, 0xf0, 0x1, 0xff, - 0x80, 0x0, 0x0, 0x0, - - /* U+E5D5 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, - 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0xbf, - 0xff, 0xfe, 0x40, 0x0, 0x7, 0xf8, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xf8, 0x0, 0xf, - 0xfc, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xf, 0xfd, 0x0, 0x0, 0x1f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf, 0xfd, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xf, 0xfd, 0x0, 0x2, 0xff, 0xff, 0xe4, 0x0, - 0x1b, 0xff, 0xff, 0x8f, 0xfd, 0x0, 0xb, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xef, 0xfd, - 0x0, 0x2f, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xfd, 0x0, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xfd, 0x2, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xfd, 0x3, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xfd, 0xb, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xfd, 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xfd, 0x1f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfd, - 0x2f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xfd, 0x3f, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, - 0xf8, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x55, 0x55, 0x55, 0x40, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x0, 0xf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xc0, 0xb, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xd0, 0x3, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, - 0x2, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0x80, 0x0, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x7f, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfd, - 0x0, 0x0, 0x2f, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xf4, 0x0, 0x0, 0xb, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xe0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xe4, 0x0, 0x1b, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xbf, 0xff, 0xfe, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E63E "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, 0xff, 0xff, - 0xfe, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x7, 0xff, 0xff, 0xff, - 0xff, 0xe5, 0x0, 0x0, 0x5, 0xbf, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x2, 0xff, 0xff, 0xff, 0xfe, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x1b, 0xff, 0xff, - 0xff, 0xfc, 0x0, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xff, 0xc3, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xfd, 0x3f, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xd3, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xfc, - 0x1f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, - 0x7f, 0xd0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, - 0xf9, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xfe, 0x40, 0x0, 0x1b, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xf9, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E668 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xc0, 0x0, - 0x1, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xf0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xfc, 0x0, 0x0, 0xb, 0xff, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0xbf, 0xfe, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xc0, - 0x0, 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0xb, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xe0, - 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0x80, 0x0, 0xbf, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x2f, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xf8, - 0xb, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xe2, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+E745 "" */ - 0x1, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 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, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xfc, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xfc, 0x3f, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xff, 0x4f, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xe1, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xff, 0xf8, 0x5, 0x55, 0x55, 0x55, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc3, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xfc, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+E770 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xa4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x4f, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0x2, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x7f, - 0xff, 0xd5, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf4, 0x0, 0xf, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xe0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xf8, 0x1a, 0x0, 0x0, 0xb, - 0xff, 0xc0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfd, - 0xbf, 0xc0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x3f, - 0xfd, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xc2, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xfb, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xef, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd3, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0xbf, 0xf0, - 0x0, 0x2, 0xc0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x1f, 0xc0, 0x0, 0x7, 0xf4, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x3, 0x40, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xf4, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xff, 0x80, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x7, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x7, 0xff, 0xff, 0xff, 0x80, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7, 0xff, - 0xff, 0xff, 0xe0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x7, 0xff, 0xff, 0xff, 0xfc, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0xff, - 0xff, 0xff, 0xff, 0x4f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - - /* U+E89C "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x55, 0x50, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xd0, 0x0, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xf4, 0x0, 0x0, - 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xff, 0x40, 0x0, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xd0, - 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xf4, 0x0, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, - 0xff, 0x40, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xd0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xf0, - 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0xbe, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x1, 0xff, 0x40, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x2, - 0xff, 0x80, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x1, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xf, 0xfd, - 0x7f, 0xf0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0xf, 0xfd, 0x7f, 0xf0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, - 0x80, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x2, 0xff, 0x80, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x1, - 0xff, 0x40, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xf5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x5f, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x40, - - /* U+E8AF "" */ - 0x0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x2, - 0xfa, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x3f, 0xfd, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xf0, 0x3, 0xff, 0xf4, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, - 0x3f, 0xff, 0xcf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x3, 0xff, 0xfc, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x0, 0x3f, 0xff, 0xcf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, - 0x3, 0xff, 0xfc, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x3f, 0xff, - 0xcf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf0, 0x3, 0xff, 0xfc, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x0, 0x3f, 0xff, 0xcf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x3, 0xff, - 0xfc, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x0, 0x3f, 0xff, 0xcf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf0, 0x3, 0xff, 0xfc, 0xff, 0xd0, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, 0x0, 0x3f, - 0xff, 0xcf, 0xfd, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x3, 0xff, 0xfc, 0xff, - 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x0, 0x3f, 0xff, 0xcf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x3, - 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0x3f, 0xff, 0xcf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x0, 0x3, 0xff, 0xfc, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xcf, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xcf, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xfc, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xc7, 0xfc, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x9, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xe0, - - /* U+E8B8 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfc, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xfd, - 0x0, 0x7f, 0xfc, 0x0, 0x3f, 0xfd, 0x0, 0x7f, - 0xe0, 0x0, 0x0, 0x3f, 0xff, 0xe3, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xcb, 0xff, 0xfc, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x3, 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, - 0x6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xb, 0xff, - 0xaf, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xfa, 0xff, 0xe0, 0xf, 0xff, 0x1, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0x40, 0xff, 0xf0, - 0x2f, 0xfe, 0x0, 0x1b, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xe4, 0x0, 0xbf, 0xf8, 0x3f, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfc, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x6, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x7f, - 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x3f, 0xfd, 0x3f, 0xff, 0x40, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x80, 0x0, 0x1, 0xff, - 0xfc, 0x2f, 0xff, 0xe0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0xb, 0xff, 0xf8, 0xb, 0xff, - 0xfc, 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x3f, 0xff, 0xe0, 0x1, 0xff, 0xff, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0xff, 0xff, 0x40, - 0x0, 0x7f, 0xfe, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0xbf, 0xfd, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, - 0xf0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xf0, 0x0, 0x0, - 0xf, 0xfd, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x7f, 0xf0, 0x0, 0x0, 0xf, 0xfd, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xf0, - 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xfc, 0x0, 0xbf, 0xf8, 0x0, 0x0, 0xff, - 0xfe, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xfc, 0x0, - 0xbf, 0xfe, 0x0, 0x7, 0xff, 0xfe, 0x0, 0xf, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0xbf, 0xff, 0xc0, - 0xf, 0xff, 0xf4, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xc0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x3, - 0xff, 0xfc, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0x0, 0x0, 0x0, 0xbf, 0xfc, 0x7f, - 0xf4, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x1f, 0xfd, 0x7f, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x59, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xfc, 0x3f, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x40, 0x0, 0x7f, 0xfc, 0x1f, 0xff, - 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x2, 0xfd, - 0x0, 0xff, 0xf4, 0xf, 0xff, 0x4b, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xe1, 0xff, 0xe0, - 0x3, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xff, 0xc0, 0x2, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, - 0x7f, 0xff, 0xfb, 0xff, 0xf8, 0x0, 0x2f, 0xff, - 0xef, 0xff, 0xfd, 0x0, 0x0, 0x1f, 0xff, 0x40, - 0xff, 0xfc, 0x0, 0x3f, 0xff, 0x1, 0xff, 0xf4, - 0x0, 0x0, 0x2, 0xa0, 0x0, 0x2f, 0xfc, 0x0, - 0x3f, 0xf8, 0x0, 0x1a, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x3f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfc, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x55, 0xbf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+E8FD "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xe4, 0x0, - 0x1, 0xbf, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, - 0xf, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x2, 0xff, 0xf4, - 0x0, 0x0, 0x6, 0xfa, 0x40, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0x40, 0x0, 0xb, 0xff, 0xc0, 0x0, - 0xf, 0xff, 0x40, 0x0, 0xb, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x2f, 0xff, 0x0, 0x2, 0xff, 0xe0, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0xff, 0xf4, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x3f, - 0xff, 0xef, 0xff, 0xd0, 0x0, 0x3, 0xff, 0xc0, - 0xb, 0xff, 0x40, 0x0, 0x7, 0xff, 0x40, 0x1f, - 0xff, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0x7f, 0xd0, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0xff, 0xe0, 0x1f, 0xfd, 0x0, 0x0, 0x2, - 0xf4, 0x0, 0x3, 0xff, 0x40, 0x0, 0xb, 0xff, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xf4, 0x0, 0x0, 0x3f, 0xf4, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, - 0x0, 0x3, 0xff, 0x83, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0x1f, - 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x0, 0x0, 0x1, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, - 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xff, 0xdb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xbf, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xef, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0xf, 0xfe, 0xbf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xff, 0xeb, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd7, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, - 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xc3, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfc, 0x2f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x81, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0xbf, 0xf0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xd0, 0x3, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x2f, - 0xfd, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x0, 0x0, - 0x0, 0xb, 0xff, 0x80, 0x0, 0xff, 0xf0, 0x0, - 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, 0x1, 0xff, - 0xf0, 0x0, 0xb, 0xff, 0xc0, 0x0, 0x0, 0xf, - 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x0, - 0x3f, 0xff, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, - 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xf0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xe4, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xfe, 0xaa, 0xaf, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6b, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+E90F "" */ - 0x0, 0x0, 0x0, 0x0, 0x15, 0x54, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x1f, 0xff, 0xfe, - 0x40, 0x1, 0xbf, 0xff, 0xf4, 0x0, 0x0, 0x3f, - 0xff, 0xd0, 0x0, 0x0, 0x7, 0xff, 0xfc, 0x0, - 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x2, 0xff, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x80, 0x7, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0xf, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf0, - 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xf4, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfc, 0x3f, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfc, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfe, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfe, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x3f, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfc, 0x2f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, - 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xf4, 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xf0, 0x7, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xd0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, - 0x0, 0xff, 0xfe, 0x55, 0x55, 0x55, 0x55, 0xbf, - 0xff, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x1f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xf4, 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, 0x55, 0x55, 0x55, 0x55, 0x40, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 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, 0x55, 0x55, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0xe0, - 0x0, 0x0, 0x0, 0x0, - - /* U+E92E "" */ - 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x1, 0x55, - 0x55, 0x5f, 0xff, 0xff, 0xff, 0xf5, 0x55, 0x55, - 0x40, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x2, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0x80, 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0x80, 0x1, 0x90, 0x0, 0x6, 0x40, 0x2, - 0xff, 0x80, 0x2, 0xff, 0x80, 0xb, 0xfc, 0x0, - 0x3f, 0xe0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, - 0xf, 0xfc, 0x0, 0x3f, 0xf0, 0x2, 0xff, 0x80, - 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, - 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, - 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, - 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, - 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, - 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, - 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, - 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, - 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, - 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, - 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, - 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, - 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, - 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, - 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, - 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, - 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, - 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, - 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, - 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, - 0x2, 0xff, 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, - 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0xf, 0xfd, - 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, - 0x80, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x2, 0xff, - 0x80, 0x2, 0xff, 0x80, 0xf, 0xfc, 0x0, 0x3f, - 0xf0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0x7, - 0xf8, 0x0, 0x2f, 0xd0, 0x2, 0xff, 0x80, 0x2, - 0xff, 0x80, 0x0, 0x40, 0x0, 0x1, 0x0, 0x2, - 0xff, 0x80, 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x2, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x80, 0x2, 0xff, - 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xff, - 0x80, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, - - /* U+E9B9 "" */ - 0x0, 0x54, 0x0, 0x0, 0x0, 0x5a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x7f, 0xf8, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x1f, 0xff, 0xf0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x43, 0xff, 0xff, 0x40, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, - 0xfc, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xc0, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xbf, 0xff, 0xfc, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, - 0xff, 0x80, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xf0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0xff, 0xfd, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2, - 0xff, 0x40, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x54, 0x0, 0x0, 0x0, 0x5a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x7f, 0xf8, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x1f, 0xff, 0xf0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x43, 0xff, 0xff, 0x40, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, - 0xfc, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xc0, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xbf, 0xff, 0xfc, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, - 0xff, 0x80, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xf0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0xff, 0xfd, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2, - 0xff, 0x40, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 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, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x54, 0x0, 0x0, 0x0, 0x5a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x7f, 0xf8, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x1f, 0xff, 0xf0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x43, 0xff, 0xff, 0x40, 0x3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, - 0xfc, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xc0, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xbf, 0xff, 0xfc, 0x0, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, - 0xff, 0x80, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xf0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0xff, 0xfd, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2, - 0xff, 0x40, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E9F4 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfd, - 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, - 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x7, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x7, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, - 0xb, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf8, - 0x2f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5, 0x50, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x50, 0x0, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, - 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x2, 0xff, - 0xff, 0x80, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, - 0xff, 0xf4, 0x1f, 0xfe, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xbf, 0xf4, 0x1f, 0xfe, - 0xff, 0xe0, 0xb, 0xff, 0x0, 0x0, 0xbf, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0xff, 0xe0, 0xb, 0xff, - 0xff, 0xd0, 0x7, 0xff, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0xff, 0xd0, 0x7, 0xff, - 0xff, 0xe0, 0xb, 0xff, 0xd0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x7, 0xff, 0xe0, 0xb, 0xff, - 0xbf, 0xf4, 0x1f, 0xff, 0xff, 0xaf, 0xff, 0xd0, - 0x7, 0xff, 0xfa, 0xff, 0xff, 0xf4, 0x1f, 0xfe, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0xf, 0xff, 0xff, 0xf0, 0x6f, 0xff, 0xf0, 0x0, - 0x0, 0xf, 0xff, 0xf9, 0xf, 0xff, 0xff, 0xf0, - 0x3, 0xff, 0xff, 0xc0, 0x1, 0xff, 0xe0, 0x0, - 0x0, 0xb, 0xff, 0x40, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0xbf, 0xfd, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x7, 0xff, 0x0, 0x0, 0x7f, 0xfe, 0x0, - 0x0, 0x1, 0x40, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x7, 0xff, 0x0, 0x0, 0x1, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, - 0x0, 0xb, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x0, - 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, - 0x0, 0x2f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, - 0x0, 0xbf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xd0, - 0x7, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe2, 0xff, - 0xff, 0x8b, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0x50, 0xff, 0xc0, 0x5, - 0x50, 0x3, 0xff, 0x5, 0x50, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xf4, 0x1f, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xf4, 0x1f, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x7, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x7, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xe0, 0xb, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xf4, 0x1f, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xf4, 0x1f, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, - - /* U+E9F7 "" */ - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xe5, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+EA07 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xfb, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x9f, 0xff, 0xf, 0xff, 0x6f, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x82, 0xff, 0xd0, 0x7f, 0xf8, 0x2f, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x3f, 0xf8, - 0x3, 0xff, 0xc0, 0x7f, 0xff, 0x80, 0x0, 0x0, - 0xf, 0xff, 0xe0, 0xb, 0xff, 0x0, 0x1f, 0xfd, - 0x0, 0xff, 0xfe, 0x0, 0x0, 0x2, 0xff, 0xf8, - 0x0, 0xff, 0xe0, 0x0, 0xff, 0xf0, 0x3, 0xff, - 0xf4, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x1f, 0xfd, - 0x0, 0x7, 0xff, 0x0, 0xf, 0xff, 0xc0, 0x0, - 0xf, 0xff, 0x80, 0x3, 0xff, 0xc0, 0x0, 0x3f, - 0xf8, 0x0, 0x3f, 0xfe, 0x0, 0x2, 0xff, 0xf0, - 0x0, 0x3f, 0xf4, 0x0, 0x2, 0xff, 0xc0, 0x0, - 0xff, 0xf4, 0x0, 0x3f, 0xfd, 0x0, 0x7, 0xff, - 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x7, 0xff, 0xc0, - 0x7, 0xff, 0xd5, 0x55, 0xff, 0xf5, 0x55, 0x56, - 0xff, 0xe5, 0x55, 0x7f, 0xfd, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x7f, 0xf0, 0x0, 0x3, 0xff, 0x80, 0x0, - 0x0, 0x3f, 0xf8, 0x0, 0x1, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2, 0xff, - 0x80, 0x0, 0xf, 0xfd, 0xbf, 0xf0, 0x0, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x2f, 0xfc, 0x0, 0x0, - 0xff, 0xdb, 0xfe, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x1, 0xff, 0xc0, 0x0, 0xf, 0xfd, 0xbf, - 0xe0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x1f, - 0xfc, 0x0, 0x0, 0xff, 0xef, 0xfe, 0x0, 0x0, - 0x3f, 0xf0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0, - 0xf, 0xfe, 0xbf, 0xe0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0xff, 0xeb, - 0xfe, 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2, - 0xff, 0xc0, 0x0, 0xf, 0xfd, 0xbf, 0xf0, 0x0, - 0x3, 0xff, 0x40, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0xff, 0xd7, 0xff, 0x0, 0x0, 0x3f, 0xf8, - 0x0, 0x0, 0x2, 0xff, 0x80, 0x0, 0xf, 0xfc, - 0x3f, 0xf9, 0x55, 0x57, 0xff, 0xd5, 0x55, 0x55, - 0x7f, 0xf9, 0x55, 0x56, 0xff, 0xc3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0x3, 0xff, 0xc0, 0x0, 0x7f, 0xf0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x3f, 0xfc, 0x0, 0x2f, - 0xfe, 0x0, 0x3, 0xff, 0x40, 0x0, 0x2f, 0xfc, - 0x0, 0xf, 0xff, 0x80, 0x0, 0xff, 0xf4, 0x0, - 0x3f, 0xf8, 0x0, 0x3, 0xff, 0x80, 0x2, 0xff, - 0xf0, 0x0, 0xb, 0xff, 0xc0, 0x2, 0xff, 0xc0, - 0x0, 0x7f, 0xf4, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x3f, 0xff, 0x0, 0xf, 0xfd, 0x0, 0xb, 0xff, - 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, 0xff, 0xfc, - 0x0, 0xff, 0xf0, 0x0, 0xff, 0xe0, 0x7, 0xff, - 0xf0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0x7, 0xff, - 0x40, 0x2f, 0xfc, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xe0, 0x3f, 0xfc, 0x3, 0xff, - 0xc1, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xe1, 0xff, 0xe0, 0xff, 0xf5, 0xbf, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0x5f, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xaf, 0xff, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+EAD6 "" */ - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x7f, 0xfe, 0x1, 0xff, 0xfc, 0x1e, - 0x0, 0x1e, 0x7, 0xff, 0xff, 0xd0, 0xff, 0xff, - 0xc3, 0xff, 0xfd, 0x3f, 0x0, 0x3f, 0x47, 0xff, - 0xff, 0xd0, 0xff, 0xff, 0xd3, 0xff, 0xfc, 0x2f, - 0x40, 0x3f, 0x7, 0xff, 0xff, 0xd0, 0xfc, 0xb, - 0xd3, 0xf0, 0x0, 0x1f, 0xc0, 0x7f, 0x7, 0xff, - 0xff, 0xd0, 0xfc, 0xb, 0xd3, 0xf0, 0x0, 0xf, - 0xc0, 0xbe, 0x7, 0xff, 0xff, 0xd0, 0xfc, 0xb, - 0xd3, 0xf0, 0x0, 0xf, 0xd0, 0xfd, 0x7, 0xff, - 0xff, 0xd0, 0xfc, 0xb, 0xd3, 0xfa, 0x40, 0xb, - 0xe0, 0xfc, 0x7, 0xff, 0xff, 0xd0, 0xfc, 0xb, - 0xd3, 0xff, 0xd0, 0x7, 0xf1, 0xfc, 0x7, 0xff, - 0xff, 0xd0, 0xfc, 0xb, 0xd3, 0xff, 0xd0, 0x3, - 0xf2, 0xf8, 0x7, 0xff, 0xff, 0xd0, 0xfc, 0xb, - 0xd3, 0xf9, 0x40, 0x3, 0xf7, 0xf0, 0x7, 0xff, - 0xff, 0xd0, 0xfc, 0xb, 0xd3, 0xf0, 0x0, 0x2, - 0xff, 0xf0, 0x7, 0xff, 0xff, 0xd0, 0xfc, 0xb, - 0xd3, 0xf0, 0x0, 0x0, 0xff, 0xe0, 0x7, 0xff, - 0xff, 0xd0, 0xfc, 0xb, 0xd3, 0xf0, 0x0, 0x0, - 0xff, 0xd0, 0x7, 0xff, 0xff, 0xd0, 0xff, 0xff, - 0xd3, 0xff, 0xfc, 0x0, 0xbf, 0xc0, 0x7, 0xff, - 0xff, 0xd0, 0xff, 0xff, 0xc3, 0xff, 0xfd, 0x0, - 0x7f, 0xc0, 0x7, 0xff, 0xff, 0xd0, 0x7f, 0xfe, - 0x1, 0xff, 0xfc, 0x0, 0x2f, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+EB8E "" */ - 0x0, 0x6a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x90, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x2, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0xbf, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0xbf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x3, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0xf, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x3f, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xd0, 0x0, 0x0, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, - 0x1f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x3, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x0, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x3f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0xf, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0xbf, 0xfe, 0x0, 0x0, 0xff, 0xff, 0xff, 0xe0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0xf, 0xff, 0x80, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0x40, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0xbf, 0xe0, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x3, 0xf8, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, - 0x80, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x55, 0x55, 0x54, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x54, 0x0, - - /* U+EB97 "" */ - 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xfe, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5f, - 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x40, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x40, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x80, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x1, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3, 0xff, 0xf0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x3f, 0xff, 0x80, 0xf, 0xfd, - 0xff, 0xd0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3, 0xff, 0xf8, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x3f, 0xff, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0x80, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf4, - 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x5, - 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0xf, - 0xfd, 0xff, 0xd0, 0x0, 0x3, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, - 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x7, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x2f, 0xff, 0xc0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x3, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x3f, - 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0xf, 0xfd, 0xff, 0xd0, 0x1, 0xff, 0xfc, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, - 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x2f, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xdf, 0xfe, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5f, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x2, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+EBCC "" */ - 0x0, 0x0, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0x0, 0x0, 0x0, 0x15, 0xff, 0xe5, - 0x55, 0x55, 0x55, 0x55, 0x5b, 0xff, 0x54, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x1, 0xf8, - 0x0, 0xb, 0xd0, 0x0, 0x2f, 0x40, 0x7, 0xff, - 0xff, 0xd0, 0x3, 0xfe, 0x0, 0x1f, 0xf4, 0x0, - 0xbf, 0xc0, 0x7, 0xff, 0xff, 0xd0, 0x7, 0xff, - 0x0, 0x2f, 0xf8, 0x0, 0xff, 0xd0, 0x7, 0xff, - 0xff, 0xd0, 0x3, 0xff, 0x0, 0x2f, 0xf4, 0x0, - 0xff, 0xc0, 0x7, 0xff, 0xff, 0xd0, 0x2, 0xfc, - 0x0, 0xf, 0xe0, 0x0, 0x7f, 0x80, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, - 0x4, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x10, - 0x0, 0x1, 0x0, 0x0, 0x4, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x2, 0xfc, 0x0, 0xf, 0xe0, 0x0, - 0x7f, 0x80, 0x7, 0xff, 0xff, 0xd0, 0x3, 0xff, - 0x0, 0x2f, 0xf4, 0x0, 0xff, 0xc0, 0x7, 0xff, - 0xff, 0xd0, 0x7, 0xff, 0x0, 0x2f, 0xf8, 0x0, - 0xff, 0xd0, 0x7, 0xff, 0xff, 0xd0, 0x3, 0xfe, - 0x0, 0x1f, 0xf4, 0x0, 0xbf, 0xc0, 0x7, 0xff, - 0xff, 0xd0, 0x1, 0xf8, 0x0, 0xb, 0xd0, 0x0, - 0x2f, 0x40, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xe5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+EC1C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xf9, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xe3, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0x87, 0xff, 0xe5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xfe, 0xf, 0xff, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xf8, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0xf, 0xff, - 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, - 0x0, 0x3f, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x1, 0xff, 0xfe, 0x0, 0x0, - 0x16, 0xbf, 0xff, 0xff, 0xff, 0xf8, 0x7, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xff, - 0xf0, 0xf, 0xff, 0xfe, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xd0, 0x2f, 0xff, 0xff, 0xff, - 0xfe, 0x94, 0x0, 0x0, 0x7f, 0xff, 0x40, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x1, 0xff, - 0xfc, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0xb, 0xff, 0xf0, 0x0, 0x6, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x2f, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xf0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, - 0xff, 0xd2, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xcb, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x6f, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xfc, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+EF40 "" */ - 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0xff, 0xf4, 0x0, - 0x0, 0xff, 0xf4, 0x0, 0x0, 0xff, 0xf4, 0x0, - 0x0, 0xff, 0xff, 0x40, 0x0, 0xff, 0xff, 0x40, - 0x0, 0xff, 0xff, 0x40, 0x0, 0xbf, 0xff, 0xf0, - 0x0, 0xbf, 0xff, 0xf0, 0x0, 0xbf, 0xff, 0xf0, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0xf, 0xff, 0xff, - 0x40, 0xf, 0xff, 0xff, 0x40, 0xf, 0xff, 0xff, - 0x40, 0x3, 0xff, 0xff, 0xd0, 0x3, 0xff, 0xff, - 0xd0, 0x3, 0xff, 0xff, 0xd0, 0x0, 0xff, 0xff, - 0xf0, 0x0, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, - 0xf0, 0x0, 0x1f, 0xff, 0xf8, 0x0, 0x1f, 0xff, - 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, 0x2, 0xff, - 0xfc, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x2, 0xff, - 0xfc, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x1f, - 0xf8, 0x0, 0x0, 0x1f, 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, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xf4, 0x0, 0x0, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x40, - 0x0, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xf0, 0x0, 0xbf, 0xff, 0xf0, - 0x0, 0x0, 0x1, 0xf8, 0x0, 0x3f, 0xff, 0xfc, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x0, 0x2, 0xff, - 0xd0, 0xf, 0xff, 0xff, 0x40, 0xf, 0xff, 0xff, - 0x40, 0x0, 0x2, 0xff, 0xfd, 0x3, 0xff, 0xff, - 0xd0, 0x3, 0xff, 0xff, 0xd0, 0x0, 0x2, 0xff, - 0xff, 0xd0, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, - 0xf0, 0x0, 0x2, 0xff, 0xff, 0xfc, 0x1f, 0xff, - 0xf8, 0x0, 0x1f, 0xff, 0xf8, 0x0, 0x2, 0xff, - 0xff, 0xff, 0x82, 0xff, 0xfc, 0x0, 0x2, 0xff, - 0xfc, 0x0, 0x2, 0xff, 0xff, 0xff, 0xe0, 0x1f, - 0xf8, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc3, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0x55, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0xff, 0xff, 0x40, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0xbf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0xc0, 0xf, 0xfe, 0x0, - 0x0, 0x3f, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x3f, - 0xc0, 0xf, 0xfe, 0x0, 0x0, 0xf, 0xff, 0xff, - 0x40, 0x0, 0x0, 0xf, 0xf0, 0xf, 0xfe, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x3, - 0xfc, 0xf, 0xfe, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xfc, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+EF4A "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xfe, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xe4, 0x0, - 0x1, 0xbf, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, - 0xf, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x2, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xc0, 0x0, - 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0x0, 0x2, 0xff, 0xe0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xf4, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xc0, - 0xb, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xfd, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0x1f, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x83, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xbf, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xef, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfe, 0xbf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xeb, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd7, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, - 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xc3, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfc, 0x2f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x81, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0xbf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xd0, 0x3, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x2f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0x80, 0x0, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, - 0xf0, 0x0, 0xb, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x0, - 0x3f, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0xf0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xe4, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0xff, 0xfe, 0xaa, 0xaf, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6b, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+EF7A "" */ - 0x0, 0x0, 0x0, 0x6f, 0xff, 0xa0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xe5, 0x5b, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xf4, 0x0, 0x0, 0xbf, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0x80, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0x0, 0x0, 0x0, 0x2, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, - 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xe0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x3f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0xbf, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, - 0x0, 0x0, 0x7, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, - 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x3f, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xfd, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x3f, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0x40, 0x0, 0x1b, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xfa, 0xab, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xe0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, - 0xff, 0xf8, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xbf, 0xe9, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+EFE6 "" */ - 0x0, 0x0, 0x0, 0x6f, 0xf9, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0x40, 0x0, 0x0, 0x7, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x7, 0xff, 0xf9, - 0x6f, 0xff, 0xc0, 0x0, 0xb, 0xff, 0xff, 0xe0, - 0x0, 0xf, 0xff, 0x80, 0x3, 0xff, 0xe0, 0x0, - 0x3f, 0xff, 0xff, 0xfc, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x7f, 0xf0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x2f, 0xfc, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0xbf, 0xff, 0xff, 0xfe, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x1a, 0xbf, 0xfe, 0xa4, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x1a, 0xbf, 0xfe, 0xa4, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0xbf, 0xff, 0xff, 0xfe, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x3f, 0xf8, 0x0, - 0x0, 0x3f, 0xf8, 0x0, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x2f, 0xfc, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x1f, 0xfe, 0x0, - 0x0, 0xbf, 0xf0, 0x0, 0x3f, 0xff, 0xff, 0xfc, - 0x0, 0xf, 0xff, 0x80, 0x2, 0xff, 0xf0, 0x0, - 0xb, 0xff, 0xff, 0xe0, 0x0, 0xb, 0xff, 0xf9, - 0x6f, 0xff, 0xd0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x7, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x3, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xd0, 0x0, 0x0, 0x1, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x6f, 0xf9, 0x0, 0x0, 0x0, - - /* U+F028 "" */ - 0x0, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x0, 0x2, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x28, 0x0, 0x1, 0x90, 0x0, 0xa, 0x40, 0x0, - 0x28, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0xff, - 0x0, 0x7, 0xf8, 0x0, 0x3f, 0xd0, 0x0, 0xff, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x2, 0xff, 0x80, - 0xf, 0xfc, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, - 0xf, 0xfd, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0xf, - 0xfc, 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0xf, - 0xfd, 0x7f, 0xf0, 0x1, 0xff, 0x40, 0xb, 0xfc, - 0x0, 0x3f, 0xe0, 0x1, 0xff, 0x40, 0xf, 0xfd, - 0x7f, 0xf0, 0x0, 0x7d, 0x0, 0x2, 0xe0, 0x0, - 0xb, 0x80, 0x0, 0x7d, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0xbe, 0x0, - 0x3, 0xf4, 0x0, 0x1f, 0xc0, 0x0, 0xbe, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x1, 0xff, 0x40, 0xf, - 0xfc, 0x0, 0x3f, 0xf0, 0x1, 0xff, 0x40, 0xf, - 0xfd, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0xf, 0xfc, - 0x0, 0x7f, 0xf0, 0x2, 0xff, 0x80, 0xf, 0xfd, - 0x7f, 0xf0, 0x1, 0xff, 0x40, 0xb, 0xfc, 0x0, - 0x3f, 0xe0, 0x1, 0xff, 0x40, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0xbe, 0x0, 0x2, 0xf0, 0x0, 0x1f, - 0x80, 0x0, 0xbe, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xf0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x40, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, - 0x0, 0x0, 0x5, 0x55, 0x55, 0x55, 0x50, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x15, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x54, 0x0, - - /* U+F090 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x3, - 0xff, 0x40, 0x2f, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfc, 0x3, 0xff, 0x40, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0x3, 0xff, 0x42, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xc3, 0xff, 0x4b, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xf3, 0xff, 0x6f, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x2, 0xff, - 0x0, 0x0, 0x0, 0x2, 0xf4, 0x3f, 0xe0, 0x0, - 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0xb, 0xfc, - 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x7f, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x0, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x54, 0x0, - - /* U+F15C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xe4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, - 0xf4, 0x0, 0x6f, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, - 0x0, 0x1, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x7, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x3f, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xe5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xd4, 0x0, 0x0, 0x3, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, - 0xff, 0x80, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xf4, 0x0, 0xf, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xfd, - 0x0, 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0x40, - 0x2f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0xaa, 0xff, 0xff, 0xc0, 0x3f, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0xf0, 0x3f, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf4, 0x3f, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xf8, 0x7f, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1f, 0xfc, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x2f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0xf, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0xf, 0xff, 0xc0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xf8, 0x3, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xf0, 0x1, 0xff, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xe0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x0, 0x0, 0x0, - - /* U+F720 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xf8, 0x7f, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xc0, 0x7, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xfd, 0x0, 0x0, 0xbf, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x80, 0x0, - 0x0, 0x2f, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xff, 0xf4, 0x0, 0x2, 0xff, 0xff, 0xf4, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x40, - 0xf, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xf8, - 0xbf, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0xff, 0xfc, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xfd, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7f, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x2f, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xd2, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0x4f, 0xfe, 0xff, 0xd0, 0x7f, 0xff, - 0xfd, 0x0, 0x0, 0xbf, 0xff, 0xf8, 0xf, 0xfe, - 0xff, 0xd0, 0x7, 0xff, 0xff, 0xc0, 0x7, 0xff, - 0xff, 0xc0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0xbf, - 0xff, 0xf8, 0x7f, 0xff, 0xfd, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x1, - 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf4, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x3, 0xff, 0xff, 0x80, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0xf, 0xfe, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x0, 0xf, 0xfe, - 0xff, 0xf8, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x0, 0x7f, 0xfd, 0xbf, 0xff, 0x40, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x0, 0x2, 0xff, 0xfc, - 0x3f, 0xff, 0xf0, 0x0, 0x0, 0x3f, 0xf4, 0x0, - 0x0, 0x2f, 0xff, 0xfc, 0x1f, 0xff, 0xfe, 0x0, - 0x0, 0x3f, 0xf4, 0x0, 0x1, 0xff, 0xff, 0xf0, - 0x7, 0xff, 0xff, 0xd0, 0x0, 0x3f, 0xf4, 0x0, - 0xb, 0xff, 0xff, 0x80, 0x0, 0x7f, 0xff, 0xfd, - 0x0, 0x3f, 0xf4, 0x0, 0xbf, 0xff, 0xfc, 0x0, - 0x0, 0xb, 0xff, 0xff, 0x80, 0x3f, 0xf4, 0x7, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xf8, 0x3f, 0xf4, 0x3f, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xff, 0xff, 0x7f, 0xfa, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1b, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F8C7 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0xa, 0x40, 0x0, 0x0, - 0xf, 0xf4, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x3, 0xfd, 0x0, 0x0, 0x2, 0xff, 0xc0, - 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0x7f, - 0xf0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x0, 0x0, - 0xff, 0xd0, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, - 0xf, 0xff, 0x40, 0x0, 0x0, 0xf, 0xfd, 0x0, - 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x2, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x1, - 0xff, 0xf0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0xf, 0xfd, 0x0, 0x0, 0x0, 0xb, 0xff, 0x80, - 0xb, 0xff, 0x40, 0x0, 0x0, 0x0, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xd0, 0x1f, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0x2, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x3f, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0x43, 0xff, 0x40, 0x0, 0x0, - 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x3f, - 0xf8, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0xfc, 0xbf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x1, - 0xff, 0xcb, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0xbf, - 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xcf, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xfc, 0xbf, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0xbf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xcb, - 0xfe, 0x0, 0x0, 0x0, 0x0, 0x2, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xfc, 0xbf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xc7, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, - 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0x83, 0xff, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xf4, 0x3f, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, - 0x1, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf0, 0xf, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xfe, 0x0, 0xbf, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xc0, 0x7, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x3f, - 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xff, 0x0, 0x0, 0xff, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xe0, 0x0, 0xb, 0xff, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x0, - 0x3f, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0x40, 0x0, 0x0, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xe0, 0x0, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xbf, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xc0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xe4, - 0x0, 0x0, 0x2, 0xff, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xff, 0xff, 0xfe, 0xa6, 0xaf, - 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xf9, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xaf, 0xfe, 0x90, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+FFF75 "󿽵" */ - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x54, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x4f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xcf, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf, 0xfd, 0xff, 0xd0, 0x2, 0xf0, - 0x0, 0x0, 0x2f, 0x0, 0x0, 0x3, 0xf0, 0x0, - 0xff, 0xdf, 0xfd, 0x0, 0x3f, 0x80, 0x0, 0x3, - 0xf8, 0x0, 0x0, 0x7f, 0x80, 0xf, 0xfd, 0xff, - 0xd0, 0x3, 0xf8, 0x0, 0x0, 0x3f, 0x80, 0x0, - 0x7, 0xf4, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x1e, - 0x0, 0x0, 0x1, 0xe0, 0x0, 0x0, 0x2e, 0x0, - 0xf, 0xfd, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xdf, - 0xfe, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0xf, 0xfd, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, - 0xff, 0xe4, 0x0, 0x0, 0x7f, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x6, 0xff, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x7, - 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0xf, - 0xfd, 0x0, 0x0, 0x0, 0x1b, 0xff, 0xff, 0xff, - 0x40, 0x0, 0xf8, 0x0, 0x0, 0xff, 0xd0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xfe, 0x40, 0x0, 0x2f, - 0xc0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x6f, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x2, 0xfc, 0x0, 0x1, - 0xff, 0xd0, 0x0, 0xbf, 0xff, 0xff, 0xf8, 0x0, - 0x0, 0x0, 0xb, 0x40, 0x0, 0x7f, 0xfc, 0x0, - 0xbf, 0xff, 0xff, 0xf4, 0x0, 0x2f, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0x80, 0x7f, 0xff, 0xff, - 0xe0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xd0, 0x0, 0x0, - 0x3f, 0x80, 0x0, 0x6, 0xff, 0xff, 0xfd, 0x3, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x1, 0xe0, 0x0, - 0x1b, 0xff, 0xff, 0xff, 0x40, 0xbf, 0xfe, 0x40, - 0xf, 0xc0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0x80, 0xf, 0xff, 0x0, 0x1, 0xfd, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0x40, 0x0, - 0xff, 0xe0, 0x0, 0x1f, 0xd0, 0x0, 0x1, 0xbf, - 0xff, 0xff, 0xfd, 0x0, 0x0, 0xf, 0xfe, 0x0, - 0x0, 0xb8, 0x0, 0x6, 0xff, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xd1, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0xff, 0xdf, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, - 0xd0, 0x1, 0xe0, 0x0, 0x0, 0x1e, 0x0, 0x0, - 0x2, 0xe0, 0x0, 0xff, 0xdf, 0xfd, 0x0, 0x3f, - 0x80, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x7f, 0x40, - 0xf, 0xfd, 0xff, 0xd0, 0x3, 0xf8, 0x0, 0x0, - 0x3f, 0x80, 0x0, 0x7, 0xf8, 0x0, 0xff, 0xdf, - 0xfd, 0x0, 0x2f, 0x0, 0x0, 0x2, 0xf0, 0x0, - 0x0, 0x3f, 0x0, 0xf, 0xfd, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xdb, 0xff, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0x7f, 0xfe, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0xff, 0xd3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x1, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 1024, .box_w = 38, .box_h = 38, .ofs_x = 13, .ofs_y = 13}, - {.bitmap_index = 361, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 955, .adv_w = 1024, .box_w = 32, .box_h = 52, .ofs_x = 14, .ofs_y = 6}, - {.bitmap_index = 1371, .adv_w = 1024, .box_w = 38, .box_h = 53, .ofs_x = 13, .ofs_y = 5}, - {.bitmap_index = 1875, .adv_w = 1024, .box_w = 58, .box_h = 60, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 2745, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 3339, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 4068, .adv_w = 1024, .box_w = 30, .box_h = 18, .ofs_x = 17, .ofs_y = 24}, - {.bitmap_index = 4203, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 4797, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 5526, .adv_w = 1024, .box_w = 48, .box_h = 48, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 6102, .adv_w = 1024, .box_w = 32, .box_h = 48, .ofs_x = 16, .ofs_y = 8}, - {.bitmap_index = 6486, .adv_w = 1024, .box_w = 42, .box_h = 47, .ofs_x = 11, .ofs_y = 8}, - {.bitmap_index = 6980, .adv_w = 1024, .box_w = 44, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 7464, .adv_w = 1024, .box_w = 36, .box_h = 36, .ofs_x = 14, .ofs_y = 14}, - {.bitmap_index = 7788, .adv_w = 1024, .box_w = 48, .box_h = 32, .ofs_x = 8, .ofs_y = 16}, - {.bitmap_index = 8172, .adv_w = 1024, .box_w = 12, .box_h = 44, .ofs_x = 26, .ofs_y = 10}, - {.bitmap_index = 8304, .adv_w = 1024, .box_w = 44, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 8788, .adv_w = 1024, .box_w = 62, .box_h = 46, .ofs_x = 1, .ofs_y = 8}, - {.bitmap_index = 9501, .adv_w = 1024, .box_w = 42, .box_h = 30, .ofs_x = 11, .ofs_y = 17}, - {.bitmap_index = 9816, .adv_w = 1024, .box_w = 49, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 10355, .adv_w = 1024, .box_w = 48, .box_h = 44, .ofs_x = 8, .ofs_y = 10}, - {.bitmap_index = 10883, .adv_w = 1024, .box_w = 44, .box_h = 54, .ofs_x = 10, .ofs_y = 5}, - {.bitmap_index = 11477, .adv_w = 1024, .box_w = 54, .box_h = 50, .ofs_x = 5, .ofs_y = 9}, - {.bitmap_index = 12152, .adv_w = 1024, .box_w = 52, .box_h = 54, .ofs_x = 6, .ofs_y = 5}, - {.bitmap_index = 12854, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 13583, .adv_w = 1024, .box_w = 40, .box_h = 54, .ofs_x = 12, .ofs_y = 5}, - {.bitmap_index = 14123, .adv_w = 1024, .box_w = 44, .box_h = 48, .ofs_x = 10, .ofs_y = 8}, - {.bitmap_index = 14651, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 15245, .adv_w = 1024, .box_w = 64, .box_h = 62, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 16237, .adv_w = 1024, .box_w = 48, .box_h = 48, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 16813, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 17542, .adv_w = 1024, .box_w = 48, .box_h = 48, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 18118, .adv_w = 1024, .box_w = 54, .box_h = 44, .ofs_x = 5, .ofs_y = 10}, - {.bitmap_index = 18712, .adv_w = 1024, .box_w = 54, .box_h = 49, .ofs_x = 5, .ofs_y = 7}, - {.bitmap_index = 19374, .adv_w = 1024, .box_w = 48, .box_h = 54, .ofs_x = 8, .ofs_y = 5}, - {.bitmap_index = 20022, .adv_w = 1024, .box_w = 44, .box_h = 54, .ofs_x = 10, .ofs_y = 5}, - {.bitmap_index = 20616, .adv_w = 1024, .box_w = 49, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 21155, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 21884, .adv_w = 1024, .box_w = 47, .box_h = 48, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 22448, .adv_w = 1024, .box_w = 48, .box_h = 48, .ofs_x = 8, .ofs_y = 8}, - {.bitmap_index = 23024, .adv_w = 1024, .box_w = 60, .box_h = 44, .ofs_x = 2, .ofs_y = 10}, - {.bitmap_index = 23684, .adv_w = 1024, .box_w = 44, .box_h = 44, .ofs_x = 10, .ofs_y = 10}, - {.bitmap_index = 24168, .adv_w = 1024, .box_w = 60, .box_h = 44, .ofs_x = 2, .ofs_y = 10}, - {.bitmap_index = 24828, .adv_w = 1024, .box_w = 48, .box_h = 54, .ofs_x = 8, .ofs_y = 5}, - {.bitmap_index = 25476, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5}, - {.bitmap_index = 26205, .adv_w = 1024, .box_w = 54, .box_h = 54, .ofs_x = 5, .ofs_y = 5} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1, - 0x1e1, 0x26a, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, - 0x48f, 0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, - 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, - 0x991, 0xa49, 0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, - 0xea1, 0xee3, 0xf4b, 0x1017, 0x15db, 0x1782 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57669, .range_length = 6019, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 46, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - }, - { - .range_start = 1048437, .range_length = 1, .glyph_id_start = 47, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 2, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_shared_64 = { -#else -lv_font_t material_symbols_shared_64 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 62, /*The maximum line height required by the font*/ - .base_line = -2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_SHARED_64*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_12.c b/Modules/lvgl-module/source-fonts/material_symbols_statusbar_12.c deleted file mode 100644 index 2da0fbd9f..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_12.c +++ /dev/null @@ -1,280 +0,0 @@ -/******************************************************************************* - * Size: 12 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 12 --font MaterialSymbolsRounded.ttf -r 0xF1DB,0xF15C,0xE322,0xE623,0xF057,0xF0B0,0xEBE4,0xEBD6,0xEBE1,0xF065,0xE1DA,0xF064,0xF257,0xF256,0xF255,0xF254,0xF253,0xF252,0xF24F,0xF250,0xE1A7,0xE60F,0xE1A8,0xE1A9,0xE1E0 --format lvgl -o source-fonts/material_symbols_statusbar_12.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_STATUSBAR_12 -#define MATERIAL_SYMBOLS_STATUSBAR_12 1 -#endif - -#if MATERIAL_SYMBOLS_STATUSBAR_12 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E1A7 "" */ - 0x1, 0x40, 0xb, 0x47, 0x2b, 0x7, 0xec, 0x7, - 0xc0, 0x1f, 0x1, 0xfb, 0x1c, 0x9d, 0x2, 0xd0, - 0x9, 0x0, - - /* U+E1A8 "" */ - 0x0, 0x20, 0x0, 0x7, 0x80, 0xd, 0x7a, 0x0, - 0x3b, 0xd0, 0x20, 0xf4, 0x82, 0xf, 0x48, 0x3, - 0xbd, 0x0, 0xd6, 0xa0, 0x0, 0x7c, 0x0, 0x2, - 0x0, - - /* U+E1A9 "" */ - 0x0, 0x14, 0x0, 0xd0, 0xb4, 0x0, 0xd2, 0xb0, - 0x0, 0xd6, 0xc0, 0x0, 0xd4, 0x0, 0x2, 0xd0, - 0x0, 0x1f, 0xd0, 0x1, 0xca, 0xd0, 0x0, 0x2e, - 0xd0, 0x0, 0x90, 0xc0, 0x0, 0x0, 0x0, - - /* U+E1DA "" */ - 0x50, 0x0, 0x0, 0x38, 0xff, 0x80, 0x2e, 0x0, - 0x78, 0xa3, 0x80, 0xe, 0x34, 0xe0, 0x1c, 0xd, - 0x38, 0x70, 0x3, 0x4e, 0x0, 0x0, 0xd7, 0x80, - 0x0, 0x3c, 0xe0, 0x0, 0x0, 0x34, 0x0, 0x0, - 0x0, - - /* U+E1E0 "" */ - 0x2, 0x0, 0x7, 0x80, 0x3, 0x0, 0x73, 0x3c, - 0xb3, 0x3c, 0x33, 0x18, 0x3f, 0xf4, 0x3, 0x0, - 0x3, 0x40, 0x3, 0x40, - - /* U+E322 "" */ - 0x0, 0x0, 0x0, 0x77, 0x40, 0x2e, 0xab, 0x3, - 0x45, 0x34, 0x77, 0xf3, 0x83, 0x77, 0x34, 0x75, - 0xa3, 0x82, 0x55, 0x70, 0x1b, 0xfe, 0x0, 0x11, - 0x0, - - /* U+E60F "" */ - 0x1, 0x40, 0x0, 0x2d, 0x0, 0x72, 0xb0, 0x1, - 0xfb, 0xc, 0x7, 0xc8, 0x80, 0x7c, 0x88, 0x1f, - 0xb0, 0xc7, 0x27, 0x40, 0x2, 0xd0, 0x0, 0x24, - 0x0, - - /* U+E623 "" */ - 0x7, 0xff, 0x1c, 0x3, 0x70, 0x43, 0xc5, 0xd7, - 0xc0, 0x43, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, - 0xc0, 0x3, 0xff, 0xff, - - /* U+EBD6 "" */ - 0x6, 0xff, 0x80, 0x3d, 0x0, 0xb8, 0xa0, 0x0, - 0xc, 0x30, 0x0, 0x28, 0x1d, 0xbd, 0xa0, 0x7, - 0xff, 0x80, 0x1, 0xfe, 0x0, 0x0, 0x78, 0x0, - 0x0, 0x0, 0x0, - - /* U+EBE1 "" */ - 0x6, 0xff, 0x80, 0x3d, 0x0, 0xb8, 0xa0, 0x0, - 0xc, 0x35, 0xfe, 0x28, 0x1f, 0xff, 0xe0, 0x7, - 0xff, 0x80, 0x1, 0xfe, 0x0, 0x0, 0x78, 0x0, - 0x0, 0x0, 0x0, - - /* U+EBE4 "" */ - 0x6, 0xff, 0x80, 0x3d, 0x0, 0xb8, 0xa0, 0x0, - 0xc, 0x30, 0x0, 0x28, 0x1c, 0x0, 0xa0, 0x7, - 0xba, 0x80, 0x1, 0xfe, 0x0, 0x0, 0x78, 0x0, - 0x0, 0x0, 0x0, - - /* U+F057 "" */ - 0x7, 0xff, 0x1c, 0x3, 0x70, 0x3, 0xc1, 0x43, - 0xc1, 0x43, 0xc1, 0x43, 0xc0, 0x3, 0xc0, 0x3, - 0xc0, 0x3, 0xff, 0xff, - - /* U+F064 "" */ - 0x6, 0xff, 0x80, 0x3d, 0x0, 0xb8, 0xa0, 0x0, - 0xd, 0x30, 0x0, 0x18, 0x1c, 0x0, 0x0, 0x7, - 0x0, 0xe8, 0x1, 0xd0, 0xb0, 0x0, 0x78, 0xe8, - 0x0, 0x0, 0x0, - - /* U+F065 "" */ - 0x6, 0xff, 0x80, 0x3f, 0xff, 0xf8, 0xbf, 0xff, - 0xfc, 0x3f, 0xff, 0xf8, 0x1f, 0xff, 0xe0, 0x7, - 0xff, 0x80, 0x1, 0xfe, 0x0, 0x0, 0x78, 0x0, - 0x0, 0x0, 0x0, - - /* U+F0B0 "" */ - 0x6, 0xff, 0x80, 0x3d, 0x0, 0xb8, 0xa0, 0x0, - 0xc, 0x30, 0x0, 0x28, 0x1c, 0x0, 0xa0, 0x7, - 0x2, 0x80, 0x1, 0xda, 0x0, 0x0, 0x78, 0x0, - 0x0, 0x0, 0x0, - - /* U+F15C "" */ - 0x0, 0xbd, 0x0, 0x3, 0x43, 0x40, 0x9, 0x0, - 0xc0, 0x38, 0x0, 0xd0, 0xa0, 0x0, 0x68, 0x90, - 0x0, 0xc, 0x70, 0x0, 0xc, 0x1f, 0xff, 0xf4, - - /* U+F1DB "" */ - 0xb, 0xe0, 0x34, 0x1c, 0x90, 0x6, 0xc3, 0xc3, - 0xc3, 0xc3, 0x90, 0x6, 0x30, 0xc, 0x1c, 0x34, - 0xb, 0xe0, 0x1, 0x40, - - /* U+F24F "" */ - 0x7f, 0xff, 0xe0, 0x96, 0xaa, 0x70, 0xaf, 0xff, - 0xb9, 0xaf, 0xff, 0xb9, 0x96, 0xaa, 0x70, 0x7f, - 0xff, 0xe0, - - /* U+F250 "" */ - 0x7f, 0xff, 0x0, 0x96, 0xa4, 0x20, 0xaf, 0xfc, - 0xf4, 0xaf, 0xf0, 0xb4, 0x96, 0x40, 0x20, 0x7f, - 0xfd, 0x0, - - /* U+F252 "" */ - 0x7f, 0xff, 0xe0, 0x96, 0xa9, 0x30, 0xaf, 0xff, - 0x39, 0xaf, 0xff, 0x39, 0x96, 0xa9, 0x30, 0x7f, - 0xff, 0xe0, - - /* U+F253 "" */ - 0x7f, 0xff, 0xe0, 0x96, 0xa4, 0x30, 0xaf, 0xfc, - 0x39, 0xaf, 0xfc, 0x39, 0x96, 0xa4, 0x30, 0x7f, - 0xff, 0xe0, - - /* U+F254 "" */ - 0x7f, 0xff, 0xe0, 0x96, 0x90, 0x30, 0xaf, 0xf0, - 0x39, 0xaf, 0xf0, 0x39, 0x96, 0x90, 0x30, 0x7f, - 0xff, 0xe0, - - /* U+F255 "" */ - 0x7f, 0xff, 0xe0, 0x96, 0x40, 0x30, 0xaf, 0xc0, - 0x39, 0xaf, 0xc0, 0x39, 0x96, 0x40, 0x30, 0x7f, - 0xff, 0xe0, - - /* U+F256 "" */ - 0x7f, 0xff, 0xe0, 0x95, 0x0, 0x30, 0xaf, 0x0, - 0x39, 0xaf, 0x0, 0x39, 0x95, 0x0, 0x30, 0x7f, - 0xff, 0xe0, - - /* U+F257 "" */ - 0x7f, 0xff, 0xe0, 0x94, 0x0, 0x30, 0xac, 0x0, - 0x39, 0xac, 0x0, 0x39, 0x94, 0x0, 0x30, 0x7f, - 0xff, 0xe0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 192, .box_w = 7, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 18, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 43, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 74, .adv_w = 192, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 107, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 127, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 152, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 177, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 197, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 224, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 251, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 278, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 298, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 325, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 352, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 379, .adv_w = 192, .box_w = 12, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 403, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 423, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 441, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 459, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 477, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 495, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 513, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 531, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 549, .adv_w = 192, .box_w = 12, .box_h = 6, .ofs_x = 0, .ofs_y = 3} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x1, 0x2, 0x33, 0x39, 0x17b, 0x468, 0x47c, - 0xa2f, 0xa3a, 0xa3d, 0xeb0, 0xebd, 0xebe, 0xf09, 0xfb5, - 0x1034, 0x10a8, 0x10a9, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, - 0x10b0 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57767, .range_length = 4273, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 25, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_statusbar_12 = { -#else -lv_font_t material_symbols_statusbar_12 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 11, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_STATUSBAR_12*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_16.c b/Modules/lvgl-module/source-fonts/material_symbols_statusbar_16.c deleted file mode 100644 index 85af971ee..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_16.c +++ /dev/null @@ -1,326 +0,0 @@ -/******************************************************************************* - * Size: 16 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 16 --font MaterialSymbolsRounded.ttf -r 0xF1DB,0xF15C,0xE322,0xE623,0xF057,0xF0B0,0xEBE4,0xEBD6,0xEBE1,0xF065,0xE1DA,0xF064,0xF257,0xF256,0xF255,0xF254,0xF253,0xF252,0xF24F,0xF250,0xE1A7,0xE60F,0xE1A8,0xE1A9,0xE1E0 --format lvgl -o source-fonts/material_symbols_statusbar_16.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_STATUSBAR_16 -#define MATERIAL_SYMBOLS_STATUSBAR_16 1 -#endif - -#if MATERIAL_SYMBOLS_STATUSBAR_16 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E1A7 "" */ - 0x0, 0x40, 0x0, 0x3c, 0x1, 0xf, 0xc1, 0xd3, - 0x6c, 0x1d, 0xef, 0x1, 0xff, 0x0, 0x1f, 0x0, - 0xf, 0xd0, 0xf, 0xfd, 0xf, 0x36, 0xcb, 0xe, - 0xe0, 0x3, 0xe0, 0x0, 0xe0, 0x0, 0x0, 0x0, - - /* U+E1A8 "" */ - 0x0, 0x10, 0x0, 0x0, 0x3c, 0x0, 0x14, 0x3f, - 0x0, 0x1d, 0x36, 0xc0, 0x7, 0x77, 0xc0, 0x1, - 0xff, 0x0, 0xb0, 0xbc, 0xe, 0x60, 0xfd, 0x9, - 0x3, 0xff, 0x40, 0xf, 0x36, 0xc0, 0x2c, 0x3b, - 0x80, 0x0, 0x3e, 0x0, 0x0, 0x38, 0x0, 0x0, - 0x0, 0x0, - - /* U+E1A9 "" */ - 0x0, 0x4, 0x0, 0x38, 0x3, 0xc0, 0x7, 0x80, - 0xfc, 0x0, 0x78, 0x36, 0xc0, 0x7, 0x8a, 0xf0, - 0x0, 0x78, 0xb0, 0x0, 0x7, 0x80, 0x0, 0x0, - 0xf8, 0x0, 0x0, 0xff, 0x80, 0x0, 0xf3, 0xf8, - 0x0, 0xb0, 0xef, 0x80, 0x0, 0x3e, 0x78, 0x0, - 0xe, 0x7, 0x40, 0x0, 0x0, 0x40, - - /* U+E1DA "" */ - 0x0, 0x0, 0x0, 0x0, 0x34, 0x1, 0x40, 0x0, - 0x1d, 0x2f, 0xfe, 0x40, 0x1f, 0x40, 0x6, 0xf0, - 0x79, 0xd0, 0x0, 0x2d, 0xb4, 0x74, 0x0, 0x1d, - 0x2d, 0x1d, 0x0, 0x74, 0xb, 0x47, 0x41, 0xd0, - 0x2, 0xd1, 0xd1, 0x40, 0x0, 0xb4, 0x74, 0x0, - 0x0, 0x2d, 0x7d, 0x0, 0x0, 0xb, 0xd7, 0x40, - 0x0, 0x1, 0x41, 0xd0, 0x0, 0x0, 0x0, 0x70, - 0x0, 0x0, 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0xe, 0x0, 0x2, 0xf0, 0x0, - 0xe, 0x0, 0x10, 0xd1, 0x5b, 0xcd, 0x3e, 0x78, - 0xd3, 0xe3, 0x4d, 0x1c, 0x39, 0xe6, 0xc2, 0xff, - 0xf4, 0x0, 0xd0, 0x0, 0xe, 0x0, 0x1, 0xf0, - 0x0, 0xe, 0x0, - - /* U+E322 "" */ - 0x0, 0x21, 0x40, 0x0, 0x6e, 0xf5, 0x0, 0xff, - 0xff, 0xd0, 0x34, 0x0, 0x34, 0x3d, 0x3f, 0x8f, - 0x87, 0x4d, 0xb3, 0x81, 0xd3, 0x6c, 0xe0, 0xf4, - 0xfe, 0x3e, 0xd, 0x0, 0xd, 0x3, 0x95, 0x57, - 0x40, 0x7f, 0xff, 0xc0, 0x0, 0xca, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+E60F "" */ - 0x0, 0x40, 0x0, 0x0, 0xf0, 0x0, 0x50, 0xfc, - 0x0, 0x74, 0xdb, 0x0, 0x2d, 0xdf, 0x9, 0xb, - 0xfc, 0x7, 0x2, 0xf0, 0xd3, 0x3, 0xf4, 0xd3, - 0xf, 0xfd, 0x7, 0x3c, 0xdb, 0x9, 0xb0, 0xee, - 0x0, 0x0, 0xf8, 0x0, 0x0, 0xe0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E623 "" */ - 0x0, 0x15, 0x54, 0x1, 0xff, 0xfc, 0x7, 0x80, - 0xd, 0x1e, 0x0, 0xd, 0x38, 0xdd, 0xdd, 0x70, - 0xdd, 0xdd, 0x70, 0x0, 0xd, 0x70, 0x0, 0xd, - 0x70, 0x0, 0xd, 0x70, 0x0, 0xd, 0x70, 0x0, - 0xd, 0x70, 0x0, 0xd, 0x7a, 0xaa, 0xad, 0x2a, - 0xaa, 0xa8, - - /* U+EBD6 "" */ - 0x0, 0x1, 0x40, 0x0, 0x1, 0xbf, 0xff, 0x40, - 0xf, 0x90, 0x6, 0xf4, 0x3c, 0x0, 0x0, 0x2d, - 0x38, 0x0, 0x0, 0x1d, 0x1e, 0x0, 0x0, 0x78, - 0x7, 0x8b, 0xe5, 0xe0, 0x1, 0xff, 0xff, 0x80, - 0x0, 0x7f, 0xfe, 0x0, 0x0, 0x1f, 0xf8, 0x0, - 0x0, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x40, 0x0, - - /* U+EBE1 "" */ - 0x0, 0x1, 0x40, 0x0, 0x1, 0xbf, 0xff, 0x40, - 0xf, 0xd0, 0x6, 0xf4, 0x3d, 0x0, 0x0, 0x2d, - 0x34, 0x0, 0x0, 0xd, 0x1d, 0x2f, 0xf9, 0x38, - 0x7, 0xff, 0xff, 0xe0, 0x1, 0xff, 0xff, 0xc0, - 0x0, 0xbf, 0xff, 0x0, 0x0, 0x2f, 0xfc, 0x0, - 0x0, 0xb, 0xf0, 0x0, 0x0, 0x1, 0x80, 0x0, - - /* U+EBE4 "" */ - 0x0, 0x1, 0x40, 0x0, 0x1, 0xbf, 0xff, 0x40, - 0xf, 0x90, 0x6, 0xf4, 0x38, 0x0, 0x0, 0x2d, - 0x38, 0x0, 0x0, 0x1d, 0x1e, 0x0, 0x0, 0x78, - 0x7, 0x80, 0x1, 0xe0, 0x0, 0xe6, 0x97, 0x80, - 0x0, 0x3f, 0xfd, 0x0, 0x0, 0xf, 0xf4, 0x0, - 0x0, 0x3, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F057 "" */ - 0x0, 0x15, 0x54, 0x1, 0xff, 0xfc, 0x7, 0x80, - 0xd, 0x1e, 0x0, 0xd, 0x38, 0x0, 0xd, 0x70, - 0x28, 0xd, 0x70, 0x28, 0xd, 0x70, 0x14, 0xd, - 0x70, 0x0, 0xd, 0x70, 0x28, 0xd, 0x70, 0x0, - 0xd, 0x70, 0x0, 0xd, 0x7a, 0xaa, 0xad, 0x2a, - 0xaa, 0xa8, - - /* U+F064 "" */ - 0x0, 0x1, 0x40, 0x0, 0x1, 0xbf, 0xff, 0x40, - 0xf, 0x90, 0x6, 0xf4, 0x38, 0x0, 0x0, 0x2d, - 0x38, 0x0, 0x0, 0x1d, 0x1e, 0x0, 0x0, 0x28, - 0x7, 0x80, 0x0, 0x0, 0x1, 0xe0, 0x2, 0x18, - 0x0, 0x78, 0x3, 0xf4, 0x0, 0x1e, 0x41, 0xf0, - 0x0, 0x7, 0xd3, 0x78, 0x0, 0x0, 0x0, 0x0, - - /* U+F065 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfe, 0x0, - 0xb, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfc, - 0x3f, 0xff, 0xff, 0xfd, 0x2f, 0xff, 0xff, 0xfc, - 0xb, 0xff, 0xff, 0xf0, 0x2, 0xff, 0xff, 0xc0, - 0x0, 0xbf, 0xff, 0x0, 0x0, 0x2f, 0xfc, 0x0, - 0x0, 0xb, 0xf0, 0x0, 0x0, 0x1, 0x80, 0x0, - - /* U+F0B0 "" */ - 0x0, 0x1, 0x40, 0x0, 0x1, 0xbf, 0xff, 0x40, - 0xf, 0x90, 0x6, 0xf4, 0x3c, 0x0, 0x0, 0x2d, - 0x38, 0x0, 0x0, 0x1d, 0x1e, 0x0, 0x0, 0x78, - 0x7, 0x80, 0x1, 0xe0, 0x1, 0xe0, 0x7, 0x80, - 0x0, 0x78, 0x1e, 0x0, 0x0, 0x1e, 0x78, 0x0, - 0x0, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x40, 0x0, - - /* U+F15C "" */ - 0x0, 0x1, 0x40, 0x0, 0x0, 0x2f, 0xf4, 0x0, - 0x0, 0xb4, 0x2d, 0x0, 0x1, 0xc0, 0xb, 0x0, - 0x7, 0xc0, 0x3, 0x40, 0x2e, 0x0, 0x3, 0xd0, - 0x34, 0x0, 0x2, 0xb8, 0x70, 0x0, 0x0, 0x1c, - 0x30, 0x0, 0x0, 0xd, 0x3c, 0x0, 0x0, 0x2c, - 0xf, 0xff, 0xff, 0xf4, 0x0, 0x55, 0x55, 0x40, - - /* U+F1DB "" */ - 0x0, 0x55, 0x0, 0x3, 0xff, 0xc0, 0xe, 0x0, - 0xb0, 0x3c, 0x0, 0x3c, 0x34, 0x14, 0x1c, 0x70, - 0x3c, 0xd, 0x70, 0x3c, 0xd, 0x34, 0x0, 0x1c, - 0x2c, 0x0, 0x38, 0xe, 0x0, 0xb0, 0x3, 0x41, - 0xc0, 0x1, 0xd7, 0x40, 0x0, 0x7d, 0x0, 0x0, - 0x0, 0x0, - - /* U+F24F "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xff, 0xfd, 0xd4, 0x77, 0xff, 0xfd, 0xdc, - 0x77, 0xff, 0xfd, 0xdc, 0x77, 0xff, 0xfd, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F250 "" */ - 0x2f, 0xff, 0xfc, 0x0, 0x35, 0x55, 0x50, 0x50, - 0x73, 0xff, 0xe1, 0xc0, 0x77, 0xff, 0xc3, 0xe8, - 0x77, 0xff, 0x46, 0xf4, 0x73, 0xfe, 0x0, 0xe0, - 0x35, 0x55, 0x50, 0xc0, 0x2f, 0xff, 0xf0, 0x0, - - /* U+F252 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xff, 0xf4, 0xd4, 0x77, 0xff, 0xf4, 0xdc, - 0x77, 0xff, 0xf4, 0xdc, 0x77, 0xff, 0xf4, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F253 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xff, 0xc0, 0xd4, 0x77, 0xff, 0xc0, 0xdc, - 0x77, 0xff, 0xc0, 0xdc, 0x77, 0xff, 0xc0, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F254 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xfe, 0x0, 0xd4, 0x77, 0xff, 0x0, 0xdc, - 0x77, 0xff, 0x0, 0xdc, 0x77, 0xff, 0x0, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F255 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xf4, 0x0, 0xd4, 0x77, 0xf8, 0x0, 0xdc, - 0x77, 0xf8, 0x0, 0xdc, 0x77, 0xf8, 0x0, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F256 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x73, 0xc0, 0x0, 0xd4, 0x77, 0xd0, 0x0, 0xdc, - 0x77, 0xd0, 0x0, 0xdc, 0x77, 0xc0, 0x0, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80, - - /* U+F257 "" */ - 0x2f, 0xff, 0xff, 0x80, 0x35, 0x55, 0x55, 0xd0, - 0x72, 0x0, 0x0, 0xd4, 0x77, 0x0, 0x0, 0xdc, - 0x77, 0x0, 0x0, 0xdc, 0x77, 0x0, 0x0, 0xd8, - 0x35, 0x55, 0x55, 0xd0, 0x2f, 0xff, 0xff, 0x80 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 256, .box_w = 9, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 32, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 74, .adv_w = 256, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 120, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 180, .adv_w = 256, .box_w = 10, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 215, .adv_w = 256, .box_w = 13, .box_h = 13, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 258, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 300, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 342, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 390, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 438, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 486, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 528, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 576, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 624, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 672, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 720, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1}, - {.bitmap_index = 762, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 794, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 826, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 858, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 890, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 922, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 954, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 986, .adv_w = 256, .box_w = 16, .box_h = 8, .ofs_x = 0, .ofs_y = 4} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x1, 0x2, 0x33, 0x39, 0x17b, 0x468, 0x47c, - 0xa2f, 0xa3a, 0xa3d, 0xeb0, 0xebd, 0xebe, 0xf09, 0xfb5, - 0x1034, 0x10a8, 0x10a9, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, - 0x10b0 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57767, .range_length = 4273, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 25, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_statusbar_16 = { -#else -lv_font_t material_symbols_statusbar_16 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 15, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_STATUSBAR_16*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_20.c b/Modules/lvgl-module/source-fonts/material_symbols_statusbar_20.c deleted file mode 100644 index dbb2f4869..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_20.c +++ /dev/null @@ -1,394 +0,0 @@ -/******************************************************************************* - * Size: 20 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 20 --font MaterialSymbolsRounded.ttf -r 0xF1DB,0xF15C,0xE322,0xE623,0xF057,0xF0B0,0xEBE4,0xEBD6,0xEBE1,0xF065,0xE1DA,0xF064,0xF257,0xF256,0xF255,0xF254,0xF253,0xF252,0xF24F,0xF250,0xE1A7,0xE60F,0xE1A8,0xE1A9,0xE1E0 --format lvgl -o source-fonts/material_symbols_statusbar_20.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_STATUSBAR_20 -#define MATERIAL_SYMBOLS_STATUSBAR_20 1 -#endif - -#if MATERIAL_SYMBOLS_STATUSBAR_20 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E1A7 "" */ - 0x0, 0x28, 0x0, 0x0, 0xf8, 0x1, 0x3, 0xf8, - 0x1e, 0xe, 0xb8, 0x2e, 0x38, 0xf0, 0x2e, 0xfb, - 0x80, 0x2f, 0xf8, 0x0, 0x2f, 0x80, 0x0, 0xbe, - 0x0, 0xb, 0xfe, 0x0, 0xbb, 0xee, 0xb, 0x8e, - 0x3c, 0x78, 0x3a, 0xe0, 0x40, 0xfe, 0x0, 0x3, - 0xe0, 0x0, 0xa, 0x0, - - /* U+E1A8 "" */ - 0x0, 0x2, 0x80, 0x0, 0x0, 0x3, 0xe0, 0x0, - 0x1, 0x3, 0xf8, 0x0, 0x7, 0x83, 0xae, 0x0, - 0x2, 0xe3, 0x8f, 0x0, 0x0, 0xbb, 0xee, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x3d, 0xb, 0xe0, 0x7c, - 0x3d, 0xb, 0xe0, 0x7c, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0xbb, 0xee, 0x0, 0x2, 0xe3, 0x8f, 0x0, - 0x7, 0x83, 0xae, 0x0, 0x1, 0x3, 0xf8, 0x0, - 0x0, 0x3, 0xe0, 0x0, 0x0, 0x2, 0x80, 0x0, - - /* U+E1A9 "" */ - 0x0, 0x0, 0xa0, 0x0, 0x1d, 0x0, 0x3e, 0x0, - 0x3, 0xd0, 0xf, 0xe0, 0x0, 0x3d, 0x3, 0xae, - 0x0, 0x3, 0xd0, 0xe3, 0xc0, 0x0, 0x3d, 0x1a, - 0xe0, 0x0, 0x3, 0xd1, 0xe0, 0x0, 0x0, 0x3d, - 0x0, 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x2, - 0xfd, 0x0, 0x0, 0x2, 0xef, 0xd0, 0x0, 0x2, - 0xe3, 0xfd, 0x0, 0x1, 0xe0, 0xeb, 0xd0, 0x0, - 0x10, 0x3f, 0xbd, 0x0, 0x0, 0xf, 0x83, 0xd0, - 0x0, 0x2, 0x80, 0x3c, 0x0, 0x0, 0x0, 0x1, - 0x0, - - /* U+E1DA "" */ - 0x34, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x1, 0xaa, - 0x40, 0x0, 0xf, 0x47, 0xff, 0xfd, 0x0, 0xb, - 0xd0, 0x0, 0x6f, 0xd0, 0x3e, 0xf4, 0x0, 0x1, - 0xf8, 0xb8, 0x3d, 0x0, 0x0, 0x3d, 0x3d, 0xf, - 0x40, 0x0, 0xbc, 0xf, 0x43, 0xd0, 0x2, 0xf0, - 0x3, 0xd0, 0xf4, 0xb, 0xc0, 0x0, 0xf4, 0x3d, - 0xf, 0x0, 0x0, 0x3d, 0xf, 0x40, 0x0, 0x0, - 0xf, 0x43, 0xd0, 0x0, 0x0, 0x3, 0xd7, 0xf4, - 0x0, 0x0, 0x0, 0xff, 0x3d, 0x0, 0x0, 0x0, - 0x3c, 0xf, 0x40, 0x0, 0x0, 0x0, 0x3, 0xd0, - 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x7d, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x38, 0x0, 0x10, - 0x38, 0x14, 0xbc, 0x38, 0x7f, 0xfd, 0x38, 0x7f, - 0x7c, 0x38, 0x7f, 0x38, 0x38, 0x2c, 0x3d, 0x7d, - 0x6c, 0x2f, 0xff, 0xfc, 0x5, 0x7d, 0x50, 0x0, - 0x38, 0x0, 0x0, 0x3c, 0x0, 0x0, 0xbe, 0x0, - 0x0, 0x7d, 0x0, 0x0, 0x0, 0x0, - - /* U+E322 "" */ - 0x0, 0x0, 0x10, 0x0, 0x0, 0x2c, 0x34, 0x0, - 0x2, 0xbe, 0xfe, 0x80, 0xf, 0xff, 0xff, 0xe0, - 0xe, 0x0, 0x0, 0xe0, 0x2e, 0xa, 0x90, 0xf4, - 0x7e, 0x2f, 0xf4, 0xfd, 0xe, 0x2c, 0x74, 0xf0, - 0xe, 0x2c, 0x74, 0xf0, 0x7e, 0x2f, 0xf4, 0xfd, - 0x2e, 0xa, 0xa0, 0xf4, 0xe, 0x0, 0x0, 0xe0, - 0xf, 0xaa, 0xaa, 0xe0, 0x7, 0xff, 0xff, 0xc0, - 0x0, 0x2c, 0x34, 0x0, 0x0, 0x4, 0x20, 0x0, - - /* U+E60F "" */ - 0x0, 0x1c, 0x0, 0x0, 0x0, 0x2f, 0x0, 0x0, - 0x10, 0x2f, 0xc0, 0x0, 0x3c, 0x2d, 0xf0, 0x0, - 0x1f, 0x2c, 0xb8, 0x28, 0x7, 0xee, 0xf0, 0x2c, - 0x1, 0xff, 0xc1, 0xc, 0x0, 0x7f, 0xb, 0xd, - 0x0, 0x7f, 0xb, 0xd, 0x1, 0xff, 0xc1, 0xc, - 0x7, 0xee, 0xf0, 0x2c, 0x1f, 0x2c, 0xb8, 0x28, - 0x3c, 0x2d, 0xf0, 0x0, 0x10, 0x2f, 0xc0, 0x0, - 0x0, 0x2f, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, - - /* U+E623 "" */ - 0x0, 0x1a, 0xaa, 0x40, 0xb, 0xff, 0xfd, 0x2, - 0xe0, 0x0, 0xe0, 0xb8, 0x0, 0xe, 0x2e, 0x10, - 0x4, 0xe7, 0x87, 0x3c, 0xce, 0xb0, 0x73, 0xdc, - 0xeb, 0x7, 0x3c, 0xce, 0xb0, 0x0, 0x0, 0xeb, - 0x0, 0x0, 0xe, 0xb0, 0x0, 0x0, 0xeb, 0x0, - 0x0, 0xe, 0xb0, 0x0, 0x0, 0xeb, 0x0, 0x0, - 0xe, 0xb0, 0x0, 0x0, 0xeb, 0x55, 0x55, 0x5e, - 0x7f, 0xff, 0xff, 0xd0, 0x55, 0x55, 0x50, - - /* U+EBD6 "" */ - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x7, 0xf9, 0x0, 0x6f, 0xd0, 0x2f, - 0x40, 0x0, 0x1, 0xf8, 0x38, 0x0, 0x0, 0x0, - 0x2c, 0x3d, 0x0, 0x0, 0x0, 0x7c, 0xf, 0x40, - 0x0, 0x1, 0xf0, 0x3, 0xd1, 0xbe, 0x47, 0xc0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, - 0xfc, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+EBE1 "" */ - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x7, 0xf9, 0x0, 0x6f, 0xd0, 0x2f, - 0x40, 0x0, 0x1, 0xf8, 0x38, 0x0, 0x0, 0x0, - 0x2c, 0x3d, 0x1, 0xaa, 0x40, 0x7c, 0xf, 0x5f, - 0xff, 0xf5, 0xf0, 0x3, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, - 0xfc, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+EBE4 "" */ - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x7, 0xf9, 0x0, 0x6f, 0xd0, 0x2f, - 0x40, 0x0, 0x1, 0xf8, 0x38, 0x0, 0x0, 0x0, - 0x2c, 0x3d, 0x0, 0x0, 0x0, 0x7c, 0xf, 0x40, - 0x0, 0x1, 0xf0, 0x3, 0xd0, 0x0, 0x7, 0xc0, - 0x0, 0xf4, 0x0, 0x1f, 0x0, 0x0, 0x3e, 0xff, - 0xbc, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+F057 "" */ - 0x0, 0x1a, 0xaa, 0x40, 0xb, 0xff, 0xfd, 0x2, - 0xe0, 0x0, 0xe0, 0xb8, 0x0, 0xe, 0x2e, 0x0, - 0x0, 0xe7, 0x80, 0x50, 0xe, 0xb0, 0xf, 0x0, - 0xeb, 0x0, 0xf0, 0xe, 0xb0, 0xf, 0x0, 0xeb, - 0x0, 0xa0, 0xe, 0xb0, 0x0, 0x0, 0xeb, 0x0, - 0x0, 0xe, 0xb0, 0xa, 0x0, 0xeb, 0x0, 0x0, - 0xe, 0xb0, 0x0, 0x0, 0xeb, 0x55, 0x55, 0x5e, - 0x7f, 0xff, 0xff, 0xd0, 0x55, 0x55, 0x50, - - /* U+F064 "" */ - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x7, 0xf9, 0x0, 0x6f, 0xd0, 0x2f, - 0x40, 0x0, 0x1, 0xf8, 0x38, 0x0, 0x0, 0x0, - 0x2c, 0x3d, 0x0, 0x0, 0x0, 0x7c, 0xf, 0x40, - 0x0, 0x0, 0xb0, 0x3, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, - 0x2d, 0xb4, 0x0, 0xf, 0x40, 0xf, 0xe0, 0x0, - 0x3, 0xd0, 0xb, 0xd0, 0x0, 0x0, 0xfe, 0x1f, - 0xf0, 0x0, 0x0, 0x3c, 0x18, 0x20, - - /* U+F065 "" */ - 0x0, 0x1, 0x69, 0x40, 0x0, 0x0, 0x7f, 0xff, - 0xfd, 0x0, 0x7, 0xff, 0xff, 0xff, 0xd0, 0x2f, - 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, - 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, - 0xff, 0xff, 0xf0, 0x3, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, - 0xfc, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+F0B0 "" */ - 0x0, 0x1, 0xaa, 0x40, 0x0, 0x0, 0xbf, 0xff, - 0xfe, 0x0, 0x7, 0xf9, 0x0, 0x6f, 0xd0, 0x2f, - 0x40, 0x0, 0x1, 0xf8, 0x38, 0x0, 0x0, 0x0, - 0x2c, 0x3d, 0x0, 0x0, 0x0, 0x7c, 0xf, 0x40, - 0x0, 0x1, 0xf0, 0x3, 0xd0, 0x0, 0x7, 0xc0, - 0x0, 0xf4, 0x0, 0x1f, 0x0, 0x0, 0x3d, 0x0, - 0x7c, 0x0, 0x0, 0xf, 0x41, 0xf0, 0x0, 0x0, - 0x3, 0xd7, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+F15C "" */ - 0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xd0, 0x0, 0x0, 0x2f, 0x41, 0xf4, 0x0, 0x0, - 0x3c, 0x0, 0x3c, 0x0, 0x0, 0xb0, 0x0, 0x1d, - 0x0, 0x7, 0xf0, 0x0, 0xe, 0x0, 0x1f, 0x40, - 0x0, 0xf, 0x80, 0x3c, 0x0, 0x0, 0xf, 0xf0, - 0x38, 0x0, 0x0, 0x0, 0x3c, 0x38, 0x0, 0x0, - 0x0, 0x2c, 0x3c, 0x0, 0x0, 0x0, 0x2c, 0x1e, - 0x0, 0x0, 0x0, 0x7c, 0xb, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0xaa, 0xaa, 0xaa, 0x80, - - /* U+F1DB "" */ - 0x0, 0x15, 0x40, 0x0, 0x1f, 0xff, 0x40, 0xb, - 0xd0, 0x7e, 0x2, 0xe0, 0x0, 0xb8, 0x3c, 0x0, - 0x3, 0xc7, 0x40, 0x50, 0x1d, 0xb0, 0x1f, 0x40, - 0xeb, 0x2, 0xf8, 0xe, 0xb0, 0xf, 0x0, 0xe7, - 0x80, 0x0, 0x2c, 0x3c, 0x0, 0x3, 0xc1, 0xf0, - 0x0, 0xf4, 0xb, 0x80, 0x2e, 0x0, 0x3e, 0xb, - 0xc0, 0x0, 0xfa, 0xf0, 0x0, 0x3, 0xfc, 0x0, - 0x0, 0xa, 0x0, 0x0, - - /* U+F24F "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x6a, 0xaa, 0x92, 0xc0, 0x3a, - 0xff, 0xff, 0xfa, 0xcc, 0x3a, 0xff, 0xff, 0xfa, - 0xcc, 0x3a, 0xff, 0xff, 0xfa, 0xcc, 0x3a, 0xff, - 0xff, 0xfa, 0xcc, 0x38, 0x6a, 0xaa, 0x92, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F250 "" */ - 0xf, 0xff, 0xff, 0xe0, 0x0, 0xfa, 0xaa, 0xaa, - 0x43, 0x3, 0x86, 0xaa, 0x90, 0x28, 0xe, 0xbf, - 0xff, 0xc2, 0xe0, 0x3a, 0xff, 0xfe, 0x1f, 0xf8, - 0xeb, 0xff, 0xe0, 0xbf, 0xc3, 0xaf, 0xff, 0x0, - 0x2d, 0xe, 0x1a, 0x90, 0x0, 0xe0, 0x3e, 0xaa, - 0xaa, 0x43, 0x0, 0x3f, 0xff, 0xff, 0x0, 0x0, - - /* U+F252 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x6a, 0xaa, 0x42, 0xc0, 0x3a, - 0xff, 0xff, 0xd2, 0xcc, 0x3a, 0xff, 0xff, 0xd2, - 0xcc, 0x3a, 0xff, 0xff, 0xd2, 0xcc, 0x3a, 0xff, - 0xff, 0xd2, 0xcc, 0x38, 0x6a, 0xaa, 0x42, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F253 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x6a, 0xa4, 0x2, 0xc0, 0x3a, - 0xff, 0xfe, 0x2, 0xcc, 0x3a, 0xff, 0xfe, 0x2, - 0xcc, 0x3a, 0xff, 0xfe, 0x2, 0xcc, 0x3a, 0xff, - 0xfe, 0x2, 0xcc, 0x38, 0x6a, 0xa4, 0x2, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F254 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x6a, 0x90, 0x2, 0xc0, 0x3a, - 0xff, 0xf0, 0x2, 0xcc, 0x3a, 0xff, 0xf0, 0x2, - 0xcc, 0x3a, 0xff, 0xf0, 0x2, 0xcc, 0x3a, 0xff, - 0xf0, 0x2, 0xcc, 0x38, 0x6a, 0x90, 0x2, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F255 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x69, 0x0, 0x2, 0xc0, 0x3a, - 0xff, 0x40, 0x2, 0xcc, 0x3a, 0xff, 0x40, 0x2, - 0xcc, 0x3a, 0xff, 0x40, 0x2, 0xcc, 0x3a, 0xff, - 0x40, 0x2, 0xcc, 0x38, 0x69, 0x0, 0x2, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F256 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x50, 0x0, 0x2, 0xc0, 0x3a, - 0xf8, 0x0, 0x2, 0xcc, 0x3a, 0xf8, 0x0, 0x2, - 0xcc, 0x3a, 0xf8, 0x0, 0x2, 0xcc, 0x3a, 0xf8, - 0x0, 0x2, 0xcc, 0x38, 0x50, 0x0, 0x2, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0, - - /* U+F257 "" */ - 0xf, 0xff, 0xff, 0xff, 0x0, 0x3e, 0xaa, 0xaa, - 0xab, 0xc0, 0x38, 0x40, 0x0, 0x2, 0xc0, 0x3a, - 0xc0, 0x0, 0x2, 0xcc, 0x3a, 0xc0, 0x0, 0x2, - 0xcc, 0x3a, 0xc0, 0x0, 0x2, 0xcc, 0x3a, 0xc0, - 0x0, 0x2, 0xcc, 0x38, 0x40, 0x0, 0x2, 0xc0, - 0x3e, 0xaa, 0xaa, 0xab, 0xc0, 0xf, 0xff, 0xff, - 0xff, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 320, .box_w = 11, .box_h = 16, .ofs_x = 4, .ofs_y = 2}, - {.bitmap_index = 44, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 108, .adv_w = 320, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = 1}, - {.bitmap_index = 181, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 271, .adv_w = 320, .box_w = 12, .box_h = 18, .ofs_x = 4, .ofs_y = 1}, - {.bitmap_index = 325, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 389, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 453, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 516, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 586, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 656, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 726, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1}, - {.bitmap_index = 789, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 859, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 929, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 999, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 1069, .adv_w = 320, .box_w = 14, .box_h = 17, .ofs_x = 3, .ofs_y = 2}, - {.bitmap_index = 1129, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1179, .adv_w = 320, .box_w = 19, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1227, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1277, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1327, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1377, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1427, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 1477, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 5} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x1, 0x2, 0x33, 0x39, 0x17b, 0x468, 0x47c, - 0xa2f, 0xa3a, 0xa3d, 0xeb0, 0xebd, 0xebe, 0xf09, 0xfb5, - 0x1034, 0x10a8, 0x10a9, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, - 0x10b0 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57767, .range_length = 4273, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 25, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_statusbar_20 = { -#else -lv_font_t material_symbols_statusbar_20 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 19, /*The maximum line height required by the font*/ - .base_line = 0, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_STATUSBAR_20*/ - diff --git a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_30.c b/Modules/lvgl-module/source-fonts/material_symbols_statusbar_30.c deleted file mode 100644 index 8afa3dbc4..000000000 --- a/Modules/lvgl-module/source-fonts/material_symbols_statusbar_30.c +++ /dev/null @@ -1,612 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 2 - * Opts: --no-compress --no-prefilter --bpp 2 --size 30 --font MaterialSymbolsRounded.ttf -r 0xF1DB,0xF15C,0xE322,0xE623,0xF057,0xF0B0,0xEBE4,0xEBD6,0xEBE1,0xF065,0xE1DA,0xF064,0xF257,0xF256,0xF255,0xF254,0xF253,0xF252,0xF24F,0xF250,0xE1A7,0xE60F,0xE1A8,0xE1A9,0xE1E0 --format lvgl -o source-fonts/material_symbols_statusbar_30.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef MATERIAL_SYMBOLS_STATUSBAR_30 -#define MATERIAL_SYMBOLS_STATUSBAR_30 1 -#endif - -#if MATERIAL_SYMBOLS_STATUSBAR_30 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+E1A7 "" */ - 0x0, 0x0, 0xb0, 0x0, 0x0, 0x0, 0xfc, 0x0, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0xc0, - 0x3d, 0x0, 0xff, 0xf0, 0x3f, 0x40, 0xf5, 0xfc, - 0xf, 0xd0, 0xf4, 0x7e, 0x3, 0xf4, 0xf4, 0xfd, - 0x0, 0xfe, 0xfb, 0xf4, 0x0, 0x3f, 0xff, 0xd0, - 0x0, 0xf, 0xff, 0x40, 0x0, 0x3, 0xfd, 0x0, - 0x0, 0x3, 0xfd, 0x0, 0x0, 0xf, 0xff, 0x40, - 0x0, 0x3f, 0xff, 0xd0, 0x0, 0xfe, 0xfb, 0xf4, - 0x3, 0xf4, 0xf4, 0xfd, 0xf, 0xd0, 0xf4, 0x7e, - 0x3f, 0x40, 0xf5, 0xfc, 0x3d, 0x0, 0xff, 0xf0, - 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0xb0, 0x0, - - /* U+E1A8 "" */ - 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x3, 0xd0, - 0xf, 0xff, 0x0, 0x0, 0x3f, 0x40, 0xf5, 0xfc, - 0x0, 0x0, 0xfd, 0xf, 0x47, 0xe0, 0x0, 0x3, - 0xf4, 0xf4, 0xfd, 0x0, 0x0, 0xf, 0xef, 0xbf, - 0x40, 0x0, 0x0, 0x3f, 0xff, 0xd0, 0x0, 0x2d, - 0x0, 0xff, 0xf4, 0x7, 0x8b, 0xf0, 0x3, 0xfd, - 0x0, 0xfe, 0xbf, 0x0, 0x3f, 0xd0, 0xf, 0xe2, - 0xd0, 0xf, 0xff, 0x40, 0x78, 0x0, 0x3, 0xff, - 0xfd, 0x0, 0x0, 0x0, 0xfe, 0xfb, 0xf4, 0x0, - 0x0, 0x3f, 0x4f, 0x4f, 0xd0, 0x0, 0xf, 0xd0, - 0xf4, 0x7e, 0x0, 0x3, 0xf4, 0xf, 0x5f, 0xc0, - 0x0, 0x3d, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0xb0, 0x0, 0x0, - - /* U+E1A9 "" */ - 0x0, 0x0, 0x0, 0xb0, 0x0, 0x0, 0x1e, 0x0, - 0x0, 0x3f, 0x0, 0x0, 0x7, 0xe0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0xfe, 0x0, 0x3, 0xff, 0x0, - 0x0, 0xf, 0xe0, 0x0, 0xff, 0xf0, 0x0, 0x0, - 0xfe, 0x0, 0x3d, 0x7f, 0x0, 0x0, 0xf, 0xe0, - 0xf, 0x47, 0xe0, 0x0, 0x0, 0xfe, 0x3, 0xd3, - 0xf4, 0x0, 0x0, 0xf, 0xe0, 0x3b, 0xf4, 0x0, - 0x0, 0x0, 0xfe, 0x3, 0xf4, 0x0, 0x0, 0x0, - 0xf, 0xe0, 0x34, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3, - 0xfb, 0xfe, 0x0, 0x0, 0x0, 0x3, 0xf4, 0xff, - 0xe0, 0x0, 0x0, 0x3, 0xf4, 0x3d, 0xfe, 0x0, - 0x0, 0x3, 0xf4, 0xf, 0x5f, 0xe0, 0x0, 0x0, - 0xf4, 0x3, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x3f, 0xc0, - 0xfe, 0x0, 0x0, 0x0, 0xf, 0xc0, 0xf, 0xe0, - 0x0, 0x0, 0x2, 0xc0, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xa, 0x0, - - /* U+E1DA "" */ - 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xd0, 0x6, 0xff, 0xf9, 0x0, 0x0, 0x0, 0x3f, - 0x40, 0xff, 0xff, 0xff, 0x80, 0x0, 0x1, 0xfd, - 0xb, 0xaa, 0xaf, 0xff, 0x80, 0x0, 0x2f, 0xf4, - 0x0, 0x0, 0x7, 0xff, 0x40, 0xf, 0xff, 0xd0, - 0x0, 0x0, 0x2, 0xfe, 0x7, 0xf8, 0x3f, 0x40, - 0x0, 0x0, 0x3, 0xfc, 0xbe, 0x0, 0xfd, 0x0, - 0x0, 0x0, 0xf, 0xc3, 0xf8, 0x3, 0xf4, 0x0, - 0x0, 0x3, 0xf8, 0xf, 0xe0, 0xf, 0xd0, 0x0, - 0x0, 0xfe, 0x0, 0x3f, 0x80, 0x3f, 0x40, 0x0, - 0x3f, 0x80, 0x0, 0xfe, 0x0, 0xfd, 0x0, 0xf, - 0xe0, 0x0, 0x3, 0xf8, 0x3, 0xf4, 0x3, 0xf8, - 0x0, 0x0, 0xf, 0xe0, 0xf, 0xd0, 0x3e, 0x0, - 0x0, 0x0, 0x3f, 0x80, 0x3f, 0x40, 0x0, 0x0, - 0x0, 0x0, 0xfe, 0x0, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x3, 0xf8, 0x7, 0xf4, 0x0, 0x0, 0x0, - 0x0, 0xf, 0xe0, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xbf, 0xbf, 0x40, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xe0, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xf8, 0x3, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x9, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x0, - - /* U+E1E0 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x0, - 0x0, 0x0, 0x2, 0xf4, 0x0, 0x0, 0x0, 0x7f, - 0xc0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, - 0x6f, 0x90, 0x0, 0x0, 0x1, 0xf0, 0x0, 0x0, - 0x0, 0x1f, 0x0, 0x0, 0x2f, 0x1, 0xf0, 0x3f, - 0xfb, 0xfc, 0x1f, 0x3, 0xff, 0xbf, 0xc1, 0xf0, - 0x3f, 0xfb, 0xfc, 0x1f, 0x3, 0xff, 0x2f, 0x1, - 0xf0, 0x3f, 0xf2, 0xf0, 0x1f, 0x0, 0xf8, 0x2f, - 0x1, 0xf0, 0xf, 0x81, 0xfa, 0xaf, 0xaa, 0xf8, - 0x1f, 0xff, 0xff, 0xff, 0x40, 0x7f, 0xff, 0xff, - 0xe0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0x0, 0x1f, - 0x0, 0x0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0x0, - 0x3f, 0xc0, 0x0, 0x0, 0xb, 0xfc, 0x0, 0x0, - 0x0, 0xbf, 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, - 0x0, 0x0, 0x5, 0x0, 0x0, - - /* U+E322 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb4, 0x2d, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3e, - 0x0, 0x0, 0x0, 0x6a, 0xfe, 0xbf, 0xa4, 0x0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0x0, 0x3, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x3, 0xe0, 0x0, 0x0, - 0xf, 0x80, 0x3, 0xe0, 0x0, 0x0, 0xf, 0x80, - 0x2b, 0xe0, 0x6a, 0xa8, 0xf, 0xe4, 0x7f, 0xe0, - 0xff, 0xfe, 0xf, 0xfc, 0x3f, 0xe0, 0xff, 0xfe, - 0xf, 0xf8, 0x3, 0xe0, 0xf8, 0x3e, 0xf, 0x80, - 0x3, 0xe0, 0xf8, 0x3e, 0xf, 0x80, 0x2b, 0xe0, - 0xfe, 0xbe, 0xf, 0xe4, 0x7f, 0xe0, 0xff, 0xfe, - 0xf, 0xfc, 0x3f, 0xe0, 0x7f, 0xfc, 0xf, 0xf8, - 0x3, 0xe0, 0x0, 0x0, 0xf, 0x80, 0x3, 0xe0, - 0x0, 0x0, 0xf, 0x80, 0x3, 0xfa, 0xaa, 0xaa, - 0xaf, 0x80, 0x2, 0xff, 0xff, 0xff, 0xff, 0x40, - 0x0, 0xbf, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, - 0xf8, 0x3e, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x3d, - 0x0, 0x0, 0x0, 0x0, 0x10, 0x4, 0x0, 0x0, - - /* U+E60F "" */ - 0x0, 0x2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xd0, 0x0, 0x0, 0xb8, - 0x3, 0xff, 0xd0, 0x0, 0x2, 0xf8, 0xf, 0x9f, - 0xd0, 0x0, 0x3, 0xf8, 0x3e, 0x1f, 0xc0, 0x28, - 0x3, 0xf8, 0xf8, 0xfe, 0x0, 0xf0, 0x3, 0xfb, - 0xef, 0xe0, 0x2, 0xe0, 0x3, 0xff, 0xfe, 0x0, - 0x7, 0xc0, 0x3, 0xff, 0xe0, 0x3c, 0xf, 0x0, - 0x3, 0xfe, 0x3, 0xf0, 0x3c, 0x0, 0xf, 0xf8, - 0xf, 0xc0, 0xf0, 0x0, 0xff, 0xf8, 0xf, 0x3, - 0xc0, 0xf, 0xff, 0xf8, 0x0, 0x1f, 0x0, 0xfe, - 0xfb, 0xf8, 0x0, 0xb4, 0xf, 0xe3, 0xe3, 0xf8, - 0x3, 0xc0, 0xfe, 0xf, 0x87, 0xf0, 0xa, 0xb, - 0xe0, 0x3e, 0x3f, 0x40, 0x0, 0x2e, 0x0, 0xff, - 0xf4, 0x0, 0x0, 0x0, 0x3, 0xff, 0x40, 0x0, - 0x0, 0x0, 0xf, 0xf4, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0xb4, 0x0, - 0x0, 0x0, - - /* U+E623 "" */ - 0x0, 0x0, 0x6a, 0xaa, 0x90, 0x0, 0x7, 0xff, - 0xff, 0xfd, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x0, - 0x7f, 0x0, 0x0, 0x2f, 0x1, 0xfc, 0x0, 0x0, - 0x2f, 0x7, 0xf0, 0x0, 0x0, 0x2f, 0x1f, 0xc0, - 0x0, 0x0, 0x2f, 0x7f, 0xb, 0x8f, 0x4f, 0x2f, - 0xfc, 0xb, 0x8f, 0x8f, 0x2f, 0xf8, 0xb, 0x8f, - 0x8f, 0x2f, 0xf8, 0xb, 0x8f, 0x8f, 0x2f, 0xf8, - 0x6, 0x46, 0xa, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, - 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x6, 0xaa, 0xaa, - 0xaa, 0x90, - - /* U+EBD6 "" */ - 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xfe, 0xaa, 0xbf, 0xff, 0x0, 0xb, 0xfe, 0x40, - 0x0, 0x1, 0xbf, 0xe0, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0xbe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbe, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0x2f, 0xc0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x2, 0xfc, - 0x2, 0xbe, 0x80, 0x3f, 0x80, 0x0, 0xbf, 0x2f, - 0xff, 0xf8, 0xfe, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+EBE1 "" */ - 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x1, 0xff, - 0xfe, 0xaa, 0xbf, 0xff, 0x40, 0xb, 0xfe, 0x40, - 0x0, 0x1, 0xbf, 0xe0, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0xbe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbe, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x7f, 0x0, 0x1, 0xaa, 0x40, 0x0, 0xfd, - 0x2f, 0xc0, 0x7f, 0xff, 0xfd, 0x3, 0xf8, 0xb, - 0xf7, 0xff, 0xff, 0xff, 0xdf, 0xe0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+EBE4 "" */ - 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xfe, 0xaa, 0xbf, 0xff, 0x0, 0xb, 0xfe, 0x40, - 0x0, 0x1, 0xbf, 0xe0, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0xbf, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xfe, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0x2f, 0xc0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x2, 0xfc, - 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0xbf, 0x0, - 0x0, 0x0, 0xfe, 0x0, 0x0, 0x2f, 0xc0, 0x0, - 0x3, 0xf8, 0x0, 0x0, 0xb, 0xf2, 0xff, 0x8f, - 0xe0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+F057 "" */ - 0x0, 0x0, 0x6a, 0xaa, 0x90, 0x0, 0x7, 0xff, - 0xff, 0xfd, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x0, - 0x7f, 0x0, 0x0, 0x2f, 0x1, 0xfc, 0x0, 0x0, - 0x2f, 0x7, 0xf0, 0x0, 0x0, 0x2f, 0x1f, 0xc0, - 0x0, 0x0, 0x2f, 0x7f, 0x0, 0x0, 0x0, 0x2f, - 0xfc, 0x0, 0x3c, 0x0, 0x2f, 0xf8, 0x0, 0x3c, - 0x0, 0x2f, 0xf8, 0x0, 0x3c, 0x0, 0x2f, 0xf8, - 0x0, 0x3c, 0x0, 0x2f, 0xf8, 0x0, 0x3c, 0x0, - 0x2f, 0xf8, 0x0, 0x3c, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, - 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x3c, - 0x0, 0x2f, 0xf8, 0x0, 0x3c, 0x0, 0x2f, 0xf8, - 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, 0x0, - 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x6, 0xaa, 0xaa, - 0xaa, 0x90, - - /* U+F064 "" */ - 0x0, 0x0, 0x6b, 0xff, 0xe9, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xfe, 0xaa, 0xbf, 0xff, 0x0, 0xb, 0xfe, 0x40, - 0x0, 0x1, 0xbf, 0xe0, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0xbe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbe, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, - 0x2f, 0xc0, 0x0, 0x0, 0x0, 0x1, 0xf8, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0x1, 0xe0, 0x2, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xc0, 0x0, - 0x1, 0x40, 0x20, 0x0, 0xb, 0xf0, 0x0, 0x3, - 0xe1, 0xf8, 0x0, 0x2, 0xfc, 0x0, 0x2, 0xff, - 0xf4, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xbf, 0xd0, - 0x0, 0x0, 0x2f, 0xc0, 0x0, 0x7f, 0xc0, 0x0, - 0x0, 0xb, 0xfb, 0x1, 0xff, 0xe0, 0x0, 0x0, - 0x2, 0xff, 0x43, 0xf6, 0xf4, 0x0, 0x0, 0x0, - 0xbe, 0x3, 0xd0, 0xb4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+F065 "" */ - 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0xbf, 0xff, - 0xff, 0xff, 0xfe, 0x0, 0x0, 0x2f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, - 0xe0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+F0B0 "" */ - 0x0, 0x0, 0x1b, 0xff, 0xe4, 0x0, 0x0, 0x0, - 0xb, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0xff, - 0xfe, 0xaa, 0xbf, 0xff, 0x0, 0xb, 0xfe, 0x40, - 0x0, 0x1, 0xbf, 0xe0, 0x3f, 0xe0, 0x0, 0x0, - 0x0, 0xb, 0xfc, 0xbe, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbe, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xbf, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, - 0x2f, 0xc0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0xb, - 0xf0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x2, 0xfc, - 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0xbf, 0x0, - 0x0, 0x0, 0xfe, 0x0, 0x0, 0x2f, 0xc0, 0x0, - 0x3, 0xf8, 0x0, 0x0, 0xb, 0xf0, 0x0, 0xf, - 0xe0, 0x0, 0x0, 0x2, 0xfc, 0x0, 0x3f, 0x80, - 0x0, 0x0, 0x0, 0xbf, 0x0, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xc3, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+F15C "" */ - 0x0, 0x0, 0x6, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x3f, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xaa, 0xff, 0x0, 0x0, 0x0, 0x3, 0xf8, - 0x0, 0x2f, 0xc0, 0x0, 0x0, 0xb, 0xd0, 0x0, - 0xb, 0xd0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x3, - 0xf0, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x1, 0xf4, - 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0xf4, 0x0, - 0xf, 0xfe, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x2f, - 0x80, 0x0, 0x0, 0x0, 0xff, 0x80, 0x3e, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf0, 0xbc, 0x0, 0x0, - 0x0, 0x0, 0x16, 0xfc, 0xbc, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7d, 0xbc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3e, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3e, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0xbd, 0xf, - 0xfa, 0xaa, 0xaa, 0xaa, 0xab, 0xfc, 0x7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0x40, - - /* U+F1DB "" */ - 0x0, 0x0, 0x55, 0x0, 0x0, 0x0, 0x1f, 0xff, - 0xf4, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x3, - 0xfd, 0x0, 0x7f, 0xc0, 0xf, 0xd0, 0x0, 0x7, - 0xf0, 0x2f, 0x40, 0x0, 0x1, 0xf8, 0x3e, 0x0, - 0x0, 0x0, 0xbc, 0xbc, 0x0, 0x0, 0x0, 0x3e, - 0xfc, 0x0, 0x7d, 0x0, 0x3f, 0xf8, 0x0, 0xff, - 0x0, 0x2f, 0xf8, 0x1, 0xff, 0x40, 0x2f, 0xf8, - 0x0, 0xff, 0x0, 0x2f, 0xfc, 0x0, 0x7d, 0x0, - 0x3f, 0xbc, 0x0, 0x0, 0x0, 0x3d, 0x3e, 0x0, - 0x0, 0x0, 0xbc, 0x2f, 0x0, 0x0, 0x0, 0xf8, - 0xf, 0xc0, 0x0, 0x3, 0xf0, 0x7, 0xe0, 0x0, - 0xb, 0xd0, 0x2, 0xf4, 0x0, 0x1f, 0x80, 0x0, - 0xfd, 0x0, 0x7f, 0x0, 0x0, 0x3f, 0x41, 0xfc, - 0x0, 0x0, 0xf, 0xd7, 0xf0, 0x0, 0x0, 0x7, - 0xff, 0xd0, 0x0, 0x0, 0x1, 0xff, 0x40, 0x0, - 0x0, 0x0, 0x28, 0x0, 0x0, - - /* U+F24F "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0xaa, 0xaa, - 0xaa, 0xf, 0x40, 0xf8, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0x4d, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xcf, - 0x4f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x4f, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x4f, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xcf, 0x4f, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xcf, 0x4e, 0xf8, 0xbf, 0xff, - 0xff, 0xff, 0x4f, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F250 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xa4, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xfc, 0x3, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0xb, 0x0, 0xf8, 0x6a, 0xaa, 0xaa, - 0x40, 0x2f, 0x0, 0xf8, 0xff, 0xff, 0xff, 0xc0, - 0x7e, 0x0, 0xf8, 0xff, 0xff, 0xff, 0x80, 0xfe, - 0x0, 0xf8, 0xff, 0xff, 0xff, 0x3, 0xff, 0xfc, - 0xf8, 0xff, 0xff, 0xfc, 0xb, 0xff, 0xf0, 0xf8, - 0xff, 0xff, 0xf4, 0x1, 0x5f, 0xd0, 0xf8, 0xff, - 0xff, 0xe0, 0x0, 0x1f, 0x80, 0xf8, 0xbf, 0xff, - 0x80, 0x0, 0x2f, 0x0, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x3c, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xf0, - 0x30, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xf0, 0x10, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x0, - - /* U+F252 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0xaa, 0xaa, - 0xa0, 0xf, 0x40, 0xf8, 0xff, 0xff, 0xff, 0xfc, - 0xf, 0x4d, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xf, - 0x4f, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xf, 0x4f, - 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xf, 0x4f, 0xf8, - 0xff, 0xff, 0xff, 0xfc, 0xf, 0x4f, 0xf8, 0xff, - 0xff, 0xff, 0xfc, 0xf, 0x4e, 0xf8, 0xbf, 0xff, - 0xff, 0xf8, 0xf, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F253 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0xaa, 0xa9, - 0x0, 0xf, 0x40, 0xf8, 0xff, 0xff, 0xff, 0x40, - 0xf, 0x4d, 0xf8, 0xff, 0xff, 0xff, 0x40, 0xf, - 0x4f, 0xf8, 0xff, 0xff, 0xff, 0x40, 0xf, 0x4f, - 0xf8, 0xff, 0xff, 0xff, 0x40, 0xf, 0x4f, 0xf8, - 0xff, 0xff, 0xff, 0x40, 0xf, 0x4f, 0xf8, 0xff, - 0xff, 0xff, 0x40, 0xf, 0x4e, 0xf8, 0xbf, 0xff, - 0xff, 0x0, 0xf, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F254 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0xaa, 0x80, - 0x0, 0xf, 0x40, 0xf8, 0xff, 0xff, 0xf0, 0x0, - 0xf, 0x4d, 0xf8, 0xff, 0xff, 0xf0, 0x0, 0xf, - 0x4f, 0xf8, 0xff, 0xff, 0xf0, 0x0, 0xf, 0x4f, - 0xf8, 0xff, 0xff, 0xf0, 0x0, 0xf, 0x4f, 0xf8, - 0xff, 0xff, 0xf0, 0x0, 0xf, 0x4f, 0xf8, 0xff, - 0xff, 0xf0, 0x0, 0xf, 0x4e, 0xf8, 0xbf, 0xff, - 0xe0, 0x0, 0xf, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F255 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0xa4, 0x0, - 0x0, 0xf, 0x40, 0xf8, 0xff, 0xfd, 0x0, 0x0, - 0xf, 0x4d, 0xf8, 0xff, 0xfd, 0x0, 0x0, 0xf, - 0x4f, 0xf8, 0xff, 0xfd, 0x0, 0x0, 0xf, 0x4f, - 0xf8, 0xff, 0xfd, 0x0, 0x0, 0xf, 0x4f, 0xf8, - 0xff, 0xfd, 0x0, 0x0, 0xf, 0x4f, 0xf8, 0xff, - 0xfd, 0x0, 0x0, 0xf, 0x4e, 0xf8, 0xbf, 0xfc, - 0x0, 0x0, 0xf, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F256 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x6a, 0x0, 0x0, - 0x0, 0xf, 0x40, 0xf8, 0xff, 0xc0, 0x0, 0x0, - 0xf, 0x4d, 0xf8, 0xff, 0xc0, 0x0, 0x0, 0xf, - 0x4f, 0xf8, 0xff, 0xc0, 0x0, 0x0, 0xf, 0x4f, - 0xf8, 0xff, 0xc0, 0x0, 0x0, 0xf, 0x4f, 0xf8, - 0xff, 0xc0, 0x0, 0x0, 0xf, 0x4f, 0xf8, 0xff, - 0xc0, 0x0, 0x0, 0xf, 0x4e, 0xf8, 0xbf, 0x80, - 0x0, 0x0, 0xf, 0x44, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, - - /* U+F257 "" */ - 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x7f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x1f, 0x40, 0xf8, 0x60, 0x0, 0x0, - 0x0, 0xf, 0x40, 0xf8, 0xf4, 0x0, 0x0, 0x0, - 0xf, 0x4d, 0xf8, 0xf4, 0x0, 0x0, 0x0, 0xf, - 0x4f, 0xf8, 0xf4, 0x0, 0x0, 0x0, 0xf, 0x4f, - 0xf8, 0xf4, 0x0, 0x0, 0x0, 0xf, 0x4f, 0xf8, - 0xf4, 0x0, 0x0, 0x0, 0xf, 0x4f, 0xf8, 0xf4, - 0x0, 0x0, 0x0, 0xf, 0x4e, 0xf8, 0xb0, 0x0, - 0x0, 0x0, 0xf, 0x40, 0xfc, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0x40, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x1, 0xaa, 0xaa, 0xaa, 0xaa, 0x50, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 480, .box_w = 16, .box_h = 24, .ofs_x = 6, .ofs_y = 3}, - {.bitmap_index = 96, .adv_w = 480, .box_w = 22, .box_h = 24, .ofs_x = 4, .ofs_y = 3}, - {.bitmap_index = 228, .adv_w = 480, .box_w = 25, .box_h = 25, .ofs_x = 2, .ofs_y = 2}, - {.bitmap_index = 385, .adv_w = 480, .box_w = 30, .box_h = 26, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 580, .adv_w = 480, .box_w = 18, .box_h = 26, .ofs_x = 6, .ofs_y = 2}, - {.bitmap_index = 697, .adv_w = 480, .box_w = 24, .box_h = 24, .ofs_x = 3, .ofs_y = 3}, - {.bitmap_index = 841, .adv_w = 480, .box_w = 23, .box_h = 24, .ofs_x = 4, .ofs_y = 3}, - {.bitmap_index = 979, .adv_w = 480, .box_w = 20, .box_h = 26, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 1109, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 1256, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 1403, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 1550, .adv_w = 480, .box_w = 20, .box_h = 26, .ofs_x = 5, .ofs_y = 2}, - {.bitmap_index = 1680, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 1827, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 1974, .adv_w = 480, .box_w = 28, .box_h = 21, .ofs_x = 1, .ofs_y = 4}, - {.bitmap_index = 2121, .adv_w = 480, .box_w = 28, .box_h = 20, .ofs_x = 1, .ofs_y = 5}, - {.bitmap_index = 2261, .adv_w = 480, .box_w = 20, .box_h = 25, .ofs_x = 5, .ofs_y = 3}, - {.bitmap_index = 2386, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 2498, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 2610, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 2722, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 2834, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 2946, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 3058, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 3170, .adv_w = 480, .box_w = 28, .box_h = 16, .ofs_x = 1, .ofs_y = 7} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = { - 0x0, 0x1, 0x2, 0x33, 0x39, 0x17b, 0x468, 0x47c, - 0xa2f, 0xa3a, 0xa3d, 0xeb0, 0xebd, 0xebe, 0xf09, 0xfb5, - 0x1034, 0x10a8, 0x10a9, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, - 0x10b0 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ - { - .range_start = 57767, .range_length = 4273, .glyph_id_start = 1, - .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 25, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - - - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 2, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif -}; - - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t material_symbols_statusbar_30 = { -#else -lv_font_t material_symbols_statusbar_30 = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 27, /*The maximum line height required by the font*/ - .base_line = -1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - - - -#endif /*#if MATERIAL_SYMBOLS_STATUSBAR_30*/ - diff --git a/Modules/lvgl-module/source/arch/lvgl_esp32.c b/Modules/lvgl-module/source/arch/lvgl_esp32.c index 63d1134ce..45f95f6a3 100644 --- a/Modules/lvgl-module/source/arch/lvgl_esp32.c +++ b/Modules/lvgl-module/source/arch/lvgl_esp32.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,10 @@ error_t lvgl_arch_start() { // devices and services. The latter might start adding widgets immediately. initialized = true; + lvgl_lock(); + lvgl_png_decoder_init(); + lvgl_unlock(); + // Must exist before devices/services are attached below, since those can // immediately try to assign an indev to this group (e.g. USB HID input). lvgl_keyboard_on_start_lvgl(); diff --git a/Modules/lvgl-module/source/arch/lvgl_posix.c b/Modules/lvgl-module/source/arch/lvgl_posix.c index 21a285144..673dd0b8e 100644 --- a/Modules/lvgl-module/source/arch/lvgl_posix.c +++ b/Modules/lvgl-module/source/arch/lvgl_posix.c @@ -13,6 +13,7 @@ #include #include #include +#include extern struct LvglModuleConfig lvgl_module_config; extern void lvgl_devices_attach(); @@ -129,6 +130,7 @@ error_t lvgl_arch_start() { lvgl_task_set_interrupted(false); lv_init(); + lvgl_png_decoder_init(); // Must exist before devices/services are attached from the lvgl task below, // since those can immediately try to assign an indev to this group. diff --git a/Modules/lvgl-module/source/binfont.c b/Modules/lvgl-module/source/binfont.c new file mode 100644 index 000000000..a166ee266 --- /dev/null +++ b/Modules/lvgl-module/source/binfont.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +#include + +#include +#include + +static bool get_glyph_dsc(const lv_font_t* font, lv_font_glyph_dsc_t* dsc, uint32_t letter, uint32_t letter_next) { + struct BinFont* binfont = (struct BinFont*)font->dsc; + BinFontGlyph glyph; + if (!binfont_get_glyph(binfont, letter, &glyph)) { + return false; + } + + int32_t advance_x16 = (int32_t)glyph.advance_x16; + BinFontGlyph next; + if (font->kerning == LV_FONT_KERNING_NORMAL && letter_next != 0 && binfont_get_glyph(binfont, letter_next, &next)) { + advance_x16 += binfont_get_kerning_x16(binfont, glyph.glyph_id, next.glyph_id); + } + + dsc->adv_w = (uint16_t)((advance_x16 + 8) >> 4); + dsc->box_w = glyph.width; + dsc->box_h = glyph.height; + dsc->ofs_x = glyph.x; + dsc->ofs_y = glyph.y; + dsc->stride = 0; + dsc->format = LV_FONT_GLYPH_FORMAT_A8; + dsc->is_placeholder = false; + dsc->gid.index = glyph.glyph_id; + return true; +} + +static const void* get_glyph_bitmap(lv_font_glyph_dsc_t* dsc, lv_draw_buf_t* draw_buf) { + if (dsc->box_w == 0 || dsc->box_h == 0) { + return NULL; + } + struct BinFont* binfont = (struct BinFont*)dsc->resolved_font->dsc; + const BinFontGlyph glyph = { + .glyph_id = dsc->gid.index, + .width = dsc->box_w, + .height = dsc->box_h, + }; + if (binfont_get_glyph_bitmap(binfont, &glyph, draw_buf->data, draw_buf->header.stride) != ERROR_NONE) { + return NULL; + } + lv_draw_buf_flush_cache(draw_buf, NULL); + return draw_buf; +} + +lv_font_t* lvgl_binfont_create(struct BinFont* font) { + lv_font_t* lv_font = memory_calloc(1, sizeof(lv_font_t)); + if (lv_font == NULL) { + return NULL; + } + + BinFontMetrics metrics; + binfont_get_metrics(font, &metrics); + + lv_font->get_glyph_dsc = get_glyph_dsc; + lv_font->get_glyph_bitmap = get_glyph_bitmap; + lv_font->line_height = metrics.line_height; + lv_font->base_line = metrics.base_line; + lv_font->subpx = LV_FONT_SUBPX_NONE; + lv_font->kerning = LV_FONT_KERNING_NORMAL; + lv_font->underline_position = (int8_t)metrics.underline_position; + lv_font->underline_thickness = (int8_t)metrics.underline_thickness; + lv_font->dsc = font; + return lv_font; +} + +void lvgl_binfont_destroy(lv_font_t* font) { + memory_free(font); +} diff --git a/Modules/lvgl-module/source/fonts.c b/Modules/lvgl-module/source/fonts.c index 862bfd745..1c2b42cb3 100644 --- a/Modules/lvgl-module/source/fonts.c +++ b/Modules/lvgl-module/source/fonts.c @@ -9,10 +9,16 @@ 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; -extern const lv_font_t TT_LVGL_LAUNCHER_FONT_ICON_SYMBOL; -extern const lv_font_t TT_LVGL_STATUSBAR_FONT_ICON_SYMBOL; -extern const lv_font_t TT_LVGL_SHARED_FONT_ICON_SYMBOL; -extern const lv_font_t TT_LVGL_SHARED_FONT_ICON_2X_SYMBOL; +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; +} + +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; +} uint32_t lvgl_get_text_font_height(enum LvglFontSize font_size) { switch (font_size) { @@ -33,16 +39,16 @@ const lv_font_t* lvgl_get_text_font(enum LvglFontSize font_size) { uint32_t lvgl_get_shared_icon_font_height() { return TT_LVGL_SHARED_FONT_ICON_SIZE; } -const lv_font_t* lvgl_get_shared_icon_font() { return &TT_LVGL_SHARED_FONT_ICON_SYMBOL; } +const lv_font_t* lvgl_get_shared_icon_font() { return get_icon_font(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 &TT_LVGL_SHARED_FONT_ICON_2X_SYMBOL; } +const lv_font_t* lvgl_get_shared_icon_font_2x() { return get_icon_font(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 &TT_LVGL_LAUNCHER_FONT_ICON_SYMBOL; } +const lv_font_t* lvgl_get_launcher_icon_font() { return get_icon_font(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 &TT_LVGL_STATUSBAR_FONT_ICON_SYMBOL; } +const lv_font_t* lvgl_get_statusbar_icon_font() { return get_icon_font(LVGL_ICON_FONT_STATUSBAR); } diff --git a/Modules/lvgl-module/source/icon_names.c b/Modules/lvgl-module/source/icon_names.c new file mode 100644 index 000000000..c39be6eac --- /dev/null +++ b/Modules/lvgl-module/source/icon_names.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: Apache-2.0 +// Generated by generate-icons.py + +#include + +const char* const lvgl_icon_shared_names[] = { + "add", + "apps", + "area_chart", + "app_registration", + "calendar_month", + "cable", + "circle", + "close", + "cloud", + "check", + "delete", + "devices", + "display_settings", + "edit_note", + "electric_bolt", + "folder", + "deployed_code", + "download", + "forum", + "gamepad", + "help", + "hub", + "image", + "keyboard_arrow_up", + "lightbulb", + "language", + "lists", + "mail", + "menu", + "mop", + "more_vert", + "music_note", + "note_add", + "power_settings_new", + "refresh", + "search", + "settings", + "toolbar", + "navigation", + "keyboard_alt", + "usb", + "wifi", + "bluetooth", + "terminal", + "logo_dev", + "camera", + "lightstrip", +}; + +const size_t lvgl_icon_shared_name_count = sizeof(lvgl_icon_shared_names) / sizeof(lvgl_icon_shared_names[0]); + +const char* const lvgl_icon_statusbar_names[] = { + "location_on", + "cloud", + "memory", + "sd_card", + "sd_card_alert", + "signal_wifi_0_bar", + "network_wifi_1_bar", + "network_wifi_2_bar", + "network_wifi_3_bar", + "signal_wifi_4_bar", + "signal_wifi_off", + "signal_wifi_bad", + "battery_android_frame_1", + "battery_android_frame_2", + "battery_android_frame_3", + "battery_android_frame_4", + "battery_android_frame_5", + "battery_android_frame_6", + "battery_android_frame_full", + "battery_android_frame_bolt", + "bluetooth", + "bluetooth_searching", + "bluetooth_connected", + "bluetooth_disabled", + "usb", +}; + +const size_t lvgl_icon_statusbar_name_count = sizeof(lvgl_icon_statusbar_names) / sizeof(lvgl_icon_statusbar_names[0]); + +const char* const lvgl_icon_launcher_names[] = { + "apps", + "folder", + "settings", +}; + +const size_t lvgl_icon_launcher_name_count = sizeof(lvgl_icon_launcher_names) / sizeof(lvgl_icon_launcher_names[0]); + diff --git a/Modules/lvgl-module/source/png_decoder.c b/Modules/lvgl-module/source/png_decoder.c new file mode 100644 index 000000000..9553d606a --- /dev/null +++ b/Modules/lvgl-module/source/png_decoder.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT +// Based on LVGL's lv_lodepng.c (MIT license, Copyright (c) 2020 LVGL Kft), adapted to decode with lodepng-module. + +#include + +#include + +#include +#include +#include + +#define DECODER_NAME "LODEPNG" + +#define image_cache_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers) + +static const uint8_t PNG_MAGIC[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; + +static uint32_t read_u32_big_endian(const uint8_t* bytes) { + return ((uint32_t)bytes[0] << 24) | ((uint32_t)bytes[1] << 16) | ((uint32_t)bytes[2] << 8) | bytes[3]; +} + +static lv_result_t decoder_info(lv_image_decoder_t* decoder, lv_image_decoder_dsc_t* dsc, lv_image_header_t* header) { + LV_UNUSED(decoder); + + // Width and height are at bytes 16..23 of a PNG file, in big endian + uint8_t buffer[24]; + if (dsc->src_type == LV_IMAGE_SRC_FILE) { + uint32_t read_count; + lv_fs_read(&dsc->file, buffer, sizeof(buffer), &read_count); + if (read_count != sizeof(buffer)) return LV_RESULT_INVALID; + } else if (dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t* image_dsc = dsc->src; + if (image_dsc->data_size < sizeof(buffer)) return LV_RESULT_INVALID; + lv_memcpy(buffer, image_dsc->data, sizeof(buffer)); + } else { + return LV_RESULT_INVALID; + } + + if (lv_memcmp(buffer, PNG_MAGIC, sizeof(PNG_MAGIC)) != 0) return LV_RESULT_INVALID; + + header->cf = LV_COLOR_FORMAT_ARGB8888; + header->w = read_u32_big_endian(&buffer[16]); + header->h = read_u32_big_endian(&buffer[20]); + return LV_RESULT_OK; +} + +/** Reads a whole file through lv_fs, so LVGL drive letter paths ("A:...") work */ +static uint8_t* load_file(const char* path, size_t* out_size) { + lv_fs_file_t file; + if (lv_fs_open(&file, path, LV_FS_MODE_RD) != LV_FS_RES_OK) return NULL; + + uint8_t* data = NULL; + uint32_t size = 0; + if (lv_fs_seek(&file, 0, LV_FS_SEEK_END) == LV_FS_RES_OK && + lv_fs_tell(&file, &size) == LV_FS_RES_OK && + size > 0 && + lv_fs_seek(&file, 0, LV_FS_SEEK_SET) == LV_FS_RES_OK) { + data = lodepng_malloc(size); + uint32_t read_count = 0; + if (data != NULL && (lv_fs_read(&file, data, size, &read_count) != LV_FS_RES_OK || read_count != size)) { + lodepng_free(data); + data = NULL; + } + } + lv_fs_close(&file); + *out_size = size; + return data; +} + +/** Decodes a PNG into an ARGB8888 draw buffer */ +static lv_draw_buf_t* decode_png_data(const uint8_t* png_data, size_t png_data_size) { + unsigned char* rgba = NULL; + unsigned width; + unsigned height; + const unsigned error = lodepng_decode32(&rgba, &width, &height, png_data, png_data_size); + if (error) { + LV_LOG_WARN("error %u: %s", error, lodepng_error_text(error)); + lodepng_free(rgba); + return NULL; + } + + lv_draw_buf_t* decoded = lv_draw_buf_create_ex(image_cache_draw_buf_handlers, width, height, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO); + if (decoded != NULL) { + // lodepng outputs RGBA bytes, LVGL's ARGB8888 is BGRA in memory + for (unsigned y = 0; y < height; y++) { + const unsigned char* source = rgba + (size_t)y * width * 4; + lv_color32_t* target = (lv_color32_t*)(decoded->data + (size_t)y * decoded->header.stride); + for (unsigned x = 0; x < width; x++) { + target[x].red = source[x * 4]; + target[x].green = source[x * 4 + 1]; + target[x].blue = source[x * 4 + 2]; + target[x].alpha = source[x * 4 + 3]; + } + } + } + + lodepng_free(rgba); + return decoded; +} + +static lv_result_t decoder_open(lv_image_decoder_t* decoder, lv_image_decoder_dsc_t* dsc) { + LV_PROFILER_DECODER_BEGIN_TAG("png_decoder_open"); + + lv_draw_buf_t* decoded = NULL; + if (dsc->src_type == LV_IMAGE_SRC_FILE) { + size_t size = 0; + uint8_t* data = load_file(dsc->src, &size); + if (data == NULL) { + LV_LOG_WARN("Failed to load %s", (const char*)dsc->src); + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_INVALID; + } + decoded = decode_png_data(data, size); + lodepng_free(data); + } else if (dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t* image_dsc = dsc->src; + decoded = decode_png_data(image_dsc->data, image_dsc->data_size); + } + + if (decoded == NULL) { + LV_LOG_WARN("Error decoding PNG"); + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_INVALID; + } + + lv_draw_buf_t* adjusted = lv_image_decoder_post_process(dsc, decoded); + if (adjusted == NULL) { + lv_draw_buf_destroy(decoded); + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_INVALID; + } + + // The adjusted draw buffer is newly allocated + if (adjusted != decoded) { + lv_draw_buf_destroy(decoded); + decoded = adjusted; + } + + dsc->decoded = decoded; + + if (dsc->args.no_cache || !lv_image_cache_is_enabled()) { + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_OK; + } + + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = decoded->data_size; + + lv_cache_entry_t* entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL); + if (entry == NULL) { + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_INVALID; + } + dsc->cache_entry = entry; + + LV_PROFILER_DECODER_END_TAG("png_decoder_open"); + return LV_RESULT_OK; +} + +static void decoder_close(lv_image_decoder_t* decoder, lv_image_decoder_dsc_t* dsc) { + LV_UNUSED(decoder); + if (dsc->args.no_cache || !lv_image_cache_is_enabled()) { + lv_draw_buf_destroy((lv_draw_buf_t*)dsc->decoded); + } +} + +void lvgl_png_decoder_init(void) { + lv_image_decoder_t* decoder = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(decoder, decoder_info); + lv_image_decoder_set_open_cb(decoder, decoder_open); + lv_image_decoder_set_close_cb(decoder, decoder_close); + decoder->name = DECODER_NAME; +} diff --git a/Modules/lvgl-module/source/symbols.c b/Modules/lvgl-module/source/symbols.c index 276f08633..e5c02078d 100644 --- a/Modules/lvgl-module/source/symbols.c +++ b/Modules/lvgl-module/source/symbols.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -26,6 +27,9 @@ const struct ModuleSymbol lvgl_module_symbols[] = { // lvgl module DEFINE_MODULE_SYMBOL(lvgl_module), DEFINE_MODULE_SYMBOL(lvgl_module_configure), + // lvgl_binfont + DEFINE_MODULE_SYMBOL(lvgl_binfont_create), + DEFINE_MODULE_SYMBOL(lvgl_binfont_destroy), // lvgl_fonts DEFINE_MODULE_SYMBOL(lvgl_get_shared_icon_font), DEFINE_MODULE_SYMBOL(lvgl_get_shared_icon_font_height), diff --git a/Platforms/platform-esp32/private/bluetooth/esp32_ble_internal.h b/Platforms/platform-esp32/private/bluetooth/esp32_ble_internal.h index 09520de68..829d246df 100644 --- a/Platforms/platform-esp32/private/bluetooth/esp32_ble_internal.h +++ b/Platforms/platform-esp32/private/bluetooth/esp32_ble_internal.h @@ -24,6 +24,8 @@ #include +constexpr size_t BLE_SCAN_RESULTS_MAX = 64; + // ---- Per-module headers (structs, accessors, sub-API externs) ---- #include @@ -91,10 +93,10 @@ struct BleCtx { // BLE device name (set before or after radio enable; applied in dispatch_enable) char device_name[BLE_DEVICE_NAME_MAX + 1]; - // Scan data (guarded by scan_mutex) + // Scan data (guarded by scan_mutex), allocated only while the radio is on SemaphoreHandle_t scan_mutex; - BtPeerRecord scan_results[64]; - ble_addr_t scan_addrs[64]; + BtPeerRecord* scan_results; + ble_addr_t* scan_addrs; size_t scan_count; // Device reference (passed to subscribers via BtEvent delivery) diff --git a/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble.cpp b/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble.cpp index 91ca4863b..bf5179bac 100644 --- a/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble.cpp +++ b/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble.cpp @@ -27,6 +27,7 @@ constexpr auto* TAG = "esp32_ble"; #include +#include #include #if defined(CONFIG_ESP_HOSTED_ENABLED) @@ -665,6 +666,16 @@ void ble_start_advertising_hid(struct Device* device, uint16_t appearance) { // ---- Dispatch helpers ---- +static void free_scan_buffers(BleCtx* ctx) { + xSemaphoreTake(ctx->scan_mutex, portMAX_DELAY); + memory_free(ctx->scan_results); + memory_free(ctx->scan_addrs); + ctx->scan_results = nullptr; + ctx->scan_addrs = nullptr; + ctx->scan_count = 0; + xSemaphoreGive(ctx->scan_mutex); +} + static void dispatch_enable(BleCtx* ctx) { LOG_I(TAG, "dispatch_enable()"); @@ -693,9 +704,22 @@ static void dispatch_enable(BleCtx* ctx) { } #endif - int rc = nimble_port_init(); + constexpr MemoryPolicy scan_policy = { .required = 0, .desired = MEMORY_CAPABILITY_EXTERNAL, .alignment = 0 }; + xSemaphoreTake(ctx->scan_mutex, portMAX_DELAY); + ctx->scan_results = static_cast(memory_calloc_with_policy(BLE_SCAN_RESULTS_MAX, sizeof(BtPeerRecord), &scan_policy)); + ctx->scan_addrs = static_cast(memory_calloc_with_policy(BLE_SCAN_RESULTS_MAX, sizeof(ble_addr_t), &scan_policy)); + ctx->scan_count = 0; + bool scan_alloc_failed = ctx->scan_results == nullptr || ctx->scan_addrs == nullptr; + xSemaphoreGive(ctx->scan_mutex); + + int rc = scan_alloc_failed ? -1 : nimble_port_init(); if (rc != 0) { - LOG_E(TAG, "nimble_port_init failed (rc=%d)", rc); + if (scan_alloc_failed) { + LOG_E(TAG, "Scan buffer allocation failed"); + } else { + LOG_E(TAG, "nimble_port_init failed (rc=%d)", rc); + } + free_scan_buffers(ctx); ctx->radio_state.store(BT_RADIO_STATE_OFF); struct BtEvent e = {}; e.type = BT_EVENT_RADIO_STATE_CHANGED; @@ -820,6 +844,7 @@ static void dispatch_disable(BleCtx* ctx) { } #endif nimble_port_deinit(); + free_scan_buffers(ctx); #if defined(CONFIG_ESP_HOSTED_ENABLED) // Symmetric with the enable-side esp_hosted_bt_controller_init/enable() calls. @@ -1152,8 +1177,9 @@ static error_t esp32_ble_start_device(struct Device* device) { ctx->midi_child = nullptr; ctx->hid_device_child = nullptr; ctx->scan_mutex = xSemaphoreCreateMutex(); + ctx->scan_results = nullptr; + ctx->scan_addrs = nullptr; ctx->scan_count = 0; - memset(ctx->scan_results, 0, sizeof(ctx->scan_results)); ctx->host_task_done_sem = xSemaphoreCreateBinary(); if (ctx->host_task_done_sem == nullptr) { LOG_E(TAG, "start_device: host_task_done_sem create failed"); diff --git a/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble_scan.cpp b/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble_scan.cpp index 53449a8b1..cb9ade881 100644 --- a/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble_scan.cpp +++ b/Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble_scan.cpp @@ -27,7 +27,9 @@ void ble_scan_clear_results(struct Device* device) { BleCtx* ctx = ble_get_ctx(device); xSemaphoreTake(ctx->scan_mutex, portMAX_DELAY); ctx->scan_count = 0; - memset(ctx->scan_results, 0, sizeof(ctx->scan_results)); + if (ctx->scan_results != nullptr) { + memset(ctx->scan_results, 0, BLE_SCAN_RESULTS_MAX * sizeof(BtPeerRecord)); + } xSemaphoreGive(ctx->scan_mutex); } @@ -71,7 +73,7 @@ int ble_gap_disc_event_handler(struct ble_gap_event* event, void* arg) { break; } } - if (!found && ctx->scan_count < 64) { + if (!found && ctx->scan_count < BLE_SCAN_RESULTS_MAX) { ctx->scan_results[ctx->scan_count] = record; ctx->scan_addrs[ctx->scan_count] = disc.addr; // full addr (type+val) ctx->scan_count++; diff --git a/Tactility/CMakeLists.txt b/Tactility/CMakeLists.txt index 2d12f6cdb..0f5f177ed 100644 --- a/Tactility/CMakeLists.txt +++ b/Tactility/CMakeLists.txt @@ -31,6 +31,8 @@ list(APPEND REQUIRES_LIST app-module coreutils-module audio-decoder-module + binfont-module + lodepng-module c-symbols-module cjson-module cpp-symbols-module diff --git a/Tactility/Include/Tactility/MainDispatcher.h b/Tactility/Include/Tactility/MainDispatcher.h new file mode 100644 index 000000000..d7e9ccba7 --- /dev/null +++ b/Tactility/Include/Tactility/MainDispatcher.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include + +namespace tt { + +/** + * A thin C++ wrapper around the TactilityKernel dispatcher, allowing + * std::function (and therefore capturing lambdas) to be dispatched. + */ +class [[deprecated("Use an app task's stack or a custom task with its own stack")]] MainDispatcher final { + +public: + + using Function = std::function; + + explicit MainDispatcher(DispatcherHandle_t handle) : handle(handle) {} + + /** + * Queue a function to be consumed on the main task. + * @param[in] function the function to execute elsewhere + * @param[in] timeout lock acquisition timeout + * @return true if dispatching was successful (timeout not reached) + */ + bool dispatch(Function function, TickType_t timeout = portMAX_DELAY) const; + +private: + + DispatcherHandle_t handle; +}; + +/** Provides access to the dispatcher that runs on the main task. + * @warning This dispatcher is used for WiFi and might block for some time during WiFi connection. + * @return the dispatcher + */ +[[deprecated("Use an app task's stack or a custom task with its own stack")]] +MainDispatcher getMainDispatcher(); + +} // namespace tt diff --git a/Tactility/Include/Tactility/Tactility.h b/Tactility/Include/Tactility/Tactility.h index 1796c7b1c..7dc0e7eff 100644 --- a/Tactility/Include/Tactility/Tactility.h +++ b/Tactility/Include/Tactility/Tactility.h @@ -1,11 +1,10 @@ #pragma once -#include +#include // Included for backwards compatibility + #include #include -#include - extern "C" { struct DtsDevice; } @@ -13,41 +12,11 @@ struct DtsDevice; namespace tt { /** - * A thin C++ wrapper around the TactilityKernel dispatcher, allowing - * std::function (and therefore capturing lambdas) to be dispatched. - */ -class MainDispatcher final { - -public: - - using Function = std::function; - - explicit MainDispatcher(DispatcherHandle_t handle) : handle(handle) {} - - /** - * Queue a function to be consumed on the main task. - * @param[in] function the function to execute elsewhere - * @param[in] timeout lock acquisition timeout - * @return true if dispatching was successful (timeout not reached) - */ - bool dispatch(Function function, TickType_t timeout = portMAX_DELAY) const; - -private: - - DispatcherHandle_t handle; -}; - -/** - * @brief Main entry point for Tactility. + * @brief Initializes Tactility and starts the Boot app. * @param dtsModules List of modules from devicetree, null-terminated, non-null parameter * @param dtsDevices Array that is terminated with DTS_DEVICE_TERMINATOR + * @return false when the kernel failed to initialize */ -void run(Module* const dtsModules[], const DtsDevice dtsDevices[]); - -/** Provides access to the dispatcher that runs on the main task. - * @warning This dispatcher is used for WiFi and might block for some time during WiFi connection. - * @return the dispatcher - */ -MainDispatcher getMainDispatcher(); +bool init(Module* const dtsModules[], const DtsDevice dtsDevices[]); } // namespace tt diff --git a/Tactility/Private/Tactility/TactilityPrivate.h b/Tactility/Private/Tactility/TactilityPrivate.h index 243edb95a..14815b4c2 100644 --- a/Tactility/Private/Tactility/TactilityPrivate.h +++ b/Tactility/Private/Tactility/TactilityPrivate.h @@ -1,8 +1,24 @@ #pragma once +#include + namespace tt { +/** @return the handle of the dispatcher that getMainDispatcher() wraps */ +DispatcherHandle_t getMainDispatcherHandle(); + void prepareFileSystems(); + +/** Starts the kernel modules that Tactility depends on. */ +void initModules(); + +/** Registers and starts the primary system services. */ +void registerAndStartServices(); + +/** Registers the internal apps and the apps installed on mounted file systems. */ void registerApps(); +/** Registers and starts the Boot app. */ +void startBootApp(); + } diff --git a/Tactility/Private/Tactility/app/boot/BootInit.h b/Tactility/Private/Tactility/app/boot/BootInit.h new file mode 100644 index 000000000..3da8b891c --- /dev/null +++ b/Tactility/Private/Tactility/app/boot/BootInit.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace tt::app::boot { + +/** + * Shows the splash, prepares the system and starts LVGL and the launcher. + * Halts on an error screen when the boot can't continue. + * @param[in] startTime the ticks at which the boot app started, for the minimal splash duration + * @return true when the boot completed and the next app was started + */ +bool bootInit(TickType_t startTime); + +} diff --git a/Tactility/Private/Tactility/app/boot/BootScreen.h b/Tactility/Private/Tactility/app/boot/BootScreen.h new file mode 100644 index 000000000..6351b4f51 --- /dev/null +++ b/Tactility/Private/Tactility/app/boot/BootScreen.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +struct Device; +struct PixelBuffer; + +namespace tt::app::boot { + +/** + * Draws boot screens directly to the display, for use while LVGL isn't running. + * Content is drawn in the orientation from the display settings. + */ +class BootScreen { + + Device* display = nullptr; + int panelWidth = 0; + int panelHeight = 0; + /** 0, 1, 2 or 3 for a rotation of 0, 90, 180 or 270 degrees */ + int rotation = 0; + PixelBuffer* target = nullptr; + /** Second hardware frame buffer, kept in sync with target */ + PixelBuffer* secondFrameBuffer = nullptr; + int bandHeight = 0; + + int logicalWidth() const { return (rotation % 2 == 0) ? panelWidth : panelHeight; } + int logicalHeight() const { return (rotation % 2 == 0) ? panelHeight : panelWidth; } + +public: + + ~BootScreen(); + + /** @return false when there is no usable display */ + bool begin(); + + /** Releases the display, so LVGL can take over. */ + void end(); + + /** @return the smallest logical display dimension, or 0 when there is no display */ + int getSmallestDimension() const; + + /** + * Shows a logo with text lines below it, centered on a black background. + * @param[in] logoPath path to a PNG file, or empty for no logo + * @param[in] lines text lines, wrapped when they're too long for the display + */ + void show(const std::string& logoPath, const std::vector& lines); +}; + +/** + * @param[in] action what happens on input, e.g. "reboot" + * @return "Press any key to " when a keyboard is available, otherwise + * "Touch the screen to " when a pointer is available, otherwise an empty string + */ +std::string getInputPrompt(const std::string& action); + +/** Blocks until any key is pressed on a keyboard or the screen is touched. */ +void waitForInput(); + +} diff --git a/Tactility/Private/Tactility/lvgl/IconFonts.h b/Tactility/Private/Tactility/lvgl/IconFonts.h new file mode 100644 index 000000000..56da2d0fa --- /dev/null +++ b/Tactility/Private/Tactility/lvgl/IconFonts.h @@ -0,0 +1,12 @@ +#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/Init.cpp b/Tactility/Source/Init.cpp new file mode 100644 index 000000000..c9c8b2c91 --- /dev/null +++ b/Tactility/Source/Init.cpp @@ -0,0 +1,54 @@ +#ifdef ESP_PLATFORM +#include +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace tt { + +constexpr auto* TAG = "Tactility"; + +void prepareFileSystems() { + char temp_path[FILE_MAX_PATH_STRING_LENGTH]; + if (paths_get_temp_path(temp_path, sizeof(temp_path)) != ERROR_NONE) { + LOG_E(TAG, "Failed to determine temp path"); + return; + } + if (!file::findOrCreateDirectory(temp_path, 0777)) { + LOG_E(TAG, "Failed to create %s", temp_path); + } +} + +bool init(Module* const dtsModules[], const DtsDevice dtsDevices[]) { + LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID); + + LOG_I(TAG, "Initializing kernel"); + if (kernel_init(dtsModules, dtsDevices) != ERROR_NONE) { + LOG_E(TAG, "Failed to initialize kernel"); + return false; + } + + initModules(); + +#ifdef ESP_PLATFORM + initEsp(); +#endif + + startBootApp(); + + return true; +} + +} // namespace diff --git a/Tactility/Source/InitApps.cpp b/Tactility/Source/InitApps.cpp new file mode 100644 index 000000000..d4c568759 --- /dev/null +++ b/Tactility/Source/InitApps.cpp @@ -0,0 +1,230 @@ +#include + +#ifdef ESP_PLATFORM +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace tt { + +constexpr auto* TAG = "Tactility"; + +// region Default apps + +// All apps below are converted to the new app-module + window-manager model, so their manifest +// is the new, global ::AppManifest, not this namespace's old tt::app::AppManifest. +namespace app { + namespace addgps { extern const ::AppManifest manifest; } + namespace alertdialog { extern const ::AppManifest manifest; } + namespace apphub { extern const ::AppManifest manifest; } + namespace apphubdetails { extern const ::AppManifest manifest; } + namespace apppackagedetails { extern const ::AppManifest manifest; } + namespace applist { extern const ::AppManifest manifest; } + namespace apppackagelist { extern const ::AppManifest manifest; } + namespace audiosettings { extern const ::AppManifest manifest; } + namespace boot { extern const ::AppManifest manifest; } + namespace development { extern const ::AppManifest manifest; } + namespace display { extern const ::AppManifest manifest; } + namespace files { extern const ::AppManifest manifest; } + namespace fileselection { extern const ::AppManifest manifest; } + namespace gpssettings { extern const ::AppManifest manifest; } + namespace grovesettings { extern const ::AppManifest manifest; } + namespace i2cscanner { extern const ::AppManifest manifest; } + namespace imageviewer { extern const ::AppManifest manifest; } + namespace inputdialog { extern const ::AppManifest manifest; } + namespace launcher { extern const ::AppManifest manifest; } + namespace ledstripsettings { extern const ::AppManifest manifest; } + namespace localesettings { extern const ::AppManifest manifest; } + namespace notes { extern const ::AppManifest manifest; } + namespace power { extern const ::AppManifest manifest; } + namespace poweroff { extern const ::AppManifest manifest; } + namespace selectiondialog { extern const ::AppManifest manifest; } + namespace settings { extern const ::AppManifest manifest; } + namespace setup { extern const ::AppManifest manifest; } + namespace shell { extern const ::AppManifest manifest; extern const ::AppManifest sh_manifest; } + namespace systeminfo { extern const ::AppManifest manifest; } + namespace terminal { extern const ::AppManifest manifest; } + namespace timedatesettings { extern const ::AppManifest manifest; } +#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED + namespace touchcalibration { extern const ::AppManifest manifest; } +#endif + namespace timezone { extern const ::AppManifest manifest; } + namespace usbsettings { extern const ::AppManifest manifest; } + namespace btmanage { extern const ::AppManifest manifest; } + namespace btpeersettings { extern const ::AppManifest manifest; } + namespace wifiapsettings { extern const ::AppManifest manifest; } + namespace wificonnect { extern const ::AppManifest manifest; } + namespace wifimanage { extern const ::AppManifest manifest; } + + namespace webserversettings { extern const ::AppManifest manifest; } +#ifdef ESP_PLATFORM + namespace apwebserver { extern const ::AppManifest manifest; } + namespace camera { extern const ::AppManifest manifest; } + namespace crashdiagnostics { extern const ::AppManifest manifest; } +#if CONFIG_TT_TDECK_WORKAROUND == 1 + namespace keyboardsettings { extern const ::AppManifest manifest; } // T-Deck only for now +#endif +#endif + + namespace trackballsettings { extern const ::AppManifest manifest; } // T-Deck only for now + +#if TT_FEATURE_SCREENSHOT_ENABLED + namespace screenshot { extern const ::AppManifest manifest; } +#endif + +#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) + namespace chat { extern const ::AppManifest manifest; } +#endif +} + +// endregion + +// List of all apps excluding Boot app (as Boot app calls this function indirectly) +static void registerInternalApps() { + LOG_I(TAG, "Registering internal apps"); + + app_manager_add(&app::alertdialog::manifest); + app_manager_add(&app::apppackagedetails::manifest); + app_manager_add(&app::apphub::manifest); + app_manager_add(&app::apphubdetails::manifest); + app_manager_add(&app::applist::manifest); + app_manager_add(&app::apppackagelist::manifest); + if (service::audio::isAvailable()) { + app_manager_add(&app::audiosettings::manifest); + } + if (device_exists_of_type(&DISPLAY_TYPE)) { + app_manager_add(&app::display::manifest); + } + if (device_exists_of_type(&LED_STRIP_TYPE)) { + app_manager_add(&app::ledstripsettings::manifest); + } + app_manager_add(&app::files::manifest); + app_manager_add(&app::fileselection::manifest); + app_manager_add(&app::i2cscanner::manifest); + app_manager_add(&app::imageviewer::manifest); + app_manager_add(&app::inputdialog::manifest); + app_manager_add(&app::launcher::manifest); + app_manager_add(&app::localesettings::manifest); + app_manager_add(&app::notes::manifest); + if (device_exists_of_type(&POWER_SUPPLY_TYPE)) { + app_manager_add(&app::poweroff::manifest); + } + app_manager_add(&app::settings::manifest); + app_manager_add(&app::selectiondialog::manifest); + app_manager_add(&app::setup::manifest); + app_manager_add(&app::shell::manifest); + app_manager_add(&app::shell::sh_manifest); + app_manager_add(&app::systeminfo::manifest); + app_manager_add(&app::timedatesettings::manifest); + app_manager_add(&app::terminal::manifest); +#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED + app_manager_add(&app::touchcalibration::manifest); +#endif + app_manager_add(&app::timezone::manifest); + app_manager_add(&app::wifiapsettings::manifest); + app_manager_add(&app::wificonnect::manifest); + app_manager_add(&app::wifimanage::manifest); + + app_manager_add(&app::development::manifest); + app_manager_add(&app::webserversettings::manifest); +#ifdef ESP_PLATFORM + app_manager_add(&app::apwebserver::manifest); + if (device_exists_of_type(&CAMERA_TYPE)) { + app_manager_add(&app::camera::manifest); + } + app_manager_add(&app::crashdiagnostics::manifest); +#if defined(CONFIG_TT_TDECK_WORKAROUND) + app_manager_add(&app::keyboardsettings::manifest); +#endif +#endif + + if (device_exists_of_type(&TRACKBALL_TYPE)) { + app_manager_add(&app::trackballsettings::manifest); + } + +#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED + app_manager_add(&app::usbsettings::manifest); +#endif + +#if TT_FEATURE_SCREENSHOT_ENABLED + app_manager_add(&app::screenshot::manifest); +#endif + +#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) + app_manager_add(&app::chat::manifest); +#endif + + if (device_exists_of_type(&GROVE_TYPE)) { + app_manager_add(&app::grovesettings::manifest); + } + + if (device_exists_of_type(&UART_CONTROLLER_TYPE) || device_exists_of_type(&GROVE_TYPE)) { + app_manager_add(&app::addgps::manifest); + app_manager_add(&app::gpssettings::manifest); + } + + if (device_exists_of_type(&POWER_SUPPLY_TYPE)) { + app_manager_add(&app::power::manifest); + } + +#if defined(CONFIG_BT_ENABLED) && CONFIG_BT_ENABLED + app_manager_add(&app::btmanage::manifest); + app_manager_add(&app::btpeersettings::manifest); +#endif +} + +// Registers every mounted filesystem's app install directory with app-module (see +// app_manager_install_path_add()/app_manager_install_path_scan() in app/install.h), then scans +// them once to register whatever's already installed there. +static void registerInstalledAppsFromFileSystems() { + file_system_for_each(nullptr, [](auto* fs, void* context) { + if (!file_system_is_mounted(fs)) return true; + char path[128]; + if (file_system_get_path(fs, path, sizeof(path)) != ERROR_NONE) return true; + const auto app_path = std::format("{}/tactility/app", path); + if (!app_path.starts_with(file::MOUNT_POINT_SYSTEM) && file::isDirectory(app_path)) { + LOG_I(TAG, "Registering install path %s", app_path.c_str()); + app_manager_install_path_add(app_path.c_str()); + } + return true; + }); + app_manager_install_path_scan(); +} + +void registerApps() { + registerInternalApps(); + registerInstalledAppsFromFileSystems(); +} + +void startBootApp() { + LOG_I(TAG, "Starting boot app"); + // The boot app takes care of registering system apps, user services and user apps, and starts LVGL. + app_manager_add(&app::boot::manifest); + uint32_t boot_instance_id = 0; + AppStartContext boot_context = app_start_context_for_manifest(&app::boot::manifest); + app_start_with_context(&boot_context, &boot_instance_id); +} + +} // namespace diff --git a/Tactility/Source/InitModules.cpp b/Tactility/Source/InitModules.cpp new file mode 100644 index 000000000..ccf45dba6 --- /dev/null +++ b/Tactility/Source/InitModules.cpp @@ -0,0 +1,82 @@ +#include + +#ifdef ESP_PLATFORM +#include +#include +#endif + +#if __has_include() && not defined(ESP_PLATFORM) +#define TT_IS_POSIX 1 +#else +#define TT_IS_POSIX 0 +#endif + +#if TT_IS_POSIX or defined(ESP_PLATFORM) // esp-idf supports certain posix symbols +#include +#endif + +#if TT_IS_POSIX +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Audio service exports to external ELF apps (Source/service/audio/AudioExports.cpp). +extern "C" Module tactility_audio_module; + +namespace tt { + +void initModules() { + // The following groups of symbols are sorted by the estimated chance of them occurring + + // C/C++/Posix symbols + check(module_ensure_started(&c_symbols_module) == ERROR_NONE); + check(module_ensure_started(&cjson_module) == ERROR_NONE); +#if TT_IS_POSIX or defined(ESP_PLATFORM) // esp-idf supports certain posix symbols + check(module_ensure_started(&posix_symbols_module) == ERROR_NONE); +#endif + check(module_ensure_started(&cpp_symbols_module) == ERROR_NONE); + // OS level symbols + check(module_ensure_started(&freertos_module) == ERROR_NONE); + check(module_ensure_started(&pthread_module) == ERROR_NONE); + // Other libraries + check(module_ensure_started(&http_module) == ERROR_NONE); + check(module_ensure_started(&graphics_module) == ERROR_NONE); + check(module_ensure_started(&lodepng_module) == ERROR_NONE); + check(module_ensure_started(&binfont_module) == ERROR_NONE); + check(module_ensure_started(&app_module) == ERROR_NONE); + check(module_ensure_started(&coreutils_module) == ERROR_NONE); + check(module_ensure_started(&crypt_module) == ERROR_NONE); + check(module_ensure_started(&audio_decoder_module) == ERROR_NONE); + check(module_ensure_started(&mbedtls_module) == ERROR_NONE); + check(module_ensure_started(&gps_module) == ERROR_NONE); + check(module_ensure_started(&gps_generic_module) == ERROR_NONE); + check(module_ensure_started(&gps_meshtastic_module) == ERROR_NONE); +#ifdef ESP_PLATFORM + check(module_ensure_started(&app_esp32_module) == ERROR_NONE); +#elif TT_IS_POSIX + check(module_ensure_started(&app_posix_module) == ERROR_NONE); +#endif + check(module_ensure_started(&tactility_audio_module) == ERROR_NONE); +} + +} // namespace diff --git a/Tactility/Source/InitServices.cpp b/Tactility/Source/InitServices.cpp new file mode 100644 index 000000000..5b9f20876 --- /dev/null +++ b/Tactility/Source/InitServices.cpp @@ -0,0 +1,55 @@ +#include + +#ifdef ESP_PLATFORM +#include +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace tt { + +// region Default services +namespace service { + // Primary + namespace audio { extern const ServiceManifest manifest; } + namespace development { extern const ServiceManifest manifest; } +#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) + namespace espnow { extern const ServiceManifest manifest; } +#endif +#ifdef ESP_PLATFORM + namespace rtctime { extern const ServiceManifest manifest; } +#endif + namespace webserver { extern const ServiceManifest manifest; } + +} + +// endregion + +void registerAndStartServices() { + if (device_exists_of_type(&AUDIO_STREAM_TYPE)) { + addService(service::audio::manifest); + } + check(module_ensure_started(&wifi_module) == ERROR_NONE); + addService(service::development::manifest); + addService(service::webserver::manifest); + +#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) + addService(service::espnow::manifest); +#endif +#if defined(ESP_PLATFORM) + if (device_exists_of_type(&RTC_TYPE)) { + addService(service::rtctime::manifest); + } +#endif +} + +} // namespace diff --git a/Tactility/Source/Main.cpp b/Tactility/Source/Main.cpp index cc861a429..d1f9b48da 100644 --- a/Tactility/Source/Main.cpp +++ b/Tactility/Source/Main.cpp @@ -1,15 +1,28 @@ #include +#include #include +#include + #ifndef ESP_PLATFORM #include #endif +constexpr auto* TAG = "Main"; + extern "C" { void app_main() { - tt::run(dts_modules, dts_devices); + if (!tt::init(dts_modules, dts_devices)) { + return; + } + + LOG_I(TAG, "Main dispatcher ready"); + const auto dispatcher = tt::getMainDispatcherHandle(); + while (true) { + dispatcher_consume(dispatcher); + } } -} // extern \ No newline at end of file +} // extern diff --git a/Tactility/Source/MainDispatcher.cpp b/Tactility/Source/MainDispatcher.cpp new file mode 100644 index 000000000..06e4ba04b --- /dev/null +++ b/Tactility/Source/MainDispatcher.cpp @@ -0,0 +1,41 @@ +#include +#include + +// Implements the deprecated MainDispatcher API +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +namespace tt { + +static DispatcherHandle_t mainDispatcherHandle = dispatcher_alloc(); + +namespace { + +void mainDispatcherTrampoline(void* context) { + auto* function = static_cast(context); + (*function)(); + delete function; +} + +} // namespace + +bool MainDispatcher::dispatch(Function function, TickType_t timeout) const { + auto* boxed = new Function(std::move(function)); + if (dispatcher_dispatch_timed(handle, boxed, mainDispatcherTrampoline, timeout) != ERROR_NONE) { + delete boxed; + return false; + } + return true; +} + +MainDispatcher getMainDispatcher() { + return MainDispatcher(mainDispatcherHandle); +} + +DispatcherHandle_t getMainDispatcherHandle() { + return mainDispatcherHandle; +} + +} // namespace + +#pragma GCC diagnostic pop diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp deleted file mode 100644 index e6bf9e71a..000000000 --- a/Tactility/Source/Tactility.cpp +++ /dev/null @@ -1,605 +0,0 @@ -#ifdef ESP_PLATFORM -#include -#include -#include -#endif - -#if __has_include() && not defined(ESP_PLATFORM) -#define TT_IS_POSIX 1 -#else -#define TT_IS_POSIX 0 -#endif - -#if TT_IS_POSIX or defined(ESP_PLATFORM) // esp-idf supports certain posix symbols -#include -#endif - -#if TT_IS_POSIX -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - -// Audio service exports to external ELF apps (Source/service/audio/AudioExports.cpp). -extern "C" Module tactility_audio_module; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace tt { - -constexpr auto* TAG = "Tactility"; - -static DispatcherHandle_t mainDispatcherHandle = dispatcher_alloc(); - -namespace { - -void mainDispatcherTrampoline(void* context) { - auto* function = static_cast(context); - (*function)(); - delete function; -} - -} // namespace - -bool MainDispatcher::dispatch(Function function, TickType_t timeout) const { - auto* boxed = new Function(std::move(function)); - if (dispatcher_dispatch_timed(handle, boxed, mainDispatcherTrampoline, timeout) != ERROR_NONE) { - delete boxed; - return false; - } - return true; -} - -// region Default services -namespace service { - // Primary - namespace audio { extern const ServiceManifest manifest; } - namespace autorotate { extern const ServiceManifest manifest; } - namespace development { extern const ServiceManifest manifest; } -#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) - namespace espnow { extern const ServiceManifest manifest; } -#endif - // Secondary (UI) - namespace memorychecker { extern const ServiceManifest manifest; } - namespace statusbar { extern const ServiceManifest manifest; } -#ifdef ESP_PLATFORM - namespace displayidle { extern const ServiceManifest manifest; } - namespace keyboardidle { extern const ServiceManifest manifest; } - namespace rtctime { extern const ServiceManifest manifest; } -#endif -#if TT_FEATURE_SCREENSHOT_ENABLED - namespace screenshot { extern const ServiceManifest manifest; } -#endif - namespace webserver { extern const ServiceManifest manifest; } - -} - -// endregion - -// region Default apps - -// All apps below are converted to the new app-module + window-manager model, so their manifest -// is the new, global ::AppManifest, not this namespace's old tt::app::AppManifest. -namespace app { - namespace addgps { extern const ::AppManifest manifest; } - namespace alertdialog { extern const ::AppManifest manifest; } - namespace apphub { extern const ::AppManifest manifest; } - namespace apphubdetails { extern const ::AppManifest manifest; } - namespace apppackagedetails { extern const ::AppManifest manifest; } - namespace applist { extern const ::AppManifest manifest; } - namespace apppackagelist { extern const ::AppManifest manifest; } - namespace audiosettings { extern const ::AppManifest manifest; } - namespace boot { extern const ::AppManifest manifest; } - namespace development { extern const ::AppManifest manifest; } - namespace display { extern const ::AppManifest manifest; } - namespace files { extern const ::AppManifest manifest; } - namespace fileselection { extern const ::AppManifest manifest; } - namespace gpssettings { extern const ::AppManifest manifest; } - namespace grovesettings { extern const ::AppManifest manifest; } - namespace i2cscanner { extern const ::AppManifest manifest; } - namespace imageviewer { extern const ::AppManifest manifest; } - namespace inputdialog { extern const ::AppManifest manifest; } - namespace launcher { extern const ::AppManifest manifest; } - namespace ledstripsettings { extern const ::AppManifest manifest; } - namespace localesettings { extern const ::AppManifest manifest; } - namespace notes { extern const ::AppManifest manifest; } - namespace power { extern const ::AppManifest manifest; } - namespace poweroff { extern const ::AppManifest manifest; } - namespace selectiondialog { extern const ::AppManifest manifest; } - namespace settings { extern const ::AppManifest manifest; } - namespace setup { extern const ::AppManifest manifest; } - namespace shell { extern const ::AppManifest manifest; extern const ::AppManifest sh_manifest; } - namespace systeminfo { extern const ::AppManifest manifest; } - namespace terminal { extern const ::AppManifest manifest; } - namespace timedatesettings { extern const ::AppManifest manifest; } -#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED - namespace touchcalibration { extern const ::AppManifest manifest; } -#endif - namespace timezone { extern const ::AppManifest manifest; } - namespace usbsettings { extern const ::AppManifest manifest; } - namespace btmanage { extern const ::AppManifest manifest; } - namespace btpeersettings { extern const ::AppManifest manifest; } - namespace wifiapsettings { extern const ::AppManifest manifest; } - namespace wificonnect { extern const ::AppManifest manifest; } - namespace wifimanage { extern const ::AppManifest manifest; } - - namespace webserversettings { extern const ::AppManifest manifest; } -#ifdef ESP_PLATFORM - namespace apwebserver { extern const ::AppManifest manifest; } - namespace camera { extern const ::AppManifest manifest; } - namespace crashdiagnostics { extern const ::AppManifest manifest; } -#if CONFIG_TT_TDECK_WORKAROUND == 1 - namespace keyboardsettings { extern const ::AppManifest manifest; } // T-Deck only for now -#endif -#endif - - namespace trackballsettings { extern const ::AppManifest manifest; } // T-Deck only for now - -#if TT_FEATURE_SCREENSHOT_ENABLED - namespace screenshot { extern const ::AppManifest manifest; } -#endif - -#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) - namespace chat { extern const ::AppManifest manifest; } -#endif -} - -// endregion - -// List of all apps excluding Boot app (as Boot app calls this function indirectly) -static void registerInternalApps() { - LOG_I(TAG, "Registering internal apps"); - - app_manager_add(&app::alertdialog::manifest); - app_manager_add(&app::apppackagedetails::manifest); - app_manager_add(&app::apphub::manifest); - app_manager_add(&app::apphubdetails::manifest); - app_manager_add(&app::applist::manifest); - app_manager_add(&app::apppackagelist::manifest); - if (service::audio::isAvailable()) { - app_manager_add(&app::audiosettings::manifest); - } - if (device_exists_of_type(&DISPLAY_TYPE)) { - app_manager_add(&app::display::manifest); - } - if (device_exists_of_type(&LED_STRIP_TYPE)) { - app_manager_add(&app::ledstripsettings::manifest); - } - app_manager_add(&app::files::manifest); - app_manager_add(&app::fileselection::manifest); - app_manager_add(&app::i2cscanner::manifest); - app_manager_add(&app::imageviewer::manifest); - app_manager_add(&app::inputdialog::manifest); - app_manager_add(&app::launcher::manifest); - app_manager_add(&app::localesettings::manifest); - app_manager_add(&app::notes::manifest); - if (device_exists_of_type(&POWER_SUPPLY_TYPE)) { - app_manager_add(&app::poweroff::manifest); - } - app_manager_add(&app::settings::manifest); - app_manager_add(&app::selectiondialog::manifest); - app_manager_add(&app::setup::manifest); - app_manager_add(&app::shell::manifest); - app_manager_add(&app::shell::sh_manifest); - app_manager_add(&app::systeminfo::manifest); - app_manager_add(&app::timedatesettings::manifest); - app_manager_add(&app::terminal::manifest); -#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED - app_manager_add(&app::touchcalibration::manifest); -#endif - app_manager_add(&app::timezone::manifest); - app_manager_add(&app::wifiapsettings::manifest); - app_manager_add(&app::wificonnect::manifest); - app_manager_add(&app::wifimanage::manifest); - - app_manager_add(&app::development::manifest); - app_manager_add(&app::webserversettings::manifest); -#ifdef ESP_PLATFORM - app_manager_add(&app::apwebserver::manifest); - if (device_exists_of_type(&CAMERA_TYPE)) { - app_manager_add(&app::camera::manifest); - } - app_manager_add(&app::crashdiagnostics::manifest); -#if defined(CONFIG_TT_TDECK_WORKAROUND) - app_manager_add(&app::keyboardsettings::manifest); -#endif -#endif - - if (device_exists_of_type(&TRACKBALL_TYPE)) { - app_manager_add(&app::trackballsettings::manifest); - } - -#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED - app_manager_add(&app::usbsettings::manifest); -#endif - -#if TT_FEATURE_SCREENSHOT_ENABLED - app_manager_add(&app::screenshot::manifest); -#endif - -#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) - app_manager_add(&app::chat::manifest); -#endif - - if (device_exists_of_type(&GROVE_TYPE)) { - app_manager_add(&app::grovesettings::manifest); - } - - if (device_exists_of_type(&UART_CONTROLLER_TYPE) || device_exists_of_type(&GROVE_TYPE)) { - app_manager_add(&app::addgps::manifest); - app_manager_add(&app::gpssettings::manifest); - } - - if (device_exists_of_type(&POWER_SUPPLY_TYPE)) { - app_manager_add(&app::power::manifest); - } - -#if defined(CONFIG_BT_ENABLED) && CONFIG_BT_ENABLED - app_manager_add(&app::btmanage::manifest); - app_manager_add(&app::btpeersettings::manifest); -#endif -} - -// Registers every mounted filesystem's app install directory with app-module (see -// app_manager_install_path_add()/app_manager_install_path_scan() in app/install.h), then scans -// them once to register whatever's already installed there. -static void registerInstalledAppsFromFileSystems() { - file_system_for_each(nullptr, [](auto* fs, void* context) { - if (!file_system_is_mounted(fs)) return true; - char path[128]; - if (file_system_get_path(fs, path, sizeof(path)) != ERROR_NONE) return true; - const auto app_path = std::format("{}/tactility/app", path); - if (!app_path.starts_with(file::MOUNT_POINT_SYSTEM) && file::isDirectory(app_path)) { - LOG_I(TAG, "Registering install path %s", app_path.c_str()); - app_manager_install_path_add(app_path.c_str()); - } - return true; - }); - app_manager_install_path_scan(); -} - -static void registerAndStartServices() { - LOG_I(TAG, "Registering and starting primary system services"); - if (device_exists_of_type(&AUDIO_STREAM_TYPE)) { - addService(service::audio::manifest); - } - check(module_ensure_started(&wifi_module) == ERROR_NONE); - addService(service::development::manifest); - addService(service::webserver::manifest); - -#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLED) - addService(service::espnow::manifest); -#endif -#if defined(ESP_PLATFORM) - if (device_exists_of_type(&RTC_TYPE)) { - addService(service::rtctime::manifest); - } -#endif -} - -void prepareFileSystems() { - char temp_path[FILE_MAX_PATH_STRING_LENGTH]; - if (paths_get_temp_path(temp_path, sizeof(temp_path)) != ERROR_NONE) { - LOG_E(TAG, "Failed to determine temp path"); - return; - } - if (!file::findOrCreateDirectory(temp_path, 0777)) { - LOG_E(TAG, "Failed to create %s", temp_path); - } -} - -void registerApps() { - registerInternalApps(); - registerInstalledAppsFromFileSystems(); -} - -static void stopAppFromToolbar(lv_event_t*) { - // Default nav action for any toolbar that doesn't override it itself. Prefer the topmost - // new-model app if one is showing; fall back to the old system otherwise (this is what - // every not-yet-converted app's toolbar still relies on). - AppInstanceId topmost = 0; - check(app_manager_get_topmost_instance_id(&topmost) == ERROR_NONE); - - app_event_emit_close(topmost); -} - -// The on-screen keyboard widget itself, constructed during windowManagerScreenInit -static LvglSoftwareKeyboard softwareKeyboard { .object = nullptr }; - -static lv_obj_t* windowManagerScreenInit(lv_obj_t* root) { - lv_obj_t* vertical_container = lv_obj_create(root); - lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); - lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(vertical_container, 0, LV_STATE_DEFAULT); - lv_obj_set_style_pad_gap(vertical_container, 0, LV_STATE_DEFAULT); - lv_obj_set_style_bg_color(vertical_container, lv_color_black(), LV_STATE_DEFAULT); - lv_obj_set_style_border_width(vertical_container, 0, LV_STATE_DEFAULT); - lv_obj_set_style_radius(vertical_container, 0, LV_STATE_DEFAULT); - lv_obj_remove_flag(vertical_container, LV_OBJ_FLAG_SCROLLABLE); - - lvgl::statusbar_create(vertical_container); - - auto* app_container = lv_obj_create(vertical_container); - lv_obj_set_style_pad_all(app_container, 0, LV_STATE_DEFAULT); - lv_obj_set_style_border_width(app_container, 0, LV_STATE_DEFAULT); - lv_obj_set_width(app_container, LV_PCT(100)); - lv_obj_set_flex_grow(app_container, 1); - lv_obj_set_flex_flow(app_container, LV_FLEX_FLOW_COLUMN); - lv_obj_remove_flag(app_container, LV_OBJ_FLAG_SCROLLABLE); - - // Parented to root (not app_container/vertical_container) so it overlays on top of - // everything, including the statusbar, regardless of which app is showing. Hidden until a - // focused textarea shows it (see lvgl_keyboard_add_textarea()/textarea_show_keyboard()). - lvgl_software_keyboard_construct(&softwareKeyboard, root); - - return app_container; -} - -#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED - -// Applies the calibration persisted by the touch calibration app to the live pointer indev. -// lvgl_devices_attach() runs before onLvglStarted(), so the default indev already exists here. -static void applySavedTouchCalibration() { - settings::touch::TouchCalibrationSettings settings = settings::touch::loadOrGetDefault(); - if (!settings.enabled || !settings::touch::isValid(settings)) { - return; - } - - LvglPointerCalibration calibration = { - .x_min = settings.xMin, - .x_max = settings.xMax, - .y_min = settings.yMin, - .y_max = settings.yMax, - }; - - lvgl_lock(); - auto* indev = lvgl_pointer_get_default(); - if (indev != nullptr) { - lvgl_pointer_set_calibration(indev, &calibration); - } - lvgl_unlock(); -} - -#endif // CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED - -static void onLvglStarted() { - // lv_display_create() (inside lvgl_devices_attach(), which already ran by this point) always - // resets rotation to LV_DISPLAY_ROTATION_0. The only other code that ever applies a saved - // orientation is the display settings app's dropdown change handler, so without this, every - // LVGL restart (not just first boot) silently drops back to unrotated. Must run before - // window_manager_start() below builds the window tree against the display's current size. - lvgl_lock(); - if (auto* display = lv_display_get_default(); display != nullptr) { - auto displaySettings = settings::display::loadOrGetDefault(); - lv_display_set_rotation(display, settings::display::toLvglDisplayRotation(displaySettings.orientation)); - } - lvgl_unlock(); - - window_manager_configure(windowManagerScreenInit); - check(module_ensure_started(&lvgl_window_manager_module) == ERROR_NONE); - - ToolbarConfig toolbar_config = { .nav_action_callback = stopAppFromToolbar }; - lvgl_toolbar_configure(&toolbar_config); - - addService(service::statusbar::manifest); - addService(service::memorychecker::manifest); -#if defined(ESP_PLATFORM) - addService(service::displayidle::manifest); -#endif - if (device_exists_of_type(&IMU_TYPE)) { - addService(service::autorotate::manifest); - } -#if defined(CONFIG_TT_TDECK_WORKAROUND) - addService(service::keyboardidle::manifest); -#endif -#if TT_FEATURE_SCREENSHOT_ENABLED - addService(service::screenshot::manifest); -#endif - - lvgl::startUsbHidInput(); - lvgl::startKeyboardDeviceListener(); - lvgl::initTrackball(); - -#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED - applySavedTouchCalibration(); -#endif - - memory_log_stats(); -} - -static void onLvglStopped() { - lvgl::stopKeyboardDeviceListener(); - lvgl::stopUsbHidInput(); - - if (device_exists_of_type(&IMU_TYPE)) { - check(service::removeService(service::autorotate::manifest.id)); - } -#if TT_FEATURE_SCREENSHOT_ENABLED - check(service::removeService(service::screenshot::manifest.id)); -#endif -#if defined(CONFIG_TT_TDECK_WORKAROUND) - check(service::removeService(service::keyboardidle::manifest.id)); -#endif -#if defined(ESP_PLATFORM) - check(service::removeService(service::displayidle::manifest.id)); -#endif - check(service::removeService(service::memorychecker::manifest.id)); - check(service::removeService(service::statusbar::manifest.id)); - - if (softwareKeyboard.object != nullptr) { - // lv_obj_delete() walks/mutates the object graph (event lists, group membership, - // parent/child links). Without the LVGL lock this can race the LVGL port task's own - // concurrent traversal (input dispatch, timers, animations), producing an intermittent - // double-free/use-after-free inside lv_obj_destructor/lv_event_mark_deleted. - lvgl_lock(); - lvgl_software_keyboard_destruct(&softwareKeyboard); - lvgl_unlock(); - } - - module_stop(&lvgl_window_manager_module); - - memory_log_stats(); -} - -void run(Module* const dtsModules[], const DtsDevice dtsDevices[]) { - LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID); - - LOG_I(TAG, "Initializing kernel"); - if (kernel_init(dtsModules, dtsDevices) != ERROR_NONE) { - LOG_E(TAG, "Failed to initialize kernel"); - return; - } - - // The following groups of symbols are sorted by the estimated chance of them occurring - - // C/C++/Posix symbols - check(module_ensure_started(&c_symbols_module) == ERROR_NONE); - check(module_ensure_started(&cjson_module) == ERROR_NONE); -#if TT_IS_POSIX or defined(ESP_PLATFORM) // esp-idf supports certain posix symbols - check(module_ensure_started(&posix_symbols_module) == ERROR_NONE); -#endif - check(module_ensure_started(&cpp_symbols_module) == ERROR_NONE); - // OS level symbols - check(module_ensure_started(&freertos_module) == ERROR_NONE); - check(module_ensure_started(&pthread_module) == ERROR_NONE); - // Other libraries - check(module_ensure_started(&http_module) == ERROR_NONE); - check(module_ensure_started(&graphics_module) == ERROR_NONE); - check(module_ensure_started(&app_module) == ERROR_NONE); - check(module_ensure_started(&coreutils_module) == ERROR_NONE); - check(module_ensure_started(&crypt_module) == ERROR_NONE); - check(module_ensure_started(&audio_decoder_module) == ERROR_NONE); - check(module_ensure_started(&mbedtls_module) == ERROR_NONE); - check(module_ensure_started(&gps_module) == ERROR_NONE); - check(module_ensure_started(&gps_generic_module) == ERROR_NONE); - check(module_ensure_started(&gps_meshtastic_module) == ERROR_NONE); -#ifdef ESP_PLATFORM - check(module_ensure_started(&app_esp32_module) == ERROR_NONE); -#elif TT_IS_POSIX - check(module_ensure_started(&app_posix_module) == ERROR_NONE); -#endif - check(module_ensure_started(&tactility_audio_module) == ERROR_NONE); - -#ifdef ESP_PLATFORM - initEsp(); -#endif - - settings::initTimeZone(); - - // Attempt to start all disabled SD cards (some require delayed init) - hal::sdcard::startAll(); - - network::ntp::init(); - bluetooth::systemStart(); - - registerAndStartServices(); - - lvgl_module_configure((LvglModuleConfig) { - .on_start = onLvglStarted, - .on_stop = onLvglStopped, - .task_priority = THREAD_PRIORITY_HIGHER, - .task_stack_size = 9120, -#ifdef ESP_PLATFORM - .task_affinity = getCpuAffinityConfiguration().graphics -#endif - }); - check(module_ensure_started(&lvgl_module) == ERROR_NONE); - - LOG_I(TAG, "Core systems ready"); - - LOG_I(TAG, "Starting boot app"); - // The boot app takes care of registering system apps, user services and user apps. - // It's a new-model (app-module + window-manager) app now, replacing the old app::start(). - app_manager_add(&app::boot::manifest); - uint32_t boot_instance_id = 0; - AppStartContext boot_context = app_start_context_for_manifest(&app::boot::manifest); - app_start_with_context(&boot_context, &boot_instance_id); - - LOG_I(TAG, "Main dispatcher ready"); - while (true) { - dispatcher_consume(mainDispatcherHandle); - } -} - -MainDispatcher getMainDispatcher() { - return MainDispatcher(mainDispatcherHandle); -} - -} // namespace diff --git a/Tactility/Source/TactilityEsp.cpp b/Tactility/Source/TactilityEsp.cpp index 802289f18..f16f19493 100644 --- a/Tactility/Source/TactilityEsp.cpp +++ b/Tactility/Source/TactilityEsp.cpp @@ -10,16 +10,13 @@ constexpr auto* TAG = "Tactility"; namespace tt { -static void initNetwork() { - LOG_I(TAG, "Init network"); +void initEsp() { + LOG_I(TAG, "Init esp_netif"); ESP_ERROR_CHECK(esp_netif_init()); + LOG_I(TAG, "Init esp_event_loop"); ESP_ERROR_CHECK(esp_event_loop_create_default()); } -void initEsp() { - initNetwork(); -} - } // namespace #endif diff --git a/Tactility/Source/app/boot/Boot.cpp b/Tactility/Source/app/boot/Boot.cpp index 6e8fa1986..b8fbb807b 100644 --- a/Tactility/Source/app/boot/Boot.cpp +++ b/Tactility/Source/app/boot/Boot.cpp @@ -1,381 +1,35 @@ -#include "Tactility/app/alertdialog/AlertDialog.h" -#include "tactility/memory.h" -#include "tactility/system_event.h" +#include #include -#include -#include -#include -#include +#include #include #include -#include #include #include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#ifdef ESP_PLATFORM -#include -#include -#include -#include -#else -#define CONFIG_TT_SPLASH_DURATION 0 -#endif namespace tt::app::boot { -constexpr auto* TAG = "Boot"; - extern const ::AppManifest manifest; namespace { -// Snapshot of hal::usb::isUsbBootMode(), taken before boot work starts and potentially clears -// the underlying flag via setupUsbBootMode()/resetUsbBootMode(). createSplashWidgets() reads -// this instead of the live flag to avoid a race between the two. -std::atomic isUsbBootSplash = false; - -// Set when CONFIG_TT_USER_DATA_LOCATION_SD is defined but no SD card is mounted. Switches the -// window to an error screen and halts before starting the next app. -std::atomic sdCardMissing = false; - -// Set when setupUsbBootMode() fails -std::atomic usbBootModeFailed = false; -std::string usbBootModeFailedReason; - -uint32_t bootAppInstanceId = 0; -WindowId bootWindowId = 0; - -#ifdef ESP_PLATFORM -constexpr auto PARTITION_PREFIX = std::string("/"); -#else -constexpr auto PARTITION_PREFIX = std::string(""); -#endif - -// Equivalent of AppPaths::getAssetsPath() for the internal "Boot" app id, without needing a -// live AppContext (which this app no longer has under the new app-module model). -std::string getBootAssetsPath(const std::string& childPath) { - return std::format("{}{}/app/Boot/assets/{}", PARTITION_PREFIX, file::SYSTEM_PARTITION_NAME, childPath); -} - -void setupDisplay() { - // TODO: Support for multiple displays - - Device* display = nullptr; - if (device_get_first_by_type(&DISPLAY_TYPE, &display) != ERROR_NONE) { - LOG_I(TAG, "No kernel display"); - return; - } - - // Set backlight brightness - Device* backlight; - if (display_get_backlight(display, &backlight) == ERROR_NONE) { - if (!device_is_ready(backlight)) { - if (device_start(backlight) != ERROR_NONE) { - LOG_E(TAG, "Failed to start %s", backlight->name); - } - } - - settings::display::DisplaySettings settings; - if (settings::display::load(settings)) { - } else { - settings = settings::display::getDefault(); - } - - if (backlight_set_brightness(backlight, settings.backlightDuty) == ERROR_NONE) { - LOG_I(TAG, "Backlight for %s set to %d", display->name, settings.backlightDuty); - } else { - LOG_E(TAG, "Failed to set brightness of %s", backlight->name); - } - device_put(backlight); - } else { - LOG_I(TAG, "No backlight for %s", display->name); - } - - device_put(display); -} - -// Returns true if either the MSC screen or the failure screen now owns the display, in which -// case the caller must not proceed to the normal boot path (registerApps()/startNextApp()). -bool setupUsbBootMode() { - if (!hal::usb::isUsbBootMode()) { - return false; - } - - LOG_I(TAG, "Rebooting into mass storage device mode"); - auto mode = hal::usb::getUsbBootMode(); // Get mode before reset - hal::usb::resetUsbBootMode(); - delay_millis(3000); - - bool started = false; - if (mode == hal::usb::BootMode::Flash) { - started = hal::usb::startMassStorageWithFlash(true); - } else if (mode == hal::usb::BootMode::Sdmmc) { - started = hal::usb::startMassStorageWithSdmmc(true); - } - - if (!started) { - usbBootModeFailedReason = hal::usb::getLastError(); - usbBootModeFailed = true; - } - - return true; -} - -void waitForMinimalSplashDuration(TickType_t startTime) { - const auto end_time = get_ticks(); - const auto ticks_passed = end_time - startTime; - constexpr auto minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS); - if (minimum_ticks > ticks_passed) { - delay_ticks(minimum_ticks - ticks_passed); - } -} - -std::string getLauncherAppId() { - settings::BootSettings boot_properties; - // When boot.properties hasn't been overridden, return default - if (!settings::loadBootSettings(boot_properties)) { - return CONFIG_TT_LAUNCHER_APP_ID; - } - - // When boot properties didn't specify an override, return default - if (boot_properties.launcherAppId.empty()) { - LOG_E(TAG, "Failed to load launcher configuration, or launcher not configured"); - return CONFIG_TT_LAUNCHER_APP_ID; - } - - // If the app in the boot.properties does not exist, return default - AppManifest manifest; - if (app_manager_find_manifest(boot_properties.launcherAppId.c_str(), &manifest) != ERROR_NONE) { - LOG_E(TAG, "Launcher app %s not found", boot_properties.launcherAppId.c_str()); - return CONFIG_TT_LAUNCHER_APP_ID; - } - - // The boot.properties launcher app id is valid - return boot_properties.launcherAppId; -} - -int getSmallestDimension() { - auto* display = lv_display_get_default(); - int width = lv_display_get_horizontal_resolution(display); - int height = lv_display_get_vertical_resolution(display); - return std::min(width, height); -} - -void createSplashWidgets(lv_obj_t* root, void*) { - lvgl::obj_set_style_bg_blacken(root); - lv_obj_set_style_border_width(root, 0, LV_STATE_DEFAULT); - lv_obj_set_style_radius(root, 0, LV_STATE_DEFAULT); - - auto* image = lv_image_create(root); - lv_obj_set_size(image, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_align(image, LV_ALIGN_CENTER, 0, 0); - - const char* logo; - // TODO: Replace with automatic asset buckets like on Android - if (getSmallestDimension() < 150) { // e.g. Cardputer - logo = isUsbBootSplash ? "logo_usb.png" : "logo_small.png"; - } else { - logo = isUsbBootSplash ? "logo_usb.png" : "logo.png"; - } - const auto logo_path = lvgl::PATH_PREFIX + getBootAssetsPath(logo); - LOG_I(TAG, "%s", logo_path.c_str()); - lv_image_set_src(image, logo_path.c_str()); - -#ifdef ESP_PLATFORM - if (isUsbBootSplash) { - auto* button = lv_button_create(root); - lv_obj_align(button, LV_ALIGN_BOTTOM_MID, 0, -16); - auto* label = lv_label_create(button); - lv_label_set_text(label, "Return to OS"); - lv_obj_add_event_cb(button, [](lv_event_t*) { - hal::usb::stop(); - esp_restart(); - }, LV_EVENT_SHORT_CLICKED, nullptr); - } -#endif -} - -void selectIfNoPointer(lv_obj_t* button) { - if (!lvgl_indev_exists(LV_INDEV_TYPE_POINTER)) { - lv_group_focus_obj(button); - lv_obj_add_state(button, LV_STATE_FOCUS_KEY); - } -} - -void createSdCardMissingWidgets(lv_obj_t* root, void*) { - lvgl::obj_set_style_bg_blacken(root); - lv_obj_set_style_border_width(root, 0, LV_STATE_DEFAULT); - lv_obj_set_style_radius(root, 0, LV_STATE_DEFAULT); - lv_obj_set_flex_flow(root, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - auto* label = lv_label_create(root); - lv_label_set_text(label, "SD card not found.\nPlease insert one and reboot."); - lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT); - lv_obj_set_style_text_color(label, lv_color_white(), LV_STATE_DEFAULT); - - auto* button = lv_button_create(root); - lv_obj_set_style_margin_top(button, 16, LV_STATE_DEFAULT); - auto* button_label = lv_label_create(button); - lv_label_set_text(button_label, "Reboot"); - lv_obj_add_event_cb(button, [](lv_event_t*) { -#ifdef ESP_PLATFORM - esp_restart(); -#endif - }, LV_EVENT_SHORT_CLICKED, nullptr); - selectIfNoPointer(button); -} - -// Replaces the splash with a self-contained error screen (no dependency on the old alertdialog -// app - this app has no parent in the old App stack to deliver a result back to). -void showSdCardMissingScreen() { - if (bootWindowId != 0) { - window_manager_remove(bootWindowId); - } - bootWindowId = window_manager_create(bootAppInstanceId, createSdCardMissingWidgets, nullptr); -} - -void createUsbBootModeFailedWidgets(lv_obj_t* root, void*) { - lvgl::obj_set_style_bg_blacken(root); - lv_obj_set_style_border_width(root, 0, LV_STATE_DEFAULT); - lv_obj_set_style_radius(root, 0, LV_STATE_DEFAULT); - lv_obj_set_flex_flow(root, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - auto* label = lv_label_create(root); - lv_label_set_text(label, std::format("Failed to start USB mass storage:\n{}", usbBootModeFailedReason).c_str()); - lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT); - lv_obj_set_style_text_color(label, lv_color_white(), LV_STATE_DEFAULT); - - auto* button = lv_button_create(root); - lv_obj_set_style_margin_top(button, 16, LV_STATE_DEFAULT); - auto* button_label = lv_label_create(button); - lv_label_set_text(button_label, "Reboot"); - lv_obj_add_event_cb(button, [](lv_event_t*) { -#ifdef ESP_PLATFORM - esp_restart(); -#endif - }, LV_EVENT_SHORT_CLICKED, nullptr); - selectIfNoPointer(button); -} - -void showUsbBootModeFailedScreen() { - if (bootWindowId != 0) { - window_manager_remove(bootWindowId); - } - bootWindowId = window_manager_create(bootAppInstanceId, createUsbBootModeFailedWidgets, nullptr); -} - -void startNextApp() { - if (sdCardMissing) { - showSdCardMissingScreen(); - return; - } - -#ifdef ESP_PLATFORM - if (esp_reset_reason() == ESP_RST_PANIC) { - crashdiagnostics::start(); // fire-and-forget; no result expected back - return; - } -#endif - - auto launcher_app_id = getLauncherAppId(); - uint32_t launcher_instance_id = 0; - AppStartContext context; - if (app_start_context_from_id(launcher_app_id.c_str(), &context) == ERROR_NONE) { - app_start_with_context(&context, &launcher_instance_id); - } -} - -void runBootSequence(TickType_t startTime) { - LOG_I(TAG, "Starting boot sequence"); - - // Give the UI some time to redraw - // If we don't do this, various init calls will read files and block SPI IO for the display - // This would result in a blank/black screen being shown during this phase of the boot process - // This works with 5 ms on a T-Lora Pager, so we give it 10 ms to be safe - delay_millis(10); - - LOG_I(TAG, "Setup display"); - setupDisplay(); - LOG_I(TAG, "Prepare file systems"); - prepareFileSystems(); - -#ifdef CONFIG_TT_USER_DATA_LOCATION_SD - std::string sd_path; - if (!findFirstMountedSdCardPath(sd_path)) { - LOG_E(TAG, "SD card not found"); - sdCardMissing = true; - } -#endif - - if (setupUsbBootMode()) { - if (usbBootModeFailed) { - showUsbBootModeFailedScreen(); - } - // Stay open: the splash's "Return to OS" button or the failure screen's "Reboot" button. - return; - } - - registerApps(); - waitForMinimalSplashDuration(startTime); - startNextApp(); - - if (sdCardMissing) { - // Stay open: the error screen's "Reboot" button is this app's only way to leave here. - return; - } - - // This event will likely block as other systems are initialized - // e.g. Wi-Fi reads AP configs from SD card - LOG_I(TAG, "Publish event"); - system_event_emit(KERNEL_EVENT_BOOT_COMPLETED, nullptr, 0); - - app_event_emit_close(app_scheduler_current_app_id()); -} - int32_t appMain(int argc, char* argv[]) { - uint32_t appInstanceId = app_scheduler_current_app_id(); - bootAppInstanceId = appInstanceId; const auto start_time = get_ticks(); - // Snapshot before runBootSequence() potentially clears the flag via setupUsbBootMode() - isUsbBootSplash = hal::usb::isUsbBootMode(); - sdCardMissing = false; - TaskEventGroup event_group {}; task_event_group_construct(&event_group); AppEventSubscription sub {}; check(app_event_subscribe(&sub, &event_group) == ERROR_NONE); - bootWindowId = window_manager_create(appInstanceId, createSplashWidgets, nullptr); - - runBootSequence(start_time); + if (bootInit(start_time)) { + app_event_emit_close(app_scheduler_current_app_id()); + } // Waits until app_start(launcher) (or a permanent stop) tells us to give up - // startNextApp() above is what triggers that, via app-module's "save the previously active - // app" policy, unless sdCardMissing halted before it. + // app" policy. When the boot halted on an error screen, this waits forever. while (true) { task_event_group_wait_any(&event_group, nullptr, portMAX_DELAY); @@ -390,9 +44,6 @@ int32_t appMain(int argc, char* argv[]) { if (shouldClose) break; } - if (bootWindowId != 0) { - window_manager_remove(bootWindowId); - } check(app_event_unsubscribe(&sub) == ERROR_NONE); task_event_group_destruct(&event_group); @@ -407,7 +58,7 @@ extern const ::AppManifest manifest = { .category = APP_CATEGORY_SYSTEM, .location = { .type = APP_LOCATION_MEMORY, .location = reinterpret_cast(appMain) }, .flags = APP_MANIFEST_FLAG_HIDDEN, - .stack = { .depth = 4096, .desired_memory_capability = MEMORY_CAPABILITY_INTERNAL } + .stack = { .depth = 6144, .desired_memory_capability = MEMORY_CAPABILITY_INTERNAL } }; } // namespace diff --git a/Tactility/Source/app/boot/BootInit.cpp b/Tactility/Source/app/boot/BootInit.cpp new file mode 100644 index 000000000..e4df53403 --- /dev/null +++ b/Tactility/Source/app/boot/BootInit.cpp @@ -0,0 +1,294 @@ +#include + +#include "Tactility/bluetooth/Bluetooth.h" +#include "Tactility/hal/SdCard.h" +#include "Tactility/network/NtpPrivate.h" +#include "Tactility/settings/TimePrivate.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef ESP_PLATFORM +#include +#include +#include +#else +#define CONFIG_TT_SPLASH_DURATION 0 +#endif + +namespace tt::app::boot { + +constexpr auto* TAG = "Boot"; + +namespace { + +#ifdef ESP_PLATFORM +constexpr auto PARTITION_PREFIX = std::string("/"); +#else +constexpr auto PARTITION_PREFIX = std::string(""); +#endif + +// Equivalent of AppPaths::getAssetsPath() for the internal "Boot" app id, without needing a +// live AppContext (which this app no longer has under the new app-module model). +std::string getBootAssetsPath(const std::string& childPath) { + return std::format("{}{}/app/Boot/assets/{}", PARTITION_PREFIX, file::SYSTEM_PARTITION_NAME, childPath); +} + +// TODO: Replace with automatic asset buckets like on Android +std::string getSizedAssetPath(const BootScreen& screen, const char* small, const char* medium, const char* large) { + const int smallest_dimension = screen.getSmallestDimension(); + if (smallest_dimension < 150) { // e.g. Cardputer + return getBootAssetsPath(small); + } else if (smallest_dimension >= 320) { + return getBootAssetsPath(large); + } else { + return getBootAssetsPath(medium); + } +} + +std::string getLogoPath(const BootScreen& screen) { + return getSizedAssetPath(screen, "logo_small.png", "logo.png", "logo_large.png"); +} + +std::string getUsbLogoPath(const BootScreen& screen) { + return getSizedAssetPath(screen, "logo_usb_small.png", "logo_usb.png", "logo_usb_large.png"); +} + +void setupDisplay() { + // TODO: Support for multiple displays + + Device* display = nullptr; + if (device_get_first_by_type(&DISPLAY_TYPE, &display) != ERROR_NONE) { + LOG_I(TAG, "No kernel display"); + return; + } + + // Set backlight brightness + Device* backlight; + if (display_get_backlight(display, &backlight) == ERROR_NONE) { + if (!device_is_ready(backlight)) { + if (device_start(backlight) != ERROR_NONE) { + LOG_E(TAG, "Failed to start %s", backlight->name); + } + } + + settings::display::DisplaySettings settings; + if (settings::display::load(settings)) { + } else { + settings = settings::display::getDefault(); + } + + if (backlight_set_brightness(backlight, settings.backlightDuty) == ERROR_NONE) { + LOG_I(TAG, "Backlight for %s set to %d", display->name, settings.backlightDuty); + } else { + LOG_E(TAG, "Failed to set brightness of %s", backlight->name); + } + device_put(backlight); + } else { + LOG_I(TAG, "No backlight for %s", display->name); + } + + device_put(display); +} + +enum class UsbBootResult { + /** Not booting into USB mass storage mode */ + None, + Started, + Failed +}; + +UsbBootResult setupUsbBootMode() { + if (!hal::usb::isUsbBootMode()) { + return UsbBootResult::None; + } + + LOG_I(TAG, "Rebooting into mass storage device mode"); + auto mode = hal::usb::getUsbBootMode(); // Get mode before reset + hal::usb::resetUsbBootMode(); + delay_millis(3000); + + bool started = false; + if (mode == hal::usb::BootMode::Flash) { + started = hal::usb::startMassStorageWithFlash(true); + } else if (mode == hal::usb::BootMode::Sdmmc) { + started = hal::usb::startMassStorageWithSdmmc(true); + } + + return started ? UsbBootResult::Started : UsbBootResult::Failed; +} + +void waitForMinimalSplashDuration(TickType_t startTime) { + const auto end_time = get_ticks(); + const auto ticks_passed = end_time - startTime; + constexpr auto minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS); + if (minimum_ticks > ticks_passed) { + delay_ticks(minimum_ticks - ticks_passed); + } +} + +std::string getLauncherAppId() { + settings::BootSettings boot_properties; + // When boot.properties hasn't been overridden, return default + if (!settings::loadBootSettings(boot_properties)) { + return CONFIG_TT_LAUNCHER_APP_ID; + } + + // When boot properties didn't specify an override, return default + if (boot_properties.launcherAppId.empty()) { + LOG_E(TAG, "Failed to load launcher configuration, or launcher not configured"); + return CONFIG_TT_LAUNCHER_APP_ID; + } + + // If the app in the boot.properties does not exist, return default + AppManifest manifest; + if (app_manager_find_manifest(boot_properties.launcherAppId.c_str(), &manifest) != ERROR_NONE) { + LOG_E(TAG, "Launcher app %s not found", boot_properties.launcherAppId.c_str()); + return CONFIG_TT_LAUNCHER_APP_ID; + } + + // The boot.properties launcher app id is valid + return boot_properties.launcherAppId; +} + +void reboot() { +#ifdef ESP_PLATFORM + esp_restart(); +#else + LOG_W(TAG, "Reboot is not supported on this platform"); +#endif +} + +void waitForInputAndReboot() { + waitForInput(); + reboot(); +} + +void startNextApp() { +#ifdef ESP_PLATFORM + if (esp_reset_reason() == ESP_RST_PANIC) { + crashdiagnostics::start(); // fire-and-forget; no result expected back + return; + } +#endif + + auto launcher_app_id = getLauncherAppId(); + uint32_t launcher_instance_id = 0; + AppStartContext context; + if (app_start_context_from_id(launcher_app_id.c_str(), &context) == ERROR_NONE) { + app_start_with_context(&context, &launcher_instance_id); + } +} + +} // namespace + +bool bootInit(TickType_t startTime) { + LOG_I(TAG, "Starting boot sequence"); + const bool is_usb_boot = hal::usb::isUsbBootMode(); + + auto start_time = get_millis(); + + BootScreen screen; + if (screen.begin()) { + screen.show(is_usb_boot ? getUsbLogoPath(screen) : getLogoPath(screen), {}); + } + + LOG_I(TAG, "Init display"); + setupDisplay(); + + LOG_I(TAG, "Init timezone"); + settings::initTimeZone(); + + // Attempt to start all disabled SD cards (some require delayed init) + LOG_I(TAG, "Init SDMMC"); + hal::sdcard::startAll(); + + LOG_I(TAG, "Init NTP"); + network::ntp::init(); + + LOG_I(TAG, "Init BLE"); + bluetooth::systemStart(); + + LOG_I(TAG, "Init Services"); + registerAndStartServices(); + + LOG_I(TAG, "Prepare file systems"); + prepareFileSystems(); + + bool sd_card_missing = false; +#ifdef CONFIG_TT_USER_DATA_LOCATION_SD + std::string sd_path; + if (!findFirstMountedSdCardPath(sd_path)) { + LOG_E(TAG, "SD card not found"); + sd_card_missing = true; + } +#endif + + switch (setupUsbBootMode()) { + case UsbBootResult::None: + break; + case UsbBootResult::Started: +#ifdef ESP_PLATFORM + screen.show(getUsbLogoPath(screen), { getInputPrompt("return to OS") }); + waitForInput(); + hal::usb::stop(); + esp_restart(); +#endif + return false; + case UsbBootResult::Failed: + screen.show("", { "Failed to start USB mass storage:", hal::usb::getLastError(), getInputPrompt("reboot") }); + waitForInputAndReboot(); + return false; + } + + registerApps(); + + if (sd_card_missing) { + screen.show("", { "SD card not found.", "Please insert one and reboot.", getInputPrompt("reboot") }); + waitForInputAndReboot(); + return false; + } + + LOG_I(TAG, "Loading icon fonts"); + lvgl::initIconFonts(); + + screen.end(); + + size_t total_time = get_millis() - start_time; + LOG_I(TAG, "Finished in %lu ms", static_cast(total_time)); + + waitForMinimalSplashDuration(startTime); + + LOG_I(TAG, "Starting LVGL"); + lvgl::start(); + startNextApp(); + + // This event will likely block as other systems are initialized + // e.g. Wi-Fi reads AP configs from SD card + LOG_I(TAG, "Publish event"); + system_event_emit(KERNEL_EVENT_BOOT_COMPLETED, nullptr, 0); + + return true; +} + +} diff --git a/Tactility/Source/app/boot/BootScreen.cpp b/Tactility/Source/app/boot/BootScreen.cpp new file mode 100644 index 000000000..b7ef775bb --- /dev/null +++ b/Tactility/Source/app/boot/BootScreen.cpp @@ -0,0 +1,303 @@ +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tt::app::boot { + +constexpr auto* TAG = "BootScreen"; +constexpr int BAND_HEIGHT = 16; +constexpr uint16_t TEXT_COLOR = 0xFFFF; + +namespace { + +struct Logo { + unsigned char* rgba = nullptr; + unsigned width = 0; + unsigned height = 0; + + ~Logo() { lodepng_free(rgba); } +}; + +/** Splits text into lines of at most maxCharacters, breaking at spaces where possible */ +void wrapLine(const std::string& text, size_t maxCharacters, std::vector& output) { + size_t start = 0; + while (text.size() - start > maxCharacters) { + size_t end = text.rfind(' ', start + maxCharacters); + if (end == std::string::npos || end <= start) { + end = start + maxCharacters; + output.push_back(text.substr(start, end - start)); + start = end; + } else { + output.push_back(text.substr(start, end - start)); + start = end + 1; + } + } + output.push_back(text.substr(start)); +} + +uint16_t toRgb565(uint32_t red, uint32_t green, uint32_t blue) { + return static_cast(((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3)); +} + +bool collectReadyDevice(Device* device, void* context) { + if (device_is_ready(device) && device_get(device) == ERROR_NONE) { + static_cast*>(context)->push_back(device); + } + return true; +} + +std::vector getReadyKeyboards() { + std::vector keyboards; + device_for_each_of_type(&KEYBOARD_TYPE, &keyboards, collectReadyDevice); + return keyboards; +} + +} // namespace + +BootScreen::~BootScreen() { + end(); +} + +bool BootScreen::begin() { + if (device_get_first_by_type(&DISPLAY_TYPE, &display) != ERROR_NONE) { + LOG_I(TAG, "No display"); + display = nullptr; + return false; + } + + panelWidth = display_get_resolution_x(display); + panelHeight = display_get_resolution_y(display); + const auto orientation = settings::display::loadOrGetDefault().orientation; + rotation = static_cast(settings::display::toLvglDisplayRotation(orientation)); + + const auto color_format = display_get_color_format(display); + if (display_get_frame_buffer_count(display) > 0) { + // Drawing into the hardware frame buffer avoids a copy, and a partial update to a + // double-buffered panel would flip to a half-drawn frame + void* frame_buffers[2] = { nullptr, nullptr }; + display_get_frame_buffer(display, 0, &frame_buffers[0]); + if (display_get_frame_buffer_count(display) > 1) { + display_get_frame_buffer(display, 1, &frame_buffers[1]); + } + if (frame_buffers[0] != nullptr) { + target = pixel_buffer_wrap(frame_buffers[0], color_format, panelWidth, panelHeight, 0); + } + if (target != nullptr && frame_buffers[1] != nullptr) { + secondFrameBuffer = pixel_buffer_wrap(frame_buffers[1], color_format, panelWidth, panelHeight, 0); + } + bandHeight = panelHeight; + } + + if (target == nullptr) { + const bool full_frame = color_format == DISPLAY_COLOR_FORMAT_MONOCHROME || display_has_capability(display, DISPLAY_CAPABILITY_REQUIRES_FULL_FRAME); + bandHeight = full_frame ? panelHeight : std::min(BAND_HEIGHT, panelHeight); + target = pixel_buffer_create(color_format, panelWidth, bandHeight); + } + + if (target == nullptr) { + LOG_E(TAG, "Failed to allocate buffer"); + end(); + return false; + } + + return true; +} + +void BootScreen::end() { + pixel_buffer_free(target); + pixel_buffer_free(secondFrameBuffer); + target = nullptr; + secondFrameBuffer = nullptr; + if (display != nullptr) { + device_put(display); + display = nullptr; + } +} + +int BootScreen::getSmallestDimension() const { + return std::min(panelWidth, panelHeight); +} + +void BootScreen::show(const std::string& logoPath, const std::vector& lines) { + if (target == nullptr) { + return; + } + + Logo logo; + if (!logoPath.empty()) { + const unsigned error = lodepng_decode32_file(&logo.rgba, &logo.width, &logo.height, logoPath.c_str()); + if (error != 0) { + LOG_E(TAG, "Failed to load %s: %s", logoPath.c_str(), lodepng_error_text(error)); + lodepng_free(logo.rgba); + logo.rgba = nullptr; + logo.width = 0; + logo.height = 0; + } + } + + // Layout in logical (rotated) coordinates: logo with text below it, centered as a whole + const auto& font = TT_TERMINAL_FONT_SYMBOL; + 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); + } + 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 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; + + 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); + + // Maps logical coordinates to the physical panel, like lv_display_rotate_area() + auto plot = [&](int x, int y, uint16_t color, PixelBufferConversion conversion) { + int physical_x; + int physical_y; + switch (rotation) { + case 1: physical_x = y; physical_y = panelHeight - 1 - x; break; + case 2: physical_x = panelWidth - 1 - x; physical_y = panelHeight - 1 - y; break; + case 3: physical_x = panelWidth - 1 - y; physical_y = x; break; + default: physical_x = x; physical_y = y; break; + } + if (physical_y >= band_top && physical_y < band_top + band_rows) { + pixel_buffer_set_pixel_rgb565(target, physical_x, physical_y - band_top, color, conversion); + } + }; + + for (unsigned y = 0; y < logo.height; y++) { + for (unsigned x = 0; x < logo.width; x++) { + const unsigned char* pixel = logo.rgba + (static_cast(y) * logo.width + x) * 4; + const uint32_t alpha = pixel[3]; + if (alpha != 0) { + // Blended onto the black background + const uint16_t color = toRgb565(pixel[0] * alpha / 255, pixel[1] * alpha / 255, pixel[2] * alpha / 255); + plot(logo_left + static_cast(x), content_top + static_cast(y), color, PIXEL_BUFFER_CONVERSION_LUMA_THRESHOLD); + } + } + } + + for (size_t line_index = 0; line_index < wrapped_lines.size(); line_index++) { + const auto& line = wrapped_lines[line_index]; + const int line_left = (logical_width - static_cast(line.size()) * font.glyph_width) / 2; + const int line_top = text_top + static_cast(line_index) * font.glyph_height; + 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) { + 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); + } + } + } + } + } + + pixel_buffer_msync(target, 0, 0, panelWidth, band_rows); + display_draw_bitmap(display, 0, band_top, panelWidth, band_top + band_rows, pixel_buffer_get_data(target)); + } + + if (secondFrameBuffer != nullptr) { + pixel_buffer_blit(secondFrameBuffer, 0, 0, target, 0, 0, panelWidth, panelHeight, PIXEL_BUFFER_CONVERSION_EXACT_BLACK); + pixel_buffer_msync(secondFrameBuffer, 0, 0, panelWidth, panelHeight); + } +} + +std::string getInputPrompt(const std::string& action) { + auto keyboards = getReadyKeyboards(); + const bool has_keyboard = !keyboards.empty(); + for (auto* keyboard : keyboards) { + device_put(keyboard); + } + if (has_keyboard) { + return "Press any key to " + action; + } + + Device* pointer = nullptr; + if (device_get_first_active_by_type(&POINTER_TYPE, &pointer) == ERROR_NONE) { + device_put(pointer); + return "Touch the screen to " + action; + } + + return ""; +} + +void waitForInput() { + auto keyboards = getReadyKeyboards(); + // Subscriptions must stay at the same address while subscribed + auto subscriptions = std::make_unique(keyboards.size()); + for (size_t i = 0; i < keyboards.size(); i++) { + keyboard_subscribe(keyboards[i], &subscriptions[i]); + } + + Device* pointer = nullptr; + if (device_get_first_active_by_type(&POINTER_TYPE, &pointer) != ERROR_NONE) { + pointer = nullptr; + } + + // A touch only counts when it starts after the screen was seen untouched + bool pointer_released = false; + bool done = false; + while (!done) { + for (size_t i = 0; i < keyboards.size() && !done; i++) { + // Drivers that implement read_key only deliver events to subscribers when polled + KeyboardKeyData data; + while (keyboard_read_key(keyboards[i], &data) == ERROR_NONE && data.key != 0 && data.continue_reading) {} + + while (keyboard_poll(keyboards[i], &subscriptions[i], &data) == ERROR_NONE) { + if (data.pressed) { + done = true; + } + } + } + + if (pointer != nullptr && !done && pointer_read_data(pointer, 0) == ERROR_NONE) { + uint16_t x, y, strength; + uint8_t point_count = 0; + const bool touched = pointer_get_touched_points(pointer, &x, &y, &strength, &point_count, 1) && point_count > 0; + if (!touched) { + pointer_released = true; + } else if (pointer_released) { + done = true; + } + } + + if (!done) { + delay_millis(20); + } + } + + for (size_t i = 0; i < keyboards.size(); i++) { + keyboard_unsubscribe(keyboards[i], &subscriptions[i]); + device_put(keyboards[i]); + } + if (pointer != nullptr) { + device_put(pointer); + } +} + +} diff --git a/Tactility/Source/app/usbsettings/UsbSettings.cpp b/Tactility/Source/app/usbsettings/UsbSettings.cpp index dd38b6b66..bda8f4822 100644 --- a/Tactility/Source/app/usbsettings/UsbSettings.cpp +++ b/Tactility/Source/app/usbsettings/UsbSettings.cpp @@ -55,6 +55,7 @@ void createWidgets(lv_obj_t* parent, void* userData) { lv_obj_align(wrapper, LV_ALIGN_CENTER, 0, 0); // Ensures showing selection state for keyboard/encoder devices lv_obj_set_style_pad_all(wrapper, 6, LV_ALIGN_DEFAULT); + lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT); bool hasSd = hal::usb::canRebootIntoMassStorageSdmmc(); bool hasFlash = hal::usb::canRebootIntoMassStorageFlash(); diff --git a/Tactility/Source/lvgl/IconFonts.cpp b/Tactility/Source/lvgl/IconFonts.cpp new file mode 100644 index 000000000..8505f99cc --- /dev/null +++ b/Tactility/Source/lvgl/IconFonts.cpp @@ -0,0 +1,188 @@ +#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 new file mode 100644 index 000000000..6bf3d4bc8 --- /dev/null +++ b/Tactility/Source/lvgl/Lvgl.cpp @@ -0,0 +1,232 @@ +#include + +#ifdef ESP_PLATFORM +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace tt { + +namespace service { + namespace autorotate { extern const ServiceManifest manifest; } + namespace memorychecker { extern const ServiceManifest manifest; } + namespace statusbar { extern const ServiceManifest manifest; } +#ifdef ESP_PLATFORM + namespace displayidle { extern const ServiceManifest manifest; } + namespace keyboardidle { extern const ServiceManifest manifest; } +#endif +#if TT_FEATURE_SCREENSHOT_ENABLED + namespace screenshot { extern const ServiceManifest manifest; } +#endif +} + +namespace lvgl { + +static void stopAppFromToolbar(lv_event_t*) { + // Default nav action for any toolbar that doesn't override it itself. Prefer the topmost + // new-model app if one is showing; fall back to the old system otherwise (this is what + // every not-yet-converted app's toolbar still relies on). + AppInstanceId topmost = 0; + check(app_manager_get_topmost_instance_id(&topmost) == ERROR_NONE); + + app_event_emit_close(topmost); +} + +// The on-screen keyboard widget itself, constructed during windowManagerScreenInit +static LvglSoftwareKeyboard softwareKeyboard { .object = nullptr }; + +static lv_obj_t* windowManagerScreenInit(lv_obj_t* root) { + lv_obj_t* vertical_container = lv_obj_create(root); + lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); + lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_all(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(vertical_container, lv_color_black(), LV_STATE_DEFAULT); + lv_obj_set_style_border_width(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_radius(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_remove_flag(vertical_container, LV_OBJ_FLAG_SCROLLABLE); + + lvgl::statusbar_create(vertical_container); + + auto* app_container = lv_obj_create(vertical_container); + lv_obj_set_style_pad_all(app_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(app_container, 0, LV_STATE_DEFAULT); + lv_obj_set_width(app_container, LV_PCT(100)); + lv_obj_set_flex_grow(app_container, 1); + lv_obj_set_flex_flow(app_container, LV_FLEX_FLOW_COLUMN); + lv_obj_remove_flag(app_container, LV_OBJ_FLAG_SCROLLABLE); + + // Parented to root (not app_container/vertical_container) so it overlays on top of + // everything, including the statusbar, regardless of which app is showing. Hidden until a + // focused textarea shows it (see lvgl_keyboard_add_textarea()/textarea_show_keyboard()). + lvgl_software_keyboard_construct(&softwareKeyboard, root); + + return app_container; +} + +#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED + +// Applies the calibration persisted by the touch calibration app to the live pointer indev. +// lvgl_devices_attach() runs before onLvglStarted(), so the default indev already exists here. +static void applySavedTouchCalibration() { + settings::touch::TouchCalibrationSettings settings = settings::touch::loadOrGetDefault(); + if (!settings.enabled || !settings::touch::isValid(settings)) { + return; + } + + LvglPointerCalibration calibration = { + .x_min = settings.xMin, + .x_max = settings.xMax, + .y_min = settings.yMin, + .y_max = settings.yMax, + }; + + lvgl_lock(); + auto* indev = lvgl_pointer_get_default(); + if (indev != nullptr) { + lvgl_pointer_set_calibration(indev, &calibration); + } + lvgl_unlock(); +} + +#endif // CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED + +static void onLvglStarted() { + // lv_display_create() (inside lvgl_devices_attach(), which already ran by this point) always + // resets rotation to LV_DISPLAY_ROTATION_0. The only other code that ever applies a saved + // orientation is the display settings app's dropdown change handler, so without this, every + // LVGL restart (not just first boot) silently drops back to unrotated. Must run before + // window_manager_start() below builds the window tree against the display's current size. + lvgl_lock(); + if (auto* display = lv_display_get_default(); display != nullptr) { + auto displaySettings = settings::display::loadOrGetDefault(); + lv_display_set_rotation(display, settings::display::toLvglDisplayRotation(displaySettings.orientation)); + } + lvgl_unlock(); + + window_manager_configure(windowManagerScreenInit); + check(module_ensure_started(&lvgl_window_manager_module) == ERROR_NONE); + + ToolbarConfig toolbar_config = { .nav_action_callback = stopAppFromToolbar }; + lvgl_toolbar_configure(&toolbar_config); + + addService(service::statusbar::manifest); + addService(service::memorychecker::manifest); +#if defined(ESP_PLATFORM) + addService(service::displayidle::manifest); +#endif + if (device_exists_of_type(&IMU_TYPE)) { + addService(service::autorotate::manifest); + } +#if defined(CONFIG_TT_TDECK_WORKAROUND) + addService(service::keyboardidle::manifest); +#endif +#if TT_FEATURE_SCREENSHOT_ENABLED + addService(service::screenshot::manifest); +#endif + + lvgl::startUsbHidInput(); + lvgl::startKeyboardDeviceListener(); + lvgl::initTrackball(); + +#ifdef CONFIG_TT_TOUCH_CALIBRATION_SUPPORTED + applySavedTouchCalibration(); +#endif + + memory_log_stats(); +} + +static void onLvglStopped() { + lvgl::stopKeyboardDeviceListener(); + lvgl::stopUsbHidInput(); + + if (device_exists_of_type(&IMU_TYPE)) { + check(service::removeService(service::autorotate::manifest.id)); + } +#if TT_FEATURE_SCREENSHOT_ENABLED + check(service::removeService(service::screenshot::manifest.id)); +#endif +#if defined(CONFIG_TT_TDECK_WORKAROUND) + check(service::removeService(service::keyboardidle::manifest.id)); +#endif +#if defined(ESP_PLATFORM) + check(service::removeService(service::displayidle::manifest.id)); +#endif + check(service::removeService(service::memorychecker::manifest.id)); + check(service::removeService(service::statusbar::manifest.id)); + + if (softwareKeyboard.object != nullptr) { + // lv_obj_delete() walks/mutates the object graph (event lists, group membership, + // parent/child links). Without the LVGL lock this can race the LVGL port task's own + // concurrent traversal (input dispatch, timers, animations), producing an intermittent + // double-free/use-after-free inside lv_obj_destructor/lv_event_mark_deleted. + lvgl_lock(); + lvgl_software_keyboard_destruct(&softwareKeyboard); + lvgl_unlock(); + } + + module_stop(&lvgl_window_manager_module); + + memory_log_stats(); +} + +bool isStarted() { + return module_is_started(&lvgl_module); +} + +void start() { + static bool configured = false; + if (!configured) { + lvgl_module_configure((LvglModuleConfig) { + .on_start = onLvglStarted, + .on_stop = onLvglStopped, + .task_priority = THREAD_PRIORITY_HIGHER, + .task_stack_size = 9120, +#ifdef ESP_PLATFORM + .task_affinity = getCpuAffinityConfiguration().graphics +#endif + }); + configured = true; + } + check(module_ensure_started(&lvgl_module) == ERROR_NONE); +} + +void stop() { + module_stop(&lvgl_module); +} + +} // namespace lvgl + +} // namespace tt diff --git a/Tactility/Source/service/audio/Audio.cpp b/Tactility/Source/service/audio/Audio.cpp index 81623946f..0c7d85074 100644 --- a/Tactility/Source/service/audio/Audio.cpp +++ b/Tactility/Source/service/audio/Audio.cpp @@ -9,7 +9,7 @@ namespace tt::service::audio { extern const ServiceManifest manifest; -// The service is only registered when audio hardware is present (see Tactility.cpp); +// The service is only registered when audio hardware is present (see InitServices.cpp); // treat "not registered" as "no device bound" rather than asserting via findAudioService(). static std::shared_ptr tryFindAudioService() { return findServiceById(manifest.id); diff --git a/Tactility/Source/service/rtctime/RtcTime.cpp b/Tactility/Source/service/rtctime/RtcTime.cpp index b251eb1cd..aa91d32e2 100644 --- a/Tactility/Source/service/rtctime/RtcTime.cpp +++ b/Tactility/Source/service/rtctime/RtcTime.cpp @@ -14,7 +14,7 @@ extern const ServiceManifest manifest; bool isAvailable() { #ifdef ESP_PLATFORM - // The service is only registered when an RTC device is present (see Tactility.cpp); + // The service is only registered when an RTC device is present (see InitServices.cpp); // treat "not registered" the same as "no device bound" rather than asserting. auto service = findServiceById(manifest.id); return service != nullptr && service->isAvailable(); diff --git a/Tactility/Source/service/webserver/WebServerService.cpp b/Tactility/Source/service/webserver/WebServerService.cpp index 44f1bba04..d0dd196c0 100644 --- a/Tactility/Source/service/webserver/WebServerService.cpp +++ b/Tactility/Source/service/webserver/WebServerService.cpp @@ -1525,7 +1525,7 @@ error_t WebServerService::handleApiScreenshot(HttpServerRequest* request, void*) LOG_I(TAG, "Screenshot will be saved to: %s", screenshot_path.c_str()); - // LVGL's lodepng uses lv_fs which requires the "A:" prefix + // lv_screenshot writes through lv_fs, which requires the "A:" prefix std::string lvgl_screenshot_path = lvgl::PATH_PREFIX + screenshot_path; // Capture screenshot using LVGL diff --git a/Tactility/Source/settings/DisplaySettings.cpp b/Tactility/Source/settings/DisplaySettings.cpp index bd992e485..c6b6201db 100644 --- a/Tactility/Source/settings/DisplaySettings.cpp +++ b/Tactility/Source/settings/DisplaySettings.cpp @@ -5,6 +5,9 @@ #include +#include +#include + #include #include #include @@ -28,17 +31,19 @@ constexpr auto* SETTINGS_KEY_SCREENSAVER_TYPE = "screensaverType"; constexpr auto* SETTINGS_KEY_AUTO_ROTATE_ENABLED = "autoRotateEnabled"; constexpr auto* SETTINGS_KEY_AUTO_ROTATE_MOUNT_ROTATION = "autoRotateMountRotation"; -static Orientation getDefaultOrientation() { - auto* display = lv_display_get_default(); - if (display == nullptr) { - return Orientation::Landscape; +// Uses the kernel display, so it also works while LVGL isn't running +static bool isOriginallyLandscape() { + Device* display = nullptr; + if (device_get_first_by_type(&DISPLAY_TYPE, &display) != ERROR_NONE) { + return true; } + const bool landscape = display_get_resolution_x(display) > display_get_resolution_y(display); + device_put(display); + return landscape; +} - if (lv_display_get_physical_horizontal_resolution(display) > lv_display_get_physical_vertical_resolution(display)) { - return Orientation::Landscape; - } else { - return Orientation::Portrait; - } +static Orientation getDefaultOrientation() { + return isOriginallyLandscape() ? Orientation::Landscape : Orientation::Portrait; } static std::string toString(Orientation orientation) { @@ -226,12 +231,6 @@ bool save(const DisplaySettings& settings) { return file::savePropertiesFile(settings_path, map); } -static bool isOriginallyLandscape() { - auto* lvgl_display = lv_display_get_default(); - return lv_display_get_original_horizontal_resolution(lvgl_display) > - lv_display_get_original_vertical_resolution(lvgl_display); -} - lv_display_rotation_t toLvglDisplayRotation(Orientation orientation) { if (isOriginallyLandscape()) { // Landscape display diff --git a/TactilityKernel/source/driver.cpp b/TactilityKernel/source/driver.cpp index 9df0cb4fa..31a18a867 100644 --- a/TactilityKernel/source/driver.cpp +++ b/TactilityKernel/source/driver.cpp @@ -9,9 +9,12 @@ #include #include #include +#include #define TAG "driver" +constexpr TickType_t SLOW_START_WARNING_TICKS = pdMS_TO_TICKS(100); + struct DriverInternal { int use_count = 0; bool destroying = false; @@ -59,7 +62,7 @@ error_t driver_destruct(Driver* driver) { } error_t driver_add(Driver* driver) { - LOG_I(TAG, "add %s", driver->name); + LOG_D(TAG, "add %s", driver->name); ledger.lock(); ledger.drivers.push_back(driver); ledger.unlock(); @@ -67,7 +70,7 @@ error_t driver_add(Driver* driver) { } error_t driver_remove(Driver* driver) { - LOG_I(TAG, "remove %s", driver->name); + LOG_D(TAG, "remove %s", driver->name); if (driver->owner == nullptr) return ERROR_NOT_ALLOWED; @@ -135,7 +138,12 @@ error_t driver_bind(Driver* driver, Device* device) { } if (driver->start_device != nullptr) { + const TickType_t start_ticks = get_ticks(); error = driver->start_device(device); + const TickType_t elapsed_ticks = get_ticks() - start_ticks; + if (elapsed_ticks > SLOW_START_WARNING_TICKS) { + LOG_W(TAG, "starting %s with %s took %u ms", device->name, driver->name, static_cast(elapsed_ticks * portTICK_PERIOD_MS)); + } if (error != ERROR_NONE) { goto error; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 6b4803fa0..e68b63ee0 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -12,6 +12,8 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/crypt-module/tests ${CMAKE_CURRENT_ add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/app-module/tests ${CMAKE_CURRENT_BINARY_DIR}/app-module) add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/app-posix-module/tests ${CMAKE_CURRENT_BINARY_DIR}/app-posix-module) add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/http-module/tests ${CMAKE_CURRENT_BINARY_DIR}/http-module) +add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/binfont-module/tests ${CMAKE_CURRENT_BINARY_DIR}/binfont-module) +add_subdirectory(${CMAKE_SOURCE_DIR}/Modules/lodepng-module/tests ${CMAKE_CURRENT_BINARY_DIR}/lodepng-module) add_custom_target(build-tests) add_dependencies(build-tests ServiceModuleTests) @@ -23,3 +25,5 @@ add_dependencies(build-tests CryptModuleTests) add_dependencies(build-tests AppModuleTests) add_dependencies(build-tests AppPosixModuleTests) add_dependencies(build-tests HttpModuleTests) +add_dependencies(build-tests BinFontModuleTests) +add_dependencies(build-tests LodePngModuleTests) diff --git a/device.py b/device.py index 1dc1fdac9..edec31043 100755 --- a/device.py +++ b/device.py @@ -91,7 +91,7 @@ def safe_float(value: str, error_message: str): exit_with_error(error_message) def write_defaults(output_file): - default_properties_path = os.path.join("Buildscripts", "sdkconfig", "default.properties") + default_properties_path = os.path.join("Buildscripts", "sdkconfig-default.properties") default_properties = read_file(default_properties_path) output_file.write(default_properties) diff --git a/lv_conf.h b/lv_conf.h index 15b352692..3ad79800c 100644 --- a/lv_conf.h +++ b/lv_conf.h @@ -631,7 +631,7 @@ #endif /*LODEPNG decoder library*/ -#define LV_USE_LODEPNG 1 +#define LV_USE_LODEPNG 0 /*PNG decoder(libpng) library*/ #define LV_USE_LIBPNG 0