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 
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*/
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 
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
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 
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 
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 
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 
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 
351 rd1()
352 {
353     int i;
354 
355     if((i = getc(FID)) == EOF) error("file read error");
356     return i;
357 }
358 
359 rd2()
360 {
361     register int i = rd1() << 8;
362 
363     return i + rd1();
364 }
365 
366 rd3()
367 {
368     register int i = rd2() << 8;
369 
370     return i + rd1();
371 }
372 
373 rd4()
374 {
375     register int i = rd2() << 16;
376 
377     return i + rd2();
378 }
379