Manual: Small English improvement
[maemo-rb.git] / firmware / font.c
blob0546061a15be02915b85e40612aafc3089a4c81c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2002 by Greg Haerr <greg@censoft.com>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 * Rockbox startup font initialization
23 * This file specifies which fonts get compiled-in and
24 * loaded at startup, as well as their mapping into
25 * the FONT_SYSFIXED, FONT_UI and FONT_MP3 ids.
27 #include "config.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include "inttypes.h"
33 #include "lcd.h"
34 #include "system.h"
35 #include "font.h"
36 #include "file.h"
37 #include "core_alloc.h"
38 #include "debug.h"
39 #include "panic.h"
40 #include "rbunicode.h"
41 #include "diacritic.h"
42 #include "rbpaths.h"
44 #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB
46 /* max static loadable font buffer size */
47 #ifndef MAX_FONT_SIZE
48 #if LCD_HEIGHT > 64
49 #if MEMORYSIZE > 2
50 #define MAX_FONT_SIZE 60000
51 #else
52 #define MAX_FONT_SIZE 10000
53 #endif
54 #else
55 #define MAX_FONT_SIZE 4000
56 #endif
57 #endif
59 #ifndef FONT_HEADER_SIZE
60 #define FONT_HEADER_SIZE 36
61 #endif
63 #ifndef BOOTLOADER
64 /* Font cache includes */
65 #include "font_cache.h"
66 #include "lru.h"
67 #endif
69 #ifndef O_BINARY
70 #define O_BINARY 0
71 #endif
73 /* compiled-in font */
74 extern struct font sysfont;
76 #ifndef BOOTLOADER
78 struct buflib_alloc_data {
79 struct font font;
80 bool handle_locked; /* is the buflib handle currently locked? */
81 int refcount; /* how many times has this font been loaded? */
82 unsigned char buffer[];
84 static int buflib_allocations[MAXFONTS];
85 static int handle_for_glyphcache;
87 static int buflibmove_callback(int handle, void* current, void* new)
89 (void)handle;
90 struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current;
91 size_t diff = new - current;
93 if (alloc->handle_locked)
94 return BUFLIB_CB_CANNOT_MOVE;
96 if (alloc->font.bits)
97 alloc->font.bits += diff;
98 if (alloc->font.offset)
99 alloc->font.offset += diff;
100 if (alloc->font.width)
101 alloc->font.width += diff;
103 alloc->font.buffer_start += diff;
104 alloc->font.buffer_end += diff;
105 alloc->font.buffer_position += diff;
107 if (alloc->font.cache._index)
108 alloc->font.cache._index += diff;
109 if (alloc->font.cache._lru._base)
110 alloc->font.cache._lru._base += diff;
112 return BUFLIB_CB_OK;
114 static void lock_font_handle(int handle, bool lock)
116 struct buflib_alloc_data *alloc = core_get_data(handle);
117 alloc->handle_locked = lock;
120 static struct buflib_callbacks buflibops = {buflibmove_callback, NULL };
122 static inline struct font *pf_from_handle(int handle)
124 struct buflib_alloc_data *alloc = core_get_data(handle);
125 struct font *pf = &alloc->font;
126 return pf;
129 static inline unsigned char *buffer_from_handle(int handle)
131 struct buflib_alloc_data *alloc = core_get_data(handle);
132 unsigned char* buffer = alloc->buffer;
133 return buffer;
136 /* Font cache structures */
137 static void cache_create(struct font* pf);
138 static void glyph_cache_load(struct font* pf);
139 /* End Font cache structures */
141 void font_init(void)
143 int i = 0;
144 while (i<MAXFONTS)
145 buflib_allocations[i++] = -1;
146 handle_for_glyphcache = -1;
149 /* Check if we have x bytes left in the file buffer */
150 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
152 /* Helper functions to read big-endian unaligned short or long from
153 the file buffer. Bounds-checking must be done in the calling
154 function.
157 static short readshort(struct font *pf)
159 unsigned short s;
161 s = *pf->buffer_position++ & 0xff;
162 s |= (*pf->buffer_position++ << 8);
163 return s;
166 static int32_t readlong(struct font *pf)
168 uint32_t l;
170 l = *pf->buffer_position++ & 0xff;
171 l |= *pf->buffer_position++ << 8;
172 l |= ((uint32_t)(*pf->buffer_position++)) << 16;
173 l |= ((uint32_t)(*pf->buffer_position++)) << 24;
174 return l;
177 static int glyph_bytes( struct font *pf, int width )
179 int ret;
180 if (pf->depth)
181 ret = ( pf->height * width + 1 ) / 2;
182 else
183 ret = width * ((pf->height + 7) / 8);
184 return (ret + 1) & ~1;
187 static struct font* font_load_header(struct font *pf)
189 /* Check we have enough data */
190 if (!HAVEBYTES(28))
191 return NULL;
193 /* read magic and version #*/
194 if (memcmp(pf->buffer_position, VERSION, 4) != 0)
195 return NULL;
197 pf->buffer_position += 4;
199 /* font info*/
200 pf->maxwidth = readshort(pf);
201 pf->height = readshort(pf);
202 pf->ascent = readshort(pf);
203 pf->depth = readshort(pf);
204 pf->firstchar = readlong(pf);
205 pf->defaultchar = readlong(pf);
206 pf->size = readlong(pf);
208 /* get variable font data sizes*/
209 /* # words of bitmap_t*/
210 pf->bits_size = readlong(pf);
212 return pf;
214 /* Load memory font */
215 static struct font* font_load_in_memory(struct font* pf)
217 int32_t i, noffset, nwidth;
219 if (!HAVEBYTES(4))
220 return NULL;
222 /* # longs of offset*/
223 noffset = readlong(pf);
225 /* # bytes of width*/
226 nwidth = readlong(pf);
228 /* variable font data*/
229 pf->bits = (unsigned char *)pf->buffer_position;
230 pf->buffer_position += pf->bits_size*sizeof(unsigned char);
232 if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
234 /* pad to 16-bit boundary */
235 pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1);
237 else
239 /* pad to 32-bit boundary*/
240 pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3);
243 if (noffset)
245 if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
247 pf->long_offset = 0;
248 pf->offset = (uint16_t*)pf->buffer_position;
250 /* Check we have sufficient buffer */
251 if (!HAVEBYTES(noffset * sizeof(uint16_t)))
252 return NULL;
254 for (i=0; i<noffset; ++i)
256 ((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(pf);
259 else
261 pf->long_offset = 1;
262 pf->offset = (uint16_t*)pf->buffer_position;
264 /* Check we have sufficient buffer */
265 if (!HAVEBYTES(noffset * sizeof(int32_t)))
266 return NULL;
268 for (i=0; i<noffset; ++i)
270 ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(pf);
274 else
275 pf->offset = NULL;
277 if (nwidth) {
278 pf->width = (unsigned char *)pf->buffer_position;
279 pf->buffer_position += nwidth*sizeof(unsigned char);
281 else
282 pf->width = NULL;
284 if (pf->buffer_position > pf->buffer_end)
285 return NULL;
287 return pf; /* success!*/
290 /* Load cached font */
291 static struct font* font_load_cached(struct font* pf)
293 uint32_t noffset, nwidth;
294 unsigned char* oldfileptr = pf->buffer_position;
296 if (!HAVEBYTES(2 * sizeof(int32_t)))
297 return NULL;
299 /* # longs of offset*/
300 noffset = readlong(pf);
302 /* # bytes of width*/
303 nwidth = readlong(pf);
305 /* We are now at the bitmap data, this is fixed at 36.. */
306 pf->bits = NULL;
308 /* Calculate offset to offset data */
309 pf->buffer_position += pf->bits_size * sizeof(unsigned char);
311 if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
313 pf->long_offset = 0;
314 /* pad to 16-bit boundary */
315 pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1);
317 else
319 pf->long_offset = 1;
320 /* pad to 32-bit boundary*/
321 pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3);
324 if (noffset)
325 pf->file_offset_offset = (uint32_t)(pf->buffer_position - pf->buffer_start);
326 else
327 pf->file_offset_offset = 0;
329 /* Calculate offset to widths data */
330 if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
331 pf->buffer_position += noffset * sizeof(uint16_t);
332 else
333 pf->buffer_position += noffset * sizeof(uint32_t);
335 if (nwidth)
336 pf->file_width_offset = (uint32_t)(pf->buffer_position - pf->buffer_start);
337 else
338 pf->file_width_offset = 0;
340 pf->buffer_position = oldfileptr;
342 /* Create the cache */
343 cache_create(pf);
345 return pf;
348 static void font_reset(int font_id)
350 struct font *pf = pf_from_handle(buflib_allocations[font_id]);
351 // fixme
352 memset(pf, 0, sizeof(struct font));
353 pf->fd = -1;
357 static bool internal_load_font(int font_id, const char *path,
358 char *buf, size_t buf_size)
360 size_t size;
361 struct font* pf = pf_from_handle(buflib_allocations[font_id]);
362 /* save loaded glyphs */
363 glyph_cache_save(pf);
364 /* Close font file handle */
365 if (pf->fd >= 0)
366 close(pf->fd);
368 font_reset(font_id);
370 /* open and read entire font file*/
371 pf->fd = open(path, O_RDONLY|O_BINARY);
373 if (pf->fd < 0) {
374 DEBUGF("Can't open font: %s\n", path);
375 return false;
378 /* Check file size */
379 size = filesize(pf->fd);
380 pf->buffer_start = buf;
381 pf->buffer_size = buf_size;
383 pf->buffer_position = buf;
385 if (size > pf->buffer_size)
387 read(pf->fd, pf->buffer_position, FONT_HEADER_SIZE);
388 pf->buffer_end = pf->buffer_position + FONT_HEADER_SIZE;
390 if (!font_load_header(pf))
392 DEBUGF("Failed font header load");
393 close(pf->fd);
394 pf->fd = -1;
395 return false;
398 if (!font_load_cached(pf))
400 DEBUGF("Failed font cache load");
401 close(pf->fd);
402 pf->fd = -1;
403 return false;
406 glyph_cache_load(pf);
408 else
410 read(pf->fd, pf->buffer_position, pf->buffer_size);
411 pf->buffer_end = pf->buffer_position + size;
412 close(pf->fd);
413 pf->fd = -1;
415 if (!font_load_header(pf))
417 DEBUGF("Failed font header load");
418 return false;
421 if (!font_load_in_memory(pf))
423 DEBUGF("Failed mem load");
424 return false;
427 return true;
430 static int find_font_index(const char* path)
432 int index = 0, handle;
434 while (index < MAXFONTS)
436 handle = buflib_allocations[index];
437 if (handle > 0 && !strcmp(core_get_name(handle), path))
438 return index;
439 index++;
441 return FONT_SYSFIXED;
444 static int alloc_and_init(int font_idx, const char* name, size_t size)
446 int *phandle = &buflib_allocations[font_idx];
447 int handle = *phandle;
448 struct buflib_alloc_data *pdata;
449 struct font *pf;
450 size_t alloc_size = size + sizeof(struct buflib_alloc_data);
451 if (handle > 0)
452 return handle;
453 *phandle = core_alloc_ex(name, alloc_size, &buflibops);
454 handle = *phandle;
455 if (handle < 0)
456 return handle;
457 pdata = core_get_data(handle);
458 pf = &pdata->font;
459 font_reset(font_idx);
460 pdata->handle_locked = false;
461 pdata->refcount = 1;
462 pf->buffer_position = pf->buffer_start = buffer_from_handle(handle);
463 pf->buffer_size = size;
464 return handle;
467 const char* font_filename(int font_id)
469 int handle = buflib_allocations[font_id];
470 if (handle > 0)
471 return core_get_name(handle);
472 return NULL;
475 /* read and load font into incore font structure,
476 * returns the font number on success, -1 on failure */
477 int font_load_ex(const char *path, size_t buffer_size)
479 int font_id = find_font_index(path);
480 char *buffer;
481 int *handle;
483 if (font_id > FONT_SYSFIXED)
485 /* already loaded, no need to reload */
486 struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]);
487 if (pd->font.buffer_size < buffer_size)
489 int old_refcount, old_id;
490 /* reload the font:
491 * 1) save of refcont and id
492 * 2) force unload (set refcount to 1 to make sure it get unloaded)
493 * 3) reload with the larger buffer
494 * 4) restore the id and refcount
496 old_id = font_id;
497 old_refcount = pd->refcount;
498 pd->refcount = 1;
499 font_unload(font_id);
500 font_id = font_load_ex(path, buffer_size);
501 if (font_id < 0)
503 // not much we can do here, maybe try reloading with the small buffer again
504 return -1;
506 if (old_id != font_id)
508 buflib_allocations[old_id] = buflib_allocations[font_id];
509 buflib_allocations[font_id] = -1;
510 font_id = old_id;
512 pd = core_get_data(buflib_allocations[font_id]);
513 pd->refcount = old_refcount;
515 pd->refcount++;
516 //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount);
517 return font_id;
520 for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++)
522 handle = &buflib_allocations[font_id];
523 if (*handle < 0)
525 break;
528 handle = &buflib_allocations[font_id];
529 *handle = alloc_and_init(font_id, path, buffer_size);
530 if (*handle < 0)
531 return -1;
533 if (handle_for_glyphcache < 0)
534 handle_for_glyphcache = *handle;
536 buffer = buffer_from_handle(*handle);
537 lock_font_handle(*handle, true);
539 if (!internal_load_font(font_id, path, buffer, buffer_size))
541 lock_font_handle(*handle, false);
542 core_free(*handle);
543 *handle = -1;
544 return -1;
547 lock_font_handle(*handle, false);
548 //printf("%s -> [%d] -> %d\n", path, font_id, *handle);
549 return font_id; /* success!*/
551 int font_load(const char *path)
553 int size;
554 int fd = open( path, O_RDONLY );
555 if ( fd < 0 )
556 return -1;
557 size = filesize(fd);
558 if (size > MAX_FONT_SIZE)
559 size = MAX_FONT_SIZE;
560 close(fd);
561 return font_load_ex(path, size);
564 void font_unload(int font_id)
566 int *handle = &buflib_allocations[font_id];
567 struct buflib_alloc_data *pdata = core_get_data(*handle);
568 struct font* pf = &pdata->font;
569 pdata->refcount--;
570 if (pdata->refcount < 1)
572 //printf("freeing id: %d %s\n", font_id, core_get_name(*handle));
573 if (pf && pf->fd >= 0)
574 close(pf->fd);
575 if (*handle > 0)
576 core_free(*handle);
577 if (handle_for_glyphcache == *handle)
578 handle_for_glyphcache = -1; // should find the next available handle
579 *handle = -1;
584 * Return a pointer to an incore font structure.
585 * If the requested font isn't loaded/compiled-in,
586 * decrement the font number and try again.
588 struct font* font_get(int font)
590 struct font* pf;
591 if (font == FONT_UI)
592 font = MAXFONTS-1;
593 if (font <= FONT_SYSFIXED)
594 return &sysfont;
596 while (1) {
597 if (buflib_allocations[font] > 0)
599 struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[font]);
600 pf = &alloc->font;
601 if (pf && pf->height)
602 return pf;
604 if (--font < 0)
605 return &sysfont;
609 static int pf_to_handle(struct font* pf)
611 int i;
612 for (i=0; i<MAXFONTS; i++)
614 int handle = buflib_allocations[i];
615 if (handle > 0)
617 struct buflib_alloc_data *pdata = core_get_data(handle);
618 if (pf == &pdata->font)
619 return handle;
622 return -1;
626 * Reads an entry into cache entry
628 static void
629 load_cache_entry(struct font_cache_entry* p, void* callback_data)
631 struct font* pf = callback_data;
632 int handle = pf_to_handle(pf);
633 unsigned short char_code = p->_char_code;
634 unsigned char tmp[2];
636 if (handle > 0)
637 lock_font_handle(handle, true);
638 if (pf->file_width_offset)
640 int width_offset = pf->file_width_offset + char_code;
641 lseek(pf->fd, width_offset, SEEK_SET);
642 read(pf->fd, &(p->width), 1);
644 else
646 p->width = pf->maxwidth;
649 int32_t bitmap_offset = 0;
651 if (pf->file_offset_offset)
653 int32_t offset = pf->file_offset_offset + char_code * (pf->long_offset ? sizeof(int32_t) : sizeof(int16_t));
654 lseek(pf->fd, offset, SEEK_SET);
655 read (pf->fd, tmp, 2);
656 bitmap_offset = tmp[0] | (tmp[1] << 8);
657 if (pf->long_offset) {
658 read (pf->fd, tmp, 2);
659 bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24);
662 else
664 bitmap_offset = char_code * glyph_bytes(pf, p->width);
667 int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset;
668 lseek(pf->fd, file_offset, SEEK_SET);
669 int src_bytes = glyph_bytes(pf, p->width);
670 read(pf->fd, p->bitmap, src_bytes);
672 if (handle > 0)
673 lock_font_handle(handle, false);
677 * Converts cbuf into a font cache
679 static void cache_create(struct font* pf)
681 /* maximum size of rotated bitmap */
682 int bitmap_size = glyph_bytes( pf, pf->maxwidth);
684 /* Initialise cache */
685 font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size);
689 * Returns width of character
691 int font_get_width(struct font* pf, unsigned short char_code)
693 /* check input range*/
694 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
695 char_code = pf->defaultchar;
696 char_code -= pf->firstchar;
698 return (pf->fd >= 0 && pf != &sysfont)?
699 font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->width:
700 pf->width? pf->width[char_code]: pf->maxwidth;
703 const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
705 const unsigned char* bits;
707 /* check input range*/
708 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
709 char_code = pf->defaultchar;
710 char_code -= pf->firstchar;
712 if (pf->fd >= 0 && pf != &sysfont)
714 bits =
715 (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap;
717 else
719 bits = pf->bits;
720 if (pf->offset)
722 if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
723 bits += ((uint16_t*)(pf->offset))[char_code];
724 else
725 bits += ((uint32_t*)(pf->offset))[char_code];
727 else
728 bits += char_code * glyph_bytes(pf, pf->maxwidth);
731 return bits;
733 static int cache_fd;
734 static void glyph_file_write(void* data)
736 struct font_cache_entry* p = data;
737 int handle = handle_for_glyphcache;
738 struct font* pf = pf_from_handle(handle);
739 unsigned short ch;
740 unsigned char tmp[2];
742 if ( p->_char_code == 0xffff )
743 return;
745 ch = p->_char_code + pf->firstchar;
747 if ( cache_fd >= 0) {
748 tmp[0] = ch >> 8;
749 tmp[1] = ch & 0xff;
750 if (write(cache_fd, tmp, 2) != 2) {
751 close(cache_fd);
752 cache_fd = -1;
755 return;
758 /* save the char codes of the loaded glyphs to a file */
759 void glyph_cache_save(struct font* pf)
761 if (pf != pf_from_handle(handle_for_glyphcache))
762 return;
763 if (pf->fd >= 0)
765 cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
766 if (cache_fd < 0)
767 return;
769 lru_traverse(&pf->cache._lru, glyph_file_write);
771 if (cache_fd >= 0)
773 close(cache_fd);
774 cache_fd = -1;
777 return;
780 int font_glyphs_to_bufsize(const char *path, int glyphs)
782 struct font f;
783 int bufsize;
784 char buf[FONT_HEADER_SIZE];
786 f.buffer_start = buf;
787 f.buffer_size = sizeof(buf);
788 f.buffer_position = buf;
790 f.fd = open(path, O_RDONLY|O_BINARY);
791 if(f.fd < 0)
792 return 0;
794 read(f.fd, f.buffer_position, FONT_HEADER_SIZE);
795 f.buffer_end = f.buffer_position + FONT_HEADER_SIZE;
797 if( !font_load_header(&f) )
799 close(f.fd);
800 return 0;
802 close(f.fd);
804 bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) +
805 sizeof( unsigned short);
806 bufsize += glyph_bytes(&f, f.maxwidth);
807 bufsize *= glyphs;
808 if ( bufsize < FONT_HEADER_SIZE )
809 bufsize = FONT_HEADER_SIZE;
810 return bufsize;
813 static int ushortcmp(const void *a, const void *b)
815 return ((int)(*(unsigned short*)a - *(unsigned short*)b));
817 static void glyph_cache_load(struct font* pf)
819 if (handle_for_glyphcache <= 0)
820 return;
821 #define MAX_SORT 256
822 if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) {
823 int fd;
824 int i, size;
825 unsigned char tmp[2];
826 unsigned short ch;
827 unsigned short glyphs[MAX_SORT];
828 unsigned short glyphs_lru_order[MAX_SORT];
829 int glyph_file_skip=0, glyph_file_size=0;
831 int sort_size = pf->cache._capacity;
832 if ( sort_size > MAX_SORT )
833 sort_size = MAX_SORT;
835 fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY);
836 if (fd >= 0) {
838 /* only read what fits */
839 glyph_file_size = filesize( fd );
840 if ( glyph_file_size > 2*pf->cache._capacity ) {
841 glyph_file_skip = glyph_file_size - 2*pf->cache._capacity;
842 lseek( fd, glyph_file_skip, SEEK_SET );
845 while(1) {
847 for ( size = 0;
848 read( fd, tmp, 2 ) == 2 && size < sort_size;
849 size++ )
851 glyphs[size] = (tmp[0] << 8) | tmp[1];
852 glyphs_lru_order[size] = glyphs[size];
855 /* sort glyphs array to make sector cache happy */
856 qsort((void *)glyphs, size, sizeof(unsigned short),
857 ushortcmp );
859 /* load font bitmaps */
860 i = 0;
861 font_get_bits(pf, glyphs[i]);
862 for ( i = 1; i < size ; i++) {
863 if ( glyphs[i] != glyphs[i-1] )
864 font_get_bits(pf, glyphs[i]);
867 /* redo to fix lru order */
868 for ( i = 0; i < size ; i++)
869 font_get_bits(pf, glyphs_lru_order[i]);
871 if ( size < sort_size )
872 break;
875 close(fd);
876 } else {
877 /* load latin1 chars into cache */
878 for ( ch = 32 ; ch < 256 && ch < pf->cache._capacity + 32; ch++ )
879 font_get_bits(pf, ch);
882 return;
884 #else /* BOOTLOADER */
886 void font_init(void)
891 * Bootloader only supports the built-in sysfont.
893 struct font* font_get(int font)
895 (void)font;
896 return &sysfont;
900 * Returns width of character
902 int font_get_width(struct font* pf, unsigned short char_code)
904 /* check input range*/
905 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
906 char_code = pf->defaultchar;
907 char_code -= pf->firstchar;
909 return pf->width? pf->width[char_code]: pf->maxwidth;
912 const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
914 const unsigned char* bits;
916 /* check input range*/
917 if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size)
918 char_code = pf->defaultchar;
919 char_code -= pf->firstchar;
921 /* assume small font with uint16_t offsets*/
922 bits = pf->bits + (pf->offset?
923 ((uint16_t*)(pf->offset))[char_code]:
924 (((pf->height + 7) / 8) * pf->maxwidth * char_code));
926 return bits;
929 #endif /* BOOTLOADER */
932 * Returns the stringsize of a given string.
934 int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
936 struct font* pf = font_get(fontnumber);
937 unsigned short ch;
938 int width = 0;
940 for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch))
942 if (is_diacritic(ch, NULL))
943 continue;
945 /* get proportional width and glyph bits*/
946 width += font_get_width(pf,ch);
948 if ( w )
949 *w = width;
950 if ( h )
951 *h = pf->height;
952 return width;
955 /* -----------------------------------------------------------------
956 * vim: et sw=4 ts=8 sts=4 tw=78