|
|
1.1 root 1: #include <stdio.h>
2: #include <math.h>
3: #include "pic.h"
4: extern int dbg;
5:
6: #define abs(n) (n >= 0 ? n : -(n))
7: #define max(x,y) ((x)>(y) ? (x) : (y))
8:
9: char *textshift = "\\v'.2m'"; /* move text this far down */
10:
11: /* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
12: /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
13: /* default output is 6x6 inches */
14:
15:
16: double xscale;
17: double yscale;
18:
19: double hpos = 0; /* current horizontal position in output coordinate system */
20: double vpos = 0; /* current vertical position; 0 is top of page */
21:
22: double htrue = 0; /* where we really are */
23: double vtrue = 0;
24:
25: double X0, Y0; /* left bottom of input */
26: double X1, Y1; /* right top of input */
27:
28: double hmax; /* right end of output */
29: double vmax; /* top of output (down is positive) */
30:
31: extern double deltx;
32: extern double delty;
33: extern double xmin, ymin, xmax, ymax;
34:
35: double xconv(double), yconv(double), xsc(double), ysc(double);
36: void space(double, double, double, double);
37: void hgoto(double), vgoto(double), hmot(double), vmot(double);
38: void move(double, double), movehv(double, double);
39: void cont(double, double);
40:
41: void openpl(char *s) /* initialize device; s is residue of .PS invocation line */
42: {
43: double maxw, maxh, ratio = 1;
44: double odeltx = deltx, odelty = delty;
45:
46: hpos = vpos = 0;
47: maxw = getfval("maxpswid");
48: maxh = getfval("maxpsht");
49: if (deltx > maxw) { /* shrink horizontal */
50: ratio = maxw / deltx;
51: deltx *= ratio;
52: delty *= ratio;
53: }
54: if (delty > maxh) { /* shrink vertical */
55: ratio = maxh / delty;
56: deltx *= ratio;
57: delty *= ratio;
58: }
59: if (ratio != 1) {
60: fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty);
61: fprintf(stderr, " %g X %g\n", deltx, delty);
62: }
63: space(xmin, ymin, xmax, ymax);
64: printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
65: printf("... %.3fi %.3fi %.3fi %.3fi\n",
66: xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
67: printf(".nr 00 \\n(.u\n");
68: printf(".nf\n");
69: printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
70: /* assumes \n comes as part of s */
71: }
72:
73: void space(double x0, double y0, double x1, double y1) /* set limits of page */
74: {
75: X0 = x0;
76: Y0 = y0;
77: X1 = x1;
78: Y1 = y1;
79: xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
80: yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
81: }
82:
83: double xconv(double x) /* convert x from external to internal form */
84: {
85: return (x-X0) * xscale;
86: }
87:
88: double xsc(double x) /* convert x from external to internal form, scaling only */
89: {
90:
91: return (x) * xscale;
92: }
93:
94: double yconv(double y) /* convert y from external to internal form */
95: {
96: return (Y1-y) * yscale;
97: }
98:
99: double ysc(double y) /* convert y from external to internal form, scaling only */
100: {
101: return (y) * yscale;
102: }
103:
104: void closepl(int type) /* clean up after finished */
105: {
106: movehv(0.0, 0.0); /* get back to where we started */
107: if (type == 'F')
108: printf(".PF\n");
109: else {
110: printf(".sp 1+%.3fi\n", yconv(ymin));
111: printf(".PE\n");
112: }
113: printf(".if \\n(00 .fi\n");
114: }
115:
116: void move(double x, double y) /* go to position x, y in external coords */
117: {
118: hgoto(xconv(x));
119: vgoto(yconv(y));
120: }
121:
122: void movehv(double h, double v) /* go to internal position h, v */
123: {
124: hgoto(h);
125: vgoto(v);
126: }
127:
128: void hmot(double n) /* generate n units of horizontal motion */
129: {
130: hpos += n;
131: }
132:
133: void vmot(double n) /* generate n units of vertical motion */
134: {
135: vpos += n;
136: }
137:
138: void hgoto(double n)
139: {
140: hpos = n;
141: }
142:
143: void vgoto(double n)
144: {
145: vpos = n;
146: }
147:
148: double fabs(double x)
149: {
150: return x < 0 ? -x : x;
151: }
152:
153: void hvflush(void) /* get to proper point for output */
154: {
155: if (fabs(hpos-htrue) >= 0.0005) {
156: printf("\\h'%.3fi'", hpos - htrue);
157: htrue = hpos;
158: }
159: if (fabs(vpos-vtrue) >= 0.0005) {
160: printf("\\v'%.3fi'", vpos - vtrue);
161: vtrue = vpos;
162: }
163: }
164:
165: void flyback(void) /* return to upper left corner (entry point) */
166: {
167: printf(".sp -1\n");
168: htrue = vtrue = 0;
169: }
170:
171: void printlf(int n, char *f)
172: {
173: if (f)
174: printf(".lf %d %s\n", n, f);
175: else
176: printf(".lf %d\n", n);
177: }
178:
179: void troff(char *s) /* output troff right here */
180: {
181: printf("%s\n", s);
182: }
183:
184: void label(char *s, int t, int nh) /* text s of type t nh half-lines up */
185: {
186: int q;
187: char *p;
188:
189: if (!s)
190: return;
191: hvflush();
192: dprintf("label: %s %o %d\n", s, t, nh);
193: printf("%s", textshift); /* shift down and left */
194: if (t & ABOVE)
195: nh++;
196: else if (t & BELOW)
197: nh--;
198: if (nh)
199: printf("\\v'%du*\\n(.vu/2u'", -nh);
200: /* just in case the text contains a quote: */
201: q = 0;
202: for (p = s; *p; p++)
203: if (*p == '\'') {
204: q = 1;
205: break;
206: }
207: t &= ~(ABOVE|BELOW);
208: if (t & LJUST) {
209: printf("%s", s);
210: } else if (t & RJUST) {
211: if (q)
212: printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
213: else
214: printf("\\h'-\\w'%s'u'%s", s, s);
215: } else { /* CENTER */
216: if (q)
217: printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
218: else
219: printf("\\h'-\\w'%s'u/2u'%s", s, s);
220: }
221: printf("\n");
222: flyback();
223: }
224:
225: void line(double x0, double y0, double x1, double y1) /* draw line from x0,y0 to x1,y1 */
226: {
227: move(x0, y0);
228: cont(x1, y1);
229: }
230:
231: void arrow(double x0, double y0, double x1, double y1, double w, double h,
232: double ang, int nhead) /* draw arrow (without shaft) */
233: {
234: double alpha, rot, drot, hyp;
235: double dx, dy;
236: int i;
237:
238: rot = atan2(w / 2, h);
239: hyp = sqrt(w/2 * w/2 + h * h);
240: alpha = atan2(y1-y0, x1-x0) + ang;
241: if (nhead < 2)
242: nhead = 2;
243: dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
244: for (i = nhead-1; i >= 0; i--) {
245: drot = 2 * rot / (double) (nhead-1) * (double) i;
246: dx = hyp * cos(alpha + PI - rot + drot);
247: dy = hyp * sin(alpha + PI - rot + drot);
248: dprintf("dx,dy = %g,%g\n", dx, dy);
249: line(x1+dx, y1+dy, x1, y1);
250: }
251: }
252:
253: double lastgray = 0;
254:
255: void fillstart(double v) /* this works only for postscript, obviously. */
256: { /* uses drechsler's dpost conventions... */
257: hvflush();
258: printf("\\X'BeginObject %g setgray'\n", v);
259: lastgray = v;
260: flyback();
261: }
262:
263: void fillend(int vis, int fill)
264: {
265: hvflush();
266: printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
267: !vis ? lastgray : 0.0,
268: vis ? "stroke" : "");
269: /* for dashed: [50] 0 setdash just before stroke. */
270: lastgray = 0;
271: flyback();
272: }
273:
274: void box(double x0, double y0, double x1, double y1)
275: {
276: move(x0, y0);
277: cont(x0, y1);
278: cont(x1, y1);
279: cont(x1, y0);
280: cont(x0, y0);
281: }
282:
283: void cont(double x, double y) /* continue line from here to x,y */
284: {
285: double h1, v1;
286: double dh, dv;
287:
288: h1 = xconv(x);
289: v1 = yconv(y);
290: dh = h1 - hpos;
291: dv = v1 - vpos;
292: hvflush();
293: printf("\\D'l%.3fi %.3fi'\n", dh, dv);
294: flyback(); /* expensive */
295: hpos = h1;
296: vpos = v1;
297: }
298:
299: void circle(double x, double y, double r)
300: {
301: move(x-r, y);
302: hvflush();
303: printf("\\D'c%.3fi'\n", xsc(2 * r));
304: flyback();
305: }
306:
307: void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
308: {
309: int i;
310: double dx, dy;
311: double xerr, yerr;
312:
313: move(x, y);
314: hvflush();
315: xerr = yerr = 0.0;
316: printf("\\D'~");
317: for (i = 0; i < 2 * n; i += 2) {
318: dx = xsc(xerr += p[i]);
319: xerr -= dx/xscale;
320: dy = ysc(yerr += p[i+1]);
321: yerr -= dy/yscale;
322: printf(" %.3fi %.3fi", dx, -dy); /* WATCH SIGN */
323: }
324: printf("'\n");
325: flyback();
326: }
327:
328: void ellipse(double x, double y, double r1, double r2)
329: {
330: double ir1, ir2;
331:
332: move(x-r1, y);
333: hvflush();
334: ir1 = xsc(r1);
335: ir2 = ysc(r2);
336: printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
337: flyback();
338: }
339:
340: void arc(double x, double y, double x0, double y0, double x1, double y1) /* draw arc with center x,y */
341: {
342:
343: move(x0, y0);
344: hvflush();
345: printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
346: xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y)); /* WATCH SIGNS */
347: flyback();
348: }
349:
350: void dot(void) {
351: hvflush();
352: /* what character to draw here depends on what's available. */
353: /* on the 202, l. is good but small. */
354: /* in general, use a smaller, shifted period and hope */
355:
356: printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
357: flyback();
358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.