Compare commits

...

2 Commits

Author SHA1 Message Date
Ken Van Hoeylandt
4279a8ed72
Terminal and shell support based on BreezyBox (#656)
Features:
- Implemented terminal app based on BreezyBox
- Implemented shell based on BreezyBox
- Added font-module with fixed-width fonts

Improvements:
- Improved application standard-output and error-output routing, including dynamically loaded applications.
- Updated shared icons and Material Symbols mappings.
- Other improvements & fixes
2026-09-22 23:01:03 +02:00
Shadowtrance
bdb50505e7
Improvements and fixes (#655)
USB Audio Class (UAC) output
Audio codec re-binding
Keyboard / Bluetooth HID
HID Consumer Control (media keys)
Symbol exports
Other fixes
IMU-based screen auto-rotate

See PR for details: https://github.com/TactilityProject/Tactility/pull/655
2026-09-22 19:19:53 +02:00
224 changed files with 18025 additions and 805 deletions

View File

@ -119,7 +119,7 @@ def main():
shared.generate_tactility_sdk_top_cmakelists(target_path)
# Output ESP-IDF SDK version to file
with open(os.path.join(target_path, "idf-version.txt"), "a") as f:
with open(os.path.join(target_path, "idf-version.txt"), "w") as f:
f.write(esp_idf_version)
if __name__ == "__main__":

View File

@ -1,4 +1,6 @@
app-module
audio-decoder-module
cjson-module
crypt-module
gps-module
http-module

View File

@ -84,3 +84,27 @@ CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=5
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=5
# Audio codec: audio-stream only decodes (never encodes), and AudiobookPlayer (the only current
# consumer) is MP3-only. Disabling the rest saves several hundred KB of flash across every device;
# re-enable a specific decoder here if a future app needs it.
CONFIG_AUDIO_DECODER_AAC_SUPPORT=n
CONFIG_AUDIO_DECODER_G711_SUPPORT=n
CONFIG_AUDIO_DECODER_AMRNB_SUPPORT=n
CONFIG_AUDIO_DECODER_AMRWB_SUPPORT=n
CONFIG_AUDIO_DECODER_FLAC_SUPPORT=n
CONFIG_AUDIO_DECODER_OPUS_SUPPORT=n
CONFIG_AUDIO_DECODER_VORBIS_SUPPORT=n
CONFIG_AUDIO_DECODER_ADPCM_SUPPORT=n
CONFIG_AUDIO_DECODER_ALAC_SUPPORT=n
CONFIG_AUDIO_DECODER_SBC_SUPPORT=n
CONFIG_AUDIO_DECODER_LC3_SUPPORT=n
CONFIG_AUDIO_ENCODER_AAC_SUPPORT=n
CONFIG_AUDIO_ENCODER_G711_SUPPORT=n
CONFIG_AUDIO_ENCODER_AMRNB_SUPPORT=n
CONFIG_AUDIO_ENCODER_AMRWB_SUPPORT=n
CONFIG_AUDIO_ENCODER_OPUS_SUPPORT=n
CONFIG_AUDIO_ENCODER_ADPCM_SUPPORT=n
CONFIG_AUDIO_ENCODER_ALAC_SUPPORT=n
CONFIG_AUDIO_ENCODER_SBC_SUPPORT=n
CONFIG_AUDIO_ENCODER_LC3_SUPPORT=n
CONFIG_AUDIO_ENCODER_PCM_SUPPORT=n

View File

@ -124,9 +124,12 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Libraries/minitar)
add_subdirectory(Libraries/minmea)
add_subdirectory(Modules/lvgl-module)
add_subdirectory(Modules/audio-decoder-module)
add_subdirectory(Modules/c-symbols-module)
add_subdirectory(Modules/cjson-module)
add_subdirectory(Modules/cpp-symbols-module)
add_subdirectory(Modules/crypt-module)
add_subdirectory(Modules/font-module)
add_subdirectory(Modules/freertos-module)
add_subdirectory(Modules/gps-module)
add_subdirectory(Modules/http-module)
@ -139,6 +142,9 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Modules/lvgl-window-manager-module)
add_subdirectory(Drivers/gps-generic-module)
add_subdirectory(Drivers/gps-meshtastic-module)
# Kernel-only software aggregate; built on sim so its device-lifecycle behavior
# is covered by Drivers/audio-stream-module/tests.
add_subdirectory(Drivers/audio-stream-module)
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")

View File

@ -152,5 +152,5 @@ void cl32_power_detect_start() {
}
void cl32_power_detect_stop() {
device_listener_remove(on_i2c0_started);
device_listener_remove(on_i2c0_started, nullptr);
}

View File

@ -49,7 +49,7 @@ static error_t start() {
}
static error_t stop() {
device_listener_remove(on_device_event);
device_listener_remove(on_device_event, nullptr);
return ERROR_NONE;
}

View File

@ -141,5 +141,5 @@ void tab5_detect_start() {
}
void tab5_detect_stop() {
device_listener_remove(on_display_detect_event);
device_listener_remove(on_display_detect_event, nullptr);
}

View File

