diff options
Diffstat (limited to 'src/libs/lvgl/src/lv_font/lv_font_loader.c')
| m--------- | src/libs/lvgl | 0 | ||||
| -rw-r--r-- | src/libs/lvgl/src/lv_font/lv_font_loader.c | 684 |
2 files changed, 0 insertions, 684 deletions
diff --git a/src/libs/lvgl b/src/libs/lvgl new file mode 160000 +Subproject b89c30eafe1397a778ae5d65f108a0ef820de12 diff --git a/src/libs/lvgl/src/lv_font/lv_font_loader.c b/src/libs/lvgl/src/lv_font/lv_font_loader.c deleted file mode 100644 index 1b974c0..0000000 --- a/src/libs/lvgl/src/lv_font/lv_font_loader.c +++ /dev/null @@ -1,684 +0,0 @@ -/** - * @file lv_font_loader.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include <stdint.h> -#include <stdbool.h> - -#include "../lvgl.h" -#include "../lv_misc/lv_fs.h" -#include "lv_font_loader.h" - -#if LV_USE_FILESYSTEM - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - lv_fs_file_t * fp; - int8_t bit_pos; - uint8_t byte_value; -} bit_iterator_t; - -typedef struct font_header_bin { - uint32_t version; - uint16_t tables_count; - uint16_t font_size; - uint16_t ascent; - int16_t descent; - uint16_t typo_ascent; - int16_t typo_descent; - uint16_t typo_line_gap; - int16_t min_y; - int16_t max_y; - uint16_t default_advance_width; - uint16_t kerning_scale; - uint8_t index_to_loc_format; - uint8_t glyph_id_format; - uint8_t advance_width_format; - uint8_t bits_per_pixel; - uint8_t xy_bits; - uint8_t wh_bits; - uint8_t advance_width_bits; - uint8_t compression_id; - uint8_t subpixels_mode; - uint8_t padding; - int16_t underline_position; - uint16_t underline_thickness; -} font_header_bin_t; - -typedef struct cmap_table_bin { - uint32_t data_offset; - uint32_t range_start; - uint16_t range_length; - uint16_t glyph_id_start; - uint16_t data_entries_count; - uint8_t format_type; - uint8_t padding; -} cmap_table_bin_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static bit_iterator_t init_bit_iterator(lv_fs_file_t * fp); -static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font); -int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t format, uint32_t start); - -static int read_bits_signed(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); -static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Loads a `lv_font_t` object from a binary font file - * @param font_name filename where the font file is located - * @return a pointer to the font or NULL in case of error - */ -lv_font_t * lv_font_load(const char * font_name) -{ - bool success = false; - - lv_font_t * font = lv_mem_alloc(sizeof(lv_font_t)); - memset(font, 0, sizeof(lv_font_t)); - - lv_fs_file_t file; - lv_fs_res_t res = lv_fs_open(&file, font_name, LV_FS_MODE_RD); - - if(res == LV_FS_RES_OK) { - success = lvgl_load_font(&file, font); - - if(!success) { - LV_LOG_WARN("Error loading font file: %s\n", font_name); - /* - * When `lvgl_load_font` fails it can leak some pointers. - * All non-null pointers can be assumed as allocated and - * `lv_font_free` should free them correctly. - */ - lv_font_free(font); - font = NULL; - } - - lv_fs_close(&file); - } - - return font; -} - -/** - * Frees the memory allocated by the `lv_font_load()` function - * @param font lv_font_t object created by the lv_font_load function - */ -void lv_font_free(lv_font_t * font) -{ - if(NULL != font) { - lv_font_fmt_txt_dsc_t * dsc = (lv_font_fmt_txt_dsc_t *) font->dsc; - - if(NULL != dsc) { - - if(dsc->kern_classes == 0) { - lv_font_fmt_txt_kern_pair_t * kern_dsc = - (lv_font_fmt_txt_kern_pair_t *) dsc->kern_dsc; - - if(NULL != kern_dsc) { - if(kern_dsc->glyph_ids) - lv_mem_free((void *) kern_dsc->glyph_ids); - - if(kern_dsc->values) - lv_mem_free((void *) kern_dsc->values); - - lv_mem_free((void *) kern_dsc); - } - } - else { - lv_font_fmt_txt_kern_classes_t * kern_dsc = - (lv_font_fmt_txt_kern_classes_t *) dsc->kern_dsc; - - if(NULL != kern_dsc) { - if(kern_dsc->class_pair_values) - lv_mem_free((void *) kern_dsc->class_pair_values); - - if(kern_dsc->left_class_mapping) - lv_mem_free((void *) kern_dsc->left_class_mapping); - - if(kern_dsc->right_class_mapping) - lv_mem_free((void *) kern_dsc->right_class_mapping); - - lv_mem_free((void *) kern_dsc); - } - } - - lv_font_fmt_txt_cmap_t * cmaps = - (lv_font_fmt_txt_cmap_t *) dsc->cmaps; - - if(NULL != cmaps) { - for(int i = 0; i < dsc->cmap_num; ++i) { - if(NULL != cmaps[i].glyph_id_ofs_list) - lv_mem_free((void *) cmaps[i].glyph_id_ofs_list); - if(NULL != cmaps[i].unicode_list) - lv_mem_free((void *) cmaps[i].unicode_list); - } - lv_mem_free(cmaps); - } - - if(NULL != dsc->glyph_bitmap) { - lv_mem_free((void *) dsc->glyph_bitmap); - } - if(NULL != dsc->glyph_dsc) { - lv_mem_free((void *) dsc->glyph_dsc); - } - lv_mem_free(dsc); - } - lv_mem_free(font); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static bit_iterator_t init_bit_iterator(lv_fs_file_t * fp) -{ - bit_iterator_t it; - it.fp = fp; - it.bit_pos = -1; - it.byte_value = 0; - return it; -} - -static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res) -{ - unsigned int value = 0; - while(n_bits--) { - it->byte_value = it->byte_value << 1; - it->bit_pos--; - - if(it->bit_pos < 0) { - it->bit_pos = 7; - *res = lv_fs_read(it->fp, &(it->byte_value), 1, NULL); - if(*res != LV_FS_RES_OK) { - return 0; - } - } - int8_t bit = (it->byte_value & 0x80) ? 1 : 0; - - value |= (bit << n_bits); - } - *res = LV_FS_RES_OK; - return value; -} - -static int read_bits_signed(bit_iterator_t * it, int n_bits, lv_fs_res_t * res) -{ - unsigned int value = read_bits(it, n_bits, res); - if(value & (1 << (n_bits - 1))) { - value |= ~0u << n_bits; - } - return value; -} - -static int read_label(lv_fs_file_t * fp, int start, const char * label) -{ - lv_fs_seek(fp, start); - - uint32_t length; - char buf[4]; - - if(lv_fs_read(fp, &length, 4, NULL) != LV_FS_RES_OK - || lv_fs_read(fp, buf, 4, NULL) != LV_FS_RES_OK - || memcmp(label, buf, 4) != 0) { - LV_LOG_WARN("Error reading '%s' label.", label); - return -1; - } - - return length; -} - -static bool load_cmaps_tables(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, - uint32_t cmaps_start, cmap_table_bin_t * cmap_table) -{ - if(lv_fs_read(fp, cmap_table, font_dsc->cmap_num * sizeof(cmap_table_bin_t), NULL) != LV_FS_RES_OK) { - return false; - } - - for(unsigned int i = 0; i < font_dsc->cmap_num; ++i) { - lv_fs_res_t res = lv_fs_seek(fp, cmaps_start + cmap_table[i].data_offset); - if(res != LV_FS_RES_OK) { - return false; - } - - lv_font_fmt_txt_cmap_t * cmap = (lv_font_fmt_txt_cmap_t *) & (font_dsc->cmaps[i]); - - cmap->range_start = cmap_table[i].range_start; - cmap->range_length = cmap_table[i].range_length; - cmap->glyph_id_start = cmap_table[i].glyph_id_start; - cmap->type = cmap_table[i].format_type; - - switch(cmap_table[i].format_type) { - case LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL: { - uint8_t ids_size = sizeof(uint8_t) * cmap_table[i].data_entries_count; - uint8_t * glyph_id_ofs_list = lv_mem_alloc(ids_size); - - cmap->glyph_id_ofs_list = glyph_id_ofs_list; - - if(lv_fs_read(fp, glyph_id_ofs_list, ids_size, NULL) != LV_FS_RES_OK) { - return false; - } - - cmap->list_length = cmap->range_length; - break; - } - case LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY: - break; - case LV_FONT_FMT_TXT_CMAP_SPARSE_FULL: - case LV_FONT_FMT_TXT_CMAP_SPARSE_TINY: { - uint32_t list_size = sizeof(uint16_t) * cmap_table[i].data_entries_count; - uint16_t * unicode_list = (uint16_t *) lv_mem_alloc(list_size); - - cmap->unicode_list = unicode_list; - cmap->list_length = cmap_table[i].data_entries_count; - - if(lv_fs_read(fp, unicode_list, list_size, NULL) != LV_FS_RES_OK) { - return false; - } - - if(cmap_table[i].format_type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) { - uint16_t * buf = lv_mem_alloc(sizeof(uint16_t) * cmap->list_length); - - cmap->glyph_id_ofs_list = buf; - - if(lv_fs_read(fp, buf, sizeof(uint16_t) * cmap->list_length, NULL) != LV_FS_RES_OK) { - return false; - } - } - break; - } - default: - LV_LOG_WARN("Unknown cmaps format type %d.", cmap_table[i].format_type); - return false; - } - } - return true; -} - -static int32_t load_cmaps(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint32_t cmaps_start) -{ - int32_t cmaps_length = read_label(fp, cmaps_start, "cmap"); - if(cmaps_length < 0) { - return -1; - } - - uint32_t cmaps_subtables_count; - if(lv_fs_read(fp, &cmaps_subtables_count, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { - return -1; - } - - lv_font_fmt_txt_cmap_t * cmaps = - lv_mem_alloc(cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); - - memset(cmaps, 0, cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); - - font_dsc->cmaps = cmaps; - font_dsc->cmap_num = cmaps_subtables_count; - - cmap_table_bin_t * cmaps_tables = lv_mem_alloc(sizeof(cmap_table_bin_t) * font_dsc->cmap_num); - - bool success = load_cmaps_tables(fp, font_dsc, cmaps_start, cmaps_tables); - - lv_mem_free(cmaps_tables); - - return success ? cmaps_length : -1; -} - -static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, - uint32_t start, uint32_t * glyph_offset, uint32_t loca_count, font_header_bin_t * header) -{ - int32_t glyph_length = read_label(fp, start, "glyf"); - if(glyph_length < 0) { - return -1; - } - - lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = (lv_font_fmt_txt_glyph_dsc_t *) - lv_mem_alloc(loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); - - memset(glyph_dsc, 0, loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); - - font_dsc->glyph_dsc = glyph_dsc; - - int cur_bmp_size = 0; - - for(unsigned int i = 0; i < loca_count; ++i) { - lv_font_fmt_txt_glyph_dsc_t * gdsc = &glyph_dsc[i]; - - lv_fs_res_t res = lv_fs_seek(fp, start + glyph_offset[i]); - if(res != LV_FS_RES_OK) { - return -1; - } - - bit_iterator_t bit_it = init_bit_iterator(fp); - - if(header->advance_width_bits == 0) { - gdsc->adv_w = header->default_advance_width; - } - else { - gdsc->adv_w = read_bits(&bit_it, header->advance_width_bits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - } - - if(header->advance_width_format == 0) { - gdsc->adv_w *= 16; - } - - gdsc->ofs_x = read_bits_signed(&bit_it, header->xy_bits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - - gdsc->ofs_y = read_bits_signed(&bit_it, header->xy_bits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - - gdsc->box_w = read_bits(&bit_it, header->wh_bits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - - gdsc->box_h = read_bits(&bit_it, header->wh_bits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - - int nbits = header->advance_width_bits + 2 * header->xy_bits + 2 * header->wh_bits; - int next_offset = (i < loca_count - 1) ? glyph_offset[i + 1] : (uint32_t)glyph_length; - int bmp_size = next_offset - glyph_offset[i] - nbits / 8; - - if(i == 0) { - gdsc->adv_w = 0; - gdsc->box_w = 0; - gdsc->box_h = 0; - gdsc->ofs_x = 0; - gdsc->ofs_y = 0; - } - - gdsc->bitmap_index = cur_bmp_size; - if(gdsc->box_w * gdsc->box_h != 0) { - cur_bmp_size += bmp_size; - } - } - - uint8_t * glyph_bmp = (uint8_t *) lv_mem_alloc(sizeof(uint8_t) * cur_bmp_size); - - font_dsc->glyph_bitmap = glyph_bmp; - - cur_bmp_size = 0; - - for(unsigned int i = 1; i < loca_count; ++i) { - lv_fs_res_t res = lv_fs_seek(fp, start + glyph_offset[i]); - if(res != LV_FS_RES_OK) { - return -1; - } - bit_iterator_t bit_it = init_bit_iterator(fp); - - int nbits = header->advance_width_bits + 2 * header->xy_bits + 2 * header->wh_bits; - - read_bits(&bit_it, nbits, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - - if(glyph_dsc[i].box_w * glyph_dsc[i].box_h == 0) { - continue; - } - - int next_offset = (i < loca_count - 1) ? glyph_offset[i + 1] : (uint32_t)glyph_length; - int bmp_size = next_offset - glyph_offset[i] - nbits / 8; - - if(nbits % 8 == 0) { /* Fast path */ - if(lv_fs_read(fp, &glyph_bmp[cur_bmp_size], bmp_size, NULL) != LV_FS_RES_OK) { - return -1; - } - } - else { - for(int k = 0; k < bmp_size - 1; ++k) { - glyph_bmp[cur_bmp_size + k] = read_bits(&bit_it, 8, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - } - glyph_bmp[cur_bmp_size + bmp_size - 1] = read_bits(&bit_it, 8 - nbits % 8, &res); - if(res != LV_FS_RES_OK) { - return -1; - } - } - - cur_bmp_size += bmp_size; - } - return glyph_length; -} - -/* - * Loads a `lv_font_t` from a binary file, given a `lv_fs_file_t`. - * - * Memory allocations on `lvgl_load_font` should be immediately zeroed and - * the pointer should be set on the `lv_font_t` data before any possible return. - * - * When something fails, it returns `false` and the memory on the `lv_font_t` - * still needs to be freed using `lv_font_free`. - * - * `lv_font_free` will assume that all non-null pointers are allocated and - * should be freed. - */ -static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) -{ - lv_font_fmt_txt_dsc_t * font_dsc = (lv_font_fmt_txt_dsc_t *) - lv_mem_alloc(sizeof(lv_font_fmt_txt_dsc_t)); - - memset(font_dsc, 0, sizeof(lv_font_fmt_txt_dsc_t)); - - font->dsc = font_dsc; - - /* header */ - int32_t header_length = read_label(fp, 0, "head"); - if(header_length < 0) { - return false; - } - - font_header_bin_t font_header; - if(lv_fs_read(fp, &font_header, sizeof(font_header_bin_t), NULL) != LV_FS_RES_OK) { - return false; - } - - font->base_line = -font_header.descent; - font->line_height = font_header.ascent - font_header.descent; - font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt; - font->get_glyph_bitmap = lv_font_get_bitmap_fmt_txt; - font->subpx = font_header.subpixels_mode; - font->underline_position = font_header.underline_position; - font->underline_thickness = font_header.underline_thickness; - - font_dsc->bpp = font_header.bits_per_pixel; - font_dsc->kern_scale = font_header.kerning_scale; - font_dsc->bitmap_format = font_header.compression_id; - - /* cmaps */ - uint32_t cmaps_start = header_length; - int32_t cmaps_length = load_cmaps(fp, font_dsc, cmaps_start); - if(cmaps_length < 0) { - return false; - } - - /* loca */ - uint32_t loca_start = cmaps_start + cmaps_length; - int32_t loca_length = read_label(fp, loca_start, "loca"); - if(loca_length < 0) { - return false; - } - - uint32_t loca_count; - if(lv_fs_read(fp, &loca_count, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { - return false; - } - - bool failed = false; - uint32_t * glyph_offset = lv_mem_alloc(sizeof(uint32_t) * (loca_count + 1)); - - if(font_header.index_to_loc_format == 0) { - for(unsigned int i = 0; i < loca_count; ++i) { - uint16_t offset; - if(lv_fs_read(fp, &offset, sizeof(uint16_t), NULL) != LV_FS_RES_OK) { - failed = true; - break; - } - glyph_offset[i] = offset; - } - } - else if(font_header.index_to_loc_format == 1) { - if(lv_fs_read(fp, glyph_offset, loca_count * sizeof(uint32_t), NULL) != LV_FS_RES_OK) { - failed = true; - } - } - else { - LV_LOG_WARN("Unknown index_to_loc_format: %d.", font_header.index_to_loc_format); - failed = true; - } - - if(failed) { - lv_mem_free(glyph_offset); - return false; - } - - /* glyph */ - uint32_t glyph_start = loca_start + loca_length; - int32_t glyph_length = load_glyph( - fp, font_dsc, glyph_start, glyph_offset, loca_count, &font_header); - - lv_mem_free(glyph_offset); - - if(glyph_length < 0) { - return false; - } - - if(font_header.tables_count < 4) { - font_dsc->kern_dsc = NULL; - font_dsc->kern_classes = 0; - font_dsc->kern_scale = 0; - return true; - } - - uint32_t kern_start = glyph_start + glyph_length; - - int32_t kern_length = load_kern(fp, font_dsc, font_header.glyph_id_format, kern_start); - - return kern_length >= 0; -} - -int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t format, uint32_t start) -{ - int32_t kern_length = read_label(fp, start, "kern"); - if(kern_length < 0) { - return -1; - } - - uint8_t kern_format_type; - int32_t padding; - if(lv_fs_read(fp, &kern_format_type, sizeof(uint8_t), NULL) != LV_FS_RES_OK || - lv_fs_read(fp, &padding, 3 * sizeof(uint8_t), NULL) != LV_FS_RES_OK) { - return -1; - } - - if(0 == kern_format_type) { /* sorted pairs */ - lv_font_fmt_txt_kern_pair_t * kern_pair = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_pair_t)); - - memset(kern_pair, 0, sizeof(lv_font_fmt_txt_kern_pair_t)); - - font_dsc->kern_dsc = kern_pair; - font_dsc->kern_classes = 0; - - uint32_t glyph_entries; - if(lv_fs_read(fp, &glyph_entries, sizeof(uint32_t), NULL) != LV_FS_RES_OK) { - return -1; - } - - int ids_size; - if(format == 0) { - ids_size = sizeof(int8_t) * 2 * glyph_entries; - } - else { - ids_size = sizeof(int16_t) * 2 * glyph_entries; - } - - uint8_t * glyph_ids = lv_mem_alloc(ids_size); - int8_t * values = lv_mem_alloc(glyph_entries); - - kern_pair->glyph_ids_size = format; - kern_pair->pair_cnt = glyph_entries; - kern_pair->glyph_ids = glyph_ids; - kern_pair->values = values; - - if(lv_fs_read(fp, glyph_ids, ids_size, NULL) != LV_FS_RES_OK) { - return -1; - } - - if(lv_fs_read(fp, values, glyph_entries, NULL) != LV_FS_RES_OK) { - return -1; - } - } - else if(3 == kern_format_type) { /* array M*N of classes */ - - lv_font_fmt_txt_kern_classes_t * kern_classes = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_classes_t)); - - memset(kern_classes, 0, sizeof(lv_font_fmt_txt_kern_classes_t)); - - font_dsc->kern_dsc = kern_classes; - font_dsc->kern_classes = 1; - - uint16_t kern_class_mapping_length; - uint8_t kern_table_rows; - uint8_t kern_table_cols; - - if(lv_fs_read(fp, &kern_class_mapping_length, sizeof(uint16_t), NULL) != LV_FS_RES_OK || - lv_fs_read(fp, &kern_table_rows, sizeof(uint8_t), NULL) != LV_FS_RES_OK || - lv_fs_read(fp, &kern_table_cols, sizeof(uint8_t), NULL) != LV_FS_RES_OK) { - return -1; - } - - int kern_values_length = sizeof(int8_t) * kern_table_rows * kern_table_cols; - - uint8_t * kern_left = lv_mem_alloc(kern_class_mapping_length); - uint8_t * kern_right = lv_mem_alloc(kern_class_mapping_length); - int8_t * kern_values = lv_mem_alloc(kern_values_length); - - kern_classes->left_class_mapping = kern_left; - kern_classes->right_class_mapping = kern_right; - kern_classes->left_class_cnt = kern_table_rows; - kern_classes->right_class_cnt = kern_table_cols; - kern_classes->class_pair_values = kern_values; - - if(lv_fs_read(fp, kern_left, kern_class_mapping_length, NULL) != LV_FS_RES_OK || - lv_fs_read(fp, kern_right, kern_class_mapping_length, NULL) != LV_FS_RES_OK || - lv_fs_read(fp, kern_values, kern_values_length, NULL) != LV_FS_RES_OK) { - return -1; - } - } - else { - LV_LOG_WARN("Unknown kern_format_type: %d", kern_format_type); - return -1; - } - - return kern_length; -} - -#endif /*LV_USE_FILESYSTEM*/ |
