/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (c) 2002 by Greg Haerr * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ /* * Rockbox startup font initialization * This file specifies which fonts get compiled-in and * loaded at startup, as well as their mapping into * the FONT_SYSFIXED, FONT_UI and FONT_MP3 ids. */ #include "config.h" #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) #include #include #include "lcd.h" #include "font.h" #include "file.h" #include "debug.h" #include "panic.h" #ifndef O_BINARY #define O_BINARY 0 #endif /* compiled-in font */ extern struct font sysfont; /* structure filled in by font_load */ static struct font font_ui; /* system font table, in order of FONT_xxx definition */ static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui }; /* static buffer allocation structures */ static unsigned char mbuf[MAX_FONT_SIZE]; static unsigned char *freeptr = mbuf; static unsigned char *fileptr; static unsigned char *eofptr; static void rotate_font_bits(struct font* pf); static void rotleft(unsigned char *dst, bitmap_t *src, unsigned int width, unsigned int height); void font_init(void) { rotate_font_bits(&sysfont); memset(&font_ui, 0, sizeof(struct font)); } static int readshort(unsigned short *sp) { unsigned short s; s = *fileptr++ & 0xff; *sp = (*fileptr++ << 8) | s; return (fileptr <= eofptr); } static int readlong(unsigned long *lp) { unsigned long l; l = *fileptr++ & 0xff; l |= *fileptr++ << 8; l |= *fileptr++ << 16; *lp = (*fileptr++ << 24) | l; return (fileptr <= eofptr); } /* read count bytes*/ static int readstr(char *buf, int count) { int n = count; while (--n >= 0) *buf++ = *fileptr++; return (fileptr <= eofptr)? count: 0; } /* read totlen bytes, return NUL terminated string*/ /* may write 1 past buf[totlen]; removes blank pad*/ static int readstrpad(char *buf, int totlen) { char *p = buf; int n = totlen; while (--n >= 0) *p++ = *fileptr++; if (fileptr > eofptr) return 0; p = &buf[totlen]; *p-- = 0; while (*p == ' ' && p >= buf) *p-- = '\0'; return totlen; } /* read and load font into incore font structure*/ struct font* font_load(char *path) { int fd, filesize; unsigned short maxwidth, height, ascent, pad; unsigned long firstchar, defaultchar, size; unsigned long i, nbits, noffset, nwidth; char version[4+1]; char copyright[256+1]; struct font* pf = &font_ui; memset(pf, 0, sizeof(struct font)); /* open and read entire font file*/ fd = open(path, O_RDONLY|O_BINARY); if (fd < 0) { DEBUGF("Can't open font: %s\n", path); return NULL; } /* currently, font loading replaces earlier font allocation*/ freeptr = (unsigned char *)(((int)mbuf + 3) & ~3); fileptr = freeptr; filesize = read(fd, fileptr, MAX_FONT_SIZE); eofptr = fileptr + filesize; /* no need for multiple font loads currently*/ /*freeptr += filesize;*/ /*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/ close(fd); if (filesize == MAX_FONT_SIZE) { DEBUGF("Font %s too large: %d\n", path, filesize); return NULL; } /* read magic and version #*/ memset(version, 0, sizeof(version)); if (readstr(version, 4) != 4) return NULL; if (strcmp(version, VERSION) != 0) return NULL; /* internal font name*/ pf->name = fileptr; if (readstrpad(pf->name, 64) != 64) return NULL; /* copyright, not currently stored*/ if (readstrpad(copyright, 256) != 256) return NULL; /* font info*/ if (!readshort(&maxwidth)) return NULL; pf->maxwidth = maxwidth; if (!readshort(&height)) return NULL; pf->height = height; if (!readshort(&ascent)) return NULL; pf->ascent = ascent; if (!readshort(&pad)) return NULL; if (!readlong(&firstchar)) return NULL; pf->firstchar = firstchar; if (!readlong(&defaultchar)) return NULL; pf->defaultchar = defaultchar; if (!readlong(&size)) return NULL; pf->size = size; /* get variable font data sizes*/ /* # words of bitmap_t*/ if (!readlong(&nbits)) return NULL; pf->bits_size = nbits; /* # longs of offset*/ if (!readlong(&noffset)) return NULL; /* # bytes of width*/ if (!readlong(&nwidth)) return NULL; /* variable font data*/ pf->bits = (bitmap_t *)fileptr; for (i=0; ibits[i])) return NULL; /* pad to longword boundary*/ fileptr = (unsigned char *)(((int)fileptr + 3) & ~3); if (noffset) { pf->offset = (unsigned long *)fileptr; for (i=0; ioffset[i])) return NULL; } else pf->offset = NULL; if (nwidth) { pf->width = (unsigned char *)fileptr; fileptr += nwidth*sizeof(unsigned char); } else pf->width = NULL; if (fileptr > eofptr) return NULL; /* one-time rotate font bits to rockbox format*/ rotate_font_bits(pf); return pf; /* success!*/ } /* * Return a pointer to an incore font structure. * If the requested font isn't loaded/compiled-in, * decrement the font number and try again. */ struct font* font_get(int font) { struct font* pf; if (font >= MAXFONTS) font = 0; while (1) { pf = sysfonts[font]; if (pf && pf->height) return pf; if (--font < 0) panicf("No font!"); } } /* convert font bitmap data inplace to rockbox format*/ static void rotate_font_bits(struct font* pf) { int i; unsigned long defaultchar = pf->defaultchar - pf->firstchar; bool did_defaultchar = false; unsigned char buf[256]; for (i=0; isize; ++i) { bitmap_t *bits = pf->bits + (pf->offset ? pf->offset[i] : (pf->height * i)); int width = pf->width? pf->width[i]: pf->maxwidth; int src_bytes = BITMAP_BYTES(width) * pf->height; /* * Due to the way the offset map works, * non-mapped characters are mapped to the default * character, and shouldn't be rotated twice. */ if (pf->offset && pf->offset[i] == defaultchar) { if (did_defaultchar) continue; did_defaultchar = true; } /* rotate left for lcd_bitmap function input*/ rotleft(buf, bits, width, pf->height); /* copy back into original location*/ memcpy(bits, buf, src_bytes); } } /* * Take an bitmap_t bitmap and convert to Rockbox format. * Used for converting font glyphs for the time being. * Can use for standard X11 and Win32 images as well. * * Doing it this way keeps fonts in standard formats, * as well as keeping Rockbox hw bitmap format. */ static void rotleft(unsigned char *dst, bitmap_t *src, unsigned int width, unsigned int height) { unsigned int i,j; unsigned int dst_col = 0; /* destination column*/ unsigned int dst_shift = 0; /* destination shift amount*/ unsigned int dst_linelen; /* # bytes per output row*/ unsigned int src_words; /* # words of input image*/ /* calc bytes per output row*/ dst_linelen = (height-1)/8+1; /* calc words of input image*/ src_words = BITMAP_WORDS(width) * height; /* clear background*/ memset(dst, 0, dst_linelen*width); for (i=0; i < src_words; i++) { bitmap_t srcmap; /* current src input bit*/ bitmap_t dstmap; /* current dst output bit*/ /* calc src input bit*/ srcmap = 1 << (sizeof(bitmap_t)*8-1); /* calc dst output bit*/ if (i>0 && (i%8==0)) { ++dst_col; dst_shift = 0; } dstmap = 1 << dst_shift++; /* for each input column...*/ for(j=0; j < width; j++) { /* calc input bitmask*/ bitmap_t bit = srcmap >> j; if (bit==0) { srcmap = 1 << (sizeof(bitmap_t)*8-1); bit = srcmap >> (j % 16); } /* if set in input, set in rotated output*/ if (bit & src[i]) { /* input column j becomes output row*/ dst[j*dst_linelen + dst_col] |= dstmap; } /*debugf((bit & src[i])? "*": ".");*/ } /*debugf("\n");*/ } } #endif /* HAVE_LCD_BITMAP */ /* ----------------------------------------------------------------- * local variables: * eval: (load-file "rockbox-mode.el") * vim: et sw=4 ts=8 sts=4 tw=78 * end: */