@ -6,12 +6,24 @@
#include <lvgl/lvgl.h>
#include <lvgl.h>
#include <atomic>
static lv_display_rotation_t saved_rotation = LV_DISPLAY_ROTATION_0;
static bool rotation_override_active = false;
// device_listener_remove() doesn't wait for an in-flight on_device_event() callback to finish -
// a DEVICE_EVENT_STARTED already snapshotted by device_listener_notify() can still fire after
// stop() has run. This flag makes such a late callback a no-op instead of re-applying the
// override after shutdown.
static std::atomic<bool> listener_active { false };
static void apply_rotation(bool attached) {
lvgl_lock();
if (attached && !listener_active.load(std::memory_order_acquire)) {
lvgl_unlock();
return;
}
auto* display = lv_display_get_default();
if (display == nullptr) {
lvgl_unlock();
@ -37,7 +49,7 @@ static void apply_rotation(bool attached) {
}
static void on_device_event(Device* device, DeviceEvent event, void*) {
if (!device_is_compatible(device, "m5stack,tab5-keyboard")) {
if (!listener_active.load(std::memory_order_acquire) || !device_is_compatible(device, "m5stack,tab5-keyboard")) {
return;
}
if (event == DEVICE_EVENT_STARTED) {
@ -49,10 +61,13 @@ static void on_device_event(Device* device, DeviceEvent event, void*) {
void tab5_keyboard_lvgl_rotation_start() {
rotation_override_active = false;
listener_active.store(true, std::memory_order_release);
device_listener_add(on_device_event, nullptr);
}
void tab5_keyboard_lvgl_rotation_stop() {
// Set before apply_rotation()/device_listener_remove(): a late in-flight callback must no-op.
listener_active.store(false, std::memory_order_release);
apply_rotation(false);
device_listener_remove(on_device_event);
device_listener_remove(on_device_event, nullptr);
}

View File

@ -77,7 +77,7 @@ static error_t start() {
static error_t stop() {
tab5_keyboard_lvgl_rotation_stop();
tab5_headphone_detect_stop();
device_listener_remove(on_io_expander0_started);
device_listener_remove(on_io_expander0_started, nullptr);
tab5_detect_stop();
return ERROR_NONE;
}

View File

@ -55,4 +55,10 @@ sdkconfig.CONFIG_LV_DEF_REFR_PERIOD=15
# SC202CS (SC2356) MIPI CSI camera sensor + ISP pipeline (AE/AWB/demosaicing)
sdkconfig.CONFIG_CAMERA_SC202CS=y
sdkconfig.CONFIG_CAMERA_SC202CS_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y
sdkconfig.CONFIG_ESP_VIDEO_ENABLE_ISP_PIPELINE_CONTROLLER=y
# Pipeline disabled until espressif fixes their damn bugs, camera still works but looks bad.
# Pipeline enabled with idf 6.1 currently spams the log with errors and also breaks the camera functioning.
sdkconfig.CONFIG_ESP_VIDEO_ENABLE_ISP_PIPELINE_CONTROLLER=n
# USB audio: 16 ms of isochronous transfers tolerates short display/decoder
# scheduling bursts better than the component's 9 ms default.
sdkconfig.CONFIG_UAC_NUM_ISOC_URBS=4
sdkconfig.CONFIG_UAC_NUM_PACKETS_PER_URB=4

View File

@ -209,6 +209,14 @@
usbhostmsc0 {
compatible = "espressif,esp32-usbhost-msc";
};
// USB headphones/headsets (UAC 1.0, 48 kHz / 16-bit / stereo PCM output).
// The manager installs the class client; a dynamic "usb_uac0" codec device
// appears per connected headset and the audio-stream aggregate re-binds
// output to it.
usbhostaudio0 {
compatible = "espressif,esp32-usbhost-uac";
};
};
usbdevice0 {

View File

@ -32,7 +32,8 @@ extern void vAssertCalled(unsigned long line, const char* const file);
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE (1024 * 1024)
// 1MB was insufficient for terminal app
#define configTOTAL_HEAP_SIZE (8 * 1024 * 1024)
#define configAPPLICATION_ALLOCATED_HEAP 0
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 // TODO: Compare with ESP defaults

View File

@ -94,7 +94,7 @@ static error_t start() {
}
static error_t stop() {
device_listener_remove(on_root_started);
device_listener_remove(on_root_started, nullptr);
return ERROR_NONE;
}

View File

@ -43,7 +43,7 @@ static error_t start() {
}
static error_t stop() {
device_listener_remove(&on_device_event);
device_listener_remove(&on_device_event, nullptr);
return ERROR_NONE;
}

View File

@ -2,11 +2,16 @@
## Before release
- Tactility/Source/service/autorotate/AutoRotate.cpp
TODO: Display settings app might be saving DisplaySettings at the same time. This might corrupt the settings file.
- Try out speed optimizations: https://docs.espressif.com/projects/esp-faq/en/latest/software-framework/peripherals/lcd.html
(relates to CONFIG_ESP32S3_DATA_CACHE_LINE_64B that is in use for RGB displays via the `device.properties` fix/workaround)
## Higher Priority
- App List: Close when app was started
- App List: Support marking apps as favourite
- Shell interpreter works recursive-descent algorithm, which requires a big stack size. Can we optimize this?
- CrashDiagnostics shouldn't show a QR when there's no callstack
- 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.
- Warn if file operations are done from prohibited tasks (e.g. lvgl task)

View File

@ -4,8 +4,14 @@ include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake")
file(GLOB_RECURSE SOURCE_FILES "source/*.c*")
set(REQUIRES_LIST TactilityKernel)
if (DEFINED ENV{ESP_IDF_VERSION})
# Decoder symbol exports (source/symbols.c) compile against the ESP-only audio codec component.
list(APPEND REQUIRES_LIST espressif__esp_audio_codec)
endif ()
tactility_add_module(audio-stream-module
SRCS ${SOURCE_FILES}
INCLUDE_DIRS include/
REQUIRES TactilityKernel
REQUIRES ${REQUIRES_LIST}
)

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
#include <tactility/device.h>
#include <tactility/driver.h>
#include <tactility/device_listener.h>
#include <tactility/log.h>
#include <tactility/drivers/audio_codec.h>
#include <tactility/drivers/audio_stream.h>
@ -98,19 +99,25 @@ struct AudioStreamHandleImpl : AudioStreamHandleData {
uint8_t codec_channels = 0;
uint8_t bytes_per_frame = 0; // app-side frame size (config.channels)
uint8_t codec_bytes_per_frame = 0; // codec-side frame size (codec_channels)
// Bound at open time; the AudioStreamData slot can be re-bound mid-handle by
// on_codec_device_event, but I/O must keep targeting this codec. Nulled when this codec's
// device is being removed, so close_stream() skips audio_codec_close() on soon-freed memory.
Device* codec = nullptr;
float input_gain = 1.0f; // fixed digital gain multiplier, input direction only (see audio_codec_get_input_gain_multiplier)
std::vector<uint8_t> codec_buffer; // raw codec-rate/codec-channel PCM, scratch
std::vector<uint8_t> convert_buffer; // intermediate scratch for the second conversion stage
// Lifetime guard: close_stream() can be triggered from a different task than the one
// doing read()/write() (e.g. the Settings UI disabling output while SfxEngine's audio
// task is mid-write). `closing` keeps new I/O calls out, `busy_count` tracks I/O calls
// currently in flight, and `drain_semaphore` lets close_stream() block until they finish
// before freeing the handle. All three are only touched while `AudioStreamData::mutex`
// is held, except for the give/take on drain_semaphore itself.
// Lets close_stream() and on_codec_device_event() independently wait for this handle's
// in-flight I/O to drain without racing each other or double-freeing it: each waits on its
// own semaphore (a shared one would only wake one of them), and lifetime_refs ensures
// whichever finishes last is the one that deletes `handle`. All fields here are only
// touched while `AudioStreamData::mutex` is held, except the semaphore give/take themselves.
bool listener_closed = false;
bool closing = false;
int busy_count = 0;
int lifetime_refs = 1; // the implicit reference held by the open handle itself
SemaphoreHandle_t drain_semaphore = nullptr;
SemaphoreHandle_t listener_drain_semaphore = nullptr;
};
struct AudioStreamData {
@ -134,6 +141,17 @@ struct AudioStreamData {
// through them, so close (possibly forced by set_enabled) can't race with read/write.
SemaphoreHandle_t mutex = nullptr;
// Set to the codec being opened while open_stream() holds the reservation placeholder in
// open_input/open_output; there's no handle yet to mark listener_closed, so a STOPPED event
// during that window instead polls this field until the open resolves.
Device* input_reservation_codec = nullptr;
Device* output_reservation_codec = nullptr;
// The audio-stream device this state belongs to; used by on_codec_device_event (which
// only receives the state as context) for notify_change(). Nulled during stop_device so
// a late listener invocation becomes a no-op.
Device* self = nullptr;
AudioStreamChangeCallback change_callback = nullptr;
void* change_callback_user_data = nullptr;
};
@ -226,31 +244,163 @@ Device* codec_for_direction(AudioStreamData* data, AudioCodecDirection direction
return result;
}
// Marks an I/O operation as in-flight on `handle`, preventing close_stream() from freeing it
// underneath us. Returns false (and does nothing further) if the handle is closing/closed --
// callers must bail out with an error in that case. Must be paired with io_end().
bool io_begin(AudioStreamData* data, AudioStreamHandleImpl* handle) {
// Marks I/O as in-flight on `handle` and hands back the codec to use, preventing close_stream()
// from freeing it underneath us. Returns false if the handle is closing/closed (caller must
// bail with an error). Reads handle->codec under the same lock as the validity check so it can't
// race on_codec_device_event's mutex-protected null-out. Must be paired with io_end().
bool io_begin(AudioStreamData* data, AudioStreamHandleImpl* handle, Device** out_codec) {
xSemaphoreTake(data->mutex, portMAX_DELAY);
bool is_input = (handle->direction == AUDIO_CODEC_DIR_INPUT);
AudioStreamHandleImpl* slot_value = is_input ? data->open_input : data->open_output;
if (slot_value != handle || handle->closing) {
if (slot_value != handle || handle->closing || handle->listener_closed || handle->codec == nullptr) {
xSemaphoreGive(data->mutex);
return false;
}
*out_codec = handle->codec;
handle->busy_count++;
xSemaphoreGive(data->mutex);
return true;
}
// Drops one lifetime reference; on the last one, deletes handle's semaphores (nulled out first
// so nothing else can observe a dangling pointer) and returns true so the caller frees `handle`
// itself. Never touches handle->codec: that stays close_stream()'s own responsibility.
bool release_lifetime_ref(AudioStreamData* data, AudioStreamHandleImpl* handle) {
xSemaphoreTake(data->mutex, portMAX_DELAY);
handle->lifetime_refs--;
bool last_ref = (handle->lifetime_refs == 0);
SemaphoreHandle_t drain_to_delete = nullptr;
SemaphoreHandle_t listener_drain_to_delete = nullptr;
if (last_ref) {
drain_to_delete = handle->drain_semaphore;
listener_drain_to_delete = handle->listener_drain_semaphore;
handle->drain_semaphore = nullptr;
handle->listener_drain_semaphore = nullptr;
}
xSemaphoreGive(data->mutex);
if (drain_to_delete != nullptr) {
vSemaphoreDelete(drain_to_delete);
}
if (listener_drain_to_delete != nullptr) {
vSemaphoreDelete(listener_drain_to_delete);
}
return last_ref;
}
void io_end(AudioStreamData* data, AudioStreamHandleImpl* handle) {
xSemaphoreTake(data->mutex, portMAX_DELAY);
handle->busy_count--;
if (handle->closing && handle->busy_count == 0) {
xSemaphoreGive(handle->drain_semaphore);
// Give under data->mutex: semaphore fields are only nulled under this same mutex before
// deletion, so this can't target an already-freed semaphore.
if (handle->busy_count == 0) {
if (handle->closing && handle->drain_semaphore != nullptr) {
xSemaphoreGive(handle->drain_semaphore);
}
if (handle->listener_closed && handle->listener_drain_semaphore != nullptr) {
xSemaphoreGive(handle->listener_drain_semaphore);
}
}
xSemaphoreGive(data->mutex);
}
// Re-binds each direction's codec on hotplug. A stream open on the old codec is marked
// listener_closed so it drains and closes safely; for STOPPED, the codec pointer is nulled
// first too, since the Device memory is freed right after this callback returns and an
// in-flight read/write may still be using it (io_begin captured the pointer before the null-out).
// The wait below is bounded because read/write's own timeout guarantees it finishes on its own;
// an unbounded wait here could deadlock hotplug teardown. DEVICE_EVENT_STOPPED (not STOPPING) is
// used because the device only drops out of find_first_codec_supporting's candidates once
// STOPPING has already been notified.
void on_codec_device_event(Device* dev, DeviceEvent event, void* context) {
auto* data = static_cast<AudioStreamData*>(context);
if (data == nullptr || data->self == nullptr) {
return;
}
if (device_get_type(dev) != &AUDIO_CODEC_TYPE) {
return;
}
if (event != DEVICE_EVENT_STARTED && event != DEVICE_EVENT_STOPPED) {
return;
}
const AudioCodecDirection directions[] = { AUDIO_CODEC_DIR_INPUT, AUDIO_CODEC_DIR_OUTPUT };
for (AudioCodecDirection direction : directions) {
Device* preferred = find_first_codec_supporting(direction);
xSemaphoreTake(data->mutex, portMAX_DELAY);
Device** codec_slot = (direction == AUDIO_CODEC_DIR_INPUT) ? &data->input_codec : &data->output_codec;
Device* current = *codec_slot;
if (preferred == current) {
xSemaphoreGive(data->mutex);
continue;
}
AudioStreamHandleImpl** open_slot = (direction == AUDIO_CODEC_DIR_INPUT) ? &data->open_input : &data->open_output;
AudioStreamHandleImpl* open_handle = *open_slot;
auto* reservation = reinterpret_cast<AudioStreamHandleImpl*>(1);
AudioStreamHandleImpl* drained_handle = nullptr;
bool must_drain = false;
Device** reservation_codec = (direction == AUDIO_CODEC_DIR_INPUT) ? &data->input_reservation_codec : &data->output_reservation_codec;
bool must_wait_for_open = (event == DEVICE_EVENT_STOPPED && open_handle == reservation && *reservation_codec == current);
if (open_handle != nullptr && open_handle != reservation) {
if (event == DEVICE_EVENT_STOPPED && open_handle->codec == current) {
open_handle->codec = nullptr;
// read/write_stream capture `codec` into a local before this callback's mutex
// window can run, so I/O already past that point is still using the pointer
// we just nulled out -- wait for it before returning, since our caller (the
// STOPPED event's source) frees that Device's memory right after we return.
must_drain = (open_handle->busy_count > 0);
if (must_drain) {
// Own semaphore, since close_stream() can be waiting on drain_semaphore
// concurrently for this same handle. Take a lifetime ref too so a concurrent
// close_stream() can't free `handle` out from under this wait.
open_handle->listener_drain_semaphore = xSemaphoreCreateBinary();
open_handle->lifetime_refs++;
}
drained_handle = open_handle;
}
open_handle->listener_closed = true;
*open_slot = nullptr;
}
*codec_slot = preferred;
xSemaphoreGive(data->mutex);
if (must_drain && drained_handle->listener_drain_semaphore != nullptr) {
// Bounded to 2s (comfortably covers every timeout this codebase's callers use), since
// there's no way to cancel an in-flight audio_codec_read/write call.
xSemaphoreTake(drained_handle->listener_drain_semaphore, pdMS_TO_TICKS(2000));
if (release_lifetime_ref(data, drained_handle)) {
delete drained_handle;
}
}
if (must_wait_for_open) {
// open_stream() is between reserving the slot and audio_codec_open() returning, so
// there's no handle yet to mark listener_closed/drain: poll for the reservation to
// resolve instead. Bounded for the same reason as the drain wait above.
for (int waited_ms = 0; waited_ms < 2000; waited_ms += 20) {
xSemaphoreTake(data->mutex, portMAX_DELAY);
bool resolved = (*reservation_codec != current);
xSemaphoreGive(data->mutex);
if (resolved) {
break;
}
vTaskDelay(pdMS_TO_TICKS(20));
}
}
LOG_I(
TAG,
"Re-bound %s codec: %s -> %s",
(direction == AUDIO_CODEC_DIR_INPUT) ? "input" : "output",
(current != nullptr) ? current->name : "(none)",
(preferred != nullptr) ? preferred->name : "(none)"
);
notify_change(data, data->self, direction, AUDIO_STREAM_CHANGE_CODEC);
}
}
// region AudioStreamApi
error_t open_stream(Device* device, const struct AudioStreamConfig* config, AudioCodecDirection direction, AudioStreamHandle* out_handle) {
@ -293,20 +443,24 @@ error_t open_stream(Device* device, const struct AudioStreamConfig* config, Audi
// above while we do the (potentially slow) codec open below outside the lock.
auto* reservation = reinterpret_cast<AudioStreamHandleImpl*>(1);
*slot = reservation;
// See input_reservation_codec's comment: no handle exists yet for a concurrent STOPPED
// event to mark listener_closed on, so it polls this instead.
Device** reservation_codec = is_input ? &data->input_reservation_codec : &data->output_reservation_codec;
*reservation_codec = codec;
xSemaphoreGive(data->mutex);
uint32_t codec_rate = 0;
if (audio_codec_get_native_sample_rate(codec, direction, &codec_rate) != ERROR_NONE || codec_rate == 0) {
xSemaphoreTake(data->mutex, portMAX_DELAY);
if (*slot == reservation) { *slot = nullptr; }
*reservation_codec = nullptr;
xSemaphoreGive(data->mutex);
return ERROR_RESOURCE;
}
// The codec must be opened with its native channel layout (e.g. 4 for a 4-slot TDM mic
// ADC) -- opening it with the app's requested channel count can silently corrupt the
// stream (ES7210 in TDM mode halves its configured bit depth for <= 2 channels). We
// convert between the codec's layout and the app's requested channel count ourselves.
// Must open with the codec's native channel layout (e.g. 4 for a 4-slot TDM mic ADC):
// opening with the app's count can silently corrupt the stream (ES7210 TDM halves its bit
// depth for <= 2 channels). We convert to the app's requested layout ourselves.
uint8_t codec_channels = config->channels;
if (audio_codec_get_native_channels(codec, direction, &codec_channels) != ERROR_NONE || codec_channels == 0) {
codec_channels = config->channels;
@ -323,6 +477,7 @@ error_t open_stream(Device* device, const struct AudioStreamConfig* config, Audi
LOG_E(TAG, "Failed to open codec for %s", is_input ? "input" : "output");
xSemaphoreTake(data->mutex, portMAX_DELAY);
if (*slot == reservation) { *slot = nullptr; }
*reservation_codec = nullptr;
xSemaphoreGive(data->mutex);
return ERROR_RESOURCE;
}
@ -342,6 +497,7 @@ error_t open_stream(Device* device, const struct AudioStreamConfig* config, Audi
handle->device = device;
handle->direction = direction;
handle->config = *config;
handle->codec = codec;
handle->codec_rate = codec_rate;
handle->codec_channels = codec_channels;
handle->bytes_per_frame = (uint8_t) ((config->bits_per_sample / 8) * config->channels);
@ -356,12 +512,30 @@ error_t open_stream(Device* device, const struct AudioStreamConfig* config, Audi
audio_codec_close(codec);
xSemaphoreTake(data->mutex, portMAX_DELAY);
if (*slot == reservation) { *slot = nullptr; }
*reservation_codec = nullptr;
xSemaphoreGive(data->mutex);
return ERROR_OUT_OF_MEMORY;
}
xSemaphoreTake(data->mutex, portMAX_DELAY);
Device* bound_codec = is_input ? data->input_codec : data->output_codec;
if (bound_codec != codec) {
// A codec device event re-bound this direction to another codec while we were
// opening this one (e.g. USB headphones attached mid-open). Undo the open instead
// of committing a handle whose codec no longer matches the slot: the app's retry
// picks up the new codec.
if (*slot == reservation) {
*slot = nullptr;
}
*reservation_codec = nullptr;
xSemaphoreGive(data->mutex);
audio_codec_close(codec);
vSemaphoreDelete(handle->drain_semaphore);
delete handle;
return ERROR_RESOURCE;
}
*slot = handle;
*reservation_codec = nullptr;
xSemaphoreGive(data->mutex);
*out_handle = handle;
@ -383,7 +557,7 @@ error_t read_stream(AudioStreamHandle handle_base, void* out_data, size_t data_s
}
auto* data = GET_DATA(handle->device);
if (data == nullptr || data->input_codec == nullptr) {
if (data == nullptr) {
return ERROR_RESOURCE;
}
@ -395,7 +569,8 @@ error_t read_stream(AudioStreamHandle handle_base, void* out_data, size_t data_s
return ERROR_NONE;
}
if (!io_begin(data, handle)) {
Device* codec = nullptr;
if (!io_begin(data, handle, &codec)) {
return ERROR_INVALID_STATE;
}
@ -405,7 +580,7 @@ error_t read_stream(AudioStreamHandle handle_base, void* out_data, size_t data_s
error_t result;
if (same_rate && same_channels) {
size_t codec_bytes_read = 0;
result = audio_codec_read(data->input_codec, out_data, data_size, &codec_bytes_read, timeout);
result = audio_codec_read(codec, out_data, data_size, &codec_bytes_read, timeout);
if (bytes_read != nullptr) {
*bytes_read = codec_bytes_read;
}
@ -418,7 +593,7 @@ error_t read_stream(AudioStreamHandle handle_base, void* out_data, size_t data_s
}
size_t codec_bytes_read = 0;
result = audio_codec_read(data->input_codec, handle->codec_buffer.data(), codec_bytes_needed, &codec_bytes_read, timeout);
result = audio_codec_read(codec, handle->codec_buffer.data(), codec_bytes_needed, &codec_bytes_read, timeout);
if (result == ERROR_NONE) {
size_t codec_frames_read = codec_bytes_read / handle->codec_bytes_per_frame;
const int16_t* rate_input = reinterpret_cast<const int16_t*>(handle->codec_buffer.data());
@ -468,7 +643,7 @@ error_t write_stream(AudioStreamHandle handle_base, const void* in_data, size_t
}
auto* data = GET_DATA(handle->device);
if (data == nullptr || data->output_codec == nullptr) {
if (data == nullptr) {
return ERROR_RESOURCE;
}
@ -480,7 +655,8 @@ error_t write_stream(AudioStreamHandle handle_base, const void* in_data, size_t
return ERROR_NONE;
}
if (!io_begin(data, handle)) {
Device* codec = nullptr;
if (!io_begin(data, handle, &codec)) {
return ERROR_INVALID_STATE;
}
@ -490,7 +666,7 @@ error_t write_stream(AudioStreamHandle handle_base, const void* in_data, size_t
error_t result;
if (same_rate && same_channels) {
size_t codec_bytes_written = 0;
result = audio_codec_write(data->output_codec, in_data, data_size, &codec_bytes_written, timeout);
result = audio_codec_write(codec, in_data, data_size, &codec_bytes_written, timeout);
if (bytes_written != nullptr) {
// Report in terms of input bytes consumed, matching codec_bytes_written 1:1 here.
*bytes_written = codec_bytes_written;
@ -531,7 +707,7 @@ error_t write_stream(AudioStreamHandle handle_base, const void* in_data, size_t
size_t codec_bytes_to_write = codec_frames * handle->codec_bytes_per_frame;
size_t codec_bytes_written = 0;
result = audio_codec_write(data->output_codec, handle->codec_buffer.data(), codec_bytes_to_write, &codec_bytes_written, timeout);
result = audio_codec_write(codec, handle->codec_buffer.data(), codec_bytes_to_write, &codec_bytes_written, timeout);
if (result == ERROR_NONE && bytes_written != nullptr) {
// The caller provided `data_size` worth of input; we consumed all of it (resampled/converted).
*bytes_written = data_size;
@ -550,7 +726,6 @@ error_t close_stream(AudioStreamHandle handle_base) {
}
bool is_input = (handle->direction == AUDIO_CODEC_DIR_INPUT);
Device* codec = is_input ? data->input_codec : data->output_codec;
AudioStreamHandleImpl** slot = is_input ? &data->open_input : &data->open_output;
xSemaphoreTake(data->mutex, portMAX_DELAY);
@ -564,6 +739,12 @@ error_t close_stream(AudioStreamHandle handle_base) {
*slot = nullptr;
}
bool must_drain = (handle->busy_count > 0);
// Close the codec this handle was opened against - NOT the current slot value, which may
// since have been re-bound to a different codec by a device event. Read under the mutex:
// on_codec_device_event() nulls this same field (also under the mutex) right before the
// codec Device's memory is freed, so reading it unlocked could race and capture a pointer
// that's about to dangle.
Device* codec = handle->codec;
xSemaphoreGive(data->mutex);
if (must_drain && handle->drain_semaphore != nullptr) {
@ -574,11 +755,13 @@ error_t close_stream(AudioStreamHandle handle_base) {
audio_codec_close(codec);
}
if (handle->drain_semaphore != nullptr) {
vSemaphoreDelete(handle->drain_semaphore);
// Releases this call's (the app's) lifetime reference. If a codec-hotplug listener is
// concurrently waiting to drain this same handle (see AudioStreamHandleImpl's comment), its
// own reference keeps `handle` alive until it finishes too - only the last release actually
// deletes it.
if (release_lifetime_ref(data, handle)) {
delete handle;
}
delete handle;
return ERROR_NONE;
}
@ -768,7 +951,9 @@ error_t start_device(Device* device) {
delete data;
return ERROR_OUT_OF_MEMORY;
}
data->self = device;
device_set_driver_data(device, data);
device_listener_add(on_codec_device_event, data);
return ERROR_NONE;
}
@ -778,6 +963,10 @@ error_t stop_device(Device* device) {
return ERROR_NONE;
}
// Stop reacting to codec device events before tearing anything down.
data->self = nullptr;
device_listener_remove(on_codec_device_event, data);
if (data->open_input != nullptr) {
close_stream(data->open_input);
}

View File

@ -5,12 +5,28 @@
#include <tactility/log.h>
#include <tactility/module.h>
#ifdef ESP_PLATFORM
#include <esp_audio_dec_default.h>
#include <esp_audio_simple_dec_default.h>
#endif
extern "C" {
extern Driver audio_stream_driver;
extern Device audio_stream_device;
static error_t start() {
#ifdef ESP_PLATFORM
/* Firmware-owned decoder registration, before any app can open a decode stream.
* External ELF apps reach the decoders through this module's symbol table. */
esp_audio_err_t dec_result = esp_audio_dec_register_default();
esp_audio_err_t simple_result = esp_audio_simple_dec_register_default();
if (dec_result != ESP_AUDIO_ERR_OK || simple_result != ESP_AUDIO_ERR_OK) {
LOG_E("AudioStream", "Decoder registration failed: dec=%d simple=%d",
(int) dec_result, (int) simple_result);
}
#endif
/* We crash when construct fails, because if a single driver fails to construct,
* there is no guarantee that the previously constructed drivers can be destroyed */
check(driver_construct_add(&audio_stream_driver) == ERROR_NONE);

View File

@ -1,6 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
#include <tactility/module.h>
#ifdef ESP_PLATFORM
#include <esp_audio_simple_dec.h>
// The software decoders live in the esp_audio_codec component and are registered once at
// module start (source/module.cpp), so apps never register decoders themselves.
const struct ModuleSymbol audio_stream_module_symbols[] = {
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_open),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_close),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_process),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_get_info),
MODULE_SYMBOL_TERMINATOR
};
#else // !ESP_PLATFORM: no decoder exports outside the ESP build
const struct ModuleSymbol audio_stream_module_symbols[] = {
MODULE_SYMBOL_TERMINATOR
};
#endif

View File

@ -0,0 +1,18 @@
project(AudioStreamModuleTests)
enable_language(C CXX ASM)
file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp)
add_executable(AudioStreamModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
target_include_directories(AudioStreamModuleTests PRIVATE ${DOCTESTINC})
add_test(NAME AudioStreamModuleTests COMMAND AudioStreamModuleTests)
target_link_libraries(AudioStreamModuleTests PUBLIC
TactilityKernel
audio-stream-module
platform-posix
freertos_kernel
)

View File

@ -0,0 +1,277 @@
// Regression tests for the audio-stream open/hotplug race in open_stream():
// while a codec is being opened (slot reserved), a codec device event can re-bind
// the direction to another codec. The abort path must release the reservation --
// before the fix it checked `*slot == handle` (never true at that point, the handle
// is only committed afterwards), stranding the reservation sentinel in the slot so
// every later open of that direction failed with ERROR_INVALID_STATE.
//
// The race is reproduced deterministically: a mock codec's open() blocks on a gate
// semaphore, holding open_stream() mid-window, while the test starts a second codec
// device (its DEVICE_EVENT_STARTED re-binds the direction through the module's own
// device listener).
#include "doctest.h"
#include <atomic>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <tactility/device.h>
#include <tactility/driver.h>
#include <tactility/drivers/audio_codec.h>
#include <tactility/drivers/audio_stream.h>
#include <tactility/concurrent/thread.h>
extern "C" {
// Exported by the audio-stream module (see source/audio_stream.cpp bottom).
extern Driver audio_stream_driver;
extern Device audio_stream_device;
}
// region Mock codec
struct MockCodecState {
AudioCodecDirection capabilities = AUDIO_CODEC_DIR_OUTPUT;
bool fail_open = false;
// When set, open() blocks until the gate is given, letting the test hold
// open_stream() in its mid-open window (slot reserved, codec not yet opened).
SemaphoreHandle_t open_gate = nullptr;
std::atomic<int> open_count{0};
int close_count = 0;
};
static MockCodecState state_a;
static MockCodecState state_b;
#define MOCK_STATE(device) (static_cast<MockCodecState*>(const_cast<void*>((device)->config)))
static error_t mock_start(Device* device) {
return ERROR_NONE;
}
static error_t mock_stop(Device* device) {
return ERROR_NONE;
}
static error_t mock_open(Device* device, const AudioCodecStreamConfig* config) {
auto* state = MOCK_STATE(device);
state->open_count++;
if (state->open_gate != nullptr) {
xSemaphoreTake(state->open_gate, portMAX_DELAY);
}
return state->fail_open ? ERROR_RESOURCE : ERROR_NONE;
}
static error_t mock_close(Device* device) {
MOCK_STATE(device)->close_count++;
return ERROR_NONE;
}
static error_t mock_read(Device* device, void* data, size_t data_size, size_t* bytes_read, TickType_t timeout) {
return ERROR_NOT_SUPPORTED;
}
static error_t mock_write(Device* device, const void* data, size_t data_size, size_t* bytes_written, TickType_t timeout) {
return ERROR_NOT_SUPPORTED;
}
static error_t mock_set_volume(Device* device, AudioCodecDirection direction, float volume_percent) {
return ERROR_NONE;
}
static error_t mock_get_volume(Device* device, AudioCodecDirection direction, float* volume_percent) {
*volume_percent = 100.0f;
return ERROR_NONE;
}
static error_t mock_set_mute(Device* device, AudioCodecDirection direction, bool muted) {
return ERROR_NONE;
}
static error_t mock_get_mute(Device* device, AudioCodecDirection direction, bool* muted) {
*muted = false;
return ERROR_NONE;
}
static error_t mock_get_native_sample_rate(Device* device, AudioCodecDirection direction, uint32_t* rate_hz) {
*rate_hz = 48000;
return ERROR_NONE;
}
static error_t mock_get_native_channels(Device* device, AudioCodecDirection direction, uint8_t* channels) {
*channels = 2;
return ERROR_NONE;
}
static error_t mock_get_capabilities(Device* device, AudioCodecDirection* supported_directions) {
*supported_directions = MOCK_STATE(device)->capabilities;
return ERROR_NONE;
}
static error_t mock_get_input_gain_multiplier(Device* device, float* gain) {
*gain = 1.0f;
return ERROR_NONE;
}
static const AudioCodecApi MOCK_API = {
.open = mock_open,
.close = mock_close,
.read = mock_read,
.write = mock_write,
.set_volume = mock_set_volume,
.get_volume = mock_get_volume,
.set_mute = mock_set_mute,
.get_mute = mock_get_mute,
.get_native_sample_rate = mock_get_native_sample_rate,
.get_native_channels = mock_get_native_channels,
.get_capabilities = mock_get_capabilities,
.get_input_gain_multiplier = mock_get_input_gain_multiplier,
};
static Driver mock_codec_driver = {
.name = "audio_stream_test_codec",
.compatible = (const char*[]) { "audio-stream-test-codec", nullptr },
.start_device = mock_start,
.stop_device = mock_stop,
.api = &MOCK_API,
.device_type = &AUDIO_CODEC_TYPE,
.owner = nullptr,
.internal = nullptr,
};
static Device codec_a = {
.address = 0,
.name = "test_codec_a",
.config = &state_a,
.parent = nullptr,
.internal = nullptr,
};
static Device codec_b = {
.address = 0,
.name = "test_codec_b",
.config = &state_b,
.parent = nullptr,
.internal = nullptr,
};
// endregion
static void reset_mock_state(MockCodecState& state, AudioCodecDirection capabilities) {
if (state.open_gate != nullptr) {
vSemaphoreDelete(state.open_gate);
state.open_gate = nullptr;
}
state.capabilities = capabilities;
state.fail_open = false;
state.open_count = 0;
state.close_count = 0;
}
struct OpenRequest {
Device* stream;
AudioStreamConfig config;
AudioStreamHandle handle = nullptr;
error_t result = ERROR_UNDEFINED;
};
static int32_t open_output_thread(void* context) {
auto* request = static_cast<OpenRequest*>(context);
request->result = audio_stream_open_output(request->stream, &request->config, &request->handle);
return 0;
}
static void teardown_devices_and_drivers() {
// Only tear down devices this test case actually started (each case starts a
// different subset; device_stop on a never-constructed device faults).
if (device_is_added(&codec_a)) {
device_stop(&codec_a);
device_remove(&codec_a);
device_destruct(&codec_a);
}
if (device_is_added(&codec_b)) {
device_stop(&codec_b);
device_remove(&codec_b);
device_destruct(&codec_b);
}
if (device_is_added(&audio_stream_device)) {
device_stop(&audio_stream_device);
device_remove(&audio_stream_device);
device_destruct(&audio_stream_device);
}
driver_remove_destruct(&mock_codec_driver);
driver_remove_destruct(&audio_stream_driver);
}
TEST_CASE("open_stream reservations are released on codec re-bind and failed codec open") {
// Codec A is both-capable (binds output and input); codec B is output-only, so
// starting it re-binds the output direction away from A.
reset_mock_state(state_a, AUDIO_CODEC_DIR_BOTH);
reset_mock_state(state_b, AUDIO_CODEC_DIR_OUTPUT);
REQUIRE_EQ(driver_construct_add(&audio_stream_driver), ERROR_NONE);
REQUIRE_EQ(driver_construct_add(&mock_codec_driver), ERROR_NONE);
REQUIRE_EQ(device_construct_add_start(&audio_stream_device, "audio-stream"), ERROR_NONE);
REQUIRE_EQ(device_construct_add_start(&codec_a, "audio-stream-test-codec"), ERROR_NONE);
// Hold open_stream() mid-open: the slot is reserved and the codec open blocks.
state_a.open_gate = xSemaphoreCreateBinary();
REQUIRE(state_a.open_gate != nullptr);
OpenRequest request = {
.stream = &audio_stream_device,
.config = { .sample_rate = 44100, .bits_per_sample = 16, .channels = 2 },
};
Thread* thread = thread_alloc_full("open_race", 4096, open_output_thread, &request, -1);
REQUIRE(thread != nullptr);
REQUIRE_EQ(thread_start(thread), ERROR_NONE);
// Wait until the open is inside the codec (reservation is set by then).
for (int i = 0; i < 500 && state_a.open_count == 0; ++i) {
vTaskDelay(pdMS_TO_TICKS(2));
}
REQUIRE_EQ(state_a.open_count, 1);
// Re-bind the output direction mid-open: codec B's DEVICE_EVENT_STARTED makes it
// the preferred output codec. The module's listener leaves the reserved slot alone.
REQUIRE_EQ(device_construct_add_start(&codec_b, "audio-stream-test-codec"), ERROR_NONE);
// Release the gate; the open aborts because its codec no longer matches the slot.
xSemaphoreGive(state_a.open_gate);
REQUIRE_EQ(thread_join(thread, pdMS_TO_TICKS(10000), pdMS_TO_TICKS(5)), ERROR_NONE);
thread_free(thread);
REQUIRE_EQ(request.result, ERROR_RESOURCE);
REQUIRE_EQ(request.handle, nullptr);
REQUIRE_EQ(state_a.close_count, 1); // the aborted open undid its codec open
// The regression: the reservation must be released, so the retry open succeeds
// (before the fix this failed permanently with ERROR_INVALID_STATE).
AudioStreamConfig config = { .sample_rate = 44100, .bits_per_sample = 16, .channels = 2 };
AudioStreamHandle handle = nullptr;
REQUIRE_EQ(audio_stream_open_output(&audio_stream_device, &config, &handle), ERROR_NONE);
REQUIRE(handle != nullptr);
REQUIRE_EQ(state_b.open_count, 1);
// Normal close still succeeds, and another open/close cycle works afterwards.
REQUIRE_EQ(audio_stream_close(handle), ERROR_NONE);
REQUIRE_EQ(state_b.close_count, 1);
handle = nullptr;
REQUIRE_EQ(audio_stream_open_output(&audio_stream_device, &config, &handle), ERROR_NONE);
REQUIRE_EQ(audio_stream_close(handle), ERROR_NONE);
// A failed codec open must also release the reservation: the retry reaches the
// codec again (a stranded reservation would return ERROR_INVALID_STATE instead),
// and once the codec succeeds the stream opens and closes normally.
state_b.fail_open = true;
REQUIRE_EQ(audio_stream_open_output(&audio_stream_device, &config, &handle), ERROR_RESOURCE);
REQUIRE_EQ(audio_stream_open_output(&audio_stream_device, &config, &handle), ERROR_RESOURCE);
REQUIRE_EQ(state_b.open_count, 4); // 1 + 1 + 2 failed attempts
state_b.fail_open = false;
REQUIRE_EQ(audio_stream_open_output(&audio_stream_device, &config, &handle), ERROR_NONE);
REQUIRE_EQ(audio_stream_close(handle), ERROR_NONE);
teardown_devices_and_drivers();
}

View File

@ -0,0 +1,53 @@
#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"
#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;
}

View File

@ -15,26 +15,12 @@ tactility_add_module(app-module
# Tells source/io.cpp its real-syscall fallback must go through __real_read/write/close() rather
# than calling ::read/::write/::close() directly, on every platform where those are wrapped: via
# -Wl,--wrap= on ESP-IDF (see the top-level CMakeLists.txt) and non-Apple POSIX (below), or via
# source/stdio_wrap.cpp's dyld interpose on Apple (whose linker lacks --wrap).
# -Wl,--wrap= on ESP-IDF (see the top-level CMakeLists.txt), or via source/stdio_wrap.cpp's own
# read/write/close and printf-family definitions on POSIX (dyld interpose on Apple, plain
# symbol overrides elsewhere - see that file for why POSIX doesn't use --wrap).
tactility_get_module_name(app-module MODULE_NAME)
target_compile_definitions(${MODULE_NAME} PRIVATE TT_APP_IO_WRAPS_STDIO)
# Routes every read()/write()/close() and printf-family call to source/stdio_wrap.cpp's __wrap_*
# functions; see that file for what they do and why. ESP-IDF wraps the same symbols itself (see
# the top-level CMakeLists.txt); Apple gets the same routing via dyld interpose instead, self-
# registered in that file. PUBLIC so every consumer of this module (Tactility, and any test target
# that links app-module directly) gets the flags too.
if (NOT ESP_PLATFORM AND NOT APPLE)
tactility_get_module_name(app-module MODULE_NAME)
target_link_options(${MODULE_NAME} PUBLIC
"-Wl,--wrap=read" "-Wl,--wrap=write" "-Wl,--wrap=close"
"-Wl,--wrap=printf" "-Wl,--wrap=fprintf" "-Wl,--wrap=vprintf" "-Wl,--wrap=vfprintf"
"-Wl,--wrap=puts" "-Wl,--wrap=fputs" "-Wl,--wrap=putchar" "-Wl,--wrap=fputc"
"-Wl,--wrap=getchar" "-Wl,--wrap=fgetc" "-Wl,--wrap=fgets"
)
endif ()
# install.cpp resolves an installed binary's fixed bin/<platform>/<binary>.so path itself, so it
# needs the same platform-arch string app-posix-module's own CMakeLists.txt defines for its
# loader (the ESP32 equivalent, CONFIG_IDF_TARGET, comes for free from sdkconfig.h there).

View File

@ -94,6 +94,8 @@ error_t app_execute_for_result_with_streams(
*/
bool app_is_executable(struct AppLocation location);
bool app_is_executable_path(const char* path);
#ifdef __cplusplus
}
#endif

View File

@ -12,39 +12,28 @@
extern "C" {
#endif
/** Which readiness condition to block for in AppFileOps::await(). */
typedef enum {
APP_FILE_WAIT_READABLE,
APP_FILE_WAIT_WRITABLE,
} AppFileWait;
/** Bits returned by AppFileOps::poll(). */
#define APP_FILE_READABLE (1u << 0)
#define APP_FILE_WRITABLE (1u << 1)
/**
* Operations table for one kind of file-like object (stream, file, device, ...). Every function
* takes the type-erased `object` a concrete AppFile instance was constructed with.
*/
struct AppFileOps {
ssize_t (*read)(void* object, void* buffer, size_t size);
ssize_t (*write)(void* object, const void* buffer, size_t size);
error_t (*close)(void* object);
error_t (*await)(void* object, AppFileWait wait, TickType_t timeout);
/** @return bitmask of APP_FILE_READABLE / APP_FILE_WRITABLE. */
uint32_t (*poll)(void* object);
/** Optional (may be NULL). Called by app_fd_table_get_and_retain() atomically with the fd
* lookup, before handing `object` to a caller about to dispatch into it, so a concurrent
* teardown of `object` can wait for that dispatch to finish instead of racing it. The caller
* calls release() once done, regardless of what the dispatched call returned. */
void (*retain)(void* object);
void (*release)(void* object);
};
/** A file-descriptor-table entry: an operations table paired with the object it operates on. */
struct AppFile {
const struct AppFileOps* ops;
void* object;
bool suppress_console_tee;
};
#ifdef __cplusplus

View File

@ -1,9 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <app/file.h>
#include <stddef.h>
#include <sys/types.h>
#include <tactility/error.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -16,20 +20,31 @@ extern "C" {
#define APP_MAX_FDS 16
/**
* FD-table dispatch for read()/write()/close(). When the calling task belongs to a running app
* instance and @a fd is one that instance bound/allocated itself, it's looked up in that
* instance's own fd table. Otherwise (no app instance, e.g. a kernel service task; or an app
* instance's own fd that was never bound through app-module, e.g. a real file from fopen()/
* open(), which this layer never intercepts) @a fd is a real underlying fd and the call falls
* through to the real syscall unchanged.
* @return number of bytes transferred, 0 on EOF (read) or a closed peer (write), or -1 with
* errno set on failure. This is the fd-layer translation of AppFileOps::read()/write()'s ssize_t
* and AppFileOps::close()'s error_t.
* FD-table dispatch for read()/write()/close(). Falls through to the real syscall for a fd not
* bound by the calling task's own app instance.
*/
ssize_t app_io_read(int fd, void* buffer, size_t size);
ssize_t app_io_write(int fd, const void* buffer, size_t size);
int app_io_close(int fd);
/**
* FD-table dispatch for AppFileOps::await(): blocks until @a fd is ready or @a timeout elapses.
* @retval ERROR_NOT_FOUND @a fd isn't bound in the calling task's own app instance fd table
* @retval ERROR_TIMEOUT @a timeout elapsed
* @retval ERROR_NONE the condition is true
*/
error_t app_io_await(int fd, AppFileWait wait, TickType_t timeout);
/**
* Installs a custom AppFileOps at @a fd in the calling task's own app instance fd table.
* Unlike AppStreamBinding, writes are never teed to the real underlying fd.
* @warning Must be called from the app instance's own task.
* @retval ERROR_NOT_FOUND the calling task isn't a running app instance
* @retval ERROR_OUT_OF_RANGE @a fd is outside [0, APP_MAX_FDS)
* @retval ERROR_NONE on success
*/
error_t app_io_bind_self(int fd, const struct AppFileOps* ops, void* object);
#ifdef __cplusplus
}
#endif

View File

@ -32,9 +32,10 @@ enum AppManifestFlags {
};
/** Largest stack depth (in words) an app may request. Keeps `depth * sizeof(StackType_t)` safely
* bounded and stops one app from claiming an unreasonable share of available RAM. A depth beyond
* this must be rejected outright, not silently truncated or clamped. */
#define APP_STACK_SIZE_MAX 16384
* bounded and stops one app from claiming an unreasonable share of available RAM.
* A depth beyond must be rejected outright.
* Was last increased because of recursive-descent shell interpreter. */
#define APP_STACK_SIZE_MAX 65535
struct AppStackConfig {
/** Stack depth (in words, matching FreeRTOS's configSTACK_DEPTH_TYPE) for this app's task.

View File

@ -17,7 +17,7 @@
extern "C" {
#endif
/** @warning This is internal data. Do not read/write to it directly. */
/** @warning Internal data. */
struct AppStreamBuffer {
uint8_t* data;
size_t capacity;
@ -29,45 +29,29 @@ struct AppStreamBuffer {
/**
* Buffered byte-oriented communication between one producer task and one consumer task. The
* consumer owns the AppStream object and its lifetime. See app_stream_subscribe().
*
* @warning This is internal data. Do not read/write to it directly.
* @warning Internal data.
*/
struct AppStream {
struct AppStreamBuffer buffer;
AppInstanceId producer_id;
TaskHandle_t producer_task;
/** fd this stream is installed at in producer_id's fd table; set by
* app_stream_subscribe()/app_start_with_streams(), used by
* app_stream_unsubscribe() to find it again. */
int producer_fd;
struct Mutex mutex;
/** Caller-owned group readiness is signalled on; see app_stream_subscribe(). */
struct TaskEventGroup* event_group;
uint32_t readable_bit;
uint32_t writable_bit;
bool closed;
/** Count of AppFileOps calls currently executing against this stream; app_stream_unsubscribe()
* waits for this to reach 0 before destructing `mutex`, since a call already blocked in
* app_stream_await() when unsubscribe starts only wakes (it doesn't vanish) when closed. */
int active_operations;
};
/**
* Registers @a stream as the file-like object bound to @a producer_id's fd table at
* @a producer_fd, claiming two bits from @a event_group for its readable/writable readiness.
* There is at most one subscriber for a given app fd. Subscribing over an existing one
* atomically closes it first (any task blocked on it wakes; already-buffered bytes remain
* readable until drained) and installs @a stream in its place.
* @param[in,out] stream caller-owned. Storage must remain valid until app_stream_unsubscribe()
* returns. That is the only operation guaranteeing both that the fd-table binding is gone and
* that no AppFileOps call is still executing against @a stream; app_stream_close() alone does
* neither.
* @param[in] buffer ring buffer storage; caller-owned, same validity requirement as @a stream.
* @param[in] buffer_capacity size of @a buffer in bytes.
* @param[in] event_group caller-owned; must outlive @a stream (i.e. be destructed only after
* app_stream_unsubscribe()). Lets a task wait on this stream's readiness together with other
* event sources sharing the same group via task_event_group_wait()/task_event_group_wait_any().
* @a producer_fd, claiming two bits from @a event_group for readiness. At most one subscriber
* per fd; subscribing over an existing one closes it first.
* @param[in,out] stream caller-owned; must stay valid until app_stream_unsubscribe() returns.
* @param[in] buffer ring buffer storage; caller-owned, same validity as @a stream.
* @param[in] event_group caller-owned; must outlive @a stream.
* @retval ERROR_NOT_FOUND no instance with this id is running
* @retval ERROR_OUT_OF_RANGE @a producer_fd is out of range
* @retval ERROR_RESOURCE @a event_group has no free bits left to claim
@ -76,19 +60,22 @@ struct AppStream {
error_t app_stream_subscribe(struct AppStream* stream, void* buffer, size_t buffer_capacity, struct TaskEventGroup* event_group, AppInstanceId producer_id, int producer_fd);
/**
* Removes @a stream's binding from whichever fd table it was installed in (further use of that
* fd then fails), wakes and waits for every AppFileOps call currently in flight against
* @a stream to finish, then releases its two bits back to the event_group given to
* app_stream_subscribe() and destructs its internal mutex. Only after this returns is
* @a stream's storage safe to free or reuse.
* Binds an already-subscribed @a stream at a second fd too, so writes to either fd land in the
* same buffer in true write-time order (e.g. aliasing stderr onto a stdout stream).
* @retval ERROR_NOT_FOUND no instance with @a stream's producer_id is running
* @retval ERROR_OUT_OF_RANGE @a alias_fd is out of range
*/
error_t app_stream_bind_alias_fd(struct AppStream* stream, int alias_fd);
/**
* Removes @a stream's fd-table binding, waits for in-flight AppFileOps calls to finish, then
* releases its event bits and destructs its mutex. Only after this returns is @a stream safe to
* free or reuse.
*/
error_t app_stream_unsubscribe(struct AppStream* stream);
/**
* Blocks until @a stream becomes readable/writable (per @a wait) or @a timeout elapses. Checks
* the current state directly before blocking, so a permanently-true condition (e.g. closed)
* keeps returning immediately on every call, even though the underlying event bit itself is
* one-shot (task_event_group_wait() clears a matched bit on exit).
* Blocks until @a stream becomes readable/writable (per @a wait) or @a timeout elapses.
* @retval ERROR_NONE the condition is true
* @retval ERROR_TIMEOUT @a timeout elapsed
* @retval ERROR_ISR_STATUS called from an ISR
@ -98,16 +85,10 @@ error_t app_stream_await(struct AppStream* stream, AppFileWait wait, TickType_t
/** Non-blocking: copies up to @a buffer_size currently-available bytes out of @a stream. */
size_t app_stream_read(struct AppStream* stream, void* buffer, size_t buffer_size);
/** Non-blocking: copies up to @a buffer_size bytes into @a stream, as much as currently fits.
* Copies nothing and returns 0 once @a stream is closed. */
/** Non-blocking: copies up to @a buffer_size bytes into @a stream. Returns 0 once closed. */
size_t app_stream_write(struct AppStream* stream, const void* buffer, size_t buffer_size);
/**
* Marks @a stream closed: wakes any task blocked in app_stream_await(), and causes the other side
* to observe EOF (reader, once drained) or a write error (writer). Safe to call while another
* task may be blocked on @a stream, unlike app_stream_unsubscribe() (see its own doc); does not
* by itself make @a stream's storage safe to free.
*/
/** Marks @a stream closed: readers see EOF, writers fail. Does not free @a stream's storage. */
error_t app_stream_close(struct AppStream* stream);
#ifdef __cplusplus

View File

@ -58,9 +58,10 @@ void app_fd_table_teardown(struct AppFdTable* table);
/**
* Installs {ops, object} at @a fd, closing whatever was previously there first (the null device
* counts as "previously there" for fds 0-2, so this doubles as their initial stdio binding).
* @param[in] suppress_console_tee see AppFile::suppress_console_tee
* @retval ERROR_OUT_OF_RANGE @a fd is outside [0, APP_MAX_FDS)
*/
error_t app_fd_table_bind(struct AppFdTable* table, int fd, const struct AppFileOps* ops, void* object);
error_t app_fd_table_bind(struct AppFdTable* table, int fd, const struct AppFileOps* ops, void* object, bool suppress_console_tee);
/**
* Installs {ops, object} at the lowest unused fd >= 3.

View File

@ -44,6 +44,18 @@ error_t app_execute_for_result_with_streams(AppLocation location, AppStackConfig
return app_manager_start_internal(nullptr, location, stack, parent_instance_id, argc, argv, bindings, binding_count, out_app_instance_id);
}
bool app_is_executable_path(const char* path) {
const AppLoaderApi* loader = find_loader_api(APP_LOCATION_PATH);
if (loader == nullptr || loader->is_executable == nullptr) {
return false;
}
AppLocation location = {
.type = APP_LOCATION_PATH,
.location = (void*)path,
};
return loader->is_executable(location);
}
bool app_is_executable(AppLocation location) {
const AppLoaderApi* loader = find_loader_api(location.type);
if (loader == nullptr || loader->is_executable == nullptr) {

View File

@ -71,7 +71,7 @@ void app_fd_table_teardown(AppFdTable* table) {
mutex_destruct(&table->mutex);
}
error_t app_fd_table_bind(AppFdTable* table, int fd, const AppFileOps* ops, void* object) {
error_t app_fd_table_bind(AppFdTable* table, int fd, const AppFileOps* ops, void* object, bool suppress_console_tee) {
if (!fd_in_range(fd)) {
return ERROR_OUT_OF_RANGE;
}
@ -81,7 +81,7 @@ error_t app_fd_table_bind(AppFdTable* table, int fd, const AppFileOps* ops, void
AppFdSlot& slot = table->slots[fd];
AppFile old = slot.file;
bool had_old = slot.in_use;
slot.file = { .ops = ops, .object = object };
slot.file = { .ops = ops, .object = object, .suppress_console_tee = suppress_console_tee };
slot.in_use = true;
slot.ever_used = true;
mutex_unlock(&table->mutex);

View File

@ -92,7 +92,7 @@ bool delete_recursively(const std::string& path) {
}
bool get_app_install_directory(std::string& out_path) {
char root[192];
char root[FILE_MAX_PATH_STRING_LENGTH];
if (paths_get_data_path(root, sizeof(root)) != ERROR_NONE) {
return false;
}

View File

@ -96,14 +96,17 @@ ssize_t app_io_write(int fd, const void* buffer, size_t size) {
if (file.ops->release != nullptr) {
file.ops->release(file.object);
}
// Tee to the real fd too: a bound stream only exists because a parent explicitly asked
// to capture this app instance's own output (see AppStreamBinding), but generic code
// running on that same instance's thread - most commonly the platform's own logging
// Tee to the real fd too: a bound stream normally exists because a parent explicitly
// asked to capture this app instance's own output (see AppStreamBinding), but generic
// code running on that same instance's thread - most commonly the platform's own logging
// (LOG_I/etc, which calls write() the same as anything else) - has no way to know its
// output is currently being intercepted. Without this, a log line emitted while any app
// instance has its stdout captured would vanish from the console entirely instead of
// just also being visible to the capturing parent.
real_write(fd, buffer, size);
// just also being visible to the capturing parent. An instance that bound its own fd
// (see app_io_bind_self()) opts out - it wants exclusive ownership, not a silent tap.
if (!file.suppress_console_tee) {
real_write(fd, buffer, size);
}
return result;
}
if (table != nullptr && app_fd_table_is_app_owned(table, fd)) {
@ -128,4 +131,28 @@ int app_io_close(int fd) {
return real_close(fd);
}
error_t app_io_await(int fd, AppFileWait wait, TickType_t timeout) {
AppFdTable* table = current_app_fd_table();
if (table == nullptr) {
return ERROR_NOT_FOUND;
}
AppFile file {};
if (!app_fd_table_get_and_retain(table, fd, &file)) {
return ERROR_NOT_FOUND;
}
error_t result = file.ops->await(file.object, wait, timeout);
if (file.ops->release != nullptr) {
file.ops->release(file.object);
}
return result;
}
error_t app_io_bind_self(int fd, const AppFileOps* ops, void* object) {
AppFdTable* table = current_app_fd_table();
if (table == nullptr) {
return ERROR_NOT_FOUND;
}
return app_fd_table_bind(table, fd, ops, object, /*suppress_console_tee=*/true);
}
} // extern "C"

View File

@ -33,6 +33,7 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(app_execute_with_streams),
DEFINE_MODULE_SYMBOL(app_execute_for_result_with_streams),
DEFINE_MODULE_SYMBOL(app_is_executable),
DEFINE_MODULE_SYMBOL(app_is_executable_path),
// app/install
DEFINE_MODULE_SYMBOL(app_get_install_path),
DEFINE_MODULE_SYMBOL(app_install),
@ -41,6 +42,8 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(app_io_read),
DEFINE_MODULE_SYMBOL(app_io_write),
DEFINE_MODULE_SYMBOL(app_io_close),
DEFINE_MODULE_SYMBOL(app_io_await),
DEFINE_MODULE_SYMBOL(app_io_bind_self),
// app/manager
DEFINE_MODULE_SYMBOL(app_manager_stop),
DEFINE_MODULE_SYMBOL(app_manager_get_state),
@ -76,6 +79,7 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(app_start_with_streams),
DEFINE_MODULE_SYMBOL(app_start_for_result_with_streams),
// app/stream
DEFINE_MODULE_SYMBOL(app_stream_bind_alias_fd),
DEFINE_MODULE_SYMBOL(app_stream_subscribe),
DEFINE_MODULE_SYMBOL(app_stream_unsubscribe),
DEFINE_MODULE_SYMBOL(app_stream_await),

View File

@ -31,7 +31,7 @@ bool app_get_install_dir_from_binary_path(const char* binary_path, std::string&
extern "C" {
error_t app_paths_get_user_data_directory(const char* app_id, char* out_path, size_t out_path_size) {
char root[192];
char root[FILE_MAX_PATH_STRING_LENGTH];
error_t error = paths_get_data_path(root, sizeof(root));
if (error != ERROR_NONE) {
return error;
@ -44,7 +44,7 @@ error_t app_paths_get_user_data_directory(const char* app_id, char* out_path, si
}
error_t app_paths_get_user_data_path(const char* app_id, const char* child_path, char* out_path, size_t out_path_size) {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
error_t error = app_paths_get_user_data_directory(app_id, directory, sizeof(directory));
if (error != ERROR_NONE) {
return error;
@ -80,7 +80,7 @@ error_t app_paths_get_assets_directory(const char* app_id, char* out_path, size_
}
error_t app_paths_get_assets_path(const char* app_id, const char* child_path, char* out_path, size_t out_path_size) {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
error_t error = app_paths_get_assets_directory(app_id, directory, sizeof(directory));
if (error != ERROR_NONE) {
return error;

View File

@ -412,7 +412,7 @@ error_t app_scheduler_start(AppInstanceId app_instance_id, AppLocation location,
vTaskPrioritySet(task_handle, APP_TASK_PRIORITY);
vTaskResume(task_handle);
memory_print_stats();
memory_log_stats();
return ERROR_NONE;
}

View File

@ -1,20 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
// Paired with -Wl,--wrap= on POSIX (this module's own CMakeLists.txt) and ESP32 (top-level
// CMakeLists.txt); self-registered via dyld interpose below on Apple, whose linker doesn't
// support --wrap.
// ESP32 uses -Wl,--wrap=. POSIX can't: --wrap doesn't reach a dlopen()ed app's own printf/write
// calls, so these are defined under their real names instead - dyld interpose on Apple, plain
// strong definitions elsewhere (ELF gives the main executable's symbols priority process-wide).
#include <app/io.h>
#include <sys/types.h>
#ifdef ESP_PLATFORM
// Newlib's own stdio (fflush()'s buffer-flush path, in particular) calls the reentrant
// _read_r/_write_r/_close_r syscall stubs directly, not the plain read()/write()/close() newlib
// itself provides as thin wrappers around them (see e.g. esp-idf's components/newlib/src/
// syscalls.c: `write(fd, dst, size) { return _write_r(__getreent(), fd, dst, size); }`)
// Wrapping the plain names only catches direct write()-style callers, not newlib's own internal
// stdio calls, so the _r stubs are wrapped here instead.
// Newlib's own stdio calls the reentrant _read_r/_write_r/_close_r stubs directly, not the plain
// read/write/close wrappers, so those stubs are wrapped instead of the plain names.
#include <reent.h>
extern "C" {
@ -54,15 +50,7 @@ int __wrap_close(int fd) {
}
#endif // ESP_PLATFORM
#ifdef __APPLE__
// --wrap also synthesizes __real_read/write/close automatically; dyld interpose doesn't, so
// io.cpp's TT_APP_IO_WRAPS_STDIO fallback needs them defined here. dlsym(RTLD_NEXT, ...) is the
// standard way to reach the true libSystem implementation despite the interpose below: a direct
// call to read/write/close from this file would just recurse into __wrap_read/write/close, since
// interpose rewrites every reference to those symbols in the process, this file included.
// dlsym(RTLD_NEXT, ...) avoids recursing into our own override below.
#include <dlfcn.h>
#include <unistd.h>
@ -85,9 +73,9 @@ int __real_close(int fd) {
}
// <mach-o/dyld-interposing.h> isn't a public SDK header (it ships with dyld's own source, not
// Xcode/Command Line Tools), so this reimplements its DYLD_INTERPOSE macro locally; reused below
// for the printf-family interposes too.
#ifdef __APPLE__
// <mach-o/dyld-interposing.h> isn't a public SDK header, so reimplemented locally.
#define TT_DYLD_INTERPOSE(replacement, replacee) \
__attribute__((used)) static struct { const void* replacement; const void* replacee; } \
tt_interpose_##replacee __attribute__((section("__DATA,__interpose"))) = { \
@ -98,21 +86,37 @@ TT_DYLD_INTERPOSE(__wrap_read, read)
TT_DYLD_INTERPOSE(__wrap_write, write)
TT_DYLD_INTERPOSE(__wrap_close, close)
#else
extern "C" {
ssize_t read(int fd, void* buffer, size_t size) {
return __wrap_read(fd, buffer, size);
}
ssize_t write(int fd, const void* buffer, size_t size) {
return __wrap_write(fd, buffer, size);
}
int close(int fd) {
return __wrap_close(fd);
}
}
#endif // __APPLE__
#endif // ESP_PLATFORM
// region glibc stdio wraps
//
// libc's printf/fprintf/etc are compiled into the C library and call an internal, non-exported
// write() alias, which --wrap=write/the read/write/close interpose above can't reach: only calls
// WE make to the public symbol. These wraps instead redirect calls WE make to printf/fprintf/etc,
// the same trick as read/write/close above. Newlib (ESP-IDF) doesn't have this gap: its stdio does
// call the wrappable syscall stubs, so this block is POSIX-only.
// libc's printf/fprintf/etc call an internal, non-exported write() alias that the read/write/close
// wraps above can't reach, so these redirect calls to printf/fprintf/etc directly. POSIX-only:
// newlib's stdio already goes through the wrappable syscall stubs.
//
// Scoped to the printf/getc families only: fread/fwrite take an arbitrary FILE* and are already
// used sitewide for real file I/O (e.g. File.cpp's readBinaryInternal), so wrapping them would
// route every such call through this file's stdin/stdout check, a correctness risk for unrelated
// code that isn't worth taking here. putc/getc are excluded too since libc defines them as
// macros, not real calls, so wrapping those symbols wouldn't reliably intercept them.
// Scoped to printf/getc: fread/fwrite are used sitewide for real file I/O, so wrapping them would
// be a correctness risk for unrelated code. putc/getc are macros, not real calls, so wrapping
// those symbols wouldn't reliably intercept them.
#if !defined(ESP_PLATFORM)
@ -130,10 +134,6 @@ int __real_fgetc(FILE* stream);
char* __real_fgets(char* buffer, int size, FILE* stream);
}
#ifdef __APPLE__
// --wrap synthesizes these automatically elsewhere; on Apple they're defined here via
// dlsym(RTLD_NEXT, ...) instead. See the read/write/close __real_* block above for why.
#include <dlfcn.h>
extern "C" {
@ -165,15 +165,13 @@ char* __real_fgets(char* buffer, int size, FILE* stream) {
}
#endif // __APPLE__
namespace {
void writeAllToStdout(const void* data, size_t size) {
void writeAllTo(int fd, const void* data, size_t size) {
const auto* bytes = static_cast<const char*>(data);
size_t remaining = size;
while (remaining > 0) {
ssize_t written = app_io_write(STDOUT_FILENO, bytes, remaining);
ssize_t written = app_io_write(fd, bytes, remaining);
if (written <= 0) {
break;
}
@ -182,9 +180,7 @@ void writeAllToStdout(const void* data, size_t size) {
}
}
// Formats into stdout via app_io_write() rather than through a FILE*'s own buffering, since that
// buffering is exactly what glibc's internal write() call sidesteps --wrap for in the first place.
int formatToStdout(const char* format, va_list args) {
int formatTo(int fd, const char* format, va_list args) {
char stackBuffer[256];
va_list argsForStack;
va_copy(argsForStack, args);
@ -194,7 +190,7 @@ int formatToStdout(const char* format, va_list args) {
return needed;
}
if (static_cast<size_t>(needed) < sizeof(stackBuffer)) {
writeAllToStdout(stackBuffer, static_cast<size_t>(needed));
writeAllTo(fd, stackBuffer, static_cast<size_t>(needed));
return needed;
}
auto heapBuffer = std::make_unique<char[]>(static_cast<size_t>(needed) + 1);
@ -202,7 +198,7 @@ int formatToStdout(const char* format, va_list args) {
va_copy(argsForHeap, args);
vsnprintf(heapBuffer.get(), static_cast<size_t>(needed) + 1, format, argsForHeap);
va_end(argsForHeap);
writeAllToStdout(heapBuffer.get(), static_cast<size_t>(needed));
writeAllTo(fd, heapBuffer.get(), static_cast<size_t>(needed));
return needed;
}
@ -210,25 +206,32 @@ int readOneFromStdin(char& out) {
return static_cast<int>(app_io_read(STDIN_FILENO, &out, 1));
}
int targetFdOf(FILE* stream) {
if (stream == stdout) return STDOUT_FILENO;
if (stream == stderr) return STDERR_FILENO;
return -1;
}
} // namespace
extern "C" {
int __wrap_vprintf(const char* format, va_list args) {
return formatToStdout(format, args);
return formatTo(STDOUT_FILENO, format, args);
}
int __wrap_printf(const char* format, ...) {
va_list args;
va_start(args, format);
int result = formatToStdout(format, args);
int result = formatTo(STDOUT_FILENO, format, args);
va_end(args);
return result;
}
int __wrap_vfprintf(FILE* stream, const char* format, va_list args) {
if (stream == stdout) {
return formatToStdout(format, args);
int fd = targetFdOf(stream);
if (fd >= 0) {
return formatTo(fd, format, args);
}
return __real_vfprintf(stream, format, args);
}
@ -236,20 +239,22 @@ int __wrap_vfprintf(FILE* stream, const char* format, va_list args) {
int __wrap_fprintf(FILE* stream, const char* format, ...) {
va_list args;
va_start(args, format);
int result = (stream == stdout) ? formatToStdout(format, args) : __real_vfprintf(stream, format, args);
int fd = targetFdOf(stream);
int result = (fd >= 0) ? formatTo(fd, format, args) : __real_vfprintf(stream, format, args);
va_end(args);
return result;
}
int __wrap_puts(const char* s) {
writeAllToStdout(s, strlen(s));
writeAllToStdout("\n", 1);
writeAllTo(STDOUT_FILENO, s, strlen(s));
writeAllTo(STDOUT_FILENO, "\n", 1);
return 0;
}
int __wrap_fputs(const char* s, FILE* stream) {
if (stream == stdout) {
writeAllToStdout(s, strlen(s));
int fd = targetFdOf(stream);
if (fd >= 0) {
writeAllTo(fd, s, strlen(s));
return 0;
}
return __real_fputs(s, stream);
@ -257,13 +262,16 @@ int __wrap_fputs(const char* s, FILE* stream) {
int __wrap_putchar(int c) {
auto ch = static_cast<char>(c);
writeAllToStdout(&ch, 1);
writeAllTo(STDOUT_FILENO, &ch, 1);
return c;
}
int __wrap_fputc(int c, FILE* stream) {
if (stream == stdout) {
return __wrap_putchar(c);
int fd = targetFdOf(stream);
if (fd >= 0) {
auto ch = static_cast<char>(c);
writeAllTo(fd, &ch, 1);
return c;
}
return __real_fputc(c, stream);
}
@ -320,6 +328,64 @@ TT_DYLD_INTERPOSE(__wrap_fputc, fputc)
TT_DYLD_INTERPOSE(__wrap_getchar, getchar)
TT_DYLD_INTERPOSE(__wrap_fgetc, fgetc)
TT_DYLD_INTERPOSE(__wrap_fgets, fgets)
#else
extern "C" {
int vprintf(const char* format, va_list args) {
return __wrap_vprintf(format, args);
}
int printf(const char* format, ...) {
va_list args;
va_start(args, format);
int result = __wrap_vprintf(format, args);
va_end(args);
return result;
}
int vfprintf(FILE* stream, const char* format, va_list args) {
return __wrap_vfprintf(stream, format, args);
}
int fprintf(FILE* stream, const char* format, ...) {
va_list args;
va_start(args, format);
int result = __wrap_vfprintf(stream, format, args);
va_end(args);
return result;
}
int puts(const char* s) {
return __wrap_puts(s);
}
int fputs(const char* s, FILE* stream) {
return __wrap_fputs(s, stream);
}
int putchar(int c) {
return __wrap_putchar(c);
}
int fputc(int c, FILE* stream) {
return __wrap_fputc(c, stream);
}
int getchar() {
return __wrap_getchar();
}
int fgetc(FILE* stream) {
return __wrap_fgetc(stream);
}
char* fgets(char* buffer, int size, FILE* stream) {
return __wrap_fgets(buffer, size, stream);
}
}
#endif // __APPLE__
#endif // !ESP_PLATFORM

View File

@ -194,7 +194,7 @@ error_t app_stream_subscribe(AppStream* stream, void* buffer, size_t buffer_capa
return ERROR_NOT_FOUND;
}
stream->producer_task = iterator->second.task;
error_t bind_result = app_fd_table_bind(&iterator->second.fd_table, producer_fd, &STREAM_OPS, stream);
error_t bind_result = app_fd_table_bind(&iterator->second.fd_table, producer_fd, &STREAM_OPS, stream, /*suppress_console_tee=*/false);
mutex_unlock(&ledger.mutex);
if (bind_result != ERROR_NONE) {
@ -205,6 +205,25 @@ error_t app_stream_subscribe(AppStream* stream, void* buffer, size_t buffer_capa
return bind_result;
}
error_t app_stream_bind_alias_fd(AppStream* stream, int alias_fd) {
if (alias_fd < 0 || alias_fd >= APP_MAX_FDS) {
return ERROR_OUT_OF_RANGE;
}
// Same locking rationale as app_stream_subscribe(): held across the fd-table lookup and bind
// so this can't race app_fd_table_teardown().
auto& ledger = app_ledger();
mutex_lock(&ledger.mutex);
auto iterator = ledger.instances.find(stream->producer_id);
if (iterator == ledger.instances.end()) {
mutex_unlock(&ledger.mutex);
return ERROR_NOT_FOUND;
}
error_t result = app_fd_table_bind(&iterator->second.fd_table, alias_fd, &STREAM_OPS, stream, /*suppress_console_tee=*/false);
mutex_unlock(&ledger.mutex);
return result;
}
error_t app_stream_unsubscribe(AppStream* stream) {
// Held across the fd-table lookup, get, and close. See app_stream_subscribe()'s own
// comment on why this must stay exclusive with app_fd_table_teardown().
@ -213,9 +232,14 @@ error_t app_stream_unsubscribe(AppStream* stream) {
auto iterator = ledger.instances.find(stream->producer_id);
if (iterator != ledger.instances.end()) {
AppFdTable* table = &iterator->second.fd_table;
AppFile current {};
if (app_fd_table_get(table, stream->producer_fd, &current) && current.object == stream) {
app_fd_table_close(table, stream->producer_fd); // -> stream_file_close() -> app_stream_close()
// Closes producer_fd and any fd bound via app_stream_bind_alias_fd(): all share this same
// stream object, and app_fd_table_teardown() finding one afterwards would dispatch into
// a destructed mutex otherwise.
for (int fd = 0; fd < APP_MAX_FDS; fd++) {
AppFile current {};
if (app_fd_table_get(table, fd, &current) && current.object == stream) {
app_fd_table_close(table, fd); // -> stream_file_close() -> app_stream_close()
}
}
}
mutex_unlock(&ledger.mutex);

View File

@ -44,6 +44,18 @@ bool wait_for_state(AppInstanceId id, AppInstanceState target, uint32_t timeout_
return app_manager_get_state(id) == target;
}
bool wait_for_flag(std::atomic<bool>& flag, uint32_t timeout_ms) {
uint32_t waited = 0;
while (waited < timeout_ms) {
if (flag.load(std::memory_order_acquire)) {
return true;
}
delay_millis(10);
waited += 10;
}
return flag.load(std::memory_order_acquire);
}
std::atomic<ssize_t> g_stdio_write_result { -2 };
std::atomic<ssize_t> g_stdio_read_result { -2 };
@ -90,6 +102,19 @@ int32_t blocked_writer_app_main(int, char*[]) {
return 0;
}
std::atomic<error_t> g_await_before_write { ERROR_NONE };
std::atomic<error_t> g_await_after_write { ERROR_TIMEOUT };
std::atomic<bool> g_await_first_done { false };
std::atomic<bool> g_await_done { false };
int32_t await_reader_app_main(int, char*[]) {
g_await_before_write.store(app_io_await(STDIN_FILENO, APP_FILE_WAIT_READABLE, pdMS_TO_TICKS(50)), std::memory_order_release);
g_await_first_done.store(true, std::memory_order_release);
g_await_after_write.store(app_io_await(STDIN_FILENO, APP_FILE_WAIT_READABLE, pdMS_TO_TICKS(1000)), std::memory_order_release);
g_await_done.store(true, std::memory_order_release);
return 0;
}
std::atomic<ssize_t> g_real_file_write_result { -2 };
std::atomic<ssize_t> g_real_file_read_result { -2 };
std::atomic<bool> g_real_file_read_matches { false };
@ -117,6 +142,53 @@ int32_t real_file_io_app_main(int, char*[]) {
return 0;
}
struct SelfBoundObject {
char written[16] = {};
size_t written_len = 0;
};
ssize_t self_bound_write(void* object, const void* buffer, size_t size) {
auto* obj = static_cast<SelfBoundObject*>(object);
size_t n = size < sizeof(obj->written) ? size : sizeof(obj->written);
memcpy(obj->written, buffer, n);
obj->written_len = n;
return static_cast<ssize_t>(n);
}
ssize_t self_bound_read(void*, void* buffer, size_t size) {
const char reply[] = "yo";
size_t n = size < sizeof(reply) - 1 ? size : sizeof(reply) - 1;
memcpy(buffer, reply, n);
return static_cast<ssize_t>(n);
}
error_t self_bound_close(void*) { return ERROR_NONE; }
error_t self_bound_await(void*, AppFileWait, TickType_t) { return ERROR_NONE; }
uint32_t self_bound_poll(void*) { return APP_FILE_READABLE | APP_FILE_WRITABLE; }
const AppFileOps SELF_BOUND_OPS = {
.read = self_bound_read,
.write = self_bound_write,
.close = self_bound_close,
.await = self_bound_await,
.poll = self_bound_poll,
.retain = nullptr,
.release = nullptr,
};
SelfBoundObject g_self_bound_object;
std::atomic<error_t> g_self_bind_result { ERROR_UNDEFINED };
std::atomic<ssize_t> g_self_bound_write_result { -2 };
std::atomic<ssize_t> g_self_bound_read_result { -2 };
char g_self_bound_read_buffer[16] = {};
int32_t self_bind_app_main(int, char*[]) {
g_self_bind_result.store(app_io_bind_self(STDOUT_FILENO, &SELF_BOUND_OPS, &g_self_bound_object), std::memory_order_release);
g_self_bound_write_result.store(app_io_write(STDOUT_FILENO, "hi", 2), std::memory_order_release);
g_self_bound_read_result.store(app_io_read(STDOUT_FILENO, g_self_bound_read_buffer, sizeof(g_self_bound_read_buffer) - 1), std::memory_order_release);
return 0;
}
std::atomic<int> g_double_close_first_result { -2 };
std::atomic<int> g_double_close_second_result { -2 };
std::atomic<ssize_t> g_write_after_close_result { -2 };
@ -186,39 +258,40 @@ TEST_CASE("app_start_with_streams pipes a child's app_io_write() calls into a pa
app_manager_remove("test.io.writer");
}
TEST_CASE("app_start_with_streams pipes a child's plain printf() calls into a parent-owned AppStream") {
TEST_CASE("app_io_await blocks until the bound stream becomes readable or times out") {
ensure_memory_loader_registered();
g_await_before_write.store(ERROR_NONE, std::memory_order_relaxed);
g_await_after_write.store(ERROR_TIMEOUT, std::memory_order_relaxed);
g_await_first_done.store(false, std::memory_order_relaxed);
g_await_done.store(false, std::memory_order_relaxed);
AppManifest manifest { "test.io.printf_writer", "PrintfWriter", APP_CATEGORY_USER, { APP_LOCATION_MEMORY, reinterpret_cast<void*>(stdout_printf_app_main) } };
AppManifest manifest { "test.io.await", "Await", APP_CATEGORY_USER, { APP_LOCATION_MEMORY, reinterpret_cast<void*>(await_reader_app_main) } };
REQUIRE_EQ(app_manager_add(&manifest), ERROR_NONE);
TaskEventGroup event_group {};
task_event_group_construct(&event_group);
uint8_t storage[64];
AppStream child_stdout {};
AppStreamBinding binding { STDOUT_FILENO, &child_stdout, storage, sizeof(storage), &event_group };
uint8_t storage[16];
AppStream child_stdin {};
AppStreamBinding binding { STDIN_FILENO, &child_stdin, storage, sizeof(storage), &event_group };
AppInstanceId child_id = 0;
REQUIRE_EQ(app_start_with_streams("test.io.printf_writer", &binding, 1, &child_id), ERROR_NONE);
REQUIRE_EQ(app_start_with_streams("test.io.await", &binding, 1, &child_id), ERROR_NONE);
std::vector<uint8_t> received;
while (app_stream_await(&child_stdout, APP_FILE_WAIT_READABLE, pdMS_TO_TICKS(1000)) == ERROR_NONE) {
uint8_t chunk[16];
size_t n = app_stream_read(&child_stdout, chunk, sizeof(chunk));
if (n == 0) {
break; // EOF
}
received.insert(received.end(), chunk, chunk + n);
}
// Wait for the child's first await (50ms, on an empty stream) to actually return before
// writing: a fixed delay doesn't prove that, and under slow scheduling the write could land
// first, making the first await succeed and the second one time out instead.
REQUIRE(wait_for_flag(g_await_first_done, 1000));
CHECK_FALSE(g_await_done.load(std::memory_order_acquire));
REQUIRE_EQ(received.size(), 5u);
CHECK_EQ(std::memcmp(received.data(), "hello", 5), 0);
app_stream_write(&child_stdin, "x", 1);
REQUIRE(wait_for_state(child_id, APP_INSTANCE_STATE_STOPPED, 1000));
app_stream_unsubscribe(&child_stdout);
CHECK_EQ(g_await_before_write.load(std::memory_order_acquire), ERROR_TIMEOUT);
CHECK_EQ(g_await_after_write.load(std::memory_order_acquire), ERROR_NONE);
app_stream_unsubscribe(&child_stdin);
task_event_group_destruct(&event_group);
app_manager_remove("test.io.printf_writer");
app_manager_remove("test.io.await");
}
TEST_CASE("a write blocked on a full stream wakes with an error once the consumer closes it") {
@ -315,6 +388,36 @@ TEST_CASE("app_io_read/write/close pass through a real file fd app-module never
app_manager_remove("test.io.real_file");
}
TEST_CASE("app_io_bind_self installs a custom AppFileOps used by subsequent app_io_read/write") {
ensure_memory_loader_registered();
g_self_bind_result.store(ERROR_UNDEFINED, std::memory_order_relaxed);
g_self_bound_write_result.store(-2, std::memory_order_relaxed);
g_self_bound_read_result.store(-2, std::memory_order_relaxed);
g_self_bound_object = SelfBoundObject {};
memset(g_self_bound_read_buffer, 0, sizeof(g_self_bound_read_buffer));
AppManifest manifest { "test.io.self_bind", "SelfBind", APP_CATEGORY_USER, { APP_LOCATION_MEMORY, reinterpret_cast<void*>(self_bind_app_main) } };
REQUIRE_EQ(app_manager_add(&manifest), ERROR_NONE);
AppInstanceId instance_id = 0;
REQUIRE_EQ(app_start("test.io.self_bind", 0, nullptr, &instance_id), ERROR_NONE);
REQUIRE(wait_for_state(instance_id, APP_INSTANCE_STATE_STOPPED, 1000));
CHECK_EQ(g_self_bind_result.load(std::memory_order_acquire), ERROR_NONE);
CHECK_EQ(g_self_bound_write_result.load(std::memory_order_acquire), 2);
CHECK_EQ(g_self_bound_object.written_len, 2u);
CHECK_EQ(std::memcmp(g_self_bound_object.written, "hi", 2), 0);
CHECK_EQ(g_self_bound_read_result.load(std::memory_order_acquire), 2);
CHECK_EQ(std::memcmp(g_self_bound_read_buffer, "yo", 2), 0);
app_manager_remove("test.io.self_bind");
}
TEST_CASE("app_io_bind_self returns ERROR_NOT_FOUND when called outside a running app instance") {
SelfBoundObject object;
CHECK_EQ(app_io_bind_self(STDOUT_FILENO, &SELF_BOUND_OPS, &object), ERROR_NOT_FOUND);
}
TEST_CASE("closing an already-closed app fd reports EBADF instead of falling through to the platform") {
ensure_memory_loader_registered();
g_double_close_first_result.store(-2, std::memory_order_relaxed);

View File

@ -11,6 +11,13 @@ add_library(app_posix_module_test_fixture SHARED EXCLUDE_FROM_ALL ${CMAKE_CURREN
target_include_directories(app_posix_module_test_fixture PRIVATE ${CMAKE_SOURCE_DIR}/Modules/app-module/include)
set_target_properties(app_posix_module_test_fixture PROPERTIES POSITION_INDEPENDENT_CODE ON)
# Fixture: calls printf() with no app-module linkage of its own, so its call must resolve against
# the host process's own printf - proves a dlopen()ed app's stdio actually reaches app_io_write()
# rather than bypassing straight to libc (see stdio_wrap.cpp's own comment for why that's not a
# given on POSIX).
add_library(printf_fixture SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_LIST_DIR}/fixtures/printf_fixture.cpp)
set_target_properties(printf_fixture PROPERTIES POSITION_INDEPENDENT_CODE ON)
# A file with a ".so" extension but no ELF header, for is_executable() rejection tests.
set(NON_ELF_FIXTURE_PATH "${CMAKE_CURRENT_BINARY_DIR}/not-elf.so")
file(WRITE "${NON_ELF_FIXTURE_PATH}" "not an elf file")
@ -29,11 +36,12 @@ add_custom_target(install_dir_fixture DEPENDS "${INSTALL_DIR_FIXTURE_BIN_DIR}/ap
file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp)
add_executable(AppPosixModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
add_dependencies(AppPosixModuleTests app_posix_module_test_fixture install_dir_fixture)
add_dependencies(AppPosixModuleTests app_posix_module_test_fixture printf_fixture install_dir_fixture)
target_include_directories(AppPosixModuleTests PRIVATE ${DOCTESTINC})
target_compile_definitions(AppPosixModuleTests PRIVATE
FIXTURE_APP_PATH="$<TARGET_FILE:app_posix_module_test_fixture>"
PRINTF_FIXTURE_APP_PATH="$<TARGET_FILE:printf_fixture>"
FIXTURE_NON_ELF_PATH="${NON_ELF_FIXTURE_PATH}"
FIXTURE_INSTALL_DIR_PATH="${INSTALL_DIR_FIXTURE_PATH}"
)

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: Apache-2.0
#include <cstdint>
#include <cstdio>
// Deliberately not linked against app-module: printf()'s dynamic symbol resolution must reach
// Tactility's own override in the loading process, exactly like a real loaded app's would.
extern "C" int32_t main(int, char*[]) {
printf("hello from dlopen'd app\n");
// %s, not a literal: a literal fprintf compiles to fwrite(), which bypasses the wrap.
fprintf(stderr, "%s\n", "oops from dlopen'd app");
return 0;
}

View File

@ -7,13 +7,16 @@
#include <app/manager.h>
#include <app/start.h>
#include <app/scheduler.h>
#include <app/stream.h>
#include <service/manager.h>
#include <tactility/delay.h>
#include <atomic>
#include <cstring>
#include <string>
#include <unistd.h>
extern ServiceManifest loader_service_manifest; // app-posix-module's own
extern ServiceManifest app_internal_loader_service_manifest; // app-module's real memory loader
@ -103,8 +106,91 @@ int32_t parent_app_main(int, char*[]) {
return 0;
}
std::string g_printf_fixture_output;
std::string g_printf_fixture_stderr;
// Starts the printf fixture with its stdout/stderr each piped through an AppStream, proving
// printf()/fprintf(stderr, ...) reach app_io_write() rather than bypassing straight to libc.
int32_t printf_parent_app_main(int, char*[]) {
static uint8_t stdoutBuffer[256];
static uint8_t stderrBuffer[256];
AppStream stdoutStream {};
AppStream stderrStream {};
TaskEventGroup event_group {};
task_event_group_construct(&event_group);
AppEventSubscription sub {};
app_event_subscribe(&sub, &event_group);
AppInstanceId self_id = app_scheduler_current_app_id();
AppStreamBinding bindings[] = {
{ STDOUT_FILENO, &stdoutStream, stdoutBuffer, sizeof(stdoutBuffer), &event_group },
{ STDERR_FILENO, &stderrStream, stderrBuffer, sizeof(stderrBuffer), &event_group },
};
AppLocation location { APP_LOCATION_PATH, const_cast<char*>(PRINTF_FIXTURE_APP_PATH) };
AppInstanceId childId = 0;
app_execute_for_result_with_streams(location, AppStackConfig {}, 0, nullptr, bindings, 2, self_id, &childId);
uint8_t drain[256];
bool childDone = false;
while (!childDone) {
if (task_event_group_wait_any(&event_group, nullptr, pdMS_TO_TICKS(5000)) != ERROR_NONE) {
break; // safety net so a bug here can't hang the test suite
}
size_t n;
while ((n = app_stream_read(&stdoutStream, drain, sizeof(drain))) > 0) {
g_printf_fixture_output.append(reinterpret_cast<const char*>(drain), n);
}
while ((n = app_stream_read(&stderrStream, drain, sizeof(drain))) > 0) {
g_printf_fixture_stderr.append(reinterpret_cast<const char*>(drain), n);
}
AppEvent event {};
while (app_event_poll(&sub, &event) == ERROR_NONE) {
if (event.type == APP_EVENT_RESULT && event.result.launch_id == childId) {
childDone = true;
}
}
}
size_t n;
while ((n = app_stream_read(&stdoutStream, drain, sizeof(drain))) > 0) {
g_printf_fixture_output.append(reinterpret_cast<const char*>(drain), n);
}
while ((n = app_stream_read(&stderrStream, drain, sizeof(drain))) > 0) {
g_printf_fixture_stderr.append(reinterpret_cast<const char*>(drain), n);
}
app_stream_unsubscribe(&stdoutStream);
app_stream_unsubscribe(&stderrStream);
app_event_unsubscribe(&sub);
task_event_group_destruct(&event_group);
return 0;
}
} // namespace
TEST_CASE("app-posix-module's loader-path service dlopen()s a .so whose printf()/fprintf(stderr, ...) output reaches the parent's streams") {
ensure_path_loader_registered();
ensure_memory_loader_registered();
g_printf_fixture_output.clear();
g_printf_fixture_stderr.clear();
AppManifest parent_manifest { "test.posix.printf_parent", "PrintfParent", APP_CATEGORY_USER, { APP_LOCATION_MEMORY, reinterpret_cast<void*>(printf_parent_app_main) } };
REQUIRE_EQ(app_manager_add(&parent_manifest), ERROR_NONE);
AppInstanceId parent_id = 0;
REQUIRE_EQ(app_start("test.posix.printf_parent", 0, nullptr, &parent_id), ERROR_NONE);
REQUIRE(wait_for_state(parent_id, APP_INSTANCE_STATE_STOPPED, 3000));
CHECK_EQ(g_printf_fixture_output, "hello from dlopen'd app\n");
// Not exact: the child's own scheduler bookkeeping may also log to stderr while running.
CHECK(g_printf_fixture_stderr.find("oops from dlopen'd app\n") != std::string::npos);
app_manager_remove("test.posix.printf_parent");
}
TEST_CASE("app-posix-module's loader-path service dlopen()s a .so and calls its main(), which resolves a real Tactility symbol against the host") {
ensure_path_loader_registered();
ensure_memory_loader_registered();

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.20)
include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake")
file(GLOB_RECURSE SOURCE_FILES "source/*.c*")
# include/tactility/esp_audio_simple_dec.h and esp_audio_types.h are vendored verbatim from
# espressif__esp_audio_codec so apps can include this module's header alone; symbols resolve
# from the firmware's module table at load, like any other kernel/platform export.
# ESP-only: there is no POSIX audio-decoder backend.
set(REQUIRES_LIST TactilityKernel)
if (DEFINED ENV{ESP_IDF_VERSION})
list(APPEND REQUIRES_LIST espressif__esp_audio_codec)
endif ()
tactility_add_module(audio-decoder-module
SRCS ${SOURCE_FILES}
INCLUDE_DIRS include/
REQUIRES ${REQUIRES_LIST}
)

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <tactility/module.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct Module audio_decoder_module;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,232 @@
/*
* Espressif Modified MIT License
*
* Copyright (c) 2025 Espressif Systems (Shanghai) CO., LTD
*
* Permission is hereby granted for use EXCLUSIVELY with Espressif Systems products.
* This includes the right to use, copy, modify, merge, publish, distribute, and sublicense
* the Software, subject to the following conditions:
*
* 1. This Software MUST BE USED IN CONJUNCTION WITH ESPRESSIF SYSTEMS PRODUCTS.
* 2. The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
* 3. Redistribution of the Software in source or binary form FOR USE WITH NON-ESPRESSIF PRODUCTS
* is strictly prohibited.
*
* 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.
*
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_audio_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Audio simple decoder handle
*
* @note Most audio decoder can only process frame data.
* To support playback simply, simple decoder is imported.
* In simple playback scenario, like play MP3, AAC, WAV etc.
* User need only provide the original audio data, simple decoder will filter out frame data,
* send frame data to decoder, then return decoded data to user directly.
*/
typedef void *esp_audio_simple_dec_handle_t;
/**
* @brief Recovery strategy for tht current frame
*/
typedef enum {
ESP_AUDIO_SIMPLE_DEC_RECOVERY_NONE = 0, /*!< The current frame is a normal decoded frame */
ESP_AUDIO_SIMPLE_DEC_RECOVERY_PLC = 1, /*!< The current frame is recovered through the packet loss concealment (PLC) mechanism */
} esp_audio_simple_dec_recovery_t;
/**
* @brief Audio simple decoder type
*/
typedef enum {
ESP_AUDIO_SIMPLE_DEC_TYPE_NONE = 0, /*!< Invalid simple decoder type */
ESP_AUDIO_SIMPLE_DEC_TYPE_AAC = ESP_AUDIO_TYPE_AAC, /*!< Simple decoder for AAC, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_MP3 = ESP_AUDIO_TYPE_MP3, /*!< Simple decoder for MP3, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_AMRNB = ESP_AUDIO_TYPE_AMRNB, /*!< Simple decoder for AMR-NB, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_AMRWB = ESP_AUDIO_TYPE_AMRWB, /*!< Simple decoder for AMR-WB, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_FLAC = ESP_AUDIO_TYPE_FLAC, /*!< Simple decoder for FLAC, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_WAV = ESP_AUDIO_FOURCC_TO_INT('W', 'A', 'V', ' '), /*!< Simple decoder for WAV, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_M4A = ESP_AUDIO_FOURCC_TO_INT('M', '4', 'A', 'A'), /*!< Simple decoder for M4A, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_TS = ESP_AUDIO_FOURCC_TO_INT('M', '2', 'T', 'S'), /*!< Simple decoder for TS, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_RAW_OPUS = ESP_AUDIO_TYPE_OPUS, /*!< Simple decoder for OPUS (raw data with no extra header),
only supports input data with a size of one encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_G711A = ESP_AUDIO_TYPE_G711A, /*!< Simple decoder for G711A, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_G711U = ESP_AUDIO_TYPE_G711U, /*!< Simple decoder for G711U, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_PCM = ESP_AUDIO_TYPE_PCM, /*!< Simple decoder for PCM, support input data of any size */
ESP_AUDIO_SIMPLE_DEC_TYPE_ADPCM = ESP_AUDIO_TYPE_ADPCM, /*!< Simple decoder for IMA-ADPCM,
only supports input data with a size of one encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_SBC = ESP_AUDIO_TYPE_SBC, /*!< Simple decoder for SBC,
only supports input data with a size of one or multi encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_LC3 = ESP_AUDIO_TYPE_LC3, /*!< Simple decoder for LC3,
in vbr and no len_prefixed case, only supports input data with a size of one encoded frame,
other cases, support input data with a size of one or multi encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_ALAC = ESP_AUDIO_TYPE_ALAC, /*!< Simple decoder for ALAC,
only supports input data with a size of one encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_VORBIS = ESP_AUDIO_TYPE_VORBIS, /*!< Simple decoder for Vorbis (raw data with no extra header),
only supports input data with a size of one encoded frame */
ESP_AUDIO_SIMPLE_DEC_TYPE_CUSTOM = 0x1, /*!< Customized simple decoder type start */
ESP_AUDIO_SIMPLE_DEC_TYPE_CUSTOM_MAX = 0x10, /*!< Customized simple decoder type end */
} esp_audio_simple_dec_type_t;
/**
* @brief Audio simple decoder configuration
*/
typedef struct {
esp_audio_simple_dec_type_t dec_type; /*!< Simple decoder type */
void *dec_cfg; /*!< Decoder specified configuration data (check decoder header file for details)
Ex: When use internal aac decoder can refer `esp_aac_dec.h`
If user want to enable AAC_PLUS can set it to pointer to
`esp_aac_dec_cfg_t` */
int cfg_size; /*!< Decoder specified configuration size */
bool use_frame_dec; /*!< The flag of whether use frame decoder without parse
If set to true, means that the input data is a complete frame and can be decoded directly
If set to false, for decoders with parser, will parse to obtain the complete frame and then decode it */
} esp_audio_simple_dec_cfg_t;
/**
* @brief Input data information to be decoded
*/
typedef struct {
uint8_t *buffer; /*!< Raw data to be decoded */
uint32_t len; /*!< Raw data length */
bool eos; /*!< Whether end of stream (some parser like FLAC need eos flag to flush cached data) */
uint32_t consumed; /*!< Consumed size of input raw data */
esp_audio_simple_dec_recovery_t frame_recover; /*!< Recovery strategy for current frame */
} esp_audio_simple_dec_raw_t;
/**
* @brief Audio simple decoder output frame
*/
typedef struct {
uint8_t *buffer; /*!< Output buffer to hold decoded PCM data */
uint32_t len; /*!< Output buffer size */
uint32_t needed_size; /*!< Set when output buffer size not enough (output) */
uint32_t decoded_size; /*!< Decoded PCM data size (output) */
} esp_audio_simple_dec_out_t;
/**
* @brief Audio simple decoder information
*/
typedef struct {
uint32_t sample_rate; /*!< Audio sample rate */
uint8_t bits_per_sample; /*!< Bits per sample */
uint8_t channel; /*!< Audio channel*/
uint32_t bitrate; /*!< Audio bitrate (bits per second) */
uint32_t frame_size; /*!< Audio frame size */
} esp_audio_simple_dec_info_t;
/**
* @brief Query whether the simple decoder type is supported
*
* @param[in] dec_type Simple decoder type
*
* @return
* - ESP_AUDIO_ERR_OK On success
* - ESP_AUDIO_ERR_NOT_SUPPORT Not support the audio type
*/
esp_audio_err_t esp_audio_simple_check_audio_type(esp_audio_simple_dec_type_t dec_type);
/**
* @brief Open audio simple decoder
*
* @param[in] cfg Decoder configuration
* @param[out] dec_handle Pointer to output simple decoder handle
*
* @return
* - ESP_AUDIO_ERR_OK Open decoder success
* - ESP_AUDIO_ERR_INVALID_PARAMETER Invalid input argument
* - ESP_AUDIO_ERR_MEM_LACK No memory for decoder instance
* - ESP_AUDIO_ERR_NOT_SUPPORT Not supported parse type
*/
esp_audio_err_t esp_audio_simple_dec_open(esp_audio_simple_dec_cfg_t *cfg, esp_audio_simple_dec_handle_t *dec_handle);
/**
* @brief Decode input raw data to PCM data
*
* @param[in] dec_handle Simple decoder handle
* @param[in,out] raw Raw data to be decoded
* @param[in,out] frame Decoded PCM frame
*
* @return
* - ESP_AUDIO_ERR_OK Decode success or data feed into cached buffer
* - ESP_AUDIO_ERR_INVALID_PARAMETER Invalid input argument
* - ESP_AUDIO_ERR_BUFF_NOT_ENOUGH Output frame buffer not enough need reallocated and try again
* - ESP_AUDIO_ERR_NOT_SUPPORT Decoder not supported
*/
esp_audio_err_t esp_audio_simple_dec_process(esp_audio_simple_dec_handle_t dec_handle, esp_audio_simple_dec_raw_t *raw,
esp_audio_simple_dec_out_t *frame);
/**
* @brief Get audio simple decoder information
*
* @note Audio decoder information contain 2 parts:
* 1. Basic information which can be used for play (`sample_rate`, `channel`, `bits`)
* This information is ready when decoder decode output PCM data
* When `esp_audio_simple_dec_process` return `decoded_size` have value
* User no need frequently call this API to get it for it almost unchanged
* 2. Frame related information such as (`frame_size`) which may differ for each frame
* User can use it to estimate duration and play position.
*
* @param[in] dec_handle Simple decoder handle
* @param[out] info Decoder information
*
* @return
* - ESP_AUDIO_ERR_OK Open decoder success
* - ESP_AUDIO_ERR_INVALID_PARAMETER Invalid input argument
* - ESP_AUDIO_ERR_NOT_FOUND Decode information not ready yet
*/
esp_audio_err_t esp_audio_simple_dec_get_info(esp_audio_simple_dec_handle_t dec_handle, esp_audio_simple_dec_info_t *info);
/**
* @brief Reset audio simple decoder
* Reset action will reset both of the internal parser and decoder to initial state
* It allows the handle to be reused efficiently, avoiding the overhead of closing and recreating the handle
* Typical use cases include:
* - Replay the same audio stream
* - Seek when use frame decoder
*
* @note 1. This function is not thread-safe. The user must ensure proper call sequencing
* and avoid invoking this function while the process is running
* 2. Work as a frame decoder: After calling the `esp_audio_simple_dec_reset`, playback can
* start from any frame of the audio stream. The audio file can be the same or different but keeping
* 3. Work as a non-frame decoder: After calling the `esp_audio_simple_dec_reset`,
* playback must starts from the beginning of the audio stream.
* The audio file can be the same or different from the previous one but keeping format unchanged
*
* @param[in] dec_handle Simple decoder handle
*
* @return
* - ESP_AUDIO_ERR_OK On success
* - ESP_AUDIO_ERR_FAIL Fail to reset
* - ESP_AUDIO_ERR_INVALID_PARAMETER Invalid parameter
*/
esp_audio_err_t esp_audio_simple_dec_reset(esp_audio_simple_dec_handle_t dec_handle);
/**
* @brief Close audio simple decoder
*
* @param[in] dec_handle Decoder handle
*
*/
void esp_audio_simple_dec_close(esp_audio_simple_dec_handle_t dec_handle);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,113 @@
/*
* Espressif Modified MIT License
*
* Copyright (c) 2025 Espressif Systems (Shanghai) CO., LTD
*
* Permission is hereby granted for use EXCLUSIVELY with Espressif Systems products.
* This includes the right to use, copy, modify, merge, publish, distribute, and sublicense
* the Software, subject to the following conditions:
*
* 1. This Software MUST BE USED IN CONJUNCTION WITH ESPRESSIF SYSTEMS PRODUCTS.
* 2. The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
* 3. Redistribution of the Software in source or binary form FOR USE WITH NON-ESPRESSIF PRODUCTS
* is strictly prohibited.
*
* 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.
*
* SPDX-License-Identifier: LicenseRef-Espressif-Modified-MIT
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_AUDIO_SAMPLE_RATE_8K (8000)
#define ESP_AUDIO_SAMPLE_RATE_11K (11025)
#define ESP_AUDIO_SAMPLE_RATE_12K (12000)
#define ESP_AUDIO_SAMPLE_RATE_16K (16000)
#define ESP_AUDIO_SAMPLE_RATE_22K (22050)
#define ESP_AUDIO_SAMPLE_RATE_24K (24000)
#define ESP_AUDIO_SAMPLE_RATE_32K (32000)
#define ESP_AUDIO_SAMPLE_RATE_44K (44100)
#define ESP_AUDIO_SAMPLE_RATE_48K (48000)
#define ESP_AUDIO_SAMPLE_RATE_64K (64000)
#define ESP_AUDIO_SAMPLE_RATE_88K (88200)
#define ESP_AUDIO_SAMPLE_RATE_96K (96000)
#define ESP_AUDIO_BIT8 (8)
#define ESP_AUDIO_BIT16 (16)
#define ESP_AUDIO_BIT24 (24)
#define ESP_AUDIO_BIT32 (32)
#define ESP_AUDIO_MONO (1)
#define ESP_AUDIO_DUAL (2)
#define ESP_AUDIO_FOURCC_TO_INT(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b << 8)) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
/**
* @brief Audio codec type
*
* @note 1. The type enum value is reference to `esp_fourcc.h`(http://github.com/espressif/esp-gmf/blob/main/gmf_core/helpers/include/esp_fourcc.h)
* 2. The range of customized type is [0x20, 0x40]
*/
typedef enum {
ESP_AUDIO_TYPE_UNSUPPORT = 0,
ESP_AUDIO_TYPE_AMRNB = ESP_AUDIO_FOURCC_TO_INT('A', 'M', 'R', 'N'),
ESP_AUDIO_TYPE_AMRWB = ESP_AUDIO_FOURCC_TO_INT('A', 'M', 'R', 'W'),
ESP_AUDIO_TYPE_AAC = ESP_AUDIO_FOURCC_TO_INT('A', 'A', 'C', ' '),
ESP_AUDIO_TYPE_G711A = ESP_AUDIO_FOURCC_TO_INT('A', 'L', 'A', 'W'),
ESP_AUDIO_TYPE_G711U = ESP_AUDIO_FOURCC_TO_INT('U', 'L', 'A', 'W'),
ESP_AUDIO_TYPE_OPUS = ESP_AUDIO_FOURCC_TO_INT('O', 'P', 'U', 'S'),
ESP_AUDIO_TYPE_ADPCM = ESP_AUDIO_FOURCC_TO_INT('A', 'D', 'P', 'C'),
ESP_AUDIO_TYPE_PCM = ESP_AUDIO_FOURCC_TO_INT('P', 'C', 'M', ' '),
ESP_AUDIO_TYPE_FLAC = ESP_AUDIO_FOURCC_TO_INT('F', 'L', 'A', 'C'),
ESP_AUDIO_TYPE_VORBIS = ESP_AUDIO_FOURCC_TO_INT('V', 'O', 'B', 'S'),
ESP_AUDIO_TYPE_MP3 = ESP_AUDIO_FOURCC_TO_INT('M', 'P', '3', ' '),
ESP_AUDIO_TYPE_ALAC = ESP_AUDIO_FOURCC_TO_INT('A', 'L', 'A', 'C'),
ESP_AUDIO_TYPE_SBC = ESP_AUDIO_FOURCC_TO_INT('S', 'B', 'C', ' '),
ESP_AUDIO_TYPE_LC3 = ESP_AUDIO_FOURCC_TO_INT('L', 'C', '3', '0'),
ESP_AUDIO_TYPE_CUSTOMIZED = 0x20,
ESP_AUDIO_TYPE_CUSTOMIZED_MAX = 0x40,
} esp_audio_type_t;
/**
* @brief Audio codec error type definition
*/
typedef enum {
ESP_AUDIO_ERR_CONTINUE = 1, /*!< Continue */
ESP_AUDIO_ERR_OK = 0, /*!< Success */
ESP_AUDIO_ERR_FAIL = -1, /*!< Fail */
ESP_AUDIO_ERR_MEM_LACK = -2, /*!< Fail to malloc memory */
ESP_AUDIO_ERR_DATA_LACK = -3, /*!< Data is not enough */
ESP_AUDIO_ERR_HEADER_PARSE = -4, /*!< Parse header happened error */
ESP_AUDIO_ERR_INVALID_PARAMETER = -5, /*!< Input invalid parameter */
ESP_AUDIO_ERR_ALREADY_EXIST = -6, /*!< Audio library is already exist */
ESP_AUDIO_ERR_NOT_SUPPORT = -7, /*!< Not support type */
ESP_AUDIO_ERR_BUFF_NOT_ENOUGH = -8, /*!< Buffer not enough */
ESP_AUDIO_ERR_NOT_FOUND = -9, /*!< Not found */
} esp_audio_err_t;
/**
* @brief Get audio codec type stringify name
*
* @param[in] type Audio codec type
*
* @return
* - "NONE" Invalid codec type
* - Others Codec stringify name
*/
const char *esp_audio_codec_get_name(esp_audio_type_t type);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
#include <audio_decoder/module.h>
#ifdef ESP_PLATFORM
#include <simple_dec/esp_audio_simple_dec.h>
#include <esp_audio_dec_default.h>
#include <esp_log.h>
// Registers Kconfig-selected decoders once so any app can use esp_audio_simple_dec_open()
// without registering itself.
static error_t audio_decoder_module_start(void) {
esp_audio_err_t dec_register_result = esp_audio_dec_register_default();
if (dec_register_result != ESP_AUDIO_ERR_OK) {
// Not a boot failure: apps can still use everything else. But without this, a later
// esp_audio_simple_dec_open() failure has no explanation in the log.
ESP_LOGE("audio-decoder", "esp_audio_dec_register_default failed: %d", (int) dec_register_result);
}
return ERROR_NONE;
}
extern "C" {
static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(esp_audio_simple_check_audio_type),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_open),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_process),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_get_info),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_reset),
DEFINE_MODULE_SYMBOL(esp_audio_simple_dec_close),
MODULE_SYMBOL_TERMINATOR
};
Module audio_decoder_module = {
.name = "audio-decoder",
.start = audio_decoder_module_start,
.stop = nullptr,
.drivers = nullptr,
.symbols = SYMBOLS,
.internal = nullptr,
};
}
#else // !ESP_PLATFORM
extern "C" {
Module audio_decoder_module = {
.name = "audio-decoder",
.start = nullptr,
.stop = nullptr,
.drivers = nullptr,
.symbols = nullptr,
.internal = nullptr,
};
}
#endif // ESP_PLATFORM

View File

@ -100,6 +100,7 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL_SIGNATURE(round, double (*)(double)),
// cassert / cstdio
DEFINE_MODULE_SYMBOL(abort),
DEFINE_MODULE_SYMBOL(clearerr),
DEFINE_MODULE_SYMBOL(fclose),
DEFINE_MODULE_SYMBOL(feof),
DEFINE_MODULE_SYMBOL(ferror),

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.20)
include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake")
file(GLOB_RECURSE SOURCE_FILES "source/*.c*")
# include/cJSON.h is vendored verbatim from espressif__cjson so apps can `#include <cJSON.h>`
# against this module alone (no idf_component.yml entry of their own needed) - the app ELF keeps
# cJSON_* calls undefined and the firmware resolves them from this module's symbol table at load,
# same mechanism as any other kernel/platform export.
#
# cJSON symbol exports (source/module.cpp) are used on every platform, but the managed-component
# target name only resolves in an ESP-IDF build; POSIX links the repo's own cJSON library instead.
set(REQUIRES_LIST TactilityKernel)
if (ESP_PLATFORM)
list(APPEND REQUIRES_LIST espressif__cjson)
else ()
list(APPEND REQUIRES_LIST cJSON)
endif ()
tactility_add_module(cjson-module
SRCS ${SOURCE_FILES}
INCLUDE_DIRS include/
REQUIRES ${REQUIRES_LIST}
)

View File

@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.

View File

@ -0,0 +1,306 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
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.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 19
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <tactility/module.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct Module cjson_module;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,104 @@
// SPDX-License-Identifier: Apache-2.0
#include <cjson_symbols/module.h>
#include <cJSON.h>
extern "C" {
static const ModuleSymbol SYMBOLS[] = {
// cJSON.h - every real exported function (not the header's inline SetIntValue/
// SetNumberValue/SetBoolValue/ArrayForEach macros, which expand at the app's own compile
// time and need no export).
DEFINE_MODULE_SYMBOL(cJSON_Version),
// cJSON_InitHooks intentionally not exported: it overrides cJSON's process-global
// malloc/free hooks, which every app and the firmware itself share - one app could break
// allocation for everyone.
DEFINE_MODULE_SYMBOL(cJSON_Parse),
DEFINE_MODULE_SYMBOL(cJSON_ParseWithLength),
DEFINE_MODULE_SYMBOL(cJSON_ParseWithOpts),
DEFINE_MODULE_SYMBOL(cJSON_ParseWithLengthOpts),
DEFINE_MODULE_SYMBOL(cJSON_Print),
DEFINE_MODULE_SYMBOL(cJSON_PrintUnformatted),
DEFINE_MODULE_SYMBOL(cJSON_PrintBuffered),
DEFINE_MODULE_SYMBOL(cJSON_PrintPreallocated),
DEFINE_MODULE_SYMBOL(cJSON_Delete),
DEFINE_MODULE_SYMBOL(cJSON_GetArraySize),
DEFINE_MODULE_SYMBOL(cJSON_GetArrayItem),
DEFINE_MODULE_SYMBOL(cJSON_GetObjectItem),
DEFINE_MODULE_SYMBOL(cJSON_GetObjectItemCaseSensitive),
DEFINE_MODULE_SYMBOL(cJSON_HasObjectItem),
DEFINE_MODULE_SYMBOL(cJSON_GetErrorPtr),
DEFINE_MODULE_SYMBOL(cJSON_GetStringValue),
DEFINE_MODULE_SYMBOL(cJSON_GetNumberValue),
DEFINE_MODULE_SYMBOL(cJSON_IsInvalid),
DEFINE_MODULE_SYMBOL(cJSON_IsFalse),
DEFINE_MODULE_SYMBOL(cJSON_IsTrue),
DEFINE_MODULE_SYMBOL(cJSON_IsBool),
DEFINE_MODULE_SYMBOL(cJSON_IsNull),
DEFINE_MODULE_SYMBOL(cJSON_IsNumber),
DEFINE_MODULE_SYMBOL(cJSON_IsString),
DEFINE_MODULE_SYMBOL(cJSON_IsArray),
DEFINE_MODULE_SYMBOL(cJSON_IsObject),
DEFINE_MODULE_SYMBOL(cJSON_IsRaw),
DEFINE_MODULE_SYMBOL(cJSON_CreateNull),
DEFINE_MODULE_SYMBOL(cJSON_CreateTrue),
DEFINE_MODULE_SYMBOL(cJSON_CreateFalse),
DEFINE_MODULE_SYMBOL(cJSON_CreateBool),
DEFINE_MODULE_SYMBOL(cJSON_CreateNumber),
DEFINE_MODULE_SYMBOL(cJSON_CreateString),
DEFINE_MODULE_SYMBOL(cJSON_CreateRaw),
DEFINE_MODULE_SYMBOL(cJSON_CreateArray),
DEFINE_MODULE_SYMBOL(cJSON_CreateObject),
DEFINE_MODULE_SYMBOL(cJSON_CreateStringReference),
DEFINE_MODULE_SYMBOL(cJSON_CreateObjectReference),
DEFINE_MODULE_SYMBOL(cJSON_CreateArrayReference),
DEFINE_MODULE_SYMBOL(cJSON_CreateIntArray),
DEFINE_MODULE_SYMBOL(cJSON_CreateFloatArray),
DEFINE_MODULE_SYMBOL(cJSON_CreateDoubleArray),
DEFINE_MODULE_SYMBOL(cJSON_CreateStringArray),
DEFINE_MODULE_SYMBOL(cJSON_AddItemToArray),
DEFINE_MODULE_SYMBOL(cJSON_AddItemToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddItemToObjectCS),
DEFINE_MODULE_SYMBOL(cJSON_AddItemReferenceToArray),
DEFINE_MODULE_SYMBOL(cJSON_AddItemReferenceToObject),
DEFINE_MODULE_SYMBOL(cJSON_DetachItemViaPointer),
DEFINE_MODULE_SYMBOL(cJSON_DetachItemFromArray),
DEFINE_MODULE_SYMBOL(cJSON_DeleteItemFromArray),
DEFINE_MODULE_SYMBOL(cJSON_DetachItemFromObject),
DEFINE_MODULE_SYMBOL(cJSON_DetachItemFromObjectCaseSensitive),
DEFINE_MODULE_SYMBOL(cJSON_DeleteItemFromObject),
DEFINE_MODULE_SYMBOL(cJSON_DeleteItemFromObjectCaseSensitive),
DEFINE_MODULE_SYMBOL(cJSON_InsertItemInArray),
DEFINE_MODULE_SYMBOL(cJSON_ReplaceItemViaPointer),
DEFINE_MODULE_SYMBOL(cJSON_ReplaceItemInArray),
DEFINE_MODULE_SYMBOL(cJSON_ReplaceItemInObject),
DEFINE_MODULE_SYMBOL(cJSON_ReplaceItemInObjectCaseSensitive),
DEFINE_MODULE_SYMBOL(cJSON_Duplicate),
DEFINE_MODULE_SYMBOL(cJSON_Compare),
DEFINE_MODULE_SYMBOL(cJSON_Minify),
DEFINE_MODULE_SYMBOL(cJSON_AddNullToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddTrueToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddFalseToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddBoolToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddNumberToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddStringToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddRawToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddObjectToObject),
DEFINE_MODULE_SYMBOL(cJSON_AddArrayToObject),
DEFINE_MODULE_SYMBOL(cJSON_SetNumberHelper),
DEFINE_MODULE_SYMBOL(cJSON_SetValuestring),
DEFINE_MODULE_SYMBOL(cJSON_malloc),
DEFINE_MODULE_SYMBOL(cJSON_free),
MODULE_SYMBOL_TERMINATOR
};
Module cjson_module = {
.name = "cjson",
.start = nullptr,
.stop = nullptr,
.drivers = nullptr,
.symbols = SYMBOLS,
.internal = nullptr,
};
}

View File

@ -7,9 +7,11 @@ instantiation, not a plain function call. Apps still `#include <new>`/`<map>`/`<
directly; this module only makes sure the actual out-of-line definitions resolve when their ELF
is loaded into the firmware.
ESP32-only: several of these symbols are mangled for a 32-bit ABI (`j` = `unsigned int`, used
here to represent `size_t`). On a 64-bit host those would mangle differently (e.g. `_Znwm`
instead of `_Znwj`), so this module doesn't build for the POSIX simulator.
Most of this module is ESP32-only: several of these symbols are mangled for a 32-bit ABI (`j` =
`unsigned int`, used here to represent `size_t`) that only applies there - a 64-bit host mangles
them differently (e.g. `_Znwm` instead of `_Znwj`). Those sections are gated behind `#ifdef
ESP_PLATFORM` in `source/module.cpp`; symbols outside that gate (e.g. `__cxa_pure_virtual`,
`__cxa_guard_*`) build and export on the POSIX simulator too.
## Supported symbols
@ -74,15 +76,73 @@ symbol - the same trick used for `_M_replace_cold` and friends, except *we* supp
instead of pointing at one the library already provides). An app whose loaded ELF needs it will
still fail with `Can't find common ...C1.../...C2.../...C5...`.
### `std::deque<char>` / `<double>` / `<basic_string<char>>`, `std::stack`
Non-template `_Deque_base`/`_Deque_iterator` internals plus each element type's own out-of-line
member set (push_back/pop_back/emplace_back, map reallocation, iterator arithmetic). Needed by any
app using `std::stack` (whose default underlying container is `std::deque`). None of this has an
`extern template` instantiation in libstdc++.a, so every member here is forced into existence by
a wrapper that calls the real public deque/stack API on a real object (see `source/module.cpp`).
### `std::_Rb_tree<std::string, ...>`, `std::map<std::string, std::string>`
The `std::map<string, string>` instantiation's own non-template-shared internals (on top of the
generic `_Rb_tree_increment`/`_Rb_tree_insert_and_rebalance` helpers above), plus
`operator[]`/piecewise-construct support for in-place node construction.
### `std::vector<const char*>`, `std::vector<std::pair<std::string, bool>>`
Same `_M_check_len`/`_Guard_alloc`/`emplace_back`/`_M_realloc_append` pattern as `vector<string>`
and `vector<unsigned char>` above, for two more element types apps instantiate over.
### `std::shared_ptr<T>` control block
`__shared_count::operator=`, `_Sp_counted_base`'s virtual dispatch, and its vtable, for both lock
policies (atomic and mutex-based - which one an app's build selects isn't controlled by this
firmware, so both are exported). Forced via `std::shared_ptr<int>` rather than any real app type,
since none of these three carry a pointee type in their mangled name.
**Not exported: the raw-pointer constructor** (`__shared_count<Lp>::__shared_count<T*>(T*)`),
because its mangled name does embed the pointee type `T` - no single firmware-side entry can serve
every app's `shared_ptr<AppDefinedType>`. This isn't a gap in practice: the app's own compiler
already emits a local, weak-linkage definition of that exact constructor in the app's own ELF
(standard behavior for an implicitly-instantiated template), and the ELF loader falls back to an
app-local definition whenever firmware doesn't provide one, so it resolves without any firmware
export at all. Confirmed by loading an app holding a `shared_ptr` to one of its own types with
nothing shared_ptr-specific exported here beyond the generic pieces above.
### `std::function<int(char*, unsigned int)>`
`operator()`, `swap`, copy constructor, and `operator=(nullptr)` for this one call signature.
### Misc algorithm/iterator template instantiations
`__copy_move_a2`, `__copy_move_backward_a2`, `__relocate_a_1`, `__advance`, `iter_swap`,
`transform`, `std::min`/`std::max<short>` - pulled in by `std::stack`/`vector<pair<...>>` usage
above rather than needed standalone.
## Adding a new symbol
1. Find the mangled name (`nm`/`c++filt`, or the linker's "undefined reference" error from an
app build).
1. Find the mangled name. `TactilityApps/Tools/check-app-symbols.py <path/to/App.app.elf>` reports
every symbol an app's ELF actually needs firmware to resolve - it already excludes symbols the
app's own ELF defines locally (e.g. an implicitly-instantiated template like a `shared_ptr<T>`
constructor over an app-defined `T`), so if it doesn't list something, it doesn't need adding
here even if the mangled name shows up in the ELF's relocations.
2. Add an `extern "C"` declaration for it in `source/module.cpp` if the name isn't already a
valid identifier you can reference directly (mangled names usually are, e.g. `_ZSt19...`).
valid identifier you can reference directly (mangled names usually are, e.g. `_ZSt19...`). If a
plain `extern` declaration compiles but fails to *link*, the symbol likely has no `extern
template` instantiation anywhere in libstdc++.a (true for `deque`, `vector<pair<...>>`,
`shared_ptr`'s control block, `std::function`, and most algorithm templates) - write a small
wrapper that calls the real public API on a real object instead (see any of the existing
`construct_*`/`destroy_*` functions in this file for the pattern), and register the wrapper's
address rather than the mangled name directly.
3. Add a `DEFINE_MODULE_SYMBOL(...)` entry (or a manual `{ "mangled_name", (void*)&expr }` pair
when the address isn't reachable through the mangled identifier itself, e.g. `std::nothrow`
or the `__throw_*` functions).
4. Rebuild the firmware and confirm with `nm`/`check-app-symbols.py` that the symbol resolves to
a real, non-null defined address - a reference that merely compiles and links without error can
still silently resolve to the wrong (e.g. an unrelated weak-undefined stub) or a null definition
if something else in the link graph shifts which archive member satisfies it first.
## License

View File

@ -3,9 +3,17 @@
#include <cstddef>
#include <cstdint>
#include <deque>
#include <exception>
#include <functional>
#include <map>
#include <memory>
#include <new>
#include <stack>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#if defined(__GLIBCXX__) || defined(ESP_PLATFORM)
#define TT_CPP_SYMBOLS_AVAILABLE 1
@ -29,11 +37,12 @@ extern "C" {
extern void _ZdlPv(void* p); // operator delete(void*)
extern void _ZdaPv(void* p); // operator delete[](void*)
#endif
extern void __cxa_pure_virtual();
// cxx_guards.cpp
extern int __cxa_guard_acquire(void* pg);
extern void __cxa_guard_release(void* pg) throw();
extern void __cxa_guard_abort(void* pg) throw();
// bits/atomic_wait.h (pulled in via <memory>) declares these as long long*; must match
// exactly or GCC treats them as conflicting redeclarations.
extern int __cxa_guard_acquire(long long* pg);
extern void __cxa_guard_release(long long* pg) throw();
extern void __cxa_guard_abort(long long* pg) throw();
#ifdef ESP_PLATFORM
// Not part of the Itanium C++ ABI that desktop libstdc++ implements; ESP-IDF's toolchain only.
extern void __cxa_guard_dummy(void);
@ -72,9 +81,164 @@ extern "C" {
// return-value pointer (Itanium ABI), same convention as substr() above.
void* _ZSt12__str_concatINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEET_PKNS6_10value_typeENS6_9size_typeES9_SA_RKNS6_14allocator_typeE(void*, const char*, unsigned int, const char*, unsigned int, const void*);
void* _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EERKS8_PKS5_(void*, const void*, const char*);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4findEPKcj(const void*, const char*, unsigned int);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4findEPKcjj(const void*, const char*, unsigned int, unsigned int);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEPKcjj(const void*, const char*, unsigned int, unsigned int);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEcj(const void*, char, unsigned int);
int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareERKS4_(const void*, const void*);
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4swapERS4_(void*, void*);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6insertEjPKc(void*, unsigned int, const char*);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7replaceEjjPKcj(void*, unsigned int, unsigned int, const char*, unsigned int);
unsigned int _ZNSt8__detail14__to_chars_lenIjEEjT_i(unsigned int, int);
void _ZNSt8__detail18__to_chars_10_implIjEEvPcjT_(char*, unsigned int, unsigned int);
// `unsigned long` overloads of the same two helpers - to_string(long)'s internal path,
// distinct mangled names from the `unsigned int` ones above (to_string(unsigned)'s path).
unsigned int _ZNSt8__detail14__to_chars_lenImEEjT_i(unsigned long, int);
void _ZNSt8__detail18__to_chars_10_implImEEvPcjT_(char*, unsigned int, unsigned long);
bool _ZSteqIcSt11char_traitsIcESaIcEEbRKNSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_(const void*, const char*); // operator==(string const&, const char*)
bool _ZSteqIcSt11char_traitsIcESaIcEEbRKNSt7__cxx1112basic_stringIT_T0_T1_EESA_(const void*, const void*); // operator==(string const&, string const&)
// operator+ overloads: hidden return-value pointer (return basic_string by value).
void* _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEOS8_S9_(void*, void*, void*);
void* _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_(void*, const char*, const void*);
void* _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EERKS8_SA_(void*, const void*, const void*);
// vector<unsigned char> and vector<std::string> internals - Note: mangled names required.
void _ZNKSt6vectorIhSaIhEE12_M_check_lenEjPKc(const void*, unsigned int, const char*);
void _ZNKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12_M_check_lenEjPKc(const void*, unsigned int, const char*);
bool _ZNKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE5emptyEv(const void*);
void* _ZNSt12_Vector_baseIhSaIhEE11_M_allocateEj(void*, unsigned int);
void* _ZNSt12_Vector_baseIhSaIhEE17_M_create_storageEj(void*, unsigned int);
void _ZNSt6vectorIhSaIhEE17_M_default_appendEj(void*, unsigned int);
void _ZNSt6vectorIhSaIhEE6resizeEj(void*, unsigned int);
unsigned char* _ZNSt27__uninitialized_default_n_1ILb1EE18__uninit_default_nIPhjEET_S3_T0_(unsigned char*, unsigned int);
void* _ZSt9__fill_a1IhhEN9__gnu_cxx11__enable_ifIXaasrSt9__is_byteIT_E7__valueoosrSt10__are_sameIS3_T0_E7__valuesrSt20__memcpyable_integerIS6_E7__widthEvE6__typeEPS3_SC_RKS6_(unsigned char*, unsigned char*, const unsigned char*);
// std::mutex
void _ZNSt5mutex4lockEv(void*);
// Remaining basic_string/vector template instantiations, raw-extern like _M_construct's
// forward-iterator overload above - these are genuinely out-of-line template
// instantiations (not compiler-inlined ctors/dtors), so no forcing wrapper is needed.
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb1EEEvPKcj(void*, const char*, unsigned int);
// resize_and_overwrite's instantiation is scoped to to_string(unsigned)'s own private lambda
// type - unnameable directly, but calling std::to_string(unsigned) below (construct_
// to_string_result) instantiates it in this TU under this exact mangled name, addressable
// by name even though its C++ type can't be spelled outside to_string's own body.
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE20resize_and_overwriteIRZNS_9to_stringEjEUlPcjE_EEvjT_(void*, unsigned int, void*);
void* _ZSt14__relocate_a_1IPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_SaIS5_EET0_T_S9_S8_RT1_(void*, void*, void*, void*);
int _ZStssIcSt11char_traitsIcESaIcEEDTcl21__char_traits_cmp_catIT0_ELi0EEERKNSt7__cxx1112basic_stringIT_S3_T1_EESB_(const void*, const void*); // operator<=>(string const&, string const&)
long _ZNKSt8functionIFlvEEclEv(const void*); // std::function<long()>::operator()() const
void _ZNSt14_Function_baseD2Ev(void*); // std::_Function_base::~_Function_base()
void _ZNSt8functionIFlvEEC1ERKS1_(void*, const void*); // std::function<long()>::function(function const&)
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE13find_first_ofEPKcj(const void*, const char*, unsigned int);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE13find_first_ofEPKcjj(const void*, const char*, unsigned int, unsigned int);
unsigned int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4copyEPcjj(const void*, char*, unsigned int, unsigned int);
int _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEjjPKc(const void*, unsigned int, unsigned int, const char*);
void _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE8_M_checkEjPKc(const void*, unsigned int, const char*);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructEjc(void*, unsigned int, char);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE14_M_replace_auxEjjjc(void*, unsigned int, unsigned int, unsigned int, char);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5eraseEjj(void*, unsigned int, unsigned int);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6appendEjc(void*, unsigned int, char);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6assignEPKcj(void*, const char*, unsigned int);
void* _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6resizeEjc(void*, unsigned int, char);
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_S_assignEPcjc(char*, unsigned int, char);
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcjRKS3_(void*, const char*, unsigned int, const void*);
// resize_and_overwrite/to_string's `long` overloads - distinct mangled names from the
// `unsigned int` ones already handled above (construct_to_string_result et al.).
void _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE20resize_and_overwriteIRZNS_9to_stringElEUlPcjE_EEvjT_(void*, unsigned int, void*);
// std::_Rb_tree<std::string, std::pair<const std::string, std::string>, ...> - std::map<string,
// string>'s internals.
void* _ZNKSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_lower_boundEPSt18_Rb_tree_node_baseSG_RS7_(const void*, void*, void*, const void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE10_Auto_node9_M_insertES6_IPSt18_Rb_tree_node_baseSH_E(void*, void*, void*);
void _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE10_Auto_nodeD1Ev(void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE11lower_boundERS7_(void*, const void*);
void _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE12_M_drop_nodeEPSt13_Rb_tree_nodeIS8_E(void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_create_nodeIJRKSt21piecewise_construct_tSt5tupleIJOS5_EESJ_IJEEEEEPSt13_Rb_tree_nodeIS8_EDpOT_(void*, const void*, void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_create_nodeIJRKSt21piecewise_construct_tSt5tupleIJRS7_EESJ_IJEEEEEPSt13_Rb_tree_nodeIS8_EDpOT_(void*, const void*, void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_insert_nodeEPSt18_Rb_tree_node_baseSG_PSt13_Rb_tree_nodeIS8_E(void*, void*, void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJOS5_EESJ_IJEEEEESt17_Rb_tree_iteratorIS8_ESt23_Rb_tree_const_iteratorIS8_EDpOT_(void*, void*, const void*, void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS7_EESJ_IJEEEEESt17_Rb_tree_iteratorIS8_ESt23_Rb_tree_const_iteratorIS8_EDpOT_(void*, void*, const void*, void*, void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE24_M_get_insert_unique_posERS7_(void*, const void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS7_(void*, void*, const void*);
void* _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE4findERS7_(void*, const void*);
void _ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE8_M_eraseEPSt13_Rb_tree_nodeIS8_E(void*, void*);
// std::map<std::string, std::string>::operator[] (two overloads: rvalue key and const& key).
void* _ZNSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St4lessIS5_ESaISt4pairIKS5_S5_EEEixEOS5_(void*, void*);
void* _ZNSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St4lessIS5_ESaISt4pairIKS5_S5_EEEixERS9_(void*, const void*);
// pair<const string, string>(piecewise_construct_t, tuple<string&>, tuple<>) - the map-node
// in-place construction path std::map<string,string>::operator[] uses internally.
void _ZNSt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_EC1IJRS6_EJEEESt21piecewise_construct_tSt5tupleIJDpT_EESB_IJDpT0_EE(void*, const void*, void*, void*);
// No addressable name of their own (private members / SFINAE overloads); the forcing
// wrappers above make GCC emit real definitions, resolved here by mangled name.
void _ZNSt11_Deque_baseIcSaIcEEC2Ev(void*);
void _ZNSt11_Deque_baseIcSaIcEED2Ev(void*);
void _ZNSt11_Deque_baseIcSaIcEE15_M_create_nodesEPPcS3_(void*, char**, char**);
void _ZNSt11_Deque_baseIcSaIcEE16_M_destroy_nodesEPPcS3_(void*, char**, char**);
void _ZNSt11_Deque_baseIcSaIcEE17_M_initialize_mapEj(void*, unsigned int);
void _ZNSt11_Deque_baseIdSaIdEEC2Ev(void*);
void _ZNSt11_Deque_baseIdSaIdEED2Ev(void*);
void _ZNSt11_Deque_baseIdSaIdEE15_M_create_nodesEPPdS3_(void*, double**, double**);
void _ZNSt11_Deque_baseIdSaIdEE16_M_destroy_nodesEPPdS3_(void*, double**, double**);
void _ZNSt11_Deque_baseIdSaIdEE17_M_initialize_mapEj(void*, unsigned int);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EEC2Ev(void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EEC2EOS7_(void*, void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED2Ev(void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_create_nodesEPPS5_S9_(void*, void*, void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_destroy_nodesEPPS5_S9_(void*, void*, void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEj(void*, unsigned int);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_Deque_impl_dataC1EOS8_(void*, void*);
void _ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_Deque_impl_dataC1ERKS8_(void*, const void*);
void* _ZSt4swapINSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EE16_Deque_impl_dataEENSt9enable_ifIXsrSt6__and_IJSt6__not_ISt15__is_tuple_likeIT_EESt21is_move_constructibleISE_ESt18is_move_assignableISE_EEE5valueEvE4typeERSE_SO_(void*, void*);
void _ZNSt5dequeIcSaIcEE15_M_pop_back_auxEv(void*);
void _ZNSt5dequeIcSaIcEE16_M_push_back_auxIJRKcEEEvDpOT_(void*, const char*);
void _ZNSt5dequeIcSaIcEE16_M_push_back_auxIJcEEEvDpOT_(void*, char*);
void _ZNSt5dequeIcSaIcEE17_M_reallocate_mapEjb(void*, unsigned int, bool);
void _ZNSt5dequeIcSaIcEE22_M_reserve_map_at_backEj(void*, unsigned int);
void _ZNSt5dequeIdSaIdEE15_M_pop_back_auxEv(void*);
void _ZNSt5dequeIdSaIdEE16_M_push_back_auxIJRKdEEEvDpOT_(void*, const double*);
void _ZNSt5dequeIdSaIdEE16_M_push_back_auxIJdEEEvDpOT_(void*, double*);
void _ZNSt5dequeIdSaIdEE17_M_reallocate_mapEjb(void*, unsigned int, bool);
void _ZNSt5dequeIdSaIdEE22_M_reserve_map_at_backEj(void*, unsigned int);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_pop_front_auxEv(void*);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_push_back_auxIJRKS5_EEEvDpOT_(void*, const void*);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_push_back_auxIJS5_EEEvDpOT_(void*, void*);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_reallocate_mapEjb(void*, unsigned int, bool);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE22_M_reserve_map_at_backEj(void*, unsigned int);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_destroy_dataESt15_Deque_iteratorIS5_RS5_PS5_ESB_RKS6_(void*, void*, void*, const void*);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_erase_at_endESt15_Deque_iteratorIS5_RS5_PS5_E(void*, void*);
void _ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE19_M_destroy_data_auxESt15_Deque_iteratorIS5_RS5_PS5_ESB_(void*, void*, void*);
void _ZNKSt6vectorIPKcSaIS1_EE12_M_check_lenEjS1_(const void*, unsigned int, const char*);
void _ZNKSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE12_M_check_lenEjPKc(const void*, unsigned int, const char*);
void _ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE15_M_erase_at_endEPS7_(void*, void*);
void* _ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE4backEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE10_M_destroyEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE10_M_releaseEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE19_M_release_last_useEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_releaseEv(void*);
void _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE19_M_release_last_useEv(void*);
// Base _Sp_counted_base<Lock_policy> vtable (not a derived _Sp_counted_ptr<T,...>'s, which
// varies per pointee type); exported as a weak symbol once the shared_count wrappers below
// force its emission.
extern void* _ZTVSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE;
extern void* _ZTVSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE;
#endif
}
namespace {
// Reimplements __cxa_pure_virtual's terminate() call directly rather than linking against
// libstdc++.a(pure.o): once this file's locale/codecvt-pulling surface area (deque/vector<pair>/
// shared_ptr/function below) grows large enough, some archive members carry their own
// weak-undefined __cxa_pure_virtual reference that ld can resolve against instead of pure.o,
// silently leaving the exported symbol null. Unconditional (not gated behind #ifdef
// ESP_PLATFORM): also needed on the POSIX/simulator build.
[[noreturn]] void pure_virtual_called() {
std::terminate();
}
}
#ifdef ESP_PLATFORM
namespace {
// basic_string(basic_string const&, pos, len) has no out-of-line definition anywhere to take the
@ -95,6 +259,308 @@ void construct_basic_string_from_cstr(void* self, const char* s, const void* all
void construct_basic_string_move(void* self, void* other) {
new (self) std::string(std::move(*static_cast<std::string*>(other)));
}
// vector<std::string>: same story as basic_string's ctors above - the destructor for a
// non-trivial element type has no out-of-line definition anywhere to take the address of, so a
// wrapper that actually destroys one forces the compiler to emit a genuine, addressable
// definition here, registered below under the mangled name the ELF loader looks up.
void destroy_vector_of_strings(void* self) {
static_cast<std::vector<std::string>*>(self)->~vector();
}
// Same story for __new_allocator<std::string>::allocate() (used internally by vector<string>'s
// growth/reserve path).
void* allocate_string_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<std::string>*>(self)->allocate(n, hint);
}
// Same story for vector<unsigned char>'s destructor.
void destroy_vector_of_bytes(void* self) {
static_cast<std::vector<unsigned char>*>(self)->~vector();
}
// _Vector_base<T>::~_Vector_base only deallocates the raw buffer (element destruction is
// vector<T>::~vector()'s job, called before this) - a distinct entry point with no accessible
// out-of-line definition of its own (it's a protected base of vector<T>, and its destructor body
// is a one-line inline in the header). A shim that publicly re-derives from it regains access to
// call the real destructor at the right address, without duplicating its (private) cleanup logic.
struct StringVectorBaseShim : std::_Vector_base<std::string, std::allocator<std::string>> {};
void destroy_vector_base_of_strings(void* self) {
static_cast<StringVectorBaseShim*>(self)->~StringVectorBaseShim();
}
// std::to_string(unsigned) is `inline` in the header (no prebuilt out-of-line definition in
// libstdc++'s archive) - the app calls it directly as an opaque function in at least one call
// site (rather than always inlining it), so it needs a real out-of-line definition under its own
// mangled name, not just a forcing side effect. Hidden return-value pointer convention, matching
// the other string-returning functions (operator+, __str_concat) elsewhere in this file. This
// same call also instantiates resize_and_overwrite()'s to_string-private lambda, registered
// separately below under its own mangled name.
void construct_to_string_result(void* out, unsigned int value) {
new (out) std::string(std::to_string(value));
}
// Same story for std::to_string(long) - a distinct overload/mangled name from the unsigned one
// above. Also instantiates its own private resize_and_overwrite lambda, registered separately
// under its own mangled name (see the extern declarations above).
void construct_to_string_result_long(void* out, long value) {
new (out) std::string(std::to_string(value));
}
// basic_string::rfind<string_view>(string_view const&, pos) is a small header-inline SFINAE
// forwarder around the already-exported rfind(const char*, pos, n) overload - no prebuilt
// out-of-line definition either, same story as to_string above.
[[gnu::used]] unsigned int rfind_string_view(const std::string& self, const std::string_view& sv, unsigned int pos) {
return self.rfind(sv, pos);
}
// _Vector_base<T>::_Vector_impl_data::_M_swap_data - a plain one-line inline swap of three
// pointers, normally never emitted out-of-line, but the app references it directly anyway
// (matches _M_replace_cold's "kept out of line" pattern elsewhere in this file). Its type and
// method are public members of the (struct, so default-public) _Vector_base.
using StringVectorImplData = std::_Vector_base<std::string, std::allocator<std::string>>::_Vector_impl_data;
void swap_string_vector_impl_data(void* self, void* other) {
static_cast<StringVectorImplData*>(self)->_M_swap_data(*static_cast<StringVectorImplData*>(other));
}
// Same story for vector<unsigned char>(size_type, allocator const&).
void construct_vector_of_bytes_sized(void* self, unsigned int count, const void* alloc) {
new (self) std::vector<unsigned char>(count, *static_cast<const std::allocator<unsigned char>*>(alloc));
}
// Same _Vector_base<T>::~_Vector_base distinction as the string version above, for
// vector<unsigned char>.
struct ByteVectorBaseShim : std::_Vector_base<unsigned char, std::allocator<unsigned char>> {};
void destroy_vector_base_of_bytes(void* self) {
static_cast<ByteVectorBaseShim*>(self)->~ByteVectorBaseShim();
}
// push_back/emplace_back/back on vector<string> are ordinary public member functions with
// out-of-line definitions, registered below under their real mangled names - the app's own
// push_back/emplace_back calls resolve directly here, so each must insert exactly once.
void push_back_string(void* self, const std::string& value) {
static_cast<std::vector<std::string>*>(self)->push_back(value);
}
std::string& emplace_back_string(void* self, std::string&& value) {
return static_cast<std::vector<std::string>*>(self)->emplace_back(std::move(value));
}
// _M_realloc_append(T&&) is what push_back/emplace_back call internally when the vector needs
// to grow - the app can also call it directly (its own compiled code inlined the fast/slow-path
// split from push_back's body, keeping only the growth call out-of-line). These do exactly what
// _M_realloc_append itself does (append one element, growing the vector), so redirecting the
// app's call here is behavior-preserving - unlike push_back_string/emplace_back_string above,
// which append TWO elements and must not be reused for this.
void realloc_append_string_const_ref(void* self, const std::string& value) {
static_cast<std::vector<std::string>*>(self)->push_back(value);
}
void realloc_append_string_rvalue(void* self, std::string&& value) {
static_cast<std::vector<std::string>*>(self)->push_back(std::move(value));
}
// std::deque<char>/<double>/<basic_string<char>> - unlike basic_string, libstdc++ does NOT
// `extern template` instantiate std::deque anywhere, so NONE of its members (public or private)
// exist as prebuilt symbols in libstdc++.a - a plain extern declaration link-fails even though it
// compiles. Every wrapper below calls only the PUBLIC deque API on a real object; that forces the
// compiler to instantiate and emit genuine out-of-line definitions for both the public entry point
// and whichever private _M_*/_Deque_base helpers it needs internally, each addressable under its
// own real mangled name (registered directly in SYMBOLS[] below, same as _M_realloc_append above).
void destroy_deque_char(void* self) { static_cast<std::deque<char>*>(self)->~deque(); }
char& back_of_deque_char(void* self) { return static_cast<std::deque<char>*>(self)->back(); }
void pop_back_deque_char(void* self) { static_cast<std::deque<char>*>(self)->pop_back(); }
void push_back_deque_char(void* self, const char& v) { static_cast<std::deque<char>*>(self)->push_back(v); }
char& emplace_back_deque_char(void* self, char&& v) { return static_cast<std::deque<char>*>(self)->emplace_back(std::move(v)); }
void destroy_deque_double(void* self) { static_cast<std::deque<double>*>(self)->~deque(); }
double& back_of_deque_double(void* self) { return static_cast<std::deque<double>*>(self)->back(); }
void pop_back_deque_double(void* self) { static_cast<std::deque<double>*>(self)->pop_back(); }
void push_back_deque_double(void* self, const double& v) { static_cast<std::deque<double>*>(self)->push_back(v); }
double& emplace_back_deque_double(void* self, double&& v) { return static_cast<std::deque<double>*>(self)->emplace_back(std::move(v)); }
using StringDeque = std::deque<std::string>;
void construct_deque_string(void* self) { new (self) StringDeque(); }
void move_construct_deque_string(void* self, void* other) { new (self) StringDeque(std::move(*static_cast<StringDeque*>(other))); }
void destroy_deque_string(void* self) { static_cast<StringDeque*>(self)->~deque(); }
std::string& back_of_deque_string(void* self) { return static_cast<StringDeque*>(self)->back(); }
void clear_deque_string(void* self) { static_cast<StringDeque*>(self)->clear(); }
void pop_front_deque_string(void* self) { static_cast<StringDeque*>(self)->pop_front(); }
void push_back_deque_string(void* self, const std::string& v) { static_cast<StringDeque*>(self)->push_back(v); }
std::string& emplace_back_deque_string(void* self, std::string&& v) { return static_cast<StringDeque*>(self)->emplace_back(std::move(v)); }
// std::stack<T, deque<T>>'s default constructor - trivial, but (like everything else deque-related
// here) has no prebuilt out-of-line definition anywhere; a value-initializing placement-new forces
// the compiler to emit one.
void construct_stack_char(void* self) { new (self) std::stack<char, std::deque<char>>(); }
void construct_stack_double(void* self) { new (self) std::stack<double, std::deque<double>>(); }
// std::_Deque_iterator<T,...>::operator--() and operator-(iterator, iterator) - reached through
// std::stack<T>::pop()/size() internals when T's deque grows past a single node. Forced the same
// way: call the real operators on real iterators (obtained via begin()/end(), which are cheap and
// always valid even on an empty deque).
void decrement_deque_iterator_char(void* self) { --*static_cast<std::deque<char>::iterator*>(self); }
void decrement_deque_iterator_double(void* self) { --*static_cast<std::deque<double>::iterator*>(self); }
void decrement_deque_iterator_string(void* self) { --*static_cast<StringDeque::iterator*>(self); }
int subtract_deque_iterators_char(const void* a, const void* b) {
return static_cast<int>(*static_cast<const std::deque<char>::iterator*>(a) - *static_cast<const std::deque<char>::iterator*>(b));
}
int subtract_deque_iterators_double(const void* a, const void* b) {
return static_cast<int>(*static_cast<const std::deque<double>::iterator*>(a) - *static_cast<const std::deque<double>::iterator*>(b));
}
int subtract_deque_iterators_string(const void* a, const void* b) {
return static_cast<int>(*static_cast<const StringDeque::iterator*>(a) - *static_cast<const StringDeque::iterator*>(b));
}
// std::vector<const char*> and std::vector<std::pair<std::string, bool>> - same "no extern
// template anywhere" story as deque above (nothing else in the firmware happens to instantiate
// these two particular element types, unlike vector<string>/vector<unsigned char> which do get
// pulled in elsewhere and so link fine as plain externs). Forced via the public API, same pattern.
using CStrVector = std::vector<const char*>;
void destroy_vector_base_of_cstrs(void* self) { static_cast<std::_Vector_base<const char*, std::allocator<const char*>>*>(self)->~_Vector_base(); }
const char*& back_of_cstr_vector(void* self) { return static_cast<CStrVector*>(self)->back(); }
const char*& emplace_back_cstr_vector(void* self, const char*&& v) { return static_cast<CStrVector*>(self)->emplace_back(std::move(v)); }
void realloc_append_cstr_vector(void* self, const char*&& v) { static_cast<CStrVector*>(self)->push_back(std::move(v)); }
void reserve_cstr_vector(void* self, unsigned int n) { static_cast<CStrVector*>(self)->reserve(n); }
void* allocate_cstr_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<const char*>*>(self)->allocate(n, hint);
}
using StringBoolPair = std::pair<std::string, bool>;
using StringBoolPairVector = std::vector<StringBoolPair>;
bool empty_string_bool_pair_vector(const void* self) { return static_cast<const StringBoolPairVector*>(self)->empty(); }
// erase(begin(), end()) calls _M_erase_at_end(pointer) internally, forcing its instantiation
// under the mangled name registered directly via DEFINE_MODULE_SYMBOL below - this function
// itself is never called or registered, it exists purely so that call happens somewhere in this
// TU. [[gnu::used]] keeps the compiler from dead-stripping it as an uncalled anonymous-namespace
// function, which would silently drop the instantiation it exists to force.
[[gnu::used]] void clear_string_bool_pair_vector(void* self) {
auto* v = static_cast<StringBoolPairVector*>(self);
v->erase(v->begin(), v->end());
}
void destroy_vector_base_of_string_bool_pairs(void* self) { static_cast<std::_Vector_base<StringBoolPair, std::allocator<StringBoolPair>>*>(self)->~_Vector_base(); }
void destroy_vector_of_string_bool_pairs(void* self) { static_cast<StringBoolPairVector*>(self)->~vector(); }
StringBoolPair& emplace_back_string_bool_pair_vector(void* self, StringBoolPair&& v) { return static_cast<StringBoolPairVector*>(self)->emplace_back(std::move(v)); }
void realloc_append_string_bool_pair_vector(void* self, StringBoolPair&& v) { static_cast<StringBoolPairVector*>(self)->push_back(std::move(v)); }
void* allocate_string_bool_pair_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<StringBoolPair>*>(self)->allocate(n, hint);
}
void* allocate_string_ptr_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<std::string*>*>(self)->allocate(n, hint);
}
void* allocate_char_ptr_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<char*>*>(self)->allocate(n, hint);
}
void* allocate_double_ptr_storage(void* self, unsigned int n, const void* hint) {
return static_cast<std::__new_allocator<double*>*>(self)->allocate(n, hint);
}
// std::__shared_count<Lp>/_Sp_counted_base<Lp> - no extern-template instantiation anywhere, same
// story as deque/vector<pair<...>> above. Forced via std::shared_ptr<int> rather than a real app
// type: the raw-pointer constructor's mangled name embeds the pointee type, but operator= and
// _Sp_counted_base's virtual dispatch (forced as a side effect of constructing one) don't - their
// mangled names carry only the Lock_policy, so those two are genuinely reusable across every app's
// shared_ptr<AnyType> regardless of what int has to do with any of them.
using GenericSharedCountAtomic = std::__shared_count<__gnu_cxx::_Lock_policy::_S_atomic>;
using GenericSharedCountMutex = std::__shared_count<__gnu_cxx::_Lock_policy::_S_mutex>;
// [[gnu::used]]: neither of these is registered in SYMBOLS[] under its own name (nothing looks
// up "construct a shared_ptr<int>" by that description) - they exist purely so the compiler
// instantiates _Sp_counted_base<Lock_policy>'s virtual table and out-of-line thunks as a side
// effect, which -ffunction-sections/--gc-sections would otherwise strip as dead code since no
// other code in this TU calls them and nothing takes their address.
[[gnu::used]] void construct_shared_count_atomic_int(void* self, int* p) { new (self) GenericSharedCountAtomic(p); }
void assign_shared_count_atomic(void* self, const void* other) {
*static_cast<GenericSharedCountAtomic*>(self) = *static_cast<const GenericSharedCountAtomic*>(other);
}
[[gnu::used]] void construct_shared_count_mutex_int(void* self, int* p) { new (self) GenericSharedCountMutex(p); }
void assign_shared_count_mutex(void* self, const void* other) {
*static_cast<GenericSharedCountMutex*>(self) = *static_cast<const GenericSharedCountMutex*>(other);
}
// _Sp_counted_base<Lock_policy> is an abstract base (_M_destroy/_M_release/_M_release_last_use
// are virtual, overridden by the concrete _Sp_counted_ptr<T*,...> that __shared_count's
// constructor above actually allocates) - can't instantiate it standalone, but constructing a real
// GenericSharedCount*(ptr) above already forces the compiler to emit its base class's virtual
// table and out-of-line virtual function thunks, addressable under _Sp_counted_base's own mangled
// names because that's the base subobject type the virtual calls are dispatched through, and
// those names carry only the Lock_policy (not the pointee type T), so this generic forcing works
// for every app's shared_ptr<AnyType> without needing to know AnyType.
//
// The raw-pointer __shared_count<Lp>::__shared_count<T*>(T*) constructor is deliberately NOT
// exported here: the app's own compiler already emits a local weak-linkage definition of it, and
// esp_elf.c's relocate loop falls back to that when the firmware doesn't provide one.
// std::function<int(char*, unsigned int)> - no extern-template instantiation anywhere, so forced
// via the public API on a real object, same pattern as everything else above.
using CharBufferFn = std::function<int(char*, unsigned int)>;
int call_char_buffer_fn(const void* self, char* buf, unsigned int len) { return (*static_cast<const CharBufferFn*>(self))(buf, len); }
void swap_char_buffer_fn(void* self, void* other) { static_cast<CharBufferFn*>(self)->swap(*static_cast<CharBufferFn*>(other)); }
void construct_char_buffer_fn_copy(void* self, const void* other) { new (self) CharBufferFn(*static_cast<const CharBufferFn*>(other)); }
void* assign_char_buffer_fn_nullptr(void* self) { return &(*static_cast<CharBufferFn*>(self) = nullptr); }
// _Guard_alloc's dtor is private to vector<T> itself (unlike _Vector_base above), so this
// replicates its fixed layout/dtor logic directly instead of calling the inaccessible real one.
template <typename T>
struct GuardAllocLayout {
T* storage;
std::size_t len;
void* vect;
};
template <typename T>
void destroy_guard_alloc(void* self) {
auto* guard = static_cast<GuardAllocLayout<T>*>(self);
if (guard->storage) {
std::allocator<T>().deallocate(guard->storage, guard->len);
}
}
std::string& back_of_string_vector(void* self) {
return static_cast<std::vector<std::string>*>(self)->back();
}
// vector<string>'s move-assignment operator (self = std::move(other)) - forces the private
// _M_move_assign/_M_swap_data helpers it needs to be emitted as addressable definitions too.
void move_assign_string_vector(void* self, void* other) {
*static_cast<std::vector<std::string>*>(self) = std::move(*static_cast<std::vector<std::string>*>(other));
}
// Misc algorithm/iterator template instantiations pulled in by std::stack<char/double> and
// vector<pair<string,bool>> usage - none prebuilt anywhere, forced by calling the public std::
// algorithm entry point on real pointers/iterators of the exact instantiated type.
std::string** copy_move_a2_string_ptr(std::string** first, std::string** last, std::string** out) {
return std::copy(first, last, out);
}
char** copy_move_a2_char_ptr(char** first, char** last, char** out) { return std::copy(first, last, out); }
double** copy_move_a2_double_ptr(double** first, double** last, double** out) { return std::copy(first, last, out); }
StringBoolPair* relocate_string_bool_pairs(StringBoolPair* first, StringBoolPair* last, StringBoolPair* out, std::allocator<StringBoolPair>& alloc) {
return std::__relocate_a(first, last, out, alloc);
}
std::string** copy_move_backward_a2_string_ptr(std::string** first, std::string** last, std::string** out) {
return std::copy_backward(first, last, out);
}
char** copy_move_backward_a2_char_ptr(char** first, char** last, char** out) { return std::copy_backward(first, last, out); }
double** copy_move_backward_a2_double_ptr(double** first, double** last, double** out) { return std::copy_backward(first, last, out); }
StringBoolPair* move_backward_string_bool_pairs(StringBoolPair* first, StringBoolPair* last, StringBoolPair* out) {
return std::move_backward(first, last, out);
}
short max_short_init_list(std::initializer_list<short> values) {
return std::max(values);
}
short min_short_init_list(std::initializer_list<short> values) {
return std::min(values);
}
void advance_string_ptr_ptr(std::string*** it, int n) { std::advance(*it, n); }
void advance_char_ptr_ptr(char*** it, int n) { std::advance(*it, n); }
void advance_double_ptr_ptr(double*** it, int n) { std::advance(*it, n); }
void iter_swap_string_bool_pair_vector(StringBoolPairVector::iterator a, StringBoolPairVector::iterator b) {
std::iter_swap(a, b);
}
__gnu_cxx::__normal_iterator<char*, std::string> transform_char_to_upper(
__gnu_cxx::__normal_iterator<char*, std::string> first,
__gnu_cxx::__normal_iterator<char*, std::string> last,
__gnu_cxx::__normal_iterator<char*, std::string> out,
int (*fn)(int)
) {
return std::transform(first, last, out, fn);
}
// std::_Any_data (std::function's internal storage union) - swap<T> is SFINAE-enabled only for
// move-constructible/assignable, non-tuple-like T; _Any_data qualifies, so calling std::swap on
// two real ones forces this exact overload's instantiation.
void swap_any_data(void* a, void* b) {
std::swap(*static_cast<std::_Any_data*>(a), *static_cast<std::_Any_data*>(b));
}
}
#endif
#endif
@ -111,7 +577,7 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(_ZdaPv), // operator delete[](void*)
#endif
{ "_ZSt7nothrow", (void*)&std::nothrow },
DEFINE_MODULE_SYMBOL(__cxa_pure_virtual), // class-related, see https://arobenko.github.io/bare_metal_cpp/
{ "__cxa_pure_virtual", (void*)&pure_virtual_called }, // see comment above pure_virtual_called
DEFINE_MODULE_SYMBOL(__cxa_guard_acquire),
DEFINE_MODULE_SYMBOL(__cxa_guard_release),
DEFINE_MODULE_SYMBOL(__cxa_guard_abort),
@ -164,6 +630,225 @@ static const ModuleSymbol SYMBOLS[] = {
{ "_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC5EOS4_", (void*)&construct_basic_string_move },
DEFINE_MODULE_SYMBOL(_ZSt12__str_concatINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEET_PKNS6_10value_typeENS6_9size_typeES9_SA_RKNS6_14allocator_typeE),
DEFINE_MODULE_SYMBOL(_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EERKS8_PKS5_),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4findEPKcj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4findEPKcjj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEPKcjj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEcj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareERKS4_),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4swapERS4_),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6insertEjPKc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7replaceEjjPKcj),
DEFINE_MODULE_SYMBOL(_ZNSt8__detail14__to_chars_lenIjEEjT_i),
DEFINE_MODULE_SYMBOL(_ZNSt8__detail18__to_chars_10_implIjEEvPcjT_),
DEFINE_MODULE_SYMBOL(_ZNSt8__detail14__to_chars_lenImEEjT_i),
DEFINE_MODULE_SYMBOL(_ZNSt8__detail18__to_chars_10_implImEEvPcjT_),
DEFINE_MODULE_SYMBOL(_ZSteqIcSt11char_traitsIcESaIcEEbRKNSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_),
DEFINE_MODULE_SYMBOL(_ZSteqIcSt11char_traitsIcESaIcEEbRKNSt7__cxx1112basic_stringIT_T0_T1_EESA_),
DEFINE_MODULE_SYMBOL(_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEOS8_S9_),
DEFINE_MODULE_SYMBOL(_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_),
DEFINE_MODULE_SYMBOL(_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EERKS8_SA_),
DEFINE_MODULE_SYMBOL(_ZNKSt6vectorIhSaIhEE12_M_check_lenEjPKc),
DEFINE_MODULE_SYMBOL(_ZNKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12_M_check_lenEjPKc),
DEFINE_MODULE_SYMBOL(_ZNKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE5emptyEv),
DEFINE_MODULE_SYMBOL(_ZNSt12_Vector_baseIhSaIhEE11_M_allocateEj),
DEFINE_MODULE_SYMBOL(_ZNSt12_Vector_baseIhSaIhEE17_M_create_storageEj),
DEFINE_MODULE_SYMBOL(_ZNSt6vectorIhSaIhEE17_M_default_appendEj),
DEFINE_MODULE_SYMBOL(_ZNSt6vectorIhSaIhEE6resizeEj),
DEFINE_MODULE_SYMBOL(_ZNSt27__uninitialized_default_n_1ILb1EE18__uninit_default_nIPhjEET_S3_T0_),
DEFINE_MODULE_SYMBOL(_ZSt9__fill_a1IhhEN9__gnu_cxx11__enable_ifIXaasrSt9__is_byteIT_E7__valueoosrSt10__are_sameIS3_T0_E7__valuesrSt20__memcpyable_integerIS6_E7__widthEvE6__typeEPS3_SC_RKS6_),
DEFINE_MODULE_SYMBOL(_ZNSt5mutex4lockEv),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb1EEEvPKcj),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE20resize_and_overwriteIRZNS_9to_stringEjEUlPcjE_EEvjT_),
{ "_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindISt17basic_string_viewIcS2_EEENSt9enable_ifIXsrSt6__and_IJSt14is_convertibleIRKT_S7_ESt6__not_ISA_IPSC_PKS4_EESF_ISA_ISD_PKcEEEE5valueEjE4typeESD_j", (void*)&rfind_string_view },
DEFINE_MODULE_SYMBOL(_ZSt14__relocate_a_1IPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_SaIS5_EET0_T_S9_S8_RT1_),
DEFINE_MODULE_SYMBOL(_ZStssIcSt11char_traitsIcESaIcEEDTcl21__char_traits_cmp_catIT0_ELi0EEERKNSt7__cxx1112basic_stringIT_S3_T1_EESB_),
// vector<std::string> - Note: You have to use the mangled names here
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED1Ev", (void*)&destroy_vector_of_strings },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED2Ev", (void*)&destroy_vector_of_strings },
{ "_ZNSt15__new_allocatorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE8allocateEjPKv", (void*)&allocate_string_storage },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE9push_backERKS5_", (void*)&push_back_string },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12emplace_backIJS5_EEERS5_DpOT_", (void*)&emplace_back_string },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE4backEv", (void*)&back_of_string_vector },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE14_M_move_assignEOS7_St17integral_constantIbLb1EE", (void*)&move_assign_string_vector },
// vector<unsigned char> - Note: You have to use the mangled names here
{ "_ZNSt6vectorIhSaIhEED1Ev", (void*)&destroy_vector_of_bytes },
{ "_ZNSt6vectorIhSaIhEED2Ev", (void*)&destroy_vector_of_bytes },
{ "_ZNSt6vectorIhSaIhEEC1EjRKS0_", (void*)&construct_vector_of_bytes_sized },
{ "_ZNSt12_Vector_baseIhSaIhEED2Ev", (void*)&destroy_vector_base_of_bytes },
// _Vector_base<T>::~_Vector_base only deallocates the raw buffer (elements are destroyed by
// vector<T>'s own destructor before this runs) - a distinct entry point from ~vector(), so
// it needs its own wrapper rather than reusing destroy_vector_of_strings/_of_bytes above.
{ "_ZNSt12_Vector_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED2Ev", (void*)&destroy_vector_base_of_strings },
{ "_ZNSt7__cxx119to_stringEj", (void*)&construct_to_string_result },
{ "_ZNSt12_Vector_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_Vector_impl_data12_M_swap_dataERS8_", (void*)&swap_string_vector_impl_data },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_realloc_appendIJRKS5_EEEvDpOT_", (void*)&realloc_append_string_const_ref },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_realloc_appendIJS5_EEEvDpOT_", (void*)&realloc_append_string_rvalue },
{ "_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12_Guard_allocD1Ev", (void*)&destroy_guard_alloc<std::string> },
{ "_ZNSt6vectorIhSaIhEE12_Guard_allocD1Ev", (void*)&destroy_guard_alloc<unsigned char> },
DEFINE_MODULE_SYMBOL(_ZNKSt8functionIFlvEEclEv),
DEFINE_MODULE_SYMBOL(_ZNSt14_Function_baseD2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt8functionIFlvEEC1ERKS1_),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE13find_first_ofEPKcj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE13find_first_ofEPKcjj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4copyEPcjj),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEjjPKc),
DEFINE_MODULE_SYMBOL(_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE8_M_checkEjPKc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructEjc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE14_M_replace_auxEjjjc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5eraseEjj),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6appendEjc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6assignEPKcj),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6resizeEjc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_S_assignEPcjc),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcjRKS3_),
DEFINE_MODULE_SYMBOL(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE20resize_and_overwriteIRZNS_9to_stringElEUlPcjE_EEvjT_),
{ "_ZNSt7__cxx119to_stringEl", (void*)&construct_to_string_result_long },
// std::deque<char>/<double>/<basic_string<char>> and std::stack<T, deque<T>>
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIcSaIcEEC2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIcSaIcEED2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIcSaIcEE15_M_create_nodesEPPcS3_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIcSaIcEE16_M_destroy_nodesEPPcS3_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIcSaIcEE17_M_initialize_mapEj),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIdSaIdEEC2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIdSaIdEED2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIdSaIdEE15_M_create_nodesEPPdS3_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIdSaIdEE16_M_destroy_nodesEPPdS3_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseIdSaIdEE17_M_initialize_mapEj),
{ "_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EEC2Ev", (void*)&construct_deque_string },
{ "_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EEC2EOS7_", (void*)&move_construct_deque_string },
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED2Ev),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_create_nodesEPPS5_S9_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_destroy_nodesEPPS5_S9_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_initialize_mapEj),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_Deque_impl_dataC1EOS8_),
DEFINE_MODULE_SYMBOL(_ZNSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_Deque_impl_dataC1ERKS8_),
DEFINE_MODULE_SYMBOL(_ZSt4swapINSt11_Deque_baseINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EE16_Deque_impl_dataEENSt9enable_ifIXsrSt6__and_IJSt6__not_ISt15__is_tuple_likeIT_EESt21is_move_constructibleISE_ESt18is_move_assignableISE_EEE5valueEvE4typeERSE_SO_),
{ "_ZNSt15_Deque_iteratorIcRcPcEmmEv", (void*)&decrement_deque_iterator_char },
{ "_ZNSt15_Deque_iteratorIdRdPdEmmEv", (void*)&decrement_deque_iterator_double },
{ "_ZNSt15_Deque_iteratorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS5_PS5_EmmEv", (void*)&decrement_deque_iterator_string },
{ "_ZStmiRKSt15_Deque_iteratorIcRcPcES4_", (void*)&subtract_deque_iterators_char },
{ "_ZStmiRKSt15_Deque_iteratorIdRdPdES4_", (void*)&subtract_deque_iterators_double },
{ "_ZStmiRKSt15_Deque_iteratorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS5_PS5_ESA_", (void*)&subtract_deque_iterators_string },
{ "_ZNSt5dequeIcSaIcEED1Ev", (void*)&destroy_deque_char },
{ "_ZNSt5dequeIcSaIcEE4backEv", (void*)&back_of_deque_char },
{ "_ZNSt5dequeIcSaIcEE8pop_backEv", (void*)&pop_back_deque_char },
{ "_ZNSt5dequeIcSaIcEE9push_backERKc", (void*)&push_back_deque_char },
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIcSaIcEE15_M_pop_back_auxEv),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIcSaIcEE16_M_push_back_auxIJRKcEEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIcSaIcEE16_M_push_back_auxIJcEEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIcSaIcEE17_M_reallocate_mapEjb),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIcSaIcEE22_M_reserve_map_at_backEj),
{ "_ZNSt5dequeIcSaIcEE12emplace_backIJcEEERcDpOT_", (void*)&emplace_back_deque_char },
{ "_ZNSt5dequeIdSaIdEED1Ev", (void*)&destroy_deque_double },
{ "_ZNSt5dequeIdSaIdEE4backEv", (void*)&back_of_deque_double },
{ "_ZNSt5dequeIdSaIdEE8pop_backEv", (void*)&pop_back_deque_double },
{ "_ZNSt5dequeIdSaIdEE9push_backERKd", (void*)&push_back_deque_double },
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIdSaIdEE15_M_pop_back_auxEv),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIdSaIdEE16_M_push_back_auxIJRKdEEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIdSaIdEE16_M_push_back_auxIJdEEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIdSaIdEE17_M_reallocate_mapEjb),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeIdSaIdEE22_M_reserve_map_at_backEj),
{ "_ZNSt5dequeIdSaIdEE12emplace_backIJdEEERdDpOT_", (void*)&emplace_back_deque_double },
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED1Ev", (void*)&destroy_deque_string },
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE4backEv", (void*)&back_of_deque_string },
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE5clearEv", (void*)&clear_deque_string },
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE9pop_frontEv", (void*)&pop_front_deque_string },
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE9push_backERKS5_", (void*)&push_back_deque_string },
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_pop_front_auxEv),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_push_back_auxIJRKS5_EEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE16_M_push_back_auxIJS5_EEEvDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_reallocate_mapEjb),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE22_M_reserve_map_at_backEj),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_destroy_dataESt15_Deque_iteratorIS5_RS5_PS5_ESB_RKS6_),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE15_M_erase_at_endESt15_Deque_iteratorIS5_RS5_PS5_E),
DEFINE_MODULE_SYMBOL(_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE19_M_destroy_data_auxESt15_Deque_iteratorIS5_RS5_PS5_ESB_),
{ "_ZNSt5dequeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12emplace_backIJS5_EEERS5_DpOT_", (void*)&emplace_back_deque_string },
{ "_ZNSt5stackIcSt5dequeIcSaIcEEEC1IS2_vEEv", (void*)&construct_stack_char },
{ "_ZNSt5stackIdSt5dequeIdSaIdEEEC1IS2_vEEv", (void*)&construct_stack_double },
// std::vector<const char*> / vector<pair<string,bool>> internals
DEFINE_MODULE_SYMBOL(_ZNKSt6vectorIPKcSaIS1_EE12_M_check_lenEjS1_),
{ "_ZNSt12_Vector_baseIPKcSaIS1_EED2Ev", (void*)&destroy_vector_base_of_cstrs },
{ "_ZNSt6vectorIPKcSaIS1_EE12_Guard_allocD1Ev", (void*)&(destroy_guard_alloc<const char*>) },
{ "_ZNSt6vectorIPKcSaIS1_EE12emplace_backIJS1_EEERS1_DpOT_", (void*)&emplace_back_cstr_vector },
{ "_ZNSt6vectorIPKcSaIS1_EE17_M_realloc_appendIJS1_EEEvDpOT_", (void*)&realloc_append_cstr_vector },
{ "_ZNSt6vectorIPKcSaIS1_EE4backEv", (void*)&back_of_cstr_vector },
{ "_ZNSt6vectorIPKcSaIS1_EE7reserveEj", (void*)&reserve_cstr_vector },
{ "_ZNSt15__new_allocatorIPKcE8allocateEjPKv", (void*)&allocate_cstr_storage },
DEFINE_MODULE_SYMBOL(_ZNKSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE12_M_check_lenEjPKc),
{ "_ZNKSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE5emptyEv", (void*)&empty_string_bool_pair_vector },
{ "_ZNSt12_Vector_baseISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EED2Ev", (void*)&destroy_vector_base_of_string_bool_pairs },
{ "_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE12_Guard_allocD1Ev", (void*)&(destroy_guard_alloc<StringBoolPair>) },
{ "_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE12emplace_backIJS7_EEERS7_DpOT_", (void*)&emplace_back_string_bool_pair_vector },
DEFINE_MODULE_SYMBOL(_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE15_M_erase_at_endEPS7_),
{ "_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE17_M_realloc_appendIJS7_EEEvDpOT_", (void*)&realloc_append_string_bool_pair_vector },
DEFINE_MODULE_SYMBOL(_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EE4backEv),
{ "_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESaIS7_EED1Ev", (void*)&destroy_vector_of_string_bool_pairs },
{ "_ZNSt15__new_allocatorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbEE8allocateEjPKv", (void*)&allocate_string_bool_pair_storage },
{ "_ZNSt15__new_allocatorIPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE8allocateEjPKv", (void*)&allocate_string_ptr_storage },
{ "_ZNSt15__new_allocatorIPcE8allocateEjPKv", (void*)&allocate_char_ptr_storage },
{ "_ZNSt15__new_allocatorIPdE8allocateEjPKv", (void*)&allocate_double_ptr_storage },
// std::_Rb_tree<string, pair<const string,string>, ...> - std::map<string,string> internals
DEFINE_MODULE_SYMBOL(_ZNKSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_lower_boundEPSt18_Rb_tree_node_baseSG_RS7_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE10_Auto_node9_M_insertES6_IPSt18_Rb_tree_node_baseSH_E),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE10_Auto_nodeD1Ev),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE11lower_boundERS7_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE12_M_drop_nodeEPSt13_Rb_tree_nodeIS8_E),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_create_nodeIJRKSt21piecewise_construct_tSt5tupleIJOS5_EESJ_IJEEEEEPSt13_Rb_tree_nodeIS8_EDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_create_nodeIJRKSt21piecewise_construct_tSt5tupleIJRS7_EESJ_IJEEEEEPSt13_Rb_tree_nodeIS8_EDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE14_M_insert_nodeEPSt18_Rb_tree_node_baseSG_PSt13_Rb_tree_nodeIS8_E),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJOS5_EESJ_IJEEEEESt17_Rb_tree_iteratorIS8_ESt23_Rb_tree_const_iteratorIS8_EDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS7_EESJ_IJEEEEESt17_Rb_tree_iteratorIS8_ESt23_Rb_tree_const_iteratorIS8_EDpOT_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE24_M_get_insert_unique_posERS7_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS7_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE4findERS7_),
DEFINE_MODULE_SYMBOL(_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE8_M_eraseEPSt13_Rb_tree_nodeIS8_E),
// std::map<string,string>::operator[] + its map-node piecewise-construct path
DEFINE_MODULE_SYMBOL(_ZNSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St4lessIS5_ESaISt4pairIKS5_S5_EEEixEOS5_),
DEFINE_MODULE_SYMBOL(_ZNSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St4lessIS5_ESaISt4pairIKS5_S5_EEEixERS9_),
DEFINE_MODULE_SYMBOL(_ZNSt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_EC1IJRS6_EJEEESt21piecewise_construct_tSt5tupleIJDpT_EESB_IJDpT0_EE),
{ "_ZSt19piecewise_construct", (void*)&std::piecewise_construct },
// std::shared_ptr<T> control block - generic; see the comment above assign_shared_count_atomic
// for why the raw-pointer constructor itself is deliberately not registered here.
{ "_ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE1EEaSERKS2_", (void*)&assign_shared_count_atomic },
{ "_ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEaSERKS2_", (void*)&assign_shared_count_mutex },
DEFINE_MODULE_SYMBOL(_ZTVSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE),
DEFINE_MODULE_SYMBOL(_ZTVSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE10_M_destroyEv),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE10_M_releaseEv),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE19_M_release_last_useEv),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_releaseEv),
DEFINE_MODULE_SYMBOL(_ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE19_M_release_last_useEv),
// std::function<int(char*, unsigned int)>
{ "_ZNKSt8functionIFiPcjEEclES0_j", (void*)&call_char_buffer_fn },
{ "_ZNSt8functionIFiPcjEE4swapERS2_", (void*)&swap_char_buffer_fn },
{ "_ZNSt8functionIFiPcjEEC1ERKS2_", (void*)&construct_char_buffer_fn_copy },
{ "_ZNSt8functionIFiPcjEEaSEDn", (void*)&assign_char_buffer_fn_nullptr },
// Misc algorithm/iterator template instantiations
{ "_ZSt14__copy_move_a2ILb0EPPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_S7_ET2_T0_T1_S8_", (void*)&copy_move_a2_string_ptr },
{ "_ZSt14__copy_move_a2ILb0EPPcS1_S1_ET2_T0_T1_S2_", (void*)&copy_move_a2_char_ptr },
{ "_ZSt14__copy_move_a2ILb0EPPdS1_S1_ET2_T0_T1_S2_", (void*)&copy_move_a2_double_ptr },
{ "_ZSt14__relocate_a_1IPSt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbES8_SaIS7_EET0_T_SB_SA_RT1_", (void*)&relocate_string_bool_pairs },
{ "_ZSt23__copy_move_backward_a2ILb0EPPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ET1_T0_S9_S8_", (void*)&copy_move_backward_a2_string_ptr },
{ "_ZSt23__copy_move_backward_a2ILb0EPPcS1_ET1_T0_S3_S2_", (void*)&copy_move_backward_a2_char_ptr },
{ "_ZSt23__copy_move_backward_a2ILb0EPPdS1_ET1_T0_S3_S2_", (void*)&copy_move_backward_a2_double_ptr },
{ "_ZSt23__copy_move_backward_a2ILb1EPSt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbES8_ET1_T0_SA_S9_", (void*)&move_backward_string_bool_pairs },
{ "_ZSt3maxIsET_St16initializer_listIS0_E", (void*)&max_short_init_list },
{ "_ZSt3minIsET_St16initializer_listIS0_E", (void*)&min_short_init_list },
{ "_ZSt9__advanceIPPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiEvRT_T0_St26random_access_iterator_tag", (void*)&advance_string_ptr_ptr },
{ "_ZSt9__advanceIPPciEvRT_T0_St26random_access_iterator_tag", (void*)&advance_char_ptr_ptr },
{ "_ZSt9__advanceIPPdiEvRT_T0_St26random_access_iterator_tag", (void*)&advance_double_ptr_ptr },
{ "_ZSt9iter_swapIN9__gnu_cxx17__normal_iteratorIPSt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbESt6vectorIS9_SaIS9_EEEESE_EvT_T0_", (void*)&iter_swap_string_bool_pair_vector },
{ "_ZSt9transformIN9__gnu_cxx17__normal_iteratorIPcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEES9_PFiiEET0_T_SD_SC_T1_", (void*)&transform_char_to_upper },
{ "_ZSt4swapISt9_Any_dataENSt9enable_ifIXsrSt6__and_IJSt6__not_ISt15__is_tuple_likeIT_EESt21is_move_constructibleIS5_ESt18is_move_assignableIS5_EEE5valueEvE4typeERS5_SF_", (void*)&swap_any_data },
#endif
#endif // TT_CPP_SYMBOLS_AVAILABLE
MODULE_SYMBOL_TERMINATOR

View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.20)
include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake")
file(GLOB_RECURSE SOURCE_FILES "source/*.c*")
tactility_add_module(font-module
SRCS ${SOURCE_FILES}
INCLUDE_DIRS include/
REQUIRES TactilityKernel
)

View File

@ -0,0 +1,32 @@
menu "Fonts"
config TT_FONT_IBMPLEXMONO_12
bool "IBM Plex Mono 12 (7x12)"
default n
help
Include the ibmplexmono12 bitmap font.
config TT_FONT_IBMPLEXMONO_14
bool "IBM Plex Mono 14 (8x14)"
default n
help
Include the ibmplexmono14 bitmap font.
config TT_FONT_IBMPLEXMONO_16
bool "IBM Plex Mono 16 (10x16)"
default n
help
Include the ibmplexmono16 bitmap font.
config TT_FONT_IBMPLEXMONO_18
bool "IBM Plex Mono 18 (11x18)"
default n
help
Include the ibmplexmono18 bitmap font.
config TT_FONT_IBMPLEXMONO_24
bool "IBM Plex Mono 24 (14x24)"
default n
help
Include the ibmplexmono24 bitmap font.
config TT_FONT_IBMPLEXMONO_28
bool "IBM Plex Mono 28 (17x28)"
default n
help
Include the ibmplexmono28 bitmap font.
endmenu

View File

@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.

View File

@ -0,0 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* A fixed-width bitmap font: monospaced glyphs covering a contiguous codepoint range, one row of
* glyph_bytes_per_row bytes per pixel row (bit 7 of the first byte is the leftmost pixel).
*
* glyph_bitmap is indexed as glyph_bitmap[(ch - first_codepoint) * glyph_height *
* glyph_bytes_per_row + row * glyph_bytes_per_row + byte]; a codepoint outside
* [first_codepoint, last_codepoint] has no entry.
*/
typedef struct FixedWidthFont {
uint8_t glyph_width;
uint8_t glyph_height;
uint8_t glyph_bytes_per_row;
uint8_t first_codepoint;
uint8_t last_codepoint;
const uint8_t* glyph_bitmap;
} FixedWidthFont;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
// Every font generate-all.py produces, so a caller can pull them all in with one include.
#include <font/ibmplexmono12.h>
#include <font/ibmplexmono14.h>
#include <font/ibmplexmono16.h>
#include <font/ibmplexmono18.h>
#include <font/ibmplexmono24.h>
#include <font/ibmplexmono28.h>

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_12_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_14_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_16_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_18_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_24_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const FixedWidthFont ibmplexmono_28_font;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <tactility/module.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct Module font_module;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <font/font.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Renders one character's glyph into buffer, a caller-owned RGB565 pixel buffer laid out as
* `stride` pixels per row. The glyph occupies a font->glyph_width x font->glyph_height box
* starting at buffer's first pixel - buffer must already point at that box's top-left corner
* within the larger destination image. A character outside [first_codepoint, last_codepoint]
* renders as a space.
*/
void font_render_char(const FixedWidthFont* font, char ch, uint16_t fg, uint16_t bg, uint16_t* buffer, int stride);
/**
* Renders a null-terminated string left to right, one font_render_char() call per character,
* each advanced by font->glyph_width pixels from the last. buffer must point at the first
* character's top-left corner; the string occupies strlen(str) * font->glyph_width x
* font->glyph_height pixels in total.
*/
void font_render_string(const FixedWidthFont* font, const char* str, uint16_t fg, uint16_t bg, uint16_t* buffer, int stride);
/** Pixel width font_render_string() would occupy for str: strlen(str) * font->glyph_width. */
int font_get_string_length(const FixedWidthFont* font, const char* str);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1 @@
*.ttf

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""
Generates bitmap font files (see generate.py) for a fixed set of glyph heights, from the same
monospace TTF.
Requires the freetype-py package: pip install freetype-py
Usage:
python3 generate-all.py
"""
import importlib.util
import os
MONO_URL = "https://github.com/google/fonts/raw/refs/heads/main/ofl/ibmplexmono/IBMPlexMono-Regular.ttf"
SIZES = [12, 14, 16, 18, 24, 28]
spec = importlib.util.spec_from_file_location("generate_font", os.path.join(os.path.dirname(__file__), "generate.py"))
generate_font = importlib.util.module_from_spec(spec)
spec.loader.exec_module(generate_font)
def write_fonts_header(outputs: list):
path = os.path.join(generate_font.INCLUDE_DIR, "fonts.h")
print(f"Generating {path}")
with open(path, "w") as f:
f.write("// SPDX-License-Identifier: Apache-2.0\n")
f.write("#pragma once\n\n")
f.write("// Every font generate-all.py produces, so a caller can pull them all in with one include.\n")
for output in outputs:
f.write(f"#include <font/{output}.h>\n")
if __name__ == "__main__":
outputs = [f"ibmplexmono{size}" for size in SIZES]
for output, size in zip(outputs, SIZES):
generate_font.generate(MONO_URL, size, output)
write_fonts_header(outputs)

View File

@ -0,0 +1,190 @@
#!/usr/bin/env python3
"""
Downloads a monospace TTF and rasterizes it into a FixedWidthFont (see include/font/font.h) covering:
- U+0020-U+007E
- Height rows per glyph
- Each row ceil(width / 8)
- Bytes (bit 7 of the first byte = leftmost pixel)
Plus a header declaring the font. Glyph width is the font's own natural advance width at the given size.
Requires the freetype-py package: pip install freetype-py
Usage:
python3 generate.py --url URL --size SIZE --output NAME
"""
import argparse
import math
import os
import re
import urllib.request
import freetype
GLYPH_FIRST = 0x20
GLYPH_LAST = 0x7E
MODULE_DIR = os.path.join(os.path.dirname(__file__), "..")
SOURCE_DIR = os.path.join(MODULE_DIR, "source")
INCLUDE_DIR = os.path.join(MODULE_DIR, "include", "font")
def download_file(url: str, filename: str):
if not os.path.exists(filename):
print(f"Downloading {filename} from {url}")
urllib.request.urlretrieve(url, filename)
else:
print(f"{filename} already exists, skipping download.")
def measure_advance_width(face: freetype.Face, size: int) -> float:
"""Natural advance width (px) of the font at `size` px tall, isotropic DPI."""
face.set_char_size(0, size * 64, 72, 72)
face.load_char("M", freetype.FT_LOAD_DEFAULT)
return face.glyph.advance.x / 64
def get_bit(bitmap, x: int, y: int) -> bool:
if x < 0 or x >= bitmap.width or y < 0 or y >= bitmap.rows:
return False
byte = bitmap.buffer[y * abs(bitmap.pitch) + x // 8]
return bool((byte >> (7 - x % 8)) & 1)
def measure_baseline(face: freetype.Face, cell_height: int) -> int:
"""
Row (from the cell top) the baseline sits on.
face.size.ascender/descender are line-spacing metrics, not ink extents - many fonts set them
taller than the glyphs actually are, which pushes the baseline row below the bottom of the
cell and clips it off entirely. Measuring the real cap-height ('A') and descender depth ('g')
at this pixel size keeps both in view instead.
"""
face.load_char("A", freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO)
cap_top = face.glyph.bitmap_top
face.load_char("g", freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO)
descender = face.glyph.bitmap.rows - face.glyph.bitmap_top
max_baseline = cell_height - 1 - descender
if max_baseline >= cap_top:
baseline = cap_top + (max_baseline - cap_top) // 2
else:
# Cap height and descender depth don't both fit in cell_height rows (common at very
# small sizes) - keep the cap/baseline row intact and let the descender clip instead.
baseline = cap_top
return min(max(baseline, 0), cell_height - 1)
def render_glyph(face: freetype.Face, codepoint: int, cell_width: int, cell_height: int, baseline_y: int, bytes_per_row: int) -> bytearray:
face.load_char(chr(codepoint), freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO)
glyph = face.glyph
bitmap = glyph.bitmap
out = bytearray(cell_height * bytes_per_row)
for row in range(cell_height):
src_y = row - baseline_y + glyph.bitmap_top
for col in range(cell_width):
src_x = col - glyph.bitmap_left
if get_bit(bitmap, src_x, src_y):
out[row * bytes_per_row + col // 8] |= 1 << (7 - col % 8)
return out
def split_name(output: str) -> tuple:
"""'ibmplexmono14' -> ('ibmplexmono', '14'), so identifiers can put an underscore between the
font name and its size instead of running them together."""
match = re.match(r"^([a-zA-Z]+)(\d+)$", output)
if not match:
raise ValueError(f"'{output}' must be a name followed by digits, e.g. 'ibmplexmono14'")
return match.group(1), match.group(2)
def escape_char(ch: str) -> str:
if ch == "\\":
return "\\\\"
if ch == '"':
return '\\"'
return ch
def write_c_file(path: str, output: str, width: int, height: int, bytes_per_row: int, glyphs: dict):
glyph_count = GLYPH_LAST - GLYPH_FIRST + 1
glyph_bytes = height * bytes_per_row
total_bytes = glyph_count * glyph_bytes
name, size_digits = split_name(output)
bitmap_name = f"{output}_glyph_bitmap"
struct_name = f"{name}_{size_digits}_font"
config_macro = f"CONFIG_TT_FONT_{name.upper()}_{size_digits}"
with open(path, "w") as f:
f.write(f"/*\n * {os.path.basename(path)} - {output} FixedWidthFont\n")
f.write(f" *\n * Rasterized from a TTF with Modules/font-module/scripts/generate.py.\n")
f.write(f" * Each glyph is {width} pixels wide and {height} pixels tall, stored as {height} rows of\n")
f.write(f" * {bytes_per_row} byte{'s' if bytes_per_row != 1 else ''} each (bit 7 of the first byte = leftmost pixel).\n */\n\n")
f.write(f"#include <font/{output}.h>\n\n")
f.write("#ifdef ESP_PLATFORM\n")
f.write("#include <sdkconfig.h>\n")
f.write("#endif\n\n")
f.write(f"// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating\n")
f.write(f"// this font's Kconfig entry) is treated the same as enabled.\n")
f.write(f"#if !defined({config_macro}) || {config_macro}\n\n")
f.write(f"// Glyph bitmap data: {glyph_count} characters (0x20-0x7E), {glyph_bytes} bytes each = {total_bytes} bytes\n")
f.write(f"static const uint8_t {bitmap_name}[] = {{\n")
for cp in range(GLYPH_FIRST, GLYPH_LAST + 1):
f.write(f' /* U+{cp:04X} "{escape_char(chr(cp))}" */\n')
data = glyphs[cp]
f.write(" " + ", ".join(f"0x{b:X}" for b in data) + ",\n")
f.write("};\n\n")
f.write(f"const FixedWidthFont {struct_name} = {{\n")
f.write(f" .glyph_width = {width},\n")
f.write(f" .glyph_height = {height},\n")
f.write(f" .glyph_bytes_per_row = {bytes_per_row},\n")
f.write(f" .first_codepoint = 0x{GLYPH_FIRST:02X},\n")
f.write(f" .last_codepoint = 0x{GLYPH_LAST:02X},\n")
f.write(f" .glyph_bitmap = {bitmap_name},\n")
f.write("};\n\n")
f.write(f"#endif // {config_macro}\n")
def write_h_file(path: str, output: str):
name, size_digits = split_name(output)
struct_name = f"{name}_{size_digits}_font"
with open(path, "w") as f:
f.write("// SPDX-License-Identifier: Apache-2.0\n")
f.write("#pragma once\n\n")
f.write("#include <font/font.h>\n\n")
f.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n")
f.write(f"extern const FixedWidthFont {struct_name};\n\n")
f.write("#ifdef __cplusplus\n}\n#endif\n")
def generate(mono_url: str, size: int, output: str):
ttf_filename = os.path.basename(mono_url)
download_file(mono_url, ttf_filename)
face = freetype.Face(ttf_filename)
natural_width = measure_advance_width(face, size)
if natural_width <= 0:
raise RuntimeError("Font reported a non-positive advance width")
width = round(natural_width)
bytes_per_row = math.ceil(width / 8)
baseline_y = measure_baseline(face, size)
glyphs = {cp: render_glyph(face, cp, width, size, baseline_y, bytes_per_row) for cp in range(GLYPH_FIRST, GLYPH_LAST + 1)}
c_path = os.path.join(SOURCE_DIR, f"{output}.c")
h_path = os.path.join(INCLUDE_DIR, f"{output}.h")
print(f"Generating {h_path}")
write_h_file(h_path, output)
print(f"Generating {c_path}")
write_c_file(c_path, output, width, size, bytes_per_row, glyphs)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--url", required=True, help="URL of the monospace TTF to download")
parser.add_argument("--size", type=int, required=True, help="Glyph height in pixels")
parser.add_argument("--output", required=True, help="Output file base name (no extension)")
args = parser.parse_args()
generate(args.url, args.size, args.output)

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono12.c - ibmplexmono12 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 7 pixels wide and 12 pixels tall, stored as 12 rows of
* 1 byte each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono12.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_12) || CONFIG_TT_FONT_IBMPLEXMONO_12
// Glyph bitmap data: 95 characters (0x20-0x7E), 12 bytes each = 1140 bytes
static const uint8_t ibmplexmono12_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0x28, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0x34, 0x28, 0x6E, 0x28, 0x28, 0xEC, 0x48, 0x50, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0x38, 0x56, 0x50, 0x70, 0x1C, 0x12, 0xD4, 0x3C, 0x10, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x62, 0x94, 0x94, 0x68, 0x2C, 0x52, 0x52, 0x8C, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0x30, 0x48, 0x40, 0x26, 0x74, 0x98, 0x8C, 0x76, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0xC, 0x0, 0x0,
/* U+0029 ")" */
0x20, 0x10, 0x10, 0x8, 0x8, 0x8, 0x10, 0x10, 0x20, 0x60, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x10, 0x10, 0xFE, 0x10, 0x28, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x10, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x10, 0x10, 0x20, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x4, 0x8, 0x8, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x0, 0x0,
/* U+0030 "0" */
0x38, 0x44, 0x44, 0x54, 0x54, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0x30, 0x70, 0x50, 0x10, 0x10, 0x10, 0x10, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0x38, 0x44, 0x4, 0x4, 0x8, 0x30, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0x38, 0x44, 0x4, 0x38, 0xC, 0x4, 0xC4, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0x8, 0x18, 0x28, 0x48, 0x48, 0xFE, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x7C, 0x40, 0x40, 0x78, 0x44, 0x4, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0x18, 0x20, 0x40, 0x78, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x7C, 0x44, 0x4, 0x8, 0x8, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0x3C, 0x44, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0x38, 0x44, 0x44, 0x44, 0x3C, 0x4, 0x8, 0x30, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x18, 0x10, 0x10, 0x20, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x4, 0x8, 0x30, 0x40, 0x30, 0x8, 0x4, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x7C, 0x0, 0x7C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x40, 0x20, 0x18, 0x4, 0x18, 0x20, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x38, 0x44, 0x4, 0x18, 0x10, 0x0, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x38, 0x44, 0x5C, 0x54, 0x64, 0x64, 0x5C, 0x40, 0x38, 0x0, 0x0, 0x0,
/* U+0041 "A" */
0x10, 0x28, 0x28, 0x28, 0x44, 0x7C, 0x44, 0xC6, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0x38, 0x44, 0x40, 0x40, 0x40, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x7C, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x7C, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x38, 0x44, 0x40, 0x40, 0x5C, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0x3C, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4C, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x46, 0x48, 0x58, 0x50, 0x78, 0x48, 0x44, 0x46, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x44, 0x6C, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x44, 0x64, 0x64, 0x54, 0x54, 0x4C, 0x4C, 0x4C, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x7C, 0x44, 0x44, 0x44, 0x7C, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x10, 0x1C, 0x0, 0x0,
/* U+0052 "R" */
0x7C, 0x44, 0x44, 0x44, 0x7C, 0x48, 0x48, 0x46, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0x38, 0x44, 0x40, 0x70, 0xC, 0x4, 0xC4, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0xC6, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x82, 0x82, 0x94, 0xB4, 0x6C, 0x6C, 0x6C, 0x6C, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0xC6, 0x44, 0x28, 0x10, 0x18, 0x28, 0x44, 0xC6, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0xC2, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x7C, 0x4, 0x8, 0x10, 0x30, 0x20, 0x40, 0xFC, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x0, 0x0,
/* U+005C "\\" */
0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x8, 0x8, 0x8, 0x4, 0x0, 0x0,
/* U+005D "]" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x0, 0x0,
/* U+005E "^" */
0x10, 0x28, 0x28, 0x44, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7C, 0x0, 0x0,
/* U+0060 "`" */
0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x38, 0x4C, 0x4, 0x7C, 0x44, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x78, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x38, 0x44, 0x40, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x4, 0x4, 0x34, 0x4C, 0x44, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x38, 0x44, 0x7C, 0x40, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x6, 0x38, 0x44, 0x44, 0x38, 0x40, 0x3C, 0x42, 0x7C, 0x0, 0x0,
/* U+0068 "h" */
0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0x18, 0x0, 0x70, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0x8, 0x0, 0x78, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x78, 0x0, 0x0,
/* U+006B "k" */
0x40, 0x40, 0x46, 0x48, 0x50, 0x68, 0x4C, 0x46, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x6C, 0x54, 0x54, 0x54, 0x54, 0x54, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x58, 0x64, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x34, 0x4C, 0x44, 0x44, 0x44, 0x3C, 0x4, 0x4, 0x0, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x7E, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x38, 0x44, 0x70, 0xC, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x20, 0x1C, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x44, 0x44, 0x44, 0x44, 0x44, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x92, 0xB2, 0xAC, 0x6C, 0x6C, 0x6C, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x44, 0x44, 0x28, 0x28, 0x30, 0x10, 0x10, 0x60, 0x0, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x7C, 0xC, 0x10, 0x20, 0x40, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0x10, 0x10, 0x10, 0x8, 0x70, 0x18, 0x10, 0x10, 0x10, 0x1C, 0x0, 0x0,
/* U+007C "|" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0,
/* U+007D "}" */
0x10, 0x10, 0x20, 0x20, 0x1C, 0x30, 0x20, 0x10, 0x10, 0x70, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x64, 0x54, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_12_font = {
.glyph_width = 7,
.glyph_height = 12,
.glyph_bytes_per_row = 1,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono12_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_12

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono14.c - ibmplexmono14 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 8 pixels wide and 14 pixels tall, stored as 14 rows of
* 1 byte each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono14.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_14) || CONFIG_TT_FONT_IBMPLEXMONO_14
// Glyph bitmap data: 95 characters (0x20-0x7E), 14 bytes each = 1330 bytes
static const uint8_t ibmplexmono14_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0x18, 0x18, 0x18, 0x18, 0x10, 0x10, 0x10, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0x24, 0x24, 0x24, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0x12, 0x14, 0x14, 0x67, 0x24, 0x24, 0xE6, 0x28, 0x28, 0x48, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0x3C, 0x4A, 0x49, 0x48, 0x38, 0xE, 0xA, 0xB, 0x4A, 0x3C, 0x8, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x71, 0x92, 0x92, 0x94, 0x70, 0xE, 0x29, 0x49, 0x49, 0x8E, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0x38, 0x44, 0x40, 0x40, 0x23, 0x52, 0x8C, 0x8C, 0xC6, 0x7B, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x8, 0x8, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x8, 0x8, 0x6, 0x0, 0x0,
/* U+0029 ")" */
0x10, 0x10, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x10, 0x10, 0x60, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x0, 0x18, 0x18, 0x5A, 0xBD, 0x18, 0x24, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x0, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x10, 0x10, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x0, 0x0,
/* U+0030 "0" */
0x3C, 0x66, 0x42, 0x42, 0x5A, 0x5A, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0x18, 0x28, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x7F, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0x3C, 0x46, 0x42, 0x2, 0x6, 0xC, 0x18, 0x30, 0x60, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0x3C, 0x46, 0x2, 0x4, 0x38, 0x6, 0x2, 0x2, 0xC6, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0xC, 0xC, 0x14, 0x24, 0x24, 0x44, 0x44, 0xFF, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x7E, 0x40, 0x40, 0x40, 0x5C, 0x66, 0x2, 0x2, 0x46, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0xC, 0x10, 0x20, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x7E, 0x42, 0x46, 0x4, 0x4, 0x8, 0x8, 0x18, 0x10, 0x30, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0x3C, 0x42, 0x42, 0x42, 0x3C, 0x66, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0x3C, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x2, 0x4, 0x8, 0x30, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x10, 0x10, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x0, 0x2, 0xC, 0x18, 0x60, 0x60, 0x18, 0xE, 0x2, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x0, 0x7E, 0x0, 0x0, 0x7E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x0, 0x40, 0x70, 0x18, 0x6, 0x6, 0x18, 0x30, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x3C, 0x66, 0x42, 0x2, 0x4, 0x18, 0x10, 0x0, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x3C, 0x66, 0x42, 0x4E, 0x52, 0x52, 0x52, 0x52, 0x5E, 0x40, 0x60, 0x3C, 0x0, 0x0,
/* U+0041 "A" */
0x18, 0x18, 0x3C, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x7C, 0x42, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0x3C, 0x22, 0x42, 0x40, 0x40, 0x40, 0x40, 0x44, 0x22, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x7C, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x7C, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x7E, 0x40, 0x40, 0x40, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x7E, 0x40, 0x40, 0x40, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x3C, 0x66, 0x44, 0x40, 0x40, 0x4E, 0x42, 0x42, 0x66, 0x3A, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0x3E, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x44, 0x38, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x43, 0x46, 0x4C, 0x48, 0x58, 0x68, 0x4C, 0x44, 0x42, 0x43, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x42, 0x66, 0x66, 0x5A, 0x5A, 0x5A, 0x52, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x62, 0x62, 0x72, 0x52, 0x52, 0x4A, 0x4A, 0x4A, 0x46, 0x46, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x3C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x3C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x18, 0xE, 0x0, 0x0,
/* U+0052 "R" */
0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x46, 0x43, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0x3C, 0x42, 0x40, 0x40, 0x78, 0xE, 0x2, 0x2, 0xC2, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0xC3, 0x42, 0x42, 0x62, 0x24, 0x24, 0x24, 0x3C, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x81, 0x81, 0xC1, 0x5A, 0x5A, 0x5A, 0x5A, 0x66, 0x66, 0x66, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0xC3, 0x62, 0x24, 0x1C, 0x18, 0x18, 0x3C, 0x24, 0x42, 0xC3, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0xC3, 0x42, 0x66, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x7E, 0x2, 0x4, 0x8, 0x18, 0x10, 0x20, 0x60, 0x40, 0xFE, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x0, 0x0,
/* U+005C "\\" */
0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x8, 0x8, 0x4, 0x4, 0x4, 0x2, 0x0, 0x0,
/* U+005D "]" */
0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x78, 0x0, 0x0,
/* U+005E "^" */
0x18, 0x18, 0x24, 0x66, 0x42, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x0, 0x0,
/* U+0060 "`" */
0x30, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x0, 0x3C, 0x44, 0x6, 0x7E, 0x46, 0x4A, 0x7B, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x40, 0x40, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x62, 0x5C, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x0, 0x3C, 0x62, 0x40, 0x40, 0x40, 0x62, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x2, 0x2, 0x2, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x0, 0x3C, 0x66, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0xE, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x0, 0x3, 0x3C, 0x66, 0x42, 0x66, 0x3C, 0x40, 0x3E, 0x43, 0x43, 0x7E, 0x0,
/* U+0068 "h" */
0x40, 0x40, 0x40, 0x5C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0x8, 0x8, 0x0, 0x78, 0x8, 0x8, 0x8, 0x8, 0x8, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0xC, 0xC, 0x0, 0x7C, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x78, 0x0,
/* U+006B "k" */
0x40, 0x40, 0x40, 0x43, 0x4C, 0x58, 0x78, 0x44, 0x46, 0x43, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x0, 0x76, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x0, 0x5C, 0x66, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x0, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x0, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x62, 0x5C, 0x40, 0x40, 0x40, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x2, 0x2, 0x2, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x0, 0x77, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x0, 0x3C, 0x42, 0x40, 0x3C, 0x2, 0x42, 0x3C, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x0, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3A, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x0, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x0, 0x99, 0x99, 0x5A, 0x6A, 0x66, 0x66, 0x66, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x0, 0x42, 0x24, 0x18, 0x18, 0x18, 0x24, 0x42, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x0, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x10, 0x10, 0x60, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x0, 0x7E, 0x4, 0x8, 0x18, 0x30, 0x60, 0x7E, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0x10, 0x10, 0x18, 0x8, 0x8, 0x70, 0x8, 0x8, 0x18, 0x10, 0x10, 0x1E, 0x0, 0x0,
/* U+007C "|" */
0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0,
/* U+007D "}" */
0x8, 0x8, 0x18, 0x10, 0x10, 0xE, 0x10, 0x10, 0x18, 0x8, 0x8, 0x78, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x0, 0x72, 0x5A, 0x4E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_14_font = {
.glyph_width = 8,
.glyph_height = 14,
.glyph_bytes_per_row = 1,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono14_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_14

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono16.c - ibmplexmono16 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 10 pixels wide and 16 pixels tall, stored as 16 rows of
* 2 bytes each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono16.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_16) || CONFIG_TT_FONT_IBMPLEXMONO_16
// Glyph bitmap data: 95 characters (0x20-0x7E), 32 bytes each = 3040 bytes
static const uint8_t ibmplexmono16_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0x9, 0x0, 0x9, 0x0, 0x1B, 0x0, 0x73, 0xC0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xF3, 0x80, 0x36, 0x0, 0x24, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0x1F, 0x0, 0x25, 0x80, 0x64, 0x0, 0x64, 0x0, 0x34, 0x0, 0x1F, 0x0, 0x5, 0x80, 0x4, 0x80, 0x44, 0x80, 0x65, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x70, 0xC0, 0x48, 0x80, 0xC9, 0x0, 0x4B, 0x0, 0x72, 0x0, 0x0, 0x0, 0x13, 0x80, 0x24, 0x80, 0x24, 0x80, 0x44, 0x80, 0xC3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0x1C, 0x0, 0x22, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0x0, 0x39, 0x80, 0x49, 0x0, 0x45, 0x0, 0x42, 0x0, 0x65, 0x0, 0x39, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x6, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x18, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x6, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0029 ")" */
0x18, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x18, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x4C, 0x80, 0x7F, 0x80, 0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x1, 0x0, 0x2, 0x0, 0x2, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x10, 0x0, 0x10, 0x0, 0x10, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0030 "0" */
0x1E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x61, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x40, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0x1C, 0x0, 0x34, 0x0, 0x64, 0x0, 0x44, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0x1E, 0x0, 0x23, 0x0, 0x61, 0x0, 0x1, 0x0, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x8, 0x0, 0x10, 0x0, 0x20, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0x1E, 0x0, 0x23, 0x0, 0x41, 0x0, 0x1, 0x0, 0x3, 0x0, 0x1C, 0x0, 0x3, 0x0, 0x1, 0x0, 0x41, 0x0, 0x63, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0x7, 0x0, 0x7, 0x0, 0xB, 0x0, 0x1B, 0x0, 0x13, 0x0, 0x23, 0x0, 0x23, 0x0, 0x43, 0x0, 0x7F, 0x80, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x1, 0x80, 0x1, 0x80, 0x41, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0x6, 0x0, 0x18, 0x0, 0x10, 0x0, 0x20, 0x0, 0x3E, 0x0, 0x61, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x7F, 0x80, 0x41, 0x80, 0x41, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x40, 0x80, 0x40, 0x80, 0x61, 0x80, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x80, 0x1F, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0, 0xC, 0x0, 0x30, 0x0, 0x60, 0x0, 0x30, 0x0, 0xC, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0xC, 0x0, 0x3, 0x0, 0x1, 0x80, 0x3, 0x0, 0xC, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x1E, 0x0, 0x21, 0x0, 0x61, 0x0, 0x1, 0x0, 0x3, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x1E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x67, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x49, 0x80, 0x6F, 0x80, 0x20, 0x0, 0x30, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0041 "A" */
0xC, 0x0, 0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x12, 0x0, 0x33, 0x0, 0x23, 0x0, 0x3F, 0x0, 0x61, 0x80, 0x61, 0x80, 0x40, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x3E, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x3E, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0x1E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x20, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x21, 0x0, 0x31, 0x80, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x3E, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x0, 0x23, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x1E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x67, 0x80, 0x61, 0x80, 0x61, 0x80, 0x31, 0x80, 0x1F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x7F, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x3F, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0x3F, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x23, 0x0, 0x62, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x21, 0x80, 0x23, 0x0, 0x22, 0x0, 0x24, 0x0, 0x2C, 0x0, 0x3C, 0x0, 0x36, 0x0, 0x22, 0x0, 0x23, 0x0, 0x21, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x61, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, 0x80, 0x6D, 0x80, 0x6D, 0x80, 0x6D, 0x80, 0x69, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x29, 0x80, 0x29, 0x80, 0x2D, 0x80, 0x25, 0x80, 0x27, 0x80, 0x23, 0x80, 0x23, 0x80, 0x23, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x3F, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1E, 0x0, 0xC, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0052 "R" */
0x3F, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x24, 0x0, 0x22, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0x1F, 0x0, 0x21, 0x80, 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, 0x1F, 0x0, 0x1, 0x80, 0x1, 0x80, 0x41, 0x80, 0x61, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0x40, 0x80, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x33, 0x0, 0x12, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x5E, 0x80, 0x72, 0x80, 0x73, 0x80, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0x61, 0x80, 0x21, 0x0, 0x33, 0x0, 0x1A, 0x0, 0xC, 0x0, 0xC, 0x0, 0xE, 0x0, 0x12, 0x0, 0x33, 0x0, 0x21, 0x0, 0x40, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0xC0, 0xC0, 0x61, 0x80, 0x31, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x7F, 0x80, 0x1, 0x80, 0x3, 0x0, 0x2, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x10, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005C "\\" */
0x20, 0x0, 0x10, 0x0, 0x10, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005D "]" */
0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005E "^" */
0xC, 0x0, 0x1E, 0x0, 0x12, 0x0, 0x33, 0x0, 0x21, 0x0, 0x61, 0x80, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0,
/* U+0060 "`" */
0x8, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x23, 0x0, 0x1, 0x0, 0x3F, 0x0, 0x61, 0x0, 0x61, 0x0, 0x67, 0x0, 0x3D, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x31, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x31, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1D, 0x0, 0x23, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x21, 0x80, 0x7F, 0x80, 0x60, 0x0, 0x61, 0x0, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x1E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x21, 0x0, 0x13, 0x0, 0x3E, 0x0, 0x20, 0x0, 0x1F, 0x0, 0x60, 0x80, 0x60, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0068 "h" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006B "k" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x21, 0x80, 0x22, 0x0, 0x24, 0x0, 0x2C, 0x0, 0x36, 0x0, 0x22, 0x0, 0x21, 0x0, 0x21, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5B, 0x80, 0x6C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x21, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x31, 0x0, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x21, 0x80, 0x31, 0x0, 0x2E, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1D, 0x0, 0x23, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x61, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7B, 0x80, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x20, 0x0, 0x3C, 0x0, 0x7, 0x0, 0x1, 0x80, 0x61, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0x80, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x21, 0x0, 0x23, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x12, 0x0, 0x12, 0x0, 0x12, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x4C, 0x80, 0x52, 0x80, 0x33, 0x0, 0x33, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x33, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x16, 0x0, 0x33, 0x0, 0x61, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0x80, 0x21, 0x0, 0x21, 0x0, 0x12, 0x0, 0x12, 0x0, 0x1E, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x1, 0x0, 0x2, 0x0, 0x4, 0x0, 0x8, 0x0, 0x10, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x4, 0x0, 0x38, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007C "|" */
0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007D "}" */
0x4, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x80, 0x6D, 0x80, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_16_font = {
.glyph_width = 10,
.glyph_height = 16,
.glyph_bytes_per_row = 2,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono16_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_16

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono18.c - ibmplexmono18 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 11 pixels wide and 18 pixels tall, stored as 18 rows of
* 2 bytes each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono18.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_18) || CONFIG_TT_FONT_IBMPLEXMONO_18
// Glyph bitmap data: 95 characters (0x20-0x7E), 36 bytes each = 3420 bytes
static const uint8_t ibmplexmono18_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0xC, 0x80, 0x9, 0x80, 0x9, 0x0, 0x9, 0x0, 0x79, 0xE0, 0x19, 0x0, 0x1B, 0x0, 0x13, 0x0, 0xF3, 0xC0, 0x12, 0x0, 0x32, 0x0, 0x32, 0x0, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0x1F, 0x0, 0x34, 0xC0, 0x24, 0x80, 0x64, 0x0, 0x24, 0x0, 0x34, 0x0, 0xF, 0x0, 0x4, 0xC0, 0x4, 0xC0, 0x4, 0x40, 0x44, 0xC0, 0x74, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x38, 0x60, 0x4C, 0xC0, 0xC4, 0x80, 0xC5, 0x80, 0x4D, 0x0, 0x7A, 0x0, 0x0, 0x0, 0x3, 0x80, 0x1E, 0x40, 0x34, 0x60, 0x24, 0x60, 0x66, 0x40, 0xC3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0x1E, 0x0, 0x33, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0x0, 0x10, 0x0, 0x38, 0xC0, 0x6C, 0x80, 0x46, 0x80, 0x43, 0x0, 0x41, 0x0, 0x62, 0x80, 0x3C, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0029 ")" */
0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x75, 0xC0, 0x1F, 0x0, 0xE, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x1, 0x80, 0x1, 0x0, 0x1, 0x0, 0x2, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x10, 0x0, 0x10, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0030 "0" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x6E, 0xC0, 0x6E, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0xE, 0x0, 0x1E, 0x0, 0x36, 0x0, 0x66, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0x1F, 0x0, 0x31, 0x80, 0x60, 0x80, 0x0, 0x80, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0x2, 0x0, 0x4, 0x0, 0x8, 0x0, 0x10, 0x0, 0x60, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0x1F, 0x0, 0x31, 0x80, 0x61, 0x80, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0xE, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x80, 0x40, 0x80, 0x61, 0x80, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0x3, 0x0, 0x7, 0x0, 0x5, 0x0, 0x9, 0x0, 0x19, 0x0, 0x11, 0x0, 0x31, 0x0, 0x61, 0x0, 0x41, 0x0, 0x7F, 0xC0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x0, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x20, 0x80, 0x71, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0x7, 0x0, 0xC, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x2F, 0x0, 0x71, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x7F, 0xC0, 0x60, 0xC0, 0x60, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0xE, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x31, 0xC0, 0x1E, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x1, 0x80, 0x6, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x30, 0x0, 0x1C, 0x0, 0x6, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0xC, 0x0, 0x7, 0x0, 0x1, 0x80, 0x1, 0x80, 0x7, 0x0, 0xC, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x40, 0x80, 0x1, 0x80, 0x1, 0x80, 0xF, 0x0, 0xC, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x67, 0xC0, 0x6C, 0xC0, 0x68, 0xC0, 0x68, 0xC0, 0x68, 0xC0, 0x6C, 0xC0, 0x67, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x10, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0041 "A" */
0xE, 0x0, 0xE, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x11, 0x0, 0x31, 0x80, 0x3F, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x3F, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0xF, 0x0, 0x11, 0x80, 0x30, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x20, 0x0, 0x30, 0xC0, 0x11, 0x80, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x3F, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x21, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x3F, 0xC0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x67, 0x80, 0x60, 0x80, 0x60, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x7F, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x3F, 0x80, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0x1F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x61, 0x80, 0x31, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x20, 0xC0, 0x21, 0x80, 0x21, 0x0, 0x23, 0x0, 0x26, 0x0, 0x2C, 0x0, 0x3E, 0x0, 0x36, 0x0, 0x23, 0x0, 0x21, 0x0, 0x21, 0x80, 0x20, 0xC0, 0x20, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x60, 0xC0, 0x71, 0xC0, 0x71, 0xC0, 0x7B, 0xC0, 0x6A, 0xC0, 0x6A, 0xC0, 0x64, 0xC0, 0x64, 0xC0, 0x64, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x28, 0xC0, 0x28, 0xC0, 0x2C, 0xC0, 0x24, 0xC0, 0x26, 0xC0, 0x22, 0xC0, 0x22, 0xC0, 0x23, 0xC0, 0x21, 0xC0, 0x21, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0,
/* U+0052 "R" */
0x3F, 0x0, 0x20, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x3F, 0x0, 0x26, 0x0, 0x23, 0x0, 0x23, 0x0, 0x21, 0x80, 0x20, 0x80, 0x20, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0x1F, 0x0, 0x30, 0xC0, 0x60, 0x80, 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, 0xF, 0x0, 0x1, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x40, 0xC0, 0x61, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0x40, 0x40, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x31, 0x80, 0x11, 0x0, 0x11, 0x0, 0x1B, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x4E, 0x40, 0x4A, 0x40, 0x6A, 0xC0, 0x6A, 0xC0, 0x6A, 0xC0, 0x7B, 0xC0, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x19, 0x0, 0xB, 0x0, 0xE, 0x0, 0x6, 0x0, 0xE, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0xC0, 0x60, 0x60, 0xC0, 0x30, 0x80, 0x31, 0x80, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x7F, 0xC0, 0x0, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005C "\\" */
0x30, 0x0, 0x10, 0x0, 0x10, 0x0, 0x8, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x80, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005D "]" */
0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005E "^" */
0xE, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x11, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xC0, 0x0, 0x0, 0x0, 0x0,
/* U+0060 "`" */
0xC, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x21, 0x0, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x3E, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x31, 0x80, 0x2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x11, 0x80, 0x21, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x80, 0x31, 0x80, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x1E, 0x80, 0x31, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x7F, 0xC0, 0x60, 0x0, 0x20, 0x0, 0x30, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0x7, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x7F, 0xC0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x3F, 0x80, 0x20, 0x40, 0x60, 0x40, 0x60, 0xC0, 0x3F, 0x80, 0x0, 0x0,
/* U+0068 "h" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3E, 0x0, 0x0, 0x0,
/* U+006B "k" */
0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0xC0, 0x21, 0x0, 0x26, 0x0, 0x2C, 0x0, 0x3E, 0x0, 0x33, 0x0, 0x21, 0x0, 0x21, 0x80, 0x20, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0x3C, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x59, 0x80, 0x66, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x31, 0x80, 0x20, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x31, 0x80, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x31, 0x80, 0x2F, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x20, 0x0, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x80, 0x31, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x60, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7D, 0xC0, 0xE, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0x0, 0x30, 0x80, 0x20, 0x0, 0x30, 0x0, 0x1F, 0x0, 0x0, 0x80, 0x0, 0xC0, 0x60, 0x80, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7F, 0xC0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0x8, 0x0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x80, 0x1E, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x20, 0x80, 0x31, 0x80, 0x11, 0x0, 0x11, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xA, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x40, 0x4E, 0x40, 0x4A, 0x40, 0x4A, 0x40, 0x6A, 0x40, 0x2A, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x31, 0x80, 0x1B, 0x0, 0xE, 0x0, 0x4, 0x0, 0xA, 0x0, 0x1B, 0x0, 0x31, 0x80, 0x60, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xC0, 0x20, 0x80, 0x30, 0x80, 0x31, 0x80, 0x11, 0x0, 0x1B, 0x0, 0xA, 0x0, 0xE, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x38, 0x0, 0x0, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x80, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0x4, 0x0, 0x8, 0x0, 0x18, 0x0, 0x30, 0x0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0xC, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x2, 0x0, 0x2, 0x0, 0x3C, 0x0, 0x6, 0x0, 0x2, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0xC, 0x0, 0xC, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007C "|" */
0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007D "}" */
0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0x8, 0x0, 0x8, 0x0, 0x7, 0x80, 0xC, 0x0, 0x8, 0x0, 0xC, 0x0, 0x4, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x40, 0x2C, 0x40, 0x46, 0x80, 0x43, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_18_font = {
.glyph_width = 11,
.glyph_height = 18,
.glyph_bytes_per_row = 2,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono18_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_18

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono24.c - ibmplexmono24 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 14 pixels wide and 24 pixels tall, stored as 24 rows of
* 2 bytes each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono24.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_24) || CONFIG_TT_FONT_IBMPLEXMONO_24
// Glyph bitmap data: 95 characters (0x20-0x7E), 48 bytes each = 4560 bytes
static const uint8_t ibmplexmono24_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0x6, 0x30, 0x6, 0x20, 0x6, 0x60, 0x6, 0x60, 0x4, 0x60, 0x7C, 0x7C, 0x7C, 0x7C, 0xC, 0x40, 0xC, 0xC0, 0x8, 0xC0, 0xF8, 0xF8, 0xF8, 0xF8, 0x18, 0x80, 0x19, 0x80, 0x19, 0x80, 0x11, 0x80, 0x31, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0xF, 0xC0, 0x1F, 0xF0, 0x39, 0x38, 0x31, 0x10, 0x31, 0x0, 0x31, 0x0, 0x39, 0x0, 0x1F, 0x80, 0xF, 0xE0, 0x1, 0xF0, 0x1, 0x38, 0x1, 0x18, 0x1, 0x18, 0x61, 0x18, 0x39, 0x38, 0x1F, 0xF0, 0xF, 0xC0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x3C, 0xC, 0x7E, 0x18, 0xC6, 0x10, 0xC2, 0x30, 0xC2, 0x20, 0xC6, 0x60, 0x7E, 0x40, 0x3C, 0x80, 0x0, 0x0, 0x0, 0xF0, 0xD, 0xF8, 0x19, 0x8C, 0x11, 0xC, 0x31, 0xC, 0x21, 0x8C, 0x61, 0xF8, 0xC0, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0xF, 0x0, 0x1F, 0x80, 0x38, 0xC0, 0x30, 0x80, 0x30, 0x0, 0x30, 0x0, 0x18, 0x0, 0x1C, 0x38, 0x3E, 0x38, 0x76, 0x20, 0x63, 0x20, 0xC1, 0xA0, 0xC1, 0xE0, 0xE0, 0xE0, 0x70, 0xF0, 0x7F, 0x30, 0x1E, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x0, 0xC0, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x0, 0xC0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0029 ")" */
0xC, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0xC, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x73, 0x38, 0x3F, 0xF0, 0x7, 0x80, 0x7, 0x80, 0xC, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xE0, 0xF, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x0, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0x40, 0x0, 0xC0, 0x0, 0xC0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x4, 0x0, 0xC, 0x0, 0xC, 0x0, 0x18, 0x0, 0x18, 0x0, 0x10, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0030 "0" */
0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0x7, 0x80, 0xF, 0x80, 0x1D, 0x80, 0x39, 0x80, 0x71, 0x80, 0x21, 0x80, 0x41, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0xF8, 0x3F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0xF, 0x80, 0x1F, 0xE0, 0x38, 0x60, 0x30, 0x30, 0x60, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0x0, 0xE0, 0x1, 0xC0, 0x3, 0x80, 0x7, 0x0, 0xE, 0x0, 0x18, 0x0, 0x30, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0xF, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x60, 0xF, 0xC0, 0xF, 0xC0, 0x0, 0x60, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x60, 0x30, 0x70, 0x70, 0x3F, 0xE0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0x0, 0xE0, 0x1, 0xE0, 0x3, 0x60, 0x3, 0x60, 0x6, 0x60, 0x4, 0x60, 0xC, 0x60, 0x18, 0x60, 0x18, 0x60, 0x30, 0x60, 0x20, 0x60, 0x60, 0x60, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x1F, 0xF0, 0x1F, 0xF0, 0x10, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x37, 0xC0, 0x3F, 0xE0, 0x38, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x18, 0x0, 0x38, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0x1, 0xC0, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x18, 0x0, 0x18, 0x0, 0x33, 0xC0, 0x3F, 0xE0, 0x38, 0x70, 0x70, 0x30, 0x60, 0x18, 0x60, 0x18, 0x20, 0x18, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x7F, 0xF8, 0x7F, 0xF8, 0x60, 0x30, 0x60, 0x30, 0x60, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0xC0, 0x0, 0xC0, 0x1, 0x80, 0x1, 0x80, 0x3, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0xF, 0xC0, 0xF, 0xC0, 0x38, 0x70, 0x70, 0x38, 0x60, 0x18, 0x60, 0x18, 0x70, 0x38, 0x38, 0x70, 0x3F, 0xF0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0xF, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x10, 0x60, 0x18, 0x60, 0x18, 0x30, 0x38, 0x38, 0x70, 0x1F, 0xF0, 0xF, 0x30, 0x0, 0x60, 0x0, 0x60, 0x0, 0xC0, 0x1, 0x80, 0x3, 0x80, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x80, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x30, 0x0, 0xE0, 0x3, 0xC0, 0x7, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x30, 0x0, 0x1C, 0x0, 0x7, 0x0, 0x3, 0xC0, 0x0, 0xF0, 0x0, 0x30, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x30, 0x0, 0x3C, 0x0, 0xF, 0x0, 0x3, 0x80, 0x0, 0xE0, 0x0, 0x30, 0x0, 0x30, 0x0, 0xE0, 0x3, 0x80, 0xF, 0x0, 0x1C, 0x0, 0x30, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x7, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x10, 0x30, 0x0, 0x30, 0x0, 0x60, 0x1, 0xC0, 0x3, 0x80, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x7, 0xC0, 0x1F, 0xE0, 0x18, 0x70, 0x30, 0x30, 0x30, 0x30, 0x21, 0xD0, 0x63, 0xD0, 0x66, 0x30, 0x66, 0x10, 0x66, 0x10, 0x66, 0x10, 0x66, 0x10, 0x66, 0x30, 0x63, 0xD0, 0x23, 0xD0, 0x30, 0x0, 0x30, 0x0, 0x18, 0x0, 0x1F, 0xE0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0041 "A" */
0x3, 0x80, 0x7, 0x80, 0x7, 0x80, 0x5, 0x80, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x3F, 0xC0, 0x3F, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x3F, 0xC0, 0x3F, 0xE0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0x7, 0xC0, 0xF, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30, 0x28, 0x30, 0x0, 0x30, 0x0, 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x20, 0x38, 0x38, 0x1C, 0x70, 0xF, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x3F, 0x80, 0x3F, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x3F, 0xE0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x3F, 0xF8, 0x3F, 0xF8, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x20, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x61, 0xF0, 0x61, 0xF0, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xF0, 0xF, 0xB0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x3F, 0xF0, 0x3F, 0xF0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0x1F, 0xE0, 0x1F, 0xE0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x0, 0x60, 0x30, 0x60, 0x38, 0xE0, 0x1F, 0xC0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x30, 0x18, 0x30, 0x30, 0x30, 0x60, 0x30, 0xE0, 0x31, 0xC0, 0x31, 0x80, 0x33, 0x0, 0x37, 0x0, 0x3F, 0x0, 0x3D, 0x80, 0x39, 0xC0, 0x30, 0xC0, 0x30, 0x60, 0x30, 0x70, 0x30, 0x30, 0x30, 0x38, 0x30, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x18, 0x0, 0x1F, 0xF8, 0x1F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x70, 0x38, 0x78, 0x78, 0x78, 0x78, 0x68, 0x58, 0x6C, 0xD8, 0x6C, 0xD8, 0x66, 0x98, 0x67, 0x98, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x62, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x38, 0x30, 0x38, 0x30, 0x3C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x26, 0x30, 0x26, 0x30, 0x22, 0x30, 0x23, 0x30, 0x23, 0x30, 0x21, 0xB0, 0x21, 0xB0, 0x20, 0xB0, 0x20, 0xF0, 0x20, 0xF0, 0x20, 0x70, 0x20, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x3F, 0xC0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xE0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x7, 0x80, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x3, 0x0, 0x3, 0x0, 0x3, 0xF0, 0x1, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0052 "R" */
0x3F, 0xC0, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x3F, 0xF0, 0x3F, 0xC0, 0x31, 0x80, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x18, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x3F, 0x80, 0xF, 0xE0, 0x0, 0xF0, 0x0, 0x38, 0x0, 0x18, 0x0, 0x18, 0x60, 0x38, 0x78, 0x70, 0x3F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0xFF, 0xFC, 0xFF, 0xFC, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0x60, 0x18, 0x60, 0x18, 0x70, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x40, 0x8, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x63, 0x18, 0x63, 0x18, 0x67, 0x98, 0x67, 0x98, 0x66, 0x98, 0x64, 0x98, 0x64, 0x98, 0x2C, 0xD0, 0x2C, 0xD0, 0x2C, 0xD0, 0x28, 0x50, 0x38, 0x70, 0x38, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0x60, 0x18, 0x30, 0x38, 0x30, 0x30, 0x18, 0x60, 0xC, 0xE0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x7, 0x80, 0x7, 0xC0, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0xE0, 0x1C, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x60, 0x1C, 0xE0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x30, 0x0, 0x70, 0x0, 0xE0, 0x0, 0xC0, 0x1, 0x80, 0x3, 0x80, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x1C, 0x0, 0x18, 0x0, 0x30, 0x0, 0x60, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x7, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005C "\\" */
0x30, 0x0, 0x18, 0x0, 0x18, 0x0, 0x8, 0x0, 0xC, 0x0, 0xC, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x3, 0x0, 0x1, 0x80, 0x1, 0x80, 0x0, 0x80, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0x60, 0x0, 0x60, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005D "]" */
0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005E "^" */
0x3, 0x0, 0x7, 0x80, 0x5, 0x80, 0xC, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xF8, 0x7F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0060 "`" */
0x6, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x80, 0x1F, 0xC0, 0x30, 0x60, 0x20, 0x60, 0x0, 0x60, 0x1F, 0xE0, 0x3F, 0xE0, 0x70, 0x60, 0x60, 0x60, 0x30, 0xA0, 0x3F, 0xB8, 0x1F, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x38, 0x70, 0x37, 0xE0, 0x33, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xC0, 0x1F, 0xE0, 0x18, 0x70, 0x30, 0x20, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x30, 0x18, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0xF, 0x30, 0x1F, 0xB0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xC0, 0x1F, 0xE0, 0x38, 0x30, 0x30, 0x30, 0x3F, 0xF8, 0x7F, 0xF8, 0x60, 0x0, 0x30, 0x0, 0x30, 0x20, 0x38, 0x70, 0x1F, 0xE0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0x3, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF8, 0x3F, 0xF8, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x78, 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x38, 0x60, 0x1F, 0xE0, 0xF, 0x80, 0x10, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x1F, 0xF8, 0x30, 0x18, 0x60, 0x18, 0x70, 0x18, 0x3F, 0xF0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0,
/* U+0068 "h" */
0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0x3, 0x80, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x80, 0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0xF8, 0x3F, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0x0, 0xE0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xC0, 0x3F, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x0, 0xC0, 0x3F, 0xC0, 0x3F, 0x80, 0x0, 0x0, 0x0, 0x0,
/* U+006B "k" */
0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x38, 0x30, 0x60, 0x30, 0xC0, 0x31, 0x80, 0x33, 0x0, 0x37, 0x0, 0x3D, 0x80, 0x30, 0xC0, 0x30, 0xE0, 0x30, 0x70, 0x30, 0x30, 0x30, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0x3F, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E, 0x70, 0x7E, 0xF8, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xC0, 0x1F, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x10, 0x60, 0x18, 0x60, 0x18, 0x60, 0x10, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xE0, 0xF, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0xC0, 0x37, 0xE0, 0x38, 0x70, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x38, 0x70, 0x37, 0xE0, 0x33, 0xC0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x30, 0x1F, 0xB0, 0x38, 0x70, 0x30, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0x78, 0x3E, 0xF8, 0x6, 0x80, 0x7, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xC0, 0x1F, 0xF0, 0x38, 0x30, 0x30, 0x0, 0x38, 0x0, 0x1F, 0xC0, 0x7, 0xF0, 0x0, 0x30, 0x0, 0x30, 0x30, 0x30, 0x7F, 0xF0, 0xF, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7F, 0xF0, 0x7F, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x70, 0x1F, 0xB0, 0xF, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x20, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0xC, 0xC0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0xC, 0x43, 0x8, 0x67, 0x98, 0x67, 0x98, 0x64, 0x98, 0x64, 0x98, 0x24, 0x90, 0x2C, 0xD0, 0x2C, 0xD0, 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x38, 0x18, 0x60, 0x1C, 0x60, 0xC, 0xC0, 0x7, 0x80, 0x3, 0x0, 0x7, 0x80, 0x7, 0x80, 0xC, 0xC0, 0x18, 0x60, 0x38, 0x70, 0x70, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x10, 0x30, 0x18, 0x60, 0x18, 0x60, 0xC, 0xC0, 0xC, 0xC0, 0x4, 0x80, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3E, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x70, 0x0, 0xE0, 0x1, 0x80, 0x3, 0x0, 0x6, 0x0, 0xC, 0x0, 0x18, 0x0, 0x30, 0x0, 0x3F, 0xF0, 0x3F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0x7, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x0, 0x3F, 0x0, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x2, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0xF0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007C "|" */
0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007D "}" */
0x3F, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x0, 0x3, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x3, 0xF0, 0x3, 0xF0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x3, 0x0, 0x1, 0x0, 0x1, 0x80, 0x1, 0x80, 0x3F, 0x80, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0x18, 0x3E, 0x18, 0x37, 0x18, 0x63, 0xB0, 0x61, 0xF0, 0x60, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_24_font = {
.glyph_width = 14,
.glyph_height = 24,
.glyph_bytes_per_row = 2,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono24_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_24

View File

@ -0,0 +1,222 @@
/*
* ibmplexmono28.c - ibmplexmono28 FixedWidthFont
*
* Rasterized from a TTF with Modules/font-module/scripts/generate.py.
* Each glyph is 17 pixels wide and 28 pixels tall, stored as 28 rows of
* 3 bytes each (bit 7 of the first byte = leftmost pixel).
*/
#include <font/ibmplexmono28.h>
#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif
// See Modules/font-module/Kconfig: undefined (POSIX, or an ESP-IDF build predating
// this font's Kconfig entry) is treated the same as enabled.
#if !defined(CONFIG_TT_FONT_IBMPLEXMONO_28) || CONFIG_TT_FONT_IBMPLEXMONO_28
// Glyph bitmap data: 95 characters (0x20-0x7E), 84 bytes each = 7980 bytes
static const uint8_t ibmplexmono28_glyph_bitmap[] = {
/* U+0020 " " */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0021 "!" */
0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0022 "\"" */
0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0023 "#" */
0x1, 0x8C, 0x0, 0x3, 0xC, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x3F, 0x1F, 0x0, 0x3E, 0x3F, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7E, 0x3E, 0x0, 0x7C, 0x7E, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0xC, 0x60, 0x0, 0x18, 0x60, 0x0, 0x18, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0024 "$" */
0x7, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0xDE, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xC0, 0x0, 0x30, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x18, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0xF, 0xF0, 0x0, 0x1, 0xFC, 0x0, 0x0, 0xDE, 0x0, 0x0, 0xC6, 0x0, 0x0, 0xC6, 0x0, 0x0, 0xC7, 0x0, 0x20, 0xC6, 0x0, 0x30, 0xC6, 0x0, 0x7C, 0xDE, 0x0, 0x1F, 0xFC, 0x0, 0x7, 0xF0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0025 "%" */
0x1E, 0x3, 0x0, 0x3F, 0x3, 0x0, 0x63, 0x86, 0x0, 0x61, 0x8E, 0x0, 0x61, 0x8C, 0x0, 0x61, 0x98, 0x0, 0x61, 0x98, 0x0, 0x63, 0xB0, 0x0, 0x3F, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0x7E, 0x0, 0x6, 0xE3, 0x0, 0xC, 0xC3, 0x0, 0xC, 0xC3, 0x0, 0x18, 0xC3, 0x0, 0x30, 0xC3, 0x0, 0x30, 0xE3, 0x0, 0x60, 0x7E, 0x0, 0x60, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0026 "&" */
0x7, 0xC0, 0x0, 0xF, 0xE0, 0x0, 0x1C, 0x70, 0x0, 0x18, 0x20, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0x0, 0x0, 0xE, 0x0, 0x0, 0xE, 0xF, 0x0, 0x3B, 0xF, 0x0, 0x33, 0x8C, 0x0, 0x71, 0xCC, 0x0, 0x60, 0xE8, 0x0, 0x60, 0x78, 0x0, 0x60, 0x38, 0x0, 0x70, 0x38, 0x0, 0x38, 0x6C, 0x0, 0x3F, 0xCE, 0x0, 0xF, 0x87, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0027 "'" */
0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0028 "(" */
0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0029 ")" */
0x6, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002A "*" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x21, 0xC2, 0x0, 0x7D, 0xDF, 0x0, 0x3F, 0xFE, 0x0, 0x7, 0xF0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002B "+" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002C "," */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002D "-" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xF8, 0x0, 0xF, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002E "." */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+002F "/" */
0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0030 "0" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0031 "1" */
0x3, 0xC0, 0x0, 0x7, 0xC0, 0x0, 0xE, 0xC0, 0x0, 0x1C, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x38, 0xC0, 0x0, 0x30, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x3F, 0xFF, 0x0, 0x3F, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0032 "2" */
0x7, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x30, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x7, 0x0, 0x0, 0xE, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0033 "3" */
0x7, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x10, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x7, 0xE0, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x38, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xE, 0x0, 0x20, 0xE, 0x0, 0x30, 0xC, 0x0, 0x78, 0x3C, 0x0, 0x1F, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0034 "4" */
0x0, 0x78, 0x0, 0x0, 0x78, 0x0, 0x0, 0xD8, 0x0, 0x1, 0xD8, 0x0, 0x1, 0x98, 0x0, 0x3, 0x18, 0x0, 0x3, 0x18, 0x0, 0x6, 0x18, 0x0, 0xE, 0x18, 0x0, 0xC, 0x18, 0x0, 0x18, 0x18, 0x0, 0x38, 0x18, 0x0, 0x30, 0x18, 0x0, 0x60, 0x18, 0x0, 0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0035 "5" */
0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x8, 0xE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x10, 0xE, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0036 "6" */
0x0, 0xF0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0xE, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x3B, 0xF8, 0x0, 0x34, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0037 "7" */
0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x30, 0xE, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x70, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0038 "8" */
0x7, 0xF0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0x7, 0xF0, 0x0, 0x7, 0xF0, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0039 "9" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x16, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003A ":" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003B ";" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003C "<" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0xC, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xF0, 0x0, 0x1, 0xE0, 0x0, 0x7, 0x80, 0x0, 0x1E, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x7, 0x80, 0x0, 0x1, 0xE0, 0x0, 0x0, 0xF0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xC, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003E ">" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x7, 0x80, 0x0, 0x3, 0xC0, 0x0, 0x0, 0xF0, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x3C, 0x0, 0x0, 0xF0, 0x0, 0x3, 0xC0, 0x0, 0x7, 0x80, 0x0, 0x1E, 0x0, 0x0, 0x18, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x78, 0x0, 0x1, 0xF0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0040 "@" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0xC, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0xE6, 0x0, 0x31, 0xF6, 0x0, 0x31, 0x8E, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x6, 0x0, 0x33, 0x8E, 0x0, 0x31, 0xFE, 0x0, 0x30, 0xF6, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0x0, 0x0, 0xE, 0x0, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0041 "A" */
0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x7, 0x70, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x1C, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x70, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0042 "B" */
0x1F, 0xF0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0x1C, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xC, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0043 "C" */
0x3, 0xF0, 0x0, 0x7, 0xF8, 0x0, 0xE, 0x1C, 0x0, 0x1C, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x6, 0x0, 0x1C, 0xE, 0x0, 0xE, 0x1C, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0044 "D" */
0x1F, 0xE0, 0x0, 0x1F, 0xF8, 0x0, 0x18, 0x3C, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x18, 0xE, 0x0, 0x18, 0x1C, 0x0, 0x18, 0x3C, 0x0, 0x1F, 0xF8, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0045 "E" */
0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0046 "F" */
0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0047 "G" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0xFE, 0x0, 0x30, 0xFE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x16, 0x0, 0xF, 0xF6, 0x0, 0x3, 0xC6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0048 "H" */
0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0049 "I" */
0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004A "J" */
0xF, 0xFC, 0x0, 0xF, 0xFC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x10, 0x18, 0x0, 0x38, 0x18, 0x0, 0x1C, 0x38, 0x0, 0xF, 0xF0, 0x0, 0x7, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004B "K" */
0x38, 0x7, 0x0, 0x38, 0xE, 0x0, 0x38, 0x1C, 0x0, 0x38, 0x38, 0x0, 0x38, 0x30, 0x0, 0x38, 0x70, 0x0, 0x38, 0xE0, 0x0, 0x39, 0xC0, 0x0, 0x3B, 0x80, 0x0, 0x3B, 0xC0, 0x0, 0x3E, 0xE0, 0x0, 0x3E, 0xE0, 0x0, 0x3C, 0x70, 0x0, 0x38, 0x30, 0x0, 0x38, 0x38, 0x0, 0x38, 0x1C, 0x0, 0x38, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x38, 0x6, 0x0, 0x38, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004C "L" */
0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004D "M" */
0x38, 0xE, 0x0, 0x3C, 0x1E, 0x0, 0x3C, 0x1E, 0x0, 0x3C, 0x1E, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x33, 0x26, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x30, 0x86, 0x0, 0x30, 0x86, 0x0, 0x30, 0x86, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004E "N" */
0x3C, 0x6, 0x0, 0x3C, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3E, 0x6, 0x0, 0x3B, 0x6, 0x0, 0x3B, 0x6, 0x0, 0x3B, 0x86, 0x0, 0x39, 0x86, 0x0, 0x39, 0x86, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xC6, 0x0, 0x38, 0xE6, 0x0, 0x38, 0x66, 0x0, 0x38, 0x66, 0x0, 0x38, 0x36, 0x0, 0x38, 0x36, 0x0, 0x38, 0x3E, 0x0, 0x38, 0x1E, 0x0, 0x38, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+004F "O" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0050 "P" */
0x1F, 0xF0, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0051 "Q" */
0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0xFC, 0x0, 0x0, 0x7C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0052 "R" */
0x1F, 0xF0, 0x0, 0x1F, 0xFC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xF0, 0x0, 0x18, 0xE0, 0x0, 0x18, 0x60, 0x0, 0x18, 0x70, 0x0, 0x18, 0x30, 0x0, 0x18, 0x38, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0053 "S" */
0x7, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0x1E, 0x0, 0x38, 0x6, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x1F, 0x0, 0x0, 0xF, 0xF0, 0x0, 0x3, 0xFC, 0x0, 0x0, 0x1E, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x20, 0x6, 0x0, 0x70, 0xE, 0x0, 0x3C, 0x1C, 0x0, 0x1F, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0054 "T" */
0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0055 "U" */
0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0056 "V" */
0x70, 0x7, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xE, 0x38, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0057 "W" */
0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x60, 0x3, 0x0, 0x70, 0x3, 0x0, 0x31, 0xC7, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x32, 0x26, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x36, 0x0, 0x36, 0x16, 0x0, 0x1C, 0x1E, 0x0, 0x1C, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0058 "X" */
0x70, 0x7, 0x0, 0x38, 0x6, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xE, 0x18, 0x0, 0x6, 0x38, 0x0, 0x7, 0x30, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x70, 0x0, 0x6, 0x30, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0059 "Y" */
0x70, 0x7, 0x0, 0x70, 0x7, 0x0, 0x38, 0xE, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xE, 0x38, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005A "Z" */
0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0xE, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x30, 0x0, 0x0, 0x7F, 0xFF, 0x0, 0x7F, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005B "[" */
0x3, 0xFC, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0xFC, 0x0, 0x3, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005C "\\" */
0x18, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x70, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005D "]" */
0x1F, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x1F, 0xE0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005E "^" */
0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x3, 0x60, 0x0, 0x7, 0x70, 0x0, 0x6, 0x30, 0x0, 0xC, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x30, 0x6, 0x0, 0x70, 0x7, 0x0, 0x20, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+005F "_" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0060 "`" */
0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0061 "a" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xE0, 0x0, 0xF, 0xF0, 0x0, 0x1C, 0x38, 0x0, 0x30, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0xF, 0xF8, 0x0, 0x1F, 0xF8, 0x0, 0x38, 0x18, 0x0, 0x30, 0x18, 0x0, 0x30, 0x18, 0x0, 0x38, 0x38, 0x0, 0x1F, 0xCF, 0x0, 0xF, 0x8F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0062 "b" */
0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0x1B, 0xF8, 0x0, 0x19, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0063 "c" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xF0, 0x0, 0x7, 0xF8, 0x0, 0xE, 0x1C, 0x0, 0x1C, 0xC, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x38, 0x0, 0x0, 0x38, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x8, 0x0, 0x1C, 0xC, 0x0, 0xE, 0x1E, 0x0, 0x7, 0xF8, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0064 "d" */
0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x7, 0xCC, 0x0, 0xF, 0xEC, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0065 "e" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1C, 0xC, 0x0, 0xF, 0xFE, 0x0, 0x3, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0066 "f" */
0x0, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0067 "g" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x1F, 0x0, 0x3, 0xF0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0x1C, 0x0, 0xC, 0x18, 0x0, 0x7, 0xF8, 0x0, 0x7, 0xE0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0xF, 0xFE, 0x0, 0x18, 0x7, 0x0, 0x30, 0x3, 0x0, 0x30, 0x3, 0x0, 0x38, 0xE, 0x0, 0x1F, 0xFE, 0x0, 0xF, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0068 "h" */
0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0069 "i" */
0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xE0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xE0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006A "j" */
0x0, 0x38, 0x0, 0x0, 0x78, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xF0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x0, 0x30, 0x0, 0x1F, 0xF0, 0x0, 0x1F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006B "k" */
0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0xE, 0x0, 0x18, 0x1C, 0x0, 0x18, 0x38, 0x0, 0x18, 0x70, 0x0, 0x18, 0xE0, 0x0, 0x19, 0x80, 0x0, 0x1F, 0xC0, 0x0, 0x1E, 0xE0, 0x0, 0x1C, 0x70, 0x0, 0x18, 0x38, 0x0, 0x18, 0x18, 0x0, 0x18, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006C "l" */
0x3F, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3F, 0xFE, 0x0, 0x3F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006D "m" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x37, 0x1C, 0x0, 0x3F, 0xBE, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x31, 0xC6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006E "n" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1E, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+006F "o" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xE0, 0x0, 0xF, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xC, 0x0, 0x38, 0xE, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xF8, 0x0, 0x3, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0070 "p" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0xF0, 0x0, 0x1B, 0xF8, 0x0, 0x1C, 0x1C, 0x0, 0x18, 0xE, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0x6, 0x0, 0x18, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0x1B, 0xF8, 0x0, 0x19, 0xF0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xCC, 0x0, 0xF, 0xEC, 0x0, 0x1C, 0x1C, 0x0, 0x38, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x30, 0xC, 0x0, 0x38, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0072 "r" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F, 0x9F, 0x0, 0x3F, 0xBF, 0x0, 0x3, 0xE0, 0x0, 0x3, 0xC0, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3F, 0xFC, 0x0, 0x3F, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0073 "s" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xF0, 0x0, 0xF, 0xFC, 0x0, 0x1C, 0x1E, 0x0, 0x18, 0x8, 0x0, 0x18, 0x0, 0x0, 0x1E, 0x0, 0x0, 0xF, 0xF0, 0x0, 0x3, 0xFC, 0x0, 0x0, 0xE, 0x0, 0x0, 0x6, 0x0, 0x10, 0xE, 0x0, 0x3C, 0x1C, 0x0, 0x1F, 0xFC, 0x0, 0x7, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0074 "t" */
0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x7F, 0xFE, 0x0, 0x7F, 0xFE, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0xFE, 0x0, 0x1, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0075 "u" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x3C, 0x0, 0xF, 0xEC, 0x0, 0x7, 0xCC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0076 "v" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x6, 0x0, 0x38, 0xE, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0xC, 0x18, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0077 "w" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xC3, 0x0, 0x61, 0xC3, 0x0, 0x61, 0x43, 0x0, 0x21, 0x43, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x33, 0x66, 0x0, 0x32, 0x26, 0x0, 0x32, 0x36, 0x0, 0x36, 0x36, 0x0, 0x16, 0x34, 0x0, 0x1E, 0x34, 0x0, 0x1C, 0x1C, 0x0, 0x1C, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0078 "x" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xE, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0xE0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x3, 0xE0, 0x0, 0x7, 0x70, 0x0, 0xE, 0x38, 0x0, 0xC, 0x18, 0x0, 0x18, 0x1C, 0x0, 0x38, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+0079 "y" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x6, 0x0, 0x30, 0x6, 0x0, 0x18, 0xC, 0x0, 0x18, 0xC, 0x0, 0x1C, 0x1C, 0x0, 0xC, 0x18, 0x0, 0xE, 0x18, 0x0, 0x6, 0x30, 0x0, 0x6, 0x30, 0x0, 0x7, 0x70, 0x0, 0x3, 0x60, 0x0, 0x3, 0x60, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007A "z" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1F, 0xFC, 0x0, 0x1F, 0xFC, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x38, 0x0, 0x0, 0x70, 0x0, 0x0, 0xE0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0xC, 0x0, 0x0, 0x18, 0x0, 0x0, 0x1F, 0xFE, 0x0, 0x1F, 0xFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007B "{" */
0x1, 0xFC, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xE0, 0x0, 0x1F, 0xC0, 0x0, 0x1F, 0x80, 0x0, 0x0, 0xE0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0x60, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x1, 0xFC, 0x0, 0x1, 0xFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007C "|" */
0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007D "}" */
0x1F, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1, 0x80, 0x0, 0x1, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x80, 0x0, 0x1, 0xFC, 0x0, 0x0, 0xFC, 0x0, 0x3, 0x80, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0x1F, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
/* U+007E "~" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x2, 0x0, 0x1F, 0x6, 0x0, 0x39, 0x86, 0x0, 0x30, 0xCE, 0x0, 0x30, 0xFC, 0x0, 0x20, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
const FixedWidthFont ibmplexmono_28_font = {
.glyph_width = 17,
.glyph_height = 28,
.glyph_bytes_per_row = 3,
.first_codepoint = 0x20,
.last_codepoint = 0x7E,
.glyph_bitmap = ibmplexmono28_glyph_bitmap,
};
#endif // CONFIG_TT_FONT_IBMPLEXMONO_28

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: Apache-2.0
#include <font/module.h>
#include <font/render.h>
static const struct ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(font_render_char),
DEFINE_MODULE_SYMBOL(font_render_string),
DEFINE_MODULE_SYMBOL(font_get_string_length),
MODULE_SYMBOL_TERMINATOR
};
struct Module font_module = {
.name = "font",
.start = NULL,
.stop = NULL,
.drivers = NULL,
.symbols = SYMBOLS,
.internal = NULL,
};

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
#include <font/render.h>
#include <cstring>
void font_render_char(const FixedWidthFont* font, char ch, uint16_t fg, uint16_t bg, uint16_t* buffer, int stride) {
// Anything outside the font's range renders as blank rather than as garbage. The comparison
// uses an unsigned value so that a byte above 0x7F cannot come out negative and pass the
// lower-bound test.
const auto raw = static_cast<unsigned char>(ch);
const unsigned char glyphChar = (raw >= font->first_codepoint && raw <= font->last_codepoint) ? raw : ' ';
const uint8_t* glyph = &font->glyph_bitmap[(glyphChar - font->first_codepoint) * font->glyph_height * font->glyph_bytes_per_row];
for (int y = 0; y < font->glyph_height; y++) {
const uint8_t* bits = &glyph[y * font->glyph_bytes_per_row];
uint16_t* out = &buffer[y * stride];
for (int x = 0; x < font->glyph_width; x++) {
// The font stores the leftmost pixel of each row byte in the most significant bit.
out[x] = (bits[x / 8] & (0x80U >> (x % 8))) ? fg : bg;
}
}
}
void font_render_string(const FixedWidthFont* font, const char* str, uint16_t fg, uint16_t bg, uint16_t* buffer, int stride) {
for (const char* p = str; *p != '\0'; p++) {
font_render_char(font, *p, fg, bg, buffer, stride);
buffer += font->glyph_width;
}
}
int font_get_string_length(const FixedWidthFont* font, const char* str) {
return static_cast<int>(strlen(str)) * font->glyph_width;
}

View File

@ -1,5 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
#include <gps/gps_settings.h>
#include "tactility/paths.h"
#include <gps/private/gps_ledger.h>
#include <service/paths.h>
@ -76,7 +79,7 @@ static error_t write_configurations(const std::vector<GpsConfiguration>& configu
return ERROR_RESOURCE;
}
char path[256];
char path[FILE_MAX_PATH_STRING_LENGTH];
if (!get_configuration_path(path, sizeof(path))) {
return ERROR_RESOURCE;
}

View File

@ -44,10 +44,11 @@ def generate_icon_fonts(font_file, font_sizes, symbols, output):
generate(2, size, font_file, symbols, output)
def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_name: str):
filename = f"lvgl_icon_{variable_name}.h"
filename = f"{variable_name}.h"
print(f"Generating {filename}")
output_path = os.path.join("..", "include", "tactility", filename)
output_path = os.path.join("..", "include", "lvgl", "icons", filename)
with open(output_path, 'w') as f:
f.write("// SPDX-License-Identifier: Apache-2.0\n\n")
f.write("#pragma once\n\n")
for name in codepoint_names:
safe_name = name.lower()

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#define LVGL_ICON_LAUNCHER_APPS "\xEE\x97\x83"

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#define LVGL_ICON_SHARED_ADD "\xEE\x85\x85"
@ -10,7 +11,7 @@
#define LVGL_ICON_SHARED_CIRCLE "\xEE\xBD\x8A"
#define LVGL_ICON_SHARED_CLOSE "\xEE\x97\x8D"
#define LVGL_ICON_SHARED_CLOUD "\xEF\x85\x9C"
#define LVGL_ICON_SHARED_CHECK "\xEE\x97\x8A"
#define LVGL_ICON_SHARED_CHECK "\xEE\x99\xA8"
#define LVGL_ICON_SHARED_DELETE "\xEE\xA4\xAE"
#define LVGL_ICON_SHARED_DEVICES "\xEE\x8C\xA6"
#define LVGL_ICON_SHARED_DISPLAY_SETTINGS "\xEE\xAE\x97"
@ -26,7 +27,7 @@
#define LVGL_ICON_SHARED_IMAGE "\xEE\x8F\xB4"
#define LVGL_ICON_SHARED_KEYBOARD_ARROW_UP "\xEE\x8C\x96"
#define LVGL_ICON_SHARED_LIGHTBULB "\xEE\xA4\x8F"
#define LVGL_ICON_SHARED_LANGUAGE "\xEE\xA2\x94"
#define LVGL_ICON_SHARED_LANGUAGE "\xEE\xA8\x87"
#define LVGL_ICON_SHARED_LISTS "\xEE\xA6\xB9"
#define LVGL_ICON_SHARED_MAIL "\xEE\x85\x99"
#define LVGL_ICON_SHARED_MENU "\xEE\x97\x92"
@ -36,7 +37,7 @@
#define LVGL_ICON_SHARED_NOTE_ADD "\xEE\xA2\x9C"
#define LVGL_ICON_SHARED_POWER_SETTINGS_NEW "\xEF\xA3\x87"
#define LVGL_ICON_SHARED_REFRESH "\xEE\x97\x95"
#define LVGL_ICON_SHARED_SEARCH "\xEE\xA2\xB6"
#define LVGL_ICON_SHARED_SEARCH "\xEE\xBD\xBA"
#define LVGL_ICON_SHARED_SETTINGS "\xEE\xA2\xB8"
#define LVGL_ICON_SHARED_TOOLBAR "\xEE\xA7\xB7"
#define LVGL_ICON_SHARED_NAVIGATION "\xEE\x95\x9D"

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#define LVGL_ICON_STATUSBAR_LOCATION_ON "\xEF\x87\x9B"

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* 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,0xE5CA,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xE894,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xE8B6,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7 --format lvgl -o ../source-fonts/material_symbols_shared_12.c --force-fast-kern-format
* 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 --format lvgl -o ../source-fonts/material_symbols_shared_12.c --force-fast-kern-format
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@ -86,10 +86,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xf3, 0xcf, 0xf3, 0xcf, 0x0, 0x0, 0xf3, 0xcf,
0xf3, 0xcf, 0x0, 0x0, 0xf3, 0xcf, 0xf3, 0xcf,
/* U+E5CA "" */
0x0, 0x2, 0x0, 0xd, 0x0, 0x34, 0xa0, 0xd0,
0x2b, 0x40, 0x9, 0x0,
/* U+E5CD "" */
0x10, 0x0, 0x34, 0x1c, 0xd, 0x70, 0x3, 0xc0,
0x7, 0xd0, 0x1c, 0x34, 0x30, 0xc, 0x0, 0x0,
@ -111,6 +107,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -121,12 +121,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xd0, 0xc, 0x94, 0x90, 0xc9, 0x1f, 0x8c, 0xbb,
0xff, 0xcb, 0xff, 0xfc, 0x0, 0x0, 0x0,
/* U+E894 "" */
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+E89C "" */
0xff, 0xd0, 0xc0, 0xb8, 0xc0, 0xbd, 0xc0, 0x2b,
0xc1, 0x43, 0xc6, 0x93, 0xc6, 0x93, 0xc1, 0x43,
@ -138,12 +132,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xaa, 0xf0, 0xff, 0xff, 0x0, 0x0, 0xb0, 0x0,
0x0,
/* U+E8B6 "" */
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+E8B8 "" */
0x1, 0xf4, 0x1, 0x25, 0x84, 0x7e, 0xb, 0xda,
0xa, 0xa, 0x36, 0xf9, 0xc3, 0x2f, 0x9c, 0xa0,
@ -184,6 +172,12 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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+EB97 "" */
0x15, 0x55, 0x4e, 0xaa, 0xab, 0xc0, 0x0, 0x3c,
0xaa, 0x63, 0xc1, 0x0, 0x3c, 0xdf, 0xf3, 0xc1,
@ -212,6 +206,12 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -264,29 +264,29 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 203, .adv_w = 192, .box_w = 6, .box_h = 10, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 218, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 238, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 254, .adv_w = 192, .box_w = 8, .box_h = 6, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 266, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 282, .adv_w = 192, .box_w = 10, .box_h = 6, .ofs_x = 1, .ofs_y = 3},
{.bitmap_index = 297, .adv_w = 192, .box_w = 2, .box_h = 8, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 301, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 317, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 254, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 270, .adv_w = 192, .box_w = 10, .box_h = 6, .ofs_x = 1, .ofs_y = 3},
{.bitmap_index = 285, .adv_w = 192, .box_w = 2, .box_h = 8, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 289, .adv_w = 192, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 305, .adv_w = 192, .box_w = 12, .box_h = 9, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 332, .adv_w = 192, .box_w = 8, .box_h = 6, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 344, .adv_w = 192, .box_w = 9, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 362, .adv_w = 192, .box_w = 10, .box_h = 9, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 385, .adv_w = 192, .box_w = 10, .box_h = 10, .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 = 385, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 405, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .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 = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 530, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 550, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 570, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 590, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 480, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 500, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 520, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 540, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 576, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1},
{.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 = 10, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 701, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 721, .adv_w = 192, .box_w = 9, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 676, .adv_w = 192, .box_w = 8, .box_h = 10, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 696, .adv_w = 192, .box_w = 9, .box_h = 8, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 714, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 739, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 764, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 789, .adv_w = 192, .box_w = 12, .box_h = 8, .ofs_x = 0, .ofs_y = 2},
@ -302,10 +302,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
static const uint16_t unicode_list_0[] = {
0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x485, 0x488, 0x48d,
0x48f, 0x490, 0x4f9, 0x600, 0x62b, 0x74f, 0x757, 0x76a,
0x771, 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2,
0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xea1, 0xee3, 0xf4b,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, 0x48f,
0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, 0x773,
0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, 0xa52,
0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, 0xea1, 0xee3, 0xf4b,
0x1017, 0x15db, 0x1782
};

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* 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,0xE5CA,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xE894,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xE8B6,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7 --format lvgl -o ../source-fonts/material_symbols_shared_16.c --force-fast-kern-format
* 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 --format lvgl -o ../source-fonts/material_symbols_shared_16.c --force-fast-kern-format
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@ -114,11 +114,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x14, 0x14, 0x14, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c,
0x3c, 0x0, 0x0, 0x0,
/* U+E5CA "" */
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+E5CD "" */
0x20, 0x0, 0x43, 0xc0, 0x1d, 0xf, 0x7, 0x40,
0x3e, 0xd0, 0x0, 0xf4, 0x0, 0x1f, 0xc0, 0x7,
@ -149,6 +144,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -163,15 +163,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xf4, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x55, 0x55, 0x55,
/* U+E894 "" */
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+E89C "" */
0x15, 0x54, 0x0, 0x3f, 0xff, 0x40, 0x70, 0x7,
0xd0, 0x70, 0x7, 0xf4, 0x70, 0x7, 0xfc, 0x70,
@ -188,13 +179,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7f, 0xff, 0xfc, 0x3, 0xff, 0xff, 0xc0, 0x0,
0x0, 0x3c, 0x0, 0x0, 0x0, 0x80,
/* U+E8B6 "" */
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+E8B8 "" */
0x0, 0x5, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x4,
0x35, 0xc1, 0x2, 0xff, 0xf, 0xf8, 0x35, 0x40,
@ -252,6 +236,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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+EB97 "" */
0x7f, 0xff, 0xff, 0xce, 0x55, 0x55, 0x5d, 0xd0,
0x0, 0x0, 0xdd, 0x15, 0x53, 0x4d, 0xd1, 0x55,
@ -292,6 +285,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -360,30 +360,30 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 377, .adv_w = 256, .box_w = 8, .box_h = 12, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 401, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 437, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 473, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 497, .adv_w = 256, .box_w = 10, .box_h = 10, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 522, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 546, .adv_w = 256, .box_w = 4, .box_h = 12, .ofs_x = 6, .ofs_y = 2},
{.bitmap_index = 558, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 594, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 473, .adv_w = 256, .box_w = 10, .box_h = 10, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 498, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 522, .adv_w = 256, .box_w = 4, .box_h = 12, .ofs_x = 6, .ofs_y = 2},
{.bitmap_index = 534, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 570, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 618, .adv_w = 256, .box_w = 12, .box_h = 8, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 642, .adv_w = 256, .box_w = 13, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 681, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 717, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.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 = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 890, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 939, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 988, .adv_w = 256, .box_w = 10, .box_h = 14, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 1023, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1059, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 1101, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1165, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1201, .adv_w = 256, .box_w = 14, .box_h = 13, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1247, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1289, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1331, .adv_w = 256, .box_w = 13, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1370, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 717, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 759, .adv_w = 256, .box_w = 14, .box_h = 13, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 805, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.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 = 10, .box_h = 14, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 938, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 974, .adv_w = 256, .box_w = 14, .box_h = 12, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 1016, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1080, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1116, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1165, .adv_w = 256, .box_w = 14, .box_h = 13, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1211, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1253, .adv_w = 256, .box_w = 12, .box_h = 14, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1295, .adv_w = 256, .box_w = 13, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1334, .adv_w = 256, .box_w = 14, .box_h = 14, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1383, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1419, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1455, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 1503, .adv_w = 256, .box_w = 12, .box_h = 12, .ofs_x = 2, .ofs_y = 2},
@ -398,10 +398,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
static const uint16_t unicode_list_0[] = {
0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x485, 0x488, 0x48d,
0x48f, 0x490, 0x4f9, 0x600, 0x62b, 0x74f, 0x757, 0x76a,
0x771, 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2,
0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xea1, 0xee3, 0xf4b,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, 0x48f,
0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, 0x773,
0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, 0xa52,
0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, 0xea1, 0xee3, 0xf4b,
0x1017, 0x15db, 0x1782
};

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* 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,0xE5CA,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xE894,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xE8B6,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7 --format lvgl -o ../source-fonts/material_symbols_shared_20.c --force-fast-kern-format
* 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 --format lvgl -o ../source-fonts/material_symbols_shared_20.c --force-fast-kern-format
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@ -142,13 +142,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xf4, 0xbd, 0xbe, 0x2f, 0x8b, 0xe3, 0x80, 0xe0,
0x38,
/* U+E5CA "" */
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+E5CD "" */
0x20, 0x0, 0x9, 0x3c, 0x0, 0x2e, 0x1f, 0x0,
0xb8, 0x7, 0xc2, 0xe0, 0x1, 0xfb, 0x80, 0x0,
@ -188,6 +181,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -206,19 +206,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xbe, 0x3f, 0xff, 0xce, 0xbf, 0xff, 0xff, 0xfe,
0xbf, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfd,
/* U+E894 "" */
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+E89C "" */
0x1a, 0xaa, 0x40, 0xb, 0xff, 0xfe, 0x0, 0xb0,
0x1, 0xf8, 0xb, 0x0, 0xf, 0xe0, 0xb0, 0x0,
@ -241,16 +228,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x0, 0x0, 0x3, 0xe0, 0x0, 0x0, 0x0, 0x1d,
0x0, 0x0, 0x0, 0x0, 0x0,
/* U+E8B6 "" */
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+E8B8 "" */
0x0, 0x6, 0x90, 0x0, 0x0, 0x7, 0xfd, 0x0,
0x0, 0x2, 0xc3, 0x80, 0x0, 0x79, 0xf0, 0xf6,
@ -330,6 +307,19 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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+EB97 "" */
0xa, 0xaa, 0xaa, 0xaa, 0x43, 0xff, 0xff, 0xff,
0xfd, 0x38, 0x0, 0x0, 0x0, 0xe3, 0x80, 0x0,
@ -384,6 +374,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -470,30 +470,30 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 578, .adv_w = 320, .box_w = 10, .box_h = 16, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 618, .adv_w = 320, .box_w = 14, .box_h = 16, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 674, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 723, .adv_w = 320, .box_w = 14, .box_h = 10, .ofs_x = 3, .ofs_y = 5},
{.bitmap_index = 758, .adv_w = 320, .box_w = 12, .box_h = 12, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 794, .adv_w = 320, .box_w = 16, .box_h = 10, .ofs_x = 2, .ofs_y = 5},
{.bitmap_index = 834, .adv_w = 320, .box_w = 4, .box_h = 14, .ofs_x = 8, .ofs_y = 3},
{.bitmap_index = 848, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 897, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 723, .adv_w = 320, .box_w = 12, .box_h = 12, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 759, .adv_w = 320, .box_w = 16, .box_h = 10, .ofs_x = 2, .ofs_y = 5},
{.bitmap_index = 799, .adv_w = 320, .box_w = 4, .box_h = 14, .ofs_x = 8, .ofs_y = 3},
{.bitmap_index = 813, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 862, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 937, .adv_w = 320, .box_w = 14, .box_h = 10, .ofs_x = 3, .ofs_y = 5},
{.bitmap_index = 972, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 1028, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 1084, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.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 = 16, .box_h = 15, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 1365, .adv_w = 320, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1442, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1523, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 1586, .adv_w = 320, .box_w = 14, .box_h = 16, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 1642, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3},
{.bitmap_index = 1705, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1805, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1869, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 1941, .adv_w = 320, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 2013, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 2076, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2132, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1084, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 1147, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 1224, .adv_w = 320, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1301, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1382, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 1445, .adv_w = 320, .box_w = 14, .box_h = 16, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 1501, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = 3},
{.bitmap_index = 1564, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1664, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1728, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 1809, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 1881, .adv_w = 320, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 1},
{.bitmap_index = 1953, .adv_w = 320, .box_w = 14, .box_h = 18, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 2016, .adv_w = 320, .box_w = 16, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2072, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 1},
{.bitmap_index = 2153, .adv_w = 320, .box_w = 16, .box_h = 15, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 2213, .adv_w = 320, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 2277, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = 3},
{.bitmap_index = 2347, .adv_w = 320, .box_w = 14, .box_h = 14, .ofs_x = 3, .ofs_y = 3},
@ -508,10 +508,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
static const uint16_t unicode_list_0[] = {
0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x485, 0x488, 0x48d,
0x48f, 0x490, 0x4f9, 0x600, 0x62b, 0x74f, 0x757, 0x76a,
0x771, 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2,
0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xea1, 0xee3, 0xf4b,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, 0x48f,
0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, 0x773,
0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, 0xa52,
0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, 0xea1, 0xee3, 0xf4b,
0x1017, 0x15db, 0x1782
};

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* 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,0xE5CA,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xE894,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xE8B6,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7 --format lvgl -o ../source-fonts/material_symbols_shared_24.c --force-fast-kern-format
* 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 --format lvgl -o ../source-fonts/material_symbols_shared_24.c --force-fast-kern-format
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@ -170,14 +170,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7d, 0x7, 0xd0, 0x7d, 0xff, 0xf, 0xf0, 0xff,
0xff, 0xf, 0xf0, 0xff, 0x7d, 0x7, 0xd0, 0x7d,
/* U+E5CA "" */
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+E5CD "" */
0x10, 0x0, 0x0, 0x4b, 0x40, 0x0, 0x3d, 0x7d,
0x0, 0xf, 0xc1, 0xf4, 0x3, 0xf0, 0x7, 0xd0,
@ -225,6 +217,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -248,21 +248,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0,
/* U+E894 "" */
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+E89C "" */
0x7f, 0xff, 0xf4, 0x0, 0xff, 0xff, 0xfe, 0x0,
0xf0, 0x0, 0x3f, 0x80, 0xf0, 0x0, 0x3f, 0xe0,
@ -289,19 +274,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x0, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0,
0x0, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x5,
/* U+E8B6 "" */
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+E8B8 "" */
0x0, 0x2, 0xff, 0x0, 0x0, 0x0, 0x3, 0xff,
0x80, 0x0, 0x0, 0x7, 0x83, 0xc0, 0x0, 0xb,
@ -400,6 +372,21 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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+EB97 "" */
0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xf0,
@ -466,6 +453,19 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -565,30 +565,30 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 747, .adv_w = 384, .box_w = 12, .box_h = 18, .ofs_x = 6, .ofs_y = 3},
{.bitmap_index = 801, .adv_w = 384, .box_w = 16, .box_h = 18, .ofs_x = 4, .ofs_y = 3},
{.bitmap_index = 873, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 937, .adv_w = 384, .box_w = 16, .box_h = 12, .ofs_x = 4, .ofs_y = 6},
{.bitmap_index = 985, .adv_w = 384, .box_w = 14, .box_h = 14, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 1034, .adv_w = 384, .box_w = 18, .box_h = 12, .ofs_x = 3, .ofs_y = 6},
{.bitmap_index = 1088, .adv_w = 384, .box_w = 4, .box_h = 16, .ofs_x = 10, .ofs_y = 4},
{.bitmap_index = 1104, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 1168, .adv_w = 384, .box_w = 24, .box_h = 17, .ofs_x = 0, .ofs_y = 3},
{.bitmap_index = 937, .adv_w = 384, .box_w = 14, .box_h = 14, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 986, .adv_w = 384, .box_w = 18, .box_h = 12, .ofs_x = 3, .ofs_y = 6},
{.bitmap_index = 1040, .adv_w = 384, .box_w = 4, .box_h = 16, .ofs_x = 10, .ofs_y = 4},
{.bitmap_index = 1056, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 1120, .adv_w = 384, .box_w = 24, .box_h = 17, .ofs_x = 0, .ofs_y = 3},
{.bitmap_index = 1222, .adv_w = 384, .box_w = 16, .box_h = 12, .ofs_x = 4, .ofs_y = 6},
{.bitmap_index = 1270, .adv_w = 384, .box_w = 18, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 1342, .adv_w = 384, .box_w = 18, .box_h = 17, .ofs_x = 3, .ofs_y = 4},
{.bitmap_index = 1419, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.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 = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 1775, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1875, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1975, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 2055, .adv_w = 384, .box_w = 16, .box_h = 18, .ofs_x = 4, .ofs_y = 3},
{.bitmap_index = 2127, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 2207, .adv_w = 384, .box_w = 24, .box_h = 23, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 2345, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2426, .adv_w = 384, .box_w = 20, .box_h = 18, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 2516, .adv_w = 384, .box_w = 18, .box_h = 20, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 2606, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 2686, .adv_w = 384, .box_w = 18, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 2758, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 1419, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 1499, .adv_w = 384, .box_w = 20, .box_h = 19, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 1594, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.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 = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 1874, .adv_w = 384, .box_w = 16, .box_h = 18, .ofs_x = 4, .ofs_y = 3},
{.bitmap_index = 1946, .adv_w = 384, .box_w = 20, .box_h = 16, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 2026, .adv_w = 384, .box_w = 24, .box_h = 23, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 2164, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2245, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 2345, .adv_w = 384, .box_w = 20, .box_h = 18, .ofs_x = 2, .ofs_y = 3},
{.bitmap_index = 2435, .adv_w = 384, .box_w = 18, .box_h = 20, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 2525, .adv_w = 384, .box_w = 16, .box_h = 20, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 2605, .adv_w = 384, .box_w = 18, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 2677, .adv_w = 384, .box_w = 20, .box_h = 20, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 2777, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2858, .adv_w = 384, .box_w = 18, .box_h = 18, .ofs_x = 3, .ofs_y = 3},
{.bitmap_index = 2939, .adv_w = 384, .box_w = 22, .box_h = 16, .ofs_x = 1, .ofs_y = 4},
{.bitmap_index = 3027, .adv_w = 384, .box_w = 16, .box_h = 16, .ofs_x = 4, .ofs_y = 4},
@ -603,10 +603,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
static const uint16_t unicode_list_0[] = {
0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x485, 0x488, 0x48d,
0x48f, 0x490, 0x4f9, 0x600, 0x62b, 0x74f, 0x757, 0x76a,
0x771, 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2,
0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xea1, 0xee3, 0xf4b,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, 0x48f,
0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, 0x773,
0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, 0xa52,
0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, 0xea1, 0xee3, 0xf4b,
0x1017, 0x15db, 0x1782
};

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* 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,0xE5CA,0xE92E,0xE326,0xEB97,0xE745,0xEC1C,0xE2C7,0xF720,0xF090,0xE8AF,0xE30F,0xE8FD,0xE9F4,0xE3F4,0xE316,0xE90F,0xE894,0xE9B9,0xE159,0xE5D2,0xE28D,0xE5D4,0xE405,0xE89C,0xF8C7,0xE5D5,0xE8B6,0xE8B8,0xE9F7,0xE55D,0xF028,0xE1E0,0xE63E,0xE1A7 --format lvgl -o ../source-fonts/material_symbols_shared_32.c --force-fast-kern-format
* 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 --format lvgl -o ../source-fonts/material_symbols_shared_32.c --force-fast-kern-format
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@ -274,19 +274,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7f, 0xc0, 0x7f, 0xc1, 0xe4, 0x1, 0xe4, 0x1,
0xe4,
/* U+E5CA "" */
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+E5CD "" */
0x24, 0x0, 0x0, 0x1, 0x8b, 0xd0, 0x0, 0x0,
0x7e, 0x7f, 0x40, 0x0, 0x1f, 0xd1, 0xfd, 0x0,
@ -364,6 +351,19 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -403,33 +403,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa,
/* U+E894 "" */
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+E89C "" */
0x6, 0xaa, 0xaa, 0x90, 0x0, 0x3, 0xff, 0xff,
0xff, 0x80, 0x0, 0xbf, 0xff, 0xff, 0xfe, 0x0,
@ -477,26 +450,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x4,
/* U+E8B6 "" */
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+E8B8 "" */
0x0, 0x0, 0x6, 0xa9, 0x0, 0x0, 0x0, 0x0,
0x1, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x3f,
@ -663,6 +616,33 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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+EB97 "" */
0xb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xaa,
@ -778,6 +758,26 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
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,
@ -934,30 +934,30 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 1409, .adv_w = 512, .box_w = 16, .box_h = 24, .ofs_x = 8, .ofs_y = 4},
{.bitmap_index = 1505, .adv_w = 512, .box_w = 22, .box_h = 24, .ofs_x = 5, .ofs_y = 4},
{.bitmap_index = 1637, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 1758, .adv_w = 512, .box_w = 22, .box_h = 16, .ofs_x = 5, .ofs_y = 8},
{.bitmap_index = 1846, .adv_w = 512, .box_w = 18, .box_h = 18, .ofs_x = 7, .ofs_y = 7},
{.bitmap_index = 1927, .adv_w = 512, .box_w = 24, .box_h = 16, .ofs_x = 4, .ofs_y = 8},
{.bitmap_index = 2023, .adv_w = 512, .box_w = 6, .box_h = 22, .ofs_x = 13, .ofs_y = 5},
{.bitmap_index = 2056, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 2177, .adv_w = 512, .box_w = 32, .box_h = 23, .ofs_x = 0, .ofs_y = 4},
{.bitmap_index = 1758, .adv_w = 512, .box_w = 18, .box_h = 18, .ofs_x = 7, .ofs_y = 7},
{.bitmap_index = 1839, .adv_w = 512, .box_w = 24, .box_h = 16, .ofs_x = 4, .ofs_y = 8},
{.bitmap_index = 1935, .adv_w = 512, .box_w = 6, .box_h = 22, .ofs_x = 13, .ofs_y = 5},
{.bitmap_index = 1968, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 2089, .adv_w = 512, .box_w = 32, .box_h = 23, .ofs_x = 0, .ofs_y = 4},
{.bitmap_index = 2273, .adv_w = 512, .box_w = 22, .box_h = 16, .ofs_x = 5, .ofs_y = 8},
{.bitmap_index = 2361, .adv_w = 512, .box_w = 25, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 2499, .adv_w = 512, .box_w = 24, .box_h = 22, .ofs_x = 4, .ofs_y = 5},
{.bitmap_index = 2631, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.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 = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 3307, .adv_w = 512, .box_w = 26, .box_h = 28, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 3489, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 3685, .adv_w = 512, .box_w = 20, .box_h = 28, .ofs_x = 6, .ofs_y = 2},
{.bitmap_index = 3825, .adv_w = 512, .box_w = 22, .box_h = 24, .ofs_x = 5, .ofs_y = 4},
{.bitmap_index = 3957, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5},
{.bitmap_index = 4111, .adv_w = 512, .box_w = 32, .box_h = 31, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 4359, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 4503, .adv_w = 512, .box_w = 28, .box_h = 24, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 4671, .adv_w = 512, .box_w = 24, .box_h = 28, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 4839, .adv_w = 512, .box_w = 22, .box_h = 28, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 4993, .adv_w = 512, .box_w = 25, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 5131, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 2631, .adv_w = 512, .box_w = 22, .box_h = 28, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 2785, .adv_w = 512, .box_w = 28, .box_h = 26, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 2967, .adv_w = 512, .box_w = 26, .box_h = 28, .ofs_x = 3, .ofs_y = 2},
{.bitmap_index = 3149, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 3345, .adv_w = 512, .box_w = 20, .box_h = 28, .ofs_x = 6, .ofs_y = 2},
{.bitmap_index = 3485, .adv_w = 512, .box_w = 22, .box_h = 24, .ofs_x = 5, .ofs_y = 4},
{.bitmap_index = 3617, .adv_w = 512, .box_w = 28, .box_h = 22, .ofs_x = 2, .ofs_y = 5},
{.bitmap_index = 3771, .adv_w = 512, .box_w = 32, .box_h = 31, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 4019, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 4163, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 4359, .adv_w = 512, .box_w = 28, .box_h = 24, .ofs_x = 2, .ofs_y = 4},
{.bitmap_index = 4527, .adv_w = 512, .box_w = 24, .box_h = 28, .ofs_x = 4, .ofs_y = 2},
{.bitmap_index = 4695, .adv_w = 512, .box_w = 22, .box_h = 28, .ofs_x = 5, .ofs_y = 2},
{.bitmap_index = 4849, .adv_w = 512, .box_w = 25, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
{.bitmap_index = 4987, .adv_w = 512, .box_w = 28, .box_h = 28, .ofs_x = 2, .ofs_y = 2},
{.bitmap_index = 5183, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 5327, .adv_w = 512, .box_w = 24, .box_h = 24, .ofs_x = 4, .ofs_y = 4},
{.bitmap_index = 5471, .adv_w = 512, .box_w = 30, .box_h = 22, .ofs_x = 1, .ofs_y = 5},
{.bitmap_index = 5636, .adv_w = 512, .box_w = 22, .box_h = 22, .ofs_x = 5, .ofs_y = 5},
@ -972,10 +972,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
static const uint16_t unicode_list_0[] = {
0x0, 0x14, 0x62, 0x9b, 0x148, 0x182, 0x1ca, 0x1d1,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x485, 0x488, 0x48d,
0x48f, 0x490, 0x4f9, 0x600, 0x62b, 0x74f, 0x757, 0x76a,
0x771, 0x773, 0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2,
0xa52, 0xa87, 0xad7, 0xdfb, 0xe05, 0xea1, 0xee3, 0xf4b,
0x1e1, 0x2af, 0x2c0, 0x418, 0x47e, 0x488, 0x48d, 0x48f,
0x490, 0x4f9, 0x523, 0x600, 0x62b, 0x757, 0x76a, 0x773,
0x7b8, 0x7ca, 0x7e9, 0x874, 0x8af, 0x8b2, 0x8c2, 0xa52,
0xa87, 0xad7, 0xdfb, 0xe05, 0xe35, 0xea1, 0xee3, 0xf4b,
0x1017, 0x15db, 0x1782
};

View File

@ -92,6 +92,7 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_obj_clean),
DEFINE_MODULE_SYMBOL(lv_obj_create),
DEFINE_MODULE_SYMBOL(lv_obj_delete),
DEFINE_MODULE_SYMBOL(lv_obj_delete_async),
DEFINE_MODULE_SYMBOL(lv_obj_add_event_cb),
DEFINE_MODULE_SYMBOL(lv_obj_add_flag),
DEFINE_MODULE_SYMBOL(lv_obj_add_state),
@ -155,6 +156,7 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_obj_set_style_margin_left),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_margin_right),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_margin_all),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_min_width),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_pad_all),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_pad_hor),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_pad_ver),
@ -216,6 +218,8 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_obj_set_style_max_height),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_width),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_height),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_clip_corner),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_shadow_color),
// lv_font
DEFINE_MODULE_SYMBOL(lv_font_get_bitmap_fmt_txt),
DEFINE_MODULE_SYMBOL(lv_font_get_default),

View File

@ -8,7 +8,7 @@
extern "C" {
error_t service_paths_get_user_data_directory(const char* service_id, char* out_path, size_t out_path_size) {
char root[192];
char root[FILE_MAX_PATH_STRING_LENGTH];
error_t error = paths_get_data_path(root, sizeof(root));
if (error != ERROR_NONE) {
return error;
@ -21,7 +21,7 @@ error_t service_paths_get_user_data_directory(const char* service_id, char* out_
}
error_t service_paths_get_user_data_path(const char* service_id, const char* child_path, char* out_path, size_t out_path_size) {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
error_t error = service_paths_get_user_data_directory(service_id, directory, sizeof(directory));
if (error != ERROR_NONE) {
return error;
@ -34,7 +34,7 @@ error_t service_paths_get_user_data_path(const char* service_id, const char* chi
}
error_t service_paths_get_assets_directory(const char* service_id, char* out_path, size_t out_path_size) {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
error_t error = service_paths_get_user_data_directory(service_id, directory, sizeof(directory));
if (error != ERROR_NONE) {
return error;
@ -47,7 +47,7 @@ error_t service_paths_get_assets_directory(const char* service_id, char* out_pat
}
error_t service_paths_get_assets_path(const char* service_id, const char* child_path, char* out_path, size_t out_path_size) {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
error_t error = service_paths_get_assets_directory(service_id, directory, sizeof(directory));
if (error != ERROR_NONE) {
return error;

View File

@ -8,7 +8,7 @@
#include <string>
TEST_CASE("paths_get_data_path returns a non-empty path") {
char buffer[192];
char buffer[FILE_MAX_PATH_STRING_LENGTH];
REQUIRE_EQ(paths_get_data_path(buffer, sizeof(buffer)), ERROR_NONE);
CHECK_GT(std::strlen(buffer), 0);
}
@ -19,10 +19,10 @@ TEST_CASE("paths_get_data_path reports overflow for a too-small buffer") {
}
TEST_CASE("service_paths_get_user_data_directory includes the service id") {
char root[192];
char root[FILE_MAX_PATH_STRING_LENGTH];
REQUIRE_EQ(paths_get_data_path(root, sizeof(root)), ERROR_NONE);
char buffer[224];
char buffer[FILE_MAX_PATH_STRING_LENGTH];
CHECK_EQ(service_paths_get_user_data_directory("my-service", buffer, sizeof(buffer)), ERROR_NONE);
std::string expected = std::string(root) + "/service/my-service";
@ -30,7 +30,7 @@ TEST_CASE("service_paths_get_user_data_directory includes the service id") {
}
TEST_CASE("service_paths_get_user_data_path appends the child path") {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
REQUIRE_EQ(service_paths_get_user_data_directory("my-service", directory, sizeof(directory)), ERROR_NONE);
char buffer[256];
@ -41,10 +41,10 @@ TEST_CASE("service_paths_get_user_data_path appends the child path") {
}
TEST_CASE("service_paths_get_assets_directory is nested under the user data directory") {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
REQUIRE_EQ(service_paths_get_user_data_directory("my-service", directory, sizeof(directory)), ERROR_NONE);
char buffer[256];
char buffer[FILE_MAX_PATH_STRING_LENGTH];
CHECK_EQ(service_paths_get_assets_directory("my-service", buffer, sizeof(buffer)), ERROR_NONE);
std::string expected = std::string(directory) + "/assets";
@ -52,10 +52,10 @@ TEST_CASE("service_paths_get_assets_directory is nested under the user data dire
}
TEST_CASE("service_paths_get_assets_path appends the child path") {
char directory[224];
char directory[FILE_MAX_PATH_STRING_LENGTH];
REQUIRE_EQ(service_paths_get_assets_directory("my-service", directory, sizeof(directory)), ERROR_NONE);
char buffer[256];
char buffer[FILE_MAX_PATH_STRING_LENGTH];
CHECK_EQ(service_paths_get_assets_path("my-service", "icon.png", buffer, sizeof(buffer)), ERROR_NONE);
std::string expected = std::string(directory) + "/icon.png";

View File

@ -28,7 +28,10 @@ if (DEFINED ENV{ESP_IDF_VERSION})
endif ()
endif ()
idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc)
idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc espressif__esp_audio_codec)
if ("${IDF_TARGET}" STREQUAL "esp32s3" OR "${IDF_TARGET}" STREQUAL "esp32p4")
idf_component_optional_requires(PRIVATE espressif__usb_host_uac)
endif ()
if ("${IDF_TARGET}" STREQUAL "esp32p4")
# Force-links esp32p4_libc_compat.c's __issignalingf() shim - nothing references it until

View File

@ -0,0 +1,9 @@
description: ESP32 USB Host UAC manager (installs the USB Audio Class client)
compatible: "espressif,esp32-usbhost-uac"
properties:
_unused:
type: int
default: 0
description: Placeholder required by the binding schema; this driver has no device-tree configuration.

View File

@ -12,6 +12,7 @@ DEFINE_DEVICETREE(esp32_usbhost, struct Esp32UsbHostConfig)
DEFINE_DEVICETREE(esp32_usbhost_hid, struct Esp32UsbHostChildConfig)
DEFINE_DEVICETREE(esp32_usbhost_midi, struct Esp32UsbHostChildConfig)
DEFINE_DEVICETREE(esp32_usbhost_msc, struct Esp32UsbHostChildConfig)
DEFINE_DEVICETREE(esp32_usbhost_uac, struct Esp32UsbHostChildConfig)
#ifdef __cplusplus
}

View File

@ -15,7 +15,7 @@ void release_pin(GpioDescriptor** gpio_descriptor);
* If the pin spec is invalid, the pointer is set to null.
* @return true if the pin was acquired successfully
*/
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor);
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor, GpioOwnerType owner = GPIO_OWNER_GPIO);
/**
* Safely acquire the native pin value.

View File

@ -9,13 +9,13 @@ void release_pin(GpioDescriptor** gpio_descriptor) {
*gpio_descriptor = nullptr;
}
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor) {
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor, GpioOwnerType owner) {
if (pin_spec.gpio_controller == nullptr) {
*gpio_descriptor = nullptr;
return true;
}
*gpio_descriptor = gpio_descriptor_acquire(pin_spec.gpio_controller, pin_spec.pin, pin_spec.flags | direction_flags, GPIO_OWNER_GPIO);
*gpio_descriptor = gpio_descriptor_acquire(pin_spec.gpio_controller, pin_spec.pin, pin_spec.flags | direction_flags, owner);
if (*gpio_descriptor == nullptr) {
LOG_E(TAG, "Failed to acquire pin %u from %s", pin_spec.pin, pin_spec.gpio_controller->name);
}

View File

@ -153,14 +153,14 @@ static error_t start(Device* device) {
auto dts_config = GET_CONFIG(device);
auto& sda_spec = dts_config->pinSda;
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, sda_spec.flags | GPIO_FLAG_DIRECTION_INPUT_OUTPUT, GPIO_OWNER_GPIO);
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, sda_spec.flags | GPIO_FLAG_DIRECTION_INPUT_OUTPUT, GPIO_OWNER_PERIPHERAL);
if (!sda_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", sda_spec.pin);
return ERROR_RESOURCE;
}
auto& scl_spec = dts_config->pinScl;
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, scl_spec.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, scl_spec.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_PERIPHERAL);
if (!scl_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", scl_spec.pin);
gpio_descriptor_release(sda_descriptor);

View File

@ -65,11 +65,11 @@ struct Esp32I2sInternal {
auto& data_out_spec = dts_config->pin_data_out;
auto& mclk_spec = dts_config->pin_mclk;
bool success = acquire_pin_or_set_null(ws_spec, GPIO_FLAG_DIRECTION_OUTPUT, &ws_descriptor) &&
acquire_pin_or_set_null(bclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &bclk_descriptor) &&
acquire_pin_or_set_null(data_in_spec, GPIO_FLAG_DIRECTION_INPUT, &data_in_descriptor) &&
acquire_pin_or_set_null(data_out_spec, GPIO_FLAG_DIRECTION_OUTPUT, &data_out_descriptor) &&
acquire_pin_or_set_null(mclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &mclk_descriptor);
bool success = acquire_pin_or_set_null(ws_spec, GPIO_FLAG_DIRECTION_OUTPUT, &ws_descriptor, GPIO_OWNER_PERIPHERAL) &&
acquire_pin_or_set_null(bclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &bclk_descriptor, GPIO_OWNER_PERIPHERAL) &&
acquire_pin_or_set_null(data_in_spec, GPIO_FLAG_DIRECTION_INPUT, &data_in_descriptor, GPIO_OWNER_PERIPHERAL) &&
acquire_pin_or_set_null(data_out_spec, GPIO_FLAG_DIRECTION_OUTPUT, &data_out_descriptor, GPIO_OWNER_PERIPHERAL) &&
acquire_pin_or_set_null(mclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &mclk_descriptor, GPIO_OWNER_PERIPHERAL);
if (!success) {
cleanup_pins();

Some files were not shown because too many files have changed in this diff Show More