mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-24 11:46:34 +00:00
Add font_loader
This commit is contained in:
parent
b520ae0253
commit
a751569bde
681
src/font/hasp_font_loader.cpp
Normal file
681
src/font/hasp_font_loader.cpp
Normal file
@ -0,0 +1,681 @@
|
||||
/**
|
||||
* @file hasp_font_loader.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "lv_misc/lv_fs.h"
|
||||
#include "hasp_font_loader.h"
|
||||
|
||||
#include "hasplib.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* hasp_font_load(const char* font_name)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
lv_font_t* font = (lv_font_t*)malloc(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) {
|
||||
LOG_WARNING(TAG_FONT, "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.
|
||||
*/
|
||||
hasp_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 hasp_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) free((void*)kern_dsc->glyph_ids);
|
||||
|
||||
if(kern_dsc->values) free((void*)kern_dsc->values);
|
||||
|
||||
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) free((void*)kern_dsc->class_pair_values);
|
||||
|
||||
if(kern_dsc->left_class_mapping) free((void*)kern_dsc->left_class_mapping);
|
||||
|
||||
if(kern_dsc->right_class_mapping) free((void*)kern_dsc->right_class_mapping);
|
||||
|
||||
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) free((void*)cmaps[i].glyph_id_ofs_list);
|
||||
if(NULL != cmaps[i].unicode_list) free((void*)cmaps[i].unicode_list);
|
||||
}
|
||||
free(cmaps);
|
||||
}
|
||||
|
||||
if(NULL != dsc->glyph_bitmap) {
|
||||
free((void*)dsc->glyph_bitmap);
|
||||
}
|
||||
if(NULL != dsc->glyph_dsc) {
|
||||
free((void*)dsc->glyph_dsc);
|
||||
}
|
||||
free(dsc);
|
||||
}
|
||||
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) {
|
||||
LOG_WARNING(TAG_FONT, "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 = (uint8_t*)malloc(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*)malloc(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 = (uint16_t*)malloc(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:
|
||||
LOG_WARNING(TAG_FONT, "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_font_fmt_txt_cmap_t*)malloc(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 = (cmap_table_bin_t*)malloc(sizeof(cmap_table_bin_t) * font_dsc->cmap_num);
|
||||
|
||||
bool success = load_cmaps_tables(fp, font_dsc, cmaps_start, cmaps_tables);
|
||||
|
||||
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*)malloc(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;
|
||||
#ifdef ESP32
|
||||
if(psramFound())
|
||||
glyph_bmp = (uint8_t*)ps_malloc(sizeof(uint8_t) * cur_bmp_size);
|
||||
else
|
||||
glyph_bmp = (uint8_t*)malloc(sizeof(uint8_t) * cur_bmp_size);
|
||||
#else
|
||||
glyph_bmp = (uint8_t*)malloc(sizeof(uint8_t) * cur_bmp_size);
|
||||
#endif
|
||||
|
||||
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*)malloc(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 = (uint32_t*)malloc(sizeof(uint32_t) * (loca_count + 1));
|
||||
|
||||
/*TODO check NULL*/
|
||||
|
||||
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 {
|
||||
LOG_WARNING(TAG_FONT, "Unknown index_to_loc_format: %d.", font_header.index_to_loc_format);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if(failed) {
|
||||
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);
|
||||
|
||||
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 = malloc(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 = malloc(ids_size);
|
||||
// int8_t * values = malloc(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 = malloc(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 = malloc(kern_class_mapping_length);
|
||||
// uint8_t * kern_right = malloc(kern_class_mapping_length);
|
||||
// int8_t * kern_values = malloc(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 {
|
||||
// LOG_WARNING(TAG_FONT,"Unknown kern_format_type: %d", kern_format_type);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// return kern_length;
|
||||
// }
|
||||
|
||||
#endif /*LV_USE_FILESYSTEM*/
|
44
src/font/hasp_font_loader.h
Normal file
44
src/font/hasp_font_loader.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file hasp_font_loader.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HASP_FONT_LOADER_H
|
||||
#define HASP_FONT_LOADER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_FILESYSTEM
|
||||
|
||||
lv_font_t * hasp_font_load(const char * fontName);
|
||||
void hasp_font_free(lv_font_t * font);
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_FONT_LOADER_H*/
|
Loading…
x
Reference in New Issue
Block a user