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 "core_alloc.h"
40 #include "rbunicode.h"
41 #include "diacritic.h"
44 #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB
46 /* max static loadable font buffer size */
50 #define MAX_FONT_SIZE 60000
52 #define MAX_FONT_SIZE 10000
55 #define MAX_FONT_SIZE 4000
59 #ifndef FONT_HEADER_SIZE
60 #define FONT_HEADER_SIZE 36
64 /* Font cache includes */
65 #include "font_cache.h"
73 /* Define this to try loading /.rockbox/.glyphcache *
74 * when a font specific file fails. This requires the *
75 * user to copy and rename a font glyph cache file */
76 //#define TRY_DEFAULT_GLYPHCACHE
78 /* compiled-in font */
79 extern struct font sysfont
;
83 struct buflib_alloc_data
{
85 int handle_locks
; /* is the buflib handle currently locked? */
86 int refcount
; /* how many times has this font been loaded? */
87 unsigned char buffer
[];
89 static int buflib_allocations
[MAXFONTS
];
91 static int font_ui
= -1;
93 static struct font
* cache_pf
;
95 static int buflibmove_callback(int handle
, void* current
, void* new)
98 struct buflib_alloc_data
*alloc
= (struct buflib_alloc_data
*)current
;
99 ptrdiff_t diff
= new - current
;
101 if (alloc
->handle_locks
> 0)
102 return BUFLIB_CB_CANNOT_MOVE
;
104 #define UPDATE(x) if (x) { x = PTR_ADD(x, diff); }
106 UPDATE(alloc
->font
.bits
);
107 UPDATE(alloc
->font
.offset
);
108 UPDATE(alloc
->font
.width
);
110 UPDATE(alloc
->font
.buffer_start
);
111 UPDATE(alloc
->font
.buffer_end
);
112 UPDATE(alloc
->font
.buffer_position
);
114 UPDATE(alloc
->font
.cache
._index
);
115 UPDATE(alloc
->font
.cache
._lru
._base
);
119 static void lock_font_handle(int handle
, bool lock
)
121 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
123 alloc
->handle_locks
++;
125 alloc
->handle_locks
--;
128 void font_lock(int font_id
, bool lock
)
130 if( font_id
== FONT_SYSFIXED
)
132 if( buflib_allocations
[font_id
] >= 0 )
133 lock_font_handle(buflib_allocations
[font_id
], lock
);
136 static struct buflib_callbacks buflibops
= {buflibmove_callback
, NULL
};
138 static inline struct font
*pf_from_handle(int handle
)
140 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
141 struct font
*pf
= &alloc
->font
;
145 static inline unsigned char *buffer_from_handle(int handle
)
147 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
148 unsigned char* buffer
= alloc
->buffer
;
152 /* Font cache structures */
153 static void cache_create(struct font
* pf
);
154 static void glyph_cache_load(int fond_id
);
155 /* End Font cache structures */
162 buflib_allocations
[i
++] = -1;
165 /* Check if we have x bytes left in the file buffer */
166 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
168 /* Helper functions to read big-endian unaligned short or long from
169 the file buffer. Bounds-checking must be done in the calling
173 static short readshort(struct font
*pf
)
177 s
= *pf
->buffer_position
++ & 0xff;
178 s
|= (*pf
->buffer_position
++ << 8);
182 static int32_t readlong(struct font
*pf
)
186 l
= *pf
->buffer_position
++ & 0xff;
187 l
|= *pf
->buffer_position
++ << 8;
188 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 16;
189 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 24;
193 static int glyph_bytes( struct font
*pf
, int width
)
197 ret
= ( pf
->height
* width
+ 1 ) / 2;
199 ret
= width
* ((pf
->height
+ 7) / 8);
200 return (ret
+ 1) & ~1;
203 static struct font
* font_load_header(struct font
*pf
)
205 /* Check we have enough data */
209 /* read magic and version #*/
210 if (memcmp(pf
->buffer_position
, VERSION
, 4) != 0)
213 pf
->buffer_position
+= 4;
216 pf
->maxwidth
= readshort(pf
);
217 pf
->height
= readshort(pf
);
218 pf
->ascent
= readshort(pf
);
219 pf
->depth
= readshort(pf
);
220 pf
->firstchar
= readlong(pf
);
221 pf
->defaultchar
= readlong(pf
);
222 pf
->size
= readlong(pf
);
224 /* get variable font data sizes*/
225 /* # words of bitmap_t*/
226 pf
->bits_size
= readlong(pf
);
230 /* Load memory font */
231 static struct font
* font_load_in_memory(struct font
* pf
)
233 int32_t i
, noffset
, nwidth
;
238 /* # longs of offset*/
239 noffset
= readlong(pf
);
241 /* # bytes of width*/
242 nwidth
= readlong(pf
);
244 /* variable font data*/
245 pf
->bits
= (unsigned char *)pf
->buffer_position
;
246 pf
->buffer_position
+= pf
->bits_size
*sizeof(unsigned char);
248 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
250 /* pad to 16-bit boundary */
251 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
255 /* pad to 32-bit boundary*/
256 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
261 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
264 pf
->offset
= (uint16_t*)pf
->buffer_position
;
266 /* Check we have sufficient buffer */
267 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
270 for (i
=0; i
<noffset
; ++i
)
272 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort(pf
);
278 pf
->offset
= (uint16_t*)pf
->buffer_position
;
280 /* Check we have sufficient buffer */
281 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
284 for (i
=0; i
<noffset
; ++i
)
286 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong(pf
);
294 pf
->width
= (unsigned char *)pf
->buffer_position
;
295 pf
->buffer_position
+= nwidth
*sizeof(unsigned char);
300 if (pf
->buffer_position
> pf
->buffer_end
)
303 return pf
; /* success!*/
306 /* Load cached font */
307 static struct font
* font_load_cached(struct font
* pf
)
309 uint32_t noffset
, nwidth
;
310 unsigned char* oldfileptr
= pf
->buffer_position
;
312 if (!HAVEBYTES(2 * sizeof(int32_t)))
315 /* # longs of offset*/
316 noffset
= readlong(pf
);
318 /* # bytes of width*/
319 nwidth
= readlong(pf
);
321 /* We are now at the bitmap data, this is fixed at 36.. */
324 /* Calculate offset to offset data */
325 pf
->buffer_position
+= pf
->bits_size
* sizeof(unsigned char);
327 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
330 /* pad to 16-bit boundary */
331 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
336 /* pad to 32-bit boundary*/
337 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
341 pf
->file_offset_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
343 pf
->file_offset_offset
= 0;
345 /* Calculate offset to widths data */
346 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
347 pf
->buffer_position
+= noffset
* sizeof(uint16_t);
349 pf
->buffer_position
+= noffset
* sizeof(uint32_t);
352 pf
->file_width_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
354 pf
->file_width_offset
= 0;
356 pf
->buffer_position
= oldfileptr
;
358 /* Create the cache */
364 static bool internal_load_font(int font_id
, const char *path
, char *buf
,
365 size_t buf_size
, int handle
)
368 struct font
* pf
= pf_from_handle(handle
);
370 /* open and read entire font file*/
371 pf
->fd
= open(path
, O_RDONLY
|O_BINARY
);
374 DEBUGF("Can't open font: %s\n", path
);
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");
398 if (!font_load_cached(pf
))
400 DEBUGF("Failed font cache load");
406 /* Cheat to get sector cache for different parts of font *
407 * file while preloading glyphs. Without this the disk head *
408 * thrashes between the width, offset, and bitmap data *
409 * in glyph_cache_load(). */
410 pf
->fd_width
= open(path
, O_RDONLY
|O_BINARY
);
411 pf
->fd_offset
= open(path
, O_RDONLY
|O_BINARY
);
413 glyph_cache_load(font_id
);
415 if(pf
->fd_width
>= 0)
419 if(pf
->fd_offset
>= 0)
420 close(pf
->fd_offset
);
425 read(pf
->fd
, pf
->buffer_position
, pf
->buffer_size
);
426 pf
->buffer_end
= pf
->buffer_position
+ size
;
432 if (!font_load_header(pf
))
434 DEBUGF("Failed font header load");
438 if (!font_load_in_memory(pf
))
440 DEBUGF("Failed mem load");
447 static int find_font_index(const char* path
)
449 int index
= 0, handle
;
451 while (index
< MAXFONTS
)
453 handle
= buflib_allocations
[index
];
454 if (handle
> 0 && !strcmp(core_get_name(handle
), path
))
458 return FONT_SYSFIXED
;
461 static int alloc_and_init(int font_idx
, const char* name
, size_t size
)
463 int *phandle
= &buflib_allocations
[font_idx
];
464 int handle
= *phandle
;
465 struct buflib_alloc_data
*pdata
;
467 size_t alloc_size
= size
+ sizeof(struct buflib_alloc_data
);
470 *phandle
= core_alloc_ex(name
, alloc_size
, &buflibops
);
474 pdata
= core_get_data(handle
);
476 pdata
->handle_locks
= 0;
478 pf
->buffer_position
= pf
->buffer_start
= buffer_from_handle(handle
);
479 pf
->buffer_size
= size
;
485 const char* font_filename(int font_id
)
487 int handle
= buflib_allocations
[font_id
];
489 return core_get_name(handle
);
493 /* read and load font into incore font structure,
494 * returns the font number on success, -1 on failure */
495 int font_load_ex(const char *path
, size_t buffer_size
)
497 int font_id
= find_font_index(path
);
501 if (font_id
> FONT_SYSFIXED
)
503 /* already loaded, no need to reload */
504 struct buflib_alloc_data
*pd
= core_get_data(buflib_allocations
[font_id
]);
505 if (pd
->font
.buffer_size
< buffer_size
)
507 int old_refcount
, old_id
;
509 * 1) save of refcont and id
510 * 2) force unload (set refcount to 1 to make sure it get unloaded)
511 * 3) reload with the larger buffer
512 * 4) restore the id and refcount
515 old_refcount
= pd
->refcount
;
517 font_unload(font_id
);
518 font_id
= font_load_ex(path
, buffer_size
);
521 // not much we can do here, maybe try reloading with the small buffer again
524 if (old_id
!= font_id
)
526 buflib_allocations
[old_id
] = buflib_allocations
[font_id
];
527 buflib_allocations
[font_id
] = -1;
530 pd
= core_get_data(buflib_allocations
[font_id
]);
531 pd
->refcount
= old_refcount
;
534 //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount);
538 for (font_id
= FONT_FIRSTUSERFONT
; font_id
< MAXFONTS
; font_id
++)
540 handle
= buflib_allocations
[font_id
];
546 handle
= alloc_and_init(font_id
, path
, buffer_size
);
550 buffer
= buffer_from_handle(handle
);
551 lock_font_handle(handle
, true);
553 if (!internal_load_font(font_id
, path
, buffer
, buffer_size
, handle
))
555 lock_font_handle(handle
, false);
557 buflib_allocations
[font_id
] = -1;
561 lock_font_handle(handle
, false);
562 buflib_allocations
[font_id
] = handle
;
563 //printf("%s -> [%d] -> %d\n", path, font_id, handle);
564 return font_id
; /* success!*/
566 int font_load(const char *path
)
569 int fd
= open( path
, O_RDONLY
);
573 if (size
> MAX_FONT_SIZE
)
574 size
= MAX_FONT_SIZE
;
576 return font_load_ex(path
, size
);
579 void font_unload(int font_id
)
581 if ( font_id
== FONT_SYSFIXED
)
583 int handle
= buflib_allocations
[font_id
];
586 struct buflib_alloc_data
*pdata
= core_get_data(handle
);
587 struct font
* pf
= &pdata
->font
;
589 if (pdata
->refcount
< 1)
591 //printf("freeing id: %d %s\n", font_id, core_get_name(*handle));
592 if (pf
&& pf
->fd
>= 0)
594 glyph_cache_save(font_id
);
599 buflib_allocations
[font_id
] = -1;
604 void font_unload_all(void)
607 for (i
=0; i
<MAXFONTS
; i
++)
609 if (buflib_allocations
[i
] > 0)
611 struct buflib_alloc_data
*alloc
= core_get_data(buflib_allocations
[i
]);
612 alloc
->refcount
= 1; /* force unload */
619 * Return a pointer to an incore font structure.
620 * Return the requested font, font_ui, or sysfont
622 struct font
* font_get(int font_id
)
624 struct buflib_alloc_data
*alloc
;
628 if( font_id
== FONT_UI
)
631 if( font_id
== FONT_SYSFIXED
)
637 handle
= buflib_allocations
[id
];
640 alloc
= core_get_data(buflib_allocations
[id
]);
642 if( pf
&& pf
->height
)
645 handle
= buflib_allocations
[font_ui
];
648 alloc
= core_get_data(buflib_allocations
[font_ui
]);
650 if( pf
&& pf
->height
)
657 void font_set_ui( int font_id
)
668 static int pf_to_handle(struct font
* pf
)
671 for (i
=0; i
<MAXFONTS
; i
++)
673 int handle
= buflib_allocations
[i
];
676 struct buflib_alloc_data
*pdata
= core_get_data(handle
);
677 if (pf
== &pdata
->font
)
685 * Reads an entry into cache entry
688 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
690 struct font
* pf
= callback_data
;
691 int handle
= pf_to_handle(pf
);
692 unsigned short char_code
= p
->_char_code
;
693 unsigned char tmp
[2];
697 lock_font_handle(handle
, true);
698 if (pf
->file_width_offset
)
700 int width_offset
= pf
->file_width_offset
+ char_code
;
701 /* load via different fd to get this file section cached */
702 if(pf
->fd_width
>=0 )
706 lseek(fd
, width_offset
, SEEK_SET
);
707 read(fd
, &(p
->width
), 1);
711 p
->width
= pf
->maxwidth
;
714 int32_t bitmap_offset
= 0;
716 if (pf
->file_offset_offset
)
718 int32_t offset
= pf
->file_offset_offset
+ char_code
* (pf
->long_offset
? sizeof(int32_t) : sizeof(int16_t));
719 /* load via different fd to get this file section cached */
720 if(pf
->fd_offset
>=0 )
724 lseek(fd
, offset
, SEEK_SET
);
726 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
727 if (pf
->long_offset
) {
729 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
734 bitmap_offset
= char_code
* glyph_bytes(pf
, p
->width
);
737 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
738 lseek(pf
->fd
, file_offset
, SEEK_SET
);
739 int src_bytes
= glyph_bytes(pf
, p
->width
);
740 read(pf
->fd
, p
->bitmap
, src_bytes
);
743 lock_font_handle(handle
, false);
747 * Converts cbuf into a font cache
749 static void cache_create(struct font
* pf
)
751 /* maximum size of rotated bitmap */
752 int bitmap_size
= glyph_bytes( pf
, pf
->maxwidth
);
754 /* Initialise cache */
755 font_cache_create(&pf
->cache
, pf
->buffer_start
, pf
->buffer_size
, bitmap_size
);
759 * Returns width of character
761 int font_get_width(struct font
* pf
, unsigned short char_code
)
763 /* check input range*/
764 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
765 char_code
= pf
->defaultchar
;
766 char_code
-= pf
->firstchar
;
768 return (pf
->fd
>= 0 && pf
!= &sysfont
)?
769 font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->width
:
770 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
773 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
775 const unsigned char* bits
;
777 /* check input range*/
778 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
779 char_code
= pf
->defaultchar
;
780 char_code
-= pf
->firstchar
;
782 if (pf
->fd
>= 0 && pf
!= &sysfont
)
785 (unsigned char*)font_cache_get(&pf
->cache
,char_code
,load_cache_entry
, pf
)->bitmap
;
792 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
793 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
795 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
798 bits
+= char_code
* glyph_bytes(pf
, pf
->maxwidth
);
804 void font_path_to_glyph_path( const char *font_path
, char *glyph_path
)
807 /* take full file name, cut extension, and add .glyphcache */
808 strlcpy(glyph_path
, font_path
, MAX_PATH
);
809 glyph_path
[strlen(glyph_path
)-4] = '\0';
810 strcat(glyph_path
, ".gc");
813 /* call with NULL to flush */
814 static void glyph_file_write(void* data
)
816 struct font_cache_entry
* p
= data
;
817 struct font
* pf
= cache_pf
;
819 static int buffer_pos
= 0;
820 #define WRITE_BUFFER 256
821 static unsigned char buffer
[WRITE_BUFFER
];
823 /* flush buffer & reset */
824 if ( data
== NULL
|| buffer_pos
>= WRITE_BUFFER
)
826 write(cache_fd
, buffer
, buffer_pos
);
831 if ( p
->_char_code
== 0xffff )
834 ch
= p
->_char_code
+ pf
->firstchar
;
835 buffer
[buffer_pos
] = ch
>> 8;
836 buffer
[buffer_pos
+1] = ch
& 0xff;
841 /* save the char codes of the loaded glyphs to a file */
842 void glyph_cache_save(int font_id
)
848 int handle
= buflib_allocations
[font_id
];
852 struct font
*pf
= pf_from_handle(handle
);
853 if(pf
&& pf
->fd
>= 0)
855 /* FIXME: This sleep should not be necessary but without it *
856 * unloading multiple fonts and saving glyphcache files *
857 * quickly in succession creates multiple glyphcache files *
858 * with the same name. */
860 char filename
[MAX_PATH
];
861 font_path_to_glyph_path(font_filename(font_id
), filename
);
862 fd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
868 lru_traverse(&cache_pf
->cache
._lru
, glyph_file_write
);
869 glyph_file_write(NULL
);
879 int font_glyphs_to_bufsize(const char *path
, int glyphs
)
883 char buf
[FONT_HEADER_SIZE
];
885 f
.buffer_start
= buf
;
886 f
.buffer_size
= sizeof(buf
);
887 f
.buffer_position
= buf
;
889 f
.fd
= open(path
, O_RDONLY
|O_BINARY
);
893 read(f
.fd
, f
.buffer_position
, FONT_HEADER_SIZE
);
894 f
.buffer_end
= f
.buffer_position
+ FONT_HEADER_SIZE
;
896 if( !font_load_header(&f
) )
903 bufsize
= LRU_SLOT_OVERHEAD
+ sizeof(struct font_cache_entry
) +
904 sizeof( unsigned short);
905 bufsize
+= glyph_bytes(&f
, f
.maxwidth
);
907 if ( bufsize
< FONT_HEADER_SIZE
)
908 bufsize
= FONT_HEADER_SIZE
;
912 static int ushortcmp(const void *a
, const void *b
)
914 return ((int)(*(unsigned short*)a
- *(unsigned short*)b
));
916 static void glyph_cache_load(int font_id
)
918 int handle
= buflib_allocations
[font_id
];
921 struct font
*pf
= pf_from_handle(handle
);
925 unsigned char tmp
[2];
927 unsigned short glyphs
[MAX_SORT
];
928 unsigned short glyphs_lru_order
[MAX_SORT
];
929 int glyph_file_skip
=0, glyph_file_size
=0;
931 int sort_size
= pf
->cache
._capacity
;
932 if ( sort_size
> MAX_SORT
)
933 sort_size
= MAX_SORT
;
935 char filename
[MAX_PATH
];
936 font_path_to_glyph_path(font_filename(font_id
), filename
);
938 fd
= open(filename
, O_RDONLY
|O_BINARY
);
939 #ifdef TRY_DEFAULT_GLYPHCACHE
940 /* if font specific file fails, try default */
942 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
945 /* only read what fits */
946 glyph_file_size
= filesize( fd
);
947 if ( glyph_file_size
> 2*pf
->cache
._capacity
) {
948 glyph_file_skip
= glyph_file_size
- 2*pf
->cache
._capacity
;
949 lseek( fd
, glyph_file_skip
, SEEK_SET
);
955 read( fd
, tmp
, 2 ) == 2 && size
< sort_size
;
958 glyphs
[size
] = (tmp
[0] << 8) | tmp
[1];
959 glyphs_lru_order
[size
] = glyphs
[size
];
962 /* sort glyphs array to make sector cache happy */
963 qsort((void *)glyphs
, size
, sizeof(unsigned short),
966 /* load font bitmaps */
967 for( i
= 0; i
< size
; i
++ )
968 font_get_bits(pf
, glyphs
[i
]);
970 /* redo to fix lru order */
971 for ( i
= 0; i
< size
; i
++)
972 font_get_bits(pf
, glyphs_lru_order
[i
]);
974 if ( size
< sort_size
)
980 /* load latin1 chars into cache */
981 for ( ch
= 32 ; ch
< 256 && ch
< pf
->cache
._capacity
+ 32; ch
++ )
982 font_get_bits(pf
, ch
);
987 #else /* BOOTLOADER */
993 void font_lock(int font_id
, bool lock
)
1000 * Bootloader only supports the built-in sysfont.
1002 struct font
* font_get(int font
)
1008 void font_set_ui(int font_id
)
1016 return FONT_SYSFIXED
;
1021 * Returns width of character
1023 int font_get_width(struct font
* pf
, unsigned short char_code
)
1025 /* check input range*/
1026 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
1027 char_code
= pf
->defaultchar
;
1028 char_code
-= pf
->firstchar
;
1030 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
1033 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
1035 const unsigned char* bits
;
1037 /* check input range*/
1038 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
1039 char_code
= pf
->defaultchar
;
1040 char_code
-= pf
->firstchar
;
1042 /* assume small font with uint16_t offsets*/
1043 bits
= pf
->bits
+ (pf
->offset
?
1044 ((uint16_t*)(pf
->offset
))[char_code
]:
1045 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
1050 #endif /* BOOTLOADER */
1053 * Returns the stringsize of a given string.
1055 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
1057 struct font
* pf
= font_get(fontnumber
);
1061 font_lock( fontnumber
, true );
1062 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
1064 if (is_diacritic(ch
, NULL
))
1067 /* get proportional width and glyph bits*/
1068 width
+= font_get_width(pf
,ch
);
1074 font_lock( fontnumber
, false );
1078 /* -----------------------------------------------------------------
1079 * vim: et sw=4 ts=8 sts=4 tw=78