diff --git a/apps/settings.c b/apps/settings.c index a698606..a1ebf29 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -880,7 +880,7 @@ void settings_apply(bool read_disk) snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.font_file); - if (!loaded_font || strcmp(loaded_font, buf)) + if (!loaded_font || strcmp(loaded_font, global_settings.font_file)) { CHART2(">font_load ", global_settings.font_file); if (global_status.font_id[SCREEN_MAIN] >= 0) @@ -897,7 +897,7 @@ void settings_apply(bool read_disk) const char* loaded_font = font_filename(global_status.font_id[SCREEN_REMOTE]); snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.remote_font_file); - if (!loaded_font || strcmp(loaded_font, buf)) + if (!loaded_font || strcmp(loaded_font, global_settings.remote_font_file)) { CHART2(">font_load_remoteui ", global_settings.remote_font_file); if (global_status.font_id[SCREEN_REMOTE] >= 0) diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index fc84fdd..4111530 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -457,6 +457,7 @@ void LCDFN(scroll_fn)(void) else s->offset += LCDFN(scroll_info).step; + font_lock(current_vp->font, true); pf = font_get(current_vp->font); xpos = s->startx; ypos = s->y * pf->height + s->y_offset; @@ -492,6 +493,7 @@ void LCDFN(scroll_fn)(void) pf->height, s->offset); LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width - xpos, pf->height); + font_lock(current_vp->font, false); } LCDFN(set_viewport)(old_vp); } diff --git a/firmware/export/font.h b/firmware/export/font.h index 582c08f..9bebd90 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -120,18 +120,21 @@ 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); +void font_unload_all(void); + +void font_lock(int font_id, bool lock); struct font* font_get(int font); int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); int font_get_width(struct font* ft, unsigned short ch); const unsigned char * font_get_bits(struct font* ft, unsigned short ch); -void glyph_cache_save(struct font* pf); #else /* HAVE_LCD_BITMAP */ #define font_init() #define font_load(x) +#define font_unload_all() #endif diff --git a/firmware/font.c b/firmware/font.c index 0546061..c834685 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -77,20 +77,19 @@ extern struct font sysfont; struct buflib_alloc_data { struct font font; - bool handle_locked; /* is the buflib handle currently locked? */ + int lock_count; /* is the buflib handle currently locked? */ int refcount; /* how many times has this font been loaded? */ unsigned char buffer[]; }; static int buflib_allocations[MAXFONTS]; -static int handle_for_glyphcache; static int buflibmove_callback(int handle, void* current, void* new) { (void)handle; struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current; - size_t diff = new - current; + ptrdiff_t diff = new - current; - if (alloc->handle_locked) + if (alloc->lock_count > 0) return BUFLIB_CB_CANNOT_MOVE; if (alloc->font.bits) @@ -105,7 +104,7 @@ static int buflibmove_callback(int handle, void* current, void* new) alloc->font.buffer_position += diff; if (alloc->font.cache._index) - alloc->font.cache._index += diff; + alloc->font.cache._index = (void*)alloc->font.cache._index + diff; if (alloc->font.cache._lru._base) alloc->font.cache._lru._base += diff; @@ -114,7 +113,14 @@ static int buflibmove_callback(int handle, void* current, void* new) static void lock_font_handle(int handle, bool lock) { struct buflib_alloc_data *alloc = core_get_data(handle); - alloc->handle_locked = lock; + alloc->lock_count += lock ? 1 : -1; +} + +void font_lock(int font_id, bool lock) +{ + int handle = buflib_allocations[font_id]; + if (handle > 0) + lock_font_handle(handle, lock); } static struct buflib_callbacks buflibops = {buflibmove_callback, NULL }; @@ -135,7 +141,8 @@ static inline unsigned char *buffer_from_handle(int handle) /* Font cache structures */ static void cache_create(struct font* pf); -static void glyph_cache_load(struct font* pf); +static void glyph_cache_load(int font_id); +static void glyph_cache_save(int font_id); /* End Font cache structures */ void font_init(void) @@ -143,7 +150,6 @@ void font_init(void) int i = 0; while (ifd >= 0) - close(pf->fd); - - font_reset(font_id); /* open and read entire font file*/ pf->fd = open(path, O_RDONLY|O_BINARY); @@ -403,7 +402,7 @@ static bool internal_load_font(int font_id, const char *path, return false; } - glyph_cache_load(pf); + glyph_cache_load(font_id); } else { @@ -427,14 +426,28 @@ static bool internal_load_font(int font_id, const char *path, return true; } +static const char* font_shrinkfilename(const char* path) +{ + static char filename[MAX_PATH]; + char *end = strrchr(path, '/'); + if (!end) + return NULL; + strlcpy(filename, end+1, MAX_PATH); + end = strrchr(filename, '.'); + if (end) + *end = '\0'; + return filename; +} + static int find_font_index(const char* path) { int index = 0, handle; + const char* shortname = font_shrinkfilename(path); while (index < MAXFONTS) { handle = buflib_allocations[index]; - if (handle > 0 && !strcmp(core_get_name(handle), path)) + if (handle > 0 && !strcmp(core_get_name(handle), shortname)) return index; index++; } @@ -450,14 +463,14 @@ static int alloc_and_init(int font_idx, const char* name, size_t size) size_t alloc_size = size + sizeof(struct buflib_alloc_data); if (handle > 0) return handle; - *phandle = core_alloc_ex(name, alloc_size, &buflibops); + *phandle = core_alloc_ex(font_shrinkfilename(name), alloc_size, &buflibops); handle = *phandle; if (handle < 0) return handle; pdata = core_get_data(handle); pf = &pdata->font; font_reset(font_idx); - pdata->handle_locked = false; + pdata->lock_count = 0; pdata->refcount = 1; pf->buffer_position = pf->buffer_start = buffer_from_handle(handle); pf->buffer_size = size; @@ -530,9 +543,6 @@ int font_load_ex(const char *path, size_t buffer_size) if (*handle < 0) return -1; - if (handle_for_glyphcache < 0) - handle_for_glyphcache = *handle; - buffer = buffer_from_handle(*handle); lock_font_handle(*handle, true); @@ -570,16 +580,27 @@ void font_unload(int font_id) if (pdata->refcount < 1) { //printf("freeing id: %d %s\n", font_id, core_get_name(*handle)); + lock_font_handle(*handle, true); + glyph_cache_save(font_id); if (pf && pf->fd >= 0) close(pf->fd); + lock_font_handle(*handle, false); if (*handle > 0) core_free(*handle); - if (handle_for_glyphcache == *handle) - handle_for_glyphcache = -1; // should find the next available handle *handle = -1; } } +void font_unload_all(void) +{ + int i; + for (i=0; i 0) + font_unload(i); + } +} + /* * Return a pointer to an incore font structure. * If the requested font isn't loaded/compiled-in, @@ -604,7 +625,7 @@ struct font* font_get(int font) if (--font < 0) return &sysfont; } -} +} static int pf_to_handle(struct font* pf) { @@ -731,11 +752,11 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) return bits; } static int cache_fd; +static struct font* cache_pf; static void glyph_file_write(void* data) { struct font_cache_entry* p = data; - int handle = handle_for_glyphcache; - struct font* pf = pf_from_handle(handle); + struct font* pf = cache_pf; unsigned short ch; unsigned char tmp[2]; @@ -756,16 +777,19 @@ static void glyph_file_write(void* data) } /* save the char codes of the loaded glyphs to a file */ -void glyph_cache_save(struct font* pf) +static void glyph_cache_save(int font_id) { - if (pf != pf_from_handle(handle_for_glyphcache)) - return; + struct font *pf = pf_from_handle(buflib_allocations[font_id]); if (pf->fd >= 0) { - cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); + char filename[MAX_PATH]; + snprintf(filename, MAX_PATH, ROCKBOX_DIR "/%s.glyphcache", + font_filename(font_id)); + cache_fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (cache_fd < 0) return; + cache_pf = pf; lru_traverse(&pf->cache._lru, glyph_file_write); if (cache_fd >= 0) @@ -814,12 +838,11 @@ static int ushortcmp(const void *a, const void *b) { return ((int)(*(unsigned short*)a - *(unsigned short*)b)); } -static void glyph_cache_load(struct font* pf) +static void glyph_cache_load(int font_id) { - if (handle_for_glyphcache <= 0) - return; + struct font* pf = pf_from_handle(buflib_allocations[font_id]); #define MAX_SORT 256 - if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) { + if (pf && pf->fd >= 0) { int fd; int i, size; unsigned char tmp[2]; @@ -832,7 +855,10 @@ static void glyph_cache_load(struct font* pf) if ( sort_size > MAX_SORT ) sort_size = MAX_SORT; - fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); + char filename[MAX_PATH]; + snprintf(filename, MAX_PATH, ROCKBOX_DIR "/%s.glyphcache", + font_filename(font_id)); + fd = open(filename, O_RDONLY|O_BINARY); if (fd >= 0) { /* only read what fits */ diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 79a7a90..c0f0f09 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -655,9 +655,7 @@ void shutdown_hw(void) audio_stop(); if (battery_level_safe()) { /* do not save on critical battery */ -#ifdef HAVE_LCD_BITMAP - glyph_cache_save(NULL); -#endif + font_unload_all(); /* Commit pending writes if needed. Even though we don't do write caching, things like flash translation layers may need this to commit scattered