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
;
103 /* Check if we have x bytes left in the file buffer */
104 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
106 /* Helper functions to read big-endian unaligned short or long from
107 the file buffer. Bounds-checking must be done in the calling
111 static short readshort(struct font
*pf
)
115 s
= *pf
->buffer_position
++ & 0xff;
116 s
|= (*pf
->buffer_position
++ << 8);
120 static int32_t readlong(struct font
*pf
)
124 l
= *pf
->buffer_position
++ & 0xff;
125 l
|= *pf
->buffer_position
++ << 8;
126 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 16;
127 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 24;
131 void font_reset(struct font
*pf
)
133 unsigned char* buffer
= NULL
;
139 buffer
= pf
->buffer_start
;
140 buf_size
= pf
->buffer_size
;
142 memset(pf
, 0, sizeof(struct font
));
146 pf
->buffer_start
= buffer
;
147 pf
->buffer_size
= buf_size
;
151 static struct font
* font_load_header(struct font
*pf
)
153 /* Check we have enough data */
157 /* read magic and version #*/
158 if (memcmp(pf
->buffer_position
, VERSION
, 4) != 0)
161 pf
->buffer_position
+= 4;
164 pf
->maxwidth
= readshort(pf
);
165 pf
->height
= readshort(pf
);
166 pf
->ascent
= readshort(pf
);
167 pf
->buffer_position
+= 2; /* Skip padding */
168 pf
->firstchar
= readlong(pf
);
169 pf
->defaultchar
= readlong(pf
);
170 pf
->size
= readlong(pf
);
172 /* get variable font data sizes*/
173 /* # words of bitmap_t*/
174 pf
->bits_size
= readlong(pf
);
178 /* Load memory font */
179 static struct font
* font_load_in_memory(struct font
* pf
)
181 int32_t i
, noffset
, nwidth
;
186 /* # longs of offset*/
187 noffset
= readlong(pf
);
189 /* # bytes of width*/
190 nwidth
= readlong(pf
);
192 /* variable font data*/
193 pf
->bits
= (unsigned char *)pf
->buffer_position
;
194 pf
->buffer_position
+= pf
->bits_size
*sizeof(unsigned char);
196 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
198 /* pad to 16-bit boundary */
199 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
203 /* pad to 32-bit boundary*/
204 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
209 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
212 pf
->offset
= (uint16_t*)pf
->buffer_position
;
214 /* Check we have sufficient buffer */
215 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
218 for (i
=0; i
<noffset
; ++i
)
220 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort(pf
);
226 pf
->offset
= (uint16_t*)pf
->buffer_position
;
228 /* Check we have sufficient buffer */
229 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
232 for (i
=0; i
<noffset
; ++i
)
234 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong(pf
);
242 pf
->width
= (unsigned char *)pf
->buffer_position
;
243 pf
->buffer_position
+= nwidth
*sizeof(unsigned char);
248 if (pf
->buffer_position
> pf
->buffer_end
)
251 return pf
; /* success!*/
254 /* Load cached font */
255 static struct font
* font_load_cached(struct font
* pf
)
257 uint32_t noffset
, nwidth
;
258 unsigned char* oldfileptr
= pf
->buffer_position
;
260 if (!HAVEBYTES(2 * sizeof(int32_t)))
263 /* # longs of offset*/
264 noffset
= readlong(pf
);
266 /* # bytes of width*/
267 nwidth
= readlong(pf
);
269 /* We are now at the bitmap data, this is fixed at 36.. */
272 /* Calculate offset to offset data */
273 pf
->buffer_position
+= pf
->bits_size
* sizeof(unsigned char);
275 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
278 /* pad to 16-bit boundary */
279 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
284 /* pad to 32-bit boundary*/
285 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
289 pf
->file_offset_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
291 pf
->file_offset_offset
= 0;
293 /* Calculate offset to widths data */
294 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
295 pf
->buffer_position
+= noffset
* sizeof(uint16_t);
297 pf
->buffer_position
+= noffset
* sizeof(uint32_t);
300 pf
->file_width_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
302 pf
->file_width_offset
= 0;
304 pf
->buffer_position
= oldfileptr
;
306 /* Create the cache */
307 cache_create(pf
, pf
->maxwidth
, pf
->height
);
312 static bool internal_load_font(struct font
* pf
, const char *path
,
313 char *buf
, size_t buf_size
)
317 /* save loaded glyphs */
318 glyph_cache_save(pf
);
319 /* Close font file handle */
325 /* open and read entire font file*/
326 pf
->fd
= open(path
, O_RDONLY
|O_BINARY
);
329 DEBUGF("Can't open font: %s\n", path
);
333 /* Check file size */
334 size
= filesize(pf
->fd
);
335 pf
->buffer_start
= buf
;
336 pf
->buffer_size
= buf_size
;
338 pf
->buffer_position
= buf
;
340 if (size
> pf
->buffer_size
)
342 read(pf
->fd
, pf
->buffer_position
, FONT_HEADER_SIZE
);
343 pf
->buffer_end
= pf
->buffer_position
+ FONT_HEADER_SIZE
;
345 if (!font_load_header(pf
))
347 DEBUGF("Failed font header load");
351 if (!font_load_cached(pf
))
353 DEBUGF("Failed font cache load");
357 glyph_cache_load(pf
);
361 read(pf
->fd
, pf
->buffer_position
, pf
->buffer_size
);
362 pf
->buffer_end
= pf
->buffer_position
+ size
;
366 if (!font_load_header(pf
))
368 DEBUGF("Failed font header load");
372 if (!font_load_in_memory(pf
))
374 DEBUGF("Failed mem load");
381 #ifdef HAVE_REMOTE_LCD
382 /* Load a font into the special remote ui font slot */
383 int font_load_remoteui(const char* path
)
385 struct font
* pf
= &remote_font_ui
;
388 if (sysfonts
[FONT_UI_REMOTE
] && sysfonts
[FONT_UI_REMOTE
] != sysfonts
[FONT_UI
])
389 font_unload(FONT_UI_REMOTE
);
390 sysfonts
[FONT_UI_REMOTE
] = NULL
;
393 if (!internal_load_font(pf
, path
, remote_buf
, REMOTE_FONT_SIZE
))
395 sysfonts
[FONT_UI_REMOTE
] = NULL
;
399 sysfonts
[FONT_UI_REMOTE
] = pf
;
400 return FONT_UI_REMOTE
;
404 /* read and load font into incore font structure,
405 * returns the font number on success, -1 on failure */
406 int font_load(struct font
* pf
, const char *path
)
418 for (font_id
= SYSTEMFONTCOUNT
; font_id
< MAXFONTS
; font_id
++)
420 if (sysfonts
[font_id
] == NULL
)
423 if (font_id
== MAXFONTS
)
424 return -1; /* too many fonts */
427 if (font_id
== FONT_UI
)
429 /* currently, font loading replaces earlier font allocation*/
430 buffer
= (unsigned char *)(((intptr_t)main_buf
+ 3) & ~3);
431 buffer_size
= MAX_FONT_SIZE
;
435 buffer
= pf
->buffer_start
;
436 buffer_size
= pf
->buffer_size
;
439 if (!internal_load_font(pf
, path
, buffer
, buffer_size
))
442 sysfonts
[font_id
] = pf
;
443 return font_id
; /* success!*/
446 void font_unload(int font_id
)
448 struct font
* pf
= sysfonts
[font_id
];
449 if (font_id
>= SYSTEMFONTCOUNT
&& pf
)
453 sysfonts
[font_id
] = NULL
;
458 * Return a pointer to an incore font structure.
459 * If the requested font isn't loaded/compiled-in,
460 * decrement the font number and try again.
462 struct font
* font_get(int font
)
468 if (pf
&& pf
->height
)
476 * Reads an entry into cache entry
479 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
481 struct font
* pf
= callback_data
;
482 unsigned short char_code
= p
->_char_code
;
483 unsigned char tmp
[2];
485 if (pf
->file_width_offset
)
487 int width_offset
= pf
->file_width_offset
+ char_code
;
488 lseek(pf
->fd
, width_offset
, SEEK_SET
);
489 read(pf
->fd
, &(p
->width
), 1);
493 p
->width
= pf
->maxwidth
;
496 int32_t bitmap_offset
= 0;
498 if (pf
->file_offset_offset
)
500 int32_t offset
= pf
->file_offset_offset
+ char_code
* (pf
->long_offset
? sizeof(int32_t) : sizeof(int16_t));
501 lseek(pf
->fd
, offset
, SEEK_SET
);
502 read (pf
->fd
, tmp
, 2);
503 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
504 if (pf
->long_offset
) {
505 read (pf
->fd
, tmp
, 2);
506 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
511 bitmap_offset
= ((pf
->height
+ 7) / 8) * p
->width
* char_code
;
514 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
515 lseek(pf
->fd
, file_offset
, SEEK_SET
);
517 int src_bytes
= p
->width
* ((pf
->height
+ 7) / 8);
518 read(pf
->fd
, p
->bitmap
, src_bytes
);
522 * Converts cbuf into a font cache
524 static void cache_create(struct font
* pf
, int maxwidth
, int height
)
526 /* maximum size of rotated bitmap */
527 int bitmap_size
= maxwidth
* ((height
+ 7) / 8);
529 /* Initialise cache */
530 font_cache_create(&pf
->cache
, pf
->buffer_start
, pf
->buffer_size
, bitmap_size
);
534 * Returns width of character
536 int font_get_width(struct font
* pf
, unsigned short char_code
)
538 /* check input range*/
539 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
540 char_code
= pf
->defaultchar
;
541 char_code
-= pf
->firstchar
;
543 return (pf
->fd
>= 0 && pf
!= &sysfont
)?
544 font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->width
:
545 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
548 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
550 const unsigned char* bits
;
552 /* check input range*/
553 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
554 char_code
= pf
->defaultchar
;
555 char_code
-= pf
->firstchar
;
557 if (pf
->fd
>= 0 && pf
!= &sysfont
)
560 (unsigned char*)font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->bitmap
;
567 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
568 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
570 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
573 bits
+= ((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
;
579 static void glyph_file_write(void* data
)
581 struct font_cache_entry
* p
= data
;
582 struct font
* pf
= &font_ui
;
584 unsigned char tmp
[2];
586 ch
= p
->_char_code
+ pf
->firstchar
;
588 if (ch
!= 0xffff && cache_fd
>= 0) {
591 if (write(cache_fd
, tmp
, 2) != 2) {
599 /* save the char codes of the loaded glyphs to a file */
600 void glyph_cache_save(struct font
* pf
)
604 if (pf
->fd
>= 0 && pf
== &font_ui
)
607 cache_fd
= open(GLYPH_CACHE_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
609 cache_fd
= creat(GLYPH_CACHE_FILE
);
611 if (cache_fd
< 0) return;
613 lru_traverse(&pf
->cache
._lru
, glyph_file_write
);
624 static void glyph_cache_load(struct font
* pf
)
628 unsigned char tmp
[2];
631 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
635 while (read(fd
, tmp
, 2) == 2) {
636 ch
= (tmp
[0] << 8) | tmp
[1];
637 font_get_bits(pf
, ch
);
642 /* load latin1 chars into cache */
645 font_get_bits(pf
, ch
);
650 #else /* BOOTLOADER */
657 * Bootloader only supports the built-in sysfont.
659 struct font
* font_get(int font
)
666 * Returns width of character
668 int font_get_width(struct font
* pf
, unsigned short char_code
)
670 /* check input range*/
671 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
672 char_code
= pf
->defaultchar
;
673 char_code
-= pf
->firstchar
;
675 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
678 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
680 const unsigned char* bits
;
682 /* check input range*/
683 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
684 char_code
= pf
->defaultchar
;
685 char_code
-= pf
->firstchar
;
687 /* assume small font with uint16_t offsets*/
688 bits
= pf
->bits
+ (pf
->offset
?
689 ((uint16_t*)(pf
->offset
))[char_code
]:
690 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
695 #endif /* BOOTLOADER */
698 * Returns the stringsize of a given string.
700 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
702 struct font
* pf
= font_get(fontnumber
);
706 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
708 if (is_diacritic(ch
, NULL
))
711 /* get proportional width and glyph bits*/
712 width
+= font_get_width(pf
,ch
);
721 /* -----------------------------------------------------------------
722 * vim: et sw=4 ts=8 sts=4 tw=78