1*11517Sralph /* VPLOT: version 4.1 updated 03/10/83 211516Sralph * 3*11517Sralph * Reads standard graphics input and produces a plot on the 4*11517Sralph * Varian or Versatec 5*11517Sralph * -- creates in /usr/tmp a raster file of 500 1K-blocks. 611516Sralph */ 7*11517Sralph #include <stdio.h> 811516Sralph #include <signal.h> 9*11517Sralph #include <vfont.h> 1011516Sralph 11*11517Sralph #define LPR "/usr/ucb/lpr" 12*11517Sralph #define VAX /* Machine Flag (don't simulate VM on vax) */ 13*11517Sralph 14*11517Sralph #ifdef VAX 15*11517Sralph #define NB 1024 /* Number of blocks in virtual memory */ 16*11517Sralph #else 17*11517Sralph #define NB 88 /* Number of blocks kept in memory */ 18*11517Sralph #endif 19*11517Sralph #define BSIZ 512 /* Size of blocks */ 20*11517Sralph #define LOGBSIZ 9 /* log base 2 of BSIZ */ 21*11517Sralph 22*11517Sralph #define mapx(x) ((DevRange*((x)-botx)/del)+centx) 23*11517Sralph #define mapy(y) ((DevRange*(del-(y)+boty)/del)-centy) 2411516Sralph #define SOLID -1 2511516Sralph #define DOTTED 014 2611516Sralph #define SHORTDASHED 034 2711516Sralph #define DOTDASHED 054 2811516Sralph #define LONGDASHED 074 2911516Sralph 30*11517Sralph char *Sid = "@(#)\t03/10/83"; 31*11517Sralph 3211516Sralph int linmod = SOLID; 3311516Sralph int done1; 3411516Sralph char chrtab[][16]; 35*11517Sralph char blocks[NB][BSIZ]; 3611516Sralph int lastx; 3711516Sralph int lasty; 38*11517Sralph int radius, startx, starty, endx, endy; 39*11517Sralph double topx; 40*11517Sralph double topy; 41*11517Sralph double botx; 42*11517Sralph double boty; 43*11517Sralph int centx = 0; 44*11517Sralph int centy = 0; 45*11517Sralph double delx; 46*11517Sralph double dely; 47*11517Sralph double del; 4811516Sralph 49*11517Sralph int warned = 0; /* Indicates whether the warning message about 50*11517Sralph * unimplemented routines has been printed */ 51*11517Sralph 52*11517Sralph #ifdef VAX 53*11517Sralph char dirty[NB]; /* marks if a block has been written into */ 54*11517Sralph #else 5511516Sralph struct buf { 5611516Sralph int bno; 5711516Sralph char *block; 58*11517Sralph } bufs[NB]; 59*11517Sralph #endif 6011516Sralph 61*11517Sralph FILE *infile; 62*11517Sralph int fd; 63*11517Sralph char picture[] = "/usr/tmp/rastAXXXXXX"; 64*11517Sralph int run = 13; /* index of 'a' in picture[] */ 65*11517Sralph int DevRange = 1536; /* output array size (square) in pixels */ 66*11517Sralph int BytesPerLine = 264; /* Bytes per raster line (physical) */ 67*11517Sralph int lparg = 7; /* index into lpargs */ 6811516Sralph 69*11517Sralph char *lpargs[50] = { "lpr", "-Pvarian", "-v", "-s", "-r", "-J", "vplot" }; 70*11517Sralph 71*11517Sralph /* variables for used to print from font file */ 72*11517Sralph int fontSet = 0; /* Has the font file been read */ 73*11517Sralph struct header header; 74*11517Sralph struct dispatch dispatch[256]; 75*11517Sralph char *bits; 76*11517Sralph char *fontFile = "/usr/lib/vfont/R.6"; 77*11517Sralph 7811516Sralph main(argc, argv) 79*11517Sralph int argc; 8011516Sralph char **argv; 8111516Sralph { 82*11517Sralph extern int cleanup(); 83*11517Sralph extern char *malloc(); 84*11517Sralph register i, j; 85*11517Sralph register char *arg; 86*11517Sralph int again; 8711516Sralph 88*11517Sralph infile = stdin; 89*11517Sralph while (argc > 1 && argv[1][0] == '-') { 90*11517Sralph argc--; 91*11517Sralph arg = *++argv; 92*11517Sralph switch (*++arg) { 93*11517Sralph case 'W': 94*11517Sralph DevRange = 2047; 95*11517Sralph BytesPerLine = 880; 96*11517Sralph lpargs[1] = "-Pversatec"; 97*11517Sralph break; 98*11517Sralph case 'V': 99*11517Sralph DevRange = 1536; 100*11517Sralph BytesPerLine = 264; 101*11517Sralph lpargs[1] = "-Pvarian"; 102*11517Sralph break; 103*11517Sralph case 'b': 104*11517Sralph if (argc-- > 1) 105*11517Sralph lpargs[lparg-1] = *++argv; 106*11517Sralph break; 107*11517Sralph default: 108*11517Sralph fprintf(stderr, "vplot: %s option unknown\n", *argv); 109*11517Sralph break; 110*11517Sralph } 11111516Sralph } 112*11517Sralph if (argc > 1) { 113*11517Sralph if ((infile = fopen(*++argv, "r")) == NULL) { 114*11517Sralph perror(*argv); 115*11517Sralph cleanup(); 116*11517Sralph } 117*11517Sralph } 118*11517Sralph 119*11517Sralph /* init constants for scaling */ 120*11517Sralph topx = topy = DevRange; 121*11517Sralph botx = boty = 0; 122*11517Sralph delx = dely = del = DevRange; 123*11517Sralph centx = (DevRange - mapx(topx))/2; 124*11517Sralph centy = mapy(topy)/2; 125*11517Sralph signal(SIGTERM, cleanup); 12611516Sralph if (signal(SIGINT, SIG_IGN) != SIG_IGN) 127*11517Sralph signal(SIGINT, cleanup); 128*11517Sralph mktemp(picture); 129*11517Sralph do { 130*11517Sralph if ((fd = creat(picture, 0666)) < 0) { 131*11517Sralph fprintf(stderr, "can't create %s\n", picture); 132*11517Sralph cleanup(); 13311516Sralph } 134*11517Sralph #ifndef VAX 135*11517Sralph close(fd); 136*11517Sralph if ((fd = open(picture, 2)) < 0) { 137*11517Sralph fprintf(stderr, "can't reopen %s\n", picture); 138*11517Sralph cleanup(); 139*11517Sralph } 140*11517Sralph #endif 141*11517Sralph i = strlen(picture) + 1; 142*11517Sralph if ((arg = malloc(i)) == NULL) { 143*11517Sralph fprintf(stderr, "ran out of memory\n"); 144*11517Sralph cleanup(); 145*11517Sralph } 146*11517Sralph strcpy(arg, picture); 147*11517Sralph lpargs[lparg++] = arg; 148*11517Sralph picture[run]++; 149*11517Sralph for (i=0; i<NB; i++) { 150*11517Sralph #ifdef VAX 151*11517Sralph dirty[i] = 0; 152*11517Sralph for (j=0; j<BSIZ; ++j) 153*11517Sralph blocks[i][j] = 0; 154*11517Sralph #else 155*11517Sralph bufs[i].bno = -1; 156*11517Sralph bufs[i.block = blocks[i]; 157*11517Sralph #endif 158*11517Sralph } 159*11517Sralph #ifdef NOHOLES 160*11517Sralph /* clear the entire file */ 161*11517Sralph for (i=0; i<BSIZ; i++) 162*11517Sralph blocks[0][i] = '\0'; 163*11517Sralph for (i=0; i<1024; i++) 164*11517Sralph write(fd, blocks[0], BSIZ); 165*11517Sralph #endif 166*11517Sralph 167*11517Sralph again = getpict(); 168*11517Sralph 169*11517Sralph for (i=0; i<NB; i++) { 170*11517Sralph #ifdef VAX 171*11517Sralph if (dirty[i]) { /* write out non-zero blocks */ 172*11517Sralph zseek(fd, i); 173*11517Sralph write(fd, blocks[i], BSIZ); 174*11517Sralph } 175*11517Sralph #else 176*11517Sralph if (bufs[i].bno != -1) { 177*11517Sralph zseek(fd, bufs[i].bno); 178*11517Sralph write(fd, bufs[i].blocks[i], BSIZ); 179*11517Sralph } 180*11517Sralph #endif 181*11517Sralph } 182*11517Sralph close(fd); 183*11517Sralph } while (again); 184*11517Sralph lpargs[lparg] = 0; 185*11517Sralph execv(LPR, lpargs); 186*11517Sralph fprintf(stderr, "can't exec %s\n", LPR); 187*11517Sralph cleanup(); 18811516Sralph } 18911516Sralph 19011516Sralph getpict() 19111516Sralph { 19211516Sralph register x1, y1; 19311516Sralph 194*11517Sralph for (;;) switch (x1 = getc(infile)) { 19511516Sralph 196*11517Sralph case '\n': 197*11517Sralph continue; 198*11517Sralph 19911516Sralph case 's': 200*11517Sralph botx = getinteger(infile); 201*11517Sralph boty = getinteger(infile); 202*11517Sralph topx = getinteger(infile); 203*11517Sralph topy = getinteger(infile); 20411516Sralph delx = topx-botx; 20511516Sralph dely = topy-boty; 20611516Sralph if (dely/delx > 1536./2048.) 20711516Sralph del = dely; 20811516Sralph else 209*11517Sralph del = delx; 21011516Sralph centx = 0; 211*11517Sralph centx = (DevRange - mapx(topx))/2; 21211516Sralph centy = 0; 21311516Sralph centy = mapy(topy) / 2; 21411516Sralph continue; 21511516Sralph 216*11517Sralph case 'b': 217*11517Sralph x1 = getc(infile); 218*11517Sralph continue; 219*11517Sralph 22011516Sralph case 'l': 22111516Sralph done1 |= 01; 222*11517Sralph x1 = mapx(getinteger(infile)); 223*11517Sralph y1 = mapy(getinteger(infile)); 224*11517Sralph lastx = mapx(getinteger(infile)); 225*11517Sralph lasty = mapy(getinteger(infile)); 22611516Sralph line(x1, y1, lastx, lasty); 22711516Sralph continue; 22811516Sralph 229*11517Sralph case 'c': 230*11517Sralph x1 = mapx(getinteger(infile)); 231*11517Sralph y1 = mapy(getinteger(infile)); 232*11517Sralph radius = mapx(getinteger(infile)); 233*11517Sralph if (!warned) { 234*11517Sralph fprintf(stderr,"Circles are Implemented\n"); 235*11517Sralph warned++; 236*11517Sralph } 237*11517Sralph circle(x1, y1, radius); 238*11517Sralph continue; 239*11517Sralph 240*11517Sralph case 'a': 241*11517Sralph x1 = mapx(getinteger(infile)); 242*11517Sralph y1 = mapy(getinteger(infile)); 243*11517Sralph startx = mapx(getinteger(infile)); 244*11517Sralph starty = mapy(getinteger(infile)); 245*11517Sralph endx = mapx(getinteger(infile)); 246*11517Sralph endy = mapy(getinteger(infile)); 247*11517Sralph if (!warned) { 248*11517Sralph fprintf(stderr,"Circles and Arcs are unimplemented\n"); 249*11517Sralph warned++; 250*11517Sralph } 251*11517Sralph continue; 252*11517Sralph 25311516Sralph case 'm': 254*11517Sralph lastx = mapx(getinteger(infile)); 255*11517Sralph lasty = mapy(getinteger(infile)); 25611516Sralph continue; 25711516Sralph 25811516Sralph case 't': 259*11517Sralph lastx = lastx - 6; 260*11517Sralph lasty = lasty + 6; 26111516Sralph done1 |= 01; 262*11517Sralph while ((x1 = getc(infile)) != '\n') 26311516Sralph plotch(x1); 26411516Sralph continue; 26511516Sralph 26611516Sralph case 'e': 267*11517Sralph if (done1) 268*11517Sralph return(1); 26911516Sralph continue; 27011516Sralph 27111516Sralph case 'p': 27211516Sralph done1 |= 01; 273*11517Sralph lastx = mapx(getinteger(infile)); 274*11517Sralph lasty = mapy(getinteger(infile)); 27511516Sralph point(lastx, lasty); 27611516Sralph point(lastx+1, lasty); 27711516Sralph point(lastx, lasty+1); 27811516Sralph point(lastx+1, lasty+1); 27911516Sralph continue; 28011516Sralph 28111516Sralph case 'n': 28211516Sralph done1 |= 01; 283*11517Sralph x1 = mapx(getinteger(infile)); 284*11517Sralph y1 = mapy(getinteger(infile)); 28511516Sralph line(lastx, lasty, x1, y1); 28611516Sralph lastx = x1; 28711516Sralph lasty = y1; 28811516Sralph continue; 28911516Sralph 29011516Sralph case 'f': 291*11517Sralph getinteger(infile); 292*11517Sralph getc(infile); 293*11517Sralph switch (getc(infile)) { 29411516Sralph case 't': 29511516Sralph linmod = DOTTED; 29611516Sralph break; 29711516Sralph default: 29811516Sralph case 'i': 29911516Sralph linmod = SOLID; 30011516Sralph break; 30111516Sralph case 'g': 30211516Sralph linmod = LONGDASHED; 30311516Sralph break; 30411516Sralph case 'r': 30511516Sralph linmod = SHORTDASHED; 30611516Sralph break; 30711516Sralph case 'd': 30811516Sralph linmod = DOTDASHED; 30911516Sralph break; 31011516Sralph } 311*11517Sralph while ((x1 = getc(infile)) != '\n') 312*11517Sralph if (x1 == EOF) 313*11517Sralph return(0); 31411516Sralph continue; 31511516Sralph 31611516Sralph case 'd': 317*11517Sralph getinteger(infile); 318*11517Sralph getinteger(infile); 319*11517Sralph getinteger(infile); 320*11517Sralph x1 = getinteger(infile); 32111516Sralph while (--x1 >= 0) 322*11517Sralph getinteger(infile); 32311516Sralph continue; 32411516Sralph 325*11517Sralph case 0: /* ignore null characters */ 326*11517Sralph continue; 32711516Sralph 328*11517Sralph case 255: 329*11517Sralph case EOF: 330*11517Sralph return(0); 331*11517Sralph 33211516Sralph default: 333*11517Sralph fprintf(stderr, "Input format error %c(%o)\n",x1,x1); 334*11517Sralph cleanup(); 33511516Sralph } 33611516Sralph } 33711516Sralph 338*11517Sralph plotch(ch) 339*11517Sralph char ch; 34011516Sralph { 341*11517Sralph register int i,j,k; 342*11517Sralph register char *ptr,c; 343*11517Sralph int nbytes; 34411516Sralph 345*11517Sralph if (!fontSet) 346*11517Sralph InitFont(); /* Read font if not already read */ 347*11517Sralph 348*11517Sralph ptr = bits + dispatch[ch].addr; 349*11517Sralph 350*11517Sralph for (i = dispatch[ch].up; i > -dispatch[ch].down; --i) { 351*11517Sralph nbytes = (dispatch[ch].right + dispatch[ch].left + 7)/8; 352*11517Sralph for (j = 0; j < nbytes; j++) { 353*11517Sralph c = *ptr++; 354*11517Sralph for (k = 7; k >= 0; k--) 355*11517Sralph if ((c >> k) & 1) 356*11517Sralph point(lastx+7-k+j*8-dispatch[ch].left, lasty-i); 357*11517Sralph } 35811516Sralph } 359*11517Sralph if (ch != ' ') 360*11517Sralph lastx += dispatch[ch].width; 361*11517Sralph else 362*11517Sralph lastx += dispatch['a'].width; 36311516Sralph } 36411516Sralph 365*11517Sralph InitFont() 36611516Sralph { 367*11517Sralph char *s; 368*11517Sralph int fonts; 369*11517Sralph int i; 37011516Sralph 371*11517Sralph fontSet = 1; 372*11517Sralph /* Get the font file */ 373*11517Sralph s = fontFile; 374*11517Sralph if ((fonts = open(s, 0)) == -1) { 375*11517Sralph perror(s); 376*11517Sralph fprintf(stderr, "Can't get font file"); 377*11517Sralph cleanup(); 37811516Sralph } 379*11517Sralph /* Get the header and check magic number */ 380*11517Sralph if (read(fonts, &header, sizeof(header)) != sizeof(header)) { 381*11517Sralph perror(s); 382*11517Sralph fprintf(stderr, "Bad read in font file"); 383*11517Sralph cleanup(); 38411516Sralph } 385*11517Sralph if (header.magic != 0436) { 386*11517Sralph fprintf(stderr,"Bad magic numer in font file"); 387*11517Sralph cleanup(); 388*11517Sralph } 389*11517Sralph /* Get dispatches */ 390*11517Sralph if (read(fonts, dispatch, sizeof(dispatch)) != sizeof(dispatch)) { 391*11517Sralph perror(s); 392*11517Sralph fprintf(stderr, "Bad read in font file"); 393*11517Sralph cleanup(); 394*11517Sralph } 395*11517Sralph /* Allocate space for bit map and read in bits */ 396*11517Sralph bits = (char *) malloc(header.size); 397*11517Sralph if (read(fonts, bits, header.size) != header.size) { 398*11517Sralph perror(s); 399*11517Sralph fprintf(stderr,"Can't read bit map in font file"); 400*11517Sralph cleanup(); 401*11517Sralph } 402*11517Sralph /* Close font file */ 403*11517Sralph if (close(fonts) != 0) { 404*11517Sralph perror(s); 405*11517Sralph fprintf(stderr,"Can't close font file"); 406*11517Sralph cleanup(); 407*11517Sralph } 40811516Sralph } 40911516Sralph 41011516Sralph line(x0, y0, x1, y1) 41111516Sralph register x0, y0; 41211516Sralph { 41311516Sralph int dx, dy; 41411516Sralph int xinc, yinc; 41511516Sralph register res1; 41611516Sralph int res2; 41711516Sralph int slope; 41811516Sralph 41911516Sralph xinc = 1; 42011516Sralph yinc = 1; 42111516Sralph if ((dx = x1-x0) < 0) { 42211516Sralph xinc = -1; 42311516Sralph dx = -dx; 42411516Sralph } 42511516Sralph if ((dy = y1-y0) < 0) { 42611516Sralph yinc = -1; 42711516Sralph dy = -dy; 42811516Sralph } 42911516Sralph slope = xinc*yinc; 43011516Sralph res1 = 0; 43111516Sralph res2 = 0; 43211516Sralph if (dx >= dy) while (x0 != x1) { 433*11517Sralph if ((x0+slope*y0) & linmod) 434*11517Sralph point(x0, y0); 43511516Sralph if (res1 > res2) { 43611516Sralph res2 += dx - res1; 43711516Sralph res1 = 0; 43811516Sralph y0 += yinc; 43911516Sralph } 44011516Sralph res1 += dy; 44111516Sralph x0 += xinc; 44211516Sralph } else while (y0 != y1) { 443*11517Sralph if ((x0+slope*y0) & linmod) 44411516Sralph point(x0, y0); 44511516Sralph if (res1 > res2) { 44611516Sralph res2 += dy - res1; 44711516Sralph res1 = 0; 44811516Sralph x0 += xinc; 44911516Sralph } 45011516Sralph res1 += dx; 45111516Sralph y0 += yinc; 45211516Sralph } 453*11517Sralph if ((x1+slope*y1) & linmod) 45411516Sralph point(x1, y1); 45511516Sralph } 45611516Sralph 457*11517Sralph #define labs(a) (a >= 0 ? a : -a) 458*11517Sralph 459*11517Sralph circle(x,y,c) 460*11517Sralph { 461*11517Sralph register dx, dy; 462*11517Sralph long ep; 463*11517Sralph int de; 464*11517Sralph 465*11517Sralph dx = 0; 466*11517Sralph ep = 0; 467*11517Sralph for (dy=c; dy>=dx; dy--) { 468*11517Sralph for (;;) { 469*11517Sralph point(x+dx, y+dy); 470*11517Sralph point(x-dx, y+dy); 471*11517Sralph point(x+dx, y-dy); 472*11517Sralph point(x-dx, y-dy); 473*11517Sralph point(x+dy, y+dx); 474*11517Sralph point(x-dy, y+dx); 475*11517Sralph point(x+dy, y-dx); 476*11517Sralph point(x-dy, y-dx); 477*11517Sralph ep += 2*dx + 1; 478*11517Sralph de = -2*dy + 1; 479*11517Sralph dx++; 480*11517Sralph if (labs(ep) >= labs(ep+de)) { 481*11517Sralph ep += de; 482*11517Sralph break; 483*11517Sralph } 484*11517Sralph } 485*11517Sralph } 486*11517Sralph } 487*11517Sralph 488*11517Sralph /* 489*11517Sralph * Points should be in the range 0 <= x (or y) <= DevRange. 490*11517Sralph * The origin is the top left-hand corner with increasing x towards the 491*11517Sralph * right and increasing y going down. 492*11517Sralph */ 49311516Sralph point(x, y) 494*11517Sralph register int x, y; 49511516Sralph { 496*11517Sralph register unsigned bno, byte; 49711516Sralph 498*11517Sralph byte = y * BytesPerLine + (x >> 3); 499*11517Sralph bno = byte >> LOGBSIZ; 500*11517Sralph byte &= BSIZ - 1; 501*11517Sralph if (bno >= 1024) 502*11517Sralph return; 503*11517Sralph #ifndef VAX 504*11517Sralph if (bno != bufs[0].bno) 50511516Sralph getblk(bno); 506*11517Sralph bufs[0].block[byte] |= 1 << (7 - (x & 07)); 507*11517Sralph #else 508*11517Sralph blocks[bno][byte] |= 1 << (7 - (x & 07)); 509*11517Sralph dirty[bno] = 1; 510*11517Sralph #endif 51111516Sralph } 51211516Sralph 513*11517Sralph #ifndef VAX 51411516Sralph getblk(b) 51511516Sralph register b; 51611516Sralph { 517*11517Sralph register struct buf *bp1; 51811516Sralph register char *tp; 51911516Sralph 52011516Sralph loop: 52111516Sralph for (bp1 = bufs; bp1 < &bufs[NB]; bp1++) { 52211516Sralph if (bp1->bno == b || bp1->bno == -1) { 52311516Sralph tp = bp1->block; 524*11517Sralph while (bp1 > bufs) { 525*11517Sralph bp1->bno = (bp1-1)->bno; 526*11517Sralph bp1->block = (bp1-1)->block; 527*11517Sralph bp1--; 52811516Sralph } 529*11517Sralph bp1->bno = b; 530*11517Sralph bp1->block = tp; 53111516Sralph return; 53211516Sralph } 53311516Sralph } 534*11517Sralph zseek(fd, bufs[NB-1].bno); 535*11517Sralph write(fd, bufs[NB-1].block, BSIZ); 536*11517Sralph zseek(fd, b); 537*11517Sralph read(fd, bufs[NB-1].block, BSIZ); 53811516Sralph bufs[NB-1].bno = b; 53911516Sralph goto loop; 54011516Sralph } 541*11517Sralph #endif 54211516Sralph 543*11517Sralph cleanup() 54411516Sralph { 545*11517Sralph while (picture[run] != 'a') { 546*11517Sralph unlink(picture); 547*11517Sralph picture[run]--; 548*11517Sralph } 54911516Sralph exit(1); 55011516Sralph } 55111516Sralph 55211516Sralph zseek(a, b) 55311516Sralph { 554*11517Sralph return(lseek(a, (long)b*BSIZ, 0)); 55511516Sralph } 556*11517Sralph 557*11517Sralph getinteger(f) 558*11517Sralph FILE *f; 559*11517Sralph { 560*11517Sralph register int low, high, result; 561*11517Sralph 562*11517Sralph low = getc(f); 563*11517Sralph high = getc(f); 564*11517Sralph result = ((high << 8) | low); 565*11517Sralph if (high > 127) 566*11517Sralph result |= ~0xffff; 567*11517Sralph return(result); 568*11517Sralph } 569