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