diff options
author | Alexander Levin <al.le@rockbox.org> | 2009-03-08 16:23:14 +0000 |
---|---|---|
committer | Alexander Levin <al.le@rockbox.org> | 2009-03-08 16:23:14 +0000 |
commit | bded5db2d91d1ec459bcee2e9deed8fca02fac66 (patch) | |
tree | 65924c00372319eb63f6eefa26c45d67b032e7eb /tools | |
parent | 66cf3a3329f4708be0f89b0b44fd87c26abb256b (diff) | |
download | rockbox-bded5db2d91d1ec459bcee2e9deed8fca02fac66.tar.gz rockbox-bded5db2d91d1ec459bcee2e9deed8fca02fac66.zip |
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
Diffstat (limited to 'tools')
-rw-r--r-- | tools/convbdf.c | 344 |
1 files changed, 287 insertions, 57 deletions
diff --git a/tools/convbdf.c b/tools/convbdf.c index 8b6ef143a2..51ae5fb806 100644 --- a/tools/convbdf.c +++ b/tools/convbdf.c | |||
@@ -54,6 +54,9 @@ struct font { | |||
54 | 54 | ||
55 | /* unused by runtime system, read in by convbdf */ | 55 | /* unused by runtime system, read in by convbdf */ |
56 | int nchars; /* number of different glyphs */ | 56 | int nchars; /* number of different glyphs */ |
57 | int nchars_declared; /* number of glyphs as declared in the header */ | ||
58 | int ascent_declared; /* ascent as declared in the header */ | ||
59 | int descent_declared; /* descent as declared in the header */ | ||
57 | unsigned int* offrot; /* offsets into rotated bitmap data */ | 60 | unsigned int* offrot; /* offsets into rotated bitmap data */ |
58 | char* name; /* font name */ | 61 | char* name; /* font name */ |
59 | char* facename; /* facename of font */ | 62 | char* facename; /* facename of font */ |
@@ -70,6 +73,13 @@ struct font { | |||
70 | }; | 73 | }; |
71 | /* END font.h*/ | 74 | /* END font.h*/ |
72 | 75 | ||
76 | /* Description of how the ascent/descent is allowed to grow */ | ||
77 | struct stretch { | ||
78 | int value; /* The delta value (in pixels or percents) */ | ||
79 | int percent; /* Is the value in percents (true) or pixels (false)? */ | ||
80 | int force; /* MUST the value be set (true) or is it just a max (false) */ | ||
81 | }; | ||
82 | |||
73 | #define isprefix(buf,str) (!strncmp(buf, str, strlen(str))) | 83 | #define isprefix(buf,str) (!strncmp(buf, str, strlen(str))) |
74 | #define strequal(s1,s2) (!strcmp(s1, s2)) | 84 | #define strequal(s1,s2) (!strcmp(s1, s2)) |
75 | 85 | ||
@@ -78,14 +88,17 @@ struct font { | |||
78 | 88 | ||
79 | /* Depending on the verbosity level some warnings are printed or not */ | 89 | /* Depending on the verbosity level some warnings are printed or not */ |
80 | int verbosity_level = 0; | 90 | int verbosity_level = 0; |
91 | int trace = 0; | ||
81 | 92 | ||
82 | /* Prints a warning of the specified verbosity level. It will only be | 93 | /* Prints a warning of the specified verbosity level. It will only be |
83 | really printed if the level is >= the level set in the settings */ | 94 | really printed if the level is >= the level set in the settings */ |
84 | void print_warning(int level, const char *fmt, ...); | 95 | void print_warning(int level, const char *fmt, ...); |
85 | void print_error(const char *fmt, ...); | 96 | void print_error(const char *fmt, ...); |
86 | void print_info(const char *fmt, ...); | 97 | void print_info(const char *fmt, ...); |
87 | #define VL_CLIP 1 /* Verbosity level for clip related warnings */ | 98 | void print_trace(const char *fmt, ...); |
88 | #define VL_MIS 1 /* Verbosity level for other warnings */ | 99 | #define VL_CLIP_FONT 1 /* Verbosity level for clip related warnings at font level */ |
100 | #define VL_CLIP_CHAR 2 /* Verbosity level for clip related warnings at char level */ | ||
101 | #define VL_MISC 1 /* Verbosity level for other warnings */ | ||
89 | 102 | ||
90 | int gen_c = 0; | 103 | int gen_c = 0; |
91 | int gen_h = 0; | 104 | int gen_h = 0; |
@@ -96,6 +109,10 @@ int limit_char = 65535; | |||
96 | int oflag = 0; | 109 | int oflag = 0; |
97 | char outfile[256]; | 110 | char outfile[256]; |
98 | 111 | ||
112 | struct stretch stretch_ascent = { 0, 0, 1 }; /* Don't allow ascent to grow by default */ | ||
113 | struct stretch stretch_descent = { 0, 0, 1 }; /* Don't allow descent to grow by default */ | ||
114 | |||
115 | |||
99 | void usage(void); | 116 | void usage(void); |
100 | void getopts(int *pac, char ***pav); | 117 | void getopts(int *pac, char ***pav); |
101 | int convbdf(char *path); | 118 | int convbdf(char *path); |
@@ -104,9 +121,20 @@ void free_font(struct font* pf); | |||
104 | struct font* bdf_read_font(char *path); | 121 | struct font* bdf_read_font(char *path); |
105 | int bdf_read_header(FILE *fp, struct font* pf); | 122 | int bdf_read_header(FILE *fp, struct font* pf); |
106 | int bdf_read_bitmaps(FILE *fp, struct font* pf); | 123 | int bdf_read_bitmaps(FILE *fp, struct font* pf); |
124 | |||
125 | /* | ||
126 | Counts the glyphs and determines the max dimensions of glyphs | ||
127 | (fills the fields nchars, maxwidth, max_over_ascent, max_over_descent). | ||
128 | Returns 0 on failure or not-0 on success. | ||
129 | */ | ||
130 | int bdf_analyze_font(FILE *fp, struct font* pf); | ||
131 | void bdf_correct_bbx(int *width, int *bbx); /* Corrects bbx and width if bbx<0 */ | ||
132 | |||
133 | /* Corrects the ascent and returns the new value (value to use) */ | ||
134 | int adjust_ascent(int ascent, int overflow, struct stretch *stretch); | ||
135 | |||
107 | char * bdf_getline(FILE *fp, char *buf, int len); | 136 | char * bdf_getline(FILE *fp, char *buf, int len); |
108 | bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2); | 137 | bitmap_t bdf_hexval(unsigned char *buf, int ndx1, int ndx2); |
109 | void bitmap_buf_alloc(struct font* pf); | ||
110 | 138 | ||
111 | int gen_c_source(struct font* pf, char *path); | 139 | int gen_c_source(struct font* pf, char *path); |
112 | int gen_h_header(struct font* pf, char *path); | 140 | int gen_h_header(struct font* pf, char *path); |
@@ -115,20 +143,53 @@ int gen_fnt_file(struct font* pf, char *path); | |||
115 | void | 143 | void |
116 | usage(void) | 144 | usage(void) |
117 | { | 145 | { |
118 | char help[] = { | 146 | /* We use string array because some C compilers issue warnings about too long strings */ |
119 | "Usage: convbdf [options] [input-files]\n" | 147 | char *help[] = { |
120 | " convbdf [options] [-o output-file] [single-input-file]\n" | 148 | "Usage: convbdf [options] [input-files]\n", |
121 | "Options:\n" | 149 | " convbdf [options] [-o output-file] [single-input-file]\n", |
122 | " -c Convert .bdf to .c source file\n" | 150 | "Options:\n", |
123 | " -h Convert .bdf to .h header file (to create sysfont.h)\n" | 151 | " -c Convert .bdf to .c source file\n", |
124 | " -f Convert .bdf to .fnt font file\n" | 152 | " -h Convert .bdf to .h header file (to create sysfont.h)\n", |
125 | " -s N Start output at character encodings >= N\n" | 153 | " -f Convert .bdf to .fnt font file\n", |
126 | " -l N Limit output to character encodings <= N\n" | 154 | " -s N Start output at character encodings >= N\n", |
127 | " -n Don't generate bitmaps as comments in .c file\n" | 155 | " -l N Limit output to character encodings <= N\n", |
128 | " -v N Verbosity level: 0=quite quiet, 1=more verbose, 2=even more, etc.\n" | 156 | " -n Don't generate bitmaps as comments in .c file\n", |
157 | " -a N[%][!] Allow the ascent to grow N pixels/% to avoid glyph clipping\n", | ||
158 | " -d N[%][!] Allow the descent to grow N pixels/% to avoid glyph clipping\n", | ||
159 | " -v N Verbosity level: 0=quite quiet, 1=more verbose, 2=even more, etc.\n", | ||
160 | " -t Print internal tracing messages\n", | ||
161 | NULL /* Must be the last element in the array */ | ||
129 | }; | 162 | }; |
130 | 163 | ||
131 | print_info("%s", help); | 164 | char **p = help; |
165 | while (*p != NULL) | ||
166 | print_info("%s", *(p++)); | ||
167 | } | ||
168 | |||
169 | |||
170 | void parse_ascent_opt(char *val, struct stretch *opt) { | ||
171 | char buf[256]; | ||
172 | char *p; | ||
173 | strcpy(buf, val); | ||
174 | |||
175 | opt->force = 0; | ||
176 | opt->percent = 0; | ||
177 | p = buf + strlen(buf); | ||
178 | while (p > buf) { | ||
179 | p--; | ||
180 | if (*p == '%') { | ||
181 | opt->percent = 1; | ||
182 | *p = '\0'; | ||
183 | } | ||
184 | else if (*p == '!') { | ||
185 | opt->force = 1; | ||
186 | *p = '\0'; | ||
187 | } | ||
188 | else { | ||
189 | break; | ||
190 | } | ||
191 | } | ||
192 | opt->value = atoi(buf); | ||
132 | } | 193 | } |
133 | 194 | ||
134 | /* parse command line options*/ | 195 | /* parse command line options*/ |
@@ -199,6 +260,30 @@ void getopts(int *pac, char ***pav) | |||
199 | start_char = atoi(av[0]); | 260 | start_char = atoi(av[0]); |
200 | } | 261 | } |
201 | break; | 262 | break; |
263 | case 'a': /* ascent growth */ | ||
264 | if (*p) { | ||
265 | parse_ascent_opt(p, &stretch_ascent); | ||
266 | while (*p && *p != ' ') | ||
267 | p++; | ||
268 | } | ||
269 | else { | ||
270 | av++; ac--; | ||
271 | if (ac > 0) | ||
272 | parse_ascent_opt(av[0], &stretch_ascent); | ||
273 | } | ||
274 | break; | ||
275 | case 'd': /* descent growth */ | ||
276 | if (*p) { | ||
277 | parse_ascent_opt(p, &stretch_descent); | ||
278 | while (*p && *p != ' ') | ||
279 | p++; | ||
280 | } | ||
281 | else { | ||
282 | av++; ac--; | ||
283 | if (ac > 0) | ||
284 | parse_ascent_opt(av[0], &stretch_descent); | ||
285 | } | ||
286 | break; | ||
202 | case 'v': /* verbosity */ | 287 | case 'v': /* verbosity */ |
203 | if (*p) { | 288 | if (*p) { |
204 | verbosity_level = atoi(p); | 289 | verbosity_level = atoi(p); |
@@ -211,6 +296,9 @@ void getopts(int *pac, char ***pav) | |||
211 | verbosity_level = atoi(av[0]); | 296 | verbosity_level = atoi(av[0]); |
212 | } | 297 | } |
213 | break; | 298 | break; |
299 | case 't': /* tracing */ | ||
300 | trace = 1; | ||
301 | break; | ||
214 | default: | 302 | default: |
215 | print_info("Unknown option ignored: %c\n", *(p-1)); | 303 | print_info("Unknown option ignored: %c\n", *(p-1)); |
216 | } | 304 | } |
@@ -230,6 +318,16 @@ void print_warning(int level, const char *fmt, ...) { | |||
230 | } | 318 | } |
231 | } | 319 | } |
232 | 320 | ||
321 | void print_trace(const char *fmt, ...) { | ||
322 | if (trace) { | ||
323 | va_list ap; | ||
324 | va_start(ap, fmt); | ||
325 | fprintf(stderr, "TRACE: "); | ||
326 | vfprintf(stderr, fmt, ap); | ||
327 | va_end(ap); | ||
328 | } | ||
329 | } | ||
330 | |||
233 | void print_error(const char *fmt, ...) { | 331 | void print_error(const char *fmt, ...) { |
234 | va_list ap; | 332 | va_list ap; |
235 | va_start(ap, fmt); | 333 | va_start(ap, fmt); |
@@ -374,21 +472,64 @@ struct font* bdf_read_font(char *path) | |||
374 | print_error("Error reading font header\n"); | 472 | print_error("Error reading font header\n"); |
375 | goto errout; | 473 | goto errout; |
376 | } | 474 | } |
475 | print_trace("Read font header, nchars_decl=%d\n", pf->nchars_declared); | ||
476 | |||
477 | if (!bdf_analyze_font(fp, pf)) { | ||
478 | print_error("Error analyzing the font\n"); | ||
479 | goto errout; | ||
480 | } | ||
481 | print_trace("Analyzed font, nchars=%d, maxwidth=%d, asc_over=%d, desc_over=%d\n", | ||
482 | pf->nchars, pf->maxwidth, pf->max_over_ascent, pf->max_over_descent); | ||
483 | |||
484 | if (pf->nchars != pf->nchars_declared) { | ||
485 | print_warning(VL_MISC, "The declared number of chars (%d) " | ||
486 | "does not match the real number (%d)\n", | ||
487 | pf->nchars_declared, pf->nchars); | ||
488 | } | ||
489 | |||
490 | /* Correct ascent/descent if necessary */ | ||
491 | pf->ascent = adjust_ascent(pf->ascent_declared, pf->max_over_ascent, &stretch_ascent); | ||
492 | if (pf->ascent != pf->ascent_declared) { | ||
493 | print_info("Font ascent has been changed from %d to %d\n", | ||
494 | pf->ascent_declared, pf->ascent); | ||
495 | } | ||
496 | pf->descent = adjust_ascent(pf->descent, pf->max_over_descent, &stretch_descent); | ||
497 | if (pf->descent != pf->descent_declared) { | ||
498 | print_info("Font descent has been changed from %d to %d\n", | ||
499 | pf->descent_declared, pf->descent); | ||
500 | } | ||
501 | pf->height = pf->ascent + pf->descent; | ||
502 | if (pf->height != pf->ascent_declared + pf->descent_declared) { | ||
503 | print_warning(VL_CLIP_FONT, "Generated font's height: %d\n", pf->height); | ||
504 | } | ||
505 | |||
506 | /* Alocate memory */ | ||
507 | pf->bits_size = pf->size * BITMAP_WORDS(pf->maxwidth) * pf->height; | ||
508 | pf->bits = (bitmap_t *)malloc(pf->bits_size * sizeof(bitmap_t)); | ||
509 | pf->offset = (int *)malloc(pf->size * sizeof(int)); | ||
510 | pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int)); | ||
511 | pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char)); | ||
512 | |||
513 | if (!pf->bits || !pf->offset || !pf->offrot || !pf->width) { | ||
514 | print_error("no memory for font load\n"); | ||
515 | goto errout; | ||
516 | } | ||
377 | 517 | ||
378 | pf->max_over_ascent = pf->max_over_descent = 0; | ||
379 | pf->num_clipped_ascent = pf->num_clipped_descent = pf->num_clipped = 0; | 518 | pf->num_clipped_ascent = pf->num_clipped_descent = pf->num_clipped = 0; |
519 | pf->max_over_ascent = pf->max_over_descent = 0; | ||
380 | 520 | ||
381 | if (!bdf_read_bitmaps(fp, pf)) { | 521 | if (!bdf_read_bitmaps(fp, pf)) { |
382 | print_error("Error reading font bitmaps\n"); | 522 | print_error("Error reading font bitmaps\n"); |
383 | goto errout; | 523 | goto errout; |
384 | } | 524 | } |
525 | print_trace("Read bitmaps\n"); | ||
385 | 526 | ||
386 | if (pf->num_clipped > 0) { | 527 | if (pf->num_clipped > 0) { |
387 | print_warning(VL_CLIP, "%d character(s) out of %d were clipped " | 528 | print_warning(VL_CLIP_FONT, "%d character(s) out of %d were clipped " |
388 | "(%d at ascent, %d at descent)\n", | 529 | "(%d at ascent, %d at descent)\n", |
389 | pf->num_clipped, pf->nchars, | 530 | pf->num_clipped, pf->nchars, |
390 | pf->num_clipped_ascent, pf->num_clipped_descent); | 531 | pf->num_clipped_ascent, pf->num_clipped_descent); |
391 | print_warning(VL_CLIP, "max overflows: %d pixel(s) at ascent, %d pixel(s) at descent\n", | 532 | print_warning(VL_CLIP_FONT, "max overflows: %d pixel(s) at ascent, %d pixel(s) at descent\n", |
392 | pf->max_over_ascent, pf->max_over_descent); | 533 | pf->max_over_ascent, pf->max_over_descent); |
393 | } | 534 | } |
394 | 535 | ||
@@ -444,17 +585,19 @@ int bdf_read_header(FILE *fp, struct font* pf) | |||
444 | } | 585 | } |
445 | } | 586 | } |
446 | if (isprefix(buf, "FONT_DESCENT ")) { | 587 | if (isprefix(buf, "FONT_DESCENT ")) { |
447 | if (sscanf(buf, "FONT_DESCENT %d", &pf->descent) != 1) { | 588 | if (sscanf(buf, "FONT_DESCENT %d", &pf->descent_declared) != 1) { |
448 | print_error("bad 'FONT_DESCENT'\n"); | 589 | print_error("bad 'FONT_DESCENT'\n"); |
449 | return 0; | 590 | return 0; |
450 | } | 591 | } |
592 | pf->descent = pf->descent_declared; /* For now */ | ||
451 | continue; | 593 | continue; |
452 | } | 594 | } |
453 | if (isprefix(buf, "FONT_ASCENT ")) { | 595 | if (isprefix(buf, "FONT_ASCENT ")) { |
454 | if (sscanf(buf, "FONT_ASCENT %d", &pf->ascent) != 1) { | 596 | if (sscanf(buf, "FONT_ASCENT %d", &pf->ascent_declared) != 1) { |
455 | print_error("bad 'FONT_ASCENT'\n"); | 597 | print_error("bad 'FONT_ASCENT'\n"); |
456 | return 0; | 598 | return 0; |
457 | } | 599 | } |
600 | pf->ascent = pf->ascent_declared; /* For now */ | ||
458 | continue; | 601 | continue; |
459 | } | 602 | } |
460 | if (isprefix(buf, "FONTBOUNDINGBOX ")) { | 603 | if (isprefix(buf, "FONTBOUNDINGBOX ")) { |
@@ -466,7 +609,7 @@ int bdf_read_header(FILE *fp, struct font* pf) | |||
466 | continue; | 609 | continue; |
467 | } | 610 | } |
468 | if (isprefix(buf, "CHARS ")) { | 611 | if (isprefix(buf, "CHARS ")) { |
469 | if (sscanf(buf, "CHARS %d", &pf->nchars) != 1) { | 612 | if (sscanf(buf, "CHARS %d", &pf->nchars_declared) != 1) { |
470 | print_error("bad 'CHARS'\n"); | 613 | print_error("bad 'CHARS'\n"); |
471 | return 0; | 614 | return 0; |
472 | } | 615 | } |
@@ -515,20 +658,6 @@ int bdf_read_header(FILE *fp, struct font* pf) | |||
515 | /* calc font size (offset/width entries) */ | 658 | /* calc font size (offset/width entries) */ |
516 | pf->firstchar = firstchar; | 659 | pf->firstchar = firstchar; |
517 | pf->size = lastchar - firstchar + 1; | 660 | pf->size = lastchar - firstchar + 1; |
518 | |||
519 | /* use the font boundingbox to get initial maxwidth */ | ||
520 | /*maxwidth = pf->fbbw - pf->fbbx;*/ | ||
521 | pf->maxwidth = pf->fbbw; | ||
522 | bitmap_buf_alloc(pf); /* Allocate bitmaps */ | ||
523 | |||
524 | pf->offset = (int *)malloc(pf->size * sizeof(int)); | ||
525 | pf->offrot = (unsigned int *)malloc(pf->size * sizeof(unsigned int)); | ||
526 | pf->width = (unsigned char *)malloc(pf->size * sizeof(unsigned char)); | ||
527 | |||
528 | if (!pf->bits || !pf->offset || !pf->offrot || !pf->width) { | ||
529 | print_error("no memory for font load\n"); | ||
530 | return 0; | ||
531 | } | ||
532 | 661 | ||
533 | return 1; | 662 | return 1; |
534 | } | 663 | } |
@@ -610,15 +739,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) | |||
610 | pf->offrot[encoding-pf->firstchar] = ofr; | 739 | pf->offrot[encoding-pf->firstchar] = ofr; |
611 | 740 | ||
612 | /* calc char width */ | 741 | /* calc char width */ |
613 | if (bbx < 0) { | 742 | bdf_correct_bbx(&width, &bbx); |
614 | /* Rockbox can't render overlapping glyphs */ | ||
615 | width -= bbx; | ||
616 | bbx = 0; | ||
617 | } | ||
618 | if (width > pf->maxwidth) { | ||
619 | pf->maxwidth = width; | ||
620 | bitmap_buf_alloc(pf); /* Re-allocate bitmaps since the maxwidth has grown */ | ||
621 | } | ||
622 | pf->width[encoding-pf->firstchar] = width; | 743 | pf->width[encoding-pf->firstchar] = width; |
623 | 744 | ||
624 | ch_bitmap = pf->bits + ofs; | 745 | ch_bitmap = pf->bits + ofs; |
@@ -638,7 +759,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) | |||
638 | pf->max_over_ascent = overflow_asc; | 759 | pf->max_over_ascent = overflow_asc; |
639 | } | 760 | } |
640 | bbh = MAX(bbh - overflow_asc, 0); /* Clipped -> decrease the height */ | 761 | bbh = MAX(bbh - overflow_asc, 0); /* Clipped -> decrease the height */ |
641 | print_warning(VL_CLIP, "character %d goes %d pixel(s)" | 762 | print_warning(VL_CLIP_CHAR, "character %d goes %d pixel(s)" |
642 | " beyond the font's ascent, it will be clipped\n", | 763 | " beyond the font's ascent, it will be clipped\n", |
643 | encoding, overflow_asc); | 764 | encoding, overflow_asc); |
644 | } | 765 | } |
@@ -650,7 +771,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) | |||
650 | } | 771 | } |
651 | bby += overflow_desc; | 772 | bby += overflow_desc; |
652 | bbh = MAX(bbh - overflow_desc, 0); /* Clipped -> decrease the height */ | 773 | bbh = MAX(bbh - overflow_desc, 0); /* Clipped -> decrease the height */ |
653 | print_warning(VL_CLIP, "character %d goes %d pixel(s)" | 774 | print_warning(VL_CLIP_CHAR, "character %d goes %d pixel(s)" |
654 | " beyond the font's descent, it will be clipped\n", | 775 | " beyond the font's descent, it will be clipped\n", |
655 | encoding, overflow_desc); | 776 | encoding, overflow_desc); |
656 | } | 777 | } |
@@ -796,17 +917,126 @@ char *bdf_getline(FILE *fp, char *buf, int len) | |||
796 | } | 917 | } |
797 | return buf; | 918 | return buf; |
798 | } | 919 | } |
799 | 920 | ||
800 | /* | 921 | void bdf_correct_bbx(int *width, int *bbx) { |
801 | Calculates the necessary size of the bit buffer to hold all the | 922 | if (*bbx < 0) { |
802 | bitmaps for the glyphs in the font. Shoud be called every time | 923 | /* Rockbox can't render overlapping glyphs */ |
803 | the max width of the font grows. Font height, the max width and | 924 | *width -= *bbx; |
804 | the number of chars in the font must have been already set. | 925 | *bbx = 0; |
805 | */ | 926 | } |
806 | void bitmap_buf_alloc(struct font* pf) | 927 | } |
807 | { | 928 | |
808 | pf->bits_size = pf->size * BITMAP_WORDS(pf->maxwidth) * pf->height; | 929 | int bdf_analyze_font(FILE *fp, struct font* pf) { |
809 | pf->bits = (bitmap_t *)realloc(pf->bits, pf->bits_size * sizeof(bitmap_t)); | 930 | char buf[256]; |
931 | int encoding; | ||
932 | int width, bbw, bbh, bbx, bby, overflow; | ||
933 | int read_enc = 0, read_width = 0, read_bbx = 0, read_endchar = 1; | ||
934 | int ignore_char = 0; | ||
935 | |||
936 | /* reset file pointer */ | ||
937 | fseek(fp, 0L, SEEK_SET); | ||
938 | |||
939 | pf->maxwidth = 0; | ||
940 | pf->nchars = 0; | ||
941 | pf->max_over_ascent = pf->max_over_descent = 0; | ||
942 | |||
943 | for (;;) { | ||
944 | |||
945 | if (!bdf_getline(fp, buf, sizeof(buf))) { | ||
946 | print_error("EOF on file\n"); | ||
947 | return 0; | ||
948 | } | ||
949 | if (isprefix(buf, "ENDFONT")) { | ||
950 | if (!read_endchar) { | ||
951 | print_error("No terminating ENDCHAR for character %d\n", encoding); | ||
952 | return 0; | ||
953 | } | ||
954 | break; | ||
955 | } | ||
956 | if (isprefix(buf, "STARTCHAR")) { | ||
957 | print_trace("Read STARTCHAR, nchars=%d, read_endchar=%d\n", pf->nchars, read_endchar); | ||
958 | if (!read_endchar) { | ||
959 | print_error("No terminating ENDCHAR for character %d\n", encoding); | ||
960 | return 0; | ||
961 | } | ||
962 | read_enc = read_width = read_bbx = read_endchar = 0; | ||
963 | continue; | ||
964 | } | ||
965 | if (isprefix(buf, "ENDCHAR")) { | ||
966 | if (!read_enc) { | ||
967 | print_error("ENCODING is not specified\n"); | ||
968 | return 0; | ||
969 | } | ||
970 | ignore_char = (encoding < start_char || encoding > limit_char); | ||
971 | if (!ignore_char) { | ||
972 | if (!read_width || !read_bbx) { | ||
973 | print_error("WIDTH or BBX is not specified for character %d\n", | ||
974 | encoding); | ||
975 | } | ||
976 | bdf_correct_bbx(&width, &bbx); | ||
977 | if (width > pf->maxwidth) { | ||
978 | pf->maxwidth = width; | ||
979 | } | ||
980 | overflow = bby + bbh - pf->ascent; | ||
981 | if (overflow > pf->max_over_ascent) { | ||
982 | pf->max_over_ascent = overflow; | ||
983 | } | ||
984 | overflow = -bby - pf->descent; | ||
985 | if (overflow > pf->max_over_descent) { | ||
986 | pf->max_over_descent = overflow; | ||
987 | } | ||
988 | } | ||
989 | pf->nchars++; | ||
990 | read_endchar = 1; | ||
991 | continue; | ||
992 | } | ||
993 | if (isprefix(buf, "ENCODING ")) { | ||
994 | if (sscanf(buf, "ENCODING %d", &encoding) != 1) { | ||
995 | print_error("bad 'ENCODING': '%s'\n", buf); | ||
996 | return 0; | ||
997 | } | ||
998 | read_enc = 1; | ||
999 | continue; | ||
1000 | } | ||
1001 | if (isprefix(buf, "DWIDTH ")) { | ||
1002 | if (sscanf(buf, "DWIDTH %d", &width) != 1) { | ||
1003 | print_error("bad 'DWIDTH': '%s'\n", buf); | ||
1004 | return 0; | ||
1005 | } | ||
1006 | /* use font boundingbox width if DWIDTH <= 0 */ | ||
1007 | if (width < 0) { | ||
1008 | print_error("Negative char width: %d\n", width); | ||
1009 | return 0; | ||
1010 | } | ||
1011 | read_width = 1; | ||
1012 | } | ||
1013 | if (isprefix(buf, "BBX ")) { | ||
1014 | if (sscanf(buf, "BBX %d %d %d %d", &bbw, &bbh, &bbx, &bby) != 4) { | ||
1015 | print_error("bad 'BBX': '%s'\n", buf); | ||
1016 | return 0; | ||
1017 | } | ||
1018 | read_bbx = 1; | ||
1019 | continue; | ||
1020 | } | ||
1021 | } | ||
1022 | return 1; | ||
1023 | } | ||
1024 | |||
1025 | int adjust_ascent(int ascent, int overflow, struct stretch *stretch) { | ||
1026 | int result; | ||
1027 | int px = stretch->value; | ||
1028 | if (stretch->percent) { | ||
1029 | px = ascent * px / 100; | ||
1030 | } | ||
1031 | |||
1032 | if (stretch->force) { | ||
1033 | result = ascent + px; | ||
1034 | } | ||
1035 | else { | ||
1036 | result = ascent + MIN(overflow, px); | ||
1037 | } | ||
1038 | result = MAX(result, 0); | ||
1039 | return result; | ||
810 | } | 1040 | } |
811 | 1041 | ||
812 | 1042 | ||