From 8cd9454d00ed389164d55541c6c6842d7bb1f8b6 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Wed, 4 Feb 2026 20:48:49 +0530 Subject: [PATCH] lib: Add support for text rendering on splash screen Introduce FRAMEBUFFER_SPLASH_TEXT to allow rendering status messages directly into the linear framebuffer. This enables displaying dynamic information, such as battery levels or system status, during the bootsplash stage without requiring complex graphics libraries. Changes: - Add Kconfig option to toggle framebuffer text support. - User to call `render_text_to_framebuffer` to display the text message. - Include render_text.c in ramstage build when FRAMEBUFFER_SPLASH_TEXT is enabled. - Create 24x32 font table entry using GoogleSansFlex_24pt-Medium.ttf. TEST=Able to build google/fatcat. Change-Id: I6ac25d8d8a9d3d77a9cc2f8c6e0139268b2066b9 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/91092 Reviewed-by: Kapil Porwal Tested-by: build bot (Jenkins) --- src/include/bootsplash.h | 13 + src/lib/Kconfig | 40 + src/lib/Makefile.mk | 2 + ...font_table_google_sans_flex_medium_24x32.c | 686 ++++++++++++++++++ src/lib/fonts/fonts.h | 16 + src/lib/render_text.c | 210 ++++++ 6 files changed, 967 insertions(+) create mode 100644 src/lib/fonts/font_table_google_sans_flex_medium_24x32.c create mode 100644 src/lib/fonts/fonts.h create mode 100644 src/lib/render_text.c diff --git a/src/include/bootsplash.h b/src/include/bootsplash.h index 5caebd278d..cd02f7382e 100644 --- a/src/include/bootsplash.h +++ b/src/include/bootsplash.h @@ -20,6 +20,16 @@ enum bootsplash_type { BOOTSPLASH_MAX_NUM, }; +enum bootsplash_text_type { + /* Indicates a bootsplash text message appear at the center of the screen. */ + BOOTSPLASH_TEXT_CENTER, + /* Indicates a bootsplash text message appear at the footer of the screen. */ + BOOTSPLASH_TEXT_FOOTER, + + /* It's used to determine the total number of bootsplash types. */ + BOOTSPLASH_TEXT_MAX_NUM, +}; + /** * Sets up the framebuffer with the bootsplash.jpg from cbfs. * Returns 0 on success @@ -157,6 +167,9 @@ void load_and_convert_bmp_to_blt(uintptr_t *logo, size_t *logo_size, void convert_bmp_to_blt(uintptr_t logo, size_t logo_size, uintptr_t *blt, size_t *blt_size, uint32_t *pixel_height, uint32_t *pixel_width, enum lb_fb_orientation orientation); +void render_text_to_framebuffer(struct logo_config *config, const char *str, + enum bootsplash_text_type type); +bool platform_get_splash_text(enum bootsplash_type logo_type, char *msg, size_t msg_max); /* Mainboard-specific override for logo filenames */ const char *mainboard_bmp_logo_filename(void); diff --git a/src/lib/Kconfig b/src/lib/Kconfig index d70374d758..38cc459086 100644 --- a/src/lib/Kconfig +++ b/src/lib/Kconfig @@ -287,6 +287,46 @@ config PLATFORM_OFF_MODE_CHARGING_INDICATOR_LOGO_PATH string "Path to off-mode charging logo file" default "3rdparty/blobs/mainboard/\$(MAINBOARDDIR)/off_mode_charging.bmp" +config FRAMEBUFFER_SPLASH_TEXT + bool "Enable splash screen text" + default n + help + Enable logic to render bitmapped text strings directly into + the linear framebuffer during the splash screen stage. This + method uses a bitmapped font table to display system + status messages, such as battery charging levels. + +if FRAMEBUFFER_SPLASH_TEXT + +choice + prompt "Font Selection" + default FONT_GOOGLE_SANS_FLEX_MEDIUM_24X32 + +config FONT_GOOGLE_SANS_FLEX_MEDIUM_24X32 + bool "Google Sans Flex Medium 24x32" + help + Use the Google Sans Medium font table generated from + GoogleSansFlex_24pt-Medium.ttf using `generate_font.py` script. + Dimensions: 24x32 pixels. + +endchoice + +config FONT_WIDTH + int + default 24 if FONT_GOOGLE_SANS_FLEX_MEDIUM_24X32 + default 16 + help + The width of the font canvas in pixels. + +config FONT_HEIGHT + int + default 32 if FONT_GOOGLE_SANS_FLEX_MEDIUM_24X32 + default 24 + help + The height of the font canvas in pixels. + +endif # FRAMEBUFFER_SPLASH_TEXT + endmenu config HAVE_EARLY_POWEROFF_SUPPORT diff --git a/src/lib/Makefile.mk b/src/lib/Makefile.mk index 0405cbeb5b..3ffdfa807c 100644 --- a/src/lib/Makefile.mk +++ b/src/lib/Makefile.mk @@ -149,6 +149,8 @@ ramstage-y += wrdd.c ramstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c ramstage-$(CONFIG_BMP_LOGO) += bmp_logo.c ramstage-$(CONFIG_BMP_LOGO) += render_bmp.c +ramstage-$(CONFIG_FRAMEBUFFER_SPLASH_TEXT) += render_text.c +ramstage-$(CONFIG_FONT_GOOGLE_SANS_FLEX_MEDIUM_24X32) += fonts/font_table_google_sans_flex_medium_24x32.c ramstage-$(CONFIG_BOOTSPLASH) += bootsplash.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c diff --git a/src/lib/fonts/font_table_google_sans_flex_medium_24x32.c b/src/lib/fonts/font_table_google_sans_flex_medium_24x32.c new file mode 100644 index 0000000000..7b211698bc --- /dev/null +++ b/src/lib/fonts/font_table_google_sans_flex_medium_24x32.c @@ -0,0 +1,686 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + * Source: GoogleSansFlex_24pt-Medium.ttf + * Command: python generate_font.py GoogleSansFlex_24pt-Medium.ttf --width 24 --height 32 + */ + +#include + +#define FONT_WIDTH 24 +#define FONT_HEIGHT 32 +#define FONT_START_CHAR 32 +#define FONT_END_CHAR 126 +#define FONT_NUM_CHARS (FONT_END_CHAR - FONT_START_CHAR + 1) + +const uint32_t font_table[FONT_NUM_CHARS][FONT_HEIGHT] = { + [0x20 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ' ' */ + [0x21 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x60000000, 0x60000000, + 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, + 0x60000000, 0x60000000, 0x00000000, 0x00000000, 0x60000000, 0xf0000000, 0x60000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '!' */ + [0x22 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xec000000, 0xec000000, + 0xec000000, 0xec000000, 0xec000000, 0xec000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '"' */ + [0x23 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e300000, 0x0c700000, + 0x0c600000, 0x0c600000, 0x0c600000, 0x7ffc0000, 0xfffc0000, 0x18600000, 0x18e00000, 0x18c00000, + 0xfff80000, 0xfff80000, 0x18c00000, 0x38c00000, 0x30c00000, 0x31800000, 0x31800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '#' */ + [0x24 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x06000000, 0x1f800000, 0x3fe00000, + 0x76f00000, 0x66600000, 0x66000000, 0x76000000, 0x7e000000, 0x3f000000, 0x0fc00000, 0x07e00000, + 0x06700000, 0x06700000, 0xe6300000, 0xe6700000, 0x7ee00000, 0x3fe00000, 0x1f800000, 0x06000000, + 0x06000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '$' */ + [0x25 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c020000, 0x7e070000, + 0xc7060000, 0xc30c0000, 0xc31c0000, 0xc3180000, 0xfe300000, 0x7c700000, 0x00600000, 0x00c00000, + 0x01cf0000, 0x039fc000, 0x0318c000, 0x0730e000, 0x0e306000, 0x0c38c000, 0x1c1fc000, 0x180f8000, + 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '%' */ + [0x26 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000, 0x1f800000, + 0x1fc00000, 0x38e00000, 0x38000000, 0x38000000, 0x1c000000, 0x1e000000, 0x3e000000, 0x77000000, + 0xe3800000, 0xe1cc0000, 0xe0ec0000, 0xe0fc0000, 0xe0780000, 0x70780000, 0x7ffc0000, 0x1fd80000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '&' */ + [0x27 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '\'' */ + [0x28 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c000000, 0x1e000000, 0x1c000000, 0x38000000, + 0x30000000, 0x70000000, 0x70000000, 0x60000000, 0x60000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0x60000000, 0x60000000, 0x70000000, 0x70000000, 0x38000000, 0x38000000, 0x1c000000, + 0x1e000000, 0x0c000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '(' */ + [0x29 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x60000000, 0x70000000, 0x70000000, 0x38000000, + 0x18000000, 0x1c000000, 0x1c000000, 0x0c000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, + 0x0e000000, 0x0e000000, 0x0c000000, 0x1c000000, 0x1c000000, 0x18000000, 0x38000000, 0x70000000, + 0xf0000000, 0x60000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ')' */ + [0x2a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x18000000, 0x18000000, + 0x98800000, 0xff800000, 0xff000000, 0x1c000000, 0x3e000000, 0x67000000, 0x62000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '*' */ + [0x2b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0xffe00000, + 0xffe00000, 0xffe00000, 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '+' */ + [0x2c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf0000000, 0xf0000000, 0x70000000, 0x60000000, + 0xc0000000, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ',' */ + [0x2d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xff000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '-' */ + [0x2e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf0000000, 0xf0000000, 0x60000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '.' */ + [0x2f - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000000, 0x06000000, + 0x06000000, 0x0e000000, 0x0c000000, 0x0c000000, 0x1c000000, 0x18000000, 0x18000000, 0x38000000, + 0x38000000, 0x30000000, 0x70000000, 0x70000000, 0x60000000, 0x60000000, 0xe0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '/' */ + [0x30 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03000000, 0x1fc00000, + 0x3fe00000, 0x38700000, 0x70380000, 0x60380000, 0xe0380000, 0xe0180000, 0xe0180000, 0xe0180000, + 0xe0180000, 0xe0180000, 0xe0380000, 0x60380000, 0x70300000, 0x38f00000, 0x3fe00000, 0x0fc00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '0' */ + [0x31 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c000000, 0x3c000000, + 0x7c000000, 0xec000000, 0xcc000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, + 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x0c000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '1' */ + [0x32 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c000000, 0x3f800000, + 0x7fc00000, 0xf1c00000, 0x60e00000, 0x00e00000, 0x00e00000, 0x01c00000, 0x01c00000, 0x03800000, + 0x07000000, 0x0e000000, 0x1c000000, 0x38000000, 0x70000000, 0xe0000000, 0xffe00000, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '2' */ + [0x33 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c000000, 0x3f800000, + 0x7fc00000, 0xe1c00000, 0x60e00000, 0x00e00000, 0x00c00000, 0x01c00000, 0x0f800000, 0x0f800000, + 0x01c00000, 0x00e00000, 0x00e00000, 0x40e00000, 0xe0e00000, 0xf1e00000, 0x7fc00000, 0x3f800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '3' */ + [0x34 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01c00000, 0x01c00000, + 0x03c00000, 0x07c00000, 0x0ec00000, 0x0cc00000, 0x1cc00000, 0x38c00000, 0x30c00000, 0x70c00000, + 0xe0c00000, 0xfff00000, 0xfff00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '4' */ + [0x35 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fe00000, 0x7fe00000, + 0x70000000, 0x70000000, 0x60000000, 0x60000000, 0x6f800000, 0x7fc00000, 0x79e00000, 0x20e00000, + 0x00700000, 0x00700000, 0x60700000, 0xe0600000, 0x70e00000, 0x7fc00000, 0x3f800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '5' */ + [0x36 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000, 0x03800000, + 0x07800000, 0x07000000, 0x0e000000, 0x1c000000, 0x3c000000, 0x3f800000, 0x7fc00000, 0x79e00000, + 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0x70e00000, 0x7fc00000, 0x1f800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '6' */ + [0x37 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffe00000, 0xffe00000, + 0x00c00000, 0x01c00000, 0x01800000, 0x03800000, 0x03000000, 0x07000000, 0x0e000000, 0x0e000000, + 0x1c000000, 0x1c000000, 0x38000000, 0x38000000, 0x70000000, 0x70000000, 0xe0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '7' */ + [0x38 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x3f800000, + 0x7fc00000, 0x70e00000, 0x60e00000, 0x60e00000, 0x60e00000, 0x71c00000, 0x3f800000, 0x3fc00000, + 0x71e00000, 0xe0e00000, 0xe0600000, 0xe0700000, 0xe0600000, 0xf0e00000, 0x7fc00000, 0x3f800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '8' */ + [0x39 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x3f800000, + 0x7fc00000, 0xf0e00000, 0xe0600000, 0xc0700000, 0xc0700000, 0xe0700000, 0xe0e00000, 0x7be00000, + 0x3fc00000, 0x1fc00000, 0x03800000, 0x07000000, 0x0f000000, 0x0e000000, 0x1c000000, 0x18000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '9' */ + [0x3a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xf0000000, 0xf0000000, 0x60000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf0000000, 0xf0000000, 0x60000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ':' */ + [0x3b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x70000000, 0xf0000000, 0x70000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf0000000, 0xf0000000, 0x70000000, 0x60000000, + 0xc0000000, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ';' */ + [0x3c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00200000, 0x00e00000, 0x07e00000, 0x1f000000, 0x7c000000, + 0xe0000000, 0xfc000000, 0x1f000000, 0x07e00000, 0x00e00000, 0x00200000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '<' */ + [0x3d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffe00000, 0xffe00000, 0xffe00000, + 0x00000000, 0xffe00000, 0xffe00000, 0xffe00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '=' */ + [0x3e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe0000000, 0xf8000000, 0x3f000000, 0x07c00000, + 0x01c00000, 0x07c00000, 0x3f000000, 0xf8000000, 0xe0000000, 0x80000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '>' */ + [0x3f - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c000000, 0x3f800000, + 0x7fc00000, 0xe1c00000, 0x61c00000, 0x01c00000, 0x01c00000, 0x03800000, 0x07000000, 0x0e000000, + 0x0e000000, 0x0c000000, 0x0c000000, 0x00000000, 0x0c000000, 0x1e000000, 0x1e000000, 0x0e000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '?' */ + [0x40 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00e00000, + 0x07fc0000, 0x0f0f0000, 0x38038000, 0x3001c000, 0x61fcc000, 0x63fc6000, 0xc60c6000, 0xc60c6000, + 0xc60c6000, 0xc60c6000, 0xc60c6000, 0x671ee000, 0x63f7c000, 0x70c10000, 0x38000000, 0x1c000000, + 0x0ff80000, 0x03fc0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '@' */ + [0x41 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01c00000, 0x03c00000, + 0x03e00000, 0x07e00000, 0x07600000, 0x06700000, 0x0e700000, 0x0e300000, 0x0c380000, 0x1c380000, + 0x181c0000, 0x3ffc0000, 0x3ffc0000, 0x300e0000, 0x700e0000, 0x70060000, 0xe0070000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'A' */ + [0x42 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff800000, 0xffc00000, + 0xc0e00000, 0xc0600000, 0xc0600000, 0xc0600000, 0xc0e00000, 0xffc00000, 0xffc00000, 0xc0e00000, + 0xc0700000, 0xc0700000, 0xc0700000, 0xc0700000, 0xc0e00000, 0xffe00000, 0xff800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'B' */ + [0x43 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00c00000, 0x0ff80000, + 0x1ffe0000, 0x3c1e0000, 0x78040000, 0x70000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0x70040000, 0x78060000, 0x3e1e0000, 0x1ffc0000, 0x07f80000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'C' */ + [0x44 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff800000, 0xffe00000, + 0xc1f00000, 0xc0780000, 0xc0380000, 0xc01c0000, 0xc01c0000, 0xc01c0000, 0xc01c0000, 0xc01c0000, + 0xc01c0000, 0xc01c0000, 0xc0380000, 0xc0780000, 0xc1f00000, 0xffe00000, 0xff800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'D' */ + [0x45 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffc00000, 0xffc00000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xff800000, 0xff800000, 0xff800000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xffc00000, 0xffc00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'E' */ + [0x46 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffc00000, 0xffc00000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xff800000, 0xff800000, 0xff800000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'F' */ + [0x47 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00c00000, 0x07f80000, + 0x1ffe0000, 0x3c0e0000, 0x78040000, 0x70000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe07f8000, + 0xe07f8000, 0xe0018000, 0xe0038000, 0x70038000, 0x78070000, 0x3e0f0000, 0x1ffe0000, 0x07f80000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'G' */ + [0x48 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0180000, 0xc0180000, + 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0xfff80000, 0xfff80000, 0xc0180000, + 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0xc0180000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'H' */ + [0x49 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'I' */ + [0x4a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00600000, 0x00600000, + 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000, + 0x00600000, 0x00600000, 0x20600000, 0xe0e00000, 0x71e00000, 0x3fc00000, 0x1f800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'J' */ + [0x4b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0780000, 0xc0f00000, + 0xc1e00000, 0xc1c00000, 0xc3800000, 0xc7000000, 0xce000000, 0xde000000, 0xff000000, 0xff000000, + 0xf3800000, 0xe1c00000, 0xc1c00000, 0xc0e00000, 0xc0700000, 0xc0700000, 0xc0380000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'K' */ + [0x4c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000000, 0xc0000000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xffc00000, 0xffc00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'L' */ + [0x4d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf003c000, 0xf007c000, + 0xf007c000, 0xf807c000, 0xd80fc000, 0xdc0dc000, 0xdc1dc000, 0xcc1dc000, 0xce19c000, 0xc639c000, + 0xc731c000, 0xc771c000, 0xc371c000, 0xc3e1c000, 0xc1e1c000, 0xc1c1c000, 0xc1c1c000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'M' */ + [0x4e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0180000, 0xf0180000, + 0xf8180000, 0xf8180000, 0xdc180000, 0xcc180000, 0xce180000, 0xc7180000, 0xc7180000, 0xc3980000, + 0xc1d80000, 0xc1d80000, 0xc0f80000, 0xc0780000, 0xc0780000, 0xc0380000, 0xc0180000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'N' */ + [0x4f - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00c00000, 0x0ff80000, + 0x1ffe0000, 0x3c1f0000, 0x78070000, 0x70038000, 0xe0038000, 0xe001c000, 0xe001c000, 0xe001c000, + 0xe001c000, 0xe0018000, 0xe0038000, 0x70038000, 0x78070000, 0x3e1e0000, 0x1ffc0000, 0x07f80000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'O' */ + [0x50 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff800000, 0xffc00000, + 0xc1e00000, 0xc0e00000, 0xc0700000, 0xc0700000, 0xc0700000, 0xc0e00000, 0xc1e00000, 0xffc00000, + 0xff000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'P' */ + [0x51 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00c00000, 0x0ff80000, + 0x1ffe0000, 0x3c1f0000, 0x78070000, 0x70038000, 0xe0038000, 0xe001c000, 0xe001c000, 0xe001c000, + 0xe001c000, 0xe0018000, 0xe0338000, 0x703b8000, 0x781f0000, 0x3e1e0000, 0x1ffe0000, 0x07ff0000, + 0x00070000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'Q' */ + [0x52 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff800000, 0xffc00000, + 0xc1e00000, 0xc0e00000, 0xc0700000, 0xc0700000, 0xc0600000, 0xc0e00000, 0xffc00000, 0xff800000, + 0xc7000000, 0xc3800000, 0xc3800000, 0xc1c00000, 0xc0e00000, 0xc0e00000, 0xc0700000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'R' */ + [0x53 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x3f800000, + 0x7fc00000, 0x70e00000, 0xe0400000, 0xe0000000, 0xf0000000, 0x7c000000, 0x3f000000, 0x0fc00000, + 0x03e00000, 0x00e00000, 0x00700000, 0xc0700000, 0xe0700000, 0xf0e00000, 0x7fe00000, 0x3f800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'S' */ + [0x54 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000, + 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, + 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x0e000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'T' */ + [0x55 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe01c0000, 0xe01c0000, + 0xe01c0000, 0xe01c0000, 0xe01c0000, 0xe01c0000, 0xe01c0000, 0xe01c0000, 0xe01c0000, 0xe01c0000, + 0xe01c0000, 0xe01c0000, 0x60180000, 0x70380000, 0x78780000, 0x3ff00000, 0x1fe00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'U' */ + [0x56 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe00e0000, 0x700e0000, + 0x700c0000, 0x301c0000, 0x381c0000, 0x38180000, 0x18380000, 0x1c380000, 0x1c700000, 0x0c700000, + 0x0e600000, 0x0ee00000, 0x06e00000, 0x07c00000, 0x03c00000, 0x03c00000, 0x03800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'V' */ + [0x57 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0380e00, 0x70380c00, + 0x703c1c00, 0x707c1c00, 0x306c1c00, 0x386e1800, 0x38ee3800, 0x38e63800, 0x18c63000, 0x1dc73000, + 0x1dc37000, 0x0d837000, 0x0d83e000, 0x0f81e000, 0x0f01e000, 0x0701e000, 0x0701c000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'W' */ + [0x58 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x701e0000, 0x381c0000, + 0x38380000, 0x1c700000, 0x0e700000, 0x0ee00000, 0x07c00000, 0x03c00000, 0x03c00000, 0x07c00000, + 0x07e00000, 0x0e700000, 0x1c700000, 0x1c380000, 0x381c0000, 0x701c0000, 0xf00e0000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'X' */ + [0x59 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf01e0000, 0x701c0000, + 0x38380000, 0x1c700000, 0x1c700000, 0x0ee00000, 0x0ec00000, 0x07c00000, 0x03800000, 0x03800000, + 0x03800000, 0x03800000, 0x03800000, 0x03800000, 0x03800000, 0x03800000, 0x03800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'Y' */ + [0x5a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000, + 0x00f00000, 0x00e00000, 0x01c00000, 0x03c00000, 0x03800000, 0x07000000, 0x0e000000, 0x1e000000, + 0x1c000000, 0x38000000, 0x78000000, 0x70000000, 0xe0000000, 0xfff00000, 0xfff00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'Z' */ + [0x5b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfc000000, 0xfc000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xfc000000, 0xfc000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '[' */ + [0x5c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0x60000000, + 0x60000000, 0x70000000, 0x30000000, 0x30000000, 0x38000000, 0x18000000, 0x18000000, 0x1c000000, + 0x0c000000, 0x0c000000, 0x0e000000, 0x0e000000, 0x06000000, 0x07000000, 0x07000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '\\' */ + [0x5d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf8000000, 0xf8000000, 0x38000000, 0x38000000, + 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, + 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, + 0xf8000000, 0xf8000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* ']' */ + [0x5e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x0f000000, + 0x1f000000, 0x1b800000, 0x31c00000, 0x70c00000, 0xe0e00000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '^' */ + [0x5f - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfff00000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '_' */ + [0x60 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0x70000000, + 0x30000000, 0x30000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '`' */ + [0x61 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x7f800000, 0xf3c00000, 0x40e00000, 0x00e00000, + 0x1ee00000, 0x7fe00000, 0xe0e00000, 0xc0e00000, 0xc0e00000, 0xe1e00000, 0xffe00000, 0x7ee00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'a' */ + [0x62 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe3800000, 0xefe00000, 0xfff00000, 0xf0700000, 0xf0380000, 0xe0380000, + 0xe0380000, 0xe0380000, 0xe0380000, 0xf0380000, 0xf8700000, 0xffe00000, 0xefc00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'b' */ + [0x63 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x07000000, 0x3fc00000, 0x7fe00000, 0x70700000, 0xe0400000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xe0000000, 0xe0700000, 0x70e00000, 0x3fe00000, 0x1f800000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'c' */ + [0x64 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00300000, 0x00300000, + 0x00300000, 0x00300000, 0x0e300000, 0x3fb00000, 0x7ff00000, 0x70f00000, 0xe0700000, 0xc0300000, + 0xc0300000, 0xc0300000, 0xe0300000, 0xe0700000, 0x70f00000, 0x7ff00000, 0x1fb00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'd' */ + [0x65 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0f000000, 0x3fc00000, 0x7fe00000, 0x70e00000, 0xe0700000, + 0xc0700000, 0xfff00000, 0xc0000000, 0xe0000000, 0xe0400000, 0x70700000, 0x7fe00000, 0x1fc00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'e' */ + [0x66 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x1f000000, + 0x3f000000, 0x38000000, 0x30000000, 0x30000000, 0xfe000000, 0xfe000000, 0x30000000, 0x30000000, + 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'f' */ + [0x67 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x3fb00000, 0x7ff00000, 0xf0f00000, 0xe0700000, + 0xc0300000, 0xc0300000, 0xc0300000, 0xe0700000, 0xe0700000, 0x70f00000, 0x7fb00000, 0x1f300000, + 0x00300000, 0x20700000, 0xf0700000, 0x7fe00000, 0x3fc00000, 0x06000000, 0x00000000, 0x00000000, + }, /* 'g' */ + [0x68 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe3800000, 0xefc00000, 0xffe00000, 0xf0e00000, 0xe0700000, 0xe0700000, + 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'h' */ + [0x69 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x60000000, 0xf0000000, + 0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, + 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, 0x60000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'i' */ + [0x6a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30000000, 0x78000000, + 0x70000000, 0x00000000, 0x00000000, 0x00000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, + 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, + 0x30000000, 0x30000000, 0x70000000, 0xf0000000, 0xe0000000, 0x80000000, 0x00000000, 0x00000000, + }, /* 'j' */ + [0x6b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0100000, 0xe0e00000, 0xe1c00000, 0xe3800000, 0xe7000000, 0xee000000, + 0xff000000, 0xff000000, 0xf3800000, 0xe3c00000, 0xe1c00000, 0xe0e00000, 0xe0f00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'k' */ + [0x6c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'l' */ + [0x6d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x03030000, 0xefcfc000, 0xffffe000, 0xf0f0e000, 0xe0e06000, + 0xe0606000, 0xe0606000, 0xe0606000, 0xe0606000, 0xe0606000, 0xe0606000, 0xe0606000, 0xe0606000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'm' */ + [0x6e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x03800000, 0xefc00000, 0xffe00000, 0xf0e00000, 0xe0700000, + 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, 0xe0700000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'n' */ + [0x6f - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x07000000, 0x3fc00000, 0x7fe00000, 0x70700000, 0xe0300000, + 0xe0380000, 0xc0380000, 0xc0380000, 0xe0380000, 0xe0700000, 0x70f00000, 0x3fe00000, 0x1fc00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'o' */ + [0x70 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x03800000, 0xefe00000, 0xfff00000, 0xf0700000, 0xf0380000, + 0xe0380000, 0xe0380000, 0xe0380000, 0xe0380000, 0xf0380000, 0xf8700000, 0xffe00000, 0xefc00000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'p' */ + [0x71 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x3fb00000, 0x7ff00000, 0x70f00000, 0xe0700000, + 0xc0300000, 0xc0300000, 0xc0300000, 0xe0300000, 0xe0700000, 0x70f00000, 0x7ff00000, 0x1fb00000, + 0x00300000, 0x00300000, 0x00300000, 0x00300000, 0x00300000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'q' */ + [0x72 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x07000000, 0xef000000, 0xff000000, 0xf0000000, 0xe0000000, + 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, 0xe0000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'r' */ + [0x73 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x1c000000, 0x7f800000, 0xf3c00000, 0xe1800000, 0xe0000000, + 0xf8000000, 0x7f000000, 0x1f800000, 0x01c00000, 0x41c00000, 0xe1c00000, 0xff800000, 0x7f000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 's' */ + [0x74 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0xfe000000, 0xfe000000, 0x30000000, 0x30000000, + 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x3e000000, 0x1e000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 't' */ + [0x75 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xe0600000, 0xe0600000, 0xe0600000, 0xe0600000, 0xe0600000, + 0xe0600000, 0xe0600000, 0xe0600000, 0xe0e00000, 0x70e00000, 0x7fe00000, 0x3f600000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'u' */ + [0x76 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xe0380000, 0x60700000, 0x70700000, 0x30600000, 0x38e00000, + 0x38c00000, 0x19c00000, 0x1d800000, 0x0d800000, 0x0f800000, 0x0f000000, 0x07000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'v' */ + [0x77 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xe0e0e000, 0x60e0c000, 0x71f1c000, 0x71b1c000, 0x31b18000, + 0x33b98000, 0x3b1b8000, 0x1b1b0000, 0x1b1b0000, 0x1e0f0000, 0x0e0e0000, 0x0e0e0000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'w' */ + [0x78 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xf0700000, 0x70e00000, 0x39c00000, 0x1d800000, 0x0f800000, + 0x0f000000, 0x0f000000, 0x1f800000, 0x19800000, 0x39c00000, 0x70e00000, 0xe0700000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'x' */ + [0x79 - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xe0380000, 0x70700000, 0x70600000, 0x30e00000, 0x38e00000, + 0x18c00000, 0x1dc00000, 0x0d800000, 0x0f800000, 0x0f000000, 0x07000000, 0x07000000, 0x06000000, + 0x0e000000, 0x0c000000, 0x1c000000, 0x38000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'y' */ + [0x7a - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffc00000, 0xffc00000, 0x03800000, 0x07000000, 0x0e000000, + 0x0e000000, 0x1c000000, 0x38000000, 0x70000000, 0xe0000000, 0xffc00000, 0xffc00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* 'z' */ + [0x7b - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x1e000000, 0x38000000, 0x38000000, + 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x30000000, 0xf0000000, 0xf0000000, + 0x30000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, 0x38000000, + 0x1e000000, 0x0e000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '{' */ + [0x7c - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000000, 0xc0000000, 0xc0000000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, + 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '|' */ + [0x7d - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xe0000000, 0xf0000000, 0x70000000, 0x30000000, + 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x38000000, 0x1c000000, 0x1c000000, + 0x38000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x30000000, 0x70000000, + 0xf0000000, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '}' */ + [0x7e - FONT_START_CHAR] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7e700000, 0xffe00000, + 0xc3e00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, /* '~' */ +}; + +const uint8_t font_widths[FONT_NUM_CHARS] = { + [0x20 - FONT_START_CHAR] = 8, + [0x21 - FONT_START_CHAR] = 4, + [0x22 - FONT_START_CHAR] = 6, + [0x23 - FONT_START_CHAR] = 14, + [0x24 - FONT_START_CHAR] = 12, + [0x25 - FONT_START_CHAR] = 19, + [0x26 - FONT_START_CHAR] = 14, + [0x27 - FONT_START_CHAR] = 3, + [0x28 - FONT_START_CHAR] = 7, + [0x29 - FONT_START_CHAR] = 7, + [0x2a - FONT_START_CHAR] = 9, + [0x2b - FONT_START_CHAR] = 11, + [0x2c - FONT_START_CHAR] = 4, + [0x2d - FONT_START_CHAR] = 8, + [0x2e - FONT_START_CHAR] = 4, + [0x2f - FONT_START_CHAR] = 8, + [0x30 - FONT_START_CHAR] = 13, + [0x31 - FONT_START_CHAR] = 6, + [0x32 - FONT_START_CHAR] = 11, + [0x33 - FONT_START_CHAR] = 11, + [0x34 - FONT_START_CHAR] = 12, + [0x35 - FONT_START_CHAR] = 12, + [0x36 - FONT_START_CHAR] = 12, + [0x37 - FONT_START_CHAR] = 11, + [0x38 - FONT_START_CHAR] = 12, + [0x39 - FONT_START_CHAR] = 12, + [0x3a - FONT_START_CHAR] = 4, + [0x3b - FONT_START_CHAR] = 4, + [0x3c - FONT_START_CHAR] = 11, + [0x3d - FONT_START_CHAR] = 11, + [0x3e - FONT_START_CHAR] = 10, + [0x3f - FONT_START_CHAR] = 10, + [0x40 - FONT_START_CHAR] = 19, + [0x41 - FONT_START_CHAR] = 16, + [0x42 - FONT_START_CHAR] = 12, + [0x43 - FONT_START_CHAR] = 15, + [0x44 - FONT_START_CHAR] = 14, + [0x45 - FONT_START_CHAR] = 10, + [0x46 - FONT_START_CHAR] = 10, + [0x47 - FONT_START_CHAR] = 17, + [0x48 - FONT_START_CHAR] = 13, + [0x49 - FONT_START_CHAR] = 3, + [0x4a - FONT_START_CHAR] = 11, + [0x4b - FONT_START_CHAR] = 13, + [0x4c - FONT_START_CHAR] = 10, + [0x4d - FONT_START_CHAR] = 18, + [0x4e - FONT_START_CHAR] = 13, + [0x4f - FONT_START_CHAR] = 18, + [0x50 - FONT_START_CHAR] = 12, + [0x51 - FONT_START_CHAR] = 18, + [0x52 - FONT_START_CHAR] = 12, + [0x53 - FONT_START_CHAR] = 12, + [0x54 - FONT_START_CHAR] = 12, + [0x55 - FONT_START_CHAR] = 14, + [0x56 - FONT_START_CHAR] = 15, + [0x57 - FONT_START_CHAR] = 23, + [0x58 - FONT_START_CHAR] = 15, + [0x59 - FONT_START_CHAR] = 15, + [0x5a - FONT_START_CHAR] = 12, + [0x5b - FONT_START_CHAR] = 6, + [0x5c - FONT_START_CHAR] = 8, + [0x5d - FONT_START_CHAR] = 5, + [0x5e - FONT_START_CHAR] = 11, + [0x5f - FONT_START_CHAR] = 12, + [0x60 - FONT_START_CHAR] = 4, + [0x61 - FONT_START_CHAR] = 11, + [0x62 - FONT_START_CHAR] = 13, + [0x63 - FONT_START_CHAR] = 12, + [0x64 - FONT_START_CHAR] = 12, + [0x65 - FONT_START_CHAR] = 12, + [0x66 - FONT_START_CHAR] = 8, + [0x67 - FONT_START_CHAR] = 12, + [0x68 - FONT_START_CHAR] = 12, + [0x69 - FONT_START_CHAR] = 4, + [0x6a - FONT_START_CHAR] = 5, + [0x6b - FONT_START_CHAR] = 12, + [0x6c - FONT_START_CHAR] = 3, + [0x6d - FONT_START_CHAR] = 19, + [0x6e - FONT_START_CHAR] = 12, + [0x6f - FONT_START_CHAR] = 13, + [0x70 - FONT_START_CHAR] = 13, + [0x71 - FONT_START_CHAR] = 12, + [0x72 - FONT_START_CHAR] = 8, + [0x73 - FONT_START_CHAR] = 10, + [0x74 - FONT_START_CHAR] = 7, + [0x75 - FONT_START_CHAR] = 11, + [0x76 - FONT_START_CHAR] = 13, + [0x77 - FONT_START_CHAR] = 19, + [0x78 - FONT_START_CHAR] = 12, + [0x79 - FONT_START_CHAR] = 13, + [0x7a - FONT_START_CHAR] = 10, + [0x7b - FONT_START_CHAR] = 7, + [0x7c - FONT_START_CHAR] = 2, + [0x7d - FONT_START_CHAR] = 6, + [0x7e - FONT_START_CHAR] = 12, +}; diff --git a/src/lib/fonts/fonts.h b/src/lib/fonts/fonts.h new file mode 100644 index 0000000000..3317e012ba --- /dev/null +++ b/src/lib/fonts/fonts.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef __FONTS_H__ +#define __FONTS_H__ + +#include + +/* Printable ASCII character range [32-126] */ +#define FONT_START_CHAR 32 /* ASCII Space */ +#define FONT_END_CHAR 126 /* ASCII ~ */ +#define FONT_NUM_CHARS (FONT_END_CHAR - FONT_START_CHAR + 1) + +extern const uint32_t font_table[FONT_NUM_CHARS][CONFIG_FONT_HEIGHT]; +extern const uint8_t font_widths[]; + +#endif // __FONTS_H__ diff --git a/src/lib/render_text.c b/src/lib/render_text.c new file mode 100644 index 0000000000..da2aef1d3d --- /dev/null +++ b/src/lib/render_text.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include + +#include "fonts/fonts.h" +#include "render_bmp.h" + +/* Maps an unsigned character to the font table index */ +static const uint32_t *get_glyph_data(unsigned char c) +{ + /* Range check using macros generated by Python */ + if (c < FONT_START_CHAR || c > FONT_END_CHAR) + return font_table[0]; /* Default to space character */ + + return font_table[c - FONT_START_CHAR]; +} + +/* Retrieves the pre-calculated width for a character */ +static uint8_t get_glyph_width(unsigned char c) +{ + if (c < FONT_START_CHAR || c > FONT_END_CHAR) + return font_widths[0]; + + return font_widths[c - FONT_START_CHAR]; +} + +/* + * Maps local glyph coordinates to physical framebuffer coordinates + * based on the panel's physical orientation. + */ +static inline void get_rotated_text_coords(struct logo_config *config, + uint32_t x, uint32_t y, int row, int col, uint32_t *fb_x, uint32_t *fb_y) +{ + switch (config->panel_orientation) { + case LB_FB_ORIENTATION_RIGHT_UP: + *fb_x = x + (CONFIG_FONT_HEIGHT - 1 - row); + *fb_y = y + col; + break; + case LB_FB_ORIENTATION_LEFT_UP: + *fb_x = x + row; + *fb_y = y + (CONFIG_FONT_WIDTH - 1 - col); + break; + case LB_FB_ORIENTATION_BOTTOM_UP: + *fb_x = x + (CONFIG_FONT_WIDTH - 1 - col); + *fb_y = y + (CONFIG_FONT_HEIGHT - 1 - row); + break; + default: /* LB_FB_ORIENTATION_NORMAL */ + *fb_x = x + col; + *fb_y = y + row; + break; + } +} + +/* + * Renders a single character to the framebuffer. + * @config: Framebuffer and orientation configuration. + * @c: Character to render. + * @x, @y: Starting coordinates in the virtual grid. + * @color: Primary text color. + */ +static void draw_char(struct logo_config *config, unsigned char c, uint32_t x, uint32_t y, + struct blt_pixel color) +{ + size_t pixel_size = sizeof(struct blt_pixel); + uint8_t *fb = (uint8_t *)config->framebuffer_base; + const uint32_t *glyph = get_glyph_data(c); + uint8_t actual_width = get_glyph_width(c); + + for (int row = 0; row < CONFIG_FONT_HEIGHT; row++) { + uint32_t row_data = glyph[row]; + + for (int col = 0; col < actual_width; col++) { + uint32_t mask = (1 << (CONFIG_FONT_HEIGHT - 1)); + if (row_data & (mask >> col)) { + uint32_t fb_x, fb_y; + get_rotated_text_coords(config, x, y, row, col, &fb_x, &fb_y); + + if (fb_x < config->horizontal_resolution && + fb_y < config->vertical_resolution) { + struct blt_pixel *pixel = (struct blt_pixel *) + (fb + (fb_y * config->bytes_per_scanline) + (fb_x * pixel_size)); + *pixel = color; + } + } + } + } +} + +static bool setup_text_alignment(struct logo_config *config, + enum bootsplash_text_type type, enum fw_splash_horizontal_alignment *halign, + enum fw_splash_vertical_alignment *valign, uint32_t *margin) +{ + /* Default to center/center */ + *halign = FW_SPLASH_HALIGNMENT_CENTER; + *valign = FW_SPLASH_VALIGNMENT_CENTER; + *margin = 0; + + if (type == BOOTSPLASH_TEXT_CENTER) + return true; + + if (type != BOOTSPLASH_TEXT_FOOTER) { + printk(BIOS_ERR, "%s: Invalid text type %d\n", __func__, type); + return false; + } + + *margin = config->logo_bottom_margin; + + switch (config->panel_orientation) { + case LB_FB_ORIENTATION_RIGHT_UP: + *halign = FW_SPLASH_HALIGNMENT_LEFT; + *valign = FW_SPLASH_VALIGNMENT_CENTER; + break; + case LB_FB_ORIENTATION_LEFT_UP: + *halign = FW_SPLASH_HALIGNMENT_RIGHT; + *valign = FW_SPLASH_VALIGNMENT_CENTER; + break; + case LB_FB_ORIENTATION_BOTTOM_UP: + *halign = FW_SPLASH_HALIGNMENT_CENTER; + *valign = FW_SPLASH_VALIGNMENT_TOP; + break; + default: /* LB_FB_ORIENTATION_NORMAL */ + *halign = FW_SPLASH_HALIGNMENT_CENTER; + *valign = FW_SPLASH_VALIGNMENT_BOTTOM; + break; + } + + return true; +} + +/* + * Renders a string centered on the screen. + * @config: Framebuffer and logo configuration. + * @str: The null-terminated string to render. + * @type: Type of bootsplash text (i.e., enum bootsplash_text_type). + */ +void render_text_to_framebuffer(struct logo_config *config, const char *str, + enum bootsplash_text_type type) +{ + if (!config || !str || config->framebuffer_base == 0) + return; + + size_t len = strlen(str); + if (len == 0) + return; + + const uint32_t kerning = 1; + uint32_t total_width = 0; + + for (size_t i = 0; i < len; i++) + total_width += get_glyph_width((unsigned char)str[i]) + kerning; + + uint32_t text_w, text_h; + enum fw_splash_horizontal_alignment halign; + enum fw_splash_vertical_alignment valign; + uint32_t margin; + + if (setup_text_alignment(config, type, &halign, &valign, &margin) == false) + return; + + if (config->panel_orientation == LB_FB_ORIENTATION_LEFT_UP || + config->panel_orientation == LB_FB_ORIENTATION_RIGHT_UP) { + text_w = CONFIG_FONT_HEIGHT; + text_h = total_width; + } else { + text_w = total_width; + text_h = CONFIG_FONT_HEIGHT; + } + + struct logo_coordinates coords = calculate_logo_coordinates(config->horizontal_resolution, + config->vertical_resolution, text_w, text_h, halign, valign); + + switch (config->panel_orientation) { + case LB_FB_ORIENTATION_RIGHT_UP: + coords.x += margin; + break; + case LB_FB_ORIENTATION_LEFT_UP: + coords.x -= margin; + coords.y += total_width; + break; + case LB_FB_ORIENTATION_BOTTOM_UP: + coords.x += total_width; + coords.y += margin; + break; + default: /* LB_FB_ORIENTATION_NORMAL (default) */ + coords.y -= margin; + } + + /* Text Color: White (Default) */ + struct blt_pixel text_color = { .Red = 0xff, .Green = 0xff, .Blue = 0xff }; + uint32_t cur_x = coords.x; + uint32_t cur_y = coords.y; + + /* Loop through characters and draw them */ + for (size_t i = 0; i < len; i++) { + unsigned char c = (unsigned char)str[i]; + draw_char(config, c, cur_x, cur_y, text_color); + + uint32_t advance = get_glyph_width(c) + kerning; + if (config->panel_orientation == LB_FB_ORIENTATION_RIGHT_UP) + cur_y += advance; + else if (config->panel_orientation == LB_FB_ORIENTATION_LEFT_UP) + cur_y -= advance; + else if (config->panel_orientation == LB_FB_ORIENTATION_BOTTOM_UP) + cur_x -= advance; + else + cur_x += advance; + } +}