blob: 6f5156cc73b22e0c25602af5694b4c3344045e38 [file] [log] [blame]
Daniel Stenberg93b231c2002-09-12 13:33:59 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2002 by Greg Haerr <greg@censoft.com>
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19/*
20 * Rockbox startup font initialization
21 * This file specifies which fonts get compiled-in and
22 * loaded at startup, as well as their mapping into
23 * the FONT_SYSFIXED, FONT_UI and FONT_MP3 ids.
24 */
25#include "config.h"
26
27#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
28
29#include <stdio.h>
30#include <string.h>
31#include "lcd.h"
32#include "font.h"
Björn Stenbergbed3d3f2002-09-20 08:07:51 +000033#include "file.h"
Daniel Stenberg93b231c2002-09-12 13:33:59 +000034#include "debug.h"
35#include "panic.h"
36
Björn Stenbergbed3d3f2002-09-20 08:07:51 +000037#ifndef O_BINARY
38#define O_BINARY 0
Daniel Stenberg93b231c2002-09-12 13:33:59 +000039#endif
Daniel Stenberg0a1c2212002-09-13 06:37:49 +000040
Björn Stenbergbed3d3f2002-09-20 08:07:51 +000041/* compiled-in font */
42extern struct font sysfont;
43
44/* structure filled in by font_load */
45static struct font font_ui;
46
47/* system font table, in order of FONT_xxx definition */
48static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui };
49
50/* static buffer allocation structures */
51static unsigned char mbuf[MAX_FONT_SIZE];
52static unsigned char *freeptr = mbuf;
53static unsigned char *fileptr;
54static unsigned char *eofptr;
55
56static void rotate_font_bits(struct font* pf);
57static void rotleft(unsigned char *dst,
58 bitmap_t *src,
59 unsigned int width,
60 unsigned int height);
61
62void font_init(void)
63{
64 rotate_font_bits(&sysfont);
65 memset(&font_ui, 0, sizeof(struct font));
66}
67
68static int readshort(unsigned short *sp)
69{
70 unsigned short s;
71
72 s = *fileptr++ & 0xff;
73 *sp = (*fileptr++ << 8) | s;
74 return (fileptr <= eofptr);
75}
76
77static int readlong(unsigned long *lp)
78{
79 unsigned long l;
80
81 l = *fileptr++ & 0xff;
82 l |= *fileptr++ << 8;
83 l |= *fileptr++ << 16;
84 *lp = (*fileptr++ << 24) | l;
85 return (fileptr <= eofptr);
86}
87
88/* read count bytes*/
89static int readstr(char *buf, int count)
90{
91 int n = count;
92
93 while (--n >= 0)
94 *buf++ = *fileptr++;
95 return (fileptr <= eofptr)? count: 0;
96}
97
98/* read totlen bytes, return NUL terminated string*/
99/* may write 1 past buf[totlen]; removes blank pad*/
100static int readstrpad(char *buf, int totlen)
101{
102 char *p = buf;
103 int n = totlen;
104
105 while (--n >= 0)
106 *p++ = *fileptr++;
107 if (fileptr > eofptr)
108 return 0;
109
110 p = &buf[totlen];
111 *p-- = 0;
112 while (*p == ' ' && p >= buf)
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
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000128 /* open and read entire font file*/
129 fd = open(path, O_RDONLY|O_BINARY);
130 if (fd < 0) {
131 DEBUGF("Can't open font: %s\n", path);
132 return NULL;
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000133 }
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000134
Björn Stenbergdea31222002-10-08 15:42:40 +0000135 memset(pf, 0, sizeof(struct font));
136
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000137 /* 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;
152 }
153
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!*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000237}
238
239/*
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.
243 */
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000244struct font* font_get(int font)
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000245{
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000246 struct font* pf;
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000247
Eric Linenberg038df5c2002-09-16 03:18:49 +0000248 if (font >= MAXFONTS)
249 font = 0;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000250
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000251 while (1) {
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000252 pf = sysfonts[font];
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000253 if (pf && pf->height)
254 return pf;
255 if (--font < 0)
256 panicf("No font!");
257 }
258}
259
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000260/* convert font bitmap data inplace to rockbox format*/
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000261static void rotate_font_bits(struct font* pf)
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000262{
263 int i;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000264 unsigned long defaultchar = pf->defaultchar - pf->firstchar;
265 bool did_defaultchar = false;
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000266 unsigned char buf[256];
267
268 for (i=0; i<pf->size; ++i) {
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000269 bitmap_t *bits = pf->bits +
270 (pf->offset ? pf->offset[i] : (pf->height * i));
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000271 int width = pf->width? pf->width[i]: pf->maxwidth;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000272 int src_bytes = BITMAP_BYTES(width) * pf->height;
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000273
274 /*
275 * Due to the way the offset map works,
276 * non-mapped characters are mapped to the default
277 * character, and shouldn't be rotated twice.
278 */
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000279
280 if (pf->offset && pf->offset[i] == defaultchar) {
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000281 if (did_defaultchar)
282 continue;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000283 did_defaultchar = true;
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000284 }
285
286 /* rotate left for lcd_bitmap function input*/
287 rotleft(buf, bits, width, pf->height);
288
289 /* copy back into original location*/
290 memcpy(bits, buf, src_bytes);
291 }
292}
293
294/*
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000295 * Take an bitmap_t bitmap and convert to Rockbox format.
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000296 * Used for converting font glyphs for the time being.
297 * Can use for standard X11 and Win32 images as well.
298 *
299 * Doing it this way keeps fonts in standard formats,
300 * as well as keeping Rockbox hw bitmap format.
301 */
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000302static void rotleft(unsigned char *dst, bitmap_t *src, unsigned int width,
303 unsigned int height)
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000304{
305 unsigned int i,j;
306 unsigned int dst_col = 0; /* destination column*/
307 unsigned int dst_shift = 0; /* destination shift amount*/
308 unsigned int dst_linelen; /* # bytes per output row*/
309 unsigned int src_words; /* # words of input image*/
310
311 /* calc bytes per output row*/
312 dst_linelen = (height-1)/8+1;
313
314 /* calc words of input image*/
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000315 src_words = BITMAP_WORDS(width) * height;
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000316
317 /* clear background*/
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000318 memset(dst, 0, dst_linelen*width);
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000319
320 for (i=0; i < src_words; i++) {
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000321 bitmap_t srcmap; /* current src input bit*/
322 bitmap_t dstmap; /* current dst output bit*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000323
Eric Linenberg038df5c2002-09-16 03:18:49 +0000324 /* calc src input bit*/
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000325 srcmap = 1 << (sizeof(bitmap_t)*8-1);
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000326
Eric Linenberg038df5c2002-09-16 03:18:49 +0000327 /* calc dst output bit*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000328 if (i>0 && (i%8==0)) {
329 ++dst_col;
330 dst_shift = 0;
331 }
332 dstmap = 1 << dst_shift++;
333
Eric Linenberg038df5c2002-09-16 03:18:49 +0000334 /* for each input column...*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000335 for(j=0; j < width; j++) {
336
Eric Linenberg038df5c2002-09-16 03:18:49 +0000337 /* calc input bitmask*/
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000338 bitmap_t bit = srcmap >> j;
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000339 if (bit==0) {
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000340 srcmap = 1 << (sizeof(bitmap_t)*8-1);
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000341 bit = srcmap >> (j % 16);
342 }
343
Eric Linenberg038df5c2002-09-16 03:18:49 +0000344 /* if set in input, set in rotated output*/
345 if (bit & src[i]) {
346 /* input column j becomes output row*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000347 dst[j*dst_linelen + dst_col] |= dstmap;
348 }
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000349 /*debugf((bit & src[i])? "*": ".");*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000350 }
Daniel Stenberg0a1c2212002-09-13 06:37:49 +0000351 /*debugf("\n");*/
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000352 }
353}
354#endif /* HAVE_LCD_BITMAP */
355
356/* -----------------------------------------------------------------
357 * local variables:
358 * eval: (load-file "rockbox-mode.el")
Eric Linenberg038df5c2002-09-16 03:18:49 +0000359 * vim: et sw=4 ts=8 sts=4 tw=78
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000360 * end:
361 */