Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (c) 2002 by Greg Haerr <greg@censoft.com> |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 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. |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | /* |
| 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. |
| 26 | */ |
| 27 | #include "config.h" |
| 28 | |
| 29 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) |
| 30 | |
| 31 | #include <stdio.h> |
| 32 | #include <string.h> |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 33 | #include "inttypes.h" |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 34 | #include "lcd.h" |
| 35 | #include "font.h" |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 36 | #include "file.h" |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 37 | #include "debug.h" |
| 38 | #include "panic.h" |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 39 | #include "rbunicode.h" |
| 40 | /* Font cache includes */ |
| 41 | #include "font_cache.h" |
| 42 | #include "lru.h" |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 43 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 44 | #ifndef O_BINARY |
| 45 | #define O_BINARY 0 |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 46 | #endif |
Daniel Stenberg | 0a1c221 | 2002-09-13 06:37:49 +0000 | [diff] [blame] | 47 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 48 | /* compiled-in font */ |
| 49 | extern struct font sysfont; |
| 50 | |
| 51 | /* structure filled in by font_load */ |
| 52 | static struct font font_ui; |
| 53 | |
| 54 | /* system font table, in order of FONT_xxx definition */ |
Jens Arnold | 2b0694c | 2004-08-03 05:58:46 +0000 | [diff] [blame] | 55 | static struct font* const sysfonts[MAXFONTS] = { &sysfont, &font_ui }; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 56 | |
| 57 | /* static buffer allocation structures */ |
| 58 | static unsigned char mbuf[MAX_FONT_SIZE]; |
| 59 | static unsigned char *freeptr = mbuf; |
| 60 | static unsigned char *fileptr; |
| 61 | static unsigned char *eofptr; |
| 62 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 63 | /* Font cache structures */ |
| 64 | static struct font_cache font_cache_ui; |
| 65 | static int fnt_file = -1; /* >=0 if font is cached */ |
Bertrik Sikken | db2d61f | 2008-04-20 10:24:15 +0000 | [diff] [blame] | 66 | static uint32_t file_width_offset; /* offset to file width data */ |
| 67 | static uint32_t file_offset_offset; /* offset to file offset data */ |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 68 | static void cache_create(int maxwidth, int height); |
| 69 | static int long_offset = 0; |
| 70 | static int glyph_file; |
| 71 | /* End Font cache structures */ |
| 72 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 73 | static void glyph_cache_load(void); |
| 74 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 75 | void font_init(void) |
| 76 | { |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 77 | memset(&font_ui, 0, sizeof(struct font)); |
| 78 | } |
| 79 | |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 80 | /* Check if we have x bytes left in the file buffer */ |
| 81 | #define HAVEBYTES(x) (fileptr + (x) <= eofptr) |
| 82 | |
| 83 | /* Helper functions to read big-endian unaligned short or long from |
| 84 | the file buffer. Bounds-checking must be done in the calling |
| 85 | function. |
| 86 | */ |
| 87 | |
| 88 | static short readshort(void) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 89 | { |
| 90 | unsigned short s; |
| 91 | |
| 92 | s = *fileptr++ & 0xff; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 93 | s |= (*fileptr++ << 8); |
| 94 | return s; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 95 | } |
| 96 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 97 | static int32_t readlong(void) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 98 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 99 | uint32_t l; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 100 | |
| 101 | l = *fileptr++ & 0xff; |
| 102 | l |= *fileptr++ << 8; |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 103 | l |= ((uint32_t)(*fileptr++)) << 16; |
| 104 | l |= ((uint32_t)(*fileptr++)) << 24; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 105 | return l; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | /* read count bytes*/ |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 109 | static void readstr(char *buf, int count) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 110 | { |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 111 | while (count--) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 112 | *buf++ = *fileptr++; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 113 | } |
| 114 | |
Björn Stenberg | 227253c | 2002-10-09 23:13:25 +0000 | [diff] [blame] | 115 | void font_reset(void) |
| 116 | { |
| 117 | memset(&font_ui, 0, sizeof(struct font)); |
| 118 | } |
| 119 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 120 | static struct font* font_load_header(struct font *pf) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 121 | { |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 122 | char version[4+1]; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 123 | |
| 124 | /* Check we have enough data */ |
| 125 | if (!HAVEBYTES(28)) |
| 126 | return NULL; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 127 | |
| 128 | /* read magic and version #*/ |
| 129 | memset(version, 0, sizeof(version)); |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 130 | readstr(version, 4); |
| 131 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 132 | if (strcmp(version, VERSION) != 0) |
| 133 | return NULL; |
| 134 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 135 | /* font info*/ |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 136 | pf->maxwidth = readshort(); |
| 137 | pf->height = readshort(); |
| 138 | pf->ascent = readshort(); |
| 139 | fileptr += 2; /* Skip padding */ |
| 140 | pf->firstchar = readlong(); |
| 141 | pf->defaultchar = readlong(); |
| 142 | pf->size = readlong(); |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 143 | |
| 144 | /* get variable font data sizes*/ |
| 145 | /* # words of bitmap_t*/ |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 146 | pf->bits_size = readlong(); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 147 | |
| 148 | return pf; |
| 149 | } |
| 150 | /* Load memory font */ |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 151 | static struct font* font_load_in_memory(struct font* pf) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 152 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 153 | int32_t i, noffset, nwidth; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 154 | |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 155 | if (!HAVEBYTES(4)) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 156 | return NULL; |
| 157 | |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 158 | /* # longs of offset*/ |
| 159 | noffset = readlong(); |
| 160 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 161 | /* # bytes of width*/ |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 162 | nwidth = readlong(); |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 163 | |
| 164 | /* variable font data*/ |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 165 | pf->bits = (unsigned char *)fileptr; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 166 | fileptr += pf->bits_size*sizeof(unsigned char); |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 167 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 168 | if ( pf->bits_size < 0xFFDB ) |
| 169 | { |
| 170 | /* pad to 16-bit boundary */ |
Nils Wallménius | 9789acc | 2007-06-30 18:09:46 +0000 | [diff] [blame] | 171 | fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 172 | } |
| 173 | else |
| 174 | { |
| 175 | /* pad to 32-bit boundary*/ |
Nils Wallménius | 9789acc | 2007-06-30 18:09:46 +0000 | [diff] [blame] | 176 | fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 177 | } |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 178 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 179 | if (noffset) |
| 180 | { |
| 181 | if ( pf->bits_size < 0xFFDB ) |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 182 | { |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 183 | long_offset = 0; |
| 184 | pf->offset = (unsigned short *)fileptr; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 185 | |
| 186 | /* Check we have sufficient buffer */ |
| 187 | if (!HAVEBYTES(noffset * sizeof(short))) |
| 188 | return NULL; |
| 189 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 190 | for (i=0; i<noffset; ++i) |
| 191 | { |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 192 | ((unsigned short*)(pf->offset))[i] = (unsigned short)readshort(); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 193 | } |
| 194 | } |
| 195 | else |
| 196 | { |
| 197 | long_offset = 1; |
| 198 | pf->offset = (unsigned short *)fileptr; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 199 | |
| 200 | /* Check we have sufficient buffer */ |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 201 | if (!HAVEBYTES(noffset * sizeof(int32_t))) |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 202 | return NULL; |
| 203 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 204 | for (i=0; i<noffset; ++i) |
| 205 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 206 | ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 207 | } |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 208 | } |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 209 | } |
| 210 | else |
| 211 | pf->offset = NULL; |
| 212 | |
| 213 | if (nwidth) { |
| 214 | pf->width = (unsigned char *)fileptr; |
| 215 | fileptr += nwidth*sizeof(unsigned char); |
| 216 | } |
| 217 | else |
| 218 | pf->width = NULL; |
| 219 | |
| 220 | if (fileptr > eofptr) |
| 221 | return NULL; |
| 222 | |
Jens Arnold | 6dc88dc | 2004-05-14 23:08:08 +0000 | [diff] [blame] | 223 | return pf; /* success!*/ |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 224 | } |
| 225 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 226 | /* Load cached font */ |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 227 | static struct font* font_load_cached(struct font* pf) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 228 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 229 | uint32_t noffset, nwidth; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 230 | unsigned char* oldfileptr = fileptr; |
| 231 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 232 | if (!HAVEBYTES(2 * sizeof(int32_t))) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 233 | return NULL; |
| 234 | |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 235 | /* # longs of offset*/ |
| 236 | noffset = readlong(); |
| 237 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 238 | /* # bytes of width*/ |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 239 | nwidth = readlong(); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 240 | |
| 241 | /* We are now at the bitmap data, this is fixed at 36.. */ |
| 242 | pf->bits = NULL; |
| 243 | |
| 244 | /* Calculate offset to offset data */ |
| 245 | fileptr += pf->bits_size * sizeof(unsigned char); |
| 246 | |
| 247 | if ( pf->bits_size < 0xFFDB ) |
| 248 | { |
| 249 | long_offset = 0; |
| 250 | /* pad to 16-bit boundary */ |
Nils Wallménius | 9789acc | 2007-06-30 18:09:46 +0000 | [diff] [blame] | 251 | fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 252 | } |
| 253 | else |
| 254 | { |
| 255 | long_offset = 1; |
| 256 | /* pad to 32-bit boundary*/ |
Nils Wallménius | 9789acc | 2007-06-30 18:09:46 +0000 | [diff] [blame] | 257 | fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 258 | } |
| 259 | |
| 260 | if (noffset) |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 261 | file_offset_offset = (uint32_t)(fileptr - freeptr); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 262 | else |
| 263 | file_offset_offset = 0; |
| 264 | |
| 265 | /* Calculate offset to widths data */ |
| 266 | if ( pf->bits_size < 0xFFDB ) |
| 267 | fileptr += noffset * sizeof(unsigned short); |
| 268 | else |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 269 | fileptr += noffset * sizeof(uint32_t); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 270 | |
| 271 | if (nwidth) |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 272 | file_width_offset = (uint32_t)(fileptr - freeptr); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 273 | else |
| 274 | file_width_offset = 0; |
| 275 | |
| 276 | fileptr = oldfileptr; |
| 277 | |
| 278 | /* Create the cache */ |
| 279 | cache_create(pf->maxwidth, pf->height); |
| 280 | |
| 281 | return pf; |
| 282 | } |
| 283 | |
| 284 | /* read and load font into incore font structure*/ |
| 285 | struct font* font_load(const char *path) |
| 286 | { |
Frank Dischner | bf64c45 | 2006-04-24 16:02:44 +0000 | [diff] [blame] | 287 | int size; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 288 | struct font* pf = &font_ui; |
| 289 | |
| 290 | /* save loaded glyphs */ |
| 291 | glyph_cache_save(); |
| 292 | |
| 293 | /* Close font file handle */ |
| 294 | if (fnt_file >= 0) |
| 295 | close(fnt_file); |
| 296 | |
| 297 | /* open and read entire font file*/ |
| 298 | fnt_file = open(path, O_RDONLY|O_BINARY); |
| 299 | |
| 300 | if (fnt_file < 0) { |
| 301 | DEBUGF("Can't open font: %s\n", path); |
| 302 | return NULL; |
| 303 | } |
| 304 | |
| 305 | /* Check file size */ |
Frank Dischner | bf64c45 | 2006-04-24 16:02:44 +0000 | [diff] [blame] | 306 | size = filesize(fnt_file); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 307 | |
| 308 | font_reset(); |
| 309 | |
| 310 | /* currently, font loading replaces earlier font allocation*/ |
Jens Arnold | 8ab2cb5 | 2007-10-02 17:04:56 +0000 | [diff] [blame] | 311 | freeptr = (unsigned char *)(((intptr_t)mbuf + 3) & ~3); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 312 | fileptr = freeptr; |
| 313 | |
| 314 | |
Frank Dischner | bf64c45 | 2006-04-24 16:02:44 +0000 | [diff] [blame] | 315 | if (size > MAX_FONT_SIZE) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 316 | { |
| 317 | read(fnt_file, fileptr, FONT_HEADER_SIZE); |
| 318 | eofptr = fileptr + FONT_HEADER_SIZE; |
| 319 | |
| 320 | if (!font_load_header(pf)) |
| 321 | { |
| 322 | DEBUGF("Failed font header load"); |
| 323 | return NULL; |
| 324 | } |
| 325 | |
| 326 | if (!font_load_cached(pf)) |
| 327 | { |
| 328 | DEBUGF("Failed font cache load"); |
| 329 | return NULL; |
| 330 | } |
| 331 | |
| 332 | glyph_cache_load(); |
| 333 | } |
| 334 | else |
| 335 | { |
| 336 | read(fnt_file, fileptr, MAX_FONT_SIZE); |
Frank Dischner | bf64c45 | 2006-04-24 16:02:44 +0000 | [diff] [blame] | 337 | eofptr = fileptr + size; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 338 | close(fnt_file); |
| 339 | fnt_file = -1; |
| 340 | |
| 341 | if (!font_load_header(pf)) |
| 342 | { |
| 343 | DEBUGF("Failed font header load"); |
| 344 | return NULL; |
| 345 | } |
| 346 | |
| 347 | if (!font_load_in_memory(pf)) |
| 348 | { |
| 349 | DEBUGF("Failed mem load"); |
| 350 | return NULL; |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | /* no need for multiple font loads currently*/ |
| 355 | /*freeptr += filesize;*/ |
| 356 | /*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/ |
| 357 | |
| 358 | return pf; /* success!*/ |
| 359 | } |
| 360 | |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 361 | /* |
| 362 | * Return a pointer to an incore font structure. |
| 363 | * If the requested font isn't loaded/compiled-in, |
| 364 | * decrement the font number and try again. |
| 365 | */ |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 366 | struct font* font_get(int font) |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 367 | { |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 368 | struct font* pf; |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 369 | |
Eric Linenberg | 038df5c | 2002-09-16 03:18:49 +0000 | [diff] [blame] | 370 | if (font >= MAXFONTS) |
| 371 | font = 0; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 372 | |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 373 | while (1) { |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 374 | pf = sysfonts[font]; |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 375 | if (pf && pf->height) |
| 376 | return pf; |
| 377 | if (--font < 0) |
| 378 | panicf("No font!"); |
| 379 | } |
| 380 | } |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 381 | /* |
| 382 | * Returns the stringsize of a given string. |
| 383 | */ |
| 384 | int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber) |
| 385 | { |
| 386 | struct font* pf = font_get(fontnumber); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 387 | unsigned short ch; |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 388 | int width = 0; |
| 389 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 390 | for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch)) |
| 391 | { |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 392 | |
| 393 | /* get proportional width and glyph bits*/ |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 394 | width += font_get_width(pf,ch); |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 395 | } |
| 396 | if ( w ) |
| 397 | *w = width; |
| 398 | if ( h ) |
| 399 | *h = pf->height; |
| 400 | return width; |
| 401 | } |
| 402 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 403 | /* |
| 404 | * Reads an entry into cache entry |
| 405 | */ |
| 406 | static void |
| 407 | load_cache_entry(struct font_cache_entry* p, void* callback_data) |
| 408 | { |
| 409 | struct font* pf = callback_data; |
| 410 | unsigned short char_code = p->_char_code; |
| 411 | unsigned char tmp[2]; |
| 412 | |
| 413 | if (file_width_offset) |
| 414 | { |
| 415 | int width_offset = file_width_offset + char_code; |
| 416 | lseek(fnt_file, width_offset, SEEK_SET); |
| 417 | read(fnt_file, &(p->width), 1); |
| 418 | } |
| 419 | else |
| 420 | { |
| 421 | p->width = pf->maxwidth; |
| 422 | } |
| 423 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 424 | int32_t bitmap_offset = 0; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 425 | |
| 426 | if (file_offset_offset) |
| 427 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 428 | int32_t offset = file_offset_offset + char_code * (long_offset ? sizeof(int32_t) : sizeof(short)); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 429 | lseek(fnt_file, offset, SEEK_SET); |
| 430 | read (fnt_file, tmp, 2); |
| 431 | bitmap_offset = tmp[0] | (tmp[1] << 8); |
| 432 | if (long_offset) { |
| 433 | read (fnt_file, tmp, 2); |
| 434 | bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); |
| 435 | } |
| 436 | } |
| 437 | else |
| 438 | { |
| 439 | bitmap_offset = ((pf->height + 7) / 8) * p->width * char_code; |
| 440 | } |
| 441 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 442 | int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 443 | lseek(fnt_file, file_offset, SEEK_SET); |
| 444 | |
| 445 | int src_bytes = p->width * ((pf->height + 7) / 8); |
| 446 | read(fnt_file, p->bitmap, src_bytes); |
| 447 | } |
| 448 | |
| 449 | /* |
| 450 | * Converts cbuf into a font cache |
| 451 | */ |
| 452 | static void cache_create(int maxwidth, int height) |
| 453 | { |
| 454 | /* maximum size of rotated bitmap */ |
| 455 | int bitmap_size = maxwidth * ((height + 7) / 8); |
| 456 | |
| 457 | /* Initialise cache */ |
| 458 | font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); |
| 459 | } |
| 460 | |
| 461 | /* |
| 462 | * Returns width of character |
| 463 | */ |
| 464 | int font_get_width(struct font* pf, unsigned short char_code) |
| 465 | { |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 466 | /* check input range*/ |
| 467 | if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) |
| 468 | char_code = pf->defaultchar; |
| 469 | char_code -= pf->firstchar; |
| 470 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 471 | return (fnt_file >= 0 && pf != &sysfont)? |
| 472 | font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->width: |
| 473 | pf->width? pf->width[char_code]: pf->maxwidth; |
| 474 | } |
| 475 | |
| 476 | const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) |
| 477 | { |
| 478 | const unsigned char* bits; |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 479 | |
| 480 | /* check input range*/ |
| 481 | if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) |
| 482 | char_code = pf->defaultchar; |
| 483 | char_code -= pf->firstchar; |
| 484 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 485 | if (fnt_file >= 0 && pf != &sysfont) |
| 486 | { |
| 487 | bits = |
| 488 | (unsigned char*)font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->bitmap; |
| 489 | } |
| 490 | else |
| 491 | { |
| 492 | bits = pf->bits + (pf->offset? |
| 493 | pf->offset[char_code]: |
| 494 | (((pf->height + 7) / 8) * pf->maxwidth * char_code)); |
| 495 | } |
| 496 | |
| 497 | return bits; |
| 498 | } |
| 499 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 500 | static void glyph_file_write(void* data) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 501 | { |
| 502 | struct font_cache_entry* p = data; |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 503 | struct font* pf = &font_ui; |
| 504 | unsigned short ch; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 505 | unsigned char tmp[2]; |
| 506 | |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 507 | ch = p->_char_code + pf->firstchar; |
| 508 | |
| 509 | if (ch != 0xffff && glyph_file >= 0) { |
| 510 | tmp[0] = ch >> 8; |
| 511 | tmp[1] = ch & 0xff; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 512 | if (write(glyph_file, tmp, 2) != 2) { |
| 513 | close(glyph_file); |
| 514 | glyph_file = -1; |
| 515 | } |
| 516 | } |
| 517 | return; |
| 518 | } |
| 519 | |
| 520 | /* save the char codes of the loaded glyphs to a file */ |
| 521 | void glyph_cache_save(void) |
| 522 | { |
| 523 | |
| 524 | if (fnt_file >= 0) { |
| 525 | |
Jens Arnold | 67eb154 | 2007-02-01 23:08:15 +0000 | [diff] [blame] | 526 | glyph_file = creat(GLYPH_CACHE_FILE); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 527 | |
| 528 | if (glyph_file < 0) return; |
| 529 | |
| 530 | lru_traverse(&font_cache_ui._lru, glyph_file_write); |
| 531 | |
| 532 | if (glyph_file >= 0) |
| 533 | close(glyph_file); |
| 534 | } |
| 535 | return; |
| 536 | } |
| 537 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 538 | static void glyph_cache_load(void) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 539 | { |
| 540 | if (fnt_file >= 0) { |
| 541 | |
| 542 | int fd; |
| 543 | unsigned char tmp[2]; |
| 544 | unsigned short ch; |
| 545 | struct font* pf = &font_ui; |
| 546 | |
| 547 | fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); |
| 548 | |
| 549 | if (fd >= 0) { |
| 550 | |
| 551 | while (read(fd, tmp, 2) == 2) { |
| 552 | ch = (tmp[0] << 8) | tmp[1]; |
| 553 | font_get_bits(pf, ch); |
| 554 | } |
| 555 | |
| 556 | close(fd); |
| 557 | } else { |
| 558 | /* load latin1 chars into cache */ |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 559 | ch = 256; |
| 560 | while (ch-- > 32) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 561 | font_get_bits(pf, ch); |
| 562 | } |
| 563 | } |
| 564 | return; |
| 565 | } |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 566 | |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 567 | #endif /* HAVE_LCD_BITMAP */ |
| 568 | |
| 569 | /* ----------------------------------------------------------------- |
Eric Linenberg | 038df5c | 2002-09-16 03:18:49 +0000 | [diff] [blame] | 570 | * vim: et sw=4 ts=8 sts=4 tw=78 |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 571 | */ |