diff options
author | Fred Bauer <fred.w.bauer@gmail.com> | 2011-11-19 23:34:26 +0000 |
---|---|---|
committer | Fred Bauer <fred.w.bauer@gmail.com> | 2011-11-19 23:34:26 +0000 |
commit | ea7a89606cfaffb2ae2c843ea9868bd8c8dd16c9 (patch) | |
tree | 5ff1f18c66be4c25f32e03ffadeb6bb3cb568656 | |
parent | d78e05c5722356fd8ce20cdb4c40df44cc2b4d33 (diff) | |
download | rockbox-ea7a89606cfaffb2ae2c843ea9868bd8c8dd16c9.tar.gz rockbox-ea7a89606cfaffb2ae2c843ea9868bd8c8dd16c9.zip |
FS#12293 Global default glyph setting in System > Limits > Glyphs To Cache. Defaults to 250. This saves a lot of RAM while still allowing non-English users to have adequate glyph coverage.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31031 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 6 | ||||
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/menus/settings_menu.c | 9 | ||||
-rw-r--r-- | apps/settings.c | 2 | ||||
-rw-r--r-- | apps/settings.h | 1 | ||||
-rw-r--r-- | apps/settings_list.c | 6 | ||||
-rw-r--r-- | firmware/export/font.h | 4 | ||||
-rw-r--r-- | firmware/font.c | 455 | ||||
-rw-r--r-- | manual/advanced_topics/main.tex | 3 | ||||
-rw-r--r-- | manual/configure_rockbox/system_options.tex | 10 | ||||
-rw-r--r-- | tools/convbdf.c | 1 |
11 files changed, 247 insertions, 264 deletions
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index ad10689107..c4a96d0e9b 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c | |||
@@ -78,7 +78,6 @@ | |||
78 | 78 | ||
79 | #define WPS_ERROR_INVALID_PARAM -1 | 79 | #define WPS_ERROR_INVALID_PARAM -1 |
80 | 80 | ||
81 | #define GLYPHS_TO_CACHE 256 | ||
82 | static char* skin_buffer = NULL; | 81 | static char* skin_buffer = NULL; |
83 | void skinparser_set_buffer(char* pointer) | 82 | void skinparser_set_buffer(char* pointer) |
84 | { | 83 | { |
@@ -468,7 +467,7 @@ static int parse_font_load(struct skin_element *element, | |||
468 | if(element->params_count > 2) | 467 | if(element->params_count > 2) |
469 | glyphs = get_param(element, 2)->data.number; | 468 | glyphs = get_param(element, 2)->data.number; |
470 | else | 469 | else |
471 | glyphs = GLYPHS_TO_CACHE; | 470 | glyphs = global_settings.glyphs; |
472 | if (id < 2) | 471 | if (id < 2) |
473 | { | 472 | { |
474 | DEBUGF("font id must be >= 2\n"); | 473 | DEBUGF("font id must be >= 2\n"); |
@@ -1742,8 +1741,7 @@ static bool skin_load_fonts(struct wps_data *data) | |||
1742 | char path[MAX_PATH]; | 1741 | char path[MAX_PATH]; |
1743 | snprintf(path, sizeof path, FONT_DIR "/%s", font->name); | 1742 | snprintf(path, sizeof path, FONT_DIR "/%s", font->name); |
1744 | #ifndef __PCTOOL__ | 1743 | #ifndef __PCTOOL__ |
1745 | font->id = font_load_ex(path, | 1744 | font->id = font_load_ex(path, 0, skinfonts[font_id-2].glyphs); |
1746 | font_glyphs_to_bufsize(path, skinfonts[font_id-2].glyphs)); | ||
1747 | 1745 | ||
1748 | #else | 1746 | #else |
1749 | font->id = font_load(path); | 1747 | font->id = font_load(path); |
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index a228a78f7f..29e6205729 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -12951,3 +12951,17 @@ | |||
12951 | hardware_click: "Speaker Keyclick" | 12951 | hardware_click: "Speaker Keyclick" |
12952 | </voice> | 12952 | </voice> |
12953 | </phrase> | 12953 | </phrase> |
12954 | <phrase> | ||
12955 | id: LANG_GLYPHS | ||
12956 | desc: in settings_menu | ||
12957 | user: core | ||
12958 | <source> | ||
12959 | *: "Glyphs To Cache" | ||
12960 | </source> | ||
12961 | <dest> | ||
12962 | *: "Glyphs To Cache" | ||
12963 | </dest> | ||
12964 | <voice> | ||
12965 | *: "Glyphs To Cache" | ||
12966 | </voice> | ||
12967 | </phrase> | ||
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index 079e86616d..4ea98efd95 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c | |||
@@ -221,8 +221,15 @@ MENUITEM_SETTING(poweroff, &global_settings.poweroff, NULL); | |||
221 | /* Limits menu */ | 221 | /* Limits menu */ |
222 | MENUITEM_SETTING(max_files_in_dir, &global_settings.max_files_in_dir, NULL); | 222 | MENUITEM_SETTING(max_files_in_dir, &global_settings.max_files_in_dir, NULL); |
223 | MENUITEM_SETTING(max_files_in_playlist, &global_settings.max_files_in_playlist, NULL); | 223 | MENUITEM_SETTING(max_files_in_playlist, &global_settings.max_files_in_playlist, NULL); |
224 | #ifdef HAVE_LCD_BITMAP | ||
225 | MENUITEM_SETTING(default_glyphs, &global_settings.glyphs, NULL); | ||
226 | #endif | ||
224 | MAKE_MENU(limits_menu, ID2P(LANG_LIMITS_MENU), 0, Icon_NOICON, | 227 | MAKE_MENU(limits_menu, ID2P(LANG_LIMITS_MENU), 0, Icon_NOICON, |
225 | &max_files_in_dir, &max_files_in_playlist); | 228 | &max_files_in_dir, &max_files_in_playlist |
229 | #ifdef HAVE_LCD_BITMAP | ||
230 | ,&default_glyphs | ||
231 | #endif | ||
232 | ); | ||
226 | 233 | ||
227 | 234 | ||
228 | /* Keyclick menu */ | 235 | /* Keyclick menu */ |
diff --git a/apps/settings.c b/apps/settings.c index fbfa438ab5..c22fa50f17 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -886,7 +886,7 @@ void settings_apply(bool read_disk) | |||
886 | CHART2(">font_load ", global_settings.font_file); | 886 | CHART2(">font_load ", global_settings.font_file); |
887 | if (font_ui >= 0) | 887 | if (font_ui >= 0) |
888 | font_unload(font_ui); | 888 | font_unload(font_ui); |
889 | rc = font_load(buf); | 889 | rc = font_load_ex(buf, 0, global_settings.glyphs); |
890 | CHART2("<font_load ", global_settings.font_file); | 890 | CHART2("<font_load ", global_settings.font_file); |
891 | screens[SCREEN_MAIN].setuifont(rc); | 891 | screens[SCREEN_MAIN].setuifont(rc); |
892 | screens[SCREEN_MAIN].setfont(rc); | 892 | screens[SCREEN_MAIN].setfont(rc); |
diff --git a/apps/settings.h b/apps/settings.h index 06eba76e3c..6608df6111 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -672,6 +672,7 @@ struct user_settings | |||
672 | unsigned char icon_file[MAX_FILENAME+1]; | 672 | unsigned char icon_file[MAX_FILENAME+1]; |
673 | unsigned char viewers_icon_file[MAX_FILENAME+1]; | 673 | unsigned char viewers_icon_file[MAX_FILENAME+1]; |
674 | unsigned char font_file[MAX_FILENAME+1]; /* last font */ | 674 | unsigned char font_file[MAX_FILENAME+1]; /* last font */ |
675 | int glyphs; | ||
675 | #ifdef HAVE_REMOTE_LCD | 676 | #ifdef HAVE_REMOTE_LCD |
676 | unsigned char remote_font_file[MAX_FILENAME+1]; /* last font */ | 677 | unsigned char remote_font_file[MAX_FILENAME+1]; /* last font */ |
677 | #endif | 678 | #endif |
diff --git a/apps/settings_list.c b/apps/settings_list.c index 9232811ada..305edd93ba 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -222,6 +222,9 @@ static const char graphic_numeric[] = "graphic,numeric"; | |||
222 | #else | 222 | #else |
223 | #define DEFAULT_FONTNAME "35-Adobe-Helvetica" | 223 | #define DEFAULT_FONTNAME "35-Adobe-Helvetica" |
224 | #endif | 224 | #endif |
225 | #define DEFAULT_GLYPHS 250 | ||
226 | #define MIN_GLYPHS 50 | ||
227 | #define MAX_GLYPHS 65540 | ||
225 | 228 | ||
226 | #else | 229 | #else |
227 | #define DEFAULT_FONTNAME "" | 230 | #define DEFAULT_FONTNAME "" |
@@ -1622,6 +1625,9 @@ const struct settings_list settings[] = { | |||
1622 | #ifdef HAVE_LCD_BITMAP | 1625 | #ifdef HAVE_LCD_BITMAP |
1623 | TEXT_SETTING(F_THEMESETTING, font_file, "font", | 1626 | TEXT_SETTING(F_THEMESETTING, font_file, "font", |
1624 | DEFAULT_FONTNAME, FONT_DIR "/", ".fnt"), | 1627 | DEFAULT_FONTNAME, FONT_DIR "/", ".fnt"), |
1628 | INT_SETTING(0, glyphs, LANG_GLYPHS, DEFAULT_GLYPHS, | ||
1629 | "glyphs", UNIT_INT, MIN_GLYPHS, MAX_GLYPHS, 10, | ||
1630 | NULL, NULL, NULL), | ||
1625 | #endif | 1631 | #endif |
1626 | #ifdef HAVE_REMOTE_LCD | 1632 | #ifdef HAVE_REMOTE_LCD |
1627 | TEXT_SETTING(F_THEMESETTING, remote_font_file, "remote font", | 1633 | TEXT_SETTING(F_THEMESETTING, remote_font_file, "remote font", |
diff --git a/firmware/export/font.h b/firmware/export/font.h index 914d3aa2ff..faa10391f8 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h | |||
@@ -102,6 +102,7 @@ struct font { | |||
102 | int fd; /* fd for the font file. >= 0 if cached */ | 102 | int fd; /* fd for the font file. >= 0 if cached */ |
103 | int fd_width; /* fd for the font file. >= 0 if cached */ | 103 | int fd_width; /* fd for the font file. >= 0 if cached */ |
104 | int fd_offset; /* fd for the font file. >= 0 if cached */ | 104 | int fd_offset; /* fd for the font file. >= 0 if cached */ |
105 | int handle; /* core_allocator handle */ | ||
105 | unsigned char *buffer_start; /* buffer to store the font in */ | 106 | unsigned char *buffer_start; /* buffer to store the font in */ |
106 | unsigned char *buffer_position; /* position in the buffer */ | 107 | unsigned char *buffer_position; /* position in the buffer */ |
107 | unsigned char *buffer_end; /* end of the buffer */ | 108 | unsigned char *buffer_end; /* end of the buffer */ |
@@ -119,8 +120,7 @@ struct font { | |||
119 | void font_init(void) INIT_ATTR; | 120 | void font_init(void) INIT_ATTR; |
120 | const char* font_filename(int font_id); | 121 | const char* font_filename(int font_id); |
121 | int font_load(const char *path); | 122 | int font_load(const char *path); |
122 | int font_load_ex(const char *path, size_t buffer_size); | 123 | int font_load_ex(const char *path, size_t buffer_size, int glyphs); |
123 | int font_glyphs_to_bufsize(const char *path, int glyphs); | ||
124 | void font_unload(int font_id); | 124 | void font_unload(int font_id); |
125 | void font_unload_all(void); | 125 | void font_unload_all(void); |
126 | void font_lock(int font_id, bool lock); | 126 | void font_lock(int font_id, bool lock); |
diff --git a/firmware/font.c b/firmware/font.c index ff5bc4b008..5dd080b89c 100644 --- a/firmware/font.c +++ b/firmware/font.c | |||
@@ -55,6 +55,11 @@ | |||
55 | #define MAX_FONT_SIZE 4000 | 55 | #define MAX_FONT_SIZE 4000 |
56 | #endif | 56 | #endif |
57 | #endif | 57 | #endif |
58 | #define GLYPHS_TO_CACHE 256 | ||
59 | |||
60 | #if MEMORYSIZE < 4 | ||
61 | #define FONT_HARD_LIMIT | ||
62 | #endif | ||
58 | 63 | ||
59 | #ifndef FONT_HEADER_SIZE | 64 | #ifndef FONT_HEADER_SIZE |
60 | #define FONT_HEADER_SIZE 36 | 65 | #define FONT_HEADER_SIZE 36 |
@@ -117,6 +122,8 @@ static int buflibmove_callback(int handle, void* current, void* new) | |||
117 | } | 122 | } |
118 | static void lock_font_handle(int handle, bool lock) | 123 | static void lock_font_handle(int handle, bool lock) |
119 | { | 124 | { |
125 | if ( handle < 0 ) | ||
126 | return; | ||
120 | struct buflib_alloc_data *alloc = core_get_data(handle); | 127 | struct buflib_alloc_data *alloc = core_get_data(handle); |
121 | if ( lock ) | 128 | if ( lock ) |
122 | alloc->handle_locks++; | 129 | alloc->handle_locks++; |
@@ -150,7 +157,7 @@ static inline unsigned char *buffer_from_handle(int handle) | |||
150 | 157 | ||
151 | /* Font cache structures */ | 158 | /* Font cache structures */ |
152 | static void cache_create(struct font* pf); | 159 | static void cache_create(struct font* pf); |
153 | static void glyph_cache_load(int fond_id); | 160 | static void glyph_cache_load(const char *font_path, struct font *pf); |
154 | /* End Font cache structures */ | 161 | /* End Font cache structures */ |
155 | 162 | ||
156 | void font_init(void) | 163 | void font_init(void) |
@@ -199,48 +206,14 @@ static int glyph_bytes( struct font *pf, int width ) | |||
199 | return (ret + 1) & ~1; | 206 | return (ret + 1) & ~1; |
200 | } | 207 | } |
201 | 208 | ||
202 | static struct font* font_load_header(struct font *pf) | ||
203 | { | ||
204 | /* Check we have enough data */ | ||
205 | if (!HAVEBYTES(28)) | ||
206 | return NULL; | ||
207 | |||
208 | /* read magic and version #*/ | ||
209 | if (memcmp(pf->buffer_position, VERSION, 4) != 0) | ||
210 | return NULL; | ||
211 | |||
212 | pf->buffer_position += 4; | ||
213 | |||
214 | /* font info*/ | ||
215 | pf->maxwidth = readshort(pf); | ||
216 | pf->height = readshort(pf); | ||
217 | pf->ascent = readshort(pf); | ||
218 | pf->depth = readshort(pf); | ||
219 | pf->firstchar = readlong(pf); | ||
220 | pf->defaultchar = readlong(pf); | ||
221 | pf->size = readlong(pf); | ||
222 | |||
223 | /* get variable font data sizes*/ | ||
224 | /* # words of bitmap_t*/ | ||
225 | pf->bits_size = readlong(pf); | ||
226 | |||
227 | return pf; | ||
228 | } | ||
229 | /* Load memory font */ | 209 | /* Load memory font */ |
230 | static struct font* font_load_in_memory(struct font* pf) | 210 | static struct font* font_load_in_memory(struct font* pf, |
211 | int32_t noffset, | ||
212 | int32_t nwidth ) | ||
231 | { | 213 | { |
232 | int32_t i, noffset, nwidth; | 214 | int i; |
233 | |||
234 | if (!HAVEBYTES(4)) | ||
235 | return NULL; | ||
236 | |||
237 | /* # longs of offset*/ | ||
238 | noffset = readlong(pf); | ||
239 | |||
240 | /* # bytes of width*/ | ||
241 | nwidth = readlong(pf); | ||
242 | |||
243 | /* variable font data*/ | 215 | /* variable font data*/ |
216 | pf->buffer_position = pf->buffer_start + 36; | ||
244 | pf->bits = (unsigned char *)pf->buffer_position; | 217 | pf->bits = (unsigned char *)pf->buffer_position; |
245 | pf->buffer_position += pf->bits_size*sizeof(unsigned char); | 218 | pf->buffer_position += pf->bits_size*sizeof(unsigned char); |
246 | 219 | ||
@@ -303,20 +276,10 @@ static struct font* font_load_in_memory(struct font* pf) | |||
303 | } | 276 | } |
304 | 277 | ||
305 | /* Load cached font */ | 278 | /* Load cached font */ |
306 | static struct font* font_load_cached(struct font* pf) | 279 | static struct font* font_load_cached(struct font* pf, |
280 | int32_t nwidth, | ||
281 | int32_t noffset) | ||
307 | { | 282 | { |
308 | uint32_t noffset, nwidth; | ||
309 | unsigned char* oldfileptr = pf->buffer_position; | ||
310 | |||
311 | if (!HAVEBYTES(2 * sizeof(int32_t))) | ||
312 | return NULL; | ||
313 | |||
314 | /* # longs of offset*/ | ||
315 | noffset = readlong(pf); | ||
316 | |||
317 | /* # bytes of width*/ | ||
318 | nwidth = readlong(pf); | ||
319 | |||
320 | /* We are now at the bitmap data, this is fixed at 36.. */ | 283 | /* We are now at the bitmap data, this is fixed at 36.. */ |
321 | pf->bits = NULL; | 284 | pf->bits = NULL; |
322 | 285 | ||
@@ -352,96 +315,12 @@ static struct font* font_load_cached(struct font* pf) | |||
352 | else | 315 | else |
353 | pf->file_width_offset = 0; | 316 | pf->file_width_offset = 0; |
354 | 317 | ||
355 | pf->buffer_position = oldfileptr; | ||
356 | |||
357 | /* Create the cache */ | 318 | /* Create the cache */ |
358 | cache_create(pf); | 319 | cache_create(pf); |
359 | 320 | ||
360 | return pf; | 321 | return pf; |
361 | } | 322 | } |
362 | 323 | ||
363 | static bool internal_load_font(int font_id, const char *path, char *buf, | ||
364 | size_t buf_size, int handle) | ||
365 | { | ||
366 | size_t size; | ||
367 | struct font* pf = pf_from_handle(handle); | ||
368 | |||
369 | /* open and read entire font file*/ | ||
370 | pf->fd = open(path, O_RDONLY|O_BINARY); | ||
371 | |||
372 | if (pf->fd < 0) { | ||
373 | DEBUGF("Can't open font: %s\n", path); | ||
374 | return false; | ||
375 | } | ||
376 | |||
377 | /* Check file size */ | ||
378 | size = filesize(pf->fd); | ||
379 | pf->buffer_start = buf; | ||
380 | pf->buffer_size = buf_size; | ||
381 | |||
382 | pf->buffer_position = buf; | ||
383 | |||
384 | if (size > pf->buffer_size) | ||
385 | { | ||
386 | read(pf->fd, pf->buffer_position, FONT_HEADER_SIZE); | ||
387 | pf->buffer_end = pf->buffer_position + FONT_HEADER_SIZE; | ||
388 | |||
389 | if (!font_load_header(pf)) | ||
390 | { | ||
391 | DEBUGF("Failed font header load"); | ||
392 | close(pf->fd); | ||
393 | pf->fd = -1; | ||
394 | return false; | ||
395 | } | ||
396 | |||
397 | if (!font_load_cached(pf)) | ||
398 | { | ||
399 | DEBUGF("Failed font cache load"); | ||
400 | close(pf->fd); | ||
401 | pf->fd = -1; | ||
402 | return false; | ||
403 | } | ||
404 | |||
405 | /* Cheat to get sector cache for different parts of font * | ||
406 | * file while preloading glyphs. Without this the disk head * | ||
407 | * thrashes between the width, offset, and bitmap data * | ||
408 | * in glyph_cache_load(). */ | ||
409 | pf->fd_width = open(path, O_RDONLY|O_BINARY); | ||
410 | pf->fd_offset = open(path, O_RDONLY|O_BINARY); | ||
411 | |||
412 | glyph_cache_load(font_id); | ||
413 | |||
414 | if(pf->fd_width >= 0) | ||
415 | close(pf->fd_width); | ||
416 | pf->fd_width = -1; | ||
417 | |||
418 | if(pf->fd_offset >= 0) | ||
419 | close(pf->fd_offset); | ||
420 | pf->fd_offset = -1; | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | read(pf->fd, pf->buffer_position, pf->buffer_size); | ||
425 | pf->buffer_end = pf->buffer_position + size; | ||
426 | close(pf->fd); | ||
427 | pf->fd = -1; | ||
428 | pf->fd_width = -1; | ||
429 | pf->fd_offset = -1; | ||
430 | |||
431 | if (!font_load_header(pf)) | ||
432 | { | ||
433 | DEBUGF("Failed font header load"); | ||
434 | return false; | ||
435 | } | ||
436 | |||
437 | if (!font_load_in_memory(pf)) | ||
438 | { | ||
439 | DEBUGF("Failed mem load"); | ||
440 | return false; | ||
441 | } | ||
442 | } | ||
443 | return true; | ||
444 | } | ||
445 | 324 | ||
446 | static int find_font_index(const char* path) | 325 | static int find_font_index(const char* path) |
447 | { | 326 | { |
@@ -457,30 +336,6 @@ static int find_font_index(const char* path) | |||
457 | return FONT_SYSFIXED; | 336 | return FONT_SYSFIXED; |
458 | } | 337 | } |
459 | 338 | ||
460 | static int alloc_and_init(int font_idx, const char* name, size_t size) | ||
461 | { | ||
462 | int *phandle = &buflib_allocations[font_idx]; | ||
463 | int handle = *phandle; | ||
464 | struct buflib_alloc_data *pdata; | ||
465 | struct font *pf; | ||
466 | size_t alloc_size = size + sizeof(struct buflib_alloc_data); | ||
467 | if (handle > 0) | ||
468 | return handle; | ||
469 | *phandle = core_alloc_ex(name, alloc_size, &buflibops); | ||
470 | handle = *phandle; | ||
471 | if (handle < 0) | ||
472 | return handle; | ||
473 | pdata = core_get_data(handle); | ||
474 | pf = &pdata->font; | ||
475 | pdata->handle_locks = 0; | ||
476 | pdata->refcount = 1; | ||
477 | pf->buffer_position = pf->buffer_start = buffer_from_handle(handle); | ||
478 | pf->buffer_size = size; | ||
479 | pf->fd_width = -1; | ||
480 | pf->fd_offset = -1; | ||
481 | return handle; | ||
482 | } | ||
483 | |||
484 | const char* font_filename(int font_id) | 339 | const char* font_filename(int font_id) |
485 | { | 340 | { |
486 | int handle = buflib_allocations[font_id]; | 341 | int handle = buflib_allocations[font_id]; |
@@ -488,22 +343,118 @@ const char* font_filename(int font_id) | |||
488 | return core_get_name(handle); | 343 | return core_get_name(handle); |
489 | return NULL; | 344 | return NULL; |
490 | } | 345 | } |
491 | 346 | ||
492 | /* read and load font into incore font structure, | 347 | size_t font_glyphs_to_bufsize(struct font *pf, int glyphs) |
493 | * returns the font number on success, -1 on failure */ | 348 | { |
494 | int font_load_ex(const char *path, size_t buffer_size) | 349 | size_t bufsize; |
350 | |||
351 | /* LRU bytes per glyph */ | ||
352 | bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + | ||
353 | sizeof( unsigned short); | ||
354 | /* Image bytes per glyph */ | ||
355 | bufsize += glyph_bytes(pf, pf->maxwidth); | ||
356 | bufsize *= glyphs; | ||
357 | |||
358 | return bufsize; | ||
359 | } | ||
360 | |||
361 | static struct font* font_load_header(int fd, struct font *pheader, | ||
362 | struct font *pf, | ||
363 | uint32_t *nwidth, uint32_t *noffset) | ||
364 | { | ||
365 | /* Load the header. Readshort() and readlong() * | ||
366 | * update buffer_position address as they read */ | ||
367 | pheader->buffer_start = pheader->buffer_position = (char *)pheader; | ||
368 | pheader->buffer_size = FONT_HEADER_SIZE; | ||
369 | pheader->buffer_end = pheader->buffer_start + pheader->buffer_size; | ||
370 | |||
371 | if (read(fd, pheader, FONT_HEADER_SIZE) != FONT_HEADER_SIZE) | ||
372 | return NULL; | ||
373 | |||
374 | /* read magic and version #*/ | ||
375 | if (memcmp(pheader->buffer_position, VERSION, 4) != 0) | ||
376 | return NULL; | ||
377 | |||
378 | pheader->buffer_position += 4; | ||
379 | |||
380 | /* font info*/ | ||
381 | pf->maxwidth = readshort(pheader); | ||
382 | pf->height = readshort(pheader); | ||
383 | pf->ascent = readshort(pheader); | ||
384 | pf->depth = readshort(pheader); | ||
385 | pf->firstchar = readlong(pheader); | ||
386 | pf->defaultchar = readlong(pheader); | ||
387 | pf->size = readlong(pheader); | ||
388 | |||
389 | /* get variable font data sizes*/ | ||
390 | /* # words of bitmap_t*/ | ||
391 | pf->bits_size = readlong(pheader); | ||
392 | *noffset = readlong(pheader); | ||
393 | *nwidth = readlong(pheader); | ||
394 | |||
395 | return pf; | ||
396 | } | ||
397 | |||
398 | /* load a font with room for glyphs, limited to bufsize if not zero */ | ||
399 | int font_load_ex( const char *path, size_t buf_size, int glyphs ) | ||
495 | { | 400 | { |
401 | //printf("\nfont_load_ex(%s, %d, %d)\n", path, buf_size, glyphs); | ||
402 | int fd = open(path, O_RDONLY|O_BINARY); | ||
403 | if ( fd < 0 ) | ||
404 | return -1; | ||
405 | |||
406 | /* load font struct f with file header */ | ||
407 | int file_size = filesize( fd ); | ||
408 | struct font header; | ||
409 | struct font *pheader = &header; | ||
410 | struct font f; | ||
411 | |||
412 | uint32_t nwidth, noffset; | ||
413 | if ( !font_load_header( fd, pheader, &f, &nwidth, &noffset ) | ||
414 | #if LCD_DEPTH < 16 | ||
415 | || f.depth | ||
416 | #endif | ||
417 | ) | ||
418 | { | ||
419 | close(fd); | ||
420 | return -1; | ||
421 | } | ||
422 | |||
423 | /* examine f and calc buffer size */ | ||
424 | bool cached = false; | ||
425 | size_t bufsize = buf_size; | ||
426 | size_t glyph_buf_size = font_glyphs_to_bufsize( &f, glyphs ); | ||
427 | |||
428 | if ( bufsize && glyphs && bufsize > glyph_buf_size) | ||
429 | bufsize = glyph_buf_size; | ||
430 | else | ||
431 | { | ||
432 | if ( glyphs ) | ||
433 | bufsize = glyph_buf_size; | ||
434 | else | ||
435 | bufsize = MAX_FONT_SIZE; | ||
436 | } | ||
437 | #ifdef FONT_HARD_LIMIT | ||
438 | if ( bufsize > MAX_FONT_SIZE ) | ||
439 | bufsize = MAX_FONT_SIZE; | ||
440 | #endif | ||
441 | if ( bufsize < (size_t) file_size ) | ||
442 | cached = true; | ||
443 | else | ||
444 | bufsize = file_size; | ||
445 | |||
446 | /* check already loaded */ | ||
496 | int font_id = find_font_index(path); | 447 | int font_id = find_font_index(path); |
497 | char *buffer; | ||
498 | int handle; | ||
499 | 448 | ||
500 | if (font_id > FONT_SYSFIXED) | 449 | if (font_id > FONT_SYSFIXED) |
501 | { | 450 | { |
502 | /* already loaded, no need to reload */ | 451 | /* already loaded, no need to reload */ |
503 | struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]); | 452 | struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]); |
504 | if (pd->font.buffer_size < buffer_size) | 453 | if (pd->font.buffer_size < bufsize) |
505 | { | 454 | { |
506 | int old_refcount, old_id; | 455 | int old_refcount, old_id; |
456 | size_t old_bufsize = pd->font.buffer_size; | ||
457 | bool failed = false; | ||
507 | /* reload the font: | 458 | /* reload the font: |
508 | * 1) save of refcont and id | 459 | * 1) save of refcont and id |
509 | * 2) force unload (set refcount to 1 to make sure it get unloaded) | 460 | * 2) force unload (set refcount to 1 to make sure it get unloaded) |
@@ -514,11 +465,14 @@ int font_load_ex(const char *path, size_t buffer_size) | |||
514 | old_refcount = pd->refcount; | 465 | old_refcount = pd->refcount; |
515 | pd->refcount = 1; | 466 | pd->refcount = 1; |
516 | font_unload(font_id); | 467 | font_unload(font_id); |
517 | font_id = font_load_ex(path, buffer_size); | 468 | font_id = font_load_ex(path, bufsize, glyphs); |
518 | if (font_id < 0) | 469 | if (font_id < 0) |
519 | { | 470 | { |
520 | // not much we can do here, maybe try reloading with the small buffer again | 471 | failed = true; |
521 | return -1; | 472 | font_id = font_load_ex(path, old_bufsize, 0); |
473 | /* we couldn't even get the old size, this shouldn't happen */ | ||
474 | if ( font_id < 0 ) | ||
475 | return -1; | ||
522 | } | 476 | } |
523 | if (old_id != font_id) | 477 | if (old_id != font_id) |
524 | { | 478 | { |
@@ -528,51 +482,100 @@ int font_load_ex(const char *path, size_t buffer_size) | |||
528 | } | 482 | } |
529 | pd = core_get_data(buflib_allocations[font_id]); | 483 | pd = core_get_data(buflib_allocations[font_id]); |
530 | pd->refcount = old_refcount; | 484 | pd->refcount = old_refcount; |
485 | if(failed) | ||
486 | /* return error because we didn't satisfy the new buffer size */ | ||
487 | return -1; | ||
531 | } | 488 | } |
532 | pd->refcount++; | 489 | pd->refcount++; |
533 | //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount); | 490 | //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount); |
491 | close(fd); | ||
534 | return font_id; | 492 | return font_id; |
535 | } | 493 | } |
536 | 494 | ||
495 | int open_slot = -1; | ||
496 | |||
537 | for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++) | 497 | for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++) |
538 | { | 498 | { |
539 | handle = buflib_allocations[font_id]; | 499 | if (buflib_allocations[ font_id ] < 0) |
540 | if (handle < 0) | ||
541 | { | 500 | { |
501 | open_slot = font_id; | ||
542 | break; | 502 | break; |
543 | } | 503 | } |
544 | } | 504 | } |
545 | handle = alloc_and_init(font_id, path, buffer_size); | 505 | if ( open_slot == -1 ) |
546 | if (handle < 0) | ||
547 | return -1; | 506 | return -1; |
507 | font_id = open_slot; | ||
548 | 508 | ||
549 | buffer = buffer_from_handle(handle); | 509 | /* allocate mem */ |
550 | lock_font_handle(handle, true); | 510 | int handle = core_alloc_ex( path, |
551 | 511 | bufsize + sizeof( struct buflib_alloc_data ), | |
552 | if (!internal_load_font(font_id, path, buffer, buffer_size, handle)) | 512 | &buflibops ); |
513 | if ( handle < 0 ) | ||
553 | { | 514 | { |
554 | lock_font_handle(handle, false); | ||
555 | core_free(handle); | ||
556 | buflib_allocations[font_id] = -1; | ||
557 | return -1; | 515 | return -1; |
558 | } | 516 | } |
559 | 517 | struct buflib_alloc_data *pdata; | |
560 | lock_font_handle(handle, false); | 518 | pdata = core_get_data(handle); |
519 | pdata->handle_locks = 1; | ||
520 | pdata->refcount = 1; | ||
521 | |||
522 | /* load and init */ | ||
523 | struct font *pf = pf_from_handle( handle ); | ||
524 | memcpy(pf, &f, sizeof( struct font) ); | ||
525 | |||
526 | pf->fd = fd; | ||
527 | pf->fd_width = pf->fd_offset = -1; | ||
528 | pf->handle = handle; | ||
529 | |||
530 | pf->buffer_start = buffer_from_handle( pf->handle ); | ||
531 | pf->buffer_position = pf->buffer_start + FONT_HEADER_SIZE; | ||
532 | pf->buffer_size = bufsize; | ||
533 | pf->buffer_end = pf->buffer_start + bufsize; | ||
534 | |||
535 | if ( cached ) | ||
536 | { | ||
537 | if ( ! font_load_cached( pf, nwidth, noffset ) ) | ||
538 | { | ||
539 | core_free( handle ); | ||
540 | return -1; | ||
541 | } | ||
542 | |||
543 | /* trick to get a small cache for each file section * | ||
544 | * during glyph_cache_load() */ | ||
545 | pf->fd_width = open( path, O_RDONLY|O_BINARY ); | ||
546 | pf->fd_offset = open( path, O_RDONLY|O_BINARY ); | ||
547 | |||
548 | glyph_cache_load( path, pf ); | ||
549 | |||
550 | /* cached font: pf->fd stays open until the font is unloaded */ | ||
551 | close( pf->fd_width ); | ||
552 | pf->fd_width = -1; | ||
553 | close( pf->fd_offset ); | ||
554 | pf->fd_offset = -1; | ||
555 | } | ||
556 | else | ||
557 | { | ||
558 | lseek( fd, 0, SEEK_SET); | ||
559 | read(fd, pf->buffer_start, pf->buffer_size); | ||
560 | |||
561 | close( fd ); | ||
562 | pf->fd = -1; | ||
563 | |||
564 | if ( ! font_load_in_memory( pf, nwidth, noffset ) ) | ||
565 | { | ||
566 | core_free( handle ); | ||
567 | return -1; | ||
568 | } | ||
569 | } | ||
561 | buflib_allocations[font_id] = handle; | 570 | buflib_allocations[font_id] = handle; |
562 | //printf("%s -> [%d] -> %d\n", path, font_id, *handle); | 571 | //printf("%s -> [%d] -> %d\n", path, font_id, *handle); |
572 | lock_font_handle( handle, false ); | ||
563 | return font_id; /* success!*/ | 573 | return font_id; /* success!*/ |
564 | } | 574 | } |
575 | |||
565 | int font_load(const char *path) | 576 | int font_load(const char *path) |
566 | { | 577 | { |
567 | int size; | 578 | return font_load_ex(path, MAX_FONT_SIZE, GLYPHS_TO_CACHE); |
568 | int fd = open( path, O_RDONLY ); | ||
569 | if ( fd < 0 ) | ||
570 | return -1; | ||
571 | size = filesize(fd); | ||
572 | if (size > MAX_FONT_SIZE) | ||
573 | size = MAX_FONT_SIZE; | ||
574 | close(fd); | ||
575 | return font_load_ex(path, size); | ||
576 | } | 579 | } |
577 | 580 | ||
578 | void font_unload(int font_id) | 581 | void font_unload(int font_id) |
@@ -640,22 +643,6 @@ struct font* font_get(int font) | |||
640 | } | 643 | } |
641 | } | 644 | } |
642 | 645 | ||
643 | static int pf_to_handle(struct font* pf) | ||
644 | { | ||
645 | int i; | ||
646 | for (i=0; i<MAXFONTS; i++) | ||
647 | { | ||
648 | int handle = buflib_allocations[i]; | ||
649 | if (handle > 0) | ||
650 | { | ||
651 | struct buflib_alloc_data *pdata = core_get_data(handle); | ||
652 | if (pf == &pdata->font) | ||
653 | return handle; | ||
654 | } | ||
655 | } | ||
656 | return -1; | ||
657 | } | ||
658 | |||
659 | /* | 646 | /* |
660 | * Reads an entry into cache entry | 647 | * Reads an entry into cache entry |
661 | */ | 648 | */ |
@@ -663,13 +650,12 @@ static void | |||
663 | load_cache_entry(struct font_cache_entry* p, void* callback_data) | 650 | load_cache_entry(struct font_cache_entry* p, void* callback_data) |
664 | { | 651 | { |
665 | struct font* pf = callback_data; | 652 | struct font* pf = callback_data; |
666 | int handle = pf_to_handle(pf); | 653 | |
667 | unsigned short char_code = p->_char_code; | 654 | unsigned short char_code = p->_char_code; |
668 | unsigned char tmp[2]; | 655 | unsigned char tmp[2]; |
669 | int fd; | 656 | int fd; |
670 | 657 | ||
671 | if (handle > 0) | 658 | lock_font_handle(pf->handle, true); |
672 | lock_font_handle(handle, true); | ||
673 | if (pf->file_width_offset) | 659 | if (pf->file_width_offset) |
674 | { | 660 | { |
675 | int width_offset = pf->file_width_offset + char_code; | 661 | int width_offset = pf->file_width_offset + char_code; |
@@ -714,8 +700,7 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) | |||
714 | int src_bytes = glyph_bytes(pf, p->width); | 700 | int src_bytes = glyph_bytes(pf, p->width); |
715 | read(pf->fd, p->bitmap, src_bytes); | 701 | read(pf->fd, p->bitmap, src_bytes); |
716 | 702 | ||
717 | if (handle > 0) | 703 | lock_font_handle(pf->handle, false); |
718 | lock_font_handle(handle, false); | ||
719 | } | 704 | } |
720 | 705 | ||
721 | /* | 706 | /* |
@@ -756,7 +741,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) | |||
756 | 741 | ||
757 | if (pf->fd >= 0 && pf != &sysfont) | 742 | if (pf->fd >= 0 && pf != &sysfont) |
758 | { | 743 | { |
759 | bits = | 744 | bits = |
760 | (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap; | 745 | (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap; |
761 | } | 746 | } |
762 | else | 747 | else |
@@ -850,49 +835,13 @@ void glyph_cache_save(int font_id) | |||
850 | return; | 835 | return; |
851 | } | 836 | } |
852 | 837 | ||
853 | int font_glyphs_to_bufsize(const char *path, int glyphs) | ||
854 | { | ||
855 | struct font f; | ||
856 | int bufsize; | ||
857 | char buf[FONT_HEADER_SIZE]; | ||
858 | |||
859 | f.buffer_start = buf; | ||
860 | f.buffer_size = sizeof(buf); | ||
861 | f.buffer_position = buf; | ||
862 | |||
863 | f.fd = open(path, O_RDONLY|O_BINARY); | ||
864 | if(f.fd < 0) | ||
865 | return 0; | ||
866 | |||
867 | read(f.fd, f.buffer_position, FONT_HEADER_SIZE); | ||
868 | f.buffer_end = f.buffer_position + FONT_HEADER_SIZE; | ||
869 | |||
870 | if( !font_load_header(&f) ) | ||
871 | { | ||
872 | close(f.fd); | ||
873 | return 0; | ||
874 | } | ||
875 | close(f.fd); | ||
876 | |||
877 | bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + | ||
878 | sizeof( unsigned short); | ||
879 | bufsize += glyph_bytes(&f, f.maxwidth); | ||
880 | bufsize *= glyphs; | ||
881 | if ( bufsize < FONT_HEADER_SIZE ) | ||
882 | bufsize = FONT_HEADER_SIZE; | ||
883 | return bufsize; | ||
884 | } | ||
885 | 838 | ||
886 | static int ushortcmp(const void *a, const void *b) | 839 | static int ushortcmp(const void *a, const void *b) |
887 | { | 840 | { |
888 | return ((int)(*(unsigned short*)a - *(unsigned short*)b)); | 841 | return ((int)(*(unsigned short*)a - *(unsigned short*)b)); |
889 | } | 842 | } |
890 | static void glyph_cache_load(int font_id) | 843 | static void glyph_cache_load(const char *font_path, struct font *pf) |
891 | { | 844 | { |
892 | int handle = buflib_allocations[font_id]; | ||
893 | if (handle < 0) | ||
894 | return; | ||
895 | struct font *pf = pf_from_handle(handle); | ||
896 | #define MAX_SORT 256 | 845 | #define MAX_SORT 256 |
897 | if (pf->fd >= 0) { | 846 | if (pf->fd >= 0) { |
898 | int i, size, fd; | 847 | int i, size, fd; |
@@ -907,7 +856,7 @@ static void glyph_cache_load(int font_id) | |||
907 | sort_size = MAX_SORT; | 856 | sort_size = MAX_SORT; |
908 | 857 | ||
909 | char filename[MAX_PATH]; | 858 | char filename[MAX_PATH]; |
910 | font_path_to_glyph_path(font_filename(font_id), filename); | 859 | font_path_to_glyph_path(font_path, filename); |
911 | 860 | ||
912 | fd = open(filename, O_RDONLY|O_BINARY); | 861 | fd = open(filename, O_RDONLY|O_BINARY); |
913 | #ifdef TRY_DEFAULT_GLYPHCACHE | 862 | #ifdef TRY_DEFAULT_GLYPHCACHE |
diff --git a/manual/advanced_topics/main.tex b/manual/advanced_topics/main.tex index 17e72cd51a..3503e5851d 100644 --- a/manual/advanced_topics/main.tex +++ b/manual/advanced_topics/main.tex | |||
@@ -342,7 +342,8 @@ and the WPS, but you can use multiple fonts in each of the individual screens.\\ | |||
342 | \item `filename' is the font filename to load. Fonts should be stored in | 342 | \item `filename' is the font filename to load. Fonts should be stored in |
343 | \fname{/.rockbox/fonts/} | 343 | \fname{/.rockbox/fonts/} |
344 | \item `glyphs' is an optional specification of how many unique glyphs to | 344 | \item `glyphs' is an optional specification of how many unique glyphs to |
345 | store in memory. Default is 256. | 345 | store in memory. Default is from the system setting |
346 | \setting{Glyphs To Load}. | ||
346 | \end{itemize} | 347 | \end{itemize} |
347 | 348 | ||
348 | An example would be: \config{\%Fl(2,12-Nimbus.fnt,100)} | 349 | An example would be: \config{\%Fl(2,12-Nimbus.fnt,100)} |
diff --git a/manual/configure_rockbox/system_options.tex b/manual/configure_rockbox/system_options.tex index 41b487164d..b61c55a5f2 100644 --- a/manual/configure_rockbox/system_options.tex +++ b/manual/configure_rockbox/system_options.tex | |||
@@ -136,9 +136,15 @@ This sub menu relates to limits in the Rockbox operating system. | |||
136 | in steps of 1,000 (default is 10,000). Higher values will shorten the | 136 | in steps of 1,000 (default is 10,000). Higher values will shorten the |
137 | music buffer, so you should increase this setting \emph{only} if you | 137 | music buffer, so you should increase this setting \emph{only} if you |
138 | have very large playlists. | 138 | have very large playlists. |
139 | |||
140 | \item [Glyphs To Cache.] This sets the default memory allocation size | ||
141 | for fonts in unique glyphs. This should be set to the number of unique | ||
142 | language glyphs and punctuation marks that are frequently displayed. | ||
143 | The default is 250. | ||
139 | \end{description} | 144 | \end{description} |
140 | \note{You will need to restart your player for changes to these options | 145 | \note{You will need to restart your player for changes to \setting{Max |
141 | to take effect.} | 146 | Entries in File Browser} or \setting{Max Playlist Size} to take effect |
147 | while \setting{Glyphs To Cache} will affect the next font load.} | ||
142 | % TODO: this needs to be rewritten in another style, it lets you mix sound from another source into the music | 148 | % TODO: this needs to be rewritten in another style, it lets you mix sound from another source into the music |
143 | \opt{player}{ | 149 | \opt{player}{ |
144 | \subsection{Line In} This option activates the line-in port on \dap, which is | 150 | \subsection{Line In} This option activates the line-in port on \dap, which is |
diff --git a/tools/convbdf.c b/tools/convbdf.c index 4ae358e833..4cc7ec9983 100644 --- a/tools/convbdf.c +++ b/tools/convbdf.c | |||
@@ -1413,6 +1413,7 @@ int gen_c_source(struct font* pf, char *path) | |||
1413 | fprintf(ofp, " -1, /* font fd */\n" | 1413 | fprintf(ofp, " -1, /* font fd */\n" |
1414 | " -1, /* font fd width */\n" | 1414 | " -1, /* font fd width */\n" |
1415 | " -1, /* font fd offset */\n" | 1415 | " -1, /* font fd offset */\n" |
1416 | " -1, /* font handle */\n" | ||
1416 | " 0, /* buffer start */\n" | 1417 | " 0, /* buffer start */\n" |
1417 | " 0, /* ^ position */\n" | 1418 | " 0, /* ^ position */\n" |
1418 | " 0, /* ^ end */\n" | 1419 | " 0, /* ^ end */\n" |