1 /* dver.c 1.17 85/08/05 2 * 3 * VAX Versatec driver for the new troff 4 * 5 * Authors: BWK(BELL) 6 * VCAT(berkley) 7 * Richard L. Hyde, Perdue University 8 * and David Slattengren, U.C. Berkeley 9 */ 10 11 12 /******************************************************************************* 13 14 output language from troff: 15 all numbers are character strings 16 17 #..\n comment 18 sn size in points 19 fn font as number from 1 to n 20 in stipple as number from 1 to n 21 cx ascii character x 22 Cxyz funny char \(xyz. terminated by white space 23 Hn go to absolute horizontal position n 24 Vn go to absolute vertical position n (down is positive) 25 hn go n units horizontally (relative) 26 vn ditto vertically 27 nnc move right nn, then print c (exactly 2 digits!) 28 (this wart is an optimization that shrinks output file size 29 about 35% and run-time about 15% while preserving ascii-ness) 30 pn new page begins (number n) -- set v to 0 31 P spread ends -- output it. 32 nb a end of line (information only -- no action needed) 33 b = space before line, a = after 34 w paddable word space -- no action needed 35 36 Dt ..\n draw operation 't': 37 Dt d set line thickness to d pixels 38 Ds d set line style mask to d 39 Dl x y line from here by x,y 40 Dc d circle of diameter d with left side here 41 De x y ellipse of axes x,y with left side here 42 Da x y r arc counter-clockwise by x,y of radius r 43 D~ x y x y ... B-spline curve by x,y then x,y ... 44 Dg x y x y ... gremlin spline curve by x,y then x,y ... 45 Dq d n miny maxy [p dx dy curx endy] polygon filled with d, has n 46 vectors, with extents from miny to maxy (no border) 47 48 x ..\n device control functions: 49 x i init 50 x T s name of device is s 51 x r n h v resolution is n/inch h = min horizontal motion, v = min vert 52 x p pause (can restart) 53 x s stop -- done for ever 54 x t generate trailer 55 x f n s font position n contains font s 56 x H n set character height to n 57 x S n set slant to N 58 59 Subcommands like "i" are often spelled out like "init". 60 61 *******************************************************************************/ 62 63 64 #include <stdio.h> 65 #include <ctype.h> 66 #include <sys/vcmd.h> 67 #include "dev.h" 68 69 70 /* #define DEBUGABLE /* No, not debugable... */ 71 #define DRIVER /* Yes, we're driving directly */ 72 #define NFONTS 65 /* total number of fonts useable */ 73 #define MAXSTATE 6 /* number of environments rememberable */ 74 #define OPENREAD 0 /* mode for openning files */ 75 #define RESTART 1 /* upon exit, return either RESTART */ 76 #define ABORT 2 /* or ABORT */ 77 #define FATAL 1 /* type of error */ 78 #define BMASK 0377 /* byte grabber */ 79 #ifndef FONTDIR 80 #define FONTDIR "/usr/lib/font" /* default place to find font descriptions */ 81 #endif 82 #ifndef BITDIR 83 #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */ 84 #endif 85 #define MAXWRIT 4096 /* max characters allowed to write at once */ 86 87 #define hmot(n) hpos += n 88 #define hgoto(n) hpos = n 89 #define vmot(n) vgoto(vpos + (n)) 90 91 92 char SccsId[]= "dver.c 1.17 85/08/05"; 93 94 int output = 0; /* do we do output at all? */ 95 int nolist = 0; /* output page list if > 0 */ 96 int olist[20]; /* pairs of page numbers */ 97 struct dev dev; 98 struct font *fontbase[NFONTS+1]; 99 short * pstab; /* point size table pointer */ 100 int nsizes; /* number of sizes device is capable of printing */ 101 int nfonts = 1; /* number of fonts device is capable of printing */ 102 int nstips = 1; /* number of stipple fonts device can print */ 103 int nchtab; 104 char * chname; 105 short * chtab; 106 char * fitab[NFONTS+1]; /* font inclusion table - maps ascii to ch # */ 107 char * widtab[NFONTS+1]; /* width table for each font */ 108 char * codetab[NFONTS+1]; /* device codes */ 109 char * fontdir = FONTDIR; /* place to find devxxx directories */ 110 char * bitdir = BITDIR; /* place to find raster fonts and fontmap */ 111 char * fontname[NFONTS+1]; /* list of what font is on what position */ 112 struct { /* table of what font */ 113 char fname[3]; /* name maps to what */ 114 char *ffile; /* filename in bitdirectory */ 115 } fontmap[NFONTS+1]; 116 117 #ifdef DEBUGABLE 118 int dbg = 0; 119 #endif 120 int size = 1; /* current point size (internal pstable index) */ 121 int font = 1; /* current font - assume reasonable starting font */ 122 int stip = -1; /* current stipple font - none to start with */ 123 int stipmem = 0; /* current member from stipple font to use */ 124 int hpos; /* horizontal position we are to be at next; left = 0 */ 125 int vpos; /* current vertical position (down positive) */ 126 int maxv; /* farthest down the page we've been */ 127 extern linethickness; /* thickness (in pixels) of any drawn object */ 128 extern linmod; /* line style (a bit mask - dotted, etc.) of objects */ 129 int lastw; /* width of last character printed */ 130 131 132 #define DISPATCHSIZE 256 /* must be a power of two */ 133 #define CHARMASK (DISPATCHSIZE-1) 134 #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE) 135 #define OUTFILE fileno (stdout) 136 137 #define RES 200 /* resolution of the device (dots/in) */ 138 #define RASTER_LENGTH 7040 /* device line length */ 139 #define BYTES_PER_LINE (RASTER_LENGTH/8) 140 #define BAND 1 /* length of a band in inches */ 141 #define NLINES (int)(BAND * RES) /* BAND" long bands */ 142 #define BUFFER_SIZE (NLINES*BYTES_PER_LINE) /* number of chars in picture */ 143 144 #define BUFTOP (&buffer[0]) 145 #define BUFBOTTOM (&buffer[BUFFER_SIZE] - 1) 146 #define buf0p BUFTOP /* vorigin in circular buffer */ 147 #define PAGEEND 1 /* flags to "outband" to tell */ 148 #define OVERBAND 0 /* whether to fill out a page */ 149 150 151 int pltmode[] = { VPLOT }; 152 int prtmode[] = { VPRINT }; 153 char buffer[BUFFER_SIZE]; /* versatec-wide NLINES buffer */ 154 int vorigin = 0; /* where on the page startbuf maps to */ 155 int pagelen = 0; /* how long the current "page" has printed */ 156 157 char * calloc(); 158 char * nalloc(); 159 char * allpanic(); 160 char * operand(); 161 162 struct header { 163 short magic; 164 unsigned short size; 165 short maxx; 166 short maxy; 167 short xtnd; 168 } header; 169 170 struct dispatch{ 171 unsigned short addr; 172 short nbytes; 173 char up; 174 char down; 175 char left; 176 char right; 177 short width; 178 }; 179 180 struct fontdes { 181 int fnum; /* if == -1, this position unused */ 182 int psize; 183 struct dispatch *disp; 184 char *bits; 185 } fontdes[NFONTS+1]; /* is initialized at start of main */ 186 187 struct dispatch *dispatch; 188 struct dispatch *stip_disp; 189 int cfnum = -1; 190 int cpsize = 10; 191 int cfont = 1; 192 char *bits; 193 char *stip_bits; 194 int fontwanted = 1; /* flag: "has a new font been requested?" */ 195 int nfontnum = -1; 196 int npsize = 10; 197 198 199 200 main(argc, argv) 201 char *argv[]; 202 { 203 register FILE *fp; 204 register int i; 205 206 for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1); 207 while (--argc > 0 && **++argv == '-') { 208 switch ((*argv)[1]) { 209 case 'F': 210 bitdir = operand(&argc, &argv); 211 break; 212 case 'f': 213 fontdir = operand(&argc, &argv); 214 break; 215 case 'o': 216 outlist(operand(&argc, &argv)); 217 break; 218 #ifdef DEBUGABLE 219 case 'd': 220 dbg = atoi(operand(&argc, &argv)); 221 if (dbg == 0) dbg = 1; 222 break; 223 #endif 224 } 225 } 226 #ifdef DRIVER 227 ioctl(OUTFILE, VSETSTATE, pltmode); 228 #endif 229 230 if (argc < 1) 231 conv(stdin); 232 else 233 while (argc-- > 0) { 234 if (strcmp(*argv, "-") == 0) 235 fp = stdin; 236 else if ((fp = fopen(*argv, "r")) == NULL) 237 error(FATAL, "can't open %s", *argv); 238 conv(fp); 239 fclose(fp); 240 argv++; 241 } 242 exit(0); 243 } 244 245 246 /*----------------------------------------------------------------------------* 247 | Routine: char * operand (& argc, & argv) 248 | 249 | Results: returns address of the operand given with a command-line 250 | option. It uses either "-Xoperand" or "-X operand", whichever 251 | is present. The program is terminated if no option is present. 252 | 253 | Side Efct: argc and argv are updated as necessary. 254 *----------------------------------------------------------------------------*/ 255 256 char *operand(argcp, argvp) 257 int * argcp; 258 char ***argvp; 259 { 260 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */ 261 if ((--*argcp) <= 0) { /* no operand */ 262 error (FATAL, "command-line option operand missing."); 263 } 264 return(*(++(*argvp))); /* operand next word */ 265 } 266 267 268 outlist(s) /* process list of page numbers to be printed */ 269 char *s; 270 { 271 int n1, n2; 272 #ifdef DEBUGABLE 273 int i; 274 #endif 275 276 nolist = 0; 277 while (*s) { 278 n1 = 0; 279 if (isdigit(*s)) 280 do 281 n1 = 10 * n1 + *s++ - '0'; 282 while (isdigit(*s)); 283 else 284 n1 = -9999; 285 n2 = n1; 286 if (*s == '-') { 287 s++; 288 n2 = 0; 289 if (isdigit(*s)) 290 do 291 n2 = 10 * n2 + *s++ - '0'; 292 while (isdigit(*s)); 293 else 294 n2 = 9999; 295 } 296 olist[nolist++] = n1; 297 olist[nolist++] = n2; 298 if (*s != '\0') 299 s++; 300 } 301 olist[nolist] = 0; 302 #ifdef DEBUGABLE 303 if (dbg) 304 for (i=0; i<nolist; i += 2) 305 fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]); 306 #endif 307 } 308 309 conv(fp) 310 register FILE *fp; 311 { 312 register int c, k; 313 int m, n, n1, m1; 314 char str[100], buf[300]; 315 316 while ((c = getc(fp)) != EOF) { 317 switch (c) { 318 case '\n': /* when input is text */ 319 case 0: /* occasional noise creeps in */ 320 case '\t': 321 case ' ': 322 break; 323 case '{': /* push down current environment */ 324 t_push(); 325 break; 326 case '}': 327 t_pop(); 328 break; 329 case '0': case '1': case '2': case '3': case '4': 330 case '5': case '6': case '7': case '8': case '9': 331 /* two motion digits plus a character */ 332 hmot((c-'0')*10 + getc(fp)-'0'); 333 put1(getc(fp)); 334 break; 335 case 'c': /* single ascii character */ 336 put1(getc(fp)); 337 break; 338 case 'C': 339 fscanf(fp, "%s", str); 340 put1s(str); 341 break; 342 case 't': /* straight text */ 343 if (fgets(buf, sizeof(buf), fp) == NULL) 344 error(FATAL, "unexpected end of input"); 345 t_text(buf); 346 break; 347 case 'D': /* draw function */ 348 if (fgets(buf, sizeof(buf), fp) == NULL) 349 error(FATAL, "unexpected end of input"); 350 switch (buf[0]) { 351 case 'l': /* draw a line */ 352 sscanf(buf+1, "%d %d", &n, &m); 353 drawline(n, m); 354 break; 355 case 'c': /* circle */ 356 sscanf(buf+1, "%d", &n); 357 drawcirc(n); 358 break; 359 case 'e': /* ellipse */ 360 sscanf(buf+1, "%d %d", &m, &n); 361 drawellip(m, n); 362 break; 363 case 'a': /* arc */ 364 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); 365 drawarc(n, m, n1, m1); 366 break; 367 case 'q': /* polygon */ 368 n = 1; /* get stipple */ 369 while (isspace(buf[++n])); /* number first */ 370 setfill(atoi(&(buf[n]))); /* set up stipple */ 371 while (isdigit(buf[++n])); 372 polygon(&(buf[n]), fp); /* draw polygon */ 373 break; 374 case '~': /* wiggly line */ 375 case 'g': /* gremlin spline */ 376 drawwig(buf+1, fp, buf[0] == '~'); 377 break; 378 case 't': /* line thickness */ 379 sscanf(buf+1, "%d", &n); 380 drawthick(n); 381 break; 382 case 's': /* line style */ 383 sscanf(buf+1, "%d", &n); 384 drawstyle(n); 385 break; 386 default: 387 error(FATAL, "unknown drawing function %s", buf); 388 break; 389 } 390 break; 391 case 's': 392 fscanf(fp, "%d", &n); 393 setsize(t_size(n)); 394 break; 395 case 'i': 396 fscanf(fp, "%d", &n); 397 setstip(n); 398 break; 399 case 'f': 400 fscanf(fp, "%s", str); 401 setfont(t_font(str)); 402 break; 403 case 'H': /* absolute horizontal motion */ 404 while ((c = getc(fp)) == ' ') 405 ; 406 k = 0; 407 do { 408 k = 10 * k + c - '0'; 409 } while (isdigit(c = getc(fp))); 410 ungetc(c, fp); 411 hgoto(k); 412 break; 413 case 'h': /* relative horizontal motion */ 414 while ((c = getc(fp)) == ' ') 415 ; 416 k = 0; 417 do { 418 k = 10 * k + c - '0'; 419 } while (isdigit(c = getc(fp))); 420 ungetc(c, fp); 421 hmot(k); 422 break; 423 case 'w': /* word space */ 424 break; 425 case 'V': 426 fscanf(fp, "%d", &n); 427 vgoto(n); 428 break; 429 case 'v': 430 fscanf(fp, "%d", &n); 431 vmot(n); 432 break; 433 case 'P': /* new spread */ 434 if (output) outband(OVERBAND); 435 break; 436 case 'p': /* new page */ 437 fscanf(fp, "%d", &n); 438 t_page(n); 439 break; 440 case 'n': /* end of line */ 441 t_newline(); 442 443 case '#': /* comment */ 444 do 445 c = getc(fp); 446 while (c != '\n' && c != EOF); 447 break; 448 case 'x': /* device control */ 449 if (devcntrl(fp)) return; 450 break; 451 default: 452 error(FATAL, "unknown input character %o %c", c, c); 453 } 454 } 455 } 456 457 int devcntrl(fp) /* interpret device control functions */ 458 FILE *fp; /* returns -1 apon recieving "stop" command */ 459 { 460 char str[20], str1[50], buf[50]; 461 int c, n; 462 463 fscanf(fp, "%s", str); 464 switch (str[0]) { /* crude for now */ 465 case 'i': /* initialize */ 466 fileinit(); 467 t_init(); 468 break; 469 case 't': /* trailer */ 470 break; 471 case 'p': /* pause -- can restart */ 472 t_reset('p'); 473 break; 474 case 's': /* stop */ 475 t_reset('s'); 476 return -1; 477 case 'r': /* resolution assumed when prepared */ 478 fscanf(fp, "%d", &n); 479 if (n!=RES) error(FATAL,"Input computed for wrong printer"); 480 break; 481 case 'f': /* font used */ 482 fscanf(fp, "%d %s", &n, str); 483 (void) fgets(buf, sizeof buf, fp); /* in case of filename */ 484 ungetc('\n', fp); /* fgets goes too far */ 485 str1[0] = 0; /* in case nothing comes in */ 486 sscanf(buf, "%s", str1); 487 loadfont(n, str, str1); 488 break; 489 /* these don't belong here... */ 490 case 'H': /* char height */ 491 fscanf(fp, "%d", &n); 492 t_charht(n); 493 break; 494 case 'S': /* slant */ 495 fscanf(fp, "%d", &n); 496 t_slant(n); 497 break; 498 } 499 while ((c = getc(fp)) != '\n') /* skip rest of input line */ 500 if (c == EOF) 501 return -1; 502 return 0; 503 } 504 505 /* fileinit: read in font and code files, etc. 506 Must open table for device, read in resolution, 507 size info, font info, etc. and set params. 508 Also read in font name mapping. 509 */ 510 fileinit() 511 { 512 register int i; 513 register int fin; 514 register int nw; 515 register char *filebase; 516 register char *p; 517 register FILE *fp; 518 char temp[100]; 519 520 521 /* first, read in font map file. The file must be of Format: 522 XX FILENAME (XX = troff font name) 523 with one entry per text line of the file. 524 Extra stuff after FILENAME is ignored */ 525 526 sprintf(temp, "%s/fontmap", bitdir); 527 if ((fp = fopen(temp, "r")) == NULL) 528 error(FATAL, "Can't open %s", temp); 529 for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) { 530 sscanf(temp, "%2s", fontmap[i].fname); 531 p = &temp[0]; 532 while (*p != ' ' && *p != ' ') p++; 533 while (*p == ' ' || *p == ' ') p++; 534 filebase = p; 535 for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++; 536 fontmap[i].ffile = nalloc(1, nw); 537 sscanf(filebase, "%s", fontmap[i].ffile); 538 } 539 fontmap[++i].fname[0] = '0'; /* finish off with zeros */ 540 fontmap[i].ffile = (char *) 0; 541 fclose(fp); 542 #ifdef DEBUGABLE 543 if(dbg) { 544 fprintf(stderr, "font map:\n"); 545 for (i = 0; fontmap[i].ffile; i++) 546 fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile); 547 } 548 #endif 549 550 551 sprintf(temp, "%s/devvp/DESC.out", fontdir); 552 if ((fin = open(temp, 0)) < 0) 553 error(FATAL, "can't open tables for %s", temp); 554 if (read(fin, &dev, sizeof(struct dev)) != sizeof(struct dev)) 555 error(FATAL, "can't read header for %s", temp); 556 nfonts = dev.nfonts; 557 nsizes = dev.nsizes; 558 nstips = dev.nstips; 559 nchtab = dev.nchtab; 560 filebase = calloc(1, dev.filesize); /* enough room for whole file */ 561 if (read(fin, filebase, dev.filesize) != dev.filesize) /* at once */ 562 error(FATAL, "can't read width table for %s", temp); 563 pstab = (short *) filebase; 564 chtab = pstab + nsizes + 1; 565 chname = (char *) (chtab + dev.nchtab); 566 p = chname + dev.lchname; 567 for (i = 1; i <= nfonts; i++) { 568 fontbase[i] = (struct font *) p; 569 nw = *p & BMASK; /* 1st thing is width count */ 570 p += sizeof(struct font); 571 widtab[i] = p; 572 codetab[i] = p + 2 * nw; 573 fitab[i] = p + 3 * nw; 574 p += 3 * nw + dev.nchtab + 128 - 32; 575 t_fp(i, fontbase[i]->namefont, fontbase[i]->intname); 576 #ifdef DEBUGABLE 577 if (dbg > 1) fontprint(i); 578 #endif 579 } 580 for (i = 1; i <= nstips; i++) { /* add in stipple "filenames" */ 581 if (nfonts + i <= NFONTS) 582 t_fp(nfonts + i, p, (char *)0); 583 p += strlen(p) + 1; 584 } 585 fontbase[0] = (struct font *) 586 calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font)); 587 widtab[0] = (char *) fontbase[0] + sizeof (struct font); 588 fontbase[0]->nwfont = 255; 589 close(fin); 590 } 591 592 #ifdef DEBUGABLE 593 fontprint(i) /* debugging print of font i (0,...) */ 594 { 595 int j, n; 596 char *p; 597 598 fprintf(stderr,"font %d:\n", i); 599 p = (char *) fontbase[i]; 600 n = fontbase[i]->nwfont & BMASK; 601 fprintf(stderr, 602 "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p, 603 n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]); 604 fprintf(stderr,"widths:\n"); 605 for (j=0; j <= n; j++) { 606 fprintf(stderr," %2d", widtab[i][j] & BMASK); 607 if (j % 20 == 19) fprintf(stderr,"\n"); 608 } 609 fprintf(stderr,"\ncodetab:\n"); 610 for (j=0; j <= n; j++) { 611 fprintf(stderr," %2d", codetab[i][j] & BMASK); 612 if (j % 20 == 19) fprintf(stderr,"\n"); 613 } 614 fprintf(stderr,"\nfitab:\n"); 615 for (j=0; j <= dev.nchtab + 128-32; j++) { 616 fprintf(stderr," %2d", fitab[i][j] & BMASK); 617 if (j % 20 == 19) fprintf(stderr,"\n"); 618 } 619 fprintf(stderr,"\n"); 620 } 621 #endif 622 623 624 loadfont(n, s, s1) /* load font info for font s on position n (0...) */ 625 int n; 626 char *s, *s1; 627 { 628 char temp[60]; 629 register int fin; 630 register int nw; 631 register int norig; 632 633 if (n < 0 || n > NFONTS) 634 error(FATAL, "illegal fp command %d %s", n, s); 635 if (strcmp(s, fontbase[n]->namefont) == 0) 636 return; 637 638 for (fin = 1; fin <= NFONTS; fin++) /* first check to see if the */ 639 if (strcmp(s, fontbase[fin]->namefont) == 0) { /* font is loaded */ 640 register char *c; /* somewhere else */ 641 642 #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; } 643 #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *)c; } 644 645 ptrfswap(fontbase[n], fontbase[fin]); 646 ptrswap(codetab[n], codetab[fin]); 647 ptrswap(widtab[n], widtab[fin]); 648 ptrswap(fitab[n], fitab[fin]); 649 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); 650 t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname); 651 return; 652 } 653 654 if (s1 == NULL || s1[0] == '\0') 655 sprintf(temp, "%s/devvp/%s.out", fontdir, s); 656 else 657 sprintf(temp, "%s/%s.out", s1, s); 658 if ((fin = open(temp, 0)) < 0) 659 error(FATAL, "can't open font table %s", temp); 660 norig = fontbase[n]->nwfont & BMASK; 661 if (read(fin,fontbase[n],3*norig+nchtab+128-32+sizeof(struct font)) < 0) 662 error(FATAL, "Can't read in font %s on position %d", s, n); 663 if ((fontbase[n]->nwfont & BMASK) > norig) 664 error(FATAL, "Font %s too big for position %d", s, n); 665 close(fin); 666 nw = fontbase[n]->nwfont & BMASK; 667 widtab[n] = (char *) fontbase[n] + sizeof(struct font); 668 codetab[n] = (char *) widtab[n] + 2 * nw; 669 fitab[n] = (char *) widtab[n] + 3 * nw; 670 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); 671 fontbase[n]->nwfont = norig; /* to later use full original size */ 672 #ifdef DEBUGABLE 673 if (dbg > 1) fontprint(n); 674 #endif 675 } 676 677 678 /*VARARGS1*/ 679 error(f, s, a1, a2, a3, a4, a5, a6, a7) { 680 fprintf(stderr, "dver: "); 681 fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); 682 fprintf(stderr, "\n"); 683 if (f) exit(ABORT); 684 } 685 686 687 t_init() /* initialize device */ 688 { 689 vorigin = pagelen = maxv = hpos = vpos = 0; 690 691 output = 0; /* don't output anything yet */ 692 setsize(t_size(10)); /* start somewhere */ 693 setfont(1); 694 } 695 696 697 struct state { 698 int ssize; 699 int sfont; 700 int shpos; 701 int svpos; 702 int sstyle; 703 int sthick; 704 }; 705 struct state state[MAXSTATE]; 706 struct state *statep = state; 707 708 t_push() /* begin a new block */ 709 { 710 statep->ssize = size; 711 statep->sfont = font; 712 statep->sstyle = linmod; 713 statep->sthick = linethickness; 714 statep->shpos = hpos; 715 statep->svpos = vpos; 716 if (statep++ >= state+MAXSTATE) 717 error(FATAL, "{ nested too deep"); 718 } 719 720 t_pop() /* pop to previous state */ 721 { 722 if (--statep < state) 723 error(FATAL, "extra }"); 724 size = statep->ssize; 725 font = statep->sfont; 726 hpos = statep->shpos; 727 vpos = statep->svpos; 728 linmod = statep->sstyle; 729 linethickness = statep->sthick; 730 } 731 732 733 t_page(n) /* do whatever new page functions */ 734 { 735 int i; 736 737 738 if (output) outband(PAGEEND); 739 740 maxv = vpos = 0; 741 742 output = 1; 743 if (nolist == 0) 744 return; /* no -o specified */ 745 output = 0; 746 for (i = 0; i < nolist; i += 2) 747 if (n >= olist[i] && n <= olist[i+1]) { 748 output = 1; 749 break; 750 } 751 } 752 753 754 outband(page) 755 int page; 756 { 757 register int outsize; 758 759 if (page == PAGEEND) { /* set outsize to inch boundary */ 760 outsize = (maxv + (RES - 2) - pagelen) / RES; 761 vorigin = pagelen = 0; /* reset for new page */ 762 if (outsize < 1) return; /* if outsize <= zero, forget it */ 763 764 outsize *= RES * BYTES_PER_LINE; 765 vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize); 766 vclear(buf0p, BUFFER_SIZE); 767 while ((outsize -= BUFFER_SIZE) > 0) 768 vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize); 769 } else { 770 vorigin += NLINES; 771 pagelen += NLINES; 772 vwrite(buf0p, BUFFER_SIZE); 773 vclear(buf0p, BUFFER_SIZE); 774 } 775 } 776 777 778 t_newline() /* do whatever for the end of a line */ 779 { 780 hpos = 0; /* because we're now back at the left margin */ 781 } 782 783 t_size(n) /* convert integer to internal size number*/ 784 int n; 785 { 786 int i; 787 788 if (n <= pstab[0]) 789 return(0); 790 else if (n >= pstab[nsizes - 1]) 791 return(nsizes - 1); 792 for (i = 0; n > pstab[i]; i++) 793 ; 794 return(i); 795 } 796 797 /*ARGSUSED*/ 798 t_charht(n) /* set character height to n */ 799 int n; 800 { 801 #ifdef DEBUGABLE 802 if (dbg) error(!FATAL, "can't set height on versatec"); 803 #endif 804 } 805 806 /*ARGSUSED*/ 807 t_slant(n) /* set slant to n */ 808 int n; 809 { 810 #ifdef DEBUGABLE 811 if (dbg) error(!FATAL, "can't set slant on versatec"); 812 #endif 813 } 814 815 t_font(s) /* convert string to internal font number */ 816 char *s; 817 { 818 int n; 819 820 n = atoi(s); 821 if (n < 0 || n > nfonts) 822 n = 1; 823 return(n); 824 } 825 826 t_text(s) /* print string s as text */ 827 char *s; 828 { 829 int c; 830 char str[100]; 831 832 if (!output) 833 return; 834 while (c = *s++) { 835 if (c == '\\') { 836 switch (c = *s++) { 837 case '\\': 838 case 'e': 839 put1('\\'); 840 break; 841 case '(': 842 str[0] = *s++; 843 str[1] = *s++; 844 str[2] = '\0'; 845 put1s(str); 846 break; 847 } 848 } else { 849 put1(c); 850 } 851 hmot(lastw); 852 #ifdef DEBUGABLE 853 if (dbg) fprintf(stderr,"width = %d\n", lastw); 854 #endif 855 } 856 } 857 858 859 t_reset(c) 860 { 861 switch(c){ 862 case 's': 863 t_page(0); 864 #ifdef DRIVER 865 ioctl(OUTFILE, VSETSTATE, prtmode); 866 #endif 867 break; 868 } 869 } 870 871 872 vgoto (n) 873 int n; 874 { 875 vpos = n; 876 } 877 878 879 put1s(s) /* s is a funny char name */ 880 char *s; 881 { 882 int i; 883 884 if (!output) 885 return; 886 #ifdef DEBUGABLE 887 if (dbg) fprintf(stderr,"%s ", s); 888 #endif 889 for (i = 0; i < nchtab; i++) 890 if (strcmp(&chname[chtab[i]], s) == 0) 891 break; 892 if (i < nchtab) 893 put1(i + 128); 894 } 895 896 put1(c) /* output char c */ 897 int c; 898 { 899 char *pw; 900 register char *p; 901 register int i, k; 902 int j, ofont, code; 903 904 if (!output) 905 return; 906 c -= 32; 907 if (c <= 0) { 908 #ifdef DEBUGABLE 909 if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32); 910 #endif 911 lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2) 912 / dev.unitwidth; 913 return; 914 } 915 k = ofont = font; 916 i = fitab[font][c] & BMASK; 917 if (i != 0) { /* it's on this font */ 918 p = codetab[font]; /* get the printing value of ch */ 919 pw = widtab[font]; /* get the width */ 920 } else /* on another font (we hope) */ 921 for (j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){ 922 if (fitab[k] == 0) 923 continue; 924 if ((i = fitab[k][c] & BMASK) != 0) { 925 p = codetab[k]; 926 pw = widtab[k]; 927 setfont(k); 928 break; 929 } 930 } 931 932 if (i == 0) { 933 #ifdef DEBUGABLE 934 if (dbg) fprintf(stderr,"not found 0%o\n", c+32); 935 #endif 936 return; 937 } 938 code = p[i] & BMASK; 939 #ifdef DEBUGABLE 940 if (dbg) { 941 if (isprint(c+32)) 942 fprintf(stderr,"%c %d\n", c+32, code); 943 else 944 fprintf(stderr,"%03o %d\n", c+32, code); 945 } 946 #endif 947 outc(code); /* character is < 254 */ 948 if (font != ofont) 949 setfont(ofont); 950 lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth; 951 } 952 953 954 955 setsize(n) /* set point size to n (internal) */ 956 int n; 957 { 958 959 if (n == size) 960 return; /* already there */ 961 if (vloadfont(font, pstab[n]) != -1) 962 size = n; 963 } 964 965 /*ARGSUSED*/ 966 t_fp(n, s, si) /* font position n now contains font s, intname si */ 967 int n; /* internal name is ignored */ 968 char *s, *si; 969 { 970 register int i; 971 972 /* first convert s to filename if possible */ 973 for (i = 0; fontmap[i].ffile != (char *) 0; i++) { 974 #ifdef DEBUGABLE 975 if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname); 976 #endif 977 if (strcmp(s, fontmap[i].fname) == 0) { 978 s = fontmap[i].ffile; 979 #ifdef DEBUGABLE 980 if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile); 981 #endif 982 break; 983 } 984 } 985 986 fontname[n] = s; 987 for(i = 0;i <= NFONTS;i++) /* free the bits of that font */ 988 if (fontdes[i].fnum == n){ 989 nfree(fontdes[i].bits); 990 fontdes[i].fnum = -1; 991 } 992 } 993 994 setfont(n) /* set font to n */ 995 int n; 996 { 997 if (n < 0 || n > nfonts) 998 error(FATAL, "illegal font %d", n); 999 if (vloadfont(n,pstab[size]) != -1) 1000 font = n; 1001 } 1002 1003 setstip(n) /* set stipple font to n */ 1004 int n; 1005 { 1006 if (n < 1 || n > nstips) 1007 error(FATAL, "illegal stipple %d", n); 1008 stip = n; 1009 } 1010 1011 1012 /*----------------------------------------------------------------------------* 1013 | Routine: setfill(stipple_number) 1014 | 1015 | Results: sets the fill-pattern pointers (stip_disp and 1016 | stip_bits) for a particular stipple. Takes stipple 1017 | font from current "stip" number. 1018 *----------------------------------------------------------------------------*/ 1019 1020 setfill(number) 1021 int number; 1022 { 1023 int curfont; /* places to save current text font */ 1024 int cursize; 1025 1026 /* set global stipmem for polygon */ 1027 if (number < 0 || number >= DISPATCHSIZE) 1028 stipmem = 0; 1029 else 1030 stipmem = number; 1031 1032 curfont = cfnum; /* get pointers to */ 1033 cursize = cpsize; /* the inuse font */ 1034 if (vloadfont(nfonts + stip, 0)) { 1035 stip_disp = (struct dispatch *) NULL; /* stipple not here */ 1036 } else { 1037 if (fontwanted) { 1038 if (getfont()) { 1039 stip_disp = (struct dispatch *) NULL; 1040 } else { 1041 stip_disp = dispatch; /* save for polygon routine */ 1042 stip_bits = bits; 1043 } 1044 } else { 1045 stip_disp = dispatch; /* save for polygon routine */ 1046 stip_bits = bits; 1047 } 1048 } 1049 vloadfont(curfont, cursize); 1050 } 1051 1052 1053 vloadfont(fnum, fsize) 1054 register int fnum; 1055 register int fsize; 1056 { 1057 register int i; 1058 1059 fontwanted = 0; 1060 if (fnum == cfnum && fsize == cpsize) 1061 return(0); 1062 for (i = 0; i <= NFONTS; i++) { 1063 if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) { 1064 cfnum = fontdes[i].fnum; 1065 cpsize = fontdes[i].psize; 1066 dispatch = &fontdes[i].disp[0]; 1067 bits = fontdes[i].bits; 1068 cfont = i; 1069 return (0); 1070 } 1071 } 1072 /* this is a new font */ 1073 if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) { 1074 #ifdef DEBUGABLE 1075 if (dbg) error(!FATAL, "illegal font %d size %d", fnum, fsize); 1076 #endif 1077 return(-1); 1078 } 1079 /* Need to verify the existance of that font/size here*/ 1080 nfontnum = fnum; 1081 npsize = fsize; 1082 fontwanted++; 1083 return (0); 1084 } 1085 1086 1087 getfont() 1088 { 1089 register int fnum; 1090 register int fsize; 1091 register int fontd; 1092 register int d; 1093 register int sizehunt = size; 1094 char cbuf[BUFSIZ]; 1095 1096 1097 fnum = nfontnum; 1098 fsize = npsize; 1099 /* try to open font file - if unsuccessful, hunt for */ 1100 /* a file of same style, different size to substitute */ 1101 d = -1; /* direction to look in pstab (smaller first) */ 1102 do { 1103 sprintf(cbuf, "%s/%s.%d", bitdir, fontname[fnum], fsize); 1104 fontd = open(cbuf, OPENREAD); 1105 if (fontd == -1) { /* File wasn't found. Try another ps */ 1106 sizehunt += d; 1107 if (sizehunt < 0) { /* past beginning - look higher */ 1108 d = 1; 1109 sizehunt = size + 1; 1110 } 1111 if (sizehunt > nsizes) { /* past top - forget it */ 1112 d = 0; 1113 } else { 1114 fsize = pstab[sizehunt]; 1115 } 1116 } 1117 } while (fontd == -1 && d != 0); 1118 1119 if (fontd == -1) { /* completely unsuccessful */ 1120 perror(cbuf); 1121 error(!FATAL,"fnum = %d, psize = %d, name = %s", 1122 fnum, npsize, fontname[fnum]); 1123 fontwanted = 0; 1124 return (-1); 1125 } 1126 if (read(fontd, &header, sizeof (header)) != sizeof (header) 1127 || header.magic != 0436) 1128 fprintf(stderr, "%s: Bad font file", cbuf); 1129 else { 1130 cfont = relfont(); 1131 if ((bits=nalloc(header.size+DSIZ+1,1))== NULL) 1132 if ((bits=allpanic(header.size+DSIZ+1))== NULL) { 1133 error(FATAL, "%s: ran out of memory", cbuf); 1134 } 1135 1136 /* 1137 * have allocated one chunk of mem for font, dispatch. 1138 * get the dispatch addr, align to word boundary. 1139 */ 1140 1141 d = (int) bits+header.size; 1142 d += 1; 1143 d &= ~1; 1144 if (read (fontd, d, DSIZ) != DSIZ 1145 || read (fontd, bits, header.size) != header.size) 1146 fprintf(stderr, "bad font header"); 1147 else { 1148 close(fontd); 1149 cfnum = fontdes[cfont].fnum = fnum; 1150 cpsize = fontdes[cfont].psize = fsize; 1151 fontdes [cfont].bits = bits; 1152 fontdes [cfont].disp = (struct dispatch *) d; 1153 dispatch = &fontdes[cfont].disp[0]; 1154 fontwanted = 0; 1155 return (0); 1156 } 1157 } 1158 close(fontd); 1159 fontwanted = 0; 1160 return(-1); 1161 } 1162 1163 /* 1164 * "release" a font position - find an empty one, if possible 1165 */ 1166 1167 relfont() 1168 { 1169 register int newfont; 1170 1171 for (newfont = 0; newfont < NFONTS; newfont++) 1172 if (fontdes [newfont].fnum == -1) 1173 break; 1174 if (fontdes [newfont].fnum != -1) { 1175 nfree (fontdes [newfont].bits); 1176 #ifdef DEBUGABLE 1177 if (dbg) fprintf (stderr, "freeing position %d\n", newfont); 1178 } else { 1179 if (dbg) 1180 fprintf (stderr, "taking, not freeing, position %d\n", newfont); 1181 #endif 1182 } 1183 fontdes[newfont].fnum = -1; 1184 return (newfont); 1185 } 1186 1187 char *allpanic (nbytes) 1188 int nbytes; 1189 { 1190 register int i; 1191 1192 for (i = 0; i <= NFONTS; i++) { 1193 if (fontdes[i].fnum != -1) nfree(fontdes[i].bits); 1194 fontdes[i].fnum = fontdes[i].psize = -1; 1195 cfnum = cpsize = -1; 1196 } 1197 return(nalloc(nbytes,1)); 1198 } 1199 1200 int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8, 1201 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 }; 1202 int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707, 1203 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff }; 1204 int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 }; 1205 1206 outc(code) 1207 int code; /* character to print */ 1208 { 1209 register struct dispatch *dis; /* ptr to character font record */ 1210 register char *addr; /* addr of font data */ 1211 int llen; /* length of each font line */ 1212 int nlines; /* number of font lines */ 1213 register char *scanp; /* ptr to output buffer */ 1214 int scanp_inc; /* increment to start of next buffer */ 1215 int offset; /* bit offset to start of font data */ 1216 register int i; /* loop counter */ 1217 register int count; /* font data ptr */ 1218 register unsigned fontdata; /* font data temporary */ 1219 register int off8; /* reverse of offset */ 1220 1221 if (fontwanted) 1222 if (getfont()) return; 1223 dis = dispatch + code; 1224 if (dis->nbytes) { 1225 #ifdef DEBUGABLE 1226 if (dbg) fprintf(stderr, "char %d at (%d,%d)", code, hpos, vpos); 1227 #endif 1228 addr = bits + dis->addr; 1229 llen = (dis->left + dis->right + 7) / 8; 1230 nlines = dis->up + dis->down; 1231 if ((i = vpos + dis->down) > maxv) maxv = i; 1232 scanp = buf0p + (vpos - (vorigin + dis->up)) * BYTES_PER_LINE 1233 + (hpos - dis->left) / 8; 1234 scanp_inc = BYTES_PER_LINE - llen; 1235 offset = (hpos - dis->left) &07; 1236 off8 = 8 - offset; 1237 for (i = 0; i < nlines; i++) { 1238 if (scanp + (count = llen) > BUFBOTTOM) { 1239 #ifdef DEBUGABLE 1240 if (dbg) fprintf(stderr, " scrapped\n"); 1241 #endif 1242 return; 1243 } 1244 #ifdef DEBUGABLE 1245 if (dbg) fprintf(stderr, "-"); 1246 #endif 1247 if (scanp >= BUFTOP) { 1248 do { 1249 fontdata = *(unsigned *)addr; 1250 addr += 4; 1251 if (count < 4) 1252 fontdata &= ~strim[count]; 1253 *(unsigned*)scanp |=(fontdata >> offset) & ~M[off8]; 1254 scanp++; 1255 *(unsigned*)scanp |=(fontdata << off8) & ~N[off8]; 1256 scanp += 3; 1257 count -= 4; 1258 } while (count > 0); 1259 } 1260 scanp += scanp_inc+count; 1261 addr += count; 1262 } 1263 #ifdef DEBUGABLE 1264 if (dbg) fprintf(stderr, "\n"); 1265 #endif 1266 } 1267 } 1268 1269 1270 vwrite(buf,usize) 1271 char *buf; 1272 int usize; 1273 { 1274 register int tsize = 0; 1275 1276 while (usize) { 1277 buf += tsize; 1278 tsize = usize > MAXWRIT ? MAXWRIT : usize; 1279 #ifdef DEBUGABLE 1280 if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize); 1281 if (!dbg) 1282 #endif 1283 if ((tsize = write(OUTFILE, buf, tsize)) < 0) { 1284 perror("dver: write failed"); 1285 exit(RESTART); 1286 } 1287 usize -= tsize; 1288 } 1289 } 1290 1291 vclear (ptr, nbytes) 1292 char *ptr; 1293 int nbytes; 1294 { 1295 register tsize = 0; 1296 1297 while (nbytes){ 1298 if ((unsigned)(16*1024) < nbytes) { 1299 tsize = 16 * 1024; 1300 } else 1301 tsize = nbytes; 1302 nbytes -= tsize; 1303 #ifdef DEBUGABLE 1304 if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize); 1305 #endif 1306 clear(ptr,tsize); 1307 ptr += tsize; 1308 } 1309 } 1310 1311 /*ARGSUSED*/ 1312 clear(lp, nbytes) 1313 char *lp; 1314 int nbytes; 1315 { 1316 #ifdef vax 1317 asm("movc5 $0,(sp),$0,8(ap),*4(ap)"); 1318 #else 1319 register int i = nbytes; 1320 register char *cp = lp; 1321 1322 while(i-- > 0) 1323 *(cp++) = 0; 1324 #endif 1325 } 1326 1327 char * 1328 nalloc(i, j) 1329 int i, j; 1330 { 1331 register char *cp; 1332 1333 cp = calloc(i, j); 1334 #ifdef DEBUGABLE 1335 if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp); 1336 #endif 1337 return(cp); 1338 } 1339 1340 nfree(cp) 1341 char *cp; 1342 { 1343 #ifdef DEBUGABLE 1344 if (dbg) fprintf(stderr, "freeing at %x\n", cp); 1345 #endif 1346 free(cp); 1347 } 1348 1349 1350 /* 1351 * Plot a dot at (x, y). Points should be in the range 0 <= x < RASTER_LENGTH, 1352 * vorigin <= y < vorigin + NLINES. If the point will not fit on the buffer, 1353 * it is left out. Things outside the x boundary are wrapped around the end. 1354 */ 1355 point(x, y) 1356 register int x; 1357 register int y; 1358 { 1359 register char *ptr = buf0p + (y - vorigin) * BYTES_PER_LINE + (x >> 3); 1360 1361 if (ptr > BUFBOTTOM || ptr < BUFTOP) /* ignore if it's off buffer */ 1362 return; 1363 1364 *ptr |= 1 << (7 - (x & 07)); 1365 if (y > maxv) maxv = y; 1366 } 1367 1368 1369 #define MAXX 0x7fff /* largest positive int */ 1370 #define MINX 0x8000 /* smallest negative int */ 1371 #define MAXVECT 75 1372 1373 typedef struct poly { 1374 struct poly *next; /* doublely-linked lists of vectors */ 1375 struct poly *prev; 1376 int param; /* bressenham line algorithm parameter */ 1377 short dy; /* delta-y for calculating line */ 1378 short dx; /* delta-x for calculating line */ 1379 short currx; /* current x in this vector */ 1380 short endy; /* where vector ends */ 1381 } polyvector; 1382 1383 int rp_len; /* length of the string in "buf" */ 1384 char * rp_ptr; /* "walking" pointer into buf */ 1385 1386 1387 /*----------------------------------------------------------------------------* 1388 | Routine: read_poly (input_buffer, file_pointer) 1389 | 1390 | Results: gets an integer from buffer pointed to by rp_ptr, 1391 | and advances in the file. If there is nothing left, 1392 | more can be read in from the file. rp_ptr and rp_len 1393 | are set in "polygon". 1394 *----------------------------------------------------------------------------*/ 1395 1396 read_poly(buf, fp) 1397 char *buf; 1398 FILE *fp; 1399 { 1400 register int i; 1401 1402 1403 if (*rp_ptr == '\n') 1404 return 0; 1405 1406 while (isspace(*++rp_ptr)); /* skip any leading spaces */ 1407 i = atoi(rp_ptr); /* convert motion to curve points */ 1408 while (isdigit(*++rp_ptr)); /* skip number*/ 1409 /* if the amount we read wasn't the */ 1410 /* whole thing, read some more in */ 1411 if (rp_len - (rp_ptr - buf) < 10 && *(buf + rp_len - 1) != '\n') { 1412 register char *cop = buf; 1413 1414 while (*(cop++) = *(rp_ptr++)); /* what's left to beginning */ 1415 if (fgets ((cop - 1), rp_len - (cop - buf), fp) == NULL) 1416 error(FATAL, "unexpected end of input"); 1417 rp_ptr = buf; 1418 } 1419 1420 return i; 1421 } 1422 1423 1424 /*----------------------------------------------------------------------------* 1425 | Routine: polygon ( string, file ) 1426 | 1427 | Results: draws a polygon specified by the parameters encoded into the 1428 | string (and from the file, if necessary). The parameters are 1429 | broken up into separate vectors. The vectors are encoded as 1430 | follows: (p dx dy curx endy); endy is the bottom of vector, 1431 | curx is where x starts; dx, dy are the deltas for the line; 1432 | if dy is negative, p is the Bresenham line algorithm parameter, 1433 | otherwise p is the starting y. All the active vectors must be 1434 | put first. 1435 | 1436 | The polygon is filled with a stipple pattern from stip_disp 1437 | and stip_bits, which point to the stipple font. The pattern 1438 | is defined by "stip" and "stipmem". 1439 | 1440 | The scan-line algorithm implemented scans from top to 1441 | bottom (low y to high y). It also scans, within a line, 1442 | from left to right (low x to high x). 1443 | 1444 | Bugs: stipple pattern MUST be a power of two bytes "wide" and 1445 | square. The square restriction comes from the fact that 1446 | the varian and versatec are respectively rotated. 1447 *----------------------------------------------------------------------------*/ 1448 1449 polygon(buf, fp) 1450 char *buf; 1451 FILE *fp; 1452 { 1453 int nexty; /* at what y value the next vector starts */ 1454 int maxy, miny; /* finds bounds of polygon */ 1455 polyvector *activehead; /* doing fill, is active edge list */ 1456 polyvector *waitinghead; /* edges waiting to be active */ 1457 register polyvector *vectptr; /* random vector */ 1458 register int i; /* random register */ 1459 1460 char *topstipple; /* points to beginning of stipple glyph */ 1461 char *leftstipple; /* points to beginning of line of stipple */ 1462 char *leftpage; /* points to the edge of a raster line */ 1463 int bytewidth; /* glyph width in bytes */ 1464 int mask; /* mask to pick off pixel index into stipple */ 1465 int bytemask; /* mask to pick off byte index into stipple */ 1466 1467 1468 rp_len = strlen(buf); /* length of the string in "buf" */ 1469 rp_ptr = buf; /* "walking" pointer into buf */ 1470 /* if no stipple, don't fill */ 1471 if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL) 1472 goto leavepoly; 1473 1474 stip_disp += stipmem; /* set up parameters for */ 1475 if (!stip_disp->nbytes) { /* tiling with the stipple */ 1476 #ifdef DEBUGABLE 1477 error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip); 1478 #endif 1479 goto leavepoly; 1480 } 1481 topstipple = stip_bits + stip_disp->addr; 1482 bytewidth = stip_disp->up + stip_disp->down; 1483 for (i = 1 << 30; i && i != bytewidth; i = i >> 1) 1484 ; 1485 if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) { 1486 error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem); 1487 goto leavepoly; 1488 } 1489 mask = bytewidth - 1; 1490 bytewidth = bytewidth >> 3; 1491 bytemask = bytewidth - 1; 1492 1493 if ((i = read_poly(buf, fp)) < 2) /* # of vects command holds */ 1494 goto leavepoly; 1495 miny = read_poly(buf, fp); /* get limits from command */ 1496 maxy = read_poly(buf, fp); 1497 1498 leftstipple = topstipple + (miny & mask) * bytewidth; 1499 leftpage = buf0p + (miny - vorigin) * BYTES_PER_LINE; 1500 1501 /* allocate space for raster-fill algorithm*/ 1502 vectptr = (polyvector *) nalloc(sizeof(polyvector), i + 4); 1503 if (vectptr == (polyvector *) NULL) { 1504 error(!FATAL, "unable to allocate space for polygon"); 1505 return; 1506 } 1507 1508 waitinghead = vectptr; 1509 vectptr->param = miny - 1; /* put dummy entry at start */ 1510 (vectptr++)->prev = NULL; 1511 waitinghead->next = vectptr; 1512 vectptr->prev = waitinghead; 1513 1514 while (i--) { 1515 vectptr->next = vectptr + 1; 1516 vectptr->param = read_poly(buf, fp); 1517 vectptr->dx = read_poly(buf,fp); 1518 vectptr->dy = read_poly(buf,fp); 1519 vectptr->currx = read_poly(buf,fp); 1520 (vectptr++)->endy = read_poly(buf,fp); 1521 vectptr->prev = vectptr - 1; 1522 } 1523 1524 vectptr->param = maxy + 1; /* dummy entry at end, too */ 1525 vectptr->currx = vectptr->dx = vectptr->dy = 0; 1526 vectptr->next = NULL; 1527 1528 activehead = ++vectptr; /* two dummy entries for active list */ 1529 vectptr->currx = MINX; /* head */ 1530 vectptr->endy = maxy + 1; 1531 vectptr->param = vectptr->dx = vectptr->dy = 0; 1532 activehead->next = ++vectptr; 1533 activehead->prev = vectptr; 1534 vectptr->prev = activehead; /* tail */ 1535 vectptr->next = activehead; 1536 vectptr->currx = MAXX; 1537 vectptr->endy = maxy + 1; 1538 vectptr->param = vectptr->dx = vectptr->dy = 0; 1539 1540 vectptr = waitinghead->next; /* if anything is active already */ 1541 if (vectptr->dy < 0) { /* put them into the active list */ 1542 register polyvector *p; /* random useful register pointer */ 1543 1544 p = vectptr; 1545 do { 1546 vectptr->dy = -vectptr->dy; 1547 } while ((++vectptr)->dy < 0); 1548 1549 waitinghead->next = vectptr; /* first, remove list from waiting */ 1550 (vectptr--)->prev = waitinghead; 1551 1552 activehead->next->prev = vectptr; /* link in end */ 1553 vectptr->next = activehead->next; 1554 activehead->next = p; /* link in start */ 1555 p->prev = activehead; 1556 } 1557 1558 /* main loop -- gets vectors off the waiting list, */ 1559 /* then displays spans while updating the vectors in */ 1560 /* the active list */ 1561 while (miny <= maxy) { 1562 i = maxy + 1; /* this is the NEXT time to get a new vector */ 1563 for (vectptr = waitinghead->next; vectptr != NULL; ) { 1564 if (miny == vectptr->param) { 1565 /* the entry in waiting list (vectptr) is */ 1566 /* ready to go into active list. Need to */ 1567 /* convert some vector stuff and sort the */ 1568 /* entry into the list. */ 1569 register polyvector *p; /* random vector pointers */ 1570 register polyvector *v; 1571 1572 /* convert this */ 1573 if (vectptr->dx < 0) /* entry to active */ 1574 vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1)); 1575 else 1576 vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1); 1577 1578 p = vectptr; /* remove from the */ 1579 vectptr = vectptr->next; /* waiting list */ 1580 vectptr->prev = p->prev; 1581 p->prev->next = vectptr; 1582 /* find where it goes */ 1583 /* in the active list */ 1584 /* (sorted smallest first) */ 1585 for (v = activehead->next; v->currx < p->currx; v = v->next) 1586 ; 1587 p->next = v; /* insert into active list */ 1588 p->prev = v->prev; /* before the one it stopped on */ 1589 v->prev = p; 1590 p->prev->next = p; 1591 } else { 1592 if (i > vectptr->param) { 1593 i = vectptr->param; 1594 } 1595 vectptr = vectptr->next; 1596 } 1597 } 1598 nexty = i; 1599 1600 /* print the polygon while there */ 1601 /* are no more vectors to add */ 1602 while (miny < nexty) { 1603 /* remove any finished vectors */ 1604 vectptr = activehead->next; 1605 do { 1606 if (vectptr->endy <= miny) { 1607 vectptr->prev->next = vectptr->next; 1608 vectptr->next->prev = vectptr->prev; 1609 } 1610 } while ((vectptr = vectptr->next) != activehead); 1611 1612 /* draw the span */ 1613 vectptr = activehead->next; 1614 while (vectptr->next != activehead) { 1615 register int start; /* get the beginning */ 1616 register int length; /* and the end of span */ 1617 register char *glyph; 1618 register char *raster; 1619 1620 start = vectptr->currx; 1621 vectptr = vectptr->next; 1622 length = vectptr->currx + 1; 1623 vectptr = vectptr->next; 1624 1625 /* bound the polygon to the page */ 1626 if (start >= RASTER_LENGTH) 1627 break; 1628 if (start < 0) start = 0; 1629 if (length > RASTER_LENGTH) length = RASTER_LENGTH; 1630 length -= start; /* length is in pixels */ 1631 1632 i = start & 7; 1633 start = start >> 3; /* start is in bytes */ 1634 raster = leftpage + start; 1635 glyph = leftstipple + (start & bytemask); 1636 1637 if (i) { /* do any piece of byte */ 1638 register char data; /* that hangs on the front */ 1639 1640 data = (*(glyph++)) & (0x7f >> --i); 1641 length -= 7 - i; 1642 if (length < 0) { /* less than one byte wide? */ 1643 data &= 0xff << -length; 1644 length = 0; /* force clean stoppage */ 1645 } 1646 *(raster++) |= data; 1647 /* update glyph ptr after first byte */ 1648 if (!(++start & bytemask)) 1649 glyph = leftstipple; 1650 } 1651 /* fill the line of raster */ 1652 while ((length -= 8) >= 0) { 1653 *(raster++) |= *(glyph++); 1654 if (!(++start & bytemask)) 1655 glyph = leftstipple; 1656 } 1657 if (length & 7) { /* add any part hanging off the end */ 1658 *raster |= (*glyph) & (0xff << -length); 1659 } 1660 } 1661 1662 #ifdef DEBUGABLE 1663 if (dbg) { 1664 vectptr = activehead; 1665 do { 1666 fprintf (stderr, "%d ", vectptr->currx); 1667 vectptr = vectptr->next; 1668 } while (vectptr != activehead); 1669 } 1670 #endif 1671 /* update the vectors */ 1672 vectptr = activehead->next; 1673 do { 1674 if (vectptr->dx > 0) { 1675 while (vectptr->param >= 0) { 1676 vectptr->param -= vectptr->dy; 1677 vectptr->currx++; 1678 } 1679 vectptr->param += vectptr->dx; 1680 } else if (vectptr->dx < 0) { 1681 while (vectptr->param >= 0) { 1682 vectptr->param -= vectptr->dy; 1683 vectptr->currx--; 1684 } 1685 vectptr->param -= vectptr->dx; 1686 } 1687 /* must sort the vectors if updates */ 1688 /* caused them to cross */ 1689 /* also move to next vector here */ 1690 if (vectptr->currx < vectptr->prev->currx) { 1691 register polyvector *v; /* vector to move */ 1692 register polyvector *p; /* vector to put it after */ 1693 1694 v = vectptr; 1695 p = v->prev; 1696 while (v->currx < p->currx) /* find the */ 1697 p = p->prev; /* right vector */ 1698 1699 vectptr = vectptr->next; /* remove from spot */ 1700 vectptr->prev = v->prev; 1701 v->prev->next = vectptr; 1702 1703 v->prev = p; /* put in new spot */ 1704 v->next = p->next; 1705 p->next = v; 1706 v->next->prev = v; 1707 } else { 1708 vectptr = vectptr->next; 1709 } 1710 } while (vectptr != activehead); 1711 #ifdef DEBUGABLE 1712 if (dbg) fprintf(stderr, "line done\n"); 1713 #endif 1714 1715 if (++miny & mask) { 1716 leftstipple += bytewidth; 1717 } else { 1718 leftstipple = topstipple; 1719 } 1720 leftpage += BYTES_PER_LINE; 1721 } /* while (miny < nexty) */ 1722 } /* while (miny <= maxy) */ 1723 1724 nfree(waitinghead); /* dump the space allocated for polygon */ 1725 1726 leavepoly: 1727 while (*rp_ptr != '\n') 1728 i = read_poly(buf, fp); 1729 } /* polygon function */ 1730