1 static char sccsid[] = "ifontinfo.c 1.7 (Berkeley) 86/03/04";
2
3 /* Font Information for Imagen-style fonts (RST format)
4 * taken from vfontinfo, by Andy Hertzfeld 4/79
5 */
6
7 #include <stdio.h>
8 #include <ctype.h>
9 #include "rst.h"
10
11 #ifndef BITDIR
12 #define BITDIR "/usr/src/local/imagen/fonts/raster"
13 #endif
14
15 char * rdchar();
16 char * malloc();
17
18 char *idstrings; /* place for identifying strings */
19 char *endstring; /* points to the end of the id strings */
20 double fixtowdth; /* "fix" and magnification conversion factor */
21 glyph_dir g[DIRSIZ]; /* directory of glyph definitions */
22 preamble p; /* set of variables for preamble */
23
24 char *fontdir = BITDIR; /* place to look for fonts */
25 char IName[100]; /* input file name put here */
26 char *rdchar (); /* function makes strings for ascii */
27 FILE * FID; /* input file number */
28
29 char defascii[DIRSIZ]; /* list of ascii characters - in order */
30 char *charswanted = defascii;/* list of characters to print info for */
31 int verbose = 0; /* flag - whether to actually show chars */
32 char charbits[10000]; /* place to store bits for a glyph */
33 int gbase; /* base address of glyphs in RST file */
34 int H, W, WB, base;
35 int zoom = 1;
36
37 char msgout[24][80]; /* place to store glyphs to print later */
38 int msgflag = 0; /* flag - use msgout and print later? */
39 int curline, curcol; /* cursor, numbered from lower left corner */
40 int minline = 24;
41 int maxline = 0;
42 int maxcol = 0;
43
44
main(argc,argv)45 main(argc,argv)
46 int argc;
47 char **argv;
48 {
49 register int i;
50 register int j;
51
52 while (argc > 1 && argv[1][0] == '-') {
53 switch(argv[1][1]) {
54 case 'z':
55 zoom = argv[1][2] - '0'; /* zoom implies verbose */
56 case 'v':
57 verbose++;
58 break;
59 case 'm':
60 msgflag = 1;
61 zoom = 2;
62 for (i=0; i<24; i++)
63 for (j=0; j<80; j++)
64 msgout[i][j] = ' ';
65 curline = 5; curcol = 0;
66 break;
67 default:
68 error("bad flag: %s", argv[1]);
69 }
70 argc--; argv++;
71 }
72 if (argc < 2)
73 error("usage: %s filename", argv[0]);
74
75 for (i=0; i<DIRSIZ; i++)
76 defascii[i] = i;
77 if (argc >= 3)
78 charswanted = argv[2];
79
80 sprintf(IName, "%s/%s", fontdir, argv[1]);
81 if ((FID = fopen(argv[1], "r")) == NULL)
82 if ((FID = fopen(IName, "r")) == NULL)
83 error("can't find %s",argv[1]);
84
85 for (i = 0; i < FMARK; filemark[i++] = getc(FID));
86 if (strncmp(filemark, "Rast", 4))
87 error("bad File Mark in Font file.");
88
89 p.p_size = rd2();
90 p.p_version = rd1();
91 if (p.p_version)
92 error("wrong version of Font file.");
93 p.p_glyph = rd3();
94 p.p_first = rd2();
95 p.p_last = rd2();
96 p.p_mag = rd4();
97 p.p_desiz = rd4();
98 p.p_linesp = rd4();
99 p.p_wordsp = rd4();
100 p.p_rot = rd2();
101 p.p_cadv = rd1();
102 p.p_ladv = rd1();
103 p.p_id = rd4();
104 p.p_res = rd2();
105
106 i = p.p_glyph - 44;
107 idstrings = (char *) malloc (i);
108 endstring = idstrings;
109 while (i--) if ((*(endstring++) = getc(FID)) == EOF)
110 error("bad preamble in Font file.");
111
112 for (i = p.p_first; i <= p.p_last; i++) {
113 g[i].g_height = rd2();
114 g[i].g_width = rd2();
115 g[i].g_up = rd2();
116 g[i].g_left = rd2();
117 g[i].g_pwidth = rd4();
118 g[i].g_bitp = rd3();
119 }
120
121 if ((fixtowdth = FIXIN * p.p_res * p.p_mag / 1000.0) == 0.0)
122 fixtowdth = FIXIN * p.p_res;
123
124 if (!msgflag) {
125 printf("Font %s, size %.2f, ", argv[1], p.p_desiz * FIX);
126 printf("first %d, last %d, res %d, ", p.p_first, p.p_last, p.p_res);
127 printf("mag %.2f\n", fixtowdth / (FIXIN * p.p_res));
128 printf("spacewidth %.2f, rot %d, cadv %d, ladv %d\n",
129 p.p_wordsp * fixtowdth, p.p_rot, p.p_cadv, p.p_ladv);
130 while (idstrings < endstring) {
131 for (i = *(idstrings++); i--; ) putchar (*(idstrings++));
132 putchar(':');
133 }
134 putchar('\n');
135
136 for (i = strlen(argv[1]) + 1; i > 0; --i) putchar(' ');
137 printf("ASCII addr height width up left pwidth\n");
138 }
139
140 for (i=p.p_first; i<=p.p_last; i++) {
141 j = charswanted[i];
142 if (i>0 && j==0)
143 break;
144 if ((gbase = g[j].g_bitp) != 0) {
145 if (!msgflag)
146 printf("%s %3o %2s %4d %6d %6d %5d %5d %6d\n",
147 argv[1], j, rdchar(j), gbase, g[j].g_height,
148 g[j].g_width, g[j].g_up, g[j].g_left,
149 (int) (g[j].g_pwidth * fixtowdth));
150 if (verbose || msgflag) {
151 int k, l, last;
152
153 H = g[j].g_height;
154 W = g[j].g_width;
155 lseek(fileno(FID), (long) gbase, 0);
156 read(fileno(FID), charbits, (WB = (W+7)/8) * H);
157 base = g[j].g_up;
158 shozoom();
159 if (msgflag) {
160 k = g[j].g_width;
161 if (zoom == 0) k *= 2;
162 else if (zoom == 2) k /= 2;
163 curcol += k;
164 }
165 }
166 }
167 }
168 if (msgflag) {
169 for (i=maxline; i>=minline; i--) {
170 for (j=0; j<maxcol; j++)
171 putchar(msgout[i][j]);
172 putchar('\n');
173 }
174 }
175 exit(0);
176 }
177
178 /*VARARGS1*/
error(string,a1,a2,a3,a4)179 error(string, a1, a2, a3, a4)
180 char *string;
181 {
182 fprintf(stderr, "ifontinfo: ");
183 fprintf(stderr, string, a1, a2, a3, a4);
184 fprintf(stderr, "\n");
185 exit(8);
186 };
187
rdchar(c)188 char *rdchar(c)
189 char c;
190 {
191 static char ret[3];
192 ret[0] = isprint(c) ? ' ' : '^';
193 ret[1] = isprint(c) ? c : c^0100;
194 ret[2] = 0;
195 return (ret);
196 }
197
198 int
fbit(row,col)199 fbit(row, col)
200 int row, col;
201 {
202 int thisbyte, thisbit, ret;
203
204 if (row<0 || row>=H || col>=W) return(0);
205 thisbyte = charbits[row*WB + (col>>3)] & 0xff;
206 thisbit = 0x80 >> (col&7);
207 ret = thisbyte & thisbit;
208 return (ret != 0);
209 }
210
211
212 /*
213 The implementation would work like this:
214 zoom level method
215 0 2 chars/pixel, 1 is "[]", 0 is " ".
216 1 2 pixels/char 2x1, using " " "," "'" "|"
217 2 8 pixels/char 4x2, using 16x16 table
218 3 32 pixels/char 8x4, mapped into (2)
219 4 and up similar, mapped into (2)
220
221 The 16x16 table maps a 4x2 pattern into a printing ascii character which
222 most closely approximates that pattern, e.g. the pattern
223 |'
224 ''
225 would be represented by the character "[". I have such a table worked out.
226
227 Grainer zoom levels would take the rule of reducing it into a smaller bitmap,
228 or-ing the bits together. (e.g. level 3 would take a 2x2 chunk and map it
229 into a single pixel: 0 if all 4 are 0, 1 otherwise.) These pixels would be
230 displayed as in 2.
231 */
232
233 /*
234 * graphtab: a table for rudimentary graphics on ordinary terminals.
235 * For each 4x2 bit pattern of the form:
236 * ae
237 * bf
238 * cg
239 * dh
240 * form the 4 bit quantities abcd and efgh and get table entry
241 * graphtab[abcd][efgh]
242 * to display in that character position.
243 *
244 * General philosophies: the dh bits are intended for descenders where
245 * possible. Characters with radically different appearance on different
246 * terminals (e.g. _ and ^) are avoided.
247 *
248 * Version 1.0, March 1981, Mark Horton.
249 */
250
251 char tab1[4] = {
252 ' ', ',', '\'', '|'
253 };
254
255 char graphtab[16][16] = {
256 ' ', '.', '.', ',', '.', ';', ':', 'j', '\'', ':', ':', ';', '\'', ';', '!', '|',
257 '.', '.', ':', ',', ';', ';', ';', 'j', '/', ';', ';', ';', 'j', 'j', 'j', 'j',
258 '.', ',', '~', ',', 'r', '<', 'j', 'q', '/', ';', 'I', ';', '/', '|', 'I', '|',
259 ',', ',', 'r', 'x', '/', '/', '/', 'd', '/', '/', '/', 'd', '/', '/', '/', 'd',
260 '.', ':', '\\', ';', '-', '=', 'v', 'q', '\'', ':', '<', '|', '\'', ':', '+', '+',
261 ';', ';', '>', ';', '=', '=', 'g', 'g', '\'', ':', 'S', 'S', '/', '/', '/', '+',
262 ':', '\\', '\\', '\\', 'r', '<', 'w', 'q', '/', '<', '6', '4', '/', '/', 'd', '+',
263 'l', 'L', '+', 'b', 'y', '[', 'p', 'g', '/', '<', '/', '6', '/', '/', '/', '+',
264 '`', ':', ':', ';', '`', '\\', '\\', '\\', '"', ':', ':', ';', '`', '\\', 'Y', 'T',
265 ';', ';', ';', ';', '`', '2', '>', '\\', ':', '=', ';', ';', '?', '?', ']', ']',
266 ':', ';', ';', ';', '>', '2', '>', '\\', 'F', ';', 'O', ';', '7', '?', ']', '7',
267 ';', ';', ';', ';', '?', '2', '>', 'b', ';', ';', ';', ';', '?', '?', ']', '#',
268 '\'', '\\', '\\', '\\', '`', '\\', '\\', '\\', '\'', '\'', '<', '5', '"', '"', 'v', 'q',
269 ';', '\\', '\\', '\\', '`', '=', '\\', '\\', '\'', '\'', '5', '5', '"', '?', 'g', 'g',
270 'I', 'L', 'L', 'L', 'D', '\\', 'b', 'f', 'F', '[', '[', '[', 'P', '?', '#', 'M',
271 '|', '|', '|', '|', '|', '#', '+', '#', 'T', '[', 'F', 'F', 'P', '?', 'P', 'M'
272 };
273
274
shozoom()275 shozoom()
276 {
277 register i;
278
279 if (zoom == 0)
280 sho0();
281 else if (zoom == 1)
282 sho1();
283 else if (zoom == 2)
284 sho2();
285 }
286
sho0()287 sho0()
288 {
289 register k,l;
290
291 for (k=0; k<H; k++) {
292 for (l=0; l<W; l++)
293 printf("%s", fbit(k,l)?"[]": " ");
294 printf("\n");
295 }
296 printf("\n");
297 }
298
sho1()299 sho1()
300 {
301 register i,k,l;
302
303 for (k = 0; k < H; k += 2) {
304 for(l = 0; l < W; l++) {
305 putchar(tab1[(fbit(k,l) << 1) | fbit(k+1,l)]);
306 }
307 putchar('\n');
308 }
309 putchar('\n');
310 }
311
sho2()312 sho2()
313 {
314 register i,j,k,l;
315 int line = curline + (base+3)/4;
316 int col;
317
318 k = base%4;
319 if (k > 0) k -= 4;
320 while (k < H) {
321 l = 0;
322 col = curcol;
323 while (l<W) {
324 i = fbit(k,l)*8 + fbit(k+1,l)*4 +
325 fbit(k+2,l)*2 + fbit(k+3,l);
326 l++;
327 j = fbit(k,l)*8 + fbit(k+1,l)*4 +
328 fbit(k+2,l)*2 + fbit(k+3,l);
329
330 if (msgflag) {
331 if (graphtab[i][j] != ' ') {
332 if (line > maxline) maxline = line;
333 if (line < minline) minline = line;
334 if (col > maxcol) maxcol = col;
335 }
336 msgout[line][col] = graphtab[i][j];
337 } else
338 printf("%c",graphtab[i][j]);
339 l++;
340 col++;
341 }
342 if (msgflag == 0)
343 printf("\n");
344 k += 4;
345 line--;
346 }
347 if (msgflag == 0)
348 printf("\n");
349 }
350
rd1()351 rd1()
352 {
353 int i;
354
355 if((i = getc(FID)) == EOF) error("file read error");
356 return i;
357 }
358
rd2()359 rd2()
360 {
361 register int i = rd1() << 8;
362
363 return i + rd1();
364 }
365
rd3()366 rd3()
367 {
368 register int i = rd2() << 8;
369
370 return i + rd1();
371 }
372
rd4()373 rd4()
374 {
375 register int i = rd2() << 16;
376
377 return i + rd2();
378 }
379