Unify more of the font generation logic between both paths and coalesce all fonts
This commit is contained in:
@@ -718,6 +718,69 @@ def prepare_languages(
|
|||||||
font_data,
|
font_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def render_font_block( data: LanguageData,
|
||||||
|
f: TextIO,
|
||||||
|
compress_font: bool = False):
|
||||||
|
font_map = data.font_map
|
||||||
|
|
||||||
|
small_font_symbol_conversion_table = build_symbol_conversion_map(
|
||||||
|
data.small_text_symbols
|
||||||
|
)
|
||||||
|
large_font_symbol_conversion_table = build_symbol_conversion_map(
|
||||||
|
data.large_text_symbols
|
||||||
|
)
|
||||||
|
|
||||||
|
if not compress_font:
|
||||||
|
font_table_text = make_font_table_cpp(
|
||||||
|
data.small_text_symbols,
|
||||||
|
data.large_text_symbols,
|
||||||
|
font_map,
|
||||||
|
small_font_symbol_conversion_table,
|
||||||
|
large_font_symbol_conversion_table,
|
||||||
|
)
|
||||||
|
f.write(font_table_text)
|
||||||
|
f.write(
|
||||||
|
"const FontSection FontSectionInfo = {\n"
|
||||||
|
" .font12_start_ptr = USER_FONT_12,\n"
|
||||||
|
" .font06_start_ptr = USER_FONT_6x8,\n"
|
||||||
|
" .font12_decompressed_size = 0,\n"
|
||||||
|
" .font06_decompressed_size = 0,\n"
|
||||||
|
" .font12_compressed_source = 0,\n"
|
||||||
|
" .font06_compressed_source = 0,\n"
|
||||||
|
"};\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
font12_uncompressed = bytearray()
|
||||||
|
for sym in data.large_text_symbols:
|
||||||
|
font12_uncompressed.extend(font_map.font12_maps[sym])
|
||||||
|
font12_compressed = brieflz.compress(bytes(font12_uncompressed))
|
||||||
|
logging.info(
|
||||||
|
f"Font table 12x16 compressed from {len(font12_uncompressed)} to {len(font12_compressed)} bytes (ratio {len(font12_compressed) / len(font12_uncompressed):.3})"
|
||||||
|
)
|
||||||
|
|
||||||
|
write_bytes_as_c_array(f, "font_12x16_brieflz", font12_compressed)
|
||||||
|
font06_uncompressed = bytearray()
|
||||||
|
for sym in data.large_text_symbols:
|
||||||
|
font06_uncompressed.extend(font_map.font06_maps[sym])
|
||||||
|
font06_compressed = brieflz.compress(bytes(font06_uncompressed))
|
||||||
|
logging.info(
|
||||||
|
f"Font table 06x08 compressed from {len(font06_uncompressed)} to {len(font06_compressed)} bytes (ratio {len(font06_compressed) / len(font06_uncompressed):.3})"
|
||||||
|
)
|
||||||
|
|
||||||
|
write_bytes_as_c_array(f, "font_06x08_brieflz", font06_compressed)
|
||||||
|
|
||||||
|
f.write(
|
||||||
|
f"static uint8_t font12_out_buffer[{len(font12_uncompressed)}];\n"
|
||||||
|
f"static uint8_t font06_out_buffer[{len(font06_uncompressed)}];\n"
|
||||||
|
"const FontSection FontSectionInfo = {\n"
|
||||||
|
" .font12_start_ptr = font12_out_buffer,\n"
|
||||||
|
" .font06_start_ptr = font06_out_buffer,\n"
|
||||||
|
f" .font12_decompressed_size = {len(font12_uncompressed)},\n"
|
||||||
|
f" .font06_decompressed_size = {len(font06_uncompressed)},\n"
|
||||||
|
" .font12_compressed_source = font_12x16_brieflz,\n"
|
||||||
|
" .font06_compressed_source = font_06x08_brieflz,\n"
|
||||||
|
"};\n"
|
||||||
|
)
|
||||||
|
|
||||||
def write_language(
|
def write_language(
|
||||||
data: LanguageData,
|
data: LanguageData,
|
||||||
@@ -729,7 +792,6 @@ def write_language(
|
|||||||
raise ValueError("More than 1 languages are provided")
|
raise ValueError("More than 1 languages are provided")
|
||||||
lang = data.langs[0]
|
lang = data.langs[0]
|
||||||
defs = data.defs
|
defs = data.defs
|
||||||
build_version = data.build_version
|
|
||||||
font_map = data.font_map
|
font_map = data.font_map
|
||||||
|
|
||||||
small_font_symbol_conversion_table = build_symbol_conversion_map(
|
small_font_symbol_conversion_table = build_symbol_conversion_map(
|
||||||
@@ -752,42 +814,7 @@ def write_language(
|
|||||||
|
|
||||||
f.write(f"\n// ---- {lang_name} ----\n\n")
|
f.write(f"\n// ---- {lang_name} ----\n\n")
|
||||||
|
|
||||||
if not compress_font:
|
render_font_block(data,f,compress_font)
|
||||||
font_table_text = make_font_table_cpp(
|
|
||||||
data.small_text_symbols,
|
|
||||||
data.large_text_symbols,
|
|
||||||
font_map,
|
|
||||||
small_font_symbol_conversion_table,
|
|
||||||
large_font_symbol_conversion_table,
|
|
||||||
)
|
|
||||||
f.write(font_table_text)
|
|
||||||
f.write(
|
|
||||||
"const FontSection FontSectionsData = {\n"
|
|
||||||
" .font12_start_ptr = USER_FONT_12,\n"
|
|
||||||
" .font06_start_ptr = USER_FONT_6x8,\n"
|
|
||||||
"};\n"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
font12_uncompressed = bytearray()
|
|
||||||
for sym in data.large_text_symbols:
|
|
||||||
font12_uncompressed.extend(font_map.font12[sym])
|
|
||||||
font12_compressed = brieflz.compress(bytes(font12_uncompressed))
|
|
||||||
logging.info(
|
|
||||||
f"Font table 12x16 compressed from {len(font12_uncompressed)} to {len(font12_compressed)} bytes (ratio {len(font12_compressed) / len(font12_uncompressed):.3})"
|
|
||||||
)
|
|
||||||
write_bytes_as_c_array(f, "font_12x16_brieflz", font12_compressed)
|
|
||||||
font_table_text = make_font_table_06_cpp(data.small_text_symbols, font_map)
|
|
||||||
f.write(font_table_text)
|
|
||||||
f.write(
|
|
||||||
f"static uint8_t font_out_buffer[{len(font12_uncompressed)}];\n"
|
|
||||||
"const FontSection FontSectionsData[] = {\n"
|
|
||||||
" {\n"
|
|
||||||
" .font12_start_ptr = font_out_buffer,\n"
|
|
||||||
" .font06_start_ptr = USER_FONT_6x8,\n"
|
|
||||||
" },\n"
|
|
||||||
"};\n"
|
|
||||||
"const FontSection *const FontSections = FontSectionsData;\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
f.write(f"\n// ---- {lang_name} ----\n\n")
|
f.write(f"\n// ---- {lang_name} ----\n\n")
|
||||||
|
|
||||||
@@ -849,11 +876,15 @@ def write_languages(
|
|||||||
) -> None:
|
) -> None:
|
||||||
defs = data.defs
|
defs = data.defs
|
||||||
build_version = data.build_version
|
build_version = data.build_version
|
||||||
combined_sym_list = data.sym_list
|
|
||||||
sym_lists_by_font = data.sym_lists_by_font
|
|
||||||
font_map = data.font_map
|
font_map = data.font_map
|
||||||
|
|
||||||
symbol_conversion_table = build_symbol_conversion_map(combined_sym_list)
|
small_font_symbol_conversion_table = build_symbol_conversion_map(
|
||||||
|
data.small_text_symbols
|
||||||
|
)
|
||||||
|
large_font_symbol_conversion_table = build_symbol_conversion_map(
|
||||||
|
data.large_text_symbols
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
language_codes: List[str] = [lang["languageCode"] for lang in data.langs]
|
language_codes: List[str] = [lang["languageCode"] for lang in data.langs]
|
||||||
logging.info(f"Generating block for {language_codes}")
|
logging.info(f"Generating block for {language_codes}")
|
||||||
@@ -866,101 +897,16 @@ def write_languages(
|
|||||||
|
|
||||||
f.write(f"\n// ---- {lang_names} ----\n\n")
|
f.write(f"\n// ---- {lang_names} ----\n\n")
|
||||||
|
|
||||||
max_decompressed_font_size = 0
|
render_font_block(data,f,compress_font)
|
||||||
if not compress_font:
|
|
||||||
font_table_text = ""
|
|
||||||
font_section_info_text = (
|
|
||||||
"const FontSectionDataInfo FontSectionDataInfos[] = {\n"
|
|
||||||
)
|
|
||||||
for font, current_sym_list in sym_lists_by_font.items():
|
|
||||||
font_table_text += f"const uint8_t font_table_data_{font}[] = {{\n"
|
|
||||||
font_table_text += "// 12x16:\n"
|
|
||||||
font_table_text += make_font_table_named_cpp(
|
|
||||||
None,
|
|
||||||
current_sym_list,
|
|
||||||
font_map.font12,
|
|
||||||
symbol_conversion_table,
|
|
||||||
)
|
|
||||||
if font != font_tables.NAME_CJK:
|
|
||||||
font_table_text += "// 6x8:\n"
|
|
||||||
font_table_text += make_font_table_named_cpp(
|
|
||||||
None,
|
|
||||||
current_sym_list,
|
|
||||||
font_map.font06, # type: ignore[arg-type]
|
|
||||||
symbol_conversion_table,
|
|
||||||
)
|
|
||||||
font_table_text += f"}}; // font_table_data_{font}\n"
|
|
||||||
if len(current_sym_list) == 0:
|
|
||||||
current_sym_start = 0
|
|
||||||
else:
|
|
||||||
current_sym_start = combined_sym_list.index(current_sym_list[0]) + 2
|
|
||||||
font_section_info_text += (
|
|
||||||
" {\n"
|
|
||||||
f" .symbol_start = {current_sym_start},\n"
|
|
||||||
f" .symbol_count = {len(current_sym_list)},\n"
|
|
||||||
f" .data_size = sizeof(font_table_data_{font}),\n"
|
|
||||||
" .data_is_compressed = false,\n"
|
|
||||||
f" .data_ptr = font_table_data_{font},\n"
|
|
||||||
" },\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
f.write(font_table_text)
|
|
||||||
font_section_info_text += (
|
|
||||||
"};\n"
|
|
||||||
"const uint8_t FontSectionDataCount = sizeof(FontSectionDataInfos) / sizeof(FontSectionDataInfos[0]);\n\n"
|
|
||||||
)
|
|
||||||
f.write(font_section_info_text)
|
|
||||||
f.write(
|
|
||||||
"FontSection DynamicFontSections[4] = {};\n"
|
|
||||||
"const FontSection *const FontSections = DynamicFontSections;\n"
|
|
||||||
"const uint8_t FontSectionsCount = sizeof(DynamicFontSections) / sizeof(DynamicFontSections[0]);\n"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
font_section_info_text = (
|
|
||||||
"const FontSectionDataInfo FontSectionDataInfos[] = {\n"
|
|
||||||
)
|
|
||||||
for font, current_sym_list in sym_lists_by_font.items():
|
|
||||||
if len(current_sym_list) == 0:
|
|
||||||
continue
|
|
||||||
current_sym_start = combined_sym_list.index(current_sym_list[0]) + 2
|
|
||||||
font_uncompressed = bytearray()
|
|
||||||
for sym in current_sym_list:
|
|
||||||
font_uncompressed.extend(font_map.font12[sym])
|
|
||||||
if font != font_tables.NAME_CJK:
|
|
||||||
for sym in current_sym_list:
|
|
||||||
font_uncompressed.extend(font_map.font06[sym]) # type: ignore[arg-type]
|
|
||||||
font_compressed = brieflz.compress(bytes(font_uncompressed))
|
|
||||||
logging.info(
|
|
||||||
f"Font table for {font} compressed from {len(font_uncompressed)} to {len(font_compressed)} bytes (ratio {len(font_compressed) / len(font_uncompressed):.3})"
|
|
||||||
)
|
|
||||||
max_decompressed_font_size += len(font_uncompressed)
|
|
||||||
write_bytes_as_c_array(f, f"font_data_brieflz_{font}", font_compressed)
|
|
||||||
font_section_info_text += (
|
|
||||||
" {\n"
|
|
||||||
f" .symbol_start = {current_sym_start},\n"
|
|
||||||
f" .symbol_count = {len(current_sym_list)},\n"
|
|
||||||
f" .data_size = sizeof(font_data_brieflz_{font}),\n"
|
|
||||||
" .data_is_compressed = true,\n"
|
|
||||||
f" .data_ptr = font_data_brieflz_{font},\n"
|
|
||||||
" },\n"
|
|
||||||
)
|
|
||||||
font_section_info_text += (
|
|
||||||
"};\n"
|
|
||||||
"const uint8_t FontSectionDataCount = sizeof(FontSectionDataInfos) / sizeof(FontSectionDataInfos[0]);\n\n"
|
|
||||||
)
|
|
||||||
f.write(font_section_info_text)
|
|
||||||
f.write(
|
|
||||||
"FontSection DynamicFontSections[4] = {};\n"
|
|
||||||
"const FontSection *const FontSections = DynamicFontSections;\n"
|
|
||||||
"const uint8_t FontSectionsCount = sizeof(DynamicFontSections) / sizeof(DynamicFontSections[0]);\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
f.write(f"\n// ---- {lang_names} ----\n\n")
|
f.write(f"\n// ---- {lang_names} ----\n\n")
|
||||||
|
|
||||||
|
|
||||||
translation_common_text = get_translation_common_text(
|
translation_common_text = get_translation_common_text(
|
||||||
defs, symbol_conversion_table, build_version
|
small_font_symbol_conversion_table, large_font_symbol_conversion_table
|
||||||
)
|
)
|
||||||
f.write(translation_common_text)
|
f.write(translation_common_text)
|
||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
f"const bool HasFahrenheit = {('true' if any([lang.get('tempUnitFahrenheit', True) for lang in data.langs]) else 'false')};\n\n"
|
f"const bool HasFahrenheit = {('true' if any([lang.get('tempUnitFahrenheit', True) for lang in data.langs]) else 'false')};\n\n"
|
||||||
)
|
)
|
||||||
@@ -971,7 +917,7 @@ def write_languages(
|
|||||||
lang_code = lang["languageCode"]
|
lang_code = lang["languageCode"]
|
||||||
translation_strings_and_indices_text = (
|
translation_strings_and_indices_text = (
|
||||||
get_translation_strings_and_indices_text(
|
get_translation_strings_and_indices_text(
|
||||||
lang, defs, symbol_conversion_table, suffix=f"_{lang_code}"
|
lang, defs, small_font_symbol_conversion_table,large_font_symbol_conversion_table, suffix=f"_{lang_code}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
f.write(translation_strings_and_indices_text)
|
f.write(translation_strings_and_indices_text)
|
||||||
@@ -1020,7 +966,7 @@ def write_languages(
|
|||||||
f.write("};\n")
|
f.write("};\n")
|
||||||
f.write(
|
f.write(
|
||||||
"const uint8_t LanguageCount = sizeof(LanguageMetas) / sizeof(LanguageMetas[0]);\n\n"
|
"const uint8_t LanguageCount = sizeof(LanguageMetas) / sizeof(LanguageMetas[0]);\n\n"
|
||||||
f"alignas(TranslationData) uint8_t translation_data_out_buffer[{max_decompressed_translation_size + max_decompressed_font_size}];\n"
|
f"alignas(TranslationData) uint8_t translation_data_out_buffer[{max_decompressed_translation_size }];\n"
|
||||||
"const uint16_t translation_data_out_buffer_size = sizeof(translation_data_out_buffer);\n\n"
|
"const uint16_t translation_data_out_buffer_size = sizeof(translation_data_out_buffer);\n\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFont = fontStyle == FontStyle::SMALL ? FontSectionsData.font06_start_ptr : FontSectionsData.font12_start_ptr;
|
currentFont = fontStyle == FontStyle::SMALL ? FontSectionInfo.font06_start_ptr : FontSectionInfo.font12_start_ptr;
|
||||||
index = charCode - 2;
|
index = charCode - 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,9 +149,13 @@ struct TranslationData {
|
|||||||
struct FontSection {
|
struct FontSection {
|
||||||
const uint8_t *font12_start_ptr;
|
const uint8_t *font12_start_ptr;
|
||||||
const uint8_t *font06_start_ptr;
|
const uint8_t *font06_start_ptr;
|
||||||
|
uint16_t font12_decompressed_size;
|
||||||
|
uint16_t font06_decompressed_size;
|
||||||
|
const uint8_t *font12_compressed_source; // Pointer to compressed data or null
|
||||||
|
const uint8_t *font06_compressed_source; // Pointer to compressed data or null
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct FontSection FontSectionsData;
|
extern const FontSection FontSectionInfo;
|
||||||
|
|
||||||
constexpr uint8_t settings_item_index(const SettingsItemIndex i) { return static_cast<uint8_t>(i); }
|
constexpr uint8_t settings_item_index(const SettingsItemIndex i) { return static_cast<uint8_t>(i); }
|
||||||
// Use a constexpr function for type-checking.
|
// Use a constexpr function for type-checking.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define TRANSLATION_MULTI_H_
|
#define TRANSLATION_MULTI_H_
|
||||||
|
|
||||||
#include "Translation.h"
|
#include "Translation.h"
|
||||||
|
#include <stdbool.h>
|
||||||
// The compressed translation data will be decompressed to this buffer. These
|
// The compressed translation data will be decompressed to this buffer. These
|
||||||
// data may include:
|
// data may include:
|
||||||
// - TranslationData (translation index table and translation strings)
|
// - TranslationData (translation index table and translation strings)
|
||||||
@@ -14,21 +14,6 @@
|
|||||||
extern uint8_t translation_data_out_buffer[];
|
extern uint8_t translation_data_out_buffer[];
|
||||||
extern const uint16_t translation_data_out_buffer_size;
|
extern const uint16_t translation_data_out_buffer_size;
|
||||||
|
|
||||||
struct FontSectionDataInfo {
|
|
||||||
uint16_t symbol_start;
|
|
||||||
uint16_t symbol_count;
|
|
||||||
uint16_t data_size : 15;
|
|
||||||
bool data_is_compressed : 1;
|
|
||||||
|
|
||||||
// Font12x16 data followed by font6x8 data
|
|
||||||
const uint8_t *data_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const FontSectionDataInfo FontSectionDataInfos[];
|
|
||||||
extern const uint8_t FontSectionDataCount;
|
|
||||||
|
|
||||||
extern FontSection DynamicFontSections[];
|
|
||||||
|
|
||||||
struct LanguageMeta {
|
struct LanguageMeta {
|
||||||
uint16_t uniqueID;
|
uint16_t uniqueID;
|
||||||
const uint8_t *translation_data;
|
const uint8_t *translation_data;
|
||||||
|
|||||||
@@ -51,30 +51,16 @@ void prepareTranslations() {
|
|||||||
}
|
}
|
||||||
Tr = &translationData->indices;
|
Tr = &translationData->indices;
|
||||||
TranslationStrings = translationData->strings;
|
TranslationStrings = translationData->strings;
|
||||||
|
// Font 12 can be compressed; if it is then we want to decompress it to ram
|
||||||
|
|
||||||
memset(DynamicFontSections, 0, FontSectionsCount * sizeof(DynamicFontSections[0]));
|
if (FontSectionInfo.font12_compressed_source != NULL) {
|
||||||
for (int i = 0; i < FontSectionDataCount; i++) {
|
|
||||||
const auto &fontSectionDataInfo = FontSectionDataInfos[i];
|
|
||||||
auto &fontSection = DynamicFontSections[i];
|
|
||||||
fontSection.symbol_start = fontSectionDataInfo.symbol_start;
|
|
||||||
fontSection.symbol_end = fontSection.symbol_start + fontSectionDataInfo.symbol_count;
|
|
||||||
const uint16_t font12_size = fontSectionDataInfo.symbol_count * (12 * 16 / 8);
|
|
||||||
uint16_t dataSize;
|
|
||||||
if (fontSectionDataInfo.data_is_compressed) {
|
|
||||||
unsigned int outsize;
|
unsigned int outsize;
|
||||||
outsize = blz_depack_srcsize(fontSectionDataInfo.data_ptr, buffer_next_ptr, fontSectionDataInfo.data_size);
|
outsize = blz_depack(FontSectionInfo.font06_compressed_source, (uint8_t *)FontSectionInfo.font12_start_ptr, FontSectionInfo.font12_decompressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
fontSection.font12_start_ptr = buffer_next_ptr;
|
if (FontSectionInfo.font06_compressed_source != NULL) {
|
||||||
dataSize = outsize;
|
unsigned int outsize;
|
||||||
buffer_remaining_size -= outsize;
|
outsize = blz_depack(FontSectionInfo.font06_compressed_source, (uint8_t *)FontSectionInfo.font06_start_ptr, FontSectionInfo.font06_decompressed_size);
|
||||||
buffer_next_ptr += outsize;
|
|
||||||
} else {
|
|
||||||
fontSection.font12_start_ptr = fontSectionDataInfo.data_ptr;
|
|
||||||
dataSize = fontSectionDataInfo.data_size;
|
|
||||||
}
|
|
||||||
if (dataSize > font12_size) {
|
|
||||||
fontSection.font06_start_ptr = fontSection.font12_start_ptr + font12_size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user