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) );