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
];
92 static struct font
* cache_pf
;
94 static int buflibmove_callback(int handle
, void* current
, void* new)
97 struct buflib_alloc_data
*alloc
= (struct buflib_alloc_data
*)current
;
98 ptrdiff_t diff
= new - current
;
100 if (alloc
->handle_locks
> 0)
101 return BUFLIB_CB_CANNOT_MOVE
;
103 #define UPDATE(x) if (x) { x = PTR_ADD(x, diff); }
105 UPDATE(alloc
->font
.bits
);
106 UPDATE(alloc
->font
.offset
);
107 UPDATE(alloc
->font
.width
);
109 UPDATE(alloc
->font
.buffer_start
);
110 UPDATE(alloc
->font
.buffer_end
);
111 UPDATE(alloc
->font
.buffer_position
);
113 UPDATE(alloc
->font
.cache
._index
);
114 UPDATE(alloc
->font
.cache
._lru
._base
);
118 static void lock_font_handle(int handle
, bool lock
)
120 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
122 alloc
->handle_locks
++;
124 alloc
->handle_locks
--;
127 void font_lock(int font_id
, bool lock
)
129 if( font_id
== FONT_SYSFIXED
)
131 if( buflib_allocations
[font_id
] >= 0 )
132 lock_font_handle(buflib_allocations
[font_id
], lock
);
135 static struct buflib_callbacks buflibops
= {buflibmove_callback
, NULL
};
137 static inline struct font
*pf_from_handle(int handle
)
139 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
140 struct font
*pf
= &alloc
->font
;
144 static inline unsigned char *buffer_from_handle(int handle
)
146 struct buflib_alloc_data
*alloc
= core_get_data(handle
);
147 unsigned char* buffer
= alloc
->buffer
;
151 /* Font cache structures */
152 static void cache_create(struct font
* pf
);
153 static void glyph_cache_load(int fond_id
);
154 /* End Font cache structures */
161 buflib_allocations
[i
++] = -1;
164 /* Check if we have x bytes left in the file buffer */
165 #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
167 /* Helper functions to read big-endian unaligned short or long from
168 the file buffer. Bounds-checking must be done in the calling
172 static short readshort(struct font
*pf
)
176 s
= *pf
->buffer_position
++ & 0xff;
177 s
|= (*pf
->buffer_position
++ << 8);
181 static int32_t readlong(struct font
*pf
)
185 l
= *pf
->buffer_position
++ & 0xff;
186 l
|= *pf
->buffer_position
++ << 8;
187 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 16;
188 l
|= ((uint32_t)(*pf
->buffer_position
++)) << 24;
192 static int glyph_bytes( struct font
*pf
, int width
)
196 ret
= ( pf
->height
* width
+ 1 ) / 2;
198 ret
= width
* ((pf
->height
+ 7) / 8);
199 return (ret
+ 1) & ~1;
202 static struct font
* font_load_header(struct font
*pf
)
204 /* Check we have enough data */
208 /* read magic and version #*/
209 if (memcmp(pf
->buffer_position
, VERSION
, 4) != 0)
212 pf
->buffer_position
+= 4;
215 pf
->maxwidth
= readshort(pf
);
216 pf
->height
= readshort(pf
);
217 pf
->ascent
= readshort(pf
);
218 pf
->depth
= readshort(pf
);
219 pf
->firstchar
= readlong(pf
);
220 pf
->defaultchar
= readlong(pf
);
221 pf
->size
= readlong(pf
);
223 /* get variable font data sizes*/
224 /* # words of bitmap_t*/
225 pf
->bits_size
= readlong(pf
);
229 /* Load memory font */
230 static struct font
* font_load_in_memory(struct font
* pf
)
232 int32_t i
, noffset
, nwidth
;
237 /* # longs of offset*/
238 noffset
= readlong(pf
);
240 /* # bytes of width*/
241 nwidth
= readlong(pf
);
243 /* variable font data*/
244 pf
->bits
= (unsigned char *)pf
->buffer_position
;
245 pf
->buffer_position
+= pf
->bits_size
*sizeof(unsigned char);
247 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
249 /* pad to 16-bit boundary */
250 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
254 /* pad to 32-bit boundary*/
255 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
260 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
263 pf
->offset
= (uint16_t*)pf
->buffer_position
;
265 /* Check we have sufficient buffer */
266 if (!HAVEBYTES(noffset
* sizeof(uint16_t)))
269 for (i
=0; i
<noffset
; ++i
)
271 ((uint16_t*)(pf
->offset
))[i
] = (uint16_t)readshort(pf
);
277 pf
->offset
= (uint16_t*)pf
->buffer_position
;
279 /* Check we have sufficient buffer */
280 if (!HAVEBYTES(noffset
* sizeof(int32_t)))
283 for (i
=0; i
<noffset
; ++i
)
285 ((uint32_t*)(pf
->offset
))[i
] = (uint32_t)readlong(pf
);
293 pf
->width
= (unsigned char *)pf
->buffer_position
;
294 pf
->buffer_position
+= nwidth
*sizeof(unsigned char);
299 if (pf
->buffer_position
> pf
->buffer_end
)
302 return pf
; /* success!*/
305 /* Load cached font */
306 static struct font
* font_load_cached(struct font
* pf
)
308 uint32_t noffset
, nwidth
;
309 unsigned char* oldfileptr
= pf
->buffer_position
;
311 if (!HAVEBYTES(2 * sizeof(int32_t)))
314 /* # longs of offset*/
315 noffset
= readlong(pf
);
317 /* # bytes of width*/
318 nwidth
= readlong(pf
);
320 /* We are now at the bitmap data, this is fixed at 36.. */
323 /* Calculate offset to offset data */
324 pf
->buffer_position
+= pf
->bits_size
* sizeof(unsigned char);
326 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
329 /* pad to 16-bit boundary */
330 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 1) & ~1);
335 /* pad to 32-bit boundary*/
336 pf
->buffer_position
= (unsigned char *)(((intptr_t)pf
->buffer_position
+ 3) & ~3);
340 pf
->file_offset_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
342 pf
->file_offset_offset
= 0;
344 /* Calculate offset to widths data */
345 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
346 pf
->buffer_position
+= noffset
* sizeof(uint16_t);
348 pf
->buffer_position
+= noffset
* sizeof(uint32_t);
351 pf
->file_width_offset
= (uint32_t)(pf
->buffer_position
- pf
->buffer_start
);
353 pf
->file_width_offset
= 0;
355 pf
->buffer_position
= oldfileptr
;
357 /* Create the cache */
363 static bool internal_load_font(int font_id
, const char *path
, char *buf
,
364 size_t buf_size
, int handle
)
367 struct font
* pf
= pf_from_handle(handle
);
369 /* open and read entire font file*/
370 pf
->fd
= open(path
, O_RDONLY
|O_BINARY
);
373 DEBUGF("Can't open font: %s\n", path
);
377 /* Check file size */
378 size
= filesize(pf
->fd
);
379 pf
->buffer_start
= buf
;
380 pf
->buffer_size
= buf_size
;
382 pf
->buffer_position
= buf
;
384 if (size
> pf
->buffer_size
)
386 read(pf
->fd
, pf
->buffer_position
, FONT_HEADER_SIZE
);
387 pf
->buffer_end
= pf
->buffer_position
+ FONT_HEADER_SIZE
;
389 if (!font_load_header(pf
))
391 DEBUGF("Failed font header load");
397 if (!font_load_cached(pf
))
399 DEBUGF("Failed font cache load");
405 /* Cheat to get sector cache for different parts of font *
406 * file while preloading glyphs. Without this the disk head *
407 * thrashes between the width, offset, and bitmap data *
408 * in glyph_cache_load(). */
409 pf
->fd_width
= open(path
, O_RDONLY
|O_BINARY
);
410 pf
->fd_offset
= open(path
, O_RDONLY
|O_BINARY
);
412 glyph_cache_load(font_id
);
414 if(pf
->fd_width
>= 0)
418 if(pf
->fd_offset
>= 0)
419 close(pf
->fd_offset
);
424 read(pf
->fd
, pf
->buffer_position
, pf
->buffer_size
);
425 pf
->buffer_end
= pf
->buffer_position
+ size
;
431 if (!font_load_header(pf
))
433 DEBUGF("Failed font header load");
437 if (!font_load_in_memory(pf
))
439 DEBUGF("Failed mem load");
446 static int find_font_index(const char* path
)
448 int index
= 0, handle
;
450 while (index
< MAXFONTS
)
452 handle
= buflib_allocations
[index
];
453 if (handle
> 0 && !strcmp(core_get_name(handle
), path
))
457 return FONT_SYSFIXED
;
460 static int alloc_and_init(int font_idx
, const char* name
, size_t size
)
462 int *phandle
= &buflib_allocations
[font_idx
];
463 int handle
= *phandle
;
464 struct buflib_alloc_data
*pdata
;
466 size_t alloc_size
= size
+ sizeof(struct buflib_alloc_data
);
469 *phandle
= core_alloc_ex(name
, alloc_size
, &buflibops
);
473 pdata
= core_get_data(handle
);
475 pdata
->handle_locks
= 0;
477 pf
->buffer_position
= pf
->buffer_start
= buffer_from_handle(handle
);
478 pf
->buffer_size
= size
;
484 const char* font_filename(int font_id
)
486 int handle
= buflib_allocations
[font_id
];
488 return core_get_name(handle
);
492 /* read and load font into incore font structure,
493 * returns the font number on success, -1 on failure */
494 int font_load_ex(const char *path
, size_t buffer_size
)
496 int font_id
= find_font_index(path
);
500 if (font_id
> FONT_SYSFIXED
)
502 /* already loaded, no need to reload */
503 struct buflib_alloc_data
*pd
= core_get_data(buflib_allocations
[font_id
]);
504 if (pd
->font
.buffer_size
< buffer_size
)
506 int old_refcount
, old_id
;
508 * 1) save of refcont and id
509 * 2) force unload (set refcount to 1 to make sure it get unloaded)
510 * 3) reload with the larger buffer
511 * 4) restore the id and refcount
514 old_refcount
= pd
->refcount
;
516 font_unload(font_id
);
517 font_id
= font_load_ex(path
, buffer_size
);
520 // not much we can do here, maybe try reloading with the small buffer again
523 if (old_id
!= font_id
)
525 buflib_allocations
[old_id
] = buflib_allocations
[font_id
];
526 buflib_allocations
[font_id
] = -1;
529 pd
= core_get_data(buflib_allocations
[font_id
]);
530 pd
->refcount
= old_refcount
;
533 //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount);
537 for (font_id
= FONT_FIRSTUSERFONT
; font_id
< MAXFONTS
; font_id
++)
539 handle
= buflib_allocations
[font_id
];
545 handle
= alloc_and_init(font_id
, path
, buffer_size
);
549 buffer
= buffer_from_handle(handle
);
550 lock_font_handle(handle
, true);
552 if (!internal_load_font(font_id
, path
, buffer
, buffer_size
, handle
))
554 lock_font_handle(handle
, false);
556 buflib_allocations
[font_id
] = -1;
560 lock_font_handle(handle
, false);
561 buflib_allocations
[font_id
] = handle
;
562 //printf("%s -> [%d] -> %d\n", path, font_id, *handle);
563 return font_id
; /* success!*/
565 int font_load(const char *path
)
568 int fd
= open( path
, O_RDONLY
);
572 if (size
> MAX_FONT_SIZE
)
573 size
= MAX_FONT_SIZE
;
575 return font_load_ex(path
, size
);
578 void font_unload(int font_id
)
580 if ( font_id
== FONT_SYSFIXED
)
582 int handle
= buflib_allocations
[font_id
];
585 struct buflib_alloc_data
*pdata
= core_get_data(handle
);
586 struct font
* pf
= &pdata
->font
;
588 if (pdata
->refcount
< 1)
590 //printf("freeing id: %d %s\n", font_id, core_get_name(*handle));
591 if (pf
&& pf
->fd
>= 0)
593 glyph_cache_save(font_id
);
598 buflib_allocations
[font_id
] = -1;
603 void font_unload_all(void)
606 for (i
=0; i
<MAXFONTS
; i
++)
608 if (buflib_allocations
[i
] > 0)
610 struct buflib_alloc_data
*alloc
= core_get_data(buflib_allocations
[i
]);
611 alloc
->refcount
= 1; /* force unload */
618 * Return a pointer to an incore font structure.
619 * If the requested font isn't loaded/compiled-in,
620 * decrement the font number and try again.
622 struct font
* font_get(int font
)
627 if (font
<= FONT_SYSFIXED
)
631 if (buflib_allocations
[font
] > 0)
633 struct buflib_alloc_data
*alloc
= core_get_data(buflib_allocations
[font
]);
635 if (pf
&& pf
->height
)
643 static int pf_to_handle(struct font
* pf
)
646 for (i
=0; i
<MAXFONTS
; i
++)
648 int handle
= buflib_allocations
[i
];
651 struct buflib_alloc_data
*pdata
= core_get_data(handle
);
652 if (pf
== &pdata
->font
)
660 * Reads an entry into cache entry
663 load_cache_entry(struct font_cache_entry
* p
, void* callback_data
)
665 struct font
* pf
= callback_data
;
666 int handle
= pf_to_handle(pf
);
667 unsigned short char_code
= p
->_char_code
;
668 unsigned char tmp
[2];
672 lock_font_handle(handle
, true);
673 if (pf
->file_width_offset
)
675 int width_offset
= pf
->file_width_offset
+ char_code
;
676 /* load via different fd to get this file section cached */
677 if(pf
->fd_width
>=0 )
681 lseek(fd
, width_offset
, SEEK_SET
);
682 read(fd
, &(p
->width
), 1);
686 p
->width
= pf
->maxwidth
;
689 int32_t bitmap_offset
= 0;
691 if (pf
->file_offset_offset
)
693 int32_t offset
= pf
->file_offset_offset
+ char_code
* (pf
->long_offset
? sizeof(int32_t) : sizeof(int16_t));
694 /* load via different fd to get this file section cached */
695 if(pf
->fd_offset
>=0 )
699 lseek(fd
, offset
, SEEK_SET
);
701 bitmap_offset
= tmp
[0] | (tmp
[1] << 8);
702 if (pf
->long_offset
) {
704 bitmap_offset
|= (tmp
[0] << 16) | (tmp
[1] << 24);
709 bitmap_offset
= char_code
* glyph_bytes(pf
, p
->width
);
712 int32_t file_offset
= FONT_HEADER_SIZE
+ bitmap_offset
;
713 lseek(pf
->fd
, file_offset
, SEEK_SET
);
714 int src_bytes
= glyph_bytes(pf
, p
->width
);
715 read(pf
->fd
, p
->bitmap
, src_bytes
);
718 lock_font_handle(handle
, false);
722 * Converts cbuf into a font cache
724 static void cache_create(struct font
* pf
)
726 /* maximum size of rotated bitmap */
727 int bitmap_size
= glyph_bytes( pf
, pf
->maxwidth
);
729 /* Initialise cache */
730 font_cache_create(&pf
->cache
, pf
->buffer_start
, pf
->buffer_size
, bitmap_size
);
734 * Returns width of character
736 int font_get_width(struct font
* pf
, unsigned short char_code
)
738 /* check input range*/
739 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
740 char_code
= pf
->defaultchar
;
741 char_code
-= pf
->firstchar
;
743 return (pf
->fd
>= 0 && pf
!= &sysfont
)?
744 font_cache_get(&pf
->cache
,char_code
,load_cache_entry
,pf
)->width
:
745 pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
748 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
750 const unsigned char* bits
;
752 /* check input range*/
753 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
754 char_code
= pf
->defaultchar
;
755 char_code
-= pf
->firstchar
;
757 if (pf
->fd
>= 0 && pf
!= &sysfont
)
760 (unsigned char*)font_cache_get(&pf
->cache
,char_code
,load_cache_entry
, pf
)->bitmap
;
767 if (pf
->bits_size
< MAX_FONTSIZE_FOR_16_BIT_OFFSETS
)
768 bits
+= ((uint16_t*)(pf
->offset
))[char_code
];
770 bits
+= ((uint32_t*)(pf
->offset
))[char_code
];
773 bits
+= char_code
* glyph_bytes(pf
, pf
->maxwidth
);
779 static void font_path_to_glyph_path( const char *font_path
, char *glyph_path
)
781 /* take full file name, cut extension, and add .glyphcache */
782 strlcpy(glyph_path
, font_path
, MAX_PATH
);
783 glyph_path
[strlen(glyph_path
)-4] = '\0';
784 strcat(glyph_path
, ".gc");
787 /* call with NULL to flush */
788 static void glyph_file_write(void* data
)
790 struct font_cache_entry
* p
= data
;
791 struct font
* pf
= cache_pf
;
793 static int buffer_pos
= 0;
794 #define WRITE_BUFFER 256
795 static unsigned char buffer
[WRITE_BUFFER
];
797 /* flush buffer & reset */
798 if ( data
== NULL
|| buffer_pos
>= WRITE_BUFFER
)
800 write(cache_fd
, buffer
, buffer_pos
);
805 if ( p
->_char_code
== 0xffff )
808 ch
= p
->_char_code
+ pf
->firstchar
;
809 buffer
[buffer_pos
] = ch
>> 8;
810 buffer
[buffer_pos
+1] = ch
& 0xff;
815 /* save the char codes of the loaded glyphs to a file */
816 void glyph_cache_save(int font_id
)
822 int handle
= buflib_allocations
[font_id
];
826 struct font
*pf
= pf_from_handle(handle
);
827 if(pf
&& pf
->fd
>= 0)
829 /* FIXME: This sleep should not be necessary but without it *
830 * unloading multiple fonts and saving glyphcache files *
831 * quickly in succession creates multiple glyphcache files *
832 * with the same name. */
834 char filename
[MAX_PATH
];
835 font_path_to_glyph_path(font_filename(font_id
), filename
);
836 fd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
842 lru_traverse(&cache_pf
->cache
._lru
, glyph_file_write
);
843 glyph_file_write(NULL
);
853 int font_glyphs_to_bufsize(const char *path
, int glyphs
)
857 char buf
[FONT_HEADER_SIZE
];
859 f
.buffer_start
= buf
;
860 f
.buffer_size
= sizeof(buf
);
861 f
.buffer_position
= buf
;
863 f
.fd
= open(path
, O_RDONLY
|O_BINARY
);
867 read(f
.fd
, f
.buffer_position
, FONT_HEADER_SIZE
);
868 f
.buffer_end
= f
.buffer_position
+ FONT_HEADER_SIZE
;
870 if( !font_load_header(&f
) )
877 bufsize
= LRU_SLOT_OVERHEAD
+ sizeof(struct font_cache_entry
) +
878 sizeof( unsigned short);
879 bufsize
+= glyph_bytes(&f
, f
.maxwidth
);
881 if ( bufsize
< FONT_HEADER_SIZE
)
882 bufsize
= FONT_HEADER_SIZE
;
886 static int ushortcmp(const void *a
, const void *b
)
888 return ((int)(*(unsigned short*)a
- *(unsigned short*)b
));
890 static void glyph_cache_load(int font_id
)
892 int handle
= buflib_allocations
[font_id
];
895 struct font
*pf
= pf_from_handle(handle
);
899 unsigned char tmp
[2];
901 unsigned short glyphs
[MAX_SORT
];
902 unsigned short glyphs_lru_order
[MAX_SORT
];
903 int glyph_file_skip
=0, glyph_file_size
=0;
905 int sort_size
= pf
->cache
._capacity
;
906 if ( sort_size
> MAX_SORT
)
907 sort_size
= MAX_SORT
;
909 char filename
[MAX_PATH
];
910 font_path_to_glyph_path(font_filename(font_id
), filename
);
912 fd
= open(filename
, O_RDONLY
|O_BINARY
);
913 #ifdef TRY_DEFAULT_GLYPHCACHE
914 /* if font specific file fails, try default */
916 fd
= open(GLYPH_CACHE_FILE
, O_RDONLY
|O_BINARY
);
919 /* only read what fits */
920 glyph_file_size
= filesize( fd
);
921 if ( glyph_file_size
> 2*pf
->cache
._capacity
) {
922 glyph_file_skip
= glyph_file_size
- 2*pf
->cache
._capacity
;
923 lseek( fd
, glyph_file_skip
, SEEK_SET
);
929 read( fd
, tmp
, 2 ) == 2 && size
< sort_size
;
932 glyphs
[size
] = (tmp
[0] << 8) | tmp
[1];
933 glyphs_lru_order
[size
] = glyphs
[size
];
936 /* sort glyphs array to make sector cache happy */
937 qsort((void *)glyphs
, size
, sizeof(unsigned short),
940 /* load font bitmaps */
941 for( i
= 0; i
< size
; i
++ )
942 font_get_bits(pf
, glyphs
[i
]);
944 /* redo to fix lru order */
945 for ( i
= 0; i
< size
; i
++)
946 font_get_bits(pf
, glyphs_lru_order
[i
]);
948 if ( size
< sort_size
)
954 /* load latin1 chars into cache */
955 for ( ch
= 32 ; ch
< 256 && ch
< pf
->cache
._capacity
+ 32; ch
++ )
956 font_get_bits(pf
, ch
);
961 #else /* BOOTLOADER */
967 void font_lock(int font_id
, bool lock
)
974 * Bootloader only supports the built-in sysfont.
976 struct font
* font_get(int font
)
983 * Returns width of character
985 int font_get_width(struct font
* pf
, unsigned short char_code
)
987 /* check input range*/
988 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
989 char_code
= pf
->defaultchar
;
990 char_code
-= pf
->firstchar
;
992 return pf
->width
? pf
->width
[char_code
]: pf
->maxwidth
;
995 const unsigned char* font_get_bits(struct font
* pf
, unsigned short char_code
)
997 const unsigned char* bits
;
999 /* check input range*/
1000 if (char_code
< pf
->firstchar
|| char_code
>= pf
->firstchar
+pf
->size
)
1001 char_code
= pf
->defaultchar
;
1002 char_code
-= pf
->firstchar
;
1004 /* assume small font with uint16_t offsets*/
1005 bits
= pf
->bits
+ (pf
->offset
?
1006 ((uint16_t*)(pf
->offset
))[char_code
]:
1007 (((pf
->height
+ 7) / 8) * pf
->maxwidth
* char_code
));
1012 #endif /* BOOTLOADER */
1015 * Returns the stringsize of a given string.
1017 int font_getstringsize(const unsigned char *str
, int *w
, int *h
, int fontnumber
)
1019 struct font
* pf
= font_get(fontnumber
);
1023 font_lock( fontnumber
, true );
1024 for (str
= utf8decode(str
, &ch
); ch
!= 0 ; str
= utf8decode(str
, &ch
))
1026 if (is_diacritic(ch
, NULL
))
1029 /* get proportional width and glyph bits*/
1030 width
+= font_get_width(pf
,ch
);
1036 font_lock( fontnumber
, false );
1040 /* -----------------------------------------------------------------
1041 * vim: et sw=4 ts=8 sts=4 tw=78