2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * mkfont ASCII_BITMAP_INPUT [-c (generate .c file)] [BITMAP_OUTPUT]
27 * This program parses the ascii bitmap (screen font) description given as
28 * input and produces either a binary font file suitable for use with
29 * "fbshow" or a .c file containing an initialized font_c_t struct.
31 * If the output file is not specified, it is created in the current directory
32 * and given the name FontFamily-FontFace.PointSize (with a .c appended if
33 * the -c option is specified); e.g. for 18 point Helvetica Bold, the output
34 * file would be: Helvetica-Bold.18.
36 * The name of the font_c_t struct created by the -c option is
37 * FontFamily_FontFace_PointSize.
40 #define EXPORT_BOOLEAN
45 #import <mach/boolean.h>
48 #define BITSINCR (8*1024*8) /* in honest-to-god bits! */
52 ENDCHAR_LINE
, ENCODING_LINE
, DWIDTH_LINE
, SWIDTH_LINE
, BBX_LINE
,
53 BITMAP_LINE
, DATA_LINE
, FONT_LINE
, SIZE_LINE
, FONTBOUNDINGBOX_LINE
,
54 CHARS_LINE
, STARTCHAR_LINE
, ENDFONT_LINE
, STARTPROPERTIES_LINE
,
55 ENDPROPERTIES_LINE
, UNKNOWN_LINE
, STARTFONT_LINE
, COMMENT_LINE
64 #define LINETBL(x) { #x, x##_LINE, (sizeof #x) - 1 }
66 linetbl_t linetbl
[] = {
76 LINETBL(FONTBOUNDINGBOX
),
80 LINETBL(STARTPROPERTIES
),
81 LINETBL(ENDPROPERTIES
),
85 { NULL
, UNKNOWN_LINE
, 0 }
88 static void read_char_description(void);
89 static void setbits(int bitx
, int nbits
, int scanbits
);
90 static void fatal(const char *format
, ...);
91 static void parse_error(void);
92 static void duplicate(char *line
);
93 static line_t
linetype(char *linebuf
);
94 static char *getline(char *buf
, int buflen
, FILE *stream
);
95 static void write_c_file(const char *outfile
);
96 static void write_bin_file(const char *outfile
);
98 const char *program_name
;
100 unsigned char *bits
= NULL
;
101 int bitsused
; /* in honest-to-god bits */
102 int bitsalloc
; /* in honest-to-god bits */
103 char linebuf
[MAXLINE
];
104 FILE *input
, *output
;
107 main(int argc
, const char * const argv
[])
110 const char *outfile
= NULL
;
111 char filename
[FONTNAMELEN
+20];
112 boolean_t did_endfont_line
, did_font_line
, did_size_line
,
113 did_fontboundingbox_line
, did_chars_line
, did_startfont_line
;
114 int chars
, chars_processed
, nprops
, bytes
;
115 boolean_t gen_c_file
= FALSE
;
118 short s1
, s2
, s3
, s4
;
120 program_name
= *argv
++; argc
--;
121 if (argc
< 1 || argc
> 3) {
122 fatal("Usage: %s ASCII_BITMAP_INPUT [-c (generate .c file)] "
123 "[BITMAP_OUTPUT]", program_name
);
126 infile
= *argv
++; argc
--;
131 while (c
= *argp
++) {
137 fatal("Usage: mkfont "
138 "ASCII_BITMAP_INPUT "
139 "[-c (generate .c file)]");
144 outfile
= *argv
++; argc
--;
148 if ((input
= fopen(infile
, "r")) == NULL
)
149 fatal("Can't open input file %s", infile
);
151 did_endfont_line
= FALSE
;
152 did_font_line
= FALSE
;
153 did_size_line
= FALSE
;
154 did_fontboundingbox_line
= FALSE
;
155 did_chars_line
= FALSE
;
156 did_startfont_line
= FALSE
;
160 while (!did_endfont_line
161 && getline(linebuf
, sizeof linebuf
, input
) != NULL
) {
162 switch (linetype(linebuf
)) {
175 if (did_startfont_line
)
176 duplicate("STARTFONT");
177 did_startfont_line
= TRUE
;
180 if (sscanf(linebuf
, "%*s %s", font
.font
) != 1)
184 did_font_line
= TRUE
;
187 if (sscanf(linebuf
, "%*s %hd", &font
.size
) != 1)
191 did_size_line
= TRUE
;
193 case FONTBOUNDINGBOX_LINE
:
194 if (sscanf(linebuf
, "%*s %hd %hd %hd %hd",
195 &s1
, &s2
, &s3
, &s4
) != 4)
198 font
.bbx
.height
= s2
;
201 if (did_fontboundingbox_line
)
202 duplicate("FONTBOUNDINGBOX");
203 did_fontboundingbox_line
= TRUE
;
206 if (sscanf(linebuf
, "%*s %d", &chars
) != 1)
210 did_chars_line
= TRUE
;
213 read_char_description();
217 did_endfont_line
= TRUE
;
219 case STARTPROPERTIES_LINE
:
220 if (sscanf(linebuf
, "%*s %d", &nprops
) != 1)
222 while (nprops
-- > 0 && getline(linebuf
, sizeof linebuf
, input
) != NULL
)
224 if (nprops
!= 0 || getline(linebuf
, sizeof linebuf
, input
) == NULL
225 || linetype(linebuf
) != ENDPROPERTIES_LINE
)
232 if (! did_font_line
|| ! did_size_line
|| ! did_fontboundingbox_line
233 || ! did_chars_line
|| ! did_endfont_line
|| ! did_startfont_line
)
234 fatal("Incomplete input file");
235 if (chars_processed
!= chars
)
236 fatal("Input file missing character descriptions");
238 fatal("No bitmaps generated!");
241 * Generate a compilable file.
243 write_c_file(outfile
);
246 write_bin_file(outfile
);
251 read_char_description(void)
253 boolean_t did_endchar_line
, did_encoding_line
, did_dwidth_line
, did_bbx_line
,
255 int encoding
, scanbits
, nbits
, h
;
257 short s1
, s2
, s3
, s4
;
259 did_endchar_line
= FALSE
;
260 did_encoding_line
= FALSE
;
261 did_dwidth_line
= FALSE
;
262 did_bbx_line
= FALSE
;
263 did_bitmap_line
= FALSE
;
265 bzero(&bm
, sizeof bm
);
266 while (! did_endchar_line
&& getline(linebuf
, sizeof linebuf
, input
) != NULL
) {
267 switch (linetype(linebuf
)) {
270 case FONTBOUNDINGBOX_LINE
:
274 case STARTPROPERTIES_LINE
:
275 case ENDPROPERTIES_LINE
:
279 if (sscanf(linebuf
, "%*s %d", &encoding
) != 1)
281 if (did_encoding_line
)
282 duplicate("ENCODING");
283 did_encoding_line
= TRUE
;
286 did_endchar_line
= TRUE
;
289 if (sscanf(linebuf
, "%*s %hd", &s1
) != 1)
294 did_dwidth_line
= TRUE
;
297 if (sscanf(linebuf
, "%*s %hd %hd %hd %hd",
298 &s1
, &s2
, &s3
, &s4
) != 4)
311 fatal("BITMAP line not proceeded by BBX line");
314 did_bitmap_line
= TRUE
;
315 nbits
= bm
.bbx
.width
* bm
.bbx
.height
;
316 while (bitsused
+ nbits
> bitsalloc
) {
318 bits
= (unsigned char *)malloc(BITSINCR
>> 3);
319 bitsused
= 1; /* bitx == 0 means no char */
321 bits
= (unsigned char *)realloc(bits
,
322 (BITSINCR
+ bitsalloc
+ 7) >> 3);
324 fatal("Out of memory");
325 bitsalloc
+= (BITSINCR
>> 3) * 8;
328 for (h
= 0; h
< bm
.bbx
.height
; h
++) {
329 if (getline(linebuf
, sizeof linebuf
, input
) == NULL
)
330 fatal("Unexpected EOF on input");
331 if (linetype(linebuf
) != DATA_LINE
)
333 if (sscanf(linebuf
, "%x", &scanbits
) != 1)
335 setbits(bm
.bitx
+ h
* bm
.bbx
.width
, bm
.bbx
.width
, scanbits
);
340 if ( ! did_endchar_line
|| ! did_encoding_line
|| ! did_dwidth_line
341 || ! did_bbx_line
|| ! did_bitmap_line
)
343 if (encoding
>= ENCODEBASE
&& encoding
<= ENCODELAST
) {
344 font
.bitmaps
[encoding
- ENCODEBASE
] = bm
;
351 setbits(int bitx
, int nbits
, int scanbits
)
355 for (i
= 0; i
< nbits
; i
++) {
356 mask
= 0x80 >> ((bitx
+ i
) & 0x7);
357 if (scanbits
& (1 << (((nbits
+ 7) & ~7) - i
- 1)))
358 bits
[(bitx
+ i
) >> 3] |= mask
;
360 bits
[(bitx
+ i
) >> 3] &= ~mask
;
365 fatal(const char *format
, ...)
369 va_start(ap
, format
);
370 fprintf(stderr
, "%s: ", program_name
);
371 vfprintf(stderr
, format
, ap
);
372 fprintf(stderr
, "\n");
377 static int lineNum
= 0;
382 fatal("Couldn't parse line %d: <%s>", lineNum
, linebuf
);
386 duplicate(char *line
)
388 fatal("Duplicate declaration of %s", line
);
392 linetype(char *linebuf
)
397 for (ltp
= linetbl
; ltp
->string
; ltp
++) {
398 if (strncmp(ltp
->string
, linebuf
, ltp
->len
) == 0
399 && (linebuf
[ltp
->len
] == '\0' || isspace(linebuf
[ltp
->len
])))
400 return ltp
->linetype
;
402 len
= strlen(linebuf
);
406 if (! isxdigit(*linebuf
++))
408 return (len
== 0) ? DATA_LINE
: UNKNOWN_LINE
;
412 getline(char *buf
, int buflen
, FILE *stream
)
417 retval
= fgets(buf
, buflen
, stream
);
424 while (len
> 0 && isspace(buf
[--len
]))
430 * generate raw binary file which will get map_fd'd into
431 * a font_t in fbshow.
433 static void write_bin_file(const char *outfile
)
435 char filename
[FONTNAMELEN
+20];
440 * Generate default filename if necessary.
442 if (outfile
== NULL
) {
443 sprintf(filename
, "%s.%d", font
.font
, font
.size
);
446 if ((output
= fopen(outfile
, "w")) == NULL
)
447 fatal("Can't create output file %s", outfile
);
452 if (fwrite(&font
, sizeof font
, 1, output
) != 1)
453 fatal("Write to file %s failed", outfile
);
456 * Now the bit array (declared in font_t as size 0).
458 bytes
= (bitsused
+ 7) >> 3;
459 if (fwrite(bits
, sizeof(unsigned char), bytes
, output
) != bytes
) {
460 fatal("Write to file %s failed", output
);
466 * Generate a compilable file.
468 #define FONTNAME_STRING_NAME "fontname"
469 #define BITS_ARRAY_NAME "bits_array"
471 static void write_c_file(const char *outfile
)
473 char structname
[FONTNAMELEN
+20];
474 char filename
[FONTNAMELEN
+20];
475 char fontname
[FONTNAMELEN
+20];
485 * Generate default filename if necessary.
487 if (outfile
== NULL
) {
488 sprintf(filename
, "%s.%d.c", font
.font
, font
.size
);
492 if ((out
= fopen(outfile
, "w")) == NULL
)
493 fatal("Can't create output file %s", outfile
);
496 * generate the name of the font_c_t struct, converting
497 * possible '-' into '_'.
499 sprintf(structname
, "%s_%d", font
.font
, font
.size
);
500 for(np
=structname
; *np
; np
++) {
507 * Start emitting code. Place fontname and bits_array first to keep
510 fprintf(out
, "/* generated by mkfont */\n\n");
513 * FIXME - maybe this should be passed in in argv...
515 fprintf(out
, "#import \"font.h\"\n\n");
518 * The bit array first.
520 fprintf(out
, "static const char %s[] = {\n", BITS_ARRAY_NAME
);
521 bytes
= (bitsused
+ 7) >> 3;
524 for(loop
=0; loop
<bytes
; loop
++) {
525 fprintf(out
, "0x%02x, ", *bitp
++);
530 fprintf(out
, "\n\t");
534 fprintf(out
, "\n};\n\n");
537 * Finally, the font_c_t itself.
539 fprintf(out
, "const font_c_t %s = {\n", structname
);
540 fprintf(out
, "\t\"%s-%d\",\n", font
.font
, font
.size
);
541 fprintf(out
, "\t%d,\n", font
.size
);
542 fprintf(out
, "\t{%d, %d, %d, %d},\n",
543 font
.bbx
.width
, font
.bbx
.height
,
544 font
.bbx
.xoff
, font
.bbx
.yoff
);
550 fprintf(out
, "\t{\n");
551 for(loop
=0; loop
<(ENCODELAST
- ENCODEBASE
+ 1); loop
++) {
552 fprintf(out
, "\t { {%4d, %4d, %4d, %4d}, %4d, %6d },",
553 bmap
->bbx
.width
, bmap
->bbx
.height
,
554 bmap
->bbx
.xoff
, bmap
->bbx
.yoff
,
555 bmap
->dwidth
, bmap
->bitx
);
557 fprintf(out
, "\t/* 0x%02x */\n", loop
+ ENCODEBASE
);
559 fprintf(out
, "\n\t},\n");
562 * and the bits array ptr.
564 fprintf(out
, "\t%s,\n", BITS_ARRAY_NAME
);
565 fprintf(out
, "};\n");
568 * now some junk to make our code smaller.
570 fprintf(out
, "\n#define %s_BBX_WIDTH\t%d\n",
571 structname
, font
.bbx
.width
);
572 fprintf(out
, "#define %s_BBX_HEIGHT\t%d\n",
573 structname
, font
.bbx
.height
);
574 fprintf(out
, "#define %s_BBX_XOFF\t%d\n",
575 structname
, font
.bbx
.xoff
);
576 fprintf(out
, "#define %s_BBX_YOFF\t%d\n",
577 structname
, font
.bbx
.yoff
);