Index: apps/recorder/keyboard.c =================================================================== --- apps/recorder/keyboard.c (Revision 17518) +++ apps/recorder/keyboard.c (Arbeitskopie) @@ -399,14 +399,14 @@ /* find max width of keyboard glyphs */ for (i = 0; i < pm->nchars; i++) { - w = font_get_width(pm->font, pm->kbd_buf[i]); + w = font_get_width(pm->font, pm->kbd_buf[i], param[l].curfont); if ( w > pm->font_w ) pm->font_w = w; } /* Since we're going to be adding spaces, make sure that we check * their width too */ - w = font_get_width( pm->font, ' ' ); + w = font_get_width( pm->font, ' ', param[l].curfont ); if ( w > pm->font_w ) pm->font_w = w; } @@ -474,7 +474,7 @@ while (*utf8) { - int w = font_get_width(pm->font, ch); + int w = font_get_width(pm->font, ch, param[l].curfont); utf8 = (unsigned char*)utf8decode(utf8, &ch); if (w > text_w) Index: apps/settings.c =================================================================== --- apps/settings.c (Revision 17518) +++ apps/settings.c (Arbeitskopie) @@ -799,10 +799,68 @@ if ( global_settings.font_file[0]) { snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.font_file); - font_load(buf); + font_load(buf, FONT_UI); } else - font_reset(); + font_reset(FONT_UI); + + /* Load all user fonts */ + if ( global_settings.userfont1[0] && + global_settings.userfont1[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont1); + font_load(buf, FONT_USER1); + } + else + font_reset(FONT_USER1); + if ( global_settings.userfont2[0] && + global_settings.userfont2[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont2); + font_load(buf, FONT_USER2); + } + else + font_reset(FONT_USER2); + if ( global_settings.userfont3[0] && + global_settings.userfont3[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont3); + font_load(buf, FONT_USER3); + } + else + font_reset(FONT_USER3); + if ( global_settings.userfont4[0] && + global_settings.userfont4[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont4); + font_load(buf, FONT_USER4); + } + else + font_reset(FONT_USER4); + if ( global_settings.userfont5[0] && + global_settings.userfont5[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont5); + font_load(buf, FONT_USER5); + } + else + font_reset(FONT_USER5); + if ( global_settings.userfont6[0] && + global_settings.userfont6[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont6); + font_load(buf, FONT_USER6); + } + else + font_reset(FONT_USER6); + if ( global_settings.userfont7[0] && + global_settings.userfont7[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont7); + font_load(buf, FONT_USER7); + } + else + font_reset(FONT_USER7); if ( global_settings.kbd_file[0]) { snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd", @@ -1101,14 +1159,15 @@ void set_file(const char* filename, char* setting, int maxlen) { - char* fptr = strrchr(filename,'/'); + char *fptr = strrchr(filename,'/'); int len; int extlen = 0; - char* ptr; + char *ptr, *oldptr; if (!fptr) return; + oldptr = fptr; *fptr = 0; fptr++; Index: apps/plugins/zxbox/zxbox_keyb.c =================================================================== --- apps/plugins/zxbox/zxbox_keyb.c (Revision 17518) +++ apps/plugins/zxbox/zxbox_keyb.c (Arbeitskopie) @@ -240,13 +240,13 @@ rb->screens[l]->setfont(param[l].curfont); /* find max width of keyboard glyphs */ for (i=0; ifont_get_width(param[l].font, param[l].kbd_buf[i]); + w = rb->font_get_width(param[l].font, param[l].kbd_buf[i], FONT_UI); if (w > param[l].font_w) param[l].font_w = w; } /* Since we're going to be adding spaces, make sure that we check * their width too */ - w = rb->font_get_width( param[l].font, ' ' ); + w = rb->font_get_width( param[l].font, ' ', FONT_UI ); if( w > param[l].font_w ) param[l].font_w = w; } @@ -298,7 +298,7 @@ text_w = param[l].font_w; while (*utf8) { utf8 = (unsigned char*)rb->utf8decode(utf8, &ch); - w = rb->font_get_width(param[l].font, ch); + w = rb->font_get_width(param[l].font, ch, FONT_SYSFIXED); if (w > text_w) text_w = w; } @@ -429,7 +429,7 @@ case KBD_ABORT: FOR_NB_SCREENS(l) - rb->screens[l]->setfont(FONT_UI); + rb->screens[l]->setfont(FONT_SYSFIXED); return -1; break; @@ -548,6 +548,6 @@ } } FOR_NB_SCREENS(l) - rb->screens[l]->setfont(FONT_UI); + rb->screens[l]->setfont(FONT_SYSFIXED); return 0; } Index: apps/plugins/mpegplayer/mpegplayer.c =================================================================== --- apps/plugins/mpegplayer/mpegplayer.c (Revision 17518) +++ apps/plugins/mpegplayer/mpegplayer.c (Arbeitskopie) @@ -550,14 +550,14 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = rb->font_get_width(pf, ch); + width = rb->font_get_width(pf, ch, FONT_UI); if (ofs > width) { ofs -= width; continue; } - bits = rb->font_get_bits(pf, ch); + bits = rb->font_get_bits(pf, ch, FONT_UI); draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: apps/plugins/viewer.c =================================================================== --- apps/plugins/viewer.c (Revision 17518) +++ apps/plugins/viewer.c (Arbeitskopie) @@ -380,7 +380,7 @@ ch = ' '; #ifdef HAVE_LCD_BITMAP - return rb->font_get_width(pf, ch); + return rb->font_get_width(pf, ch, FONT_UI); #else return 1; #endif Index: apps/plugins/rockpaint.c =================================================================== --- apps/plugins/rockpaint.c (Revision 17518) +++ apps/plugins/rockpaint.c (Arbeitskopie) @@ -447,10 +447,13 @@ { unsigned short ch; unsigned short *ucs; + int curfont=FONT_UI; struct font *pf = rb->font_get( FONT_UI ); - if( !pf ) pf = rb->font_get( FONT_SYSFIXED ); - + if( !pf ) { + pf = rb->font_get( FONT_SYSFIXED ); + curfont=FONT_SYSFIXED; + } ucs = rb->bidi_l2v( str, 1 ); while( (ch = *ucs++) != 0 && x < buf_width ) @@ -459,7 +462,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = rb->font_get_width( pf, ch ); + width = rb->font_get_width( pf, ch, curfont ); if( ofs > width ) { @@ -467,7 +470,7 @@ continue; } - bits = rb->font_get_bits( pf, ch ); + bits = rb->font_get_bits( pf, ch, curfont ); buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, width, x, y, width - ofs, pf->height); @@ -942,7 +945,7 @@ continue; rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", de->d_name ); - rb->font_load( bbuf ); + rb->font_load( bbuf, FONT_UI ); rb->font_getstringsize( de->d_name, &fw, &fh, FONT_UI ); if( nvih > 0 ) { @@ -977,12 +980,12 @@ { rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", de->d_name ); - rb->font_load( bbuf ); + rb->font_load( bbuf, FONT_UI ); rb->font_getstringsize( de->d_name, NULL, &fh, FONT_UI ); nvih = fh; } } - rb->font_load( old_font ); + rb->font_load( old_font, FONT_UI ); rb->closedir( d ); } @@ -1538,7 +1541,7 @@ case TEXT_MENU_FONT: if( browse_fonts( buffer.text.font, MAX_PATH ) ) { - rb->font_load( buffer.text.font ); + rb->font_load( buffer.text.font, FONT_UI ); } break; @@ -1590,7 +1593,7 @@ buffer.text.text ); case TEXT_MENU_CANCEL: restore_screen(); - rb->font_load( buffer.text.old_font ); + rb->font_load( buffer.text.old_font, FONT_UI ); return; } } Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 17714) +++ apps/gui/wps_parser.c (working copy) @@ -632,9 +673,38 @@ vp->height = lcd_height - vp->y; /* Default to using the user font if the font was an invalid number */ - if (!LIST_VALUE_PARSED(set, PL_FONT) || - ((vp->font != FONT_SYSFIXED) && (vp->font != FONT_UI))) - vp->font = FONT_UI; + switch (vp->font){ + case 0: + vp->font = FONT_SYSFIXED; + break; + case 1: + vp->font = FONT_UI; + break; + case 2: + vp->font = FONT_USER1; + break; + case 3: + vp->font = FONT_USER2; + break; + case 4: + vp->font = FONT_USER3; + break; + case 5: + vp->font = FONT_USER4; + break; + case 6: + vp->font = FONT_USER5; + break; + case 7: + vp->font = FONT_USER6; + break; + case 8: + vp->font = FONT_USER7; + break; + default: + vp->font = FONT_UI; + break; + } /* Validate the viewport dimensions - we know that the numbers are non-negative integers */ Index: apps/settings.h =================================================================== --- apps/settings.h (Revision 17518) +++ apps/settings.h (Arbeitskopie) @@ -418,6 +418,13 @@ #endif #ifdef HAVE_LCD_BITMAP unsigned char font_file[MAX_FILENAME+1]; /* last font */ + unsigned char userfont1[MAX_FILENAME+1]; + unsigned char userfont2[MAX_FILENAME+1]; + unsigned char userfont3[MAX_FILENAME+1]; + unsigned char userfont4[MAX_FILENAME+1]; + unsigned char userfont5[MAX_FILENAME+1]; + unsigned char userfont6[MAX_FILENAME+1]; + unsigned char userfont7[MAX_FILENAME+1]; #endif unsigned char wps_file[MAX_FILENAME+1]; /* last wps */ unsigned char lang_file[MAX_FILENAME+1]; /* last language */ Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (Revision 17518) +++ apps/settings_list.c (Arbeitskopie) @@ -533,6 +533,14 @@ SYSTEM_SETTING(NVRAM(4),last_frequency,0), #endif + FILENAME_SETTING(F_THEMESETTING,userfont1,"userfont1","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont2,"userfont2","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont3,"userfont3","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont4,"userfont4","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont5,"userfont5","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont6,"userfont6","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont7,"userfont7","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + #if BATTERY_TYPES_COUNT > 1 CHOICE_SETTING(0, battery_type, LANG_BATTERY_TYPE, 0, "battery type", "alkaline,nimh", NULL, 2, ID2P(LANG_BATTERY_TYPE_ALKALINE), Index: apps/filetree.c =================================================================== --- apps/filetree.c (Revision 17518) +++ apps/filetree.c (Arbeitskopie) @@ -506,8 +506,12 @@ #ifdef HAVE_LCD_BITMAP case FILE_ATTR_FONT: gui_syncsplash(0, ID2P(LANG_WAIT)); - font_load(buf); - set_file(buf, (char *)global_settings.font_file, MAX_FILENAME); + font_load(buf, FONT_UI); + /* set_file will change buf!!! + * so make a copy */ + char buf_copy[MAX_PATH]; + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.font_file, MAX_FILENAME); break; case FILE_ATTR_KBD: Index: apps/plugin.c =================================================================== --- apps/plugin.c (Revision 17518) +++ apps/plugin.c (Arbeitskopie) @@ -96,6 +96,7 @@ lcd_set_drawmode, lcd_get_drawmode, lcd_setfont, + lcd_getfont, lcd_drawpixel, lcd_drawline, lcd_hline, @@ -159,6 +160,7 @@ lcd_remote_set_drawmode, lcd_remote_get_drawmode, lcd_remote_setfont, + lcd_remote_getfont, lcd_remote_getstringsize, lcd_remote_drawpixel, lcd_remote_drawline, Index: apps/plugin.h =================================================================== --- apps/plugin.h (Revision 17518) +++ apps/plugin.h (Arbeitskopie) @@ -167,6 +167,7 @@ void (*lcd_set_drawmode)(int mode); int (*lcd_get_drawmode)(void); void (*lcd_setfont)(int font); + int (*lcd_getfont)(void); void (*lcd_drawpixel)(int x, int y); void (*lcd_drawline)(int x1, int y1, int x2, int y2); void (*lcd_hline)(int x1, int x2, int y); @@ -214,12 +215,12 @@ int style); unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation ); - const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code ); - struct font* (*font_load)(const char *path); + const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code, int font ); + struct font* (*font_load)(const char *path, int font); struct font* (*font_get)(int font); int (*font_getstringsize)(const unsigned char *str, int *w, int *h, int fontnumber); - int (*font_get_width)(struct font* pf, unsigned short char_code); + int (*font_get_width)(struct font* pf, unsigned short char_code, int font); void (*screen_clear_area)(struct screen * display, int xstart, int ystart, int width, int height); void (*gui_scrollbar_draw)(struct screen * screen, int x, int y, @@ -250,6 +251,7 @@ void (*lcd_remote_set_drawmode)(int mode); int (*lcd_remote_get_drawmode)(void); void (*lcd_remote_setfont)(int font); + int (*lcd_remote_getfont)(void); int (*lcd_remote_getstringsize)(const unsigned char *str, int *w, int *h); void (*lcd_remote_drawpixel)(int x, int y); void (*lcd_remote_drawline)(int x1, int y1, int x2, int y2); Index: firmware/export/font.h =================================================================== --- firmware/export/font.h (Revision 17518) +++ firmware/export/font.h (Arbeitskopie) @@ -48,7 +48,14 @@ #define FONT_HEADER_SIZE 36 #endif -#define GLYPH_CACHE_FILE "/.rockbox/.glyphcache" +#define GLYPH_CACHE_FILE_UI "/.rockbox/.glyphcache-ui" +#define GLYPH_CACHE_FILE_USER1 "/.rockbox/.glyphcache-user1" +#define GLYPH_CACHE_FILE_USER2 "/.rockbox/.glyphcache-user2" +#define GLYPH_CACHE_FILE_USER3 "/.rockbox/.glyphcache-user3" +#define GLYPH_CACHE_FILE_USER4 "/.rockbox/.glyphcache-user4" +#define GLYPH_CACHE_FILE_USER5 "/.rockbox/.glyphcache-user5" +#define GLYPH_CACHE_FILE_USER6 "/.rockbox/.glyphcache-user6" +#define GLYPH_CACHE_FILE_USER7 "/.rockbox/.glyphcache-user7" /* * Fonts are specified by number, and used for display @@ -63,6 +70,13 @@ enum { FONT_SYSFIXED, /* system fixed pitch font*/ FONT_UI, /* system porportional font*/ + FONT_USER1, /* User custom fonts for use in wps */ + FONT_USER2, /* User custom fonts for use in wps */ + FONT_USER3, /* User custom fonts for use in wps */ + FONT_USER4, /* User custom fonts for use in wps */ + FONT_USER5, /* User custom fonts for use in wps */ + FONT_USER6, /* User custom fonts for use in wps */ + FONT_USER7, /* User custom fonts for use in wps */ MAXFONTS }; @@ -108,13 +122,13 @@ /* font routines*/ void font_init(void); -struct font* font_load(const char *path); +struct font* font_load(const char *path, int font); struct font* font_get(int font); -void font_reset(void); -int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); -int font_get_width(struct font* ft, unsigned short ch); -const unsigned char * font_get_bits(struct font* ft, unsigned short ch); -void glyph_cache_save(void); +void font_reset(int font); +int font_getstringsize(const unsigned char *str, int *w, int *h, int font); +int font_get_width(struct font* ft, unsigned short ch, int font); +const unsigned char * font_get_bits(struct font* ft, unsigned short ch, int font); +void glyph_cache_save(int font); #else /* HAVE_LCD_BITMAP */ Index: firmware/font.c =================================================================== --- firmware/font.c (Revision 17518) +++ firmware/font.c (Arbeitskopie) @@ -46,35 +46,67 @@ /* compiled-in font */ extern struct font sysfont; -/* structure filled in by font_load */ +/* font structures filled in by font_load */ static struct font font_ui; +static struct font userfont1; +static struct font userfont2; +static struct font userfont3; +static struct font userfont4; +static struct font userfont5; +static struct font userfont6; +static struct font userfont7; /* system font table, in order of FONT_xxx definition */ -static struct font* const sysfonts[MAXFONTS] = { &sysfont, &font_ui }; +static struct font* sysfonts[MAXFONTS] = { + &sysfont, + &font_ui, + &userfont1, + &userfont2, + &userfont3, + &userfont4, + &userfont5, + &userfont6, + &userfont7 + }; /* 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 unsigned char font_membuf[MAXCACHEFONTS][MAX_FONT_SIZE]; /* Sysfont is compiled-in, no need for buffer */ /* Font cache structures */ -static struct font_cache font_cache_ui; -static int fnt_file = -1; /* >=0 if font is cached */ -static uint32_t file_width_offset; /* offset to file width data */ -static uint32_t file_offset_offset; /* offset to file offset data */ -static void cache_create(int maxwidth, int height); -static int long_offset = 0; -static int glyph_file; +static struct font_cache sys_font_cache[MAXCACHEFONTS]; +static struct font_file_info fntfile[MAXCACHEFONTS]; +static void cache_create(int maxwidth, int height, int font); +static void font_cache_init(void); /* End Font cache structures */ -static void glyph_cache_load(void); +static void glyph_cache_load(int font); +/* Zero out all font structures */ void font_init(void) { - memset(&font_ui, 0, sizeof(struct font)); + int i = FONT_UI; /* Skip sysfont */ + + while (i < MAXFONTS) + { + memset(sysfonts[i], 0, sizeof(struct font)); + i++; + } + + font_cache_init(); } +void font_cache_init(void) +{ + int i = 0; + + while (i < MAXCACHEFONTS) + { + fntfile[i].font_fd = -1; + i++; + } + return; +} + /* Check if we have x bytes left in the file buffer */ #define HAVEBYTES(x) (fileptr + (x) <= eofptr) @@ -82,126 +114,147 @@ the file buffer. Bounds-checking must be done in the calling function. */ - -static short readshort(void) + +static short readshort(unsigned short *sp, int font) { unsigned short s; - s = *fileptr++ & 0xff; - s |= (*fileptr++ << 8); - return s; + s = *fntfile[font].fileptr++ & 0xff; + *sp = (*fntfile[font].fileptr++ << 8) | s; + return (fntfile[font].fileptr <= fntfile[font].eofptr); } -static int32_t readlong(void) +static int32_t readlong(uint32_t *lp, int font) { uint32_t l; - l = *fileptr++ & 0xff; - l |= *fileptr++ << 8; - l |= ((uint32_t)(*fileptr++)) << 16; - l |= ((uint32_t)(*fileptr++)) << 24; - return l; + l = *fntfile[font].fileptr++ & 0xff; + l |= *fntfile[font].fileptr++ << 8; + l |= ((uint32_t)(*fntfile[font].fileptr++)) << 16; + l |= ((uint32_t)(*fntfile[font].fileptr++)) << 24; + *lp = l; + return (fntfile[font].fileptr <= fntfile[font].eofptr); } /* read count bytes*/ -static void readstr(char *buf, int count) +static int readstr(char *buf, int count, int font) { - while (count--) - *buf++ = *fileptr++; + int n = count; + + while (--n >= 0) + *buf++ = *fntfile[font].fileptr++; + + return (fntfile[font].fileptr <= fntfile[font].eofptr)? count: 0; } -void font_reset(void) +void font_reset(int font) { - memset(&font_ui, 0, sizeof(struct font)); + memset(sysfonts[font], 0, sizeof(struct font)); } -static struct font* font_load_header(struct font *pf) +static struct font* font_load_header(struct font *pf, int font) { char version[4+1]; + unsigned short maxwidth, height, ascent, pad; + uint32_t firstchar, defaultchar, size; + uint32_t nbits; - /* Check we have enough data */ - if (!HAVEBYTES(28)) - return NULL; - /* read magic and version #*/ memset(version, 0, sizeof(version)); - readstr(version, 4); + if (readstr(version, 4, font) != 4) + return NULL; if (strcmp(version, VERSION) != 0) return NULL; /* font info*/ - pf->maxwidth = readshort(); - pf->height = readshort(); - pf->ascent = readshort(); - fileptr += 2; /* Skip padding */ - pf->firstchar = readlong(); - pf->defaultchar = readlong(); - pf->size = readlong(); + if (!readshort(&maxwidth, font)) + return NULL; + pf->maxwidth = maxwidth; + if (!readshort(&height, font)) + return NULL; + pf->height = height; + + if (!readshort(&ascent, font)) + return NULL; + pf->ascent = ascent; + + if (!readshort(&pad, font)) + return NULL; + + if (!readlong(&firstchar, font)) + return NULL; + pf->firstchar = firstchar; + + if (!readlong(&defaultchar, font)) + return NULL; + pf->defaultchar = defaultchar; + + if (!readlong(&size, font)) + return NULL; + pf->size = size; + /* get variable font data sizes*/ /* # words of bitmap_t*/ - pf->bits_size = readlong(); + if (!readlong(&nbits, font)) + return NULL; + pf->bits_size = nbits; return pf; } /* Load memory font */ -static struct font* font_load_in_memory(struct font* pf) +static struct font* font_load_in_memory(struct font* pf, int font) { int32_t i, noffset, nwidth; - if (!HAVEBYTES(4)) + /* # longs of offset*/ + if (!readlong(&noffset, font)) return NULL; - /* # longs of offset*/ - noffset = readlong(); - /* # bytes of width*/ - nwidth = readlong(); + if (!readlong(&nwidth, font)) + return NULL; /* variable font data*/ - pf->bits = (unsigned char *)fileptr; - fileptr += pf->bits_size*sizeof(unsigned char); + pf->bits = (unsigned char *)fntfile[font].fileptr; + fntfile[font].fileptr += pf->bits_size*sizeof(unsigned char); if ( pf->bits_size < 0xFFDB ) { /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 1) & ~1); } else { /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 3) & ~3); } if (noffset) { if ( pf->bits_size < 0xFFDB ) { - long_offset = 0; - pf->offset = (unsigned short *)fileptr; - - /* Check we have sufficient buffer */ - if (!HAVEBYTES(noffset * sizeof(short))) - return NULL; - + fntfile[font].long_offset = 0; + pf->offset = (unsigned short *)fntfile[font].fileptr; for (i=0; ioffset))[i] = (unsigned short)readshort(); + unsigned short offset; + if (!readshort(&offset, font)) + return NULL; + ((unsigned short*)(pf->offset))[i] = (unsigned short)offset; } } else { - long_offset = 1; - pf->offset = (unsigned short *)fileptr; - - /* Check we have sufficient buffer */ - if (!HAVEBYTES(noffset * sizeof(int32_t))) - return NULL; - + fntfile[font].long_offset = 1; + pf->offset = (unsigned short *)fntfile[font].fileptr; for (i=0; ioffset))[i] = (uint32_t)readlong(); + uint32_t offset; + if (!readlong(&offset, font)) + return NULL; + ((uint32_t*)(pf->offset))[i] = (uint32_t)offset; } } } @@ -209,140 +262,140 @@ pf->offset = NULL; if (nwidth) { - pf->width = (unsigned char *)fileptr; - fileptr += nwidth*sizeof(unsigned char); + pf->width = (unsigned char *)fntfile[font].fileptr; + fntfile[font].fileptr += nwidth*sizeof(unsigned char); } else pf->width = NULL; - if (fileptr > eofptr) + if (fntfile[font].fileptr > fntfile[font].eofptr) return NULL; return pf; /* success!*/ } /* Load cached font */ -static struct font* font_load_cached(struct font* pf) +static struct font* font_load_cached(struct font* pf, int font) { uint32_t noffset, nwidth; - unsigned char* oldfileptr = fileptr; + unsigned char* oldfileptr = fntfile[font].fileptr; - if (!HAVEBYTES(2 * sizeof(int32_t))) + /* # longs of offset*/ + if (!readlong(&noffset, font)) return NULL; - /* # longs of offset*/ - noffset = readlong(); - /* # bytes of width*/ - nwidth = readlong(); + if (!readlong(&nwidth, font)) + return NULL; /* We are now at the bitmap data, this is fixed at 36.. */ pf->bits = NULL; /* Calculate offset to offset data */ - fileptr += pf->bits_size * sizeof(unsigned char); + fntfile[font].fileptr += pf->bits_size * sizeof(unsigned char); if ( pf->bits_size < 0xFFDB ) { - long_offset = 0; + fntfile[font].long_offset = 0; /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 1) & ~1); } else { - long_offset = 1; + fntfile[font].long_offset = 1; /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 3) & ~3); } if (noffset) - file_offset_offset = (uint32_t)(fileptr - freeptr); + fntfile[font].file_offset_offset = (uint32_t)(fntfile[font].fileptr - fntfile[font].freeptr); else - file_offset_offset = 0; + fntfile[font].file_offset_offset = 0; /* Calculate offset to widths data */ if ( pf->bits_size < 0xFFDB ) - fileptr += noffset * sizeof(unsigned short); + fntfile[font].fileptr += noffset * sizeof(unsigned short); else - fileptr += noffset * sizeof(uint32_t); + fntfile[font].fileptr += noffset * sizeof(uint32_t); if (nwidth) - file_width_offset = (uint32_t)(fileptr - freeptr); + fntfile[font].file_width_offset = (uint32_t)(fntfile[font].fileptr - fntfile[font].freeptr); else - file_width_offset = 0; + fntfile[font].file_width_offset = 0; - fileptr = oldfileptr; + fntfile[font].fileptr = oldfileptr; /* Create the cache */ - cache_create(pf->maxwidth, pf->height); + cache_create(pf->maxwidth, pf->height, font); return pf; } /* read and load font into incore font structure*/ -struct font* font_load(const char *path) +struct font* font_load(const char *path, int _font) { int size; - struct font* pf = &font_ui; + int font = _font - 1; /* cache index vs global font index */ + struct font* pf = sysfonts[_font]; /* save loaded glyphs */ - glyph_cache_save(); + glyph_cache_save(font); /* Close font file handle */ - if (fnt_file >= 0) - close(fnt_file); + if (fntfile[font].font_fd >= 0) + close(fntfile[font].font_fd); /* open and read entire font file*/ - fnt_file = open(path, O_RDONLY|O_BINARY); + fntfile[font].font_fd = open(path, O_RDONLY|O_BINARY); - if (fnt_file < 0) { + if (fntfile[font].font_fd < 0) { DEBUGF("Can't open font: %s\n", path); return NULL; } /* Check file size */ - size = filesize(fnt_file); + size = filesize(fntfile[font].font_fd); - font_reset(); + font_reset(_font); /* currently, font loading replaces earlier font allocation*/ - freeptr = (unsigned char *)(((intptr_t)mbuf + 3) & ~3); - fileptr = freeptr; + fntfile[font].freeptr = (unsigned char *)(((intptr_t)font_membuf[font] + 3) & ~3); + fntfile[font].fileptr = fntfile[font].freeptr; if (size > MAX_FONT_SIZE) { - read(fnt_file, fileptr, FONT_HEADER_SIZE); - eofptr = fileptr + FONT_HEADER_SIZE; + read(fntfile[font].font_fd, fntfile[font].fileptr, FONT_HEADER_SIZE); + fntfile[font].eofptr = fntfile[font].fileptr + FONT_HEADER_SIZE; - if (!font_load_header(pf)) + if (!font_load_header(pf, font)) { DEBUGF("Failed font header load"); return NULL; } - if (!font_load_cached(pf)) + if (!font_load_cached(pf, font)) { DEBUGF("Failed font cache load"); return NULL; } - glyph_cache_load(); + glyph_cache_load(font); } else { - read(fnt_file, fileptr, MAX_FONT_SIZE); - eofptr = fileptr + size; - close(fnt_file); - fnt_file = -1; + read(fntfile[font].font_fd, fntfile[font].fileptr, MAX_FONT_SIZE); + fntfile[font].eofptr = fntfile[font].fileptr + size; + close(fntfile[font].font_fd); + fntfile[font].font_fd = -1; - if (!font_load_header(pf)) + if (!font_load_header(pf, font)) { DEBUGF("Failed font header load"); return NULL; } - if (!font_load_in_memory(pf)) + if (!font_load_in_memory(pf, font)) { DEBUGF("Failed mem load"); return NULL; @@ -359,13 +412,25 @@ /* * Return a pointer to an incore font structure. * If the requested font isn't loaded/compiled-in, - * decrement the font number and try again. + * (decrement the font number and try again) + * MWE return sysfont instead + * */ -struct font* font_get(int font) +struct font *font_get(int font) { - struct font* pf; + struct font *pf; - if (font >= MAXFONTS) + if (font >= MAXFONTS){ + return &sysfont; + } + + pf = sysfonts[font]; + if (pf && pf->height) + return pf; + + return &sysfont; + +/* if (font >= MAXFONTS) font = 0; while (1) { @@ -374,14 +439,14 @@ return pf; if (--font < 0) panicf("No font!"); - } + }*/ } /* * Returns the stringsize of a given string. */ -int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber) +int font_getstringsize(const unsigned char *str, int *w, int *h, int font) { - struct font* pf = font_get(fontnumber); + struct font* pf = font_get(font); unsigned short ch; int width = 0; @@ -389,7 +454,7 @@ { /* get proportional width and glyph bits*/ - width += font_get_width(pf,ch); + width += font_get_width(pf, ch, font); } if ( w ) *w = width; @@ -402,17 +467,17 @@ * Reads an entry into cache entry */ static void -load_cache_entry(struct font_cache_entry* p, void* callback_data) +load_cache_entry(struct font_cache_entry* p, void* callback_data, int font) { struct font* pf = callback_data; unsigned short char_code = p->_char_code; unsigned char tmp[2]; - if (file_width_offset) + if (fntfile[font].file_width_offset) { - int width_offset = file_width_offset + char_code; - lseek(fnt_file, width_offset, SEEK_SET); - read(fnt_file, &(p->width), 1); + int width_offset = fntfile[font].file_width_offset + char_code; + lseek(fntfile[font].font_fd, width_offset, SEEK_SET); + read(fntfile[font].font_fd, &(p->width), 1); } else { @@ -421,14 +486,14 @@ int32_t bitmap_offset = 0; - if (file_offset_offset) + if (fntfile[font].file_offset_offset) { - int32_t offset = file_offset_offset + char_code * (long_offset ? sizeof(int32_t) : sizeof(short)); - lseek(fnt_file, offset, SEEK_SET); - read (fnt_file, tmp, 2); + int32_t offset = fntfile[font].file_offset_offset + char_code * (fntfile[font].long_offset ? sizeof(int32_t) : sizeof(short)); + lseek(fntfile[font].font_fd, offset, SEEK_SET); + read (fntfile[font].font_fd, tmp, 2); bitmap_offset = tmp[0] | (tmp[1] << 8); - if (long_offset) { - read (fnt_file, tmp, 2); + if (fntfile[font].long_offset) { + read (fntfile[font].font_fd, tmp, 2); bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); } } @@ -438,117 +503,173 @@ } int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; - lseek(fnt_file, file_offset, SEEK_SET); + lseek(fntfile[font].font_fd, file_offset, SEEK_SET); int src_bytes = p->width * ((pf->height + 7) / 8); - read(fnt_file, p->bitmap, src_bytes); + read(fntfile[font].font_fd, p->bitmap, src_bytes); } /* * Converts cbuf into a font cache */ -static void cache_create(int maxwidth, int height) +static void cache_create(int maxwidth, int height, int font) { /* maximum size of rotated bitmap */ int bitmap_size = maxwidth * ((height + 7) / 8); /* Initialise cache */ - font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); + font_cache_create(&sys_font_cache[font], &font_membuf[font], MAX_FONT_SIZE, bitmap_size); } /* * Returns width of character */ -int font_get_width(struct font* pf, unsigned short char_code) +int font_get_width(struct font* pf, unsigned short char_code, int font) { /* check input range*/ if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) char_code = pf->defaultchar; char_code -= pf->firstchar; - return (fnt_file >= 0 && pf != &sysfont)? - font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->width: - pf->width? pf->width[char_code]: pf->maxwidth; + if (pf == &sysfont || fntfile[font-1].font_fd < 0) /* sysfont or loaded into mem */ + { + if (pf->width) + return pf->width[char_code]; + else + return pf->maxwidth; + } + else /* cached */ + return font_cache_get(&sys_font_cache[font-1], char_code, load_cache_entry, pf, font-1)->width; } -const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) +const unsigned char* font_get_bits(struct font* pf, unsigned short char_code, int font) { const unsigned char* bits; /* check input range*/ if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) char_code = pf->defaultchar; - char_code -= pf->firstchar; + char_code -= pf->firstchar; - if (fnt_file >= 0 && pf != &sysfont) - { - bits = - (unsigned char*)font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->bitmap; + if (font <= 0 || fntfile[font-1].font_fd < 0) /* sysfont */ + bits = pf->bits + (pf->offset?pf->offset[char_code]:(((pf->height + 7) / 8) * pf->maxwidth * char_code)); + else + bits = (unsigned char*)font_cache_get(&sys_font_cache[font-1], char_code, load_cache_entry, pf, font-1)->bitmap; + + return bits; } - else + +static void glyph_file_write(void* data, int font) { - bits = pf->bits + (pf->offset? - pf->offset[char_code]: - (((pf->height + 7) / 8) * pf->maxwidth * char_code)); - } - - return bits; -} + struct font_cache_entry* p = data; + struct font* pf = sysfonts[font]; + unsigned short ch; + unsigned char tmp[2]; -static void glyph_file_write(void* data) -{ - struct font_cache_entry* p = data; - struct font* pf = &font_ui; - unsigned short ch; - unsigned char tmp[2]; + ch = p->_char_code + pf->firstchar; - ch = p->_char_code + pf->firstchar; + if (p->_char_code != 0xffff && fntfile[font].glyph_fd >= 0) { + tmp[0] = p->_char_code >> 8; + tmp[1] = p->_char_code & 0xff; - if (ch != 0xffff && glyph_file >= 0) { - tmp[0] = ch >> 8; - tmp[1] = ch & 0xff; - if (write(glyph_file, tmp, 2) != 2) { - close(glyph_file); - glyph_file = -1; + if (write(fntfile[font].glyph_fd, tmp, 2) != 2) { + close(fntfile[font].glyph_fd); + fntfile[font].glyph_fd = -1; + } } + return; } - return; -} -/* save the char codes of the loaded glyphs to a file */ -void glyph_cache_save(void) -{ + /* save the char codes of the loaded glyphs to a file */ +void glyph_cache_save(int font) + { - if (fnt_file >= 0) { + if (fntfile[font].font_fd >= 0) { - glyph_file = creat(GLYPH_CACHE_FILE); + switch (font) + { + case 0: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_UI); + break; + case 1: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER1); + break; + case 2: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER2); + break; + case 3: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER3); + break; + case 4: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER4); + break; + case 5: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER5); + break; + case 6: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER6); + break; + case 7: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER7); + break; + default: + return; + } - if (glyph_file < 0) return; + if (fntfile[font].glyph_fd < 0) return; - lru_traverse(&font_cache_ui._lru, glyph_file_write); + lru_traverse(&sys_font_cache[font]._lru, glyph_file_write, font); - if (glyph_file >= 0) - close(glyph_file); + if (fntfile[font].glyph_fd >= 0) + close(fntfile[font].glyph_fd); + } + return; } - return; -} -static void glyph_cache_load(void) -{ - if (fnt_file >= 0) { +static void glyph_cache_load(int font) + { + if (fntfile[font].font_fd >= 0) { int fd; unsigned char tmp[2]; unsigned short ch; - struct font* pf = &font_ui; + struct font* pf = sysfonts[font]; - fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); + switch (font) + { + case 0: + fd = open(GLYPH_CACHE_FILE_UI, O_RDONLY|O_BINARY); + break; + case 1: + fd = open(GLYPH_CACHE_FILE_USER1, O_RDONLY|O_BINARY); + break; + case 2: + fd = open(GLYPH_CACHE_FILE_USER2, O_RDONLY|O_BINARY); + break; + case 3: + fd = open(GLYPH_CACHE_FILE_USER3, O_RDONLY|O_BINARY); + break; + case 4: + fd = open(GLYPH_CACHE_FILE_USER4, O_RDONLY|O_BINARY); + break; + case 5: + fd = open(GLYPH_CACHE_FILE_USER5, O_RDONLY|O_BINARY); + break; + case 6: + fd = open(GLYPH_CACHE_FILE_USER6, O_RDONLY|O_BINARY); + break; + case 7: + fd = open(GLYPH_CACHE_FILE_USER7, O_RDONLY|O_BINARY); + break; + default: + return; + } if (fd >= 0) { while (read(fd, tmp, 2) == 2) { ch = (tmp[0] << 8) | tmp[1]; - font_get_bits(pf, ch); + font_get_bits(pf, ch, font); } close(fd); @@ -556,7 +677,7 @@ /* load latin1 chars into cache */ ch = 256; while (ch-- > 32) - font_get_bits(pf, ch); + font_get_bits(pf, ch, font); } } return; Index: firmware/font_cache.c =================================================================== --- firmware/font_cache.c (Revision 17518) +++ firmware/font_cache.c (Arbeitskopie) @@ -23,8 +23,9 @@ /******************************************************************************* * font_cache_lru_init ******************************************************************************/ -static void font_cache_lru_init(void* data) +static void font_cache_lru_init(void* data, int font) { + font = 0; /* Kill gcc warning */ struct font_cache_entry* p = data; p->_char_code = 0xffff; /* assume invalid char */ } @@ -60,7 +61,7 @@ lru_create(&fcache->_lru, lru_buf, cache_size, font_cache_entry_size); /* initialise cache */ - lru_traverse(&fcache->_lru, font_cache_lru_init); + lru_traverse(&fcache->_lru, font_cache_lru_init, 0); /* font parameter not needed for callback */ short i; for (i = 0; i < cache_size; i++) fcache->_index[i] = i; /* small cheat here */ @@ -158,8 +159,8 @@ struct font_cache_entry* font_cache_get( struct font_cache* fcache, unsigned short char_code, - void (*callback) (struct font_cache_entry* p, void *callback_data), - void *callback_data) + void (*callback) (struct font_cache_entry* p, void *callback_data, int font), + void *callback_data, int font) { int insertion_point = font_cache_insertion_point(fcache, char_code); if (insertion_point >= 0) @@ -207,7 +208,7 @@ fcache->_size++; p->_char_code = char_code; - callback(p, callback_data); + callback(p, callback_data, font); return p; } Index: firmware/include/font_cache.h =================================================================== --- firmware/include/font_cache.h (Revision 17518) +++ firmware/include/font_cache.h (Arbeitskopie) @@ -21,6 +21,10 @@ /******************************************************************************* * ******************************************************************************/ + +/* Maximum loadable/cacheable fonts. Exclude sysfont since it's compiled in */ +#define MAXCACHEFONTS MAXFONTS-1 + struct font_cache { struct lru _lru; @@ -36,6 +40,19 @@ unsigned char bitmap[1]; /* place holder */ }; +/* Per-font internal cache struct */ +struct font_file_info +{ + unsigned long file_width_offset; /* offset to file width data */ + unsigned long file_offset_offset; /* offset to file offset data */ + int long_offset; + int glyph_fd; + unsigned char *freeptr; + unsigned char *fileptr; + unsigned char *eofptr; + int font_fd; /* >=0 if font is cached */ +}; + /* void (*f) (void*, struct font_cache_entry*); */ /* Create an auto sized font cache from buf */ void font_cache_create( @@ -44,5 +61,5 @@ struct font_cache_entry* font_cache_get( struct font_cache* fcache, unsigned short char_code, - void (*callback) (struct font_cache_entry* p, void *callback_data), - void *callback_data); + void (*callback) (struct font_cache_entry* p, void *callback_data, int font), + void *callback_data, int font); Index: firmware/include/lru.h =================================================================== --- firmware/include/lru.h (Revision 17518) +++ firmware/include/lru.h (Arbeitskopie) @@ -40,7 +40,7 @@ /* Data */ void *lru_data(struct lru* pl, short handle); /* Traverse lru-wise */ -void lru_traverse(struct lru* pl, void (*callback)(void* data)); +void lru_traverse(struct lru* pl, void (*callback)(void* data, int font), int font); #endif /* LRU_H */ Index: firmware/lru.c =================================================================== --- firmware/lru.c (Revision 17518) +++ firmware/lru.c (Arbeitskopie) @@ -57,7 +57,7 @@ /******************************************************************************* * lru_traverse ******************************************************************************/ -void lru_traverse(struct lru* pl, void (*callback)(void* data)) +void lru_traverse(struct lru* pl, void (*callback)(void* data, int font), int font) { short i; struct lru_node* slot; @@ -66,7 +66,7 @@ for (i = 0; i < pl->_size; i++) { slot = lru_node_p(pl, loc); - callback(slot->data); + callback(slot->data, font); loc = slot->_next; } } Index: firmware/powermgmt.c =================================================================== --- firmware/powermgmt.c (Revision 17518) +++ firmware/powermgmt.c (Arbeitskopie) @@ -1201,7 +1201,12 @@ audio_stop(); if (battery_level_safe()) { /* do not save on critical battery */ #ifdef HAVE_LCD_BITMAP - glyph_cache_save(); + int i = FONT_UI; /* Skip sysfont, even though glyph_cache_save() would ignore it */ + while (i < MAXFONTS) + { + glyph_cache_save(i); + i++; + } #endif if(ata_disk_is_active()) ata_spindown(1); Index: firmware/drivers/lcd-1bit-vert.c =================================================================== --- firmware/drivers/lcd-1bit-vert.c (Revision 17518) +++ firmware/drivers/lcd-1bit-vert.c (Arbeitskopie) @@ -704,7 +704,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf, ch); + width = font_get_width(pf, ch, current_vp->font); if (ofs > width) { @@ -712,7 +712,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-2bit-vert.c =================================================================== --- firmware/drivers/lcd-2bit-vert.c (Revision 17518) +++ firmware/drivers/lcd-2bit-vert.c (Arbeitskopie) @@ -1031,7 +1031,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch,current_vp->font); if (ofs > width) { @@ -1039,7 +1039,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-2bit-horz.c =================================================================== --- firmware/drivers/lcd-2bit-horz.c (Revision 17518) +++ firmware/drivers/lcd-2bit-horz.c (Arbeitskopie) @@ -893,7 +893,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch,current_vp->font); if (ofs > width) { @@ -901,7 +901,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-2bit-vi.c =================================================================== --- firmware/drivers/lcd-2bit-vi.c (Revision 17518) +++ firmware/drivers/lcd-2bit-vi.c (Arbeitskopie) @@ -1048,7 +1048,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf, ch); + width = font_get_width(pf,ch, current_vp->font); if (ofs > width) { @@ -1056,7 +1056,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-16bit.c =================================================================== --- firmware/drivers/lcd-16bit.c (Revision 17518) +++ firmware/drivers/lcd-16bit.c (Arbeitskopie) @@ -926,7 +926,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch,current_vp->font); if (ofs > width) { @@ -934,7 +934,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);