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