From 100974162d20b259ee7145404ee74acd01f483b7 Mon Sep 17 00:00:00 2001 From: Fred Bauer Date: Sun, 16 Oct 2011 13:18:46 +0000 Subject: [PATCH] FS:12299 Font glyph cache is no longer saved. Each font will now have its own glyph cache file with the extension '.gc' Includes a temporary fix that delays saving the file to prevent the creation of multiple gc files with same name. Mostly JD Gordon's code. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30760 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/font.h | 2 +- firmware/font.c | 155 ++++++++++++++++++++++++++++------------- firmware/powermgmt.c | 2 +- 3 files changed, 108 insertions(+), 51 deletions(-) diff --git a/firmware/export/font.h b/firmware/export/font.h index 582c08f209..da8c85155c 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -126,7 +126,7 @@ 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); +void glyph_cache_save(int font_id); #else /* HAVE_LCD_BITMAP */ diff --git a/firmware/font.c b/firmware/font.c index 0f977c7059..8b70a7dcb9 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -70,6 +70,11 @@ #define O_BINARY 0 #endif +/* Define this to try loading /.rockbox/.glyphcache * + * when a font specific file fails. This requires the * + * user to copy and rename a font glyph cache file */ +//#define TRY_DEFAULT_GLYPHCACHE + /* compiled-in font */ extern struct font sysfont; @@ -82,7 +87,9 @@ struct buflib_alloc_data { unsigned char buffer[]; }; static int buflib_allocations[MAXFONTS]; -static int handle_for_glyphcache; + +static int cache_fd; +static struct font* cache_pf; static int buflibmove_callback(int handle, void* current, void* new) { @@ -135,15 +142,15 @@ 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 fond_id); /* End Font cache structures */ void font_init(void) { int i = 0; + cache_fd = -1; while (ifont; pdata->refcount--; if (pdata->refcount < 1) { //printf("freeing id: %d %s\n", font_id, core_get_name(*handle)); if (pf && pf->fd >= 0) + { + glyph_cache_save(font_id); close(pf->fd); - if (*handle > 0) - core_free(*handle); - if (handle_for_glyphcache == *handle) - handle_for_glyphcache = -1; // should find the next available handle - *handle = -1; + } + if (handle > 0) + core_free(handle); + buflib_allocations[font_id] = -1; + + } +} + +void font_unload_all(void) +{ + int i; + for (i=0; i 0) + { + struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[i]); + alloc->refcount = 1; /* force unload */ + font_unload(i); + } } } @@ -713,45 +737,74 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) return bits; } -static int cache_fd; + +void font_path_to_glyph_path( const char *font_path, char *glyph_path) + +{ + /* take full file name, cut extension, and add .glyphcache */ + strlcpy(glyph_path, font_path, MAX_PATH); + glyph_path[strlen(glyph_path)-4] = '\0'; + strcat(glyph_path, ".gc"); +} + +/* call with NULL to flush */ 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]; + static int buffer_pos = 0; +#define WRITE_BUFFER 256 + static unsigned char buffer[WRITE_BUFFER]; + /* flush buffer & reset */ + if ( data == NULL || buffer_pos >= WRITE_BUFFER) + { + write(cache_fd, buffer, buffer_pos); + buffer_pos = 0; + if ( data == NULL ) + return; + } if ( p->_char_code == 0xffff ) return; ch = p->_char_code + pf->firstchar; - - if ( cache_fd >= 0) { - tmp[0] = ch >> 8; - tmp[1] = ch & 0xff; - if (write(cache_fd, tmp, 2) != 2) { - close(cache_fd); - cache_fd = -1; - } - } + buffer[buffer_pos] = ch >> 8; + buffer[buffer_pos+1] = ch & 0xff; + buffer_pos += 2; return; } /* save the char codes of the loaded glyphs to a file */ -void glyph_cache_save(struct font* pf) +void glyph_cache_save(int font_id) { - if (pf != pf_from_handle(handle_for_glyphcache)) + int fd; + + if( font_id < 0 ) return; - if (pf->fd >= 0) + int handle = buflib_allocations[font_id]; + if ( handle < 0 ) + return; + + struct font *pf = pf_from_handle(handle); + if(pf && pf->fd >= 0) { - cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (cache_fd < 0) + /* FIXME: This sleep should not be necessary but without it * + * unloading multiple fonts and saving glyphcache files * + * quickly in succession creates multiple glyphcache files * + * with the same name. */ + sleep(HZ/10); + char filename[MAX_PATH]; + font_path_to_glyph_path(font_filename(font_id), filename); + fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) return; - lru_traverse(&pf->cache._lru, glyph_file_write); - - if (cache_fd >= 0) + cache_pf = pf; + cache_fd = fd; + lru_traverse(&cache_pf->cache._lru, glyph_file_write); + glyph_file_write(NULL); + if (cache_fd >= 0) { close(cache_fd); cache_fd = -1; @@ -797,14 +850,15 @@ 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) + int handle = buflib_allocations[font_id]; + if (handle < 0) return; + struct font *pf = pf_from_handle(handle); #define MAX_SORT 256 - if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) { - int fd; - int i, size; + if (pf->fd >= 0) { + int i, size, fd; unsigned char tmp[2]; unsigned short ch; unsigned short glyphs[MAX_SORT]; @@ -815,9 +869,16 @@ 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]; + font_path_to_glyph_path(font_filename(font_id), filename); + + fd = open(filename, O_RDONLY|O_BINARY); +#ifdef TRY_DEFAULT_GLYPHCACHE + /* if font specific file fails, try default */ + if (fd < 0) + fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); +#endif if (fd >= 0) { - /* only read what fits */ glyph_file_size = filesize( fd ); if ( glyph_file_size > 2*pf->cache._capacity ) { @@ -840,12 +901,8 @@ static void glyph_cache_load(struct font* pf) ushortcmp ); /* load font bitmaps */ - i = 0; - font_get_bits(pf, glyphs[i]); - for ( i = 1; i < size ; i++) { - if ( glyphs[i] != glyphs[i-1] ) + for( i = 0; i < size ; i++ ) font_get_bits(pf, glyphs[i]); - } /* redo to fix lru order */ for ( i = 0; i < size ; i++) diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 79a7a90a2b..76322d65a3 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -656,7 +656,7 @@ void shutdown_hw(void) if (battery_level_safe()) { /* do not save on critical battery */ #ifdef HAVE_LCD_BITMAP - glyph_cache_save(NULL); + font_unload_all(); #endif /* Commit pending writes if needed. Even though we don't do write caching,