|
|
1.1 root 1: #include <stdio.h>
2: #include <math.h>
3: #include "pic.h"
4: #include "y.tab.h"
5:
6: obj *linegen(int type)
7: {
8: static double prevdx = HT;
9: static double prevdy = 0;
10: static double prevw = HT10;
11: static double prevh = HT5;
12: int i, j, some, head, ddtype, invis, chop, battr, with;
13: double ddval, chop1, chop2, x0, y0, x1, y1;
14: double fillval = 0;
15: double theta;
16: double defx, defy, xwith, ywith;
17: obj *p, *ppos;
18: static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
19: static int ytab[] = { 0, 1, 0, -1 };
20: double dx[500], dy[500];
21: int ndxy;
22: double nx, ny;
23: Attr *ap, *chop_ap[4];
24:
25: nx = curx;
26: ny = cury;
27: defx = getfval("linewid");
28: defy = getfval("lineht");
29: prevh = getfval("arrowht");
30: prevw = getfval("arrowwid");
31: dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0;
32: chop = chop1 = chop2 = 0;
33: ddtype = ddval = xwith = ywith = 0;
34: for (i = 0; i < nattr; i++) {
35: ap = &attr[i];
36: switch (ap->a_type) {
37: case TEXTATTR:
38: savetext(ap->a_sub, ap->a_val.p);
39: break;
40: case HEAD:
41: head += ap->a_val.i;
42: break;
43: case INVIS:
44: invis = INVIS;
45: break;
46: case NOEDGE:
47: battr |= NOEDGEBIT;
48: break;
49: case DOT:
50: case DASH:
51: ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
52: if (ap->a_sub == DEFAULT)
53: ddval = getfval("dashwid");
54: else
55: ddval = ap->a_val.f;
56: break;
57: case SAME:
58: dx[ndxy] = prevdx;
59: dy[ndxy] = prevdy;
60: some++;
61: break;
62: case LEFT:
63: dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
64: some++;
65: hvmode = L_DIR;
66: break;
67: case RIGHT:
68: dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
69: some++;
70: hvmode = R_DIR;
71: break;
72: case UP:
73: dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
74: some++;
75: hvmode = U_DIR;
76: break;
77: case DOWN:
78: dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
79: some++;
80: hvmode = D_DIR;
81: break;
82: case HEIGHT: /* length of arrowhead */
83: prevh = ap->a_val.f;
84: break;
85: case WIDTH: /* width of arrowhead */
86: prevw = ap->a_val.f;
87: break;
88: case TO:
89: if (some) {
90: nx += dx[ndxy];
91: ny += dy[ndxy];
92: ndxy++;
93: dx[ndxy] = dy[ndxy] = some = 0;
94: }
95: ppos = attr[i].a_val.o;
96: dx[ndxy] = ppos->o_x - nx;
97: dy[ndxy] = ppos->o_y - ny;
98: some++;
99: break;
100: case BY:
101: if (some) {
102: nx += dx[ndxy];
103: ny += dy[ndxy];
104: ndxy++;
105: dx[ndxy] = dy[ndxy] = some = 0;
106: }
107: ppos = ap->a_val.o;
108: dx[ndxy] = ppos->o_x;
109: dy[ndxy] = ppos->o_y;
110: some++;
111: break;
112: case THEN: /* turn off any previous accumulation */
113: if (some) {
114: nx += dx[ndxy];
115: ny += dy[ndxy];
116: ndxy++;
117: dx[ndxy] = dy[ndxy] = some = 0;
118: }
119: break;
120: case FROM:
121: case AT:
122: ppos = ap->a_val.o;
123: nx = curx = ppos->o_x;
124: ny = cury = ppos->o_y;
125: break;
126: case WITH:
127: with = ap->a_val.i;
128: break;
129: case CHOP:
130: if (ap->a_sub != PLACENAME) {
131: if( chop == 0)
132: chop1 = chop2 = ap->a_val.f;
133: else
134: chop2 = ap->a_val.f;
135: }
136: chop_ap[chop++] = ap;
137: break;
138: case FILL:
139: battr |= FILLBIT;
140: if (ap->a_sub == DEFAULT)
141: fillval = getfval("fillval");
142: else
143: fillval = ap->a_val.f;
144: break;
145: }
146: }
147: if (with) { /* this doesn't work at all */
148: switch (with) {
149: case CENTER:
150: xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
151: }
152: for (i = 0; i < ndxy; i++) {
153: dx[i] -= xwith;
154: dy[i] -= ywith;
155: }
156: curx += xwith;
157: cury += ywith;
158: }
159: if (some) {
160: nx += dx[ndxy];
161: ny += dy[ndxy];
162: ndxy++;
163: defx = dx[ndxy-1];
164: defy = dy[ndxy-1];
165: } else {
166: defx *= xtab[hvmode];
167: defy *= ytab[hvmode];
168: dx[ndxy] = defx;
169: dy[ndxy] = defy;
170: ndxy++;
171: nx += defx;
172: ny += defy;
173: }
174: prevdx = defx;
175: prevdy = defy;
176: if (chop) {
177: if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
178: chop1 = chop2 = getfval("circlerad");
179: theta = atan2(dy[0], dx[0]);
180: x0 = chop1 * cos(theta);
181: y0 = chop1 * sin(theta);
182: curx += x0;
183: cury += y0;
184: dx[0] -= x0;
185: dy[0] -= y0;
186:
187: theta = atan2(dy[ndxy-1], dx[ndxy-1]);
188: x1 = chop2 * cos(theta);
189: y1 = chop2 * sin(theta);
190: nx -= x1;
191: ny -= y1;
192: dx[ndxy-1] -= x1;
193: dy[ndxy-1] -= y1;
194: dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
195: x0, y0, x1, y1, curx, cury, nx, ny);
196: }
197: p = makenode(type, 5 + 2 * ndxy);
198: curx = p->o_val[0] = nx;
199: cury = p->o_val[1] = ny;
200: if (head || type == ARROW) {
201: p->o_nhead = getfval("arrowhead");
202: p->o_val[2] = prevw;
203: p->o_val[3] = prevh;
204: if (head == 0)
205: head = HEAD2; /* default arrow head */
206: }
207: p->o_attr = head | invis | ddtype | battr;
208: p->o_fillval = fillval;
209: p->o_val[4] = ndxy;
210: nx = p->o_x;
211: ny = p->o_y;
212: for (i = 0, j = 5; i < ndxy; i++, j += 2) {
213: p->o_val[j] = dx[i];
214: p->o_val[j+1] = dy[i];
215: if (type == LINE || type == ARROW)
216: extreme(nx += dx[i], ny += dy[i]);
217: else if (type == SPLINE && i < ndxy-1) {
218: /* to compute approx extreme of spline at p,
219: /* compute midway between p-1 and p+1,
220: /* then go 3/4 from there to p */
221: double ex, ey, xi, yi, xi1, yi1;
222: xi = nx + dx[i]; yi = ny + dy[i]; /* p */
223: xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
224: ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
225: ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
226: extreme(ex, ey);
227: nx = xi; ny = yi;
228: }
229:
230: }
231: p->o_ddval = ddval;
232: if (dbg) {
233: printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
234: for (i = 0, j = 5; i < ndxy; i++, j += 2)
235: printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
236: }
237: extreme(p->o_x, p->o_y);
238: extreme(curx, cury);
239: return(p);
240: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.