forked from len0rd/rockbox
Introduced new options for convbdf that specify how the ascent/descent is allowed to grow to avoid glyph clipping.
The syntax is (for ascent, descent is similar): N[%][!]. E.g. -a3 allows ascent to become 3 pixels greater; -a3! forces ascent to become 3 px greater; -a20% allows ascent to grow 20% from what is specified in the font. By default, ascent/descent are not allowed to grow. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20239 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
66cf3a3329
commit
bded5db2d9
1 changed files with 287 additions and 57 deletions
342
tools/convbdf.c
342
tools/convbdf.c
|
@ -54,6 +54,9 @@ struct font {
|
||||||
|
|
||||||
/* unused by runtime system, read in by convbdf */
|
/* unused by runtime system, read in by convbdf */
|
||||||
int nchars; /* number of different glyphs */
|
int nchars; /* number of different glyphs */
|
||||||
|
int nchars_declared; /* number of glyphs as declared in the header */
|
||||||
|
int ascent_declared; /* ascent as declared in the header */
|
||||||
|
int descent_declared; /* descent as declared in the header */
|
||||||
unsigned int* offrot; /* offsets into rotated bitmap data */
|
unsigned int* offrot; /* offsets into rotated bitmap data */
|
||||||
char* name; /* font name */
|
char* name; /* font name */
|
||||||
char* facename; /* facename of font */
|
char* facename; /* facename of font */
|
||||||
|
@ -70,6 +73,13 @@ struct font {
|
||||||
};
|
};
|
||||||
/* END font.h*/
|
/* END font.h*/
|
||||||
|
|
||||||
|
/* Description of how the ascent/descent is allowed to grow */
|
||||||
|
struct stretch {
|
||||||
|
int value; /* The delta value (in pixels or percents) */
|
||||||
|
int percent; /* Is the value in percents (true) or pixels (false)? */
|
||||||
|
int force; /* MUST the value be set (true) or is it just a max (false) */
|
||||||
|
};
|
||||||
|
|
||||||
#define isprefix(buf,str) (!strncmp(buf, str, strlen(str)))
|
#define isprefix(buf,str) (!strncmp(buf, str, strlen(str)))
|
||||||
#define strequal(s1,s2) (!strcmp(s1, s2))
|
#define strequal(s1,s2) (!strcmp(s1, s2))
|
||||||
|
|
||||||
|
@ -78,14 +88,17 @@ struct font {
|
||||||
|
|
||||||
/* Depending on the verbosity level some warnings are printed or not */
|
/* Depending on the verbosity level some warnings are printed or not */
|
||||||
int verbosity_level = 0;
|
int verbosity_level = 0;
|
||||||
|
int trace = 0;
|
||||||
|
|
||||||
/* Prints a warning of the specified verbosity level. It will only be
|
/* Prints a warning of the specified verbosity level. It will only be
|
||||||
really printed if the level is >= the level set in the settings */
|
really printed if the level is >= the level set in the settings */
|
||||||
void print_warning(int level, const char *fmt, ...);
|
void print_warning(int level, const char *fmt, ...);
|
||||||
void print_error(const char *fmt, ...);
|
void print_error(const char *fmt, ...);
|
||||||
void print_info(const char *fmt, ...);
|
void print_info(const char *fmt, ...);
|
||||||
#define VL_CLIP 1 /* Verbosity level for clip related warnings */
|
void print_trace(const char *fmt, ...);
|
||||||
#define VL_MIS 1 /* Verbosity level for other warnings */
|
#define VL_CLIP_FONT 1 /* Verbosity level for clip related warnings at font level */
|
||||||
|
#define VL_CLIP_CHAR 2 /* Verbosity level for clip related warnings at char level */
|
||||||
|
#define VL_MISC 1 /* Verbosity level for other warnings */
|
||||||
|
|
||||||
int gen_c = 0;
|
int gen_c = 0;
|
||||||
int gen_h = 0;
|
int gen_h = 0;
|
||||||
|
@ -96,6 +109,10 @@ int limit_char = 65535;
|
||||||
int oflag = 0;
|
int oflag = 0;
|
||||||
char outfile[256];
|
char outfile[256];
|
||||||
|
|
||||||
|
struct stretch stretch_ascent = { 0, 0, 1 }; /* Don't allow ascent to grow by default */
|
||||||
|
struct stretch stretch_descent = { 0, 0, 1 }; /* Don't allow descent to grow by default */
|
||||||
|
|
||||||
|
|
||||||
void usage(void);
|
void usage(void);
|
||||||
void getopts(int *pac, char ***pav);
|
void getopts(int *pac, char ***pav);
|
||||||
int convbdf(char *path);
|
int convbdf(char *path);
|
||||||
|
@ -104,9 +121,20 @@ void free_font(struct font* pf);
|
||||||
struct font* bdf_read_font(char *path);
|
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 bdf_read_bitmaps(FILE *fp, struct font* pf);
|
int bdf_read_bitmaps(FILE *fp, struct font* pf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Counts the glyphs and determines the max dimensions of glyphs
|
||||||
|
(fills the fields nchars, maxwidth, max_over_ascent, max_over_descent).
|
||||||
|
Returns 0 on failure or not-0 on success.
|
||||||
|
*/
|
||||||
|
int bdf_analyze_font(FILE *fp, struct font* pf);
|
||||||
|
void bdf_correct_bbx(int *width, int *bbx); /* Corrects bbx and width if bbx<0 */
|
||||||
|
|
||||||
|
/* Corrects the ascent and returns the new value (value to use) */
|
||||||
|
int adjust_ascent(int ascent, int overflow, struct stretch *stretch);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -115,20 +143,53 @@ int gen_fnt_file(struct font* pf, char *path);
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
char help[] = {
|
/* We use string array because some C compilers issue warnings about too long strings */
|
||||||
"Usage: convbdf [options] [input-files]\n"
|
char *help[] = {
|
||||||
" convbdf [options] [-o output-file] [single-input-file]\n"
|
"Usage: convbdf [options] [input-files]\n",
|
||||||
"Options:\n"
|
" convbdf [options] [-o output-file] [single-input-file]\n",
|
||||||
" -c Convert .bdf to .c source file\n"
|
"Options:\n",
|
||||||
" -h Convert .bdf to .h header file (to create sysfont.h)\n"
|
" -c Convert .bdf to .c source file\n",
|
||||||
" -f Convert .bdf to .fnt font file\n"
|
" -h Convert .bdf to .h header file (to create sysfont.h)\n",
|
||||||
" -s N Start output at character encodings >= N\n"
|
" -f Convert .bdf to .fnt font file\n",
|
||||||
" -l N Limit output to character encodings <= N\n"
|
" -s N Start output at character encodings >= N\n",
|
||||||
" -n Don't generate bitmaps as comments in .c file\n"
|
" -l N Limit output to character encodings <= N\n",
|
||||||
" -v N Verbosity level: 0=quite quiet, 1=more verbose, 2=even more, etc.\n"
|
" -n Don't generate bitmaps as comments in .c file\n",
|
||||||
|
" -a N[%][!] Allow the ascent to grow N pixels/% to avoid glyph clipping\n",
|
||||||
|
" -d N[%][!] Allow the descent to grow N pixels/% to avoid glyph clipping\n",
|
||||||
|
" -v N Verbosity level: 0=quite quiet, 1=more verbose, 2=even more, etc.\n",
|
||||||
|
" -t Print internal tracing messages\n",
|
||||||
|
NULL /* Must be the last element in the array */
|
||||||
};
|
};
|
||||||
|
|
||||||
print_info("%s", help);
|
char **p = help;
|
||||||
|
while (*p != NULL)
|
||||||
|
print_info("%s", *(p++));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_ascent_opt(char *val, struct stretch *opt) {
|
||||||
|
char buf[256];
|
||||||
|
char *p;
|
||||||
|
strcpy(buf, val);
|
||||||
|
|
||||||
|
opt->force = 0;
|
||||||
|
opt->percent = 0;
|
||||||
|
p = buf + strlen(buf);
|
||||||
|
while (p > buf) {
|
||||||
|
p--;
|
||||||
|
if (*p == '%') {
|
||||||
|
opt->percent = 1;
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
else if (*p == '!') {
|
||||||
|
opt->force = 1;
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt->value = atoi(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse command line options*/
|
/* parse command line options*/
|
||||||
|
@ -199,6 +260,30 @@ void getopts(int *pac, char ***pav)
|
||||||
start_char = atoi(av[0]);
|
start_char = atoi(av[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'a': /* ascent growth */
|
||||||
|
if (*p) {
|
||||||
|
parse_ascent_opt(p, &stretch_ascent);
|
||||||
|
while (*p && *p != ' ')
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
av++; ac--;
|
||||||
|
if (ac > 0)
|
||||||
|
parse_ascent_opt(av[0], &stretch_ascent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd': /* descent growth */
|
||||||
|
if (*p) {
|
||||||
|
parse_ascent_opt(p, &stretch_descent);
|
||||||
|
while (*p && *p != ' ')
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
av++; ac--;
|
||||||
|
if (ac > 0)
|
||||||
|
parse_ascent_opt(av[0], &stretch_descent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'v': /* verbosity */
|
case 'v': /* verbosity */
|
||||||
if (*p) {
|
if (*p) {
|
||||||
verbosity_level = atoi(p);
|
verbosity_level = atoi(p);
|
||||||
|
@ -211,6 +296,9 @@ void getopts(int *pac, char ***pav)
|
||||||
verbosity_level = atoi(av[0]);
|
verbosity_level = atoi(av[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 't': /* tracing */
|
||||||
|
trace = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print_info("Unknown option ignored: %c\n", *(p-1));
|
print_info("Unknown option ignored: %c\n", *(p-1));
|
||||||
}
|
}
|
||||||
|
@ -230,6 +318,16 @@ void print_warning(int level, const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_trace(const char *fmt, ...) {
|
||||||
|
if (trace) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
fprintf(stderr, "TRACE: ");
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_error(const char *fmt, ...) {
|
void print_error(const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -374,21 +472,64 @@ struct font* bdf_read_font(char *path)
|
||||||
print_error("Error reading font header\n");
|
print_error("Error reading font header\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
print_trace("Read font header, nchars_decl=%d\n", pf->nchars_declared);
|
||||||
|
|
||||||
|
if (!bdf_analyze_font(fp, pf)) {
|
||||||
|
print_error("Error analyzing the font\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
print_trace("Analyzed font, nchars=%d, maxwidth=%d, asc_over=%d, desc_over=%d\n",
|
||||||
|
pf->nchars, pf->maxwidth, pf->max_over_ascent, pf->max_over_descent);
|
||||||
|
|
||||||
|
if (pf->nchars != pf->nchars_declared) {
|
||||||
|
print_warning(VL_MISC, "The declared number of chars (%d) "
|
||||||
|
"does not match the real number (%d)\n",
|
||||||
|
pf->nchars_declared, pf->nchars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Correct ascent/descent if necessary */
|
||||||
|
pf->ascent = adjust_ascent(pf->ascent_declared, pf->max_over_ascent, &stretch_ascent);
|
||||||
|
if (pf->ascent != pf->ascent_declared) {
|
||||||
|
print_info("Font ascent has been changed from %d to %d\n",
|
||||||
|
pf->ascent_declared, pf->ascent);
|
||||||
|
}
|
||||||
|
pf->descent = adjust_ascent(pf->descent, pf->max_over_descent, &stretch_descent);
|
||||||
|
if (pf->descent != pf->descent_declared) {
|
||||||
|
print_info("Font descent has been changed from %d to %d\n",
|
||||||
|
pf->descent_declared, pf->descent);
|
||||||
|
}
|
||||||
|
pf->height = pf->ascent + pf->descent;
|
||||||
|
if (pf->height != pf->ascent_declared + pf->descent_declared) {
|
||||||
|
print_warning(VL_CLIP_FONT, "Generated font's height: %d\n", pf->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alocate memory */
|
||||||
|
pf->bits_size = pf->size * BITMAP_WORDS(pf->maxwidth) * pf->height;
|
||||||
|
pf->bits = (bitmap_t *)malloc(pf->bits_size * sizeof(bitmap_t));
|
||||||
|
pf->offset = (int *)malloc(pf->size * sizeof(int));
|
||||||
|
pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int));
|
||||||
|
pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char));
|
||||||
|
|
||||||
|
if (!pf->bits || !pf->offset || !pf->offrot || !pf->width) {
|
||||||
|
print_error("no memory for font load\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
pf->max_over_ascent = pf->max_over_descent = 0;
|
|
||||||
pf->num_clipped_ascent = pf->num_clipped_descent = pf->num_clipped = 0;
|
pf->num_clipped_ascent = pf->num_clipped_descent = pf->num_clipped = 0;
|
||||||
|
pf->max_over_ascent = pf->max_over_descent = 0;
|
||||||
|
|
||||||
if (!bdf_read_bitmaps(fp, pf)) {
|
if (!bdf_read_bitmaps(fp, pf)) {
|
||||||
print_error("Error reading font bitmaps\n");
|
print_error("Error reading font bitmaps\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
print_trace("Read bitmaps\n");
|
||||||
|
|
||||||
if (pf->num_clipped > 0) {
|
if (pf->num_clipped > 0) {
|
||||||
print_warning(VL_CLIP, "%d character(s) out of %d were clipped "
|
print_warning(VL_CLIP_FONT, "%d character(s) out of %d were clipped "
|
||||||
"(%d at ascent, %d at descent)\n",
|
"(%d at ascent, %d at descent)\n",
|
||||||
pf->num_clipped, pf->nchars,
|
pf->num_clipped, pf->nchars,
|
||||||
pf->num_clipped_ascent, pf->num_clipped_descent);
|
pf->num_clipped_ascent, pf->num_clipped_descent);
|
||||||
print_warning(VL_CLIP, "max overflows: %d pixel(s) at ascent, %d pixel(s) at descent\n",
|
print_warning(VL_CLIP_FONT, "max overflows: %d pixel(s) at ascent, %d pixel(s) at descent\n",
|
||||||
pf->max_over_ascent, pf->max_over_descent);
|
pf->max_over_ascent, pf->max_over_descent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,17 +585,19 @@ int bdf_read_header(FILE *fp, struct font* pf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isprefix(buf, "FONT_DESCENT ")) {
|
if (isprefix(buf, "FONT_DESCENT ")) {
|
||||||
if (sscanf(buf, "FONT_DESCENT %d", &pf->descent) != 1) {
|
if (sscanf(buf, "FONT_DESCENT %d", &pf->descent_declared) != 1) {
|
||||||
print_error("bad 'FONT_DESCENT'\n");
|
print_error("bad 'FONT_DESCENT'\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
pf->descent = pf->descent_declared; /* For now */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isprefix(buf, "FONT_ASCENT ")) {
|
if (isprefix(buf, "FONT_ASCENT ")) {
|
||||||
if (sscanf(buf, "FONT_ASCENT %d", &pf->ascent) != 1) {
|
if (sscanf(buf, "FONT_ASCENT %d", &pf->ascent_declared) != 1) {
|
||||||
print_error("bad 'FONT_ASCENT'\n");
|
print_error("bad 'FONT_ASCENT'\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
pf->ascent = pf->ascent_declared; /* For now */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isprefix(buf, "FONTBOUNDINGBOX ")) {
|
if (isprefix(buf, "FONTBOUNDINGBOX ")) {
|
||||||
|
@ -466,7 +609,7 @@ int bdf_read_header(FILE *fp, struct font* pf)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isprefix(buf, "CHARS ")) {
|
if (isprefix(buf, "CHARS ")) {
|
||||||
if (sscanf(buf, "CHARS %d", &pf->nchars) != 1) {
|
if (sscanf(buf, "CHARS %d", &pf->nchars_declared) != 1) {
|
||||||
print_error("bad 'CHARS'\n");
|
print_error("bad 'CHARS'\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -516,20 +659,6 @@ int bdf_read_header(FILE *fp, struct font* pf)
|
||||||
pf->firstchar = firstchar;
|
pf->firstchar = firstchar;
|
||||||
pf->size = lastchar - firstchar + 1;
|
pf->size = lastchar - firstchar + 1;
|
||||||
|
|
||||||
/* use the font boundingbox to get initial maxwidth */
|
|
||||||
/*maxwidth = pf->fbbw - pf->fbbx;*/
|
|
||||||
pf->maxwidth = pf->fbbw;
|
|
||||||
bitmap_buf_alloc(pf); /* Allocate bitmaps */
|
|
||||||
|
|
||||||
pf->offset = (int *)malloc(pf->size * sizeof(int));
|
|
||||||
pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int));
|
|
||||||
pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char));
|
|
||||||
|
|
||||||
if (!pf->bits || !pf->offset || !pf->offrot || !pf->width) {
|
|
||||||
print_error("no memory for font load\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,15 +739,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
|
||||||
pf->offrot[encoding-pf->firstchar] = ofr;
|
pf->offrot[encoding-pf->firstchar] = ofr;
|
||||||
|
|
||||||
/* calc char width */
|
/* calc char width */
|
||||||
if (bbx < 0) {
|
bdf_correct_bbx(&width, &bbx);
|
||||||
/* Rockbox can't render overlapping glyphs */
|
|
||||||
width -= bbx;
|
|
||||||
bbx = 0;
|
|
||||||
}
|
|
||||||
if (width > pf->maxwidth) {
|
|
||||||
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;
|
||||||
|
|
||||||
ch_bitmap = pf->bits + ofs;
|
ch_bitmap = pf->bits + ofs;
|
||||||
|
@ -638,7 +759,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
|
||||||
pf->max_over_ascent = overflow_asc;
|
pf->max_over_ascent = overflow_asc;
|
||||||
}
|
}
|
||||||
bbh = MAX(bbh - overflow_asc, 0); /* Clipped -> decrease the height */
|
bbh = MAX(bbh - overflow_asc, 0); /* Clipped -> decrease the height */
|
||||||
print_warning(VL_CLIP, "character %d goes %d pixel(s)"
|
print_warning(VL_CLIP_CHAR, "character %d goes %d pixel(s)"
|
||||||
" beyond the font's ascent, it will be clipped\n",
|
" beyond the font's ascent, it will be clipped\n",
|
||||||
encoding, overflow_asc);
|
encoding, overflow_asc);
|
||||||
}
|
}
|
||||||
|
@ -650,7 +771,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf)
|
||||||
}
|
}
|
||||||
bby += overflow_desc;
|
bby += overflow_desc;
|
||||||
bbh = MAX(bbh - overflow_desc, 0); /* Clipped -> decrease the height */
|
bbh = MAX(bbh - overflow_desc, 0); /* Clipped -> decrease the height */
|
||||||
print_warning(VL_CLIP, "character %d goes %d pixel(s)"
|
print_warning(VL_CLIP_CHAR, "character %d goes %d pixel(s)"
|
||||||
" beyond the font's descent, it will be clipped\n",
|
" beyond the font's descent, it will be clipped\n",
|
||||||
encoding, overflow_desc);
|
encoding, overflow_desc);
|
||||||
}
|
}
|
||||||
|
@ -797,16 +918,125 @@ char *bdf_getline(FILE *fp, char *buf, int len)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void bdf_correct_bbx(int *width, int *bbx) {
|
||||||
Calculates the necessary size of the bit buffer to hold all the
|
if (*bbx < 0) {
|
||||||
bitmaps for the glyphs in the font. Shoud be called every time
|
/* Rockbox can't render overlapping glyphs */
|
||||||
the max width of the font grows. Font height, the max width and
|
*width -= *bbx;
|
||||||
the number of chars in the font must have been already set.
|
*bbx = 0;
|
||||||
*/
|
}
|
||||||
void bitmap_buf_alloc(struct font* pf)
|
}
|
||||||
{
|
|
||||||
pf->bits_size = pf->size * BITMAP_WORDS(pf->maxwidth) * pf->height;
|
int bdf_analyze_font(FILE *fp, struct font* pf) {
|
||||||
pf->bits = (bitmap_t *)realloc(pf->bits, pf->bits_size * sizeof(bitmap_t));
|
char buf[256];
|
||||||
|
int encoding;
|
||||||
|
int width, bbw, bbh, bbx, bby, overflow;
|
||||||
|
int read_enc = 0, read_width = 0, read_bbx = 0, read_endchar = 1;
|
||||||
|
int ignore_char = 0;
|
||||||
|
|
||||||
|
/* reset file pointer */
|
||||||
|
fseek(fp, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
pf->maxwidth = 0;
|
||||||
|
pf->nchars = 0;
|
||||||
|
pf->max_over_ascent = pf->max_over_descent = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
if (!bdf_getline(fp, buf, sizeof(buf))) {
|
||||||
|
print_error("EOF on file\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "ENDFONT")) {
|
||||||
|
if (!read_endchar) {
|
||||||
|
print_error("No terminating ENDCHAR for character %d\n", encoding);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "STARTCHAR")) {
|
||||||
|
print_trace("Read STARTCHAR, nchars=%d, read_endchar=%d\n", pf->nchars, read_endchar);
|
||||||
|
if (!read_endchar) {
|
||||||
|
print_error("No terminating ENDCHAR for character %d\n", encoding);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read_enc = read_width = read_bbx = read_endchar = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "ENDCHAR")) {
|
||||||
|
if (!read_enc) {
|
||||||
|
print_error("ENCODING is not specified\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ignore_char = (encoding < start_char || encoding > limit_char);
|
||||||
|
if (!ignore_char) {
|
||||||
|
if (!read_width || !read_bbx) {
|
||||||
|
print_error("WIDTH or BBX is not specified for character %d\n",
|
||||||
|
encoding);
|
||||||
|
}
|
||||||
|
bdf_correct_bbx(&width, &bbx);
|
||||||
|
if (width > pf->maxwidth) {
|
||||||
|
pf->maxwidth = width;
|
||||||
|
}
|
||||||
|
overflow = bby + bbh - pf->ascent;
|
||||||
|
if (overflow > pf->max_over_ascent) {
|
||||||
|
pf->max_over_ascent = overflow;
|
||||||
|
}
|
||||||
|
overflow = -bby - pf->descent;
|
||||||
|
if (overflow > pf->max_over_descent) {
|
||||||
|
pf->max_over_descent = overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pf->nchars++;
|
||||||
|
read_endchar = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "ENCODING ")) {
|
||||||
|
if (sscanf(buf, "ENCODING %d", &encoding) != 1) {
|
||||||
|
print_error("bad 'ENCODING': '%s'\n", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read_enc = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "DWIDTH ")) {
|
||||||
|
if (sscanf(buf, "DWIDTH %d", &width) != 1) {
|
||||||
|
print_error("bad 'DWIDTH': '%s'\n", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* use font boundingbox width if DWIDTH <= 0 */
|
||||||
|
if (width < 0) {
|
||||||
|
print_error("Negative char width: %d\n", width);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read_width = 1;
|
||||||
|
}
|
||||||
|
if (isprefix(buf, "BBX ")) {
|
||||||
|
if (sscanf(buf, "BBX %d %d %d %d", &bbw, &bbh, &bbx, &bby) != 4) {
|
||||||
|
print_error("bad 'BBX': '%s'\n", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read_bbx = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adjust_ascent(int ascent, int overflow, struct stretch *stretch) {
|
||||||
|
int result;
|
||||||
|
int px = stretch->value;
|
||||||
|
if (stretch->percent) {
|
||||||
|
px = ascent * px / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stretch->force) {
|
||||||
|
result = ascent + px;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = ascent + MIN(overflow, px);
|
||||||
|
}
|
||||||
|
result = MAX(result, 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue