1
0
Fork 0
forked from len0rd/rockbox

Revamp of the bitmap allocation for the fonts. Implements the idea from FS#9907 (reallocate when maxwidth grows), but does it correctly. Also gets rid of the warning "DWIDTH spec > ..." which is irritating since the bounding box header of the font is not required to specify the MAX width.

Also replaced TABs with spaces.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20219 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Alexander Levin 2009-03-06 22:50:47 +00:00
parent c8a60784d0
commit cbcef6700c

View file

@ -22,16 +22,20 @@
#define VERSION "RB11" #define VERSION "RB11"
#endif #endif
/* bitmap_t helper macros*/ /*
#define BITMAP_WORDS(x) (((x)+15)/16) /* image size in words*/ * bitmap_t helper macros
#define BITMAP_BYTES(x) (BITMAP_WORDS(x)*sizeof(bitmap_t)) */
typedef unsigned short bitmap_t; /* bitmap image unit size*/
/* Number of words to hold a pixel line of width x pixels */
#define BITMAP_BITSPERIMAGE (sizeof(bitmap_t) * 8) #define BITMAP_BITSPERIMAGE (sizeof(bitmap_t) * 8)
#define BITMAP_WORDS(x) (((x)+BITMAP_BITSPERIMAGE-1)/BITMAP_BITSPERIMAGE)
#define BITMAP_BYTES(x) (BITMAP_WORDS(x)*sizeof(bitmap_t))
#define BITMAP_BITVALUE(n) ((bitmap_t) (((bitmap_t) 1) << (n))) #define BITMAP_BITVALUE(n) ((bitmap_t) (((bitmap_t) 1) << (n)))
#define BITMAP_FIRSTBIT (BITMAP_BITVALUE(BITMAP_BITSPERIMAGE - 1)) #define BITMAP_FIRSTBIT (BITMAP_BITVALUE(BITMAP_BITSPERIMAGE - 1))
#define BITMAP_TESTBIT(m) ((m) & BITMAP_FIRSTBIT) #define BITMAP_TESTBIT(m) ((m) & BITMAP_FIRSTBIT)
#define BITMAP_SHIFTBIT(m) ((bitmap_t) ((m) << 1)) #define BITMAP_SHIFTBIT(m) ((bitmap_t) ((m) << 1))
typedef unsigned short bitmap_t; /* bitmap image unit size*/
/* builtin C-based proportional/fixed font structure */ /* builtin C-based proportional/fixed font structure */
/* based on The Microwindows Project http://microwindows.org */ /* based on The Microwindows Project http://microwindows.org */
@ -42,7 +46,7 @@ struct font {
int firstchar; /* first character in bitmap */ int firstchar; /* first character in bitmap */
int size; /* font size in glyphs ('holes' included) */ int size; /* font size in glyphs ('holes' included) */
bitmap_t* bits; /* 16-bit right-padded bitmap data */ bitmap_t* bits; /* 16-bit right-padded bitmap data */
unsigned int* offset; /* offsets into bitmap data*/ int* offset; /* offsets into bitmap data */
unsigned char* width; /* character widths or NULL if fixed */ unsigned char* width; /* character widths or NULL if fixed */
int defaultchar; /* default char (not glyph index) */ int defaultchar; /* default char (not glyph index) */
int bits_size; /* # words of bitmap_t bits */ int bits_size; /* # words of bitmap_t bits */
@ -71,8 +75,6 @@ struct font {
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#define EXTRA 300 /* # bytes extra allocation for buggy .bdf files*/
int gen_c = 0; int gen_c = 0;
int gen_h = 0; int gen_h = 0;
int gen_fnt = 0; int gen_fnt = 0;
@ -92,6 +94,7 @@ int bdf_read_header(FILE *fp, struct font* pf);
int bdf_read_bitmaps(FILE *fp, struct font* pf); int bdf_read_bitmaps(FILE *fp, struct font* pf);
char * bdf_getline(FILE *fp, char *buf, int len); char * bdf_getline(FILE *fp, char *buf, int len);
bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2); bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2);
void bitmap_buf_alloc(struct font* pf);
int gen_c_source(struct font* pf, char *path); int gen_c_source(struct font* pf, char *path);
int gen_h_header(struct font* pf, char *path); int gen_h_header(struct font* pf, char *path);
@ -312,6 +315,7 @@ struct font* bdf_read_font(char *path)
pf = (struct font*)calloc(1, sizeof(struct font)); pf = (struct font*)calloc(1, sizeof(struct font));
if (!pf) if (!pf)
goto errout; goto errout;
memset(pf, 0, sizeof(struct font));
pf->name = strdup(basename(path)); pf->name = strdup(basename(path));
@ -350,7 +354,6 @@ struct font* bdf_read_font(char *path)
int bdf_read_header(FILE *fp, struct font* pf) int bdf_read_header(FILE *fp, struct font* pf)
{ {
int encoding; int encoding;
int maxwidth;
int firstchar = 65535; int firstchar = 65535;
int lastchar = -1; int lastchar = -1;
char buf[256]; char buf[256];
@ -461,17 +464,17 @@ int bdf_read_header(FILE *fp, struct font* pf)
/* calc font size (offset/width entries) */ /* calc font size (offset/width entries) */
pf->firstchar = firstchar; pf->firstchar = firstchar;
pf->size = lastchar - firstchar + 1; pf->size = lastchar - firstchar + 1;
if (pf->size < pf->nchars) {
fprintf(stderr, "Error: NCHARS and max code mismatch\n");
return 0;
}
/* use the font boundingbox to get initial maxwidth */ /* use the font boundingbox to get initial maxwidth */
/*maxwidth = pf->fbbw - pf->fbbx;*/ /*maxwidth = pf->fbbw - pf->fbbx;*/
maxwidth = pf->fbbw; pf->maxwidth = pf->fbbw;
bitmap_buf_alloc(pf); /* Allocate bitmaps */
/* initially use font maxwidth * height for bits allocation*/ pf->offset = (int *)malloc(pf->size * sizeof(int));
pf->bits_size = pf->nchars * BITMAP_WORDS(maxwidth) * pf->height;
/* allocate bits, offset, and width arrays*/
pf->bits = (bitmap_t *)malloc(pf->bits_size * sizeof(bitmap_t) + EXTRA);
pf->offset = (unsigned int *)malloc(pf->size * sizeof(unsigned int));
pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int)); pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int));
pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char)); pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char));
@ -488,13 +491,14 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
{ {
int ofs = 0; int ofs = 0;
int ofr = 0; int ofr = 0;
int maxwidth = 0;
int i, k, encoding, width; int i, k, encoding, width;
int bbw, bbh, bbx, bby; int bbw, bbh, bbx, bby;
int proportional = 0; int proportional = 0;
int encodetable = 0; int encodetable = 0;
int l; int l;
char buf[256]; char buf[256];
bitmap_t *ch_bitmap;
int ch_words;
/* reset file pointer */ /* reset file pointer */
fseek(fp, 0L, SEEK_SET); fseek(fp, 0L, SEEK_SET);
@ -543,8 +547,6 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
continue; continue;
} }
if (strequal(buf, "BITMAP") || strequal(buf, "BITMAP ")) { if (strequal(buf, "BITMAP") || strequal(buf, "BITMAP ")) {
bitmap_t *ch_bitmap = pf->bits + ofs;
int ch_words;
int overflow_asc, overflow_desc; int overflow_asc, overflow_desc;
int bbh_orig, bby_orig, y; int bbh_orig, bby_orig, y;
@ -552,7 +554,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
continue; continue;
/* set bits offset in encode map*/ /* set bits offset in encode map*/
if (pf->offset[encoding-pf->firstchar] != (unsigned int)-1) { if (pf->offset[encoding-pf->firstchar] != -1) {
fprintf(stderr, "Error: duplicate encoding for character %d (0x%02x), ignoring duplicate\n", fprintf(stderr, "Error: duplicate encoding for character %d (0x%02x), ignoring duplicate\n",
encoding, encoding); encoding, encoding);
continue; continue;
@ -562,19 +564,20 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
/* calc char width */ /* calc char width */
if (bbx < 0) { if (bbx < 0) {
/* Rockbox can't render overlapping glyphs */
width -= bbx; width -= bbx;
/*if (width > maxwidth)
width = maxwidth;*/
bbx = 0; bbx = 0;
} }
if (width > maxwidth) if (width > pf->maxwidth) {
maxwidth = width; pf->maxwidth = width;
bitmap_buf_alloc(pf); /* Re-allocate bitmaps since the maxwidth has grown */
}
pf->width[encoding-pf->firstchar] = width; pf->width[encoding-pf->firstchar] = width;
/* clear bitmap*/ ch_bitmap = pf->bits + ofs;
memset(ch_bitmap, 0, BITMAP_BYTES(width) * pf->height);
ch_words = BITMAP_WORDS(width); ch_words = BITMAP_WORDS(width);
memset(ch_bitmap, 0, BITMAP_BYTES(width) * pf->height); /* clear bitmap */
#define BM(row,col) (*(ch_bitmap + ((row)*ch_words) + (col))) #define BM(row,col) (*(ch_bitmap + ((row)*ch_words) + (col)))
#define BITMAP_NIBBLES (BITMAP_BITSPERIMAGE/4) #define BITMAP_NIBBLES (BITMAP_BITSPERIMAGE/4)
@ -615,7 +618,8 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
int hexnibbles; int hexnibbles;
if (!bdf_getline(fp, buf, sizeof(buf))) { if (!bdf_getline(fp, buf, sizeof(buf))) {
fprintf(stderr, "Error: EOF reading BITMAP data\n"); fprintf(stderr, "Error: EOF reading BITMAP data for character %d\n",
encoding);
return 0; return 0;
} }
if (isprefix(buf, "ENDCHAR")) if (isprefix(buf, "ENDCHAR"))
@ -662,14 +666,11 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
break; break;
} }
/* set max width*/
pf->maxwidth = maxwidth;
/* change unused width values to default char values */ /* change unused width values to default char values */
for (i=0; i<pf->size; ++i) { for (i=0; i<pf->size; ++i) {
int defchar = pf->defaultchar - pf->firstchar; int defchar = pf->defaultchar - pf->firstchar;
if (pf->offset[i] == (unsigned int)-1) if (pf->offset[i] == -1)
pf->width[i] = pf->width[defchar]; pf->width[i] = pf->width[defchar];
} }
@ -700,7 +701,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
/* determine whether font is fixed-width */ /* determine whether font is fixed-width */
for (i=0; i<pf->size; ++i) { for (i=0; i<pf->size; ++i) {
if (pf->width[i] != maxwidth) { if (pf->width[i] != pf->maxwidth) {
proportional = 1; proportional = 1;
break; break;
} }
@ -715,16 +716,6 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
pf->bits = realloc(pf->bits, ofs * sizeof(bitmap_t)); pf->bits = realloc(pf->bits, ofs * sizeof(bitmap_t));
pf->bits_size = ofs; pf->bits_size = ofs;
} }
else {
if (ofs > pf->bits_size) {
fprintf(stderr, "Warning: DWIDTH spec > max FONTBOUNDINGBOX\n");
if (ofs > pf->bits_size+EXTRA) {
fprintf(stderr, "Error: Not enough bits initially allocated\n");
return 0;
}
pf->bits_size = ofs;
}
}
#ifdef ROTATE #ifdef ROTATE
pf->bits_size = ofr; /* always update, rotated is smaller */ pf->bits_size = ofr; /* always update, rotated is smaller */
@ -759,6 +750,19 @@ char *bdf_getline(FILE *fp, char *buf, int len)
return buf; return buf;
} }
/*
Calculates the necessary size of the bit buffer to hold all the
bitmaps for the glyphs in the font. Shoud be called every time
the max width of the font grows. Font height, the max width and
the number of chars in the font must have been already set.
*/
void bitmap_buf_alloc(struct font* pf)
{
pf->bits_size = pf->size * BITMAP_WORDS(pf->maxwidth) * pf->height;
pf->bits = (bitmap_t *)realloc(pf->bits, pf->bits_size * sizeof(bitmap_t));
}
/* return hex value of portion of buffer*/ /* return hex value of portion of buffer*/
bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2) bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2)
{ {
@ -913,7 +917,7 @@ int gen_c_source(struct font* pf, char *path)
bitmap_t bitvalue=0; bitmap_t bitvalue=0;
/* Skip missing glyphs */ /* Skip missing glyphs */
if (pf->offset && (pf->offset[i] == (unsigned int)-1)) if (pf->offset && (pf->offset[i] == -1))
continue; continue;
bits = pf->bits + (pf->offset? (int)pf->offset[i]: (pf->height * i)); bits = pf->bits + (pf->offset? (int)pf->offset[i]: (pf->height * i));
@ -994,7 +998,7 @@ int gen_c_source(struct font* pf, char *path)
"static const unsigned short _sysfont_offset[] = {\n"); "static const unsigned short _sysfont_offset[] = {\n");
for (i=0; i<pf->size; ++i) { for (i=0; i<pf->size; ++i) {
if (pf->offset[i] == (unsigned int)-1) { if (pf->offset[i] == -1) {
pf->offset[i] = pf->offset[pf->defaultchar - pf->firstchar]; pf->offset[i] = pf->offset[pf->defaultchar - pf->firstchar];
pf->offrot[i] = pf->offrot[pf->defaultchar - pf->firstchar]; pf->offrot[i] = pf->offrot[pf->defaultchar - pf->firstchar];
} }
@ -1201,7 +1205,7 @@ int gen_fnt_file(struct font* pf, char *path)
unsigned char bytemap[512]; unsigned char bytemap[512];
/* Skip missing glyphs */ /* Skip missing glyphs */
if (pf->offset && (pf->offset[i] == (unsigned int)-1)) if (pf->offset && (pf->offset[i] == -1))
continue; continue;
bits = pf->bits + (pf->offset? (int)pf->offset[i]: (pf->height * i)); bits = pf->bits + (pf->offset? (int)pf->offset[i]: (pf->height * i));
@ -1231,7 +1235,7 @@ int gen_fnt_file(struct font* pf, char *path)
{ {
for (i=0; i<pf->size; ++i) for (i=0; i<pf->size; ++i)
{ {
if (pf->offset[i] == (unsigned int)-1) { if (pf->offset[i] == -1) {
pf->offrot[i] = pf->offrot[pf->defaultchar - pf->firstchar]; pf->offrot[i] = pf->offrot[pf->defaultchar - pf->firstchar];
} }
if ( pf->bits_size < 0xFFDB ) if ( pf->bits_size < 0xFFDB )