summaryrefslogtreecommitdiff
path: root/firmware/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/font.c')
-rw-r--r--firmware/font.c286
1 files changed, 189 insertions, 97 deletions
diff --git a/firmware/font.c b/firmware/font.c
index 0f9f453ae2..fea210a3f1 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -34,6 +34,7 @@
34#include "system.h" 34#include "system.h"
35#include "font.h" 35#include "font.h"
36#include "file.h" 36#include "file.h"
37#include "core_alloc.h"
37#include "debug.h" 38#include "debug.h"
38#include "panic.h" 39#include "panic.h"
39#include "rbunicode.h" 40#include "rbunicode.h"
@@ -74,19 +75,58 @@ extern struct font sysfont;
74 75
75#ifndef BOOTLOADER 76#ifndef BOOTLOADER
76 77
77/* structure filled in by font_load */ 78struct buflib_alloc_data {
78static struct font font_ui; 79 struct font font;
79/* static buffer allocation structures */ 80 bool handle_locked; /* is the buflib handle currently locked? */
80static unsigned char main_buf[MAX_FONT_SIZE] CACHEALIGN_ATTR; 81 int refcount; /* how many times has this font been loaded? */
81#ifdef HAVE_REMOTE_LCD 82 unsigned char buffer[MAX_FONT_SIZE];
82#define REMOTE_FONT_SIZE 10000 83};
83static struct font remote_font_ui; 84static int buflib_allocations[MAXFONTS];
84static unsigned char remote_buf[REMOTE_FONT_SIZE] CACHEALIGN_ATTR; 85static int handle_for_glyphcache;
85#endif 86
87static int buflibmove_callback(int handle, void* current, void* new)
88{
89 (void)handle;
90 struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current;
91 size_t diff = new - current;
92
93 if (alloc->handle_locked)
94 return BUFLIB_CB_CANNOT_MOVE;
95
96 alloc->font.bits += diff;
97 alloc->font.offset += diff;
98 if (alloc->font.width)
99 alloc->font.width += diff;
100
101 alloc->font.buffer_start += diff;
102 alloc->font.buffer_end += diff;
103 alloc->font.buffer_position += diff;
104
105 alloc->font.cache._index += diff;
106
107 return BUFLIB_CB_OK;
108}
109static void lock_font_handle(int handle, bool lock)
110{
111 struct buflib_alloc_data *alloc = core_get_data(handle);
112 alloc->handle_locked = lock;
113}
86 114
87/* system font table, in order of FONT_xxx definition */ 115static struct buflib_callbacks buflibops = {buflibmove_callback, NULL };
88static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL};
89 116
117static inline struct font *pf_from_handle(int handle)
118{
119 struct buflib_alloc_data *alloc = core_get_data(handle);
120 struct font *pf = &alloc->font;
121 return pf;
122}
123
124static inline unsigned char *buffer_from_handle(int handle)
125{
126 struct buflib_alloc_data *alloc = core_get_data(handle);
127 unsigned char* buffer = alloc->buffer;
128 return buffer;
129}
90 130
91/* Font cache structures */ 131/* Font cache structures */
92static void cache_create(struct font* pf); 132static void cache_create(struct font* pf);
@@ -95,13 +135,10 @@ static void glyph_cache_load(struct font* pf);
95 135
96void font_init(void) 136void font_init(void)
97{ 137{
98 int i = SYSTEMFONTCOUNT; 138 int i = 0;
99 while (i<MAXFONTS) 139 while (i<MAXFONTS)
100 sysfonts[i++] = NULL; 140 buflib_allocations[i++] = -1;
101 font_reset(NULL); 141 handle_for_glyphcache = -1;
102#ifdef HAVE_REMOTE_LCD
103 font_reset(&remote_font_ui);
104#endif
105} 142}
106 143
107/* Check if we have x bytes left in the file buffer */ 144/* Check if we have x bytes left in the file buffer */
@@ -139,26 +176,6 @@ static int glyph_bytes( struct font *pf, int width )
139 width * ((pf->height + 7) / 8); 176 width * ((pf->height + 7) / 8);
140} 177}
141 178
142void font_reset(struct font *pf)
143{
144 unsigned char* buffer = NULL;
145 size_t buf_size = 0;
146 if (pf == NULL)
147 pf = &font_ui;
148 else
149 {
150 buffer = pf->buffer_start;
151 buf_size = pf->buffer_size;
152 }
153 memset(pf, 0, sizeof(struct font));
154 pf->fd = -1;
155 if (buffer)
156 {
157 pf->buffer_start = buffer;
158 pf->buffer_size = buf_size;
159 }
160}
161
162static struct font* font_load_header(struct font *pf) 179static struct font* font_load_header(struct font *pf)
163{ 180{
164 /* Check we have enough data */ 181 /* Check we have enough data */
@@ -320,18 +337,27 @@ static struct font* font_load_cached(struct font* pf)
320 return pf; 337 return pf;
321} 338}
322 339
323static bool internal_load_font(struct font* pf, const char *path, 340static void font_reset(int font_id)
341{
342 struct font *pf = pf_from_handle(buflib_allocations[font_id]);
343 // fixme
344 memset(pf, 0, sizeof(struct font));
345 pf->fd = -1;
346}
347
348
349static bool internal_load_font(int font_id, const char *path,
324 char *buf, size_t buf_size) 350 char *buf, size_t buf_size)
325{ 351{
326 int size; 352 int size;
327 353 struct font* pf = pf_from_handle(buflib_allocations[font_id]);
328 /* save loaded glyphs */ 354 /* save loaded glyphs */
329 glyph_cache_save(pf); 355 glyph_cache_save(pf);
330 /* Close font file handle */ 356 /* Close font file handle */
331 if (pf->fd >= 0) 357 if (pf->fd >= 0)
332 close(pf->fd); 358 close(pf->fd);
333 359
334 font_reset(pf); 360 font_reset(font_id);
335 361
336 /* open and read entire font file*/ 362 /* open and read entire font file*/
337 pf->fd = open(path, O_RDONLY|O_BINARY); 363 pf->fd = open(path, O_RDONLY|O_BINARY);
@@ -393,80 +419,117 @@ static bool internal_load_font(struct font* pf, const char *path,
393 return true; 419 return true;
394} 420}
395 421
396#ifdef HAVE_REMOTE_LCD 422static int find_font_index(const char* path)
397/* Load a font into the special remote ui font slot */
398int font_load_remoteui(const char* path)
399{ 423{
400 struct font* pf = &remote_font_ui; 424 int index = 0, handle;
401 if (!path) 425
402 { 426 while (index < MAXFONTS)
403 if (sysfonts[FONT_UI_REMOTE] && sysfonts[FONT_UI_REMOTE] != sysfonts[FONT_UI])
404 font_unload(FONT_UI_REMOTE);
405 sysfonts[FONT_UI_REMOTE] = NULL;
406 return FONT_UI;
407 }
408 if (!internal_load_font(pf, path, remote_buf, REMOTE_FONT_SIZE))
409 { 427 {
410 sysfonts[FONT_UI_REMOTE] = NULL; 428 handle = buflib_allocations[index];
411 return -1; 429 if (handle > 0 && !strcmp(core_get_name(handle), path))
430 return index;
431 index++;
412 } 432 }
413 433 return FONT_SYSFIXED;
414 sysfonts[FONT_UI_REMOTE] = pf;
415 return FONT_UI_REMOTE;
416} 434}
417#endif
418 435
436static int alloc_and_init(int font_idx, const char* name)
437{
438 int *phandle = &buflib_allocations[font_idx];
439 int handle = *phandle;
440 struct buflib_alloc_data *pdata;
441 struct font *pf;
442 if (handle > 0)
443 return handle;
444 *phandle = core_alloc_ex(name, sizeof(struct buflib_alloc_data), &buflibops);
445 handle = *phandle;
446 if (handle < 0)
447 return handle;
448 pdata = core_get_data(handle);
449 pf = &pdata->font;
450 font_reset(font_idx);
451 pdata->handle_locked = false;
452 pdata->refcount = 1;
453 pf->buffer_position = pf->buffer_start = buffer_from_handle(handle);
454 pf->buffer_size = MAX_FONT_SIZE;
455 return handle;
456}
457
458const char* font_filename(int font_id)
459{
460 int handle = buflib_allocations[font_id];
461 if (handle > 0)
462 return core_get_name(handle);
463 return NULL;
464}
465
419/* read and load font into incore font structure, 466/* read and load font into incore font structure,
420 * returns the font number on success, -1 on failure */ 467 * returns the font number on success, -1 on failure */
421int font_load(struct font* pf, const char *path) 468int font_load(const char *path)
422{ 469{
423 int font_id = -1; 470 int font_id = find_font_index(path);
424 char *buffer; 471 char *buffer;
425 size_t buffer_size; 472 size_t buffer_size;
426 if (pf == NULL) 473 int *handle;
474
475 if (font_id > FONT_SYSFIXED)
427 { 476 {
428 pf = &font_ui; 477 /* already loaded, no need to reload */
429 font_id = FONT_UI; 478 struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]);
479 pd->refcount++;
480 //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount);
481 return font_id;
430 } 482 }
431 else 483
484 for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++)
432 { 485 {
433 for (font_id = SYSTEMFONTCOUNT; font_id < MAXFONTS; font_id++) 486 handle = &buflib_allocations[font_id];
487 if (*handle < 0)
434 { 488 {
435 if (sysfonts[font_id] == NULL) 489 break;
436 break;
437 } 490 }
438 if (font_id == MAXFONTS)
439 return -1; /* too many fonts */
440 } 491 }
441 492 handle = &buflib_allocations[font_id];
442 if (font_id == FONT_UI) 493 *handle = alloc_and_init(font_id, path);
443 { 494 if (*handle < 0)
444 /* currently, font loading replaces earlier font allocation*/ 495 return -1;
445 buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3); 496
446 /* make sure above doesn't exceed */ 497 if (handle_for_glyphcache < 0)
447 buffer_size = MAX_FONT_SIZE-3; 498 handle_for_glyphcache = *handle;
448 } 499
449 else 500 buffer = buffer_from_handle(*handle);
501 buffer_size = MAX_FONT_SIZE; //FIXME
502 lock_font_handle(*handle, true);
503
504 if (!internal_load_font(font_id, path, buffer, buffer_size))
450 { 505 {
451 buffer = pf->buffer_start; 506 lock_font_handle(*handle, false);
452 buffer_size = pf->buffer_size; 507 core_free(*handle);
453 } 508 *handle = -1;
454
455 if (!internal_load_font(pf, path, buffer, buffer_size))
456 return -1; 509 return -1;
510 }
457 511
458 sysfonts[font_id] = pf; 512 lock_font_handle(*handle, false);
513 //printf("%s -> [%d] -> %d\n", path, font_id, *handle);
459 return font_id; /* success!*/ 514 return font_id; /* success!*/
460} 515}
461 516
462void font_unload(int font_id) 517void font_unload(int font_id)
463{ 518{
464 struct font* pf = sysfonts[font_id]; 519 int *handle = &buflib_allocations[font_id];
465 if (font_id >= SYSTEMFONTCOUNT && pf) 520 struct buflib_alloc_data *pdata = core_get_data(*handle);
521 struct font* pf = &pdata->font;
522 pdata->refcount--;
523 if (pdata->refcount < 1)
466 { 524 {
467 if (pf->fd >= 0) 525 //printf("freeing id: %d %s\n", font_id, core_get_name(*handle));
526 if (pf && pf->fd >= 0)
468 close(pf->fd); 527 close(pf->fd);
469 sysfonts[font_id] = NULL; 528 if (*handle > 0)
529 core_free(*handle);
530 if (handle_for_glyphcache == *handle)
531 handle_for_glyphcache = -1; // should find the next available handle
532 *handle = -1;
470 } 533 }
471} 534}
472 535
@@ -478,14 +541,35 @@ void font_unload(int font_id)
478struct font* font_get(int font) 541struct font* font_get(int font)
479{ 542{
480 struct font* pf; 543 struct font* pf;
544 if (font == FONT_UI)
545 font = MAXFONTS-1;
546 if (font <= FONT_SYSFIXED)
547 return &sysfont;
481 548
482 while (1) { 549 while (1) {
483 pf = sysfonts[font]; 550 struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[font]);
551 pf = &alloc->font;
484 if (pf && pf->height) 552 if (pf && pf->height)
485 return pf; 553 return pf;
486 if (--font < 0) 554 if (--font < 0)
487 panicf("No font!"); 555 return &sysfont;
556 }
557}
558
559static int pf_to_handle(struct font* pf)
560{
561 int i;
562 for (i=0; i<MAXFONTS; i++)
563 {
564 int handle = buflib_allocations[i];
565 if (handle > 0)
566 {
567 struct buflib_alloc_data *pdata = core_get_data(handle);
568 if (pf == &pdata->font)
569 return handle;
570 }
488 } 571 }
572 return -1;
489} 573}
490 574
491/* 575/*
@@ -495,9 +579,12 @@ static void
495load_cache_entry(struct font_cache_entry* p, void* callback_data) 579load_cache_entry(struct font_cache_entry* p, void* callback_data)
496{ 580{
497 struct font* pf = callback_data; 581 struct font* pf = callback_data;
582 int handle = pf_to_handle(pf);
498 unsigned short char_code = p->_char_code; 583 unsigned short char_code = p->_char_code;
499 unsigned char tmp[2]; 584 unsigned char tmp[2];
500 585
586 if (handle > 0)
587 lock_font_handle(handle, true);
501 if (pf->file_width_offset) 588 if (pf->file_width_offset)
502 { 589 {
503 int width_offset = pf->file_width_offset + char_code; 590 int width_offset = pf->file_width_offset + char_code;
@@ -531,6 +618,9 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data)
531 lseek(pf->fd, file_offset, SEEK_SET); 618 lseek(pf->fd, file_offset, SEEK_SET);
532 int src_bytes = glyph_bytes(pf, p->width); 619 int src_bytes = glyph_bytes(pf, p->width);
533 read(pf->fd, p->bitmap, src_bytes); 620 read(pf->fd, p->bitmap, src_bytes);
621
622 if (handle > 0)
623 lock_font_handle(handle, false);
534} 624}
535 625
536/* 626/*
@@ -572,7 +662,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
572 if (pf->fd >= 0 && pf != &sysfont) 662 if (pf->fd >= 0 && pf != &sysfont)
573 { 663 {
574 bits = 664 bits =
575 (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->bitmap; 665 (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap;
576 } 666 }
577 else 667 else
578 { 668 {
@@ -594,7 +684,8 @@ static int cache_fd;
594static void glyph_file_write(void* data) 684static void glyph_file_write(void* data)
595{ 685{
596 struct font_cache_entry* p = data; 686 struct font_cache_entry* p = data;
597 struct font* pf = &font_ui; 687 int handle = handle_for_glyphcache;
688 struct font* pf = pf_from_handle(handle);
598 unsigned short ch; 689 unsigned short ch;
599 unsigned char tmp[2]; 690 unsigned char tmp[2];
600 691
@@ -617,9 +708,9 @@ static void glyph_file_write(void* data)
617/* save the char codes of the loaded glyphs to a file */ 708/* save the char codes of the loaded glyphs to a file */
618void glyph_cache_save(struct font* pf) 709void glyph_cache_save(struct font* pf)
619{ 710{
620 if (!pf) 711 if (pf != pf_from_handle(handle_for_glyphcache))
621 pf = &font_ui; 712 return;
622 if (pf->fd >= 0 && pf == &font_ui) 713 if (pf->fd >= 0)
623 { 714 {
624 cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); 715 cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
625 if (cache_fd < 0) 716 if (cache_fd < 0)
@@ -675,9 +766,10 @@ static int ushortcmp(const void *a, const void *b)
675} 766}
676static void glyph_cache_load(struct font* pf) 767static void glyph_cache_load(struct font* pf)
677{ 768{
678 769 if (handle_for_glyphcache <= 0)
770 return;
679#define MAX_SORT 256 771#define MAX_SORT 256
680 if (pf->fd >= 0) { 772 if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) {
681 int fd; 773 int fd;
682 int i, size; 774 int i, size;
683 unsigned char tmp[2]; 775 unsigned char tmp[2];