2 /* Copyright (c) 1999, 2000, 2002, 2005 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* This file contains functions related to fonts,
6 * both user defined and native PostScript fonts.
15 /* The font size info is machine generated, so refer to it here. */
16 /* This gives the initialization for FONTINFO structs for all fonts. */
17 extern struct FONTINFO Fontinfo
[MAXFONTS
];
19 /* map font names to numbers. */
20 static struct FONTMAP
{
21 char *fontname
; /* abbreviated (similar to troff-style)
22 * or full font name */
23 char findex
; /* font number */
25 /*====== this table must be sorted alphabetically to allow
26 *====== binary search!!!!! */
55 { "avantgarde bold", FONT_AB
},
56 { "avantgarde boldital", FONT_AX
},
57 { "avantgarde ital", FONT_AI
},
58 { "avantgarde rom", FONT_AR
},
59 { "bookman bold", FONT_BB
},
60 { "bookman boldital", FONT_BX
},
61 { "bookman ital", FONT_BI
},
62 { "bookman rom", FONT_BR
},
63 { "courier bold", FONT_CB
},
64 { "courier boldital", FONT_CX
},
65 { "courier ital", FONT_CI
},
66 { "courier rom", FONT_CR
},
67 { "helvetica bold", FONT_HB
},
68 { "helvetica boldital", FONT_HX
},
69 { "helvetica ital", FONT_HI
},
70 { "helvetica rom", FONT_HR
},
71 { "newcentury bold", FONT_NB
},
72 { "newcentury boldital", FONT_NX
},
73 { "newcentury ital", FONT_NI
},
74 { "newcentury rom", FONT_NR
},
75 { "palatino bold", FONT_PB
},
76 { "palatino boldital", FONT_PX
},
77 { "palatino ital", FONT_PI
},
78 { "palatino rom", FONT_PR
},
79 { "times bold", FONT_TB
},
80 { "times boldital", FONT_TX
},
81 { "times ital", FONT_TI
},
82 { "times rom", FONT_TR
}
85 /* Strings to look for in a fontfile */
86 char *Mup_name
= "Mup font name:";
87 char *PostScript_name
= "PostScript font name:";
88 char *PS_definition
= "PostScript:";
89 char *Size_data
= "Size data:";
91 /* static functions */
92 static int fncmp
P((const void *fn1
, const void * fn2
));
93 static char *get_expected
P((FILE *fontfile_p
, char *filename
, char *expected
,
95 static char *get_noncomment
P((FILE *fontfile_p
, int *lineno_p
));
98 /* given a font number, return its index into Fontinfo table. FONT_TR
99 * is the first entry in the table.
100 * If the font number given is out of range, pfatal.
106 int font
; /* which font */
109 if ((font
< 0) || (font
>= MAXFONTS
)) {
110 pfatal("font %d out of range", font
);
112 /* offset relative to first valid font */
113 font
= font
- FONT_TR
;
119 /* given a fontname, return its number, or FONT_UNKNOWN */
122 lookup_font(fontname
)
127 struct FONTMAP
*finfo_p
;
130 if ((finfo_p
= (struct FONTMAP
*) bsearch(fontname
, Font_table
,
131 NUMELEM(Font_table
), sizeof(struct FONTMAP
), fncmp
))
132 != (struct FONTMAP
*) 0) {
133 return(finfo_p
->findex
);
136 return(FONT_UNKNOWN
);
142 /* font name comparision function for use by bsearch() */
148 const void *fn1
; /* font name to check */
149 const void *fn2
; /* pointer to FONTMAP to compare with. declare as char *
150 * since that's what bsearch() thinks it gives us,
151 * then we cast appropriately */
153 char *fn1
; /* font name to check */
154 char *fn2
; /* pointer to FONTMAP to compare with. declare as char *
155 * since that's what bsearch() thinks it gives us, then we
156 * cast appropriately */
160 return(strcmp(fn1
, ((struct FONTMAP
*) fn2
)->fontname
));
164 /* Given a font number, return its name. We don't have to do this too often,
165 * it's a simple int compare, and we only need to look through
166 * abbreviated names, so just do linear search. */
177 /* divide by 2 because only need to check abbreviations */
178 elements
= NUMELEM(Font_table
) / 2;
179 for (f
= 0; f
< elements
; f
++) {
180 if (Font_table
[f
].findex
== font
) {
181 return(Font_table
[f
].fontname
);
188 /* This handles a fontfile, reading it in, validating its contents,
189 * and saving the information in the Fontinfo array.
193 parse_font_file(filename
)
199 char *name
; /* Mup font name */
200 char *ps_name
; /* PostScript font name */
201 int findex
; /* which font is being defined */
202 int c
; /* character index */
203 int code
; /* "ASCII" code value */
204 int width
, height
, ascent
;
205 char *buffer
; /* line read from file */
207 int max_height
, max_ascent
;
210 debug(2, "parse_font_file(%s)", filename
);
212 if ((fontfile_p
= find_file(&filename
)) == (FILE *) 0) {
213 l_yyerror(Curr_filename
, yylineno
, "can't open '%s'", filename
);
217 /* first line of file is expected to contain the Mup font name */
219 if ((name
= get_expected(fontfile_p
, filename
, Mup_name
, &lineno
))
221 if ((findex
= lookup_font(name
)) == FONT_UNKNOWN
) {
222 l_yyerror(filename
, lineno
,
223 "'%s' is not a valid Mup font name", name
);
226 findex
= font_index(findex
);
228 if (Fontinfo
[findex
].fontfile
!= (FILE *) 0) {
229 l_yyerror(filename
, lineno
,
230 "Font '%s' redefined more than once", name
);
233 /* Save the file pointer, since we'll need to read the rest of
234 * the file to put into the Mup output */
235 Fontinfo
[findex
].fontfile
= fontfile_p
;
241 /* Next line of file is expected to contain the PostScript font name */
242 if ((ps_name
= get_expected(fontfile_p
, filename
, PostScript_name
, &lineno
))
244 if (strlen(ps_name
) == 0 ) {
245 l_yyerror(filename
, lineno
,
246 "No PostScript font name value given");
249 Fontinfo
[findex
].ps_name
= ps_name
;
255 /* Next line of file is expected to contain the Size data line */
256 if ((ps_name
= get_expected(fontfile_p
, filename
, Size_data
, &lineno
))
261 max_height
= max_ascent
= 0;
262 for (c
= FIRST_CHAR
; c
< FIRST_CHAR
+ CHARS_IN_FONT
- 1; c
++) {
263 buffer
= get_noncomment(fontfile_p
, &lineno
);
264 if ( sscanf(buffer
, "%d %d %d %d",
265 &code
, &width
, &height
, &ascent
) != 4) {
266 buffer
[strlen(buffer
) - 1] = '\0';
267 l_yyerror(filename
, lineno
,
268 "size data line has incorrect format: '%s'",
273 l_yyerror(filename
, lineno
,
274 "expecting size data for character %d, but got %d instead",
279 /* Because of how backspace works (see comment in defines.h)
280 * we need to limit width to 0.5 inch for a DEFAULT_SIZE
283 l_yyerror(filename
, lineno
, "width must be less than 500");
287 /* save size in table */
288 code
= CHAR_INDEX(code
);
289 Fontinfo
[findex
].ch_height
[code
] = height
;
290 Fontinfo
[findex
].ch_width
[code
] = width
;
291 Fontinfo
[findex
].ch_ascent
[code
] = ascent
;
293 if (height
> max_height
) {
296 if (ascent
> max_ascent
) {
301 Maxfontheight
[findex
] = (double) max_height
/ (double) FONTFACTOR
;
302 Maxfontascent
[findex
] = (double) max_ascent
/ (double) FONTFACTOR
;
304 /* Next line of file is expected to contain the PostScript: line */
305 if ((ps_name
= get_expected(fontfile_p
, filename
, PS_definition
, &lineno
))
312 /* Read from given file. If next non-comment line starts as expected,
313 * return a copy of the rest of the line after any white space.
314 * Otherwise print an error and return 0.
318 get_expected(fontfile_p
, filename
, expected
, lineno_p
)
322 char *expected
; /* line read is expected to start with this */
323 int *lineno_p
; /* line number where line was found is returned here */
330 buffer
= get_noncomment(fontfile_p
, lineno_p
);
331 if (strncmp(buffer
, expected
, strlen(expected
)) != 0) {
332 l_yyerror(filename
, *lineno_p
,
333 "Expecting '%s' in font_file '%s'", expected
, filename
);
337 /* skip any leading white space */
338 for (buffer
+= strlen(expected
); isspace(*buffer
); buffer
++) {
342 /* trim any white space from the end of the string */
343 for (p
= buffer
+ strlen(buffer
) - 1; p
>= buffer
; p
--) {
352 /* make a copy and return it */
353 MALLOCA(char, newstring
, strlen(buffer
) + 1);
354 strcpy(newstring
, buffer
);
359 /* Read lines from given file until a non-comment line is found, and
360 * return that line. A comment is a line that has # in its first column.
361 * Returns a null string on end of file. The line returned is in a static
362 * buffer overwritten on each call, so caller must save if they need a copy.
366 get_noncomment(file
, lineno_p
)
369 int *lineno_p
; /* line number gets sents in and returned here */
372 static char buffer
[128];
374 while (fgets(buffer
, sizeof(buffer
), file
) != (char *) 0) {
376 if ( *buffer
!= '#') {
377 /* not a comment, so return it */
386 /* return the height for a font in inches for a given size */
389 fontheight(font
, size
)
395 return( (double) Maxfontheight
[font_index(font
)] *
396 ((double) size
/ (double) DFLT_SIZE
) );
401 /* return the ascent for a font in inches for a given size */
404 fontascent(font
, size
)
410 return( (double) Maxfontascent
[font_index(font
)] *
411 ((double) size
/ (double) DFLT_SIZE
) );
416 /* return the descent for a font in inches for a given size */
419 fontdescent(font
, size
)
425 return( fontheight(font
, size
) - fontascent (font
, size
) );