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
;
79 /* system font table, in order of FONT_xxx definition */
80 static struct font
* const sysfonts
[MAXFONTS
] = { &sysfont
, &font_ui
};
82 /* static buffer allocation structures */
83 static unsigned char mbuf
[MAX_FONT_SIZE
];
84 static unsigned char *freeptr
= mbuf
;
85 static unsigned char *fileptr
;
86 static unsigned char *eofptr
;
88 /* Font cache structures */
89 static struct font_cache font_cache_ui
;
90 static int fnt_file
= -1; /* >=0 if font is cached */
91 static uint32_t file_width_offset
; /* offset to file width data */
92 static uint32_t file_offset_offset
; /* offset to file offset data */
93 static void cache_create(int maxwidth
, int height
);
94 static int long_offset
= 0;
95 static int glyph_file
;
96 /* End Font cache structures */
98 static void glyph_cache_load(void);
102 memset(&font_ui
, 0, sizeof(struct font
));
105 /* Check if we have x bytes left in the file buffer */
106 #define HAVEBYTES(x) (fileptr + (x) <= eofptr)
108 /* Helper functions to read big-endian unaligned short or long from
109 the file buffer. Bounds-checking must be done in the calling
113 static short readshort(void)
117 s
= *fileptr
++ & 0xff;
118 s
|= (*fileptr
++ << 8);
122 static int32_t readlong(void)
126 l
= *fileptr
++ & 0xff;
127 l
|= *fileptr
++ << 8;
128 l
|= ((uint32_t)(*fileptr
++)) << 16;
129 l
|= ((uint32_t)(*fileptr
++)) << 24;
133 void font_reset(void)
135 memset(&font_ui
, 0, sizeof(struct font
));
138 static struct font
* font_load_header(struct font
*pf
)
140 /* Check we have enough data */
144 /* read magic and version #*/
145 if (memcmp(fileptr
, VERSION
, 4) != 0)
151 pf
->maxwidth
= readshort();
152 pf
->height
= readshort();
153 pf
->ascent
= readshort();
154 fileptr
+= 2; /* Skip padding */
155 pf
->firstchar
= readlong();
156 pf
->defaultchar
= readlong();
157 pf
->size
= readlong();
159 /* get variable font data sizes*/
160 /* # words of bitmap_t*/
161 pf
->bits_size
= readlong();
165 /* Load memory font */
166 static struct font
* font_load_in_memory(struct font
* pf
)
168 int32_t i
, noffset
, nwidth
;
173 /* # longs of offset*/
174 noffset
= readlong();
176 /* # bytes of width*/
179 /* variable font data*/
180 pf
->bits
= (unsigned char *)fileptr
;
181 fileptr
+= pf
->bits_size
*sizeof(unsigned char);
183 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
185 /* pad to 16-bit boundary */
186 fileptr
= (unsigned char *)(((intptr_t)fileptr
+ 1) & ~1);
190 /* pad to 32-bit boundary*/
191 fileptr
= (unsigned char *)(((intptr_t)fileptr
+ 3) & ~3);
196 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
199 pf
->offset
= (uint16_t*)fileptr
;
201 /* Check we have sufficient buffer */
202 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
205 for (i
=0; i
<noffset
; ++i
)
207 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort();
213 pf
->offset
= (uint16_t*)fileptr
;
215 /* Check we have sufficient buffer */
216 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
219 for (i
=0; i
<noffset
; ++i
)
221 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong();
229 pf
->width
= (unsigned char *)fileptr
;
230 fileptr
+= nwidth
*sizeof(unsigned char);
235 if (fileptr
> eofptr
)
238 return pf
; /* success!*/
241 /* Load cached font */
242 static struct font
* font_load_cached(struct font
* pf
)
244 uint32_t noffset
, nwidth
;
245 unsigned char* oldfileptr
= fileptr
;
247 if (!HAVEBYTES(2 * sizeof(int32_t)))
250 /* # longs of offset*/
251 noffset
= readlong();
253 /* # bytes of width*/
256 /* We are now at the bitmap data, this is fixed at 36.. */
259 /* Calculate offset to offset data */
260 fileptr
+= pf
->bits_size
* sizeof(unsigned char);
262 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
265 /* pad to 16-bit boundary */
266 fileptr
= (unsigned char *)(((intptr_t)fileptr
+ 1) & ~1);
271 /* pad to 32-bit boundary*/
272 fileptr
= (unsigned char *)(((intptr_t)fileptr
+ 3) & ~3);
276 file_offset_offset
= (uint32_t)(fileptr
- freeptr
);
278 file_offset_offset
= 0;
280 /* Calculate offset to widths data */
281 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
282 fileptr
+= noffset
* sizeof(uint16_t);
284 fileptr
+= noffset
* sizeof(uint32_t);
287 file_width_offset
= (uint32_t)(fileptr
- freeptr
);
289 file_width_offset
= 0;
291 fileptr
= oldfileptr
;
293 /* Create the cache */
294 cache_create(pf
->maxwidth
, pf
->height
);
299 /* read and load font into incore font structure*/
300 struct font
* font_load(const char *path
)
303 struct font
* pf
= &font_ui
;
305 /* save loaded glyphs */
308 /* Close font file handle */
312 /* open and read entire font file*/
313 fnt_file
= open(path
, O_RDONLY
|O_BINARY
);
316 DEBUGF("Can't open font: %s\n", path
);
320 /* Check file size */
321 size
= filesize(fnt_file
);
325 /* currently, font loading replaces earlier font allocation*/
326 freeptr
= (unsigned char *)(((intptr_t)mbuf
+ 3) & ~3);
330 if (size
> MAX_FONT_SIZE
)
332 read(fnt_file
, fileptr
, FONT_HEADER_SIZE
);
333 eofptr
= fileptr
+ FONT_HEADER_SIZE
;
335 if (!font_load_header(pf
))
337 DEBUGF("Failed font header load");
341 if (!font_load_cached(pf
))
343 DEBUGF("Failed font cache load");
351 read(fnt_file
, fileptr
, MAX_FONT_SIZE
);
352 eofptr
= fileptr
+ size
;
356 if (!font_load_header(pf
))
358 DEBUGF("Failed font header load");
362 if (!font_load_in_memory(pf
))
364 DEBUGF("Failed mem load");
369 /* no need for multiple font loads currently*/
370 /*freeptr += filesize;*/
371 /*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/
373 return pf
; /* success!*/
377 * Return a pointer to an incore font structure.
378 * If the requested font isn't loaded/compiled-in,
379 * decrement the font number and try again.
381 struct font
* font_get(int font
)
385 if (font
>= MAXFONTS
)
390 if (pf
&& pf
->height
)
398 * Reads an entry into cache entry
401 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
403 struct font
* pf
= callback_data
;
404 unsigned short char_code
= p
->_char_code
;
405 unsigned char tmp
[2];
407 if (file_width_offset
)
409 int width_offset
= file_width_offset
+ char_code
;
410 lseek(fnt_file
, width_offset
, SEEK_SET
);
411 read(fnt_file
, &(p
->width
), 1);
415 p
->width
= pf
->maxwidth
;
418 int32_t bitmap_offset
= 0;
420 if (file_offset_offset
)
422 int32_t offset
= file_offset_offset
+ char_code
* (long_offset
? sizeof(int32_t) : sizeof(int16_t));
423 lseek(fnt_file
, offset
, SEEK_SET
);
424 read (fnt_file
, tmp
, 2);
425 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
427 read (fnt_file
, tmp
, 2);
428 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
433 bitmap_offset
= ((pf
->height
+ 7) / 8) * p
->width
* char_code
;
436 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
437 lseek(fnt_file
, file_offset
, SEEK_SET
);
439 int src_bytes
= p
->width
* ((pf
->height
+ 7) / 8);
440 read(fnt_file
, p
->bitmap
, src_bytes
);
444 * Converts cbuf into a font cache
446 static void cache_create(int maxwidth
, int height
)
448 /* maximum size of rotated bitmap */
449 int bitmap_size
= maxwidth
* ((height
+ 7) / 8);
451 /* Initialise cache */
452 font_cache_create(&font_cache_ui
, mbuf
, MAX_FONT_SIZE
, bitmap_size
);
456 * Returns width of character
458 int font_get_width(struct font
* pf
, unsigned short char_code
)
460 /* check input range*/
461 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
462 char_code
= pf
->defaultchar
;
463 char_code
-= pf
->firstchar
;
465 return (fnt_file
>= 0 && pf
!= &sysfont
)?
466 font_cache_get(&font_cache_ui
,char_code
,load_cache_entry
,pf
)->width
:
467 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
470 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
472 const unsigned char* bits
;
474 /* check input range*/
475 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
476 char_code
= pf
->defaultchar
;
477 char_code
-= pf
->firstchar
;
479 if (fnt_file
>= 0 && pf
!= &sysfont
)
482 (unsigned char*)font_cache_get(&font_cache_ui
,char_code
,load_cache_entry
,pf
)->bitmap
;
489 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
490 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
492 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
495 bits
+= ((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
;
501 static void glyph_file_write(void* data
)
503 struct font_cache_entry
* p
= data
;
504 struct font
* pf
= &font_ui
;
506 unsigned char tmp
[2];
508 ch
= p
->_char_code
+ pf
->firstchar
;
510 if (ch
!= 0xffff && glyph_file
>= 0) {
513 if (write(glyph_file
, tmp
, 2) != 2) {
521 /* save the char codes of the loaded glyphs to a file */
522 void glyph_cache_save(void)
527 glyph_file
= open(GLYPH_CACHE_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
529 glyph_file
= creat(GLYPH_CACHE_FILE
);
531 if (glyph_file
< 0) return;
533 lru_traverse(&font_cache_ui
._lru
, glyph_file_write
);
541 static void glyph_cache_load(void)
546 unsigned char tmp
[2];
548 struct font
* pf
= &font_ui
;
550 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
554 while (read(fd
, tmp
, 2) == 2) {
555 ch
= (tmp
[0] << 8) | tmp
[1];
556 font_get_bits(pf
, ch
);
561 /* load latin1 chars into cache */
564 font_get_bits(pf
, ch
);
569 #else /* BOOTLOADER */
576 * Bootloader only supports the built-in sysfont.
578 struct font
* font_get(int font
)
585 * Returns width of character
587 int font_get_width(struct font
* pf
, unsigned short char_code
)
589 /* check input range*/
590 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
591 char_code
= pf
->defaultchar
;
592 char_code
-= pf
->firstchar
;
594 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
597 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
599 const unsigned char* bits
;
601 /* check input range*/
602 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
603 char_code
= pf
->defaultchar
;
604 char_code
-= pf
->firstchar
;
606 /* assume small font with uint16_t offsets*/
607 bits
= pf
->bits
+ (pf
->offset
?
608 ((uint16_t*)(pf
->offset
))[char_code
]:
609 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
614 #endif /* BOOTLOADER */
617 * Returns the stringsize of a given string.
619 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
621 struct font
* pf
= font_get(fontnumber
);
625 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
627 if (is_diacritic(ch
, NULL
))
630 /* get proportional width and glyph bits*/
631 width
+= font_get_width(pf
,ch
);
640 /* -----------------------------------------------------------------
641 * vim: et sw=4 ts=8 sts=4 tw=78