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