summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-01-15 13:37:40 +0100
committerThomas Martitz <kugel@rockbox.org>2014-01-15 23:37:39 +0100
commitc23ce62829d98c2dc78f1fd8a8810cefd0f10402 (patch)
treec96a73b513350dabc3d33df2df376d86daa6cac9
parent84c7d6133bf8a43688f1ac56d774fb94b1d3eed5 (diff)
downloadrockbox-c23ce62829d98c2dc78f1fd8a8810cefd0f10402.tar.gz
rockbox-c23ce62829d98c2dc78f1fd8a8810cefd0f10402.zip
fonts: Do not unload completely on USB.
The font engine can now perform cache lookups even if the font file is closed, if the font was disabled with the new font_disable_all() function. It is highly probable that the lookup succeeds but in the cache-miss case a blank, full-width glyph will be returned. Change-Id: I3c97e747d2a0ba30c7b495c6118c9f029d265b56
-rw-r--r--firmware/export/font.h7
-rw-r--r--firmware/font.c116
-rw-r--r--firmware/font_cache.c3
-rw-r--r--firmware/include/font_cache.h10
4 files changed, 123 insertions, 13 deletions
diff --git a/firmware/export/font.h b/firmware/export/font.h
index ed003f220a..d19e0b87ad 100644
--- a/firmware/export/font.h
+++ b/firmware/export/font.h
@@ -125,6 +125,13 @@ void font_unload(int font_id);
125void font_unload_all(void); 125void font_unload_all(void);
126void font_lock(int font_id, bool lock); 126void font_lock(int font_id, bool lock);
127 127
128/* Closes the file descriptor if the font file (if cached) but keeps
129 * the cache intact, so font_get_{bits,width} still work. */
130void font_disable_all(void);
131/* Re-opens the file descriptor of the font file. Should be called as
132 * counter-part of font_disable_all(); */
133void font_enable_all(void);
134
128struct font* font_get(int font); 135struct font* font_get(int font);
129 136
130int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); 137int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
diff --git a/firmware/font.c b/firmware/font.c
index e7a574f0dd..723c972e3b 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -88,9 +88,10 @@ extern struct font sysfont;
88#ifndef BOOTLOADER 88#ifndef BOOTLOADER
89 89
90struct buflib_alloc_data { 90struct buflib_alloc_data {
91 struct font font; 91 struct font font; /* must be the first member! */
92 int handle_locks; /* is the buflib handle currently locked? */ 92 int handle_locks; /* is the buflib handle currently locked? */
93 int refcount; /* how many times has this font been loaded? */ 93 int refcount; /* how many times has this font been loaded? */
94 int disabled; /* font disabled (use fallback glyphs, from sysfont) */
94 unsigned char buffer[]; 95 unsigned char buffer[];
95}; 96};
96static int buflib_allocations[MAXFONTS]; 97static int buflib_allocations[MAXFONTS];
@@ -285,6 +286,7 @@ static struct font* font_load_cached(struct font* pf,
285 int32_t noffset) 286 int32_t noffset)
286{ 287{
287 /* We are now at the bitmap data, this is fixed at 36.. */ 288 /* We are now at the bitmap data, this is fixed at 36.. */
289 pf->width = NULL;
288 pf->bits = NULL; 290 pf->bits = NULL;
289 291
290 /* Calculate offset to offset data */ 292 /* Calculate offset to offset data */
@@ -412,11 +414,10 @@ int font_load_ex( const char *path, size_t buf_size, int glyphs )
412 /* load font struct f with file header */ 414 /* load font struct f with file header */
413 int file_size = filesize( fd ); 415 int file_size = filesize( fd );
414 struct font header; 416 struct font header;
415 struct font *pheader = &header;
416 struct font f; 417 struct font f;
417 418
418 uint32_t nwidth, noffset; 419 uint32_t nwidth, noffset;
419 if ( !font_load_header( fd, pheader, &f, &nwidth, &noffset ) 420 if ( !font_load_header( fd, &header, &f, &nwidth, &noffset )
420#if LCD_DEPTH < 16 421#if LCD_DEPTH < 16
421 || f.depth 422 || f.depth
422#endif 423#endif
@@ -470,6 +471,7 @@ int font_load_ex( const char *path, size_t buf_size, int glyphs )
470 old_id = font_id; 471 old_id = font_id;
471 old_refcount = pd->refcount; 472 old_refcount = pd->refcount;
472 pd->refcount = 1; 473 pd->refcount = 1;
474 pd->disabled = false;
473 font_unload(font_id); 475 font_unload(font_id);
474 font_id = font_load_ex(path, bufsize, glyphs); 476 font_id = font_load_ex(path, bufsize, glyphs);
475 if (font_id < 0) 477 if (font_id < 0)
@@ -623,6 +625,58 @@ void font_unload_all(void)
623 } 625 }
624} 626}
625 627
628static void font_disable(int font_id)
629{
630 if ( font_id < 0 || font_id >= MAXFONTS )
631 return;
632 int handle = buflib_allocations[font_id];
633 if ( handle < 0 )
634 return;
635 struct buflib_alloc_data *pdata = core_get_data(handle);
636 struct font *pf = &pdata->font;
637
638 if (pf->fd >= 0)
639 {
640 /* save the cache, but it keep it in-RAM so that cache lookups
641 * can still succeed on the same font */
642 glyph_cache_save(font_id);
643 close(pf->fd);
644 pf->fd = -1;
645 pdata->disabled = true;
646 }
647}
648
649void font_disable_all(void)
650{
651 for(int i = 0; i < MAXFONTS; i++)
652 font_disable(i);
653}
654
655static void font_enable(int font_id)
656{
657 if ( font_id < 0 || font_id >= MAXFONTS )
658 return;
659 int handle = buflib_allocations[font_id];
660 if ( handle < 0 )
661 return;
662 struct buflib_alloc_data *pdata = core_get_data(handle);
663 struct font *pf = &pdata->font;
664
665 if (pdata->disabled && pf->fd < 0)
666 {
667 const char *filename = font_filename(font_id);
668 pf->fd = open(filename, O_RDONLY);
669 pdata->disabled = false;
670 }
671}
672
673void font_enable_all(void)
674{
675 for(int i = 0; i < MAXFONTS; i++)
676 font_enable(i);
677}
678
679
626/* 680/*
627 * Return a pointer to an incore font structure. 681 * Return a pointer to an incore font structure.
628 * If the requested font isn't loaded/compiled-in, 682 * If the requested font isn't loaded/compiled-in,
@@ -715,10 +769,15 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data)
715static void cache_create(struct font* pf) 769static void cache_create(struct font* pf)
716{ 770{
717 /* maximum size of rotated bitmap */ 771 /* maximum size of rotated bitmap */
718 int bitmap_size = glyph_bytes( pf, pf->maxwidth); 772 int bitmap_size = glyph_bytes(pf, pf->maxwidth);
719 773 /* reserve one blank glyph that is guaranteed to be available, even
774 * when the font file is closed during USB */
775 unsigned char *cache_buf = pf->buffer_start + bitmap_size;
776 size_t cache_size = pf->buffer_size - (cache_buf - pf->buffer_start);
777 ALIGN_BUFFER(cache_buf, cache_size, 2);
778 memset(pf->buffer_start, 0, bitmap_size);
720 /* Initialise cache */ 779 /* Initialise cache */
721 font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size); 780 font_cache_create(&pf->cache, cache_buf, cache_size, bitmap_size);
722} 781}
723 782
724/* 783/*
@@ -726,32 +785,65 @@ static void cache_create(struct font* pf)
726 */ 785 */
727int font_get_width(struct font* pf, unsigned short char_code) 786int font_get_width(struct font* pf, unsigned short char_code)
728{ 787{
788 int width;
789 struct font_cache_entry *e;
790 struct buflib_alloc_data *data = (struct buflib_alloc_data *) pf;
791 bool cache_only = data->disabled;
792
729 /* check input range*/ 793 /* check input range*/
730 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) 794 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
731 char_code = pf->defaultchar; 795 char_code = pf->defaultchar;
732 char_code -= pf->firstchar; 796 char_code -= pf->firstchar;
733 797
734 return (pf->fd >= 0 && pf != &sysfont)? 798 if ((pf->fd >= 0 || cache_only) && pf != &sysfont
735 font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->width: 799 && (e = font_cache_get(&pf->cache,char_code,cache_only,load_cache_entry,pf)))
736 pf->width? pf->width[char_code]: pf->maxwidth; 800 width = e->width;
801 else if (pf->width)
802 width = pf->width[char_code];
803 else
804 width = pf->maxwidth;
805
806 return width;
737} 807}
738 808
739const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) 809const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
740{ 810{
741 const unsigned char* bits; 811 const unsigned char* bits;
812 struct buflib_alloc_data *data;
742 813
743 /* check input range*/ 814 /* check input range*/
744 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) 815 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
745 char_code = pf->defaultchar; 816 char_code = pf->defaultchar;
746 char_code -= pf->firstchar; 817 char_code -= pf->firstchar;
747 818
819 data = (struct buflib_alloc_data *) pf;
820
748 if (pf->fd >= 0 && pf != &sysfont) 821 if (pf->fd >= 0 && pf != &sysfont)
749 { 822 {
750 bits = 823 bits =
751 (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap; 824 (unsigned char*)font_cache_get(&pf->cache, char_code,
825 false, load_cache_entry, data)->bitmap;
826 }
827 else if (data->disabled)
828 {
829 /* the font handle is closed, but the cache is intact. Attempt
830 * a lookup, which is very likely to succeed. Return a placeholder
831 * glyph on miss (again, this is very unlikely */
832 struct font_cache_entry *e = font_cache_get(&pf->cache, char_code,
833 true, NULL, NULL);
834 if (LIKELY(e))
835 bits = (unsigned char *) e->bitmap;
836 else
837 {
838 /* Could attempt to find a suitable fallback glyph from the same
839 * font. For now just return blank space which is
840 * reserved by cache_create() at buffer_start */
841 bits = pf->buffer_start;
842 }
752 } 843 }
753 else 844 else
754 { 845 {
846 /* This font is entirely in RAM */
755 bits = pf->bits; 847 bits = pf->bits;
756 if (pf->offset) 848 if (pf->offset)
757 { 849 {
diff --git a/firmware/font_cache.c b/firmware/font_cache.c
index 4604d1524e..0b03edaf76 100644
--- a/firmware/font_cache.c
+++ b/firmware/font_cache.c
@@ -125,6 +125,7 @@ static int search(struct font_cache* fcache,
125struct font_cache_entry* font_cache_get( 125struct font_cache_entry* font_cache_get(
126 struct font_cache* fcache, 126 struct font_cache* fcache,
127 unsigned short char_code, 127 unsigned short char_code,
128 bool cache_only,
128 void (*callback) (struct font_cache_entry* p, void *callback_data), 129 void (*callback) (struct font_cache_entry* p, void *callback_data),
129 void *callback_data) 130 void *callback_data)
130{ 131{
@@ -166,6 +167,8 @@ struct font_cache_entry* font_cache_get(
166 } 167 }
167 168
168 /* not found */ 169 /* not found */
170 if (cache_only)
171 return NULL;
169 172
170 /* find index to replace */ 173 /* find index to replace */
171 short lru_handle_to_replace = fcache->_lru._head; 174 short lru_handle_to_replace = fcache->_lru._head;
diff --git a/firmware/include/font_cache.h b/firmware/include/font_cache.h
index a4c959e336..1809720ed5 100644
--- a/firmware/include/font_cache.h
+++ b/firmware/include/font_cache.h
@@ -17,8 +17,10 @@
17 * KIND, either express or implied. 17 * KIND, either express or implied.
18 * 18 *
19 ****************************************************************************/ 19 ****************************************************************************/
20
20#ifndef _FONT_CACHE_H_ 21#ifndef _FONT_CACHE_H_
21#define _FONT_CACHE_H_ 22#define _FONT_CACHE_H_
23#include <stdbool.h>
22#include "lru.h" 24#include "lru.h"
23 25
24/******************************************************************************* 26/*******************************************************************************
@@ -45,10 +47,16 @@ struct font_cache_entry
45/* Create an auto sized font cache from buf */ 47/* Create an auto sized font cache from buf */
46void font_cache_create( 48void font_cache_create(
47 struct font_cache* fcache, void* buf, int buf_size, int bitmap_bytes_size); 49 struct font_cache* fcache, void* buf, int buf_size, int bitmap_bytes_size);
48/* Get font cache entry */ 50
51/* Get font cache entry for the given char_code
52 *
53 * cache_only: true if only a cache lookup should be performed and loading on miss should be avoided
54 *
55 * Note: With cache_only this can return NULL, which otherwise never happens */
49struct font_cache_entry* font_cache_get( 56struct font_cache_entry* font_cache_get(
50 struct font_cache* fcache, 57 struct font_cache* fcache,
51 unsigned short char_code, 58 unsigned short char_code,
59 bool cache_only,
52 void (*callback) (struct font_cache_entry* p, void *callback_data), 60 void (*callback) (struct font_cache_entry* p, void *callback_data),
53 void *callback_data); 61 void *callback_data);
54 62