summaryrefslogtreecommitdiff
path: root/firmware/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/font.c')
-rw-r--r--firmware/font.c339
1 files changed, 215 insertions, 124 deletions
diff --git a/firmware/font.c b/firmware/font.c
index e9c70cd64e..72c7085b7a 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -30,165 +30,257 @@
30#include <string.h> 30#include <string.h>
31#include "lcd.h" 31#include "lcd.h"
32#include "font.h" 32#include "font.h"
33#include "file.h"
33#include "debug.h" 34#include "debug.h"
34#include "panic.h" 35#include "panic.h"
35 36
36/* available compiled-in fonts*/ 37#ifndef O_BINARY
37extern MWCFONT font_X5x8; 38#define O_BINARY 0
38/*extern MWCFONT font_X6x9; */ 39#endif
39/*extern MWCFONT font_courB08; */ 40
40/*extern MWCFONT font_timR08; */ 41/* compiled-in font */
42extern struct font sysfont;
41 43
42/* structure filled in by rbf_load_font*/ 44/* structure filled in by font_load */
43static MWCFONT font_UI; 45static struct font font_ui;
44 46
45/* system font table, in order of FONT_xxx definition*/ 47/* system font table, in order of FONT_xxx definition */
46struct corefont sysfonts[MAXFONTS] = { 48static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui };
47 { &font_X5x8, NULL }, /* compiled-in FONT_SYSFIXED*/
48 { &font_UI, "/system.fnt" }, /* loaded FONT_UI*/
49 { NULL, NULL }, /* no FONT_MP3*/
50};
51 49
52static void rotate_font_bits(PMWCFONT pf); 50/* static buffer allocation structures */
53static void rotleft(unsigned char *dst, MWIMAGEBITS *src, unsigned int width, 51static unsigned char mbuf[MAX_FONT_SIZE];
54 unsigned int height); 52static unsigned char *freeptr = mbuf;
53static unsigned char *fileptr;
54static unsigned char *eofptr;
55 55
56void 56static void rotate_font_bits(struct font* pf);
57font_init(void) 57static void rotleft(unsigned char *dst,
58 bitmap_t *src,
59 unsigned int width,
60 unsigned int height);
61
62void font_init(void)
58{ 63{
59 struct corefont *cfp; 64 rotate_font_bits(&sysfont);
60 65 memset(&font_ui, 0, sizeof(struct font));
61 for (cfp=sysfonts; cfp < &sysfonts[MAXFONTS]; ++cfp) { 66}
62 if (cfp->pf && cfp->diskname) {
63 cfp->pf = rbf_load_font(cfp->diskname, cfp->pf);
64#if defined(DEBUG) || defined(SIMULATOR)
65 if (!cfp->pf)
66 DEBUGF("Font load failed: %s\n", cfp->diskname);
67#endif
68 }
69 67
70 /* one-time rotate font bits to rockbox format*/ 68static int readshort(unsigned short *sp)
71 if (cfp->pf && cfp->pf->height) 69{
72 rotate_font_bits(cfp->pf); 70 unsigned short s;
73 } 71
72 s = *fileptr++ & 0xff;
73 *sp = (*fileptr++ << 8) | s;
74 return (fileptr <= eofptr);
74} 75}
75 76
76/* 77static int readlong(unsigned long *lp)
77 * Return a pointer to an incore font structure.
78 * If the requested font isn't loaded/compiled-in,
79 * decrement the font number and try again.
80 */
81PMWCFONT
82getfont(int font)
83{ 78{
84 PMWCFONT pf; 79 unsigned long l;
85 80
86 if (font >= MAXFONTS) 81 l = *fileptr++ & 0xff;
87 font = 0; 82 l |= *fileptr++ << 8;
88 while (1) { 83 l |= *fileptr++ << 16;
89 pf = sysfonts[font].pf; 84 *lp = (*fileptr++ << 24) | l;
90 if (pf && pf->height) 85 return (fileptr <= eofptr);
91 return pf;
92 if (--font < 0)
93 panicf("No font!");
94 }
95} 86}
96 87
97/* 88/* read count bytes*/
98 * Return width and height of a given font. 89static int readstr(char *buf, int count)
99 */
100void lcd_getfontsize(int font, int *width, int *height)
101{ 90{
102 PMWCFONT pf = getfont(font); 91 int n = count;
103 92
104 *width = pf->maxwidth; 93 while (--n >= 0)
105 *height = pf->height; 94 *buf++ = *fileptr++;
95 return (fileptr <= eofptr)? count: 0;
106} 96}
107 97
108/* 98/* read totlen bytes, return NUL terminated string*/
109 * Return width and height of a given font. 99/* may write 1 past buf[totlen]; removes blank pad*/
110 */ 100static int readstrpad(char *buf, int totlen)
111//FIXME rename to font_gettextsize, add baseline
112int
113lcd_getstringsize(unsigned char *str, int font, int *w, int *h)
114{ 101{
115 PMWCFONT pf = getfont(font); 102 char *p = buf;
116 int ch; 103 int n = totlen;
117 int width = 0; 104
118 105 while (--n >= 0)
119 while((ch = *str++)) { 106 *p++ = *fileptr++;
120 /* check input range*/ 107 if (fileptr > eofptr)
121 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) 108 return 0;
122 ch = pf->defaultchar; 109
123 ch -= pf->firstchar; 110 p = &buf[totlen];
124 111 *p-- = 0;
125 /* get proportional width and glyph bits*/ 112 while (*p == ' ' && p >= buf)
126 width += pf->width? pf->width[ch]: pf->maxwidth; 113 *p-- = '\0';
114 return totlen;
115}
116
117/* read and load font into incore font structure*/
118struct font* font_load(char *path)
119{
120 int fd, filesize;
121 unsigned short maxwidth, height, ascent, pad;
122 unsigned long firstchar, defaultchar, size;
123 unsigned long i, nbits, noffset, nwidth;
124 char version[4+1];
125 char copyright[256+1];
126 struct font* pf = &font_ui;
127
128 memset(pf, 0, sizeof(struct font));
129
130 /* open and read entire font file*/
131 fd = open(path, O_RDONLY|O_BINARY);
132 if (fd < 0) {
133 DEBUGF("Can't open font: %s\n", path);
134 return NULL;
135 }
136
137 /* currently, font loading replaces earlier font allocation*/
138 freeptr = (unsigned char *)(((int)mbuf + 3) & ~3);
139
140 fileptr = freeptr;
141 filesize = read(fd, fileptr, MAX_FONT_SIZE);
142 eofptr = fileptr + filesize;
143
144 /* no need for multiple font loads currently*/
145 /*freeptr += filesize;*/
146 /*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/
147
148 close(fd);
149 if (filesize == MAX_FONT_SIZE) {
150 DEBUGF("Font %s too large: %d\n", path, filesize);
151 return NULL;
127 } 152 }
128 *w = width;
129 *h = pf->height;
130 153
131 return width; 154 /* read magic and version #*/
155 memset(version, 0, sizeof(version));
156 if (readstr(version, 4) != 4)
157 return NULL;
158 if (strcmp(version, VERSION) != 0)
159 return NULL;
160
161 /* internal font name*/
162 pf->name = fileptr;
163 if (readstrpad(pf->name, 64) != 64)
164 return NULL;
165
166 /* copyright, not currently stored*/
167 if (readstrpad(copyright, 256) != 256)
168 return NULL;
169
170 /* font info*/
171 if (!readshort(&maxwidth))
172 return NULL;
173 pf->maxwidth = maxwidth;
174 if (!readshort(&height))
175 return NULL;
176 pf->height = height;
177 if (!readshort(&ascent))
178 return NULL;
179 pf->ascent = ascent;
180 if (!readshort(&pad))
181 return NULL;
182 if (!readlong(&firstchar))
183 return NULL;
184 pf->firstchar = firstchar;
185 if (!readlong(&defaultchar))
186 return NULL;
187 pf->defaultchar = defaultchar;
188 if (!readlong(&size))
189 return NULL;
190 pf->size = size;
191
192 /* get variable font data sizes*/
193 /* # words of bitmap_t*/
194 if (!readlong(&nbits))
195 return NULL;
196 pf->bits_size = nbits;
197
198 /* # longs of offset*/
199 if (!readlong(&noffset))
200 return NULL;
201
202 /* # bytes of width*/
203 if (!readlong(&nwidth))
204 return NULL;
205
206 /* variable font data*/
207 pf->bits = (bitmap_t *)fileptr;
208 for (i=0; i<nbits; ++i)
209 if (!readshort(&pf->bits[i]))
210 return NULL;
211 /* pad to longword boundary*/
212 fileptr = (unsigned char *)(((int)fileptr + 3) & ~3);
213
214 if (noffset) {
215 pf->offset = (unsigned long *)fileptr;
216 for (i=0; i<noffset; ++i)
217 if (!readlong(&pf->offset[i]))
218 return NULL;
219 }
220 else
221 pf->offset = NULL;
222
223 if (nwidth) {
224 pf->width = (unsigned char *)fileptr;
225 fileptr += nwidth*sizeof(unsigned char);
226 }
227 else
228 pf->width = NULL;
229
230 if (fileptr > eofptr)
231 return NULL;
232
233 /* one-time rotate font bits to rockbox format*/
234 rotate_font_bits(pf);
235
236 return pf; /* success!*/
132} 237}
133 238
134/* 239/*
135 * Put a string at specified bit position 240 * Return a pointer to an incore font structure.
241 * If the requested font isn't loaded/compiled-in,
242 * decrement the font number and try again.
136 */ 243 */
137//FIXME rename font_putsxy? 244struct font* font_get(int font)
138void
139lcd_putsxy(int x, int y, unsigned char *str, int font)
140{ 245{
141 int ch; 246 struct font* pf;
142 PMWCFONT pf = getfont(font); 247
143 248 if (font >= MAXFONTS)
144 while (((ch = *str++) != '\0')) { 249 font = 0;
145 MWIMAGEBITS *bits; 250
146 int width; 251 while (1) {
147 252 pf = sysfonts[font];
148 /* check input range*/ 253 if (pf && pf->height)
149 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) 254 return pf;
150 ch = pf->defaultchar; 255 if (--font < 0)
151 ch -= pf->firstchar; 256 panicf("No font!");
152
153 /* get proportional width and glyph bits*/
154 width = pf->width? pf->width[ch]: pf->maxwidth;
155 if (x + width > LCD_WIDTH)
156 break;
157
158 /* no partial-height drawing for now...*/
159 if (y + pf->height > LCD_HEIGHT)
160 break;
161 bits = pf->bits + (pf->offset? pf->offset[ch]: (pf->height * ch));
162
163 lcd_bitmap((unsigned char *)bits, x, y, width, pf->height, true);
164 x += width;
165 } 257 }
166} 258}
167 259
168/* convert font bitmap data inplace to rockbox format*/ 260/* convert font bitmap data inplace to rockbox format*/
169static void 261static void rotate_font_bits(struct font* pf)
170rotate_font_bits(PMWCFONT pf)
171{ 262{
172 int i; 263 int i;
173 int defaultchar = pf->defaultchar - pf->firstchar; 264 unsigned long defaultchar = pf->defaultchar - pf->firstchar;
174 int did_defaultchar = 0; 265 bool did_defaultchar = false;
175 unsigned char buf[256]; 266 unsigned char buf[256];
176 267
177 for (i=0; i<pf->size; ++i) { 268 for (i=0; i<pf->size; ++i) {
178 MWIMAGEBITS *bits = pf->bits + 269 bitmap_t *bits = pf->bits +
179 (pf->offset? pf->offset[i]: (pf->height * i)); 270 (pf->offset ? pf->offset[i] : (pf->height * i));
180 int width = pf->width? pf->width[i]: pf->maxwidth; 271 int width = pf->width? pf->width[i]: pf->maxwidth;
181 int src_bytes = MWIMAGE_BYTES(width) * pf->height; 272 int src_bytes = BITMAP_BYTES(width) * pf->height;
182 273
183 /* 274 /*
184 * Due to the way the offset map works, 275 * Due to the way the offset map works,
185 * non-mapped characters are mapped to the default 276 * non-mapped characters are mapped to the default
186 * character, and shouldn't be rotated twice. 277 * character, and shouldn't be rotated twice.
187 */ 278 */
188 if (i == defaultchar) { 279
280 if (pf->offset && pf->offset[i] == defaultchar) {
189 if (did_defaultchar) 281 if (did_defaultchar)
190 continue; 282 continue;
191 did_defaultchar = 1; 283 did_defaultchar = true;
192 } 284 }
193 285
194 /* rotate left for lcd_bitmap function input*/ 286 /* rotate left for lcd_bitmap function input*/
@@ -200,16 +292,15 @@ rotate_font_bits(PMWCFONT pf)
200} 292}
201 293
202/* 294/*
203 * Take an MWIMAGEBITS bitmap and convert to Rockbox format. 295 * Take an bitmap_t bitmap and convert to Rockbox format.
204 * Used for converting font glyphs for the time being. 296 * Used for converting font glyphs for the time being.
205 * Can use for standard X11 and Win32 images as well. 297 * Can use for standard X11 and Win32 images as well.
206 * 298 *
207 * Doing it this way keeps fonts in standard formats, 299 * Doing it this way keeps fonts in standard formats,
208 * as well as keeping Rockbox hw bitmap format. 300 * as well as keeping Rockbox hw bitmap format.
209 */ 301 */
210static void 302static void rotleft(unsigned char *dst, bitmap_t *src, unsigned int width,
211rotleft(unsigned char *dst, MWIMAGEBITS *src, unsigned int width, 303 unsigned int height)
212 unsigned int height)
213{ 304{
214 unsigned int i,j; 305 unsigned int i,j;
215 unsigned int dst_col = 0; /* destination column*/ 306 unsigned int dst_col = 0; /* destination column*/
@@ -221,17 +312,17 @@ rotleft(unsigned char *dst, MWIMAGEBITS *src, unsigned int width,
221 dst_linelen = (height-1)/8+1; 312 dst_linelen = (height-1)/8+1;
222 313
223 /* calc words of input image*/ 314 /* calc words of input image*/
224 src_words = MWIMAGE_WORDS(width) * height; 315 src_words = BITMAP_WORDS(width) * height;
225 316
226 /* clear background*/ 317 /* clear background*/
227 memset(dst, 0, dst_linelen*width); 318 memset(dst, 0, dst_linelen*width);
228 319
229 for (i=0; i < src_words; i++) { 320 for (i=0; i < src_words; i++) {
230 MWIMAGEBITS srcmap; /* current src input bit*/ 321 bitmap_t srcmap; /* current src input bit*/
231 MWIMAGEBITS dstmap; /* current dst output bit*/ 322 bitmap_t dstmap; /* current dst output bit*/
232 323
233 /* calc src input bit*/ 324 /* calc src input bit*/
234 srcmap = 1 << (sizeof(MWIMAGEBITS)*8-1); 325 srcmap = 1 << (sizeof(bitmap_t)*8-1);
235 326
236 /* calc dst output bit*/ 327 /* calc dst output bit*/
237 if (i>0 && (i%8==0)) { 328 if (i>0 && (i%8==0)) {
@@ -244,9 +335,9 @@ rotleft(unsigned char *dst, MWIMAGEBITS *src, unsigned int width,
244 for(j=0; j < width; j++) { 335 for(j=0; j < width; j++) {
245 336
246 /* calc input bitmask*/ 337 /* calc input bitmask*/
247 MWIMAGEBITS bit = srcmap >> j; 338 bitmap_t bit = srcmap >> j;
248 if (bit==0) { 339 if (bit==0) {
249 srcmap = 1 << (sizeof(MWIMAGEBITS)*8-1); 340 srcmap = 1 << (sizeof(bitmap_t)*8-1);
250 bit = srcmap >> (j % 16); 341 bit = srcmap >> (j % 16);
251 } 342 }
252 343