summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-08-25 14:11:38 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-08-25 14:11:38 +0000
commitfaaf431d321f30881ac39342d4cdc2170b922cb6 (patch)
tree23689929fef19f4d572157e53eeef652057af8e8
parent05d16b1d4e8947b23afc64a52ccfccbf2284d97b (diff)
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
-rw-r--r--apps/gui/skin_engine/skin_fonts.c14
-rw-r--r--apps/gui/skin_engine/skin_fonts.h6
-rw-r--r--apps/gui/skin_engine/skin_parser.c10
-rw-r--r--firmware/export/font.h1
-rw-r--r--firmware/font.c29
-rw-r--r--lib/skin_parser/tag_table.c2
-rw-r--r--manual/advanced_topics/main.tex6
7 files changed, 59 insertions, 9 deletions
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)}
}