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