Commit | Line | Data |
---|---|---|
ae72ba14 | 1 | /* Font description file producer for versatec fonts: David Slattengren |
ebac57d3 DS |
2 | * Taken from vfontinfo by Andy Hertzfeld 4/79 |
3 | * | |
ae72ba14 DS |
4 | * Use: mvfnt [ -nNAME ] [ -s -a -t -l -p# -r# -f# -ddir ] |
5 | * [ "-xs1,s2[;s1,s2...]" ] [ "-ys1,s2[;s1,s2...]" ] font | |
ebac57d3 DS |
6 | * |
7 | * Mkfnt takes the font named "font" and produces a ditroff description | |
ae72ba14 DS |
8 | * file from it. The -n option takes the 1 or 2 letter troff name to put |
9 | * the description (default = XX). The -f option takes an integer per- | |
10 | * centage factor to multiply widths by. The -s, -t and -a options select | |
11 | * a different character mapping than for a "roman" font. s = special; | |
12 | * t = otimespec; a = ascii. The -l option says the font has ligatures. | |
13 | * | |
14 | * Both -x and -y options allow character name mapping. A semi-colon | |
15 | * separated list of comma-separated character-name pairs follows the | |
16 | * x or y. Notice that there are no spaces in the -x or -y command. It | |
17 | * is also IMPORTANT to enclose these arguments in single quotes to stop | |
18 | * the cshell from interpretting the contents. A -x pair REPLACES the | |
19 | * definition for s1 by s2. A -y pair creates a synonym for s1 and calls | |
20 | * it s2. -x and -y MUST be sent after -s, -m, -i, or -a if one of them | |
21 | * is used. Some synonyms are defaulted. To remove a synonym or char- | |
22 | * acter, leave out s2. | |
23 | * | |
24 | * The -p# option tells what point size the DESC file has | |
25 | * as it's "unitwidth" argument (default: 36). The -r# option is the | |
26 | * resolution of the device (default: 200, in units/inch). The -d option | |
27 | * tells where to find fonts (default: /usr/lib/vfont). | |
ebac57d3 DS |
28 | */ |
29 | ||
30 | /* | |
31 | * Here's an ascii character set, just in case you need it: | |
32 | ||
33 | | 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel| | |
34 | | 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si | | |
35 | | 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb| | |
36 | | 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us | | |
37 | | 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' | | |
38 | | 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / | | |
39 | | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 | | |
40 | | 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? | | |
41 | | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G | | |
42 | | 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O | | |
43 | | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W | | |
44 | | 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ | | |
45 | | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g | | |
46 | | 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o | | |
47 | | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w | | |
48 | | 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del| | |
49 | ||
50 | * | |
51 | */ | |
52 | ||
53 | #include <stdio.h> | |
54 | #include <ctype.h> | |
55 | #include <vfont.h> | |
56 | ||
d4c56fb4 | 57 | char sccsid[] = "@(#)makevfont.c 1.3 (Berkeley) %G%"; |
ebac57d3 DS |
58 | |
59 | #define MAGICN 0436 /* font file magic number */ | |
60 | #define PCNTUP 62 /* percent of maximum height for an ascender */ | |
61 | #define PCNTDOWN 73 /* percent of maximum droop for a descender */ | |
62 | #define FONTDIR "/usr/lib/vfont" | |
ebac57d3 DS |
63 | #define POINTSIZE 36 /* this is the "unitwidth" point size */ |
64 | #define MINSIZE 6 /* the minimum and maximum point size values */ | |
65 | #define MAXSIZE 36 /* acceptible for use as "unitwidth"s */ | |
66 | #define RESOLUTION 200 /* resolution of versatec (dots/inch) */ | |
67 | #define MINRES 10 /* check up on resolution input by setting */ | |
68 | #define MAXRES 100000 /* absurdly out-of-range limits on them */ | |
69 | #define APOINT 72 /* 1/APOINT inches = 1 point */ | |
ae72ba14 DS |
70 | #define SYNON 100 /* 2 * pairs allowed in synonym table */ |
71 | ||
ebac57d3 DS |
72 | |
73 | struct header FontHeader; | |
74 | struct dispatch disptable[256]; | |
75 | ||
76 | int res = RESOLUTION; /* resolution of the device (units/inch) */ | |
77 | int pointsize = POINTSIZE; /* point size being used for unitwidth */ | |
ae72ba14 | 78 | int factor = 100; /* percent for magnifying (shrinking) widths */ |
ebac57d3 | 79 | int psize; /* point size of font actually used */ |
ae72ba14 | 80 | int psizelist[] = { 36,24,22,20,18,16,14,28,12,11,10,9,8,7,6,0 }; |
ebac57d3 | 81 | |
ae72ba14 | 82 | char *fontname = "XX"; /* troff font name - set on command line */ |
ebac57d3 DS |
83 | char *fontdir = FONTDIR; /* place to look for fonts */ |
84 | char IName[100]; /* input file name put here */ | |
85 | char *rdchar (); /* function makes strings for ascii */ | |
86 | int FID = -1; /* input file number */ | |
87 | ||
88 | int maxdown = 0; /* size of the most "droopy" character */ | |
89 | int maxup = 0; /* size of the tallest character */ | |
90 | int type; /* 1, 2, or 3 for type of ascend/descending */ | |
ae72ba14 | 91 | int ligsf = 0; /* flag "does this font have ligatures?" */ |
ebac57d3 DS |
92 | |
93 | /* following are the character maps for */ | |
94 | /* ascii code-conversion to printables... */ | |
95 | char **charmap; | |
ae72ba14 DS |
96 | char **synonyms; |
97 | int numsyn; | |
98 | ||
ebac57d3 DS |
99 | char *vregular[] = { |
100 | ||
ae72ba14 | 101 | "??", "fi", "fl", "ff", "\\-", "ru", "em", "bu", "sq", "Fi", "Fl", "de", |
ebac57d3 | 102 | "dg", "fm", "co", "rg", "ct", "14", "12", "34", "^T", "^U", "^V", "^W", |
ae72ba14 | 103 | "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", "", "!", "\"", "#", |
ebac57d3 DS |
104 | "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", |
105 | "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", | |
106 | "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", | |
107 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", | |
108 | "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", | |
109 | "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", | |
ae72ba14 DS |
110 | "x", "y", "z", "{", "|", "}", "~", "^?", |
111 | (char *) 0 | |
112 | }; | |
113 | int nregular = 2; | |
114 | char *sregular[SYNON] = { | |
115 | "-", "hy", "_", "\\_" | |
ebac57d3 | 116 | }; |
ae72ba14 | 117 | |
ebac57d3 DS |
118 | char *vspecial[] = { |
119 | ||
ae72ba14 | 120 | "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "sr", |
ebac57d3 | 121 | "ts", "is", "sl", "bv", "lf", "rf", "lc", "rc", "lt", "lb", "rt", "rb", |
ae72ba14 | 122 | "lk", "rk", "sb", "sp", "ca", "no", "lh", "mo", "", "!", "\"", "#", |
ebac57d3 DS |
123 | "$", "%", "&", "aa", "gr", ")", "mu", "pl", ",", "mi", ".", "di", "==", |
124 | "~=", "ap", "!=", "<-", "->", "ua", "da", "sc", "**", ":", ";", "<", | |
125 | "eq", ">", "?", "@", "*A", "*B", "*G", "*D", "*E", "*Z", "*Y", "*H", | |
126 | "*I", "*K", "*L", "*M", "*N", "*C", "*O", "*P", "*R", "*S", "*T", "*U", | |
127 | "*F", "*X", "*Q", "*W", "dd", "br", "ib", "\\", "ci", "^", "ul", "ga", | |
128 | "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m", | |
129 | "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w", | |
ae72ba14 DS |
130 | "pd", "*f", "{", "|", "}", "~", "^?", |
131 | (char *) 0 | |
132 | }; | |
133 | int nspecial = 0; | |
134 | char *sspecial[SYNON] = { | |
135 | "","" | |
136 | }; | |
137 | ||
138 | char *vtimes[] = { | |
139 | ||
140 | "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "mi", | |
141 | "**", "pl", "eq", "gr", "lt", "lk", "lb", "rt", "rk", "rb", "ap", "mo", | |
142 | "br", "rk", "sb", "sp", "ca", "no", "~=", "mo", "", "da", "no", "ua", | |
143 | "sc", "dd", "if", "pd", "sb", "sp", "mu", "+-", "ca", "cu", "<-", "di", | |
144 | "->", | |
145 | "!=", "sr", "<=", ">=", "==", "or", "is", "bv", "lc", "rc", "lf", "rf", | |
146 | "~=", "_", "ib", "ul", "rn", "ip", "*G", "*D", "*E", "*F", "*G", "*H", | |
147 | "*I", "??", "*L", "*L", "*N", "*C", "*O", "*P", "*H", "*S", "*S", "*U", | |
148 | "*U", "*X", "*W", "*C", "*Q", "br", "ib", "ga", "aa", "^", "ul", "ga", | |
149 | "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m", | |
150 | "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w", | |
151 | "pd", "*f", "{", "|", "}", "~", "^?", | |
152 | (char *) 0 | |
153 | }; | |
154 | int ntimes = 0; | |
155 | char *stimes[SYNON] = { | |
156 | "","" | |
157 | }; | |
158 | ||
159 | ||
160 | char *vascii[] = { | |
161 | "bx", "da", "*a", "*b", "an", "no", "mo", "*p", "*l", "*g", "*d", | |
162 | "ua", "+-", "O+", "if", "pd", "sb", "sp", "ca", "cu", "fa", "te", | |
163 | "OX", "<>", "<-", "->", "!=", "ap", "<=", ">=", "==", "or", "", | |
164 | "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", | |
165 | ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", | |
166 | "<", "=", ">", "?", | |
167 | "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", | |
168 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", | |
169 | "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", | |
170 | "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", | |
171 | "x", "y", "z", "{", "|", "}", "~", "^?", | |
172 | (char *)0 | |
173 | }; | |
174 | int nascii = 3; | |
175 | char *sascii[SYNON] = { | |
176 | "-", "hy", "-", "\\-", "_", "\\_" | |
ebac57d3 DS |
177 | }; |
178 | ||
179 | ||
180 | main (argc, argv) | |
181 | int argc; | |
182 | char **argv; | |
183 | { | |
ae72ba14 DS |
184 | register int i; /* two indexes */ |
185 | register int j; | |
186 | register char *ptr; /* string traveler */ | |
187 | register char delimit; /* place for delimiters on command line */ | |
188 | char tostring(); /* function makes a string */ | |
189 | char *nextstring(); /* moves to next string on list */ | |
ebac57d3 | 190 | |
ae72ba14 DS |
191 | |
192 | charmap = vregular; /* default character map */ | |
193 | synonyms = sregular; | |
194 | numsyn = nregular; | |
ebac57d3 DS |
195 | while (*(*(++argv)) == '-') { /* do options... */ |
196 | switch (*(++(*argv))) { | |
197 | ||
ae72ba14 DS |
198 | case 's': charmap = vspecial; /* special font */ |
199 | synonyms = sspecial; | |
200 | numsyn = nspecial; | |
201 | break; | |
202 | ||
203 | case 't': charmap = vtimes; /* times special font */ | |
204 | synonyms = stimes; | |
205 | numsyn = ntimes; | |
ebac57d3 | 206 | break; |
ae72ba14 DS |
207 | |
208 | case 'a': charmap = vascii; /* ascii font */ | |
209 | synonyms = sascii; | |
210 | numsyn = nascii; | |
211 | break; | |
212 | ||
213 | case 'l': ligsf = 1; /* ascii font */ | |
214 | break; | |
215 | ||
216 | case 'n': fontname = ++*argv; /* troff font name */ | |
217 | break; | |
218 | ||
219 | case 'x': ptr = ++*argv; /* replacements */ | |
220 | while (delimit = tostring(ptr, ',')) { /* get s1 */ | |
221 | for (i = 0; charmap[i] != 0; i++) /* search for match */ | |
222 | if (strcmp (charmap[i], ptr) == 0) | |
223 | break; | |
224 | if (!charmap[i]) error ("-x option: no match"); | |
225 | charmap[i] = ptr = nextstring(ptr); /* replace s1 */ | |
226 | delimit = tostring(ptr, ';'); /* with string s2 */ | |
227 | if (delimit) ptr = nextstring(ptr); | |
228 | } | |
229 | break; | |
230 | ||
231 | case 'y': ptr = ++*argv; /* synonyms */ | |
232 | while (delimit = tostring(ptr, ',')) { /* get s1 */ | |
233 | synonyms[2 * numsyn] = ptr; /* set on end of list */ | |
234 | ptr = nextstring(ptr); /* get string s2 */ | |
235 | delimit = tostring(ptr, ';'); | |
236 | if (*ptr) { /* if something there */ | |
237 | synonyms[2 * numsyn++ + 1] = ptr; /* add to list */ | |
238 | } else { /* otherwise remove */ | |
239 | for (i = 0; i < numsyn; i++) /* from list */ | |
240 | if (strcmp (synonyms[2 * i], ptr) == 0) | |
241 | *synonyms[2 * i] = '\0'; | |
242 | } | |
243 | if (delimit) ptr = nextstring(ptr); | |
244 | if (numsyn > SYNON) error ("out of synonym space"); | |
245 | } | |
246 | break; | |
247 | ||
ebac57d3 DS |
248 | case 'd': fontdir = ++*argv; /* directory */ |
249 | break; | |
250 | ||
251 | case 'p': pointsize = atoi(++*argv); /* point size */ | |
252 | if (pointsize < MINSIZE || pointsize > MAXSIZE) { | |
253 | fprintf(stderr, "Illegal point size: %d\n", pointsize); | |
254 | exit(1); | |
255 | } | |
256 | break; | |
257 | ||
ae72ba14 DS |
258 | case 'f': if ((factor = atoi(++*argv)) < 1 || factor > 1000) { |
259 | fprintf(stderr, "Illegal factor: %d\n", factor); | |
260 | exit(1); | |
261 | } | |
262 | break; | |
263 | ||
ebac57d3 DS |
264 | case 'r': res = atoi(++*argv); /* resolution */ |
265 | if (res < MINRES || res > MAXRES) { | |
266 | fprintf(stderr, "Illegal resolution: %d\n", res); | |
267 | exit(1); | |
268 | } | |
269 | break; | |
270 | ||
271 | default: fprintf(stderr, "Bad option: %c", **argv); | |
272 | exit(1); | |
273 | } | |
274 | } | |
ebac57d3 DS |
275 | |
276 | /* open font file */ | |
277 | for (i = 0; FID < 0 && (psize = psizelist[i]) > 0; i++) { | |
278 | sprintf (IName, "%s/%s.%d", fontdir, *argv, psize); | |
279 | FID = open (IName, 0); | |
280 | } | |
281 | if (FID < 0) { | |
282 | printf ("Can't find %s\n", *argv); | |
283 | exit (8); | |
284 | } | |
285 | ||
286 | ||
287 | if (read (FID, &FontHeader, sizeof FontHeader) != sizeof FontHeader) | |
288 | error ("Bad header in Font file."); | |
289 | if (read (FID, &disptable[0], sizeof disptable) != sizeof disptable) | |
290 | error ("Bad dispatch table in Font file"); | |
291 | if (FontHeader.magic != MAGICN) | |
292 | printf ("Magic number %o wrong\n", FontHeader.magic); | |
293 | ||
294 | ||
295 | printf ("# Font %s, ", IName); /* head off the file */ | |
296 | printf ("max width %d, max height %d\n", | |
297 | FontHeader.maxx, FontHeader.maxy); | |
ae72ba14 DS |
298 | printf ("name %s\n", fontname); |
299 | if (ligsf) | |
ebac57d3 | 300 | printf ("ligatures ff fl fi ffl ffi 0\n"); |
ebac57d3 DS |
301 | printf ("# char width u/d octal\ncharset\n"); |
302 | printf ("\\| %4d 0 0\n\\^ %4d 0 0\n", | |
303 | (res * pointsize / APOINT + 4) / 6, | |
304 | (res * pointsize / APOINT + 7) / 12); | |
305 | ||
ae72ba14 | 306 | /* pass 1 - set up maximums for ups and downs */ |
ebac57d3 DS |
307 | for (j=0; j<256; j++) { |
308 | if (disptable[j].nbytes != 0) { | |
309 | if (disptable[j].up > maxup) maxup = disptable[j].up; | |
310 | if (disptable[j].down > maxdown) maxdown = disptable[j].down; | |
311 | } | |
312 | } | |
313 | if (maxdown == 0) maxdown = 1; | |
314 | ||
315 | /******************************************************************************* | |
316 | ||
317 | `type' is used to determine overhangs (up/down) from percentage of | |
318 | the maximum heights and dips. Ascenders are higher than PCNTUP% | |
319 | of the highest, as descenders are more than PCNTDOWN%. | |
320 | widths [i = f(width)] are calculated from the definition point | |
321 | size (pointsize) and the one from this font (psize). | |
322 | ||
323 | *******************************************************************************/ | |
324 | ||
325 | for (j=0; j<256; j++) { | |
326 | if (disptable[j].nbytes != 0) { | |
327 | type = (int) (((disptable[j].up * 100) / maxup) > PCNTUP) * 2 | | |
328 | (int) (((disptable[j].down * 100) / maxdown) > PCNTDOWN); | |
ae72ba14 DS |
329 | if (*(ptr = charmap[j])) { |
330 | printf ("%s %4d %d 0%o\n", ptr, (factor * | |
331 | (pointsize * disptable[j].width + psize/2) / psize)/100, | |
332 | type, j); | |
333 | for (i = 0; i < numsyn; i++) | |
334 | if (strcmp (ptr, synonyms[2 * i]) == 0) | |
335 | printf ("%s \"\n", synonyms[2 * i + 1]); | |
336 | } | |
ebac57d3 DS |
337 | } |
338 | } | |
339 | } | |
340 | ||
ae72ba14 DS |
341 | |
342 | /*----------------------------------------------------------------------------* | |
343 | | Routine: char tostring (pointer, delimitter) | |
344 | | | |
345 | | Results: checks string pointed to by pointer and turns it into a | |
346 | | string at 'delimitter' by replacing it with '\0'. If the | |
347 | | end of the string is found first, '\0' is returned; otherwise | |
348 | | the delimitter found there is returned. | |
349 | | | |
350 | *----------------------------------------------------------------------------*/ | |
351 | ||
352 | char tostring(p, d) | |
353 | register char *p; | |
354 | register char d; | |
355 | { | |
356 | while (*p && *p != d) p++; | |
357 | d = *p; | |
358 | *p = '\0'; | |
359 | return d; | |
360 | } | |
361 | ||
362 | ||
363 | /*----------------------------------------------------------------------------* | |
364 | | Routine: char * nextstring (pointer) | |
365 | | | |
366 | | Results: returns address of next string after one pointed to by | |
367 | | pointer. The next string is after the '\0' byte. | |
368 | | | |
369 | *----------------------------------------------------------------------------*/ | |
370 | ||
371 | char *nextstring(p) | |
372 | register char *p; | |
373 | { | |
374 | while (*(p++)); | |
375 | return p; | |
376 | } | |
377 | ||
378 | ||
ebac57d3 DS |
379 | error(string) |
380 | char *string; | |
381 | ||
382 | { | |
383 | printf("\nmakefont: %s\n",string); | |
384 | exit(8); | |
385 | } |