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