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