summaryrefslogtreecommitdiffstats
path: root/firmware/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/font.c')
-rw-r--r--firmware/font.c369
1 files changed, 225 insertions, 144 deletions
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);