diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 8c87553be3..c8cca3d380 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -419,7 +419,7 @@ static int parse_font_load(struct skin_element *element, if(element->params_count > 2) glyphs = element->params[2].data.number; else - glyphs = GLYPHS_TO_CACHE; + glyphs = 0; if (id < 2) { DEBUGF("font id must be >= 2\n"); @@ -1675,8 +1675,13 @@ static bool skin_load_fonts(struct wps_data *data) { char path[MAX_PATH]; snprintf(path, sizeof path, FONT_DIR "/%s", font->name); - font->id = font_load(path/*, - skinfonts[font_id-FONT_FIRSTUSERFONT].glyphs*/); + if (skinfonts[font_id-2].glyphs > 0) + { + font->id = font_load_ex(path, + font_glyphs_to_bufsize(path, skinfonts[font_id-2].glyphs)); + } + else + font->id = font_load(path); //printf("[%d] %s -> %d\n",font_id, font->name, font->id); id_array[font_count++] = font->id; } @@ -1693,18 +1698,16 @@ static bool skin_load_fonts(struct wps_data *data) /* finally, assign the font_id to the viewport */ vp->font = font->id; } - if (success) + data->font_ids = skin_buffer_alloc(font_count * sizeof(int)); + if (!success || data->font_ids == NULL) { - data->font_ids = skin_buffer_alloc(font_count * sizeof(int)); - if (data->font_ids == NULL) - { - while (font_count > 0) - font_unload(id_array[--font_count]); - return false; - } - memcpy(data->font_ids, id_array, sizeof(int)*font_count); - data->font_count = font_count; + while (font_count > 0) + font_unload(id_array[--font_count]); + data->font_ids = NULL; + return false; } + memcpy(data->font_ids, id_array, sizeof(int)*font_count); + data->font_count = font_count; return success; } diff --git a/firmware/export/font.h b/firmware/export/font.h index 6c9e6163af..582c08f209 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -21,6 +21,7 @@ #ifndef _FONT_H #define _FONT_H +#include #include "inttypes.h" #include "stdbool.h" @@ -102,7 +103,7 @@ struct font { unsigned char *buffer_start; /* buffer to store the font in */ unsigned char *buffer_position; /* position in the buffer */ unsigned char *buffer_end; /* end of the buffer */ - int buffer_size; /* size of the buffer in bytes */ + size_t buffer_size; /* size of the buffer in bytes */ #ifndef __PCTOOL__ struct font_cache cache; uint32_t file_width_offset; /* offset to file width data */ @@ -116,6 +117,7 @@ struct font { void font_init(void) INIT_ATTR; const char* font_filename(int font_id); int font_load(const char *path); +int font_load_ex(const char *path, size_t buffer_size); int font_glyphs_to_bufsize(const char *path, int glyphs); void font_unload(int font_id); diff --git a/firmware/font.c b/firmware/font.c index fea210a3f1..2fda8483b5 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -79,7 +79,7 @@ struct buflib_alloc_data { struct font font; bool handle_locked; /* is the buflib handle currently locked? */ int refcount; /* how many times has this font been loaded? */ - unsigned char buffer[MAX_FONT_SIZE]; + unsigned char buffer[]; }; static int buflib_allocations[MAXFONTS]; static int handle_for_glyphcache; @@ -349,7 +349,7 @@ static void font_reset(int font_id) static bool internal_load_font(int font_id, const char *path, char *buf, size_t buf_size) { - int size; + size_t size; struct font* pf = pf_from_handle(buflib_allocations[font_id]); /* save loaded glyphs */ glyph_cache_save(pf); @@ -433,15 +433,16 @@ static int find_font_index(const char* path) return FONT_SYSFIXED; } -static int alloc_and_init(int font_idx, const char* name) +static int alloc_and_init(int font_idx, const char* name, size_t size) { int *phandle = &buflib_allocations[font_idx]; int handle = *phandle; struct buflib_alloc_data *pdata; struct font *pf; + size_t alloc_size = size + sizeof(struct buflib_alloc_data); if (handle > 0) return handle; - *phandle = core_alloc_ex(name, sizeof(struct buflib_alloc_data), &buflibops); + *phandle = core_alloc_ex(name, alloc_size, &buflibops); handle = *phandle; if (handle < 0) return handle; @@ -451,7 +452,7 @@ static int alloc_and_init(int font_idx, const char* name) pdata->handle_locked = false; pdata->refcount = 1; pf->buffer_position = pf->buffer_start = buffer_from_handle(handle); - pf->buffer_size = MAX_FONT_SIZE; + pf->buffer_size = size; return handle; } @@ -465,17 +466,44 @@ const char* font_filename(int font_id) /* read and load font into incore font structure, * returns the font number on success, -1 on failure */ -int font_load(const char *path) +int font_load_ex(const char *path, size_t buffer_size) { int font_id = find_font_index(path); char *buffer; - size_t buffer_size; int *handle; if (font_id > FONT_SYSFIXED) { /* already loaded, no need to reload */ struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]); + if (pd->font.buffer_size < buffer_size) + { + int old_refcount, old_id; + /* reload the font: + * 1) save of refcont and id + * 2) force unload (set refcount to 1 to make sure it get unloaded) + * 3) reload with the larger buffer + * 4) restore the id and refcount + */ + old_id = font_id; + old_refcount = pd->refcount; + pd->refcount = 1; + font_unload(font_id); + font_id = font_load_ex(path, buffer_size); + if (font_id < 0) + { + // not much we can do here, maybe try reloading with the small buffer again + return -1; + } + if (old_id != font_id) + { + buflib_allocations[old_id] = buflib_allocations[font_id]; + buflib_allocations[font_id] = -1; + font_id = old_id; + } + pd = core_get_data(buflib_allocations[font_id]); + pd->refcount = old_refcount; + } pd->refcount++; //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount); return font_id; @@ -490,7 +518,7 @@ int font_load(const char *path) } } handle = &buflib_allocations[font_id]; - *handle = alloc_and_init(font_id, path); + *handle = alloc_and_init(font_id, path, buffer_size); if (*handle < 0) return -1; @@ -498,7 +526,6 @@ int font_load(const char *path) handle_for_glyphcache = *handle; buffer = buffer_from_handle(*handle); - buffer_size = MAX_FONT_SIZE; //FIXME lock_font_handle(*handle, true); if (!internal_load_font(font_id, path, buffer, buffer_size)) @@ -513,6 +540,10 @@ int font_load(const char *path) //printf("%s -> [%d] -> %d\n", path, font_id, *handle); return font_id; /* success!*/ } +int font_load(const char *path) +{ + return font_load_ex(path, MAX_FONT_SIZE); +} void font_unload(int font_id) {