|
|
1.1 ! root 1: ! 2: /* ! 3: * ! 4: * Drawing routines used dimpress. Most, if not all the complicated code ! 5: * has been eliminated for systems running version 1.9 or later systems. ! 6: * ! 7: * If your printer doesn't support the Impress graphics primitives used ! 8: * in this file make sure you use an old version of draw.c. ! 9: * ! 10: * Apparently there's a bug in the Impress version 2.0 ellipse code. If ! 11: * you're drawing part of an ellipse and radiusa < radiusb things get ! 12: * messed up. That won't happen often - in fact only when the apsect ! 13: * ratio is less than 1. All other cases seem to work properly. I expect ! 14: * the problem to be fixed soon so I haven't bothered trying to get ! 15: * around it. ! 16: * ! 17: */ ! 18: ! 19: ! 20: #include <stdio.h> ! 21: #include <math.h> ! 22: ! 23: #include "gen.h" /* general purpose definitions */ ! 24: #include "impcodes.h" /* version 2.0 Impress codes */ ! 25: ! 26: ! 27: #define XSCALE(A) ((int) ((A) * xfac + .5 + xoffset)) ! 28: #define YSCALE(A) ((int) ((A) * yfac + .5 + yoffset)) ! 29: ! 30: ! 31: int maxdots = 32000; ! 32: ! 33: /* ! 34: * ! 35: * All these guys should be defined in file dimpress.c. ! 36: * ! 37: */ ! 38: ! 39: ! 40: extern int hpos; ! 41: extern int vpos; ! 42: extern int xoffset; ! 43: extern int yoffset; ! 44: extern float xfac; ! 45: extern float yfac; ! 46: extern int lastx; ! 47: extern int lasty; ! 48: extern int DX; ! 49: extern int DY; ! 50: extern FILE *tf; ! 51: ! 52: ! 53: /*****************************************************************************/ ! 54: ! 55: ! 56: dist(x1, y1, x2, y2) ! 57: ! 58: ! 59: int x1, y1, x2, y2; ! 60: ! 61: ! 62: { ! 63: ! 64: ! 65: float dx, dy; ! 66: ! 67: ! 68: /* ! 69: * ! 70: * Returns the integer distance between points (x1, y1) and (x2, y2). ! 71: * ! 72: */ ! 73: ! 74: ! 75: dx = x2 - x1; ! 76: dy = y2 - y1; ! 77: ! 78: return(sqrt(dx*dx + dy*dy) + 0.5); ! 79: ! 80: } /* End of dist */ ! 81: ! 82: ! 83: /*****************************************************************************/ ! 84: ! 85: ! 86: char *getstr(p, temp) ! 87: ! 88: ! 89: char *p; /* next string copied from here */ ! 90: char *temp; /* and saved here */ ! 91: ! 92: ! 93: { ! 94: ! 95: ! 96: /* ! 97: * ! 98: * Copies the next non-blank string from p to temp. p is updated and the final ! 99: * final value of the pointer is returned to the caller. Probably could do all ! 100: * this stuff just as easily using strtok(). ! 101: * ! 102: */ ! 103: ! 104: ! 105: while (*p == ' ' || *p == '\t' || *p == '\n') ! 106: p++; ! 107: ! 108: if (*p == '\0') { ! 109: temp[0] = 0; ! 110: return(NULL); ! 111: } ! 112: ! 113: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') ! 114: *temp++ = *p++; ! 115: *temp = '\0'; ! 116: ! 117: return(p); ! 118: ! 119: } /* End of getstr */ ! 120: ! 121: ! 122: /*****************************************************************************/ ! 123: ! 124: ! 125: xymove(x, y) ! 126: ! 127: ! 128: int x, y; /* move printer to this point */ ! 129: ! 130: ! 131: { ! 132: ! 133: ! 134: /* ! 135: * ! 136: * Moves the printer's current position to the pixel corresponding to the ! 137: * troff position (x, y). ! 138: * ! 139: */ ! 140: ! 141: ! 142: putc(ASETAH, tf); ! 143: putint(lastx = XSCALE(x), tf); ! 144: putc(ASETAV, tf); ! 145: putint(lasty = YSCALE(y), tf); ! 146: ! 147: } /* End of xymove */ ! 148: ! 149: ! 150: /*****************************************************************************/ ! 151: ! 152: ! 153: drawline(dx, dy) ! 154: ! 155: ! 156: int dx, dy; /* endpoint is (hpos+dx, vpos+dy) */ ! 157: ! 158: ! 159: { ! 160: ! 161: ! 162: /* ! 163: * ! 164: * Draws a line form the current position (hpos, vpos) to the point ! 165: * (hpos+dx, vpos+dy), and leaves the current position at the endpoint. ! 166: * We're assuming here that after the path is drawn Impress sets its current ! 167: * position to the endpoint of the path. If that's not the case call xymove() ! 168: * before returning. ! 169: * ! 170: */ ! 171: ! 172: ! 173: putc(ASETP, tf); /* define the path */ ! 174: putint(2, tf); ! 175: ! 176: putint(XSCALE(hpos), tf); ! 177: putint(YSCALE(vpos), tf); ! 178: putint(XSCALE(hpos + dx), tf); ! 179: putint(YSCALE(vpos + dy), tf); ! 180: ! 181: putc(ADRAWP, tf); /* then draw it */ ! 182: putc(OR_OP, tf); ! 183: ! 184: hgoto(hpos + dx); /* adjust troff's position */ ! 185: vgoto(vpos + dy); ! 186: ! 187: xymove(hpos, vpos); /* think we need it */ ! 188: ! 189: } /* End of drawline */ ! 190: ! 191: ! 192: /*****************************************************************************/ ! 193: ! 194: ! 195: drawcirc(d) ! 196: ! 197: ! 198: int d; /* diameter of the circle */ ! 199: ! 200: ! 201: { ! 202: ! 203: ! 204: /* ! 205: * ! 206: * Draws a circle of diameter d with the left 'side' of the circle at the ! 207: * current point. After we're finished drawing we move the current position ! 208: * to the right side. ! 209: * ! 210: */ ! 211: ! 212: drawellip(d, d); ! 213: ! 214: } /* End of drawcirc */ ! 215: ! 216: ! 217: /*****************************************************************************/ ! 218: ! 219: ! 220: drawellip(a, b) ! 221: ! 222: ! 223: int a, b; /* axes lengths for the ellipse */ ! 224: ! 225: ! 226: { ! 227: ! 228: ! 229: /* ! 230: * ! 231: * Draws an ellipse having axes lengths horizontally and vertically of a and ! 232: * b. The left side of the ellipse is at the current point. After we're done ! 233: * drawing the path we move the current position to the right side. ! 234: * ! 235: */ ! 236: ! 237: ! 238: xymove(hpos + a/2, vpos); ! 239: ! 240: putc(AELLIPSEARC, tf); /* define the ellipse */ ! 241: putint((int) ((a * xfac) / 2 + .5), tf); ! 242: putint((int) ((b * yfac) / 2 + .5), tf); ! 243: putint(0, tf); ! 244: putint(0, tf); ! 245: putint(16383, tf); ! 246: ! 247: putc(ADRAWP, tf); ! 248: putc(OR_OP, tf); ! 249: ! 250: hgoto(hpos + a); /* where troff wants to be */ ! 251: vgoto(vpos); ! 252: ! 253: xymove(hpos, vpos); /* move the printer there too */ ! 254: ! 255: } /* End of drawellip */ ! 256: ! 257: ! 258: /*****************************************************************************/ ! 259: ! 260: ! 261: drawarc(dx1, dy1, dx2, dy2) ! 262: ! 263: ! 264: int dx1, dy1; /* vector from current pos to center */ ! 265: int dx2, dy2; /* from center to end of the arc */ ! 266: ! 267: ! 268: { ! 269: ! 270: ! 271: int angle0; /* to get to first point */ ! 272: int angle1; /* for second point - always negative */ ! 273: int radius; ! 274: ! 275: ! 276: /* ! 277: * ! 278: * Draws a circular arc from the current position (hpos, vpos) to the point ! 279: * (hpos + dx1 + dx2, vpos + dy1 + dy2). The center of the circle is the ! 280: * point (hpos + dx1, vpos + dy1). Arcs always go in the counter-clockwise ! 281: * direction from the starting point to the endpoint. ! 282: * ! 283: * After we're finished troff expects its current position to be the end ! 284: * point of the arc. I've also made sure that Impress has its current ! 285: * position set there too, although it's probably not necessary. ! 286: * ! 287: * Used elliptical arcs in case the aspect ratio is different than 1.0. ! 288: * Things seem to work OK for aspect ratios greater than or equal to ! 289: * 1.0, but there appears to be a bug in the Impress ellipse drawing ! 290: * code that causes problems if radiusa < radiusb. I haven't bothered ! 291: * to try and fix the code since I expect the Impress problem to ! 292: * disappear, and besides apsect ratios different from 1.0 are rarely ! 293: * used. ! 294: * ! 295: */ ! 296: ! 297: ! 298: if ( dx1 == 0 && dy1 == 0 ) /* nothing to do */ ! 299: return; ! 300: ! 301: xymove(hpos + dx1, vpos + dy1); /* center of the circle */ ! 302: ! 303: radius = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + .5; ! 304: angle0 = (atan2((double) -dy1, (double) -dx1) * (1 << 14)) / (2 * PI); ! 305: angle1 = (atan2((double) dy2, (double) dx2) * (1 << 14)) / (2 * PI); ! 306: ! 307: if ( angle0 < angle1 ) ! 308: if ( angle0 < 0 ) angle0 += (1 << 14); ! 309: else angle1 -= (1 << 14); ! 310: ! 311: putc(AELLIPSEARC, tf); /* define the arc */ ! 312: putint((int) (radius * xfac + .5), tf); ! 313: putint((int) (radius * yfac + .5), tf); ! 314: putint(0, tf); ! 315: putint(angle0, tf); ! 316: putint(angle1, tf); ! 317: ! 318: putc(ADRAWP, tf); /* draw the arc */ ! 319: putc(OR_OP, tf); ! 320: ! 321: hgoto(hpos + dx1 + dx2); /* all done so get to the end point */ ! 322: vgoto(vpos + dy1 + dy2); ! 323: ! 324: xymove(hpos, vpos); /* make sure the printer's there too */ ! 325: ! 326: } /* End of drawarc */ ! 327: ! 328: ! 329: /*****************************************************************************/ ! 330: ! 331: ! 332: drawspline(fp, flag) ! 333: FILE *fp; /* input for point list */ ! 334: int flag; /* flag!=1 connect end points */ ! 335: { ! 336: int x[50], y[50], xp, yp, pxp, pyp; ! 337: float t1, t2, t3, w; ! 338: int i, j, numdots, N; ! 339: char temp[50], *p, *getstr(); ! 340: /* ! 341: * ! 342: * I haven't made any real changes to this routine. Efficiency depends ! 343: * on the size of DX and DY. ! 344: * ! 345: */ ! 346: for (N = 2; N < sizeof(x)/sizeof(x[0]); N++) ! 347: if (fscanf(fp, "%d %d", &x[N], &y[N]) != 2) ! 348: break; ! 349: x[0] = x[1] = hpos; ! 350: y[0] = y[1] = vpos; ! 351: for (i = 1; i < N; i++) { ! 352: x[i+1] += x[i]; ! 353: y[i+1] += y[i]; ! 354: } ! 355: x[N] = x[N-1]; ! 356: y[N] = y[N-1]; ! 357: pxp = pyp = -9999; ! 358: for (i = 0; i < N-1; i++) { /* interval */ ! 359: numdots = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2; ! 360: numdots /= DX; ! 361: numdots = MIN(numdots, maxdots); ! 362: for (j = 0; j < numdots; j++) { /* points within */ ! 363: w = (float) j / numdots; ! 364: t1 = 0.5 * w * w; ! 365: w = w - 0.5; ! 366: t2 = 0.75 - w * w; ! 367: w = w - 0.5; ! 368: t3 = 0.5 * w * w; ! 369: xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5; ! 370: yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5; ! 371: if (xp != pxp || yp != pyp) { ! 372: if (flag!=1 || (i!=0 && i!=N-2)) /* pg 3/21/87 */ ! 373: drawline(xp-hpos,yp-vpos); /* jsp 6/15/83 */ ! 374: hgoto(xp); ! 375: vgoto(yp); ! 376: pxp = xp; ! 377: pyp = yp; ! 378: } ! 379: } ! 380: } ! 381: ! 382: } /* End of drawspline */ ! 383: ! 384: ! 385: /*****************************************************************************/ ! 386: ! 387:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.