1 #ifndef lint 2 static char sccsid[] = "@(#)vplotf.c 4.4 (Berkeley) 03/12/84"; 3 #endif 4 5 /* 6 * Lpd filter to read standard graphics input and produce a plot on the 7 * Varian or Versatec 8 */ 9 10 #include <stdio.h> 11 #include <vfont.h> 12 #include <sys/vcmd.h> 13 14 #define mapx(x) ((DevRange*((x)-botx)/del)+centx) 15 #define mapy(y) ((DevRange*(del-(y)+boty)/del)-centy) 16 #define SOLID -1 17 #define DOTTED 014 18 #define SHORTDASHED 034 19 #define DOTDASHED 054 20 #define LONGDASHED 074 21 22 static char *Sid = "@(#)\t5/16/83"; 23 24 int linmod = SOLID; 25 int done1; 26 char chrtab[][16]; 27 char *obuf; 28 int bufsize; 29 int lastx; 30 int lasty; 31 int radius, startx, starty, endx, endy; 32 double topx; 33 double topy; 34 double botx; 35 double boty; 36 int centx = 0; 37 int centy = 0; 38 double delx; 39 double dely; 40 double del; 41 42 int warned = 0; /* Indicates whether the warning message about 43 * unimplemented routines has been printed */ 44 45 int plotmd[] = {VPLOT}; 46 int prtmd[] = {VPRINT}; 47 int varian; /* 0 for versatec, 1 for varian. */ 48 int BYTES_PER_LINE; /* number of bytes per raster line. */ 49 int PAGE_LINES; /* number of raster lines per page. */ 50 int DevRange = 1536; /* output array size (square) in pixels */ 51 int DevRange8 = 1536/8; /* output array size in bytes */ 52 int lines; /* number of raster lines printed */ 53 char zeros[880]; /* one raster line */ 54 55 char *name, *host, *acctfile; 56 57 /* variables used to print from font file */ 58 int fontSet = 0; /* Has the font file been read */ 59 struct header header; 60 struct dispatch dispatch[256]; 61 char *bits; 62 char *fontFile = "/usr/lib/vfont/R.8"; 63 64 main(argc, argv) 65 int argc; 66 char *argv[]; 67 { 68 register char *cp, *arg; 69 register n, again; 70 71 while (--argc) { 72 if (**++argv == '-') { 73 switch (argv[0][1]) { 74 case 'x': 75 BYTES_PER_LINE = atoi(&argv[0][2]) / 8; 76 if (varian = BYTES_PER_LINE == 264) { 77 DevRange = 1536; 78 DevRange8 = 1536/8; 79 } else { 80 DevRange = 2048; 81 DevRange8 = 2048/8; 82 } 83 break; 84 85 case 'y': 86 PAGE_LINES = atoi(&argv[0][2]); 87 break; 88 89 case 'n': 90 argc--; 91 name = *++argv; 92 break; 93 94 case 'h': 95 argc--; 96 host = *++argv; 97 } 98 } else 99 acctfile = *argv; 100 } 101 102 /* init constants for scaling */ 103 topx = topy = DevRange; 104 botx = boty = 0; 105 delx = dely = del = DevRange; 106 centx = (DevRange - mapx(topx))/2; 107 centy = mapy(topy)/2; 108 109 if ((obuf = (char *) malloc(bufsize = DevRange * DevRange8)) == NULL) { 110 fprintf(stderr, "vplotf: ran out of memory\n"); 111 exit(2); 112 } 113 114 do { 115 arg = &obuf[bufsize]; 116 for (cp = obuf; cp < arg; ) 117 *cp++ = 0; 118 119 again = getpict(); 120 121 ioctl(1, VSETSTATE, plotmd); 122 n = BYTES_PER_LINE - DevRange8; 123 for (cp = obuf; cp < arg; cp += DevRange8) { 124 if (write(1, cp, DevRange8) != DevRange8) 125 exit(1); 126 if (n && write(1, zeros, n) != n) 127 exit(1); 128 lines++; 129 } 130 ioctl(1, VSETSTATE, prtmd); 131 if (varian) 132 write(1, "\f", 2); 133 else 134 write(1, "\n\n\n\n\n", 6); 135 } while (again); 136 137 account(name, host, *argv); 138 exit(0); 139 } 140 141 account(who, from, acctfile) 142 char *who, *from, *acctfile; 143 { 144 register FILE *a; 145 146 if (who == NULL || acctfile == NULL) 147 return; 148 if (access(acctfile, 02) || (a = fopen(acctfile, "a")) == NULL) 149 return; 150 /* 151 * Varian accounting is done by 8.5 inch pages; 152 * Versatec accounting is by the (12 inch) foot. 153 */ 154 fprintf(a, "t%6.2f\t", (double)lines / (double)PAGE_LINES); 155 if (from != NULL) 156 fprintf(a, "%s:", from); 157 fprintf(a, "%s\n", who); 158 fclose(a); 159 } 160 161 getpict() 162 { 163 register x1, y1; 164 165 for (;;) switch (x1 = getc(stdin)) { 166 167 case '\n': 168 continue; 169 170 case 's': 171 botx = getinteger(stdin); 172 boty = getinteger(stdin); 173 topx = getinteger(stdin); 174 topy = getinteger(stdin); 175 delx = topx-botx; 176 dely = topy-boty; 177 if (dely/delx > 1536./2048.) 178 del = dely; 179 else 180 del = delx; 181 centx = 0; 182 centx = (DevRange - mapx(topx))/2; 183 centy = 0; 184 centy = mapy(topy) / 2; 185 continue; 186 187 case 'b': 188 x1 = getc(stdin); 189 continue; 190 191 case 'l': 192 done1 |= 01; 193 x1 = mapx(getinteger(stdin)); 194 y1 = mapy(getinteger(stdin)); 195 lastx = mapx(getinteger(stdin)); 196 lasty = mapy(getinteger(stdin)); 197 line(x1, y1, lastx, lasty); 198 continue; 199 200 case 'c': 201 x1 = mapx(getinteger(stdin)); 202 y1 = mapy(getinteger(stdin)); 203 radius = mapx(getinteger(stdin)); 204 circle(x1, y1, radius); 205 continue; 206 207 case 'a': 208 x1 = mapx(getinteger(stdin)); 209 y1 = mapy(getinteger(stdin)); 210 startx = mapx(getinteger(stdin)); 211 starty = mapy(getinteger(stdin)); 212 endx = mapx(getinteger(stdin)); 213 endy = mapy(getinteger(stdin)); 214 if (!warned) { 215 fprintf(stderr,"Arcs are unimplemented\n"); 216 warned++; 217 } 218 continue; 219 220 case 'm': 221 lastx = mapx(getinteger(stdin)); 222 lasty = mapy(getinteger(stdin)); 223 continue; 224 225 case 't': 226 lastx = lastx - 6; 227 lasty = lasty + 6; 228 done1 |= 01; 229 while ((x1 = getc(stdin)) != '\n') 230 plotch(x1); 231 continue; 232 233 case 'e': 234 if (done1) 235 return(1); 236 continue; 237 238 case 'p': 239 done1 |= 01; 240 lastx = mapx(getinteger(stdin)); 241 lasty = mapy(getinteger(stdin)); 242 point(lastx, lasty); 243 point(lastx+1, lasty); 244 point(lastx, lasty+1); 245 point(lastx+1, lasty+1); 246 continue; 247 248 case 'n': 249 done1 |= 01; 250 x1 = mapx(getinteger(stdin)); 251 y1 = mapy(getinteger(stdin)); 252 line(lastx, lasty, x1, y1); 253 lastx = x1; 254 lasty = y1; 255 continue; 256 257 case 'f': 258 getinteger(stdin); 259 getc(stdin); 260 switch (getc(stdin)) { 261 case 't': 262 linmod = DOTTED; 263 break; 264 default: 265 case 'i': 266 linmod = SOLID; 267 break; 268 case 'g': 269 linmod = LONGDASHED; 270 break; 271 case 'r': 272 linmod = SHORTDASHED; 273 break; 274 case 'd': 275 linmod = DOTDASHED; 276 break; 277 } 278 while ((x1 = getc(stdin)) != '\n') 279 if (x1 == EOF) 280 return(0); 281 continue; 282 283 case 'd': 284 getinteger(stdin); 285 getinteger(stdin); 286 getinteger(stdin); 287 x1 = getinteger(stdin); 288 while (--x1 >= 0) 289 getinteger(stdin); 290 continue; 291 292 case 0: /* ignore null characters */ 293 continue; 294 295 case 255: 296 case EOF: 297 return(0); 298 299 default: 300 fprintf(stderr, "Input format error %c(%o)\n",x1,x1); 301 exit(2); 302 } 303 } 304 305 plotch(ch) 306 char ch; 307 { 308 register int i,j,k; 309 register char *ptr,c; 310 int nbytes; 311 312 if (!fontSet) 313 InitFont(); /* Read font if not already read */ 314 315 ptr = bits + dispatch[ch].addr; 316 317 for (i = dispatch[ch].up; i > -dispatch[ch].down; --i) { 318 nbytes = (dispatch[ch].right + dispatch[ch].left + 7)/8; 319 for (j = 0; j < nbytes; j++) { 320 c = *ptr++; 321 for (k = 7; k >= 0; k--) 322 if ((c >> k) & 1) 323 point(lastx+7-k+j*8-dispatch[ch].left, lasty-i); 324 } 325 } 326 if (ch != ' ') 327 lastx += dispatch[ch].width; 328 else 329 lastx += dispatch['a'].width; 330 } 331 332 InitFont() 333 { 334 char *s; 335 int fonts; 336 int i; 337 338 fontSet = 1; 339 /* Get the font file */ 340 s = fontFile; 341 if ((fonts = open(s, 0)) == -1) { 342 perror(s); 343 fprintf(stderr, "Can't get font file"); 344 exit(2); 345 } 346 /* Get the header and check magic number */ 347 if (read(fonts, &header, sizeof(header)) != sizeof(header)) { 348 perror(s); 349 fprintf(stderr, "Bad read in font file"); 350 exit(2); 351 } 352 if (header.magic != 0436) { 353 fprintf(stderr,"Bad magic numer in font file"); 354 exit(2); 355 } 356 /* Get dispatches */ 357 if (read(fonts, dispatch, sizeof(dispatch)) != sizeof(dispatch)) { 358 perror(s); 359 fprintf(stderr, "Bad read in font file"); 360 exit(2); 361 } 362 /* Allocate space for bit map and read in bits */ 363 bits = (char *) malloc(header.size); 364 if (read(fonts, bits, header.size) != header.size) { 365 perror(s); 366 fprintf(stderr,"Can't read bit map in font file"); 367 exit(2); 368 } 369 /* Close font file */ 370 if (close(fonts) != 0) { 371 perror(s); 372 fprintf(stderr,"Can't close font file"); 373 exit(2); 374 } 375 } 376 377 line(x0, y0, x1, y1) 378 register x0, y0; 379 { 380 int dx, dy; 381 int xinc, yinc; 382 register res1; 383 int res2; 384 int slope; 385 386 xinc = 1; 387 yinc = 1; 388 if ((dx = x1-x0) < 0) { 389 xinc = -1; 390 dx = -dx; 391 } 392 if ((dy = y1-y0) < 0) { 393 yinc = -1; 394 dy = -dy; 395 } 396 slope = xinc*yinc; 397 res1 = 0; 398 res2 = 0; 399 if (dx >= dy) while (x0 != x1) { 400 if ((x0+slope*y0) & linmod) 401 point(x0, y0); 402 if (res1 > res2) { 403 res2 += dx - res1; 404 res1 = 0; 405 y0 += yinc; 406 } 407 res1 += dy; 408 x0 += xinc; 409 } else while (y0 != y1) { 410 if ((x0+slope*y0) & linmod) 411 point(x0, y0); 412 if (res1 > res2) { 413 res2 += dy - res1; 414 res1 = 0; 415 x0 += xinc; 416 } 417 res1 += dx; 418 y0 += yinc; 419 } 420 if ((x1+slope*y1) & linmod) 421 point(x1, y1); 422 } 423 424 #define labs(a) (a >= 0 ? a : -a) 425 426 circle(x,y,c) 427 { 428 register dx, dy; 429 long ep; 430 int de; 431 432 dx = 0; 433 ep = 0; 434 for (dy=c; dy>=dx; dy--) { 435 for (;;) { 436 point(x+dx, y+dy); 437 point(x-dx, y+dy); 438 point(x+dx, y-dy); 439 point(x-dx, y-dy); 440 point(x+dy, y+dx); 441 point(x-dy, y+dx); 442 point(x+dy, y-dx); 443 point(x-dy, y-dx); 444 ep += 2*dx + 1; 445 de = -2*dy + 1; 446 dx++; 447 if (labs(ep) >= labs(ep+de)) { 448 ep += de; 449 break; 450 } 451 } 452 } 453 } 454 455 /* 456 * Points should be in the range 0 <= x (or y) <= DevRange. 457 * The origin is the top left-hand corner with increasing x towards the 458 * right and increasing y going down. 459 */ 460 point(x, y) 461 register unsigned x, y; 462 { 463 register unsigned byte; 464 465 if (x < DevRange && y < DevRange) { 466 byte = y * DevRange8 + (x >> 3); 467 obuf[byte] |= 1 << (7 - (x & 07)); 468 } 469 } 470 471 getinteger(f) 472 FILE *f; 473 { 474 register int low, high, result; 475 476 low = getc(f); 477 high = getc(f); 478 result = ((high << 8) | low); 479 if (high > 127) 480 result |= ~0xffff; 481 return(result); 482 } 483