|
|
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.