diff --git a/apps/gui/skin_engine/skin_fonts.c b/apps/gui/skin_engine/skin_fonts.c index 2510c8c68c..b00f1572b8 100644 --- a/apps/gui/skin_engine/skin_fonts.c +++ b/apps/gui/skin_engine/skin_fonts.c @@ -57,9 +57,10 @@ void skin_font_init(void) } /* load a font into the skin buffer. return the font id. */ -int skin_font_load(char* font_name) +int skin_font_load(char* font_name, int glyphs) { int i; + int skin_font_size; struct font *pf; struct skin_font_info *font = NULL; char filename[MAX_PATH]; @@ -92,7 +93,14 @@ int skin_font_load(char* font_name) pf = &font->font; if (!font->buffer) { - pf->buffer_start = (char*)skin_buffer_alloc(SKIN_FONT_SIZE); + if (!glyphs) + glyphs = GLYPHS_TO_CACHE; + skin_font_size = glyphs * get_glyph_size(filename); + if ( !skin_font_size ) + { + skin_font_size = SKIN_FONT_SIZE; + } + pf->buffer_start = (char*)skin_buffer_alloc(skin_font_size); if (!pf->buffer_start) return -1; font->buffer = pf->buffer_start; @@ -101,7 +109,7 @@ int skin_font_load(char* font_name) { pf->buffer_start = font->buffer; } - pf->buffer_size = SKIN_FONT_SIZE; + pf->buffer_size = skin_font_size; pf->fd = -1; font->font_id = font_load(pf, filename); diff --git a/apps/gui/skin_engine/skin_fonts.h b/apps/gui/skin_engine/skin_fonts.h index 2988b43415..698ed4fe7c 100644 --- a/apps/gui/skin_engine/skin_fonts.h +++ b/apps/gui/skin_engine/skin_fonts.h @@ -36,11 +36,13 @@ #else #define SKIN_FONT_SIZE (1024*3) #endif +#define GLYPHS_TO_CACHE 256 void skin_font_init(void); -/* load a font into the skin buffer. return the font id. */ -int skin_font_load(char* font_name); +/* load a font into the skin buffer. return the font id. + * reserve room for glyphs glyphs */ +int skin_font_load(char* font_name, int glyphs); /* unload a skin font. If a font has been loaded more than once it wont actually * be unloaded untill all references have been unloaded */ diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 2c766162c3..a5ff64ac9d 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -343,6 +343,7 @@ static int parse_image_load(struct skin_element *element, struct skin_font { int id; /* the id from font_load */ char *name; /* filename without path and extension */ + int glyphs; /* how many glyphs to reserve room for */ }; static struct skin_font skinfonts[MAXUSERFONTS]; static int parse_font_load(struct skin_element *element, @@ -352,8 +353,13 @@ static int parse_font_load(struct skin_element *element, (void)wps_data; (void)token; int id = element->params[0].data.number; char *filename = element->params[1].data.text; + int glyphs; char *ptr; + if(element->params_count > 2) + glyphs = element->params[2].data.number; + else + glyphs = GLYPHS_TO_CACHE; #if defined(DEBUG) || defined(SIMULATOR) if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL) { @@ -367,6 +373,7 @@ static int parse_font_load(struct skin_element *element, return WPS_ERROR_INVALID_PARAM; skinfonts[id-FONT_FIRSTUSERFONT].id = -1; skinfonts[id-FONT_FIRSTUSERFONT].name = filename; + skinfonts[id-FONT_FIRSTUSERFONT].glyphs = glyphs; return 0; } @@ -1160,7 +1167,8 @@ static bool skin_load_fonts(struct wps_data *data) { char *dot = strchr(font->name, '.'); *dot = '\0'; - font->id = skin_font_load(font->name); + font->id = skin_font_load(font->name, + skinfonts[font_id-FONT_FIRSTUSERFONT].glyphs); } if (font->id < 0) diff --git a/firmware/export/font.h b/firmware/export/font.h index 7284564380..4aa99e4d05 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -121,6 +121,7 @@ void font_init(void) INIT_ATTR; int font_load_remoteui(const char* path); #endif int font_load(struct font* pf, const char *path); +int get_glyph_size(const char *path); void font_unload(int font_id); struct font* font_get(int font); diff --git a/firmware/font.c b/firmware/font.c index d4f0dfa77a..98bd6399fe 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -628,6 +628,35 @@ void glyph_cache_save(struct font* pf) return; } +int get_glyph_size(const char *path) +{ + struct font f; + int overhead; + char buf[FONT_HEADER_SIZE]; + + f.buffer_start = buf; + f.buffer_size = sizeof(buf); + f.buffer_position = buf; + + f.fd = open(path, O_RDONLY|O_BINARY); + if(f.fd < 0) + return 0; + + read(f.fd, f.buffer_position, FONT_HEADER_SIZE); + f.buffer_end = f.buffer_position + FONT_HEADER_SIZE; + + if( !font_load_header(&f) ) + { + close(f.fd); + return 0; + } + close(f.fd); + + overhead = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + + sizeof( unsigned short); + return overhead + (f.maxwidth * ((f.height + 7) / 8)); +} + static int ushortcmp(const void *a, const void *b) { return ((int)(*(unsigned short*)a - *(unsigned short*)b)); diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index 9c0b51dacf..7c5f45e1af 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -172,7 +172,7 @@ static const struct tag_info legal_tags[] = { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|[IT]I", 0 }, { SKIN_TOKEN_IMAGE_DISPLAY, "x", "SFII", 0|NOBREAK }, - { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF", 0|NOBREAK }, + { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF|i", 0|NOBREAK }, { SKIN_TOKEN_ALBUMART_LOAD, "Cl" , "IIII|ss", 0|NOBREAK }, { SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", SKIN_REFRESH_STATIC }, { SKIN_TOKEN_ALBUMART_FOUND, "C" , "", SKIN_REFRESH_STATIC }, diff --git a/manual/advanced_topics/main.tex b/manual/advanced_topics/main.tex index ef0d22409e..d7646eafc4 100644 --- a/manual/advanced_topics/main.tex +++ b/manual/advanced_topics/main.tex @@ -313,16 +313,18 @@ Additional fonts can be loaded within each screen file to be used in that screen. In this way not only can you have different fonts between e.g. the menu and the WPS, but you can use multiple fonts in each of the individual screens.\\ -\config{\%Fl('id',filename)} +\config{\%Fl('id',filename,glyphs)} \begin{itemize} \item `id' is the number you want to use in viewport declarations, 0 and 1 are reserved and so can't be used. \item `filename' is the font filename to load. Fonts should be stored in \fname{/.rockbox/fonts/} + \item `glyphs' is an optional specification of how many unique glyphs to + store in memory. \end{itemize} - An example would be: \config{\%Fl(2,12-Nimbus.fnt)} + An example would be: \config{\%Fl(2,12-Nimbus.fnt,100)} }