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 | */ |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 27 | #include <stdio.h> |
| 28 | #include <string.h> |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 29 | #include <stdlib.h> |
Thomas Martitz | 281d1fa | 2014-01-05 01:22:19 +0100 | [diff] [blame] | 30 | #include <stdint.h> |
| 31 | #include <stddef.h> |
| 32 | |
| 33 | #include "config.h" |
Michael Sparmann | 751303c | 2011-02-27 22:44:30 +0000 | [diff] [blame] | 34 | #include "system.h" |
Thomas Martitz | 281d1fa | 2014-01-05 01:22:19 +0100 | [diff] [blame] | 35 | #include "kernel.h" |
| 36 | #include "lcd.h" |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 37 | #include "font.h" |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 38 | #include "file.h" |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 39 | #include "core_alloc.h" |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 40 | #include "debug.h" |
| 41 | #include "panic.h" |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 42 | #include "rbunicode.h" |
Tomer Shalev | 7682cb5 | 2009-11-24 20:41:42 +0000 | [diff] [blame] | 43 | #include "diacritic.h" |
Thomas Martitz | 9c0b247 | 2010-08-01 16:15:27 +0000 | [diff] [blame] | 44 | #include "rbpaths.h" |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 45 | |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 46 | #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB |
| 47 | |
| 48 | /* max static loadable font buffer size */ |
| 49 | #ifndef MAX_FONT_SIZE |
| 50 | #if LCD_HEIGHT > 64 |
Andree Buschmann | 5d849a9 | 2011-02-02 17:43:32 +0000 | [diff] [blame] | 51 | #if MEMORYSIZE > 2 |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 52 | #define MAX_FONT_SIZE 60000 |
| 53 | #else |
| 54 | #define MAX_FONT_SIZE 10000 |
| 55 | #endif |
| 56 | #else |
| 57 | #define MAX_FONT_SIZE 4000 |
| 58 | #endif |
| 59 | #endif |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 60 | #define GLYPHS_TO_CACHE 256 |
| 61 | |
| 62 | #if MEMORYSIZE < 4 |
| 63 | #define FONT_HARD_LIMIT |
| 64 | #endif |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 65 | |
| 66 | #ifndef FONT_HEADER_SIZE |
| 67 | #define FONT_HEADER_SIZE 36 |
| 68 | #endif |
| 69 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 70 | #ifndef BOOTLOADER |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 71 | /* Font cache includes */ |
| 72 | #include "font_cache.h" |
| 73 | #include "lru.h" |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 74 | #endif |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 75 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 76 | #ifndef O_BINARY |
| 77 | #define O_BINARY 0 |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 78 | #endif |
Daniel Stenberg | 0a1c221 | 2002-09-13 06:37:49 +0000 | [diff] [blame] | 79 | |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 80 | /* Define this to try loading /.rockbox/.glyphcache * |
| 81 | * when a font specific file fails. This requires the * |
| 82 | * user to copy and rename a font glyph cache file */ |
| 83 | //#define TRY_DEFAULT_GLYPHCACHE |
| 84 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 85 | /* compiled-in font */ |
| 86 | extern struct font sysfont; |
| 87 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 88 | #ifndef BOOTLOADER |
| 89 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 90 | struct buflib_alloc_data { |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 91 | struct font font; /* must be the first member! */ |
| 92 | int handle_locks; /* is the buflib handle currently locked? */ |
| 93 | int refcount; /* how many times has this font been loaded? */ |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 94 | unsigned char buffer[]; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 95 | }; |
| 96 | static int buflib_allocations[MAXFONTS]; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 97 | |
| 98 | static int cache_fd; |
| 99 | static struct font* cache_pf; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 100 | |
Frank Gevaerts | e5a3c26 | 2011-11-27 15:24:53 +0000 | [diff] [blame] | 101 | static void glyph_cache_save(int font_id); |
| 102 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 103 | static int buflibmove_callback(int handle, void* current, void* new) |
| 104 | { |
| 105 | (void)handle; |
| 106 | struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current; |
Thomas Martitz | 5783505 | 2011-10-07 19:29:18 +0000 | [diff] [blame] | 107 | ptrdiff_t diff = new - current; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 108 | |
Fred Bauer | de3e2e7 | 2011-10-14 20:35:52 +0000 | [diff] [blame] | 109 | if (alloc->handle_locks > 0) |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 110 | return BUFLIB_CB_CANNOT_MOVE; |
| 111 | |
Thomas Martitz | 5783505 | 2011-10-07 19:29:18 +0000 | [diff] [blame] | 112 | #define UPDATE(x) if (x) { x = PTR_ADD(x, diff); } |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 113 | |
Thomas Martitz | 5783505 | 2011-10-07 19:29:18 +0000 | [diff] [blame] | 114 | UPDATE(alloc->font.bits); |
| 115 | UPDATE(alloc->font.offset); |
| 116 | UPDATE(alloc->font.width); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 117 | |
Thomas Martitz | 5783505 | 2011-10-07 19:29:18 +0000 | [diff] [blame] | 118 | UPDATE(alloc->font.buffer_start); |
| 119 | UPDATE(alloc->font.buffer_end); |
| 120 | UPDATE(alloc->font.buffer_position); |
| 121 | |
| 122 | UPDATE(alloc->font.cache._index); |
| 123 | UPDATE(alloc->font.cache._lru._base); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 124 | |
| 125 | return BUFLIB_CB_OK; |
| 126 | } |
| 127 | static void lock_font_handle(int handle, bool lock) |
| 128 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 129 | if ( handle < 0 ) |
| 130 | return; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 131 | struct buflib_alloc_data *alloc = core_get_data(handle); |
Fred Bauer | de3e2e7 | 2011-10-14 20:35:52 +0000 | [diff] [blame] | 132 | if ( lock ) |
| 133 | alloc->handle_locks++; |
| 134 | else |
| 135 | alloc->handle_locks--; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 136 | } |
| 137 | |
Fred Bauer | 04a015d | 2011-10-21 18:05:52 +0000 | [diff] [blame] | 138 | void font_lock(int font_id, bool lock) |
| 139 | { |
Frank Gevaerts | 6e664f4 | 2011-11-27 15:36:03 +0000 | [diff] [blame] | 140 | if( font_id < 0 || font_id >= MAXFONTS ) |
Fred Bauer | 04a015d | 2011-10-21 18:05:52 +0000 | [diff] [blame] | 141 | return; |
| 142 | if( buflib_allocations[font_id] >= 0 ) |
| 143 | lock_font_handle(buflib_allocations[font_id], lock); |
| 144 | } |
| 145 | |
Michael Sevakis | da6cebb | 2012-05-02 17:22:28 -0400 | [diff] [blame] | 146 | static struct buflib_callbacks buflibops = {buflibmove_callback, NULL, NULL }; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 147 | |
| 148 | static inline struct font *pf_from_handle(int handle) |
| 149 | { |
| 150 | struct buflib_alloc_data *alloc = core_get_data(handle); |
| 151 | struct font *pf = &alloc->font; |
| 152 | return pf; |
| 153 | } |
| 154 | |
| 155 | static inline unsigned char *buffer_from_handle(int handle) |
| 156 | { |
| 157 | struct buflib_alloc_data *alloc = core_get_data(handle); |
| 158 | unsigned char* buffer = alloc->buffer; |
| 159 | return buffer; |
| 160 | } |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 161 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 162 | /* Font cache structures */ |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 163 | static void cache_create(struct font* pf); |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 164 | static void glyph_cache_load(const char *font_path, struct font *pf); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 165 | /* End Font cache structures */ |
| 166 | |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 167 | void font_init(void) |
| 168 | { |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 169 | int i = 0; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 170 | cache_fd = -1; |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 171 | while (i<MAXFONTS) |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 172 | buflib_allocations[i++] = -1; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 173 | } |
| 174 | |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 175 | /* Check if we have x bytes left in the file buffer */ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 176 | #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end) |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 177 | |
| 178 | /* Helper functions to read big-endian unaligned short or long from |
| 179 | the file buffer. Bounds-checking must be done in the calling |
| 180 | function. |
| 181 | */ |
| 182 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 183 | static short readshort(struct font *pf) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 184 | { |
| 185 | unsigned short s; |
| 186 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 187 | s = *pf->buffer_position++ & 0xff; |
| 188 | s |= (*pf->buffer_position++ << 8); |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 189 | return s; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 190 | } |
| 191 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 192 | static int32_t readlong(struct font *pf) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 193 | { |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 194 | uint32_t l; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 195 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 196 | l = *pf->buffer_position++ & 0xff; |
| 197 | l |= *pf->buffer_position++ << 8; |
| 198 | l |= ((uint32_t)(*pf->buffer_position++)) << 16; |
| 199 | l |= ((uint32_t)(*pf->buffer_position++)) << 24; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 200 | return l; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 201 | } |
| 202 | |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 203 | static int glyph_bytes( struct font *pf, int width ) |
| 204 | { |
Fred Bauer | 01b36e8 | 2011-09-26 18:13:34 +0000 | [diff] [blame] | 205 | int ret; |
| 206 | if (pf->depth) |
| 207 | ret = ( pf->height * width + 1 ) / 2; |
| 208 | else |
| 209 | ret = width * ((pf->height + 7) / 8); |
| 210 | return (ret + 1) & ~1; |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 211 | } |
| 212 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 213 | /* Load memory font */ |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 214 | static struct font* font_load_in_memory(struct font* pf, |
Fred Bauer | 95a828b | 2011-11-20 17:49:47 +0000 | [diff] [blame] | 215 | int32_t nwidth, |
| 216 | int32_t noffset ) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 217 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 218 | int i; |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 219 | /* variable font data*/ |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 220 | pf->buffer_position = pf->buffer_start + 36; |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 221 | pf->bits = (unsigned char *)pf->buffer_position; |
| 222 | pf->buffer_position += pf->bits_size*sizeof(unsigned char); |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 223 | |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 224 | if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 225 | { |
| 226 | /* pad to 16-bit boundary */ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 227 | pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 228 | } |
| 229 | else |
| 230 | { |
| 231 | /* pad to 32-bit boundary*/ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 232 | pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 233 | } |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 234 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 235 | if (noffset) |
| 236 | { |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 237 | if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 238 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 239 | pf->long_offset = 0; |
| 240 | pf->offset = (uint16_t*)pf->buffer_position; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 241 | |
| 242 | /* Check we have sufficient buffer */ |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 243 | if (!HAVEBYTES(noffset * sizeof(uint16_t))) |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 244 | return NULL; |
| 245 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 246 | for (i=0; i<noffset; ++i) |
| 247 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 248 | ((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(pf); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 249 | } |
| 250 | } |
| 251 | else |
| 252 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 253 | pf->long_offset = 1; |
| 254 | pf->offset = (uint16_t*)pf->buffer_position; |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 255 | |
| 256 | /* Check we have sufficient buffer */ |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 257 | if (!HAVEBYTES(noffset * sizeof(int32_t))) |
Dave Chapman | e10f455 | 2007-04-13 19:51:19 +0000 | [diff] [blame] | 258 | return NULL; |
| 259 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 260 | for (i=0; i<noffset; ++i) |
| 261 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 262 | ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(pf); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 263 | } |
Jörg Hohensohn | 5d36aaf | 2004-08-26 21:15:07 +0000 | [diff] [blame] | 264 | } |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 265 | } |
| 266 | else |
| 267 | pf->offset = NULL; |
| 268 | |
| 269 | if (nwidth) { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 270 | pf->width = (unsigned char *)pf->buffer_position; |
| 271 | pf->buffer_position += nwidth*sizeof(unsigned char); |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 272 | } |
| 273 | else |
| 274 | pf->width = NULL; |
| 275 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 276 | if (pf->buffer_position > pf->buffer_end) |
Björn Stenberg | bed3d3f | 2002-09-20 08:07:51 +0000 | [diff] [blame] | 277 | return NULL; |
| 278 | |
Jens Arnold | 6dc88dc | 2004-05-14 23:08:08 +0000 | [diff] [blame] | 279 | return pf; /* success!*/ |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 280 | } |
| 281 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 282 | /* Load cached font */ |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 283 | static struct font* font_load_cached(struct font* pf, |
| 284 | int32_t nwidth, |
| 285 | int32_t noffset) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 286 | { |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 287 | /* We are now at the bitmap data, this is fixed at 36.. */ |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 288 | pf->width = NULL; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 289 | pf->bits = NULL; |
| 290 | |
| 291 | /* Calculate offset to offset data */ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 292 | pf->buffer_position += pf->bits_size * sizeof(unsigned char); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 293 | |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 294 | if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 295 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 296 | pf->long_offset = 0; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 297 | /* pad to 16-bit boundary */ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 298 | pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 299 | } |
| 300 | else |
| 301 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 302 | pf->long_offset = 1; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 303 | /* pad to 32-bit boundary*/ |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 304 | pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 305 | } |
| 306 | |
| 307 | if (noffset) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 308 | pf->file_offset_offset = (uint32_t)(pf->buffer_position - pf->buffer_start); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 309 | else |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 310 | pf->file_offset_offset = 0; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 311 | |
| 312 | /* Calculate offset to widths data */ |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 313 | if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 314 | pf->buffer_position += noffset * sizeof(uint16_t); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 315 | else |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 316 | pf->buffer_position += noffset * sizeof(uint32_t); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 317 | |
| 318 | if (nwidth) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 319 | pf->file_width_offset = (uint32_t)(pf->buffer_position - pf->buffer_start); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 320 | else |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 321 | pf->file_width_offset = 0; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 322 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 323 | /* Create the cache */ |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 324 | cache_create(pf); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 325 | |
| 326 | return pf; |
| 327 | } |
| 328 | |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 329 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 330 | static int find_font_index(const char* path) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 331 | { |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 332 | int index = 0, handle; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 333 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 334 | while (index < MAXFONTS) |
| 335 | { |
| 336 | handle = buflib_allocations[index]; |
| 337 | if (handle > 0 && !strcmp(core_get_name(handle), path)) |
| 338 | return index; |
| 339 | index++; |
| 340 | } |
| 341 | return FONT_SYSFIXED; |
| 342 | } |
| 343 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 344 | const char* font_filename(int font_id) |
| 345 | { |
Frank Gevaerts | 6e664f4 | 2011-11-27 15:36:03 +0000 | [diff] [blame] | 346 | if ( font_id < 0 || font_id >= MAXFONTS ) |
| 347 | return NULL; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 348 | int handle = buflib_allocations[font_id]; |
| 349 | if (handle > 0) |
| 350 | return core_get_name(handle); |
| 351 | return NULL; |
| 352 | } |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 353 | |
Bertrik Sikken | cb972ab | 2011-12-20 20:35:28 +0000 | [diff] [blame] | 354 | static size_t font_glyphs_to_bufsize(struct font *pf, int glyphs) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 355 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 356 | size_t bufsize; |
| 357 | |
| 358 | /* LRU bytes per glyph */ |
| 359 | bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + |
| 360 | sizeof( unsigned short); |
| 361 | /* Image bytes per glyph */ |
| 362 | bufsize += glyph_bytes(pf, pf->maxwidth); |
| 363 | bufsize *= glyphs; |
| 364 | |
| 365 | return bufsize; |
| 366 | } |
| 367 | |
| 368 | static struct font* font_load_header(int fd, struct font *pheader, |
| 369 | struct font *pf, |
| 370 | uint32_t *nwidth, uint32_t *noffset) |
| 371 | { |
| 372 | /* Load the header. Readshort() and readlong() * |
| 373 | * update buffer_position address as they read */ |
| 374 | pheader->buffer_start = pheader->buffer_position = (char *)pheader; |
| 375 | pheader->buffer_size = FONT_HEADER_SIZE; |
| 376 | pheader->buffer_end = pheader->buffer_start + pheader->buffer_size; |
| 377 | |
| 378 | if (read(fd, pheader, FONT_HEADER_SIZE) != FONT_HEADER_SIZE) |
| 379 | return NULL; |
| 380 | |
| 381 | /* read magic and version #*/ |
| 382 | if (memcmp(pheader->buffer_position, VERSION, 4) != 0) |
| 383 | return NULL; |
| 384 | |
| 385 | pheader->buffer_position += 4; |
| 386 | |
| 387 | /* font info*/ |
| 388 | pf->maxwidth = readshort(pheader); |
| 389 | pf->height = readshort(pheader); |
| 390 | pf->ascent = readshort(pheader); |
| 391 | pf->depth = readshort(pheader); |
| 392 | pf->firstchar = readlong(pheader); |
| 393 | pf->defaultchar = readlong(pheader); |
| 394 | pf->size = readlong(pheader); |
| 395 | |
| 396 | /* get variable font data sizes*/ |
| 397 | /* # words of bitmap_t*/ |
| 398 | pf->bits_size = readlong(pheader); |
| 399 | *noffset = readlong(pheader); |
| 400 | *nwidth = readlong(pheader); |
| 401 | |
| 402 | return pf; |
| 403 | } |
| 404 | |
| 405 | /* load a font with room for glyphs, limited to bufsize if not zero */ |
| 406 | int font_load_ex( const char *path, size_t buf_size, int glyphs ) |
| 407 | { |
| 408 | //printf("\nfont_load_ex(%s, %d, %d)\n", path, buf_size, glyphs); |
| 409 | int fd = open(path, O_RDONLY|O_BINARY); |
| 410 | if ( fd < 0 ) |
| 411 | return -1; |
| 412 | |
| 413 | /* load font struct f with file header */ |
| 414 | int file_size = filesize( fd ); |
| 415 | struct font header; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 416 | struct font f; |
| 417 | |
| 418 | uint32_t nwidth, noffset; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 419 | if ( !font_load_header( fd, &header, &f, &nwidth, &noffset ) |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 420 | #if LCD_DEPTH < 16 |
| 421 | || f.depth |
| 422 | #endif |
| 423 | ) |
| 424 | { |
| 425 | close(fd); |
| 426 | return -1; |
| 427 | } |
| 428 | |
| 429 | /* examine f and calc buffer size */ |
| 430 | bool cached = false; |
| 431 | size_t bufsize = buf_size; |
| 432 | size_t glyph_buf_size = font_glyphs_to_bufsize( &f, glyphs ); |
| 433 | |
| 434 | if ( bufsize && glyphs && bufsize > glyph_buf_size) |
| 435 | bufsize = glyph_buf_size; |
| 436 | else |
| 437 | { |
| 438 | if ( glyphs ) |
| 439 | bufsize = glyph_buf_size; |
| 440 | else |
| 441 | bufsize = MAX_FONT_SIZE; |
| 442 | } |
| 443 | #ifdef FONT_HARD_LIMIT |
| 444 | if ( bufsize > MAX_FONT_SIZE ) |
| 445 | bufsize = MAX_FONT_SIZE; |
| 446 | #endif |
| 447 | if ( bufsize < (size_t) file_size ) |
| 448 | cached = true; |
| 449 | else |
| 450 | bufsize = file_size; |
| 451 | |
| 452 | /* check already loaded */ |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 453 | int font_id = find_font_index(path); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 454 | |
| 455 | if (font_id > FONT_SYSFIXED) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 456 | { |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 457 | /* already loaded, no need to reload */ |
| 458 | struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]); |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 459 | if (pd->font.buffer_size < bufsize) |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 460 | { |
| 461 | int old_refcount, old_id; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 462 | size_t old_bufsize = pd->font.buffer_size; |
| 463 | bool failed = false; |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 464 | /* reload the font: |
| 465 | * 1) save of refcont and id |
| 466 | * 2) force unload (set refcount to 1 to make sure it get unloaded) |
| 467 | * 3) reload with the larger buffer |
| 468 | * 4) restore the id and refcount |
| 469 | */ |
| 470 | old_id = font_id; |
| 471 | old_refcount = pd->refcount; |
| 472 | pd->refcount = 1; |
| 473 | font_unload(font_id); |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 474 | font_id = font_load_ex(path, bufsize, glyphs); |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 475 | if (font_id < 0) |
| 476 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 477 | failed = true; |
| 478 | font_id = font_load_ex(path, old_bufsize, 0); |
| 479 | /* we couldn't even get the old size, this shouldn't happen */ |
| 480 | if ( font_id < 0 ) |
| 481 | return -1; |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 482 | } |
| 483 | if (old_id != font_id) |
| 484 | { |
| 485 | buflib_allocations[old_id] = buflib_allocations[font_id]; |
| 486 | buflib_allocations[font_id] = -1; |
| 487 | font_id = old_id; |
| 488 | } |
| 489 | pd = core_get_data(buflib_allocations[font_id]); |
| 490 | pd->refcount = old_refcount; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 491 | if(failed) |
| 492 | /* return error because we didn't satisfy the new buffer size */ |
| 493 | return -1; |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 494 | } |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 495 | pd->refcount++; |
| 496 | //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount); |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 497 | close(fd); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 498 | return font_id; |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 499 | } |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 500 | |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 501 | int open_slot = -1; |
| 502 | |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 503 | for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 504 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 505 | if (buflib_allocations[ font_id ] < 0) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 506 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 507 | open_slot = font_id; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 508 | break; |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 509 | } |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 510 | } |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 511 | if ( open_slot == -1 ) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 512 | return -1; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 513 | font_id = open_slot; |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 514 | |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 515 | /* allocate mem */ |
| 516 | int handle = core_alloc_ex( path, |
| 517 | bufsize + sizeof( struct buflib_alloc_data ), |
| 518 | &buflibops ); |
Bertrik Sikken | d023bf0 | 2012-06-10 17:15:47 +0200 | [diff] [blame] | 519 | if ( handle <= 0 ) |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 520 | { |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 521 | return -1; |
| 522 | } |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 523 | struct buflib_alloc_data *pdata; |
| 524 | pdata = core_get_data(handle); |
| 525 | pdata->handle_locks = 1; |
| 526 | pdata->refcount = 1; |
| 527 | |
| 528 | /* load and init */ |
Thomas Martitz | 08d9b7f | 2014-01-16 10:31:15 +0100 | [diff] [blame] | 529 | struct font *pf = &pdata->font; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 530 | memcpy(pf, &f, sizeof( struct font) ); |
| 531 | |
| 532 | pf->fd = fd; |
| 533 | pf->fd_width = pf->fd_offset = -1; |
| 534 | pf->handle = handle; |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 535 | pf->disabled = false; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 536 | |
| 537 | pf->buffer_start = buffer_from_handle( pf->handle ); |
| 538 | pf->buffer_position = pf->buffer_start + FONT_HEADER_SIZE; |
| 539 | pf->buffer_size = bufsize; |
| 540 | pf->buffer_end = pf->buffer_start + bufsize; |
| 541 | |
| 542 | if ( cached ) |
| 543 | { |
| 544 | if ( ! font_load_cached( pf, nwidth, noffset ) ) |
| 545 | { |
| 546 | core_free( handle ); |
| 547 | return -1; |
| 548 | } |
| 549 | |
| 550 | /* trick to get a small cache for each file section * |
| 551 | * during glyph_cache_load() */ |
| 552 | pf->fd_width = open( path, O_RDONLY|O_BINARY ); |
| 553 | pf->fd_offset = open( path, O_RDONLY|O_BINARY ); |
| 554 | |
| 555 | glyph_cache_load( path, pf ); |
| 556 | |
| 557 | /* cached font: pf->fd stays open until the font is unloaded */ |
| 558 | close( pf->fd_width ); |
| 559 | pf->fd_width = -1; |
| 560 | close( pf->fd_offset ); |
| 561 | pf->fd_offset = -1; |
| 562 | } |
| 563 | else |
| 564 | { |
| 565 | lseek( fd, 0, SEEK_SET); |
| 566 | read(fd, pf->buffer_start, pf->buffer_size); |
| 567 | |
| 568 | close( fd ); |
| 569 | pf->fd = -1; |
| 570 | |
| 571 | if ( ! font_load_in_memory( pf, nwidth, noffset ) ) |
| 572 | { |
| 573 | core_free( handle ); |
| 574 | return -1; |
| 575 | } |
| 576 | } |
Fred Bauer | ee7de14 | 2011-10-14 14:04:27 +0000 | [diff] [blame] | 577 | buflib_allocations[font_id] = handle; |
Jonathan Gordon | f19f3ef | 2011-11-08 10:09:33 +0000 | [diff] [blame] | 578 | //printf("%s -> [%d] -> %d\n", path, font_id, *handle); |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 579 | lock_font_handle( handle, false ); |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 580 | return font_id; /* success!*/ |
| 581 | } |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 582 | |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 583 | int font_load(const char *path) |
| 584 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 585 | return font_load_ex(path, MAX_FONT_SIZE, GLYPHS_TO_CACHE); |
Jonathan Gordon | 83cfbf4 | 2011-09-24 14:52:16 +0000 | [diff] [blame] | 586 | } |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 587 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 588 | void font_unload(int font_id) |
| 589 | { |
Frank Gevaerts | 6e664f4 | 2011-11-27 15:36:03 +0000 | [diff] [blame] | 590 | if ( font_id < 0 || font_id >= MAXFONTS ) |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 591 | return; |
| 592 | int handle = buflib_allocations[font_id]; |
| 593 | if ( handle < 0 ) |
| 594 | return; |
| 595 | struct buflib_alloc_data *pdata = core_get_data(handle); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 596 | struct font* pf = &pdata->font; |
| 597 | pdata->refcount--; |
| 598 | if (pdata->refcount < 1) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 599 | { |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 600 | //printf("freeing id: %d %s\n", font_id, core_get_name(*handle)); |
| 601 | if (pf && pf->fd >= 0) |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 602 | { |
| 603 | glyph_cache_save(font_id); |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 604 | close(pf->fd); |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 605 | } |
| 606 | if (handle > 0) |
| 607 | core_free(handle); |
| 608 | buflib_allocations[font_id] = -1; |
| 609 | |
| 610 | } |
| 611 | } |
| 612 | |
| 613 | void font_unload_all(void) |
| 614 | { |
| 615 | int i; |
| 616 | for (i=0; i<MAXFONTS; i++) |
| 617 | { |
| 618 | if (buflib_allocations[i] > 0) |
| 619 | { |
| 620 | struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[i]); |
| 621 | alloc->refcount = 1; /* force unload */ |
| 622 | font_unload(i); |
| 623 | } |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 624 | } |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 625 | } |
| 626 | |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 627 | static void font_disable(int font_id) |
| 628 | { |
| 629 | if ( font_id < 0 || font_id >= MAXFONTS ) |
| 630 | return; |
| 631 | int handle = buflib_allocations[font_id]; |
| 632 | if ( handle < 0 ) |
| 633 | return; |
| 634 | struct buflib_alloc_data *pdata = core_get_data(handle); |
| 635 | struct font *pf = &pdata->font; |
| 636 | |
| 637 | if (pf->fd >= 0) |
| 638 | { |
| 639 | /* save the cache, but it keep it in-RAM so that cache lookups |
| 640 | * can still succeed on the same font */ |
| 641 | glyph_cache_save(font_id); |
| 642 | close(pf->fd); |
| 643 | pf->fd = -1; |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 644 | pf->disabled = true; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 645 | } |
| 646 | } |
| 647 | |
| 648 | void font_disable_all(void) |
| 649 | { |
| 650 | for(int i = 0; i < MAXFONTS; i++) |
| 651 | font_disable(i); |
| 652 | } |
| 653 | |
| 654 | static void font_enable(int font_id) |
| 655 | { |
| 656 | if ( font_id < 0 || font_id >= MAXFONTS ) |
| 657 | return; |
| 658 | int handle = buflib_allocations[font_id]; |
| 659 | if ( handle < 0 ) |
| 660 | return; |
| 661 | struct buflib_alloc_data *pdata = core_get_data(handle); |
| 662 | struct font *pf = &pdata->font; |
| 663 | |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 664 | if (pf->disabled && pf->fd < 0) |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 665 | { |
| 666 | const char *filename = font_filename(font_id); |
| 667 | pf->fd = open(filename, O_RDONLY); |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 668 | pf->disabled = false; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 669 | } |
| 670 | } |
| 671 | |
| 672 | void font_enable_all(void) |
| 673 | { |
| 674 | for(int i = 0; i < MAXFONTS; i++) |
| 675 | font_enable(i); |
| 676 | } |
| 677 | |
| 678 | |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 679 | /* |
| 680 | * Return a pointer to an incore font structure. |
Jonathan Gordon | f19f3ef | 2011-11-08 10:09:33 +0000 | [diff] [blame] | 681 | * If the requested font isn't loaded/compiled-in, |
| 682 | * decrement the font number and try again. |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 683 | */ |
Jonathan Gordon | f19f3ef | 2011-11-08 10:09:33 +0000 | [diff] [blame] | 684 | struct font* font_get(int font) |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 685 | { |
Jonathan Gordon | f19f3ef | 2011-11-08 10:09:33 +0000 | [diff] [blame] | 686 | struct font* pf; |
| 687 | if (font == FONT_UI) |
| 688 | font = MAXFONTS-1; |
| 689 | if (font <= FONT_SYSFIXED) |
Fred Bauer | e299eb3 | 2011-10-22 17:13:33 +0000 | [diff] [blame] | 690 | return &sysfont; |
Jonathan Gordon | f19f3ef | 2011-11-08 10:09:33 +0000 | [diff] [blame] | 691 | |
| 692 | while (1) { |
| 693 | if (buflib_allocations[font] > 0) |
| 694 | { |
| 695 | struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[font]); |
| 696 | pf = &alloc->font; |
| 697 | if (pf && pf->height) |
| 698 | return pf; |
| 699 | } |
| 700 | if (--font < 0) |
| 701 | return &sysfont; |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 702 | } |
| 703 | } |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 704 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 705 | /* |
| 706 | * Reads an entry into cache entry |
| 707 | */ |
| 708 | static void |
| 709 | load_cache_entry(struct font_cache_entry* p, void* callback_data) |
| 710 | { |
| 711 | struct font* pf = callback_data; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 712 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 713 | unsigned short char_code = p->_char_code; |
| 714 | unsigned char tmp[2]; |
Fred Bauer | 8c90172 | 2011-10-17 13:17:04 +0000 | [diff] [blame] | 715 | int fd; |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 716 | |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 717 | lock_font_handle(pf->handle, true); |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 718 | if (pf->file_width_offset) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 719 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 720 | int width_offset = pf->file_width_offset + char_code; |
Fred Bauer | 8c90172 | 2011-10-17 13:17:04 +0000 | [diff] [blame] | 721 | /* load via different fd to get this file section cached */ |
| 722 | if(pf->fd_width >=0 ) |
| 723 | fd = pf->fd_width; |
| 724 | else |
| 725 | fd = pf->fd; |
| 726 | lseek(fd, width_offset, SEEK_SET); |
| 727 | read(fd, &(p->width), 1); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 728 | } |
| 729 | else |
| 730 | { |
| 731 | p->width = pf->maxwidth; |
| 732 | } |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 733 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 734 | int32_t bitmap_offset = 0; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 735 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 736 | if (pf->file_offset_offset) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 737 | { |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 738 | int32_t offset = pf->file_offset_offset + char_code * (pf->long_offset ? sizeof(int32_t) : sizeof(int16_t)); |
Fred Bauer | 8c90172 | 2011-10-17 13:17:04 +0000 | [diff] [blame] | 739 | /* load via different fd to get this file section cached */ |
| 740 | if(pf->fd_offset >=0 ) |
| 741 | fd = pf->fd_offset; |
| 742 | else |
| 743 | fd = pf->fd; |
| 744 | lseek(fd, offset, SEEK_SET); |
| 745 | read (fd, tmp, 2); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 746 | bitmap_offset = tmp[0] | (tmp[1] << 8); |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 747 | if (pf->long_offset) { |
Fred Bauer | 8c90172 | 2011-10-17 13:17:04 +0000 | [diff] [blame] | 748 | read (fd, tmp, 2); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 749 | bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); |
| 750 | } |
| 751 | } |
| 752 | else |
| 753 | { |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 754 | bitmap_offset = char_code * glyph_bytes(pf, p->width); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 755 | } |
| 756 | |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 757 | int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 758 | lseek(pf->fd, file_offset, SEEK_SET); |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 759 | int src_bytes = glyph_bytes(pf, p->width); |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 760 | read(pf->fd, p->bitmap, src_bytes); |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 761 | |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 762 | lock_font_handle(pf->handle, false); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 763 | } |
| 764 | |
| 765 | /* |
| 766 | * Converts cbuf into a font cache |
| 767 | */ |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 768 | static void cache_create(struct font* pf) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 769 | { |
| 770 | /* maximum size of rotated bitmap */ |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 771 | int bitmap_size = glyph_bytes(pf, pf->maxwidth); |
| 772 | /* reserve one blank glyph that is guaranteed to be available, even |
| 773 | * when the font file is closed during USB */ |
| 774 | unsigned char *cache_buf = pf->buffer_start + bitmap_size; |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 775 | size_t cache_size = pf->buffer_size - bitmap_size; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 776 | ALIGN_BUFFER(cache_buf, cache_size, 2); |
| 777 | memset(pf->buffer_start, 0, bitmap_size); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 778 | /* Initialise cache */ |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 779 | font_cache_create(&pf->cache, cache_buf, cache_size, bitmap_size); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 780 | } |
| 781 | |
| 782 | /* |
| 783 | * Returns width of character |
| 784 | */ |
| 785 | int font_get_width(struct font* pf, unsigned short char_code) |
| 786 | { |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 787 | int width; |
| 788 | struct font_cache_entry *e; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 789 | |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 790 | /* check input range*/ |
| 791 | if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) |
| 792 | char_code = pf->defaultchar; |
| 793 | char_code -= pf->firstchar; |
| 794 | |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 795 | if (pf->fd >= 0 && pf != &sysfont) |
| 796 | width = font_cache_get(&pf->cache,char_code,false,load_cache_entry,pf)->width; |
| 797 | else if (pf->disabled && |
| 798 | (e = font_cache_get(&pf->cache,char_code,true,load_cache_entry,pf))) |
| 799 | width = e->width; /* falls back to pf->maxwidth if !e */ |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 800 | else if (pf->width) |
| 801 | width = pf->width[char_code]; |
| 802 | else |
| 803 | width = pf->maxwidth; |
| 804 | |
| 805 | return width; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 806 | } |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 807 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 808 | const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) |
| 809 | { |
| 810 | const unsigned char* bits; |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 811 | |
| 812 | /* check input range*/ |
| 813 | if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) |
| 814 | char_code = pf->defaultchar; |
| 815 | char_code -= pf->firstchar; |
| 816 | |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 817 | if (pf->fd >= 0 && pf != &sysfont) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 818 | { |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 819 | bits = |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 820 | (unsigned char*)font_cache_get(&pf->cache, char_code, |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 821 | false, load_cache_entry, pf)->bitmap; |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 822 | } |
Thomas Martitz | 37be80a | 2014-01-26 13:56:53 +0100 | [diff] [blame] | 823 | else if (pf->disabled) |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 824 | { |
| 825 | /* the font handle is closed, but the cache is intact. Attempt |
| 826 | * a lookup, which is very likely to succeed. Return a placeholder |
| 827 | * glyph on miss (again, this is very unlikely */ |
| 828 | struct font_cache_entry *e = font_cache_get(&pf->cache, char_code, |
| 829 | true, NULL, NULL); |
| 830 | if (LIKELY(e)) |
| 831 | bits = (unsigned char *) e->bitmap; |
| 832 | else |
| 833 | { |
| 834 | /* Could attempt to find a suitable fallback glyph from the same |
| 835 | * font. For now just return blank space which is |
| 836 | * reserved by cache_create() at buffer_start */ |
| 837 | bits = pf->buffer_start; |
| 838 | } |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 839 | } |
| 840 | else |
| 841 | { |
Thomas Martitz | c23ce62 | 2014-01-15 13:37:40 +0100 | [diff] [blame] | 842 | /* This font is entirely in RAM */ |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 843 | bits = pf->bits; |
| 844 | if (pf->offset) |
| 845 | { |
| 846 | if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) |
| 847 | bits += ((uint16_t*)(pf->offset))[char_code]; |
| 848 | else |
| 849 | bits += ((uint32_t*)(pf->offset))[char_code]; |
| 850 | } |
| 851 | else |
Thomas Martitz | 9edd6d4 | 2011-03-05 18:36:51 +0000 | [diff] [blame] | 852 | bits += char_code * glyph_bytes(pf, pf->maxwidth); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 853 | } |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 854 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 855 | return bits; |
| 856 | } |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 857 | |
Bertrik Sikken | e71750b | 2011-11-03 23:32:49 +0000 | [diff] [blame] | 858 | static void font_path_to_glyph_path( const char *font_path, char *glyph_path) |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 859 | { |
| 860 | /* take full file name, cut extension, and add .glyphcache */ |
| 861 | strlcpy(glyph_path, font_path, MAX_PATH); |
| 862 | glyph_path[strlen(glyph_path)-4] = '\0'; |
| 863 | strcat(glyph_path, ".gc"); |
| 864 | } |
| 865 | |
| 866 | /* call with NULL to flush */ |
Nils Wallménius | df155c8 | 2007-06-30 17:54:02 +0000 | [diff] [blame] | 867 | static void glyph_file_write(void* data) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 868 | { |
| 869 | struct font_cache_entry* p = data; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 870 | struct font* pf = cache_pf; |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 871 | unsigned short ch; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 872 | static int buffer_pos = 0; |
| 873 | #define WRITE_BUFFER 256 |
| 874 | static unsigned char buffer[WRITE_BUFFER]; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 875 | |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 876 | /* flush buffer & reset */ |
| 877 | if ( data == NULL || buffer_pos >= WRITE_BUFFER) |
| 878 | { |
| 879 | write(cache_fd, buffer, buffer_pos); |
| 880 | buffer_pos = 0; |
| 881 | if ( data == NULL ) |
| 882 | return; |
| 883 | } |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 884 | if ( p->_char_code == 0xffff ) |
| 885 | return; |
| 886 | |
Marcoen Hirschberg | d257683 | 2006-03-22 09:53:27 +0000 | [diff] [blame] | 887 | ch = p->_char_code + pf->firstchar; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 888 | buffer[buffer_pos] = ch >> 8; |
| 889 | buffer[buffer_pos+1] = ch & 0xff; |
| 890 | buffer_pos += 2; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 891 | return; |
| 892 | } |
| 893 | |
| 894 | /* save the char codes of the loaded glyphs to a file */ |
Frank Gevaerts | dfd5d06 | 2011-11-27 15:28:16 +0000 | [diff] [blame] | 895 | static void glyph_cache_save(int font_id) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 896 | { |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 897 | int fd; |
| 898 | |
| 899 | if( font_id < 0 ) |
Jonathan Gordon | aa0f4a4 | 2011-09-24 13:19:34 +0000 | [diff] [blame] | 900 | return; |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 901 | int handle = buflib_allocations[font_id]; |
| 902 | if ( handle < 0 ) |
| 903 | return; |
| 904 | |
| 905 | struct font *pf = pf_from_handle(handle); |
| 906 | if(pf && pf->fd >= 0) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 907 | { |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 908 | char filename[MAX_PATH]; |
| 909 | font_path_to_glyph_path(font_filename(font_id), filename); |
| 910 | fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); |
| 911 | if (fd < 0) |
Thomas Martitz | 9c0b247 | 2010-08-01 16:15:27 +0000 | [diff] [blame] | 912 | return; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 913 | |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 914 | cache_pf = pf; |
| 915 | cache_fd = fd; |
| 916 | lru_traverse(&cache_pf->cache._lru, glyph_file_write); |
| 917 | glyph_file_write(NULL); |
| 918 | if (cache_fd >= 0) |
Jonathan Gordon | 1c2aa35 | 2010-02-14 06:26:16 +0000 | [diff] [blame] | 919 | { |
| 920 | close(cache_fd); |
| 921 | cache_fd = -1; |
| 922 | } |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 923 | } |
| 924 | return; |
| 925 | } |
| 926 | |
Jonathan Gordon | faaf431 | 2010-08-25 14:11:38 +0000 | [diff] [blame] | 927 | |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 928 | static int ushortcmp(const void *a, const void *b) |
| 929 | { |
| 930 | return ((int)(*(unsigned short*)a - *(unsigned short*)b)); |
| 931 | } |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 932 | static void glyph_cache_load(const char *font_path, struct font *pf) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 933 | { |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 934 | #define MAX_SORT 256 |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 935 | if (pf->fd >= 0) { |
| 936 | int i, size, fd; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 937 | unsigned char tmp[2]; |
| 938 | unsigned short ch; |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 939 | unsigned short glyphs[MAX_SORT]; |
| 940 | unsigned short glyphs_lru_order[MAX_SORT]; |
| 941 | int glyph_file_skip=0, glyph_file_size=0; |
| 942 | |
| 943 | int sort_size = pf->cache._capacity; |
| 944 | if ( sort_size > MAX_SORT ) |
| 945 | sort_size = MAX_SORT; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 946 | |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 947 | char filename[MAX_PATH]; |
Fred Bauer | ea7a896 | 2011-11-19 23:34:26 +0000 | [diff] [blame] | 948 | font_path_to_glyph_path(font_path, filename); |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 949 | |
| 950 | fd = open(filename, O_RDONLY|O_BINARY); |
| 951 | #ifdef TRY_DEFAULT_GLYPHCACHE |
| 952 | /* if font specific file fails, try default */ |
| 953 | if (fd < 0) |
| 954 | fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); |
| 955 | #endif |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 956 | if (fd >= 0) { |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 957 | /* only read what fits */ |
| 958 | glyph_file_size = filesize( fd ); |
| 959 | if ( glyph_file_size > 2*pf->cache._capacity ) { |
| 960 | glyph_file_skip = glyph_file_size - 2*pf->cache._capacity; |
| 961 | lseek( fd, glyph_file_skip, SEEK_SET ); |
| 962 | } |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 963 | |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 964 | while(1) { |
| 965 | |
| 966 | for ( size = 0; |
| 967 | read( fd, tmp, 2 ) == 2 && size < sort_size; |
| 968 | size++ ) |
| 969 | { |
| 970 | glyphs[size] = (tmp[0] << 8) | tmp[1]; |
| 971 | glyphs_lru_order[size] = glyphs[size]; |
| 972 | } |
| 973 | |
| 974 | /* sort glyphs array to make sector cache happy */ |
| 975 | qsort((void *)glyphs, size, sizeof(unsigned short), |
| 976 | ushortcmp ); |
| 977 | |
| 978 | /* load font bitmaps */ |
Fred Bauer | 1009741 | 2011-10-16 13:18:46 +0000 | [diff] [blame] | 979 | for( i = 0; i < size ; i++ ) |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 980 | font_get_bits(pf, glyphs[i]); |
Frank Gevaerts | 1994df6 | 2010-08-23 18:17:54 +0000 | [diff] [blame] | 981 | |
| 982 | /* redo to fix lru order */ |
| 983 | for ( i = 0; i < size ; i++) |
| 984 | font_get_bits(pf, glyphs_lru_order[i]); |
| 985 | |
| 986 | if ( size < sort_size ) |
| 987 | break; |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 988 | } |
| 989 | |
| 990 | close(fd); |
| 991 | } else { |
| 992 | /* load latin1 chars into cache */ |
Fred Bauer | edb2875 | 2010-08-27 15:10:30 +0000 | [diff] [blame] | 993 | for ( ch = 32 ; ch < 256 && ch < pf->cache._capacity + 32; ch++ ) |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame] | 994 | font_get_bits(pf, ch); |
| 995 | } |
| 996 | } |
| 997 | return; |
| 998 | } |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 999 | #else /* BOOTLOADER */ |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 1000 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1001 | void font_init(void) |
| 1002 | { |
| 1003 | } |
| 1004 | |
Dominik Riebeling | c032b9d | 2011-10-21 20:15:26 +0000 | [diff] [blame] | 1005 | void font_lock(int font_id, bool lock) |
| 1006 | { |
| 1007 | (void)font_id; |
| 1008 | (void)lock; |
| 1009 | } |
| 1010 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1011 | /* |
| 1012 | * Bootloader only supports the built-in sysfont. |
| 1013 | */ |
| 1014 | struct font* font_get(int font) |
| 1015 | { |
| 1016 | (void)font; |
Andree Buschmann | 05778b5 | 2010-01-03 10:50:34 +0000 | [diff] [blame] | 1017 | return &sysfont; |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1018 | } |
| 1019 | |
| 1020 | /* |
| 1021 | * Returns width of character |
| 1022 | */ |
| 1023 | int font_get_width(struct font* pf, unsigned short char_code) |
| 1024 | { |
| 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; |
| 1029 | |
| 1030 | return pf->width? pf->width[char_code]: pf->maxwidth; |
| 1031 | } |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 1032 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1033 | const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) |
| 1034 | { |
| 1035 | const unsigned char* bits; |
| 1036 | |
| 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; |
| 1041 | |
Nils Wallménius | 559c569 | 2009-12-13 11:07:40 +0000 | [diff] [blame] | 1042 | /* assume small font with uint16_t offsets*/ |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1043 | bits = pf->bits + (pf->offset? |
Nils Wallménius | 66776bc | 2009-12-13 11:19:06 +0000 | [diff] [blame] | 1044 | ((uint16_t*)(pf->offset))[char_code]: |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1045 | (((pf->height + 7) / 8) * pf->maxwidth * char_code)); |
Teruaki Kawashima | 3e4b5c6 | 2010-02-26 07:16:32 +0000 | [diff] [blame] | 1046 | |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1047 | return bits; |
| 1048 | } |
| 1049 | |
| 1050 | #endif /* BOOTLOADER */ |
| 1051 | |
| 1052 | /* |
| 1053 | * Returns the stringsize of a given string. |
| 1054 | */ |
| 1055 | int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber) |
| 1056 | { |
| 1057 | struct font* pf = font_get(fontnumber); |
| 1058 | unsigned short ch; |
| 1059 | int width = 0; |
| 1060 | |
Fred Bauer | 04a015d | 2011-10-21 18:05:52 +0000 | [diff] [blame] | 1061 | font_lock( fontnumber, true ); |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1062 | for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch)) |
| 1063 | { |
Tomer Shalev | 7682cb5 | 2009-11-24 20:41:42 +0000 | [diff] [blame] | 1064 | if (is_diacritic(ch, NULL)) |
| 1065 | continue; |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1066 | |
| 1067 | /* get proportional width and glyph bits*/ |
| 1068 | width += font_get_width(pf,ch); |
| 1069 | } |
| 1070 | if ( w ) |
| 1071 | *w = width; |
| 1072 | if ( h ) |
| 1073 | *h = pf->height; |
Fred Bauer | 04a015d | 2011-10-21 18:05:52 +0000 | [diff] [blame] | 1074 | font_lock( fontnumber, false ); |
Jens Arnold | ae878ff | 2008-09-23 21:35:54 +0000 | [diff] [blame] | 1075 | return width; |
| 1076 | } |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 1077 | |
| 1078 | /* ----------------------------------------------------------------- |
Eric Linenberg | 038df5c | 2002-09-16 03:18:49 +0000 | [diff] [blame] | 1079 | * vim: et sw=4 ts=8 sts=4 tw=78 |
Daniel Stenberg | 93b231c | 2002-09-12 13:33:59 +0000 | [diff] [blame] | 1080 | */ |