diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/font.h | 35 | ||||
-rw-r--r-- | firmware/font.c | 369 | ||||
-rw-r--r-- | firmware/powermgmt.c | 2 |
3 files changed, 257 insertions, 149 deletions
diff --git a/firmware/export/font.h b/firmware/export/font.h index 0fe6c30f2c..e9bf086423 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -30,6 +30,7 @@ #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) #ifndef __PCTOOL__ +#include "font_cache.h" #include "sysfont.h" #endif @@ -47,9 +48,14 @@ enum { FONT_SYSFIXED, /* system fixed pitch font*/ FONT_UI, /* system porportional font*/ - MAXFONTS +#ifdef HAVE_REMOTE_LCD + FONT_UI_REMOTE, /* UI font for remote LCD */ +#endif + SYSTEMFONTCOUNT /* Number of fonts reserved for the system and ui */ }; +#define MAXFONTS 10 + /* * .fnt loadable font file format definition * @@ -89,17 +95,38 @@ struct font { const unsigned char *width; /* character widths or NULL if fixed*/ int defaultchar; /* default char (not glyph index)*/ int32_t bits_size; /* # bytes of glyph bits*/ + + /* file, buffer and cache management */ + int fd; /* fd for the font file. >= 0 if cached */ + unsigned char *buffer_start; /* buffer to store the font in */ + unsigned char *buffer_position; /* position in the buffer */ + unsigned char *buffer_end; /* end of the buffer */ + int buffer_size; /* size of the buffer in bytes */ +#ifndef __PCTOOL__ + struct font_cache cache; + uint32_t file_width_offset; /* offset to file width data */ + uint32_t file_offset_offset; /* offset to file offset data */ + int long_offset; +#endif + }; /* font routines*/ void font_init(void); -struct font* font_load(const char *path); +#ifdef HAVE_REMOTE_LCD +/* Load a font into the special remote ui font slot */ +int font_load_remoteui(const char* path); +#endif +int font_load(struct font* pf, const char *path); +void font_unload(int font_id); + struct font* font_get(int font); -void font_reset(void); + +void font_reset(struct font *pf); int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); int font_get_width(struct font* ft, unsigned short ch); const unsigned char * font_get_bits(struct font* ft, unsigned short ch); -void glyph_cache_save(void); +void glyph_cache_save(struct font* pf); #else /* HAVE_LCD_BITMAP */ diff --git a/firmware/font.c b/firmware/font.c index a8734e93a1..52c6ffae6a 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -75,64 +75,77 @@ extern struct font sysfont; /* structure filled in by font_load */ static struct font font_ui; +/* static buffer allocation structures */ +static unsigned char main_buf[MAX_FONT_SIZE]; +#ifdef HAVE_REMOTE_LCD +#define REMOTE_FONT_SIZE 10000 +static struct font remote_font_ui; +static unsigned char remote_buf[REMOTE_FONT_SIZE]; +#endif /* system font table, in order of FONT_xxx definition */ -static struct font* const sysfonts[MAXFONTS] = { &sysfont, &font_ui }; +static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL}; -/* static buffer allocation structures */ -static unsigned char mbuf[MAX_FONT_SIZE]; -static unsigned char *freeptr = mbuf; -static unsigned char *fileptr; -static unsigned char *eofptr; /* Font cache structures */ -static struct font_cache font_cache_ui; -static int fnt_file = -1; /* >=0 if font is cached */ -static uint32_t file_width_offset; /* offset to file width data */ -static uint32_t file_offset_offset; /* offset to file offset data */ -static void cache_create(int maxwidth, int height); -static int long_offset = 0; -static int glyph_file; +static void cache_create(struct font* pf, int maxwidth, int height); +static void glyph_cache_load(struct font* pf); /* End Font cache structures */ -static void glyph_cache_load(void); - void font_init(void) { - memset(&font_ui, 0, sizeof(struct font)); + int i = SYSTEMFONTCOUNT; + while (i<MAXFONTS) + sysfonts[i++] = NULL; + font_reset(NULL); } /* Check if we have x bytes left in the file buffer */ -#define HAVEBYTES(x) (fileptr + (x) <= eofptr) +#define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end) /* Helper functions to read big-endian unaligned short or long from the file buffer. Bounds-checking must be done in the calling function. */ -static short readshort(void) +static short readshort(struct font *pf) { unsigned short s; - s = *fileptr++ & 0xff; - s |= (*fileptr++ << 8); + s = *pf->buffer_position++ & 0xff; + s |= (*pf->buffer_position++ << 8); return s; } -static int32_t readlong(void) +static int32_t readlong(struct font *pf) { uint32_t l; - l = *fileptr++ & 0xff; - l |= *fileptr++ << 8; - l |= ((uint32_t)(*fileptr++)) << 16; - l |= ((uint32_t)(*fileptr++)) << 24; + l = *pf->buffer_position++ & 0xff; + l |= *pf->buffer_position++ << 8; + l |= ((uint32_t)(*pf->buffer_position++)) << 16; + l |= ((uint32_t)(*pf->buffer_position++)) << 24; return l; } -void font_reset(void) +void font_reset(struct font *pf) { - memset(&font_ui, 0, sizeof(struct font)); + unsigned char* buffer = NULL; + size_t buf_size = 0; + if (pf == NULL) + pf = &font_ui; + else + { + buffer = pf->buffer_start; + buf_size = pf->buffer_size; + } + memset(pf, 0, sizeof(struct font)); + pf->fd = -1; + if (buffer) + { + pf->buffer_start = buffer; + pf->buffer_size = buf_size; + } } static struct font* font_load_header(struct font *pf) @@ -142,23 +155,23 @@ static struct font* font_load_header(struct font *pf) return NULL; /* read magic and version #*/ - if (memcmp(fileptr, VERSION, 4) != 0) + if (memcmp(pf->buffer_position, VERSION, 4) != 0) return NULL; - fileptr += 4; + pf->buffer_position += 4; /* font info*/ - pf->maxwidth = readshort(); - pf->height = readshort(); - pf->ascent = readshort(); - fileptr += 2; /* Skip padding */ - pf->firstchar = readlong(); - pf->defaultchar = readlong(); - pf->size = readlong(); + pf->maxwidth = readshort(pf); + pf->height = readshort(pf); + pf->ascent = readshort(pf); + pf->buffer_position += 2; /* Skip padding */ + pf->firstchar = readlong(pf); + pf->defaultchar = readlong(pf); + pf->size = readlong(pf); /* get variable font data sizes*/ /* # words of bitmap_t*/ - pf->bits_size = readlong(); + pf->bits_size = readlong(pf); return pf; } @@ -171,32 +184,32 @@ static struct font* font_load_in_memory(struct font* pf) return NULL; /* # longs of offset*/ - noffset = readlong(); + noffset = readlong(pf); /* # bytes of width*/ - nwidth = readlong(); + nwidth = readlong(pf); /* variable font data*/ - pf->bits = (unsigned char *)fileptr; - fileptr += pf->bits_size*sizeof(unsigned char); + pf->bits = (unsigned char *)pf->buffer_position; + pf->buffer_position += pf->bits_size*sizeof(unsigned char); if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) { /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1); } else { /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3); } if (noffset) { if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) { - long_offset = 0; - pf->offset = (uint16_t*)fileptr; + pf->long_offset = 0; + pf->offset = (uint16_t*)pf->buffer_position; /* Check we have sufficient buffer */ if (!HAVEBYTES(noffset * sizeof(uint16_t))) @@ -204,13 +217,13 @@ static struct font* font_load_in_memory(struct font* pf) for (i=0; i<noffset; ++i) { - ((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(); + ((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(pf); } } else { - long_offset = 1; - pf->offset = (uint16_t*)fileptr; + pf->long_offset = 1; + pf->offset = (uint16_t*)pf->buffer_position; /* Check we have sufficient buffer */ if (!HAVEBYTES(noffset * sizeof(int32_t))) @@ -218,7 +231,7 @@ static struct font* font_load_in_memory(struct font* pf) for (i=0; i<noffset; ++i) { - ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(); + ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(pf); } } } @@ -226,13 +239,13 @@ static struct font* font_load_in_memory(struct font* pf) pf->offset = NULL; if (nwidth) { - pf->width = (unsigned char *)fileptr; - fileptr += nwidth*sizeof(unsigned char); + pf->width = (unsigned char *)pf->buffer_position; + pf->buffer_position += nwidth*sizeof(unsigned char); } else pf->width = NULL; - if (fileptr > eofptr) + if (pf->buffer_position > pf->buffer_end) return NULL; return pf; /* success!*/ @@ -242,135 +255,203 @@ static struct font* font_load_in_memory(struct font* pf) static struct font* font_load_cached(struct font* pf) { uint32_t noffset, nwidth; - unsigned char* oldfileptr = fileptr; + unsigned char* oldfileptr = pf->buffer_position; if (!HAVEBYTES(2 * sizeof(int32_t))) return NULL; /* # longs of offset*/ - noffset = readlong(); + noffset = readlong(pf); /* # bytes of width*/ - nwidth = readlong(); + nwidth = readlong(pf); /* We are now at the bitmap data, this is fixed at 36.. */ pf->bits = NULL; /* Calculate offset to offset data */ - fileptr += pf->bits_size * sizeof(unsigned char); + pf->buffer_position += pf->bits_size * sizeof(unsigned char); if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) { - long_offset = 0; + pf->long_offset = 0; /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1); } else { - long_offset = 1; + pf->long_offset = 1; /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3); } if (noffset) - file_offset_offset = (uint32_t)(fileptr - freeptr); + pf->file_offset_offset = (uint32_t)(pf->buffer_position - pf->buffer_start); else - file_offset_offset = 0; + pf->file_offset_offset = 0; /* Calculate offset to widths data */ if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) - fileptr += noffset * sizeof(uint16_t); + pf->buffer_position += noffset * sizeof(uint16_t); else - fileptr += noffset * sizeof(uint32_t); + pf->buffer_position += noffset * sizeof(uint32_t); if (nwidth) - file_width_offset = (uint32_t)(fileptr - freeptr); + pf->file_width_offset = (uint32_t)(pf->buffer_position - pf->buffer_start); else - file_width_offset = 0; + pf->file_width_offset = 0; - fileptr = oldfileptr; + pf->buffer_position = oldfileptr; /* Create the cache */ - cache_create(pf->maxwidth, pf->height); + cache_create(pf, pf->maxwidth, pf->height); return pf; } -/* read and load font into incore font structure*/ -struct font* font_load(const char *path) +static bool internal_load_font(struct font* pf, const char *path, + char *buf, size_t buf_size) { int size; - struct font* pf = &font_ui; - + /* save loaded glyphs */ - glyph_cache_save(); - + glyph_cache_save(pf); /* Close font file handle */ - if (fnt_file >= 0) - close(fnt_file); + if (pf->fd >= 0) + close(pf->fd); + + font_reset(pf); /* open and read entire font file*/ - fnt_file = open(path, O_RDONLY|O_BINARY); + pf->fd = open(path, O_RDONLY|O_BINARY); - if (fnt_file < 0) { + if (pf->fd < 0) { DEBUGF("Can't open font: %s\n", path); - return NULL; + return false; } /* Check file size */ - size = filesize(fnt_file); - - font_reset(); - - /* currently, font loading replaces earlier font allocation*/ - freeptr = (unsigned char *)(((intptr_t)mbuf + 3) & ~3); - fileptr = freeptr; - - - if (size > MAX_FONT_SIZE) + size = filesize(pf->fd); + pf->buffer_start = buf; + pf->buffer_size = buf_size; + + pf->buffer_position = buf; + + if (size > pf->buffer_size) { - read(fnt_file, fileptr, FONT_HEADER_SIZE); - eofptr = fileptr + FONT_HEADER_SIZE; + read(pf->fd, pf->buffer_position, FONT_HEADER_SIZE); + pf->buffer_end = pf->buffer_position + FONT_HEADER_SIZE; if (!font_load_header(pf)) { DEBUGF("Failed font header load"); - return NULL; + return false; } if (!font_load_cached(pf)) { DEBUGF("Failed font cache load"); - return NULL; + return false; } - glyph_cache_load(); + glyph_cache_load(pf); } else { - read(fnt_file, fileptr, MAX_FONT_SIZE); - eofptr = fileptr + size; - close(fnt_file); - fnt_file = -1; + read(pf->fd, pf->buffer_position, pf->buffer_size); + pf->buffer_end = pf->buffer_position + size; + close(pf->fd); + pf->fd = -1; if (!font_load_header(pf)) { DEBUGF("Failed font header load"); - return NULL; + return false; } if (!font_load_in_memory(pf)) { DEBUGF("Failed mem load"); - return NULL; + return false; } } + return true; +} + +#ifdef HAVE_REMOTE_LCD +/* Load a font into the special remote ui font slot */ +int font_load_remoteui(const char* path) +{ + struct font* pf = &remote_font_ui; + if (!path) + { + if (sysfonts[FONT_UI_REMOTE] && sysfonts[FONT_UI_REMOTE] != sysfonts[FONT_UI]) + font_unload(FONT_UI_REMOTE); + sysfonts[FONT_UI_REMOTE] = NULL; + return FONT_UI; + } + if (!internal_load_font(pf, path, remote_buf, REMOTE_FONT_SIZE)) + { + sysfonts[FONT_UI_REMOTE] = NULL; + return -1; + } + + sysfonts[FONT_UI_REMOTE] = pf; + return FONT_UI_REMOTE; +} +#endif - /* no need for multiple font loads currently*/ - /*freeptr += filesize;*/ - /*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/ +/* read and load font into incore font structure, + * returns the font number on success, -1 on failure */ +int font_load(struct font* pf, const char *path) +{ + int font_id = -1; + char *buffer; + size_t buffer_size; + if (pf == NULL) + { + pf = &font_ui; + font_id = FONT_UI; + } + else + { + for (font_id = SYSTEMFONTCOUNT; font_id < MAXFONTS; font_id++) + { + if (sysfonts[font_id] == NULL) + break; + } + if (font_id == MAXFONTS) + return -1; /* too many fonts */ + } + + if (font_id == FONT_UI) + { + /* currently, font loading replaces earlier font allocation*/ + buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3); + buffer_size = MAX_FONT_SIZE; + } + else + { + buffer = pf->buffer_start; + buffer_size = pf->buffer_size; + } + + if (!internal_load_font(pf, path, buffer, buffer_size)) + return -1; + + sysfonts[font_id] = pf; + return font_id; /* success!*/ +} - return pf; /* success!*/ +void font_unload(int font_id) +{ + struct font* pf = sysfonts[font_id]; + if (font_id >= SYSTEMFONTCOUNT && pf) + { + if (pf->fd >= 0) + close(pf->fd); + sysfonts[font_id] = NULL; + } } /* @@ -382,9 +463,6 @@ struct font* font_get(int font) { struct font* pf; - if (font >= MAXFONTS) - font = 0; - while (1) { pf = sysfonts[font]; if (pf && pf->height) @@ -404,11 +482,11 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) unsigned short char_code = p->_char_code; unsigned char tmp[2]; - if (file_width_offset) + if (pf->file_width_offset) { - int width_offset = file_width_offset + char_code; - lseek(fnt_file, width_offset, SEEK_SET); - read(fnt_file, &(p->width), 1); + int width_offset = pf->file_width_offset + char_code; + lseek(pf->fd, width_offset, SEEK_SET); + read(pf->fd, &(p->width), 1); } else { @@ -417,14 +495,14 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) int32_t bitmap_offset = 0; - if (file_offset_offset) + if (pf->file_offset_offset) { - int32_t offset = file_offset_offset + char_code * (long_offset ? sizeof(int32_t) : sizeof(int16_t)); - lseek(fnt_file, offset, SEEK_SET); - read (fnt_file, tmp, 2); + int32_t offset = pf->file_offset_offset + char_code * (pf->long_offset ? sizeof(int32_t) : sizeof(int16_t)); + lseek(pf->fd, offset, SEEK_SET); + read (pf->fd, tmp, 2); bitmap_offset = tmp[0] | (tmp[1] << 8); - if (long_offset) { - read (fnt_file, tmp, 2); + if (pf->long_offset) { + read (pf->fd, tmp, 2); bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); } } @@ -434,22 +512,22 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) } int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; - lseek(fnt_file, file_offset, SEEK_SET); + lseek(pf->fd, file_offset, SEEK_SET); int src_bytes = p->width * ((pf->height + 7) / 8); - read(fnt_file, p->bitmap, src_bytes); + read(pf->fd, p->bitmap, src_bytes); } /* * Converts cbuf into a font cache */ -static void cache_create(int maxwidth, int height) +static void cache_create(struct font* pf, int maxwidth, int height) { /* maximum size of rotated bitmap */ int bitmap_size = maxwidth * ((height + 7) / 8); /* Initialise cache */ - font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); + font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size); } /* @@ -462,8 +540,8 @@ int font_get_width(struct font* pf, unsigned short char_code) char_code = pf->defaultchar; char_code -= pf->firstchar; - return (fnt_file >= 0 && pf != &sysfont)? - font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->width: + return (pf->fd >= 0 && pf != &sysfont)? + font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->width: pf->width? pf->width[char_code]: pf->maxwidth; } @@ -476,10 +554,10 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) char_code = pf->defaultchar; char_code -= pf->firstchar; - if (fnt_file >= 0 && pf != &sysfont) + if (pf->fd >= 0 && pf != &sysfont) { bits = - (unsigned char*)font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->bitmap; + (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->bitmap; } else { @@ -497,7 +575,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) return bits; } - +static int cache_fd; static void glyph_file_write(void* data) { struct font_cache_entry* p = data; @@ -507,45 +585,48 @@ static void glyph_file_write(void* data) ch = p->_char_code + pf->firstchar; - if (ch != 0xffff && glyph_file >= 0) { + if (ch != 0xffff && cache_fd >= 0) { tmp[0] = ch >> 8; tmp[1] = ch & 0xff; - if (write(glyph_file, tmp, 2) != 2) { - close(glyph_file); - glyph_file = -1; + if (write(cache_fd, tmp, 2) != 2) { + close(cache_fd); + cache_fd = -1; } } return; } /* save the char codes of the loaded glyphs to a file */ -void glyph_cache_save(void) +void glyph_cache_save(struct font* pf) { - - if (fnt_file >= 0) { + if (!pf) + pf = &font_ui; + if (pf->fd >= 0 && pf == &font_ui) + { #ifdef WPSEDITOR - glyph_file = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC); + cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC); #else - glyph_file = creat(GLYPH_CACHE_FILE); + cache_fd = creat(GLYPH_CACHE_FILE); #endif - if (glyph_file < 0) return; + if (cache_fd < 0) return; - lru_traverse(&font_cache_ui._lru, glyph_file_write); - - if (glyph_file >= 0) - close(glyph_file); + lru_traverse(&pf->cache._lru, glyph_file_write); + + if (cache_fd < 0) + { + close(cache_fd); + cache_fd = -1; + } } return; } -static void glyph_cache_load(void) +static void glyph_cache_load(struct font* pf) { - if (fnt_file >= 0) { - + if (pf->fd >= 0) { int fd; unsigned char tmp[2]; unsigned short ch; - struct font* pf = &font_ui; fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 5f488810ac..3f2b3c0f85 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -744,7 +744,7 @@ void shutdown_hw(void) if (battery_level_safe()) { /* do not save on critical battery */ #ifdef HAVE_LCD_BITMAP - glyph_cache_save(); + glyph_cache_save(NULL); #endif /* Commit pending writes if needed. Even though we don't do write caching, |