Accept FS#11567 by Fred Bauer - better memory management for the skin fonts

%Fl now takes an optional 3rd param which is the number of glyphs to cache (default to 256). the smaller the number, the less ram will be used (i.e using 15 for a font which only shown numbers is a good idea)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27882 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2010-08-25 14:11:38 +00:00
parent 05d16b1d4e
commit faaf431d32
7 changed files with 59 additions and 9 deletions

View file

@ -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);

View file

@ -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 */

View file

@ -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)

View file

@ -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);

View file

@ -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));

View file

@ -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 },

View file

@ -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)}
}