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