1 /* VPLOT: version 4.1 updated 03/10/83 2 * 3 * Reads standard graphics input and produces a plot on the 4 * Varian or Versatec 5 * -- creates in /usr/tmp a raster file of 500 1K-blocks. 6 */ 7 #include <stdio.h> 8 #include <signal.h> 9 #include <vfont.h> 10 11 #define LPR "/usr/ucb/lpr" 12 #define VAX /* Machine Flag (don't simulate VM on vax) */ 13 14 #ifdef VAX 15 #define NB 1024 /* Number of blocks in virtual memory */ 16 #else 17 #define NB 88 /* Number of blocks kept in memory */ 18 #endif 19 #define BSIZ 512 /* Size of blocks */ 20 #define LOGBSIZ 9 /* log base 2 of BSIZ */ 21 22 #define mapx(x) ((DevRange*((x)-botx)/del)+centx) 23 #define mapy(y) ((DevRange*(del-(y)+boty)/del)-centy) 24 #define SOLID -1 25 #define DOTTED 014 26 #define SHORTDASHED 034 27 #define DOTDASHED 054 28 #define LONGDASHED 074 29 30 char *Sid = "@(#)\t03/10/83"; 31 32 int linmod = SOLID; 33 int done1; 34 char chrtab[][16]; 35 char blocks[NB][BSIZ]; 36 int lastx; 37 int lasty; 38 int radius, startx, starty, endx, endy; 39 double topx; 40 double topy; 41 double botx; 42 double boty; 43 int centx = 0; 44 int centy = 0; 45 double delx; 46 double dely; 47 double del; 48 49 int warned = 0; /* Indicates whether the warning message about 50 * unimplemented routines has been printed */ 51 52 #ifdef VAX 53 char dirty[NB]; /* marks if a block has been written into */ 54 #else 55 struct buf { 56 int bno; 57 char *block; 58 } bufs[NB]; 59 #endif 60 61 FILE *infile; 62 int fd; 63 char picture[] = "/usr/tmp/rastAXXXXXX"; 64 int run = 13; /* index of 'a' in picture[] */ 65 int DevRange = 1536; /* output array size (square) in pixels */ 66 int BytesPerLine = 264; /* Bytes per raster line (physical) */ 67 int lparg = 7; /* index into lpargs */ 68 69 char *lpargs[50] = { "lpr", "-Pvarian", "-v", "-s", "-r", "-J", "vplot" }; 70 71 /* variables for used to print from font file */ 72 int fontSet = 0; /* Has the font file been read */ 73 struct header header; 74 struct dispatch dispatch[256]; 75 char *bits; 76 char *fontFile = "/usr/lib/vfont/R.6"; 77 78 main(argc, argv) 79 int argc; 80 char **argv; 81 { 82 extern int cleanup(); 83 extern char *malloc(); 84 register i, j; 85 register char *arg; 86 int again; 87 88 infile = stdin; 89 while (argc > 1 && argv[1][0] == '-') { 90 argc--; 91 arg = *++argv; 92 switch (*++arg) { 93 case 'W': 94 DevRange = 2047; 95 BytesPerLine = 880; 96 lpargs[1] = "-Pversatec"; 97 break; 98 case 'V': 99 DevRange = 1536; 100 BytesPerLine = 264; 101 lpargs[1] = "-Pvarian"; 102 break; 103 case 'b': 104 if (argc-- > 1) 105 lpargs[lparg-1] = *++argv; 106 break; 107 default: 108 fprintf(stderr, "vplot: %s option unknown\n", *argv); 109 break; 110 } 111 } 112 if (argc > 1) { 113 if ((infile = fopen(*++argv, "r")) == NULL) { 114 perror(*argv); 115 cleanup(); 116 } 117 } 118 119 /* init constants for scaling */ 120 topx = topy = DevRange; 121 botx = boty = 0; 122 delx = dely = del = DevRange; 123 centx = (DevRange - mapx(topx))/2; 124 centy = mapy(topy)/2; 125 signal(SIGTERM, cleanup); 126 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 127 signal(SIGINT, cleanup); 128 mktemp(picture); 129 do { 130 if ((fd = creat(picture, 0666)) < 0) { 131 fprintf(stderr, "can't create %s\n", picture); 132 cleanup(); 133 } 134 #ifndef VAX 135 close(fd); 136 if ((fd = open(picture, 2)) < 0) { 137 fprintf(stderr, "can't reopen %s\n", picture); 138 cleanup(); 139 } 140 #endif 141 i = strlen(picture) + 1; 142 if ((arg = malloc(i)) == NULL) { 143 fprintf(stderr, "ran out of memory\n"); 144 cleanup(); 145 } 146 strcpy(arg, picture); 147 lpargs[lparg++] = arg; 148 picture[run]++; 149 for (i=0; i<NB; i++) { 150 #ifdef VAX 151 dirty[i] = 0; 152 for (j=0; j<BSIZ; ++j) 153 blocks[i][j] = 0; 154 #else 155 bufs[i].bno = -1; 156 bufs[i.block = blocks[i]; 157 #endif 158 } 159 #ifdef NOHOLES 160 /* clear the entire file */ 161 for (i=0; i<BSIZ; i++) 162 blocks[0][i] = '\0'; 163 for (i=0; i<1024; i++) 164 write(fd, blocks[0], BSIZ); 165 #endif 166 167 again = getpict(); 168 169 for (i=0; i<NB; i++) { 170 #ifdef VAX 171 if (dirty[i]) { /* write out non-zero blocks */ 172 zseek(fd, i); 173 write(fd, blocks[i], BSIZ); 174 } 175 #else 176 if (bufs[i].bno != -1) { 177 zseek(fd, bufs[i].bno); 178 write(fd, bufs[i].blocks[i], BSIZ); 179 } 180 #endif 181 } 182 close(fd); 183 } while (again); 184 lpargs[lparg] = 0; 185 execv(LPR, lpargs); 186 fprintf(stderr, "can't exec %s\n", LPR); 187 cleanup(); 188 } 189 190 getpict() 191 { 192 register x1, y1; 193 194 for (;;) switch (x1 = getc(infile)) { 195 196 case '\n': 197 continue; 198 199 case 's': 200 botx = getinteger(infile); 201 boty = getinteger(infile); 202 topx = getinteger(infile); 203 topy = getinteger(infile); 204 delx = topx-botx; 205 dely = topy-boty; 206 if (dely/delx > 1536./2048.) 207 del = dely; 208 else 209 del = delx; 210 centx = 0; 211 centx = (DevRange - mapx(topx))/2; 212 centy = 0; 213 centy = mapy(topy) / 2; 214 continue; 215 216 case 'b': 217 x1 = getc(infile); 218 continue; 219 220 case 'l': 221 done1 |= 01; 222 x1 = mapx(getinteger(infile)); 223 y1 = mapy(getinteger(infile)); 224 lastx = mapx(getinteger(infile)); 225 lasty = mapy(getinteger(infile)); 226 line(x1, y1, lastx, lasty); 227 continue; 228 229 case 'c': 230 x1 = mapx(getinteger(infile)); 231 y1 = mapy(getinteger(infile)); 232 radius = mapx(getinteger(infile)); 233 if (!warned) { 234 fprintf(stderr,"Circles are Implemented\n"); 235 warned++; 236 } 237 circle(x1, y1, radius); 238 continue; 239 240 case 'a': 241 x1 = mapx(getinteger(infile)); 242 y1 = mapy(getinteger(infile)); 243 startx = mapx(getinteger(infile)); 244 starty = mapy(getinteger(infile)); 245 endx = mapx(getinteger(infile)); 246 endy = mapy(getinteger(infile)); 247 if (!warned) { 248 fprintf(stderr,"Circles and Arcs are unimplemented\n"); 249 warned++; 250 } 251 continue; 252 253 case 'm': 254 lastx = mapx(getinteger(infile)); 255 lasty = mapy(getinteger(infile)); 256 continue; 257 258 case 't': 259 lastx = lastx - 6; 260 lasty = lasty + 6; 261 done1 |= 01; 262 while ((x1 = getc(infile)) != '\n') 263 plotch(x1); 264 continue; 265 266 case 'e': 267 if (done1) 268 return(1); 269 continue; 270 271 case 'p': 272 done1 |= 01; 273 lastx = mapx(getinteger(infile)); 274 lasty = mapy(getinteger(infile)); 275 point(lastx, lasty); 276 point(lastx+1, lasty); 277 point(lastx, lasty+1); 278 point(lastx+1, lasty+1); 279 continue; 280 281 case 'n': 282 done1 |= 01; 283 x1 = mapx(getinteger(infile)); 284 y1 = mapy(getinteger(infile)); 285 line(lastx, lasty, x1, y1); 286 lastx = x1; 287 lasty = y1; 288 continue; 289 290 case 'f': 291 getinteger(infile); 292 getc(infile); 293 switch (getc(infile)) { 294 case 't': 295 linmod = DOTTED; 296 break; 297 default: 298 case 'i': 299 linmod = SOLID; 300 break; 301 case 'g': 302 linmod = LONGDASHED; 303 break; 304 case 'r': 305 linmod = SHORTDASHED; 306 break; 307 case 'd': 308 linmod = DOTDASHED; 309 break; 310 } 311 while ((x1 = getc(infile)) != '\n') 312 if (x1 == EOF) 313 return(0); 314 continue; 315 316 case 'd': 317 getinteger(infile); 318 getinteger(infile); 319 getinteger(infile); 320 x1 = getinteger(infile); 321 while (--x1 >= 0) 322 getinteger(infile); 323 continue; 324 325 case 0: /* ignore null characters */ 326 continue; 327 328 case 255: 329 case EOF: 330 return(0); 331 332 default: 333 fprintf(stderr, "Input format error %c(%o)\n",x1,x1); 334 cleanup(); 335 } 336 } 337 338 plotch(ch) 339 char ch; 340 { 341 register int i,j,k; 342 register char *ptr,c; 343 int nbytes; 344 345 if (!fontSet) 346 InitFont(); /* Read font if not already read */ 347 348 ptr = bits + dispatch[ch].addr; 349 350 for (i = dispatch[ch].up; i > -dispatch[ch].down; --i) { 351 nbytes = (dispatch[ch].right + dispatch[ch].left + 7)/8; 352 for (j = 0; j < nbytes; j++) { 353 c = *ptr++; 354 for (k = 7; k >= 0; k--) 355 if ((c >> k) & 1) 356 point(lastx+7-k+j*8-dispatch[ch].left, lasty-i); 357 } 358 } 359 if (ch != ' ') 360 lastx += dispatch[ch].width; 361 else 362 lastx += dispatch['a'].width; 363 } 364 365 InitFont() 366 { 367 char *s; 368 int fonts; 369 int i; 370 371 fontSet = 1; 372 /* Get the font file */ 373 s = fontFile; 374 if ((fonts = open(s, 0)) == -1) { 375 perror(s); 376 fprintf(stderr, "Can't get font file"); 377 cleanup(); 378 } 379 /* Get the header and check magic number */ 380 if (read(fonts, &header, sizeof(header)) != sizeof(header)) { 381 perror(s); 382 fprintf(stderr, "Bad read in font file"); 383 cleanup(); 384 } 385 if (header.magic != 0436) { 386 fprintf(stderr,"Bad magic numer in font file"); 387 cleanup(); 388 } 389 /* Get dispatches */ 390 if (read(fonts, dispatch, sizeof(dispatch)) != sizeof(dispatch)) { 391 perror(s); 392 fprintf(stderr, "Bad read in font file"); 393 cleanup(); 394 } 395 /* Allocate space for bit map and read in bits */ 396 bits = (char *) malloc(header.size); 397 if (read(fonts, bits, header.size) != header.size) { 398 perror(s); 399 fprintf(stderr,"Can't read bit map in font file"); 400 cleanup(); 401 } 402 /* Close font file */ 403 if (close(fonts) != 0) { 404 perror(s); 405 fprintf(stderr,"Can't close font file"); 406 cleanup(); 407 } 408 } 409 410 line(x0, y0, x1, y1) 411 register x0, y0; 412 { 413 int dx, dy; 414 int xinc, yinc; 415 register res1; 416 int res2; 417 int slope; 418 419 xinc = 1; 420 yinc = 1; 421 if ((dx = x1-x0) < 0) { 422 xinc = -1; 423 dx = -dx; 424 } 425 if ((dy = y1-y0) < 0) { 426 yinc = -1; 427 dy = -dy; 428 } 429 slope = xinc*yinc; 430 res1 = 0; 431 res2 = 0; 432 if (dx >= dy) while (x0 != x1) { 433 if ((x0+slope*y0) & linmod) 434 point(x0, y0); 435 if (res1 > res2) { 436 res2 += dx - res1; 437 res1 = 0; 438 y0 += yinc; 439 } 440 res1 += dy; 441 x0 += xinc; 442 } else while (y0 != y1) { 443 if ((x0+slope*y0) & linmod) 444 point(x0, y0); 445 if (res1 > res2) { 446 res2 += dy - res1; 447 res1 = 0; 448 x0 += xinc; 449 } 450 res1 += dx; 451 y0 += yinc; 452 } 453 if ((x1+slope*y1) & linmod) 454 point(x1, y1); 455 } 456 457 #define labs(a) (a >= 0 ? a : -a) 458 459 circle(x,y,c) 460 { 461 register dx, dy; 462 long ep; 463 int de; 464 465 dx = 0; 466 ep = 0; 467 for (dy=c; dy>=dx; dy--) { 468 for (;;) { 469 point(x+dx, y+dy); 470 point(x-dx, y+dy); 471 point(x+dx, y-dy); 472 point(x-dx, y-dy); 473 point(x+dy, y+dx); 474 point(x-dy, y+dx); 475 point(x+dy, y-dx); 476 point(x-dy, y-dx); 477 ep += 2*dx + 1; 478 de = -2*dy + 1; 479 dx++; 480 if (labs(ep) >= labs(ep+de)) { 481 ep += de; 482 break; 483 } 484 } 485 } 486 } 487 488 /* 489 * Points should be in the range 0 <= x (or y) <= DevRange. 490 * The origin is the top left-hand corner with increasing x towards the 491 * right and increasing y going down. 492 */ 493 point(x, y) 494 register int x, y; 495 { 496 register unsigned bno, byte; 497 498 byte = y * BytesPerLine + (x >> 3); 499 bno = byte >> LOGBSIZ; 500 byte &= BSIZ - 1; 501 if (bno >= 1024) 502 return; 503 #ifndef VAX 504 if (bno != bufs[0].bno) 505 getblk(bno); 506 bufs[0].block[byte] |= 1 << (7 - (x & 07)); 507 #else 508 blocks[bno][byte] |= 1 << (7 - (x & 07)); 509 dirty[bno] = 1; 510 #endif 511 } 512 513 #ifndef VAX 514 getblk(b) 515 register b; 516 { 517 register struct buf *bp1; 518 register char *tp; 519 520 loop: 521 for (bp1 = bufs; bp1 < &bufs[NB]; bp1++) { 522 if (bp1->bno == b || bp1->bno == -1) { 523 tp = bp1->block; 524 while (bp1 > bufs) { 525 bp1->bno = (bp1-1)->bno; 526 bp1->block = (bp1-1)->block; 527 bp1--; 528 } 529 bp1->bno = b; 530 bp1->block = tp; 531 return; 532 } 533 } 534 zseek(fd, bufs[NB-1].bno); 535 write(fd, bufs[NB-1].block, BSIZ); 536 zseek(fd, b); 537 read(fd, bufs[NB-1].block, BSIZ); 538 bufs[NB-1].bno = b; 539 goto loop; 540 } 541 #endif 542 543 cleanup() 544 { 545 while (picture[run] != 'a') { 546 unlink(picture); 547 picture[run]--; 548 } 549 exit(1); 550 } 551 552 zseek(a, b) 553 { 554 return(lseek(a, (long)b*BSIZ, 0)); 555 } 556 557 getinteger(f) 558 FILE *f; 559 { 560 register int low, high, result; 561 562 low = getc(f); 563 high = getc(f); 564 result = ((high << 8) | low); 565 if (high > 127) 566 result |= ~0xffff; 567 return(result); 568 } 569