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
58 #define GLYPHS_TO_CACHE 256
61 #define FONT_HARD_LIMIT
64 #ifndef FONT_HEADER_SIZE
65 #define FONT_HEADER_SIZE 36
69 /* Font cache includes */
70 #include "font_cache.h"
78 /* Define this to try loading /.rockbox/.glyphcache *
79 * when a font specific file fails. This requires the *
80 * user to copy and rename a font glyph cache file */
81 //#define TRY_DEFAULT_GLYPHCACHE
83 /* compiled-in font */
84 extern struct font sysfont
;
88 struct buflib_alloc_data
{
90 int handle_locks
; /* is the buflib handle currently locked? */
91 int refcount
; /* how many times has this font been loaded? */
92 unsigned char buffer
[];
94 static int buflib_allocations
[MAXFONTS
];
97 static struct font
* cache_pf
;
99 static void glyph_cache_save(int font_id
);
101 static int buflibmove_callback(int handle
, void* current
, void* new)
104 struct buflib_alloc_data
*alloc
= (struct buflib_alloc_data
*)current
;
105 ptrdiff_t diff
= new - current
;
107 if (alloc
->handle_locks
> 0)
108 return BUFLIB_CB_CANNOT_MOVE
;
110 #define UPDATE(x) if (x) { x = PTR_ADD(x, diff); }
112 UPDATE(alloc
->font
.bits
);
113 UPDATE(alloc
->font
.offset
);
114 UPDATE(alloc
->font
.width
);
116 UPDATE(alloc
->font
.buffer_start
);
117 UPDATE(alloc
->font
.buffer_end
);
118 UPDATE(alloc
->font
.buffer_position
);
120 UPDATE(alloc
->font
.cache
._index
);
121 UPDATE(alloc
->font
.cache
._lru
._base
);
125 static void lock_font_handle(int handle
, bool lock
)
129 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
131 alloc
->handle_locks
++;
133 alloc
->handle_locks
--;
136 void font_lock(int font_id
, bool lock
)
138 if( font_id
< 0 || font_id
>= MAXFONTS
)
140 if( buflib_allocations
[font_id
] >= 0 )
141 lock_font_handle(buflib_allocations
[font_id
], lock
);
144 static struct buflib_callbacks buflibops
= {buflibmove_callback
, NULL
};
146 static inline struct font
*pf_from_handle(int handle
)
148 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
149 struct font
*pf
= &alloc
->font
;
153 static inline unsigned char *buffer_from_handle(int handle
)
155 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
156 unsigned char* buffer
= alloc
->buffer
;
160 /* Font cache structures */
161 static void cache_create(struct font
* pf
);
162 static void glyph_cache_load(const char *font_path
, struct font
*pf
);
163 /* End Font cache structures */
170 buflib_allocations
[i
++] = -1;
173 /* Check if we have x bytes left in the file buffer */
174 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
176 /* Helper functions to read big-endian unaligned short or long from
177 the file buffer. Bounds-checking must be done in the calling
181 static short readshort(struct font
*pf
)
185 s
= *pf
->buffer_position
++ & 0xff;
186 s
|= (*pf
->buffer_position
++ << 8);
190 static int32_t readlong(struct font
*pf
)
194 l
= *pf
->buffer_position
++ & 0xff;
195 l
|= *pf
->buffer_position
++ << 8;
196 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 16;
197 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 24;
201 static int glyph_bytes( struct font
*pf
, int width
)
205 ret
= ( pf
->height
* width
+ 1 ) / 2;
207 ret
= width
* ((pf
->height
+ 7) / 8);
208 return (ret
+ 1) & ~1;
211 /* Load memory font */
212 static struct font
* font_load_in_memory(struct font
* pf
,
217 /* variable font data*/
218 pf
->buffer_position
= pf
->buffer_start
+ 36;
219 pf
->bits
= (unsigned char *)pf
->buffer_position
;
220 pf
->buffer_position
+= pf
->bits_size
*sizeof(unsigned char);
222 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
224 /* pad to 16-bit boundary */
225 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
229 /* pad to 32-bit boundary*/
230 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
235 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
238 pf
->offset
= (uint16_t*)pf
->buffer_position
;
240 /* Check we have sufficient buffer */
241 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
244 for (i
=0; i
<noffset
; ++i
)
246 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort(pf
);
252 pf
->offset
= (uint16_t*)pf
->buffer_position
;
254 /* Check we have sufficient buffer */
255 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
258 for (i
=0; i
<noffset
; ++i
)
260 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong(pf
);
268 pf
->width
= (unsigned char *)pf
->buffer_position
;
269 pf
->buffer_position
+= nwidth
*sizeof(unsigned char);
274 if (pf
->buffer_position
> pf
->buffer_end
)
277 return pf
; /* success!*/
280 /* Load cached font */
281 static struct font
* font_load_cached(struct font
* pf
,
285 /* We are now at the bitmap data, this is fixed at 36.. */
288 /* Calculate offset to offset data */
289 pf
->buffer_position
+= pf
->bits_size
* sizeof(unsigned char);
291 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
294 /* pad to 16-bit boundary */
295 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
300 /* pad to 32-bit boundary*/
301 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
305 pf
->file_offset_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
307 pf
->file_offset_offset
= 0;
309 /* Calculate offset to widths data */
310 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
311 pf
->buffer_position
+= noffset
* sizeof(uint16_t);
313 pf
->buffer_position
+= noffset
* sizeof(uint32_t);
316 pf
->file_width_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
318 pf
->file_width_offset
= 0;
320 /* Create the cache */
327 static int find_font_index(const char* path
)
329 int index
= 0, handle
;
331 while (index
< MAXFONTS
)
333 handle
= buflib_allocations
[index
];
334 if (handle
> 0 && !strcmp(core_get_name(handle
), path
))
338 return FONT_SYSFIXED
;
341 const char* font_filename(int font_id
)
343 if ( font_id
< 0 || font_id
>= MAXFONTS
)
345 int handle
= buflib_allocations
[font_id
];
347 return core_get_name(handle
);
351 size_t font_glyphs_to_bufsize(struct font
*pf
, int glyphs
)
355 /* LRU bytes per glyph */
356 bufsize
= LRU_SLOT_OVERHEAD
+ sizeof(struct font_cache_entry
) +
357 sizeof( unsigned short);
358 /* Image bytes per glyph */
359 bufsize
+= glyph_bytes(pf
, pf
->maxwidth
);
365 static struct font
* font_load_header(int fd
, struct font
*pheader
,
367 uint32_t *nwidth
, uint32_t *noffset
)
369 /* Load the header. Readshort() and readlong() *
370 * update buffer_position address as they read */
371 pheader
->buffer_start
= pheader
->buffer_position
= (char *)pheader
;
372 pheader
->buffer_size
= FONT_HEADER_SIZE
;
373 pheader
->buffer_end
= pheader
->buffer_start
+ pheader
->buffer_size
;
375 if (read(fd
, pheader
, FONT_HEADER_SIZE
) != FONT_HEADER_SIZE
)
378 /* read magic and version #*/
379 if (memcmp(pheader
->buffer_position
, VERSION
, 4) != 0)
382 pheader
->buffer_position
+= 4;
385 pf
->maxwidth
= readshort(pheader
);
386 pf
->height
= readshort(pheader
);
387 pf
->ascent
= readshort(pheader
);
388 pf
->depth
= readshort(pheader
);
389 pf
->firstchar
= readlong(pheader
);
390 pf
->defaultchar
= readlong(pheader
);
391 pf
->size
= readlong(pheader
);
393 /* get variable font data sizes*/
394 /* # words of bitmap_t*/
395 pf
->bits_size
= readlong(pheader
);
396 *noffset
= readlong(pheader
);
397 *nwidth
= readlong(pheader
);
402 /* load a font with room for glyphs, limited to bufsize if not zero */
403 int font_load_ex( const char *path
, size_t buf_size
, int glyphs
)
405 //printf("\nfont_load_ex(%s, %d, %d)\n", path, buf_size, glyphs);
406 int fd
= open(path
, O_RDONLY
|O_BINARY
);
410 /* load font struct f with file header */
411 int file_size
= filesize( fd
);
413 struct font
*pheader
= &header
;
416 uint32_t nwidth
, noffset
;
417 if ( !font_load_header( fd
, pheader
, &f
, &nwidth
, &noffset
)
427 /* examine f and calc buffer size */
429 size_t bufsize
= buf_size
;
430 size_t glyph_buf_size
= font_glyphs_to_bufsize( &f
, glyphs
);
432 if ( bufsize
&& glyphs
&& bufsize
> glyph_buf_size
)
433 bufsize
= glyph_buf_size
;
437 bufsize
= glyph_buf_size
;
439 bufsize
= MAX_FONT_SIZE
;
441 #ifdef FONT_HARD_LIMIT
442 if ( bufsize
> MAX_FONT_SIZE
)
443 bufsize
= MAX_FONT_SIZE
;
445 if ( bufsize
< (size_t) file_size
)
450 /* check already loaded */
451 int font_id
= find_font_index(path
);
453 if (font_id
> FONT_SYSFIXED
)
455 /* already loaded, no need to reload */
456 struct buflib_alloc_data
*pd
= core_get_data(buflib_allocations
[font_id
]);
457 if (pd
->font
.buffer_size
< bufsize
)
459 int old_refcount
, old_id
;
460 size_t old_bufsize
= pd
->font
.buffer_size
;
463 * 1) save of refcont and id
464 * 2) force unload (set refcount to 1 to make sure it get unloaded)
465 * 3) reload with the larger buffer
466 * 4) restore the id and refcount
469 old_refcount
= pd
->refcount
;
471 font_unload(font_id
);
472 font_id
= font_load_ex(path
, bufsize
, glyphs
);
476 font_id
= font_load_ex(path
, old_bufsize
, 0);
477 /* we couldn't even get the old size, this shouldn't happen */
481 if (old_id
!= font_id
)
483 buflib_allocations
[old_id
] = buflib_allocations
[font_id
];
484 buflib_allocations
[font_id
] = -1;
487 pd
= core_get_data(buflib_allocations
[font_id
]);
488 pd
->refcount
= old_refcount
;
490 /* return error because we didn't satisfy the new buffer size */
494 //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount);
501 for (font_id
= FONT_FIRSTUSERFONT
; font_id
< MAXFONTS
; font_id
++)
503 if (buflib_allocations
[ font_id
] < 0)
509 if ( open_slot
== -1 )
514 int handle
= core_alloc_ex( path
,
515 bufsize
+ sizeof( struct buflib_alloc_data
),
521 struct buflib_alloc_data
*pdata
;
522 pdata
= core_get_data(handle
);
523 pdata
->handle_locks
= 1;
527 struct font
*pf
= pf_from_handle( handle
);
528 memcpy(pf
, &f
, sizeof( struct font
) );
531 pf
->fd_width
= pf
->fd_offset
= -1;
534 pf
->buffer_start
= buffer_from_handle( pf
->handle
);
535 pf
->buffer_position
= pf
->buffer_start
+ FONT_HEADER_SIZE
;
536 pf
->buffer_size
= bufsize
;
537 pf
->buffer_end
= pf
->buffer_start
+ bufsize
;
541 if ( ! font_load_cached( pf
, nwidth
, noffset
) )
547 /* trick to get a small cache for each file section *
548 * during glyph_cache_load() */
549 pf
->fd_width
= open( path
, O_RDONLY
|O_BINARY
);
550 pf
->fd_offset
= open( path
, O_RDONLY
|O_BINARY
);
552 glyph_cache_load( path
, pf
);
554 /* cached font: pf->fd stays open until the font is unloaded */
555 close( pf
->fd_width
);
557 close( pf
->fd_offset
);
562 lseek( fd
, 0, SEEK_SET
);
563 read(fd
, pf
->buffer_start
, pf
->buffer_size
);
568 if ( ! font_load_in_memory( pf
, nwidth
, noffset
) )
574 buflib_allocations
[font_id
] = handle
;
575 //printf("%s -> [%d] -> %d\n", path, font_id, *handle);
576 lock_font_handle( handle
, false );
577 return font_id
; /* success!*/
580 int font_load(const char *path
)
582 return font_load_ex(path
, MAX_FONT_SIZE
, GLYPHS_TO_CACHE
);
585 void font_unload(int font_id
)
587 if ( font_id
< 0 || font_id
>= MAXFONTS
)
589 int handle
= buflib_allocations
[font_id
];
592 struct buflib_alloc_data
*pdata
= core_get_data(handle
);
593 struct font
* pf
= &pdata
->font
;
595 if (pdata
->refcount
< 1)
597 //printf("freeing id: %d %s\n", font_id, core_get_name(*handle));
598 if (pf
&& pf
->fd
>= 0)
600 glyph_cache_save(font_id
);
605 buflib_allocations
[font_id
] = -1;
610 void font_unload_all(void)
613 for (i
=0; i
<MAXFONTS
; i
++)
615 if (buflib_allocations
[i
] > 0)
617 struct buflib_alloc_data
*alloc
= core_get_data(buflib_allocations
[i
]);
618 alloc
->refcount
= 1; /* force unload */
625 * Return a pointer to an incore font structure.
626 * If the requested font isn't loaded/compiled-in,
627 * decrement the font number and try again.
629 struct font
* font_get(int font
)
634 if (font
<= FONT_SYSFIXED
)
638 if (buflib_allocations
[font
] > 0)
640 struct buflib_alloc_data
*alloc
= core_get_data(buflib_allocations
[font
]);
642 if (pf
&& pf
->height
)
651 * Reads an entry into cache entry
654 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
656 struct font
* pf
= callback_data
;
658 unsigned short char_code
= p
->_char_code
;
659 unsigned char tmp
[2];
662 lock_font_handle(pf
->handle
, true);
663 if (pf
->file_width_offset
)
665 int width_offset
= pf
->file_width_offset
+ char_code
;
666 /* load via different fd to get this file section cached */
667 if(pf
->fd_width
>=0 )
671 lseek(fd
, width_offset
, SEEK_SET
);
672 read(fd
, &(p
->width
), 1);
676 p
->width
= pf
->maxwidth
;
679 int32_t bitmap_offset
= 0;
681 if (pf
->file_offset_offset
)
683 int32_t offset
= pf
->file_offset_offset
+ char_code
* (pf
->long_offset
? sizeof(int32_t) : sizeof(int16_t));
684 /* load via different fd to get this file section cached */
685 if(pf
->fd_offset
>=0 )
689 lseek(fd
, offset
, SEEK_SET
);
691 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
692 if (pf
->long_offset
) {
694 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
699 bitmap_offset
= char_code
* glyph_bytes(pf
, p
->width
);
702 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
703 lseek(pf
->fd
, file_offset
, SEEK_SET
);
704 int src_bytes
= glyph_bytes(pf
, p
->width
);
705 read(pf
->fd
, p
->bitmap
, src_bytes
);
707 lock_font_handle(pf
->handle
, false);
711 * Converts cbuf into a font cache
713 static void cache_create(struct font
* pf
)
715 /* maximum size of rotated bitmap */
716 int bitmap_size
= glyph_bytes( pf
, pf
->maxwidth
);
718 /* Initialise cache */
719 font_cache_create(&pf
->cache
, pf
->buffer_start
, pf
->buffer_size
, bitmap_size
);
723 * Returns width of character
725 int font_get_width(struct font
* pf
, unsigned short char_code
)
727 /* check input range*/
728 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
729 char_code
= pf
->defaultchar
;
730 char_code
-= pf
->firstchar
;
732 return (pf
->fd
>= 0 && pf
!= &sysfont
)?
733 font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->width
:
734 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
737 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
739 const unsigned char* bits
;
741 /* check input range*/
742 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
743 char_code
= pf
->defaultchar
;
744 char_code
-= pf
->firstchar
;
746 if (pf
->fd
>= 0 && pf
!= &sysfont
)
749 (unsigned char*)font_cache_get(&pf
->cache
,char_code
,load_cache_entry
, pf
)->bitmap
;
756 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
757 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
759 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
762 bits
+= char_code
* glyph_bytes(pf
, pf
->maxwidth
);
768 static void font_path_to_glyph_path( const char *font_path
, char *glyph_path
)
770 /* take full file name, cut extension, and add .glyphcache */
771 strlcpy(glyph_path
, font_path
, MAX_PATH
);
772 glyph_path
[strlen(glyph_path
)-4] = '\0';
773 strcat(glyph_path
, ".gc");
776 /* call with NULL to flush */
777 static void glyph_file_write(void* data
)
779 struct font_cache_entry
* p
= data
;
780 struct font
* pf
= cache_pf
;
782 static int buffer_pos
= 0;
783 #define WRITE_BUFFER 256
784 static unsigned char buffer
[WRITE_BUFFER
];
786 /* flush buffer & reset */
787 if ( data
== NULL
|| buffer_pos
>= WRITE_BUFFER
)
789 write(cache_fd
, buffer
, buffer_pos
);
794 if ( p
->_char_code
== 0xffff )
797 ch
= p
->_char_code
+ pf
->firstchar
;
798 buffer
[buffer_pos
] = ch
>> 8;
799 buffer
[buffer_pos
+1] = ch
& 0xff;
804 /* save the char codes of the loaded glyphs to a file */
805 static void glyph_cache_save(int font_id
)
811 int handle
= buflib_allocations
[font_id
];
815 struct font
*pf
= pf_from_handle(handle
);
816 if(pf
&& pf
->fd
>= 0)
818 char filename
[MAX_PATH
];
819 font_path_to_glyph_path(font_filename(font_id
), filename
);
820 fd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
826 lru_traverse(&cache_pf
->cache
._lru
, glyph_file_write
);
827 glyph_file_write(NULL
);
838 static int ushortcmp(const void *a
, const void *b
)
840 return ((int)(*(unsigned short*)a
- *(unsigned short*)b
));
842 static void glyph_cache_load(const char *font_path
, struct font
*pf
)
847 unsigned char tmp
[2];
849 unsigned short glyphs
[MAX_SORT
];
850 unsigned short glyphs_lru_order
[MAX_SORT
];
851 int glyph_file_skip
=0, glyph_file_size
=0;
853 int sort_size
= pf
->cache
._capacity
;
854 if ( sort_size
> MAX_SORT
)
855 sort_size
= MAX_SORT
;
857 char filename
[MAX_PATH
];
858 font_path_to_glyph_path(font_path
, filename
);
860 fd
= open(filename
, O_RDONLY
|O_BINARY
);
861 #ifdef TRY_DEFAULT_GLYPHCACHE
862 /* if font specific file fails, try default */
864 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
867 /* only read what fits */
868 glyph_file_size
= filesize( fd
);
869 if ( glyph_file_size
> 2*pf
->cache
._capacity
) {
870 glyph_file_skip
= glyph_file_size
- 2*pf
->cache
._capacity
;
871 lseek( fd
, glyph_file_skip
, SEEK_SET
);
877 read( fd
, tmp
, 2 ) == 2 && size
< sort_size
;
880 glyphs
[size
] = (tmp
[0] << 8) | tmp
[1];
881 glyphs_lru_order
[size
] = glyphs
[size
];
884 /* sort glyphs array to make sector cache happy */
885 qsort((void *)glyphs
, size
, sizeof(unsigned short),
888 /* load font bitmaps */
889 for( i
= 0; i
< size
; i
++ )
890 font_get_bits(pf
, glyphs
[i
]);
892 /* redo to fix lru order */
893 for ( i
= 0; i
< size
; i
++)
894 font_get_bits(pf
, glyphs_lru_order
[i
]);
896 if ( size
< sort_size
)
902 /* load latin1 chars into cache */
903 for ( ch
= 32 ; ch
< 256 && ch
< pf
->cache
._capacity
+ 32; ch
++ )
904 font_get_bits(pf
, ch
);
909 #else /* BOOTLOADER */
915 void font_lock(int font_id
, bool lock
)
922 * Bootloader only supports the built-in sysfont.
924 struct font
* font_get(int font
)
931 * Returns width of character
933 int font_get_width(struct font
* pf
, unsigned short char_code
)
935 /* check input range*/
936 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
937 char_code
= pf
->defaultchar
;
938 char_code
-= pf
->firstchar
;
940 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
943 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
945 const unsigned char* bits
;
947 /* check input range*/
948 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
949 char_code
= pf
->defaultchar
;
950 char_code
-= pf
->firstchar
;
952 /* assume small font with uint16_t offsets*/
953 bits
= pf
->bits
+ (pf
->offset
?
954 ((uint16_t*)(pf
->offset
))[char_code
]:
955 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
960 #endif /* BOOTLOADER */
963 * Returns the stringsize of a given string.
965 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
967 struct font
* pf
= font_get(fontnumber
);
971 font_lock( fontnumber
, true );
972 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
974 if (is_diacritic(ch
, NULL
))
977 /* get proportional width and glyph bits*/
978 width
+= font_get_width(pf
,ch
);
984 font_lock( fontnumber
, false );
988 /* -----------------------------------------------------------------
989 * vim: et sw=4 ts=8 sts=4 tw=78