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:
parent
05d16b1d4e
commit
faaf431d32
7 changed files with 59 additions and 9 deletions
|
@ -57,9 +57,10 @@ void skin_font_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load a font into the skin buffer. return the font id. */
|
/* 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 i;
|
||||||
|
int skin_font_size;
|
||||||
struct font *pf;
|
struct font *pf;
|
||||||
struct skin_font_info *font = NULL;
|
struct skin_font_info *font = NULL;
|
||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH];
|
||||||
|
@ -92,7 +93,14 @@ int skin_font_load(char* font_name)
|
||||||
pf = &font->font;
|
pf = &font->font;
|
||||||
if (!font->buffer)
|
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)
|
if (!pf->buffer_start)
|
||||||
return -1;
|
return -1;
|
||||||
font->buffer = pf->buffer_start;
|
font->buffer = pf->buffer_start;
|
||||||
|
@ -101,7 +109,7 @@ int skin_font_load(char* font_name)
|
||||||
{
|
{
|
||||||
pf->buffer_start = font->buffer;
|
pf->buffer_start = font->buffer;
|
||||||
}
|
}
|
||||||
pf->buffer_size = SKIN_FONT_SIZE;
|
pf->buffer_size = skin_font_size;
|
||||||
|
|
||||||
pf->fd = -1;
|
pf->fd = -1;
|
||||||
font->font_id = font_load(pf, filename);
|
font->font_id = font_load(pf, filename);
|
||||||
|
|
|
@ -36,11 +36,13 @@
|
||||||
#else
|
#else
|
||||||
#define SKIN_FONT_SIZE (1024*3)
|
#define SKIN_FONT_SIZE (1024*3)
|
||||||
#endif
|
#endif
|
||||||
|
#define GLYPHS_TO_CACHE 256
|
||||||
|
|
||||||
void skin_font_init(void);
|
void skin_font_init(void);
|
||||||
|
|
||||||
/* load a font into the skin buffer. return the font id. */
|
/* load a font into the skin buffer. return the font id.
|
||||||
int skin_font_load(char* font_name);
|
* 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
|
/* unload a skin font. If a font has been loaded more than once it wont actually
|
||||||
* be unloaded untill all references have been unloaded */
|
* be unloaded untill all references have been unloaded */
|
||||||
|
|
|
@ -343,6 +343,7 @@ static int parse_image_load(struct skin_element *element,
|
||||||
struct skin_font {
|
struct skin_font {
|
||||||
int id; /* the id from font_load */
|
int id; /* the id from font_load */
|
||||||
char *name; /* filename without path and extension */
|
char *name; /* filename without path and extension */
|
||||||
|
int glyphs; /* how many glyphs to reserve room for */
|
||||||
};
|
};
|
||||||
static struct skin_font skinfonts[MAXUSERFONTS];
|
static struct skin_font skinfonts[MAXUSERFONTS];
|
||||||
static int parse_font_load(struct skin_element *element,
|
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;
|
(void)wps_data; (void)token;
|
||||||
int id = element->params[0].data.number;
|
int id = element->params[0].data.number;
|
||||||
char *filename = element->params[1].data.text;
|
char *filename = element->params[1].data.text;
|
||||||
|
int glyphs;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
|
if(element->params_count > 2)
|
||||||
|
glyphs = element->params[2].data.number;
|
||||||
|
else
|
||||||
|
glyphs = GLYPHS_TO_CACHE;
|
||||||
#if defined(DEBUG) || defined(SIMULATOR)
|
#if defined(DEBUG) || defined(SIMULATOR)
|
||||||
if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL)
|
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;
|
return WPS_ERROR_INVALID_PARAM;
|
||||||
skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
|
skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
|
||||||
skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
|
skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
|
||||||
|
skinfonts[id-FONT_FIRSTUSERFONT].glyphs = glyphs;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1160,7 +1167,8 @@ static bool skin_load_fonts(struct wps_data *data)
|
||||||
{
|
{
|
||||||
char *dot = strchr(font->name, '.');
|
char *dot = strchr(font->name, '.');
|
||||||
*dot = '\0';
|
*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)
|
if (font->id < 0)
|
||||||
|
|
|
@ -121,6 +121,7 @@ void font_init(void) INIT_ATTR;
|
||||||
int font_load_remoteui(const char* path);
|
int font_load_remoteui(const char* path);
|
||||||
#endif
|
#endif
|
||||||
int font_load(struct font* pf, const char *path);
|
int font_load(struct font* pf, const char *path);
|
||||||
|
int get_glyph_size(const char *path);
|
||||||
void font_unload(int font_id);
|
void font_unload(int font_id);
|
||||||
|
|
||||||
struct font* font_get(int font);
|
struct font* font_get(int font);
|
||||||
|
|
|
@ -628,6 +628,35 @@ void glyph_cache_save(struct font* pf)
|
||||||
return;
|
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)
|
static int ushortcmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return ((int)(*(unsigned short*)a - *(unsigned short*)b));
|
return ((int)(*(unsigned short*)a - *(unsigned short*)b));
|
||||||
|
|
|
@ -172,7 +172,7 @@ static const struct tag_info legal_tags[] =
|
||||||
{ SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|[IT]I", 0 },
|
{ SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|[IT]I", 0 },
|
||||||
{ SKIN_TOKEN_IMAGE_DISPLAY, "x", "SFII", 0|NOBREAK },
|
{ 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_LOAD, "Cl" , "IIII|ss", 0|NOBREAK },
|
||||||
{ SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", SKIN_REFRESH_STATIC },
|
{ SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", SKIN_REFRESH_STATIC },
|
||||||
{ SKIN_TOKEN_ALBUMART_FOUND, "C" , "", SKIN_REFRESH_STATIC },
|
{ SKIN_TOKEN_ALBUMART_FOUND, "C" , "", SKIN_REFRESH_STATIC },
|
||||||
|
|
|
@ -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
|
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.\\
|
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}
|
\begin{itemize}
|
||||||
\item `id' is the number you want to use in viewport declarations, 0 and 1
|
\item `id' is the number you want to use in viewport declarations, 0 and 1
|
||||||
are reserved and so can't be used.
|
are reserved and so can't be used.
|
||||||
\item `filename' is the font filename to load. Fonts should be stored in
|
\item `filename' is the font filename to load. Fonts should be stored in
|
||||||
\fname{/.rockbox/fonts/}
|
\fname{/.rockbox/fonts/}
|
||||||
|
\item `glyphs' is an optional specification of how many unique glyphs to
|
||||||
|
store in memory.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
An example would be: \config{\%Fl(2,12-Nimbus.fnt)}
|
An example would be: \config{\%Fl(2,12-Nimbus.fnt,100)}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue