1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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.
37 #include "rbunicode.h"
38 #include "diacritic.h"
40 #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB
42 /* max static loadable font buffer size */
46 #define MAX_FONT_SIZE 60000
48 #define MAX_FONT_SIZE 10000
51 #define MAX_FONT_SIZE 4000
55 #ifndef FONT_HEADER_SIZE
56 #define FONT_HEADER_SIZE 36
59 #define GLYPH_CACHE_FILE ROCKBOX_DIR"/.glyphcache"
62 /* Font cache includes */
63 #include "font_cache.h"
71 /* compiled-in font */
72 extern struct font sysfont
;
76 /* structure filled in by font_load */
77 static struct font font_ui
;
78 /* static buffer allocation structures */
79 static unsigned char main_buf
[MAX_FONT_SIZE
];
80 #ifdef HAVE_REMOTE_LCD
81 #define REMOTE_FONT_SIZE 10000
82 static struct font remote_font_ui
;
83 static unsigned char remote_buf
[REMOTE_FONT_SIZE
];
86 /* system font table, in order of FONT_xxx definition */
87 static struct font
* sysfonts
[MAXFONTS
] = { &sysfont
, &font_ui
, NULL
};
90 /* Font cache structures */
91 static void cache_create(struct font
* pf
, int maxwidth
, int height
);
92 static void glyph_cache_load(struct font
* pf
);
93 /* End Font cache structures */
97 int i
= SYSTEMFONTCOUNT
;
101 #ifdef HAVE_REMOTE_LCD
102 font_reset(&remote_font_ui
);
106 /* Check if we have x bytes left in the file buffer */
107 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
109 /* Helper functions to read big-endian unaligned short or long from
110 the file buffer. Bounds-checking must be done in the calling
114 static short readshort(struct font
*pf
)
118 s
= *pf
->buffer_position
++ & 0xff;
119 s
|= (*pf
->buffer_position
++ << 8);
123 static int32_t readlong(struct font
*pf
)
127 l
= *pf
->buffer_position
++ & 0xff;
128 l
|= *pf
->buffer_position
++ << 8;
129 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 16;
130 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 24;
134 void font_reset(struct font
*pf
)
136 unsigned char* buffer
= NULL
;
142 buffer
= pf
->buffer_start
;
143 buf_size
= pf
->buffer_size
;
145 memset(pf
, 0, sizeof(struct font
));
149 pf
->buffer_start
= buffer
;
150 pf
->buffer_size
= buf_size
;
154 static struct font
* font_load_header(struct font
*pf
)
156 /* Check we have enough data */
160 /* read magic and version #*/
161 if (memcmp(pf
->buffer_position
, VERSION
, 4) != 0)
164 pf
->buffer_position
+= 4;
167 pf
->maxwidth
= readshort(pf
);
168 pf
->height
= readshort(pf
);
169 pf
->ascent
= readshort(pf
);
170 pf
->buffer_position
+= 2; /* Skip padding */
171 pf
->firstchar
= readlong(pf
);
172 pf
->defaultchar
= readlong(pf
);
173 pf
->size
= readlong(pf
);
175 /* get variable font data sizes*/
176 /* # words of bitmap_t*/
177 pf
->bits_size
= readlong(pf
);
181 /* Load memory font */
182 static struct font
* font_load_in_memory(struct font
* pf
)
184 int32_t i
, noffset
, nwidth
;
189 /* # longs of offset*/
190 noffset
= readlong(pf
);
192 /* # bytes of width*/
193 nwidth
= readlong(pf
);
195 /* variable font data*/
196 pf
->bits
= (unsigned char *)pf
->buffer_position
;
197 pf
->buffer_position
+= pf
->bits_size
*sizeof(unsigned char);
199 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
201 /* pad to 16-bit boundary */
202 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
206 /* pad to 32-bit boundary*/
207 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
212 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
215 pf
->offset
= (uint16_t*)pf
->buffer_position
;
217 /* Check we have sufficient buffer */
218 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
221 for (i
=0; i
<noffset
; ++i
)
223 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort(pf
);
229 pf
->offset
= (uint16_t*)pf
->buffer_position
;
231 /* Check we have sufficient buffer */
232 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
235 for (i
=0; i
<noffset
; ++i
)
237 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong(pf
);
245 pf
->width
= (unsigned char *)pf
->buffer_position
;
246 pf
->buffer_position
+= nwidth
*sizeof(unsigned char);
251 if (pf
->buffer_position
> pf
->buffer_end
)
254 return pf
; /* success!*/
257 /* Load cached font */
258 static struct font
* font_load_cached(struct font
* pf
)
260 uint32_t noffset
, nwidth
;
261 unsigned char* oldfileptr
= pf
->buffer_position
;
263 if (!HAVEBYTES(2 * sizeof(int32_t)))
266 /* # longs of offset*/
267 noffset
= readlong(pf
);
269 /* # bytes of width*/
270 nwidth
= readlong(pf
);
272 /* We are now at the bitmap data, this is fixed at 36.. */
275 /* Calculate offset to offset data */
276 pf
->buffer_position
+= pf
->bits_size
* sizeof(unsigned char);
278 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
281 /* pad to 16-bit boundary */
282 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
287 /* pad to 32-bit boundary*/
288 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
292 pf
->file_offset_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
294 pf
->file_offset_offset
= 0;
296 /* Calculate offset to widths data */
297 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
298 pf
->buffer_position
+= noffset
* sizeof(uint16_t);
300 pf
->buffer_position
+= noffset
* sizeof(uint32_t);
303 pf
->file_width_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
305 pf
->file_width_offset
= 0;
307 pf
->buffer_position
= oldfileptr
;
309 /* Create the cache */
310 cache_create(pf
, pf
->maxwidth
, pf
->height
);
315 static bool internal_load_font(struct font
* pf
, const char *path
,
316 char *buf
, size_t buf_size
)
320 /* save loaded glyphs */
321 glyph_cache_save(pf
);
322 /* Close font file handle */
328 /* open and read entire font file*/
329 pf
->fd
= open(path
, O_RDONLY
|O_BINARY
);
332 DEBUGF("Can't open font: %s\n", path
);
336 /* Check file size */
337 size
= filesize(pf
->fd
);
338 pf
->buffer_start
= buf
;
339 pf
->buffer_size
= buf_size
;
341 pf
->buffer_position
= buf
;
343 if (size
> pf
->buffer_size
)
345 read(pf
->fd
, pf
->buffer_position
, FONT_HEADER_SIZE
);
346 pf
->buffer_end
= pf
->buffer_position
+ FONT_HEADER_SIZE
;
348 if (!font_load_header(pf
))
350 DEBUGF("Failed font header load");
354 if (!font_load_cached(pf
))
356 DEBUGF("Failed font cache load");
360 glyph_cache_load(pf
);
364 read(pf
->fd
, pf
->buffer_position
, pf
->buffer_size
);
365 pf
->buffer_end
= pf
->buffer_position
+ size
;
369 if (!font_load_header(pf
))
371 DEBUGF("Failed font header load");
375 if (!font_load_in_memory(pf
))
377 DEBUGF("Failed mem load");
384 #ifdef HAVE_REMOTE_LCD
385 /* Load a font into the special remote ui font slot */
386 int font_load_remoteui(const char* path
)
388 struct font
* pf
= &remote_font_ui
;
391 if (sysfonts
[FONT_UI_REMOTE
] && sysfonts
[FONT_UI_REMOTE
] != sysfonts
[FONT_UI
])
392 font_unload(FONT_UI_REMOTE
);
393 sysfonts
[FONT_UI_REMOTE
] = NULL
;
396 if (!internal_load_font(pf
, path
, remote_buf
, REMOTE_FONT_SIZE
))
398 sysfonts
[FONT_UI_REMOTE
] = NULL
;
402 sysfonts
[FONT_UI_REMOTE
] = pf
;
403 return FONT_UI_REMOTE
;
407 /* read and load font into incore font structure,
408 * returns the font number on success, -1 on failure */
409 int font_load(struct font
* pf
, const char *path
)
421 for (font_id
= SYSTEMFONTCOUNT
; font_id
< MAXFONTS
; font_id
++)
423 if (sysfonts
[font_id
] == NULL
)
426 if (font_id
== MAXFONTS
)
427 return -1; /* too many fonts */
430 if (font_id
== FONT_UI
)
432 /* currently, font loading replaces earlier font allocation*/
433 buffer
= (unsigned char *)(((intptr_t)main_buf
+ 3) & ~3);
434 buffer_size
= MAX_FONT_SIZE
;
438 buffer
= pf
->buffer_start
;
439 buffer_size
= pf
->buffer_size
;
442 if (!internal_load_font(pf
, path
, buffer
, buffer_size
))
445 sysfonts
[font_id
] = pf
;
446 return font_id
; /* success!*/
449 void font_unload(int font_id
)
451 struct font
* pf
= sysfonts
[font_id
];
452 if (font_id
>= SYSTEMFONTCOUNT
&& pf
)
456 sysfonts
[font_id
] = NULL
;
461 * Return a pointer to an incore font structure.
462 * If the requested font isn't loaded/compiled-in,
463 * decrement the font number and try again.
465 struct font
* font_get(int font
)
471 if (pf
&& pf
->height
)
479 * Reads an entry into cache entry
482 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
484 struct font
* pf
= callback_data
;
485 unsigned short char_code
= p
->_char_code
;
486 unsigned char tmp
[2];
488 if (pf
->file_width_offset
)
490 int width_offset
= pf
->file_width_offset
+ char_code
;
491 lseek(pf
->fd
, width_offset
, SEEK_SET
);
492 read(pf
->fd
, &(p
->width
), 1);
496 p
->width
= pf
->maxwidth
;
499 int32_t bitmap_offset
= 0;
501 if (pf
->file_offset_offset
)
503 int32_t offset
= pf
->file_offset_offset
+ char_code
* (pf
->long_offset
? sizeof(int32_t) : sizeof(int16_t));
504 lseek(pf
->fd
, offset
, SEEK_SET
);
505 read (pf
->fd
, tmp
, 2);
506 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
507 if (pf
->long_offset
) {
508 read (pf
->fd
, tmp
, 2);
509 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
514 bitmap_offset
= ((pf
->height
+ 7) / 8) * p
->width
* char_code
;
517 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
518 lseek(pf
->fd
, file_offset
, SEEK_SET
);
520 int src_bytes
= p
->width
* ((pf
->height
+ 7) / 8);
521 read(pf
->fd
, p
->bitmap
, src_bytes
);
525 * Converts cbuf into a font cache
527 static void cache_create(struct font
* pf
, int maxwidth
, int height
)
529 /* maximum size of rotated bitmap */
530 int bitmap_size
= maxwidth
* ((height
+ 7) / 8);
532 /* Initialise cache */
533 font_cache_create(&pf
->cache
, pf
->buffer_start
, pf
->buffer_size
, bitmap_size
);
537 * Returns width of character
539 int font_get_width(struct font
* pf
, unsigned short char_code
)
541 /* check input range*/
542 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
543 char_code
= pf
->defaultchar
;
544 char_code
-= pf
->firstchar
;
546 return (pf
->fd
>= 0 && pf
!= &sysfont
)?
547 font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->width
:
548 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
551 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
553 const unsigned char* bits
;
555 /* check input range*/
556 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
557 char_code
= pf
->defaultchar
;
558 char_code
-= pf
->firstchar
;
560 if (pf
->fd
>= 0 && pf
!= &sysfont
)
563 (unsigned char*)font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->bitmap
;
570 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
571 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
573 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
576 bits
+= ((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
;
582 static void glyph_file_write(void* data
)
584 struct font_cache_entry
* p
= data
;
585 struct font
* pf
= &font_ui
;
587 unsigned char tmp
[2];
589 ch
= p
->_char_code
+ pf
->firstchar
;
591 if (ch
!= 0xffff && cache_fd
>= 0) {
594 if (write(cache_fd
, tmp
, 2) != 2) {
602 /* save the char codes of the loaded glyphs to a file */
603 void glyph_cache_save(struct font
* pf
)
607 if (pf
->fd
>= 0 && pf
== &font_ui
)
610 cache_fd
= open(GLYPH_CACHE_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
612 cache_fd
= creat(GLYPH_CACHE_FILE
, 0666);
614 if (cache_fd
< 0) return;
616 lru_traverse(&pf
->cache
._lru
, glyph_file_write
);
627 static void glyph_cache_load(struct font
* pf
)
631 unsigned char tmp
[2];
634 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
638 while (read(fd
, tmp
, 2) == 2) {
639 ch
= (tmp
[0] << 8) | tmp
[1];
640 font_get_bits(pf
, ch
);
645 /* load latin1 chars into cache */
648 font_get_bits(pf
, ch
);
653 #else /* BOOTLOADER */
660 * Bootloader only supports the built-in sysfont.
662 struct font
* font_get(int font
)
669 * Returns width of character
671 int font_get_width(struct font
* pf
, unsigned short char_code
)
673 /* check input range*/
674 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
675 char_code
= pf
->defaultchar
;
676 char_code
-= pf
->firstchar
;
678 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
681 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
683 const unsigned char* bits
;
685 /* check input range*/
686 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
687 char_code
= pf
->defaultchar
;
688 char_code
-= pf
->firstchar
;
690 /* assume small font with uint16_t offsets*/
691 bits
= pf
->bits
+ (pf
->offset
?
692 ((uint16_t*)(pf
->offset
))[char_code
]:
693 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
698 #endif /* BOOTLOADER */
701 * Returns the stringsize of a given string.
703 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
705 struct font
* pf
= font_get(fontnumber
);
709 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
711 if (is_diacritic(ch
, NULL
))
714 /* get proportional width and glyph bits*/
715 width
+= font_get_width(pf
,ch
);
724 /* -----------------------------------------------------------------
725 * vim: et sw=4 ts=8 sts=4 tw=78