|
|
1.1 root 1: /* Copyright (c) 1988 AT&T */
2: /* All Rights Reserved */
3:
4: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
5: /* The copyright notice above does not evidence any */
6: /* actual or intended publication of such source code. */
7:
8: /* @(#)picasso:linegen.c 1.0 */
9: #include "picasso.h"
10: #include "y.tab.h"
11:
12: static float *dx = NULL;
13: static float *dy = NULL;
14: static int nxy = 0;
15: static int nxyvec = 0;
16:
17: growxy()
18: {
19: if (nxy++ >= nxyvec - 1) {
20: dx = (float *)grow((char *)dx,"dx",nxyvec += 256,sizeof(float));
21: dy = (float *)grow((char *)dy,"dy",nxyvec,sizeof(float));
22: }
23: }
24:
25: obj *linegen(type)
26: {
27: static double prevdx = HT;
28: static double prevdy = 0;
29: static double prevw = HT10; /* arrow dimensions */
30: static double prevh = HT5;
31: static double prevrad = 0;
32: static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
33: static int ytab[] = { 0, 1, 0, -1 };
34:
35: struct objattr obat;
36: double theta, defx, defy, nx, ny, x0, y0, x1, y1, chop1, chop2;
37: float bbox[4];
38: int i, j, some, head, chop;
39: obj *p, *ppos;
40: Attr *ap;
41: struct symtab *xlist, *ylist;
42:
43: nx = curx;
44: ny = cury;
45: defy = getfval("lineht");
46: defx = getfval("linewid");
47: obat.a_ht = getfval("arrowht");
48: obat.a_wid = getfval("arrowwid");
49: obat.a_rad = getfval("linerad");
50: obat.a_layer = (int)getfval("curlayer");
51: obat.a_flags = EDGED;
52: obat.a_weight = obat.a_lcolor = obat.a_pcolor = obat.a_tcolor = -1;
53: obat.a_dashpat.a = (float *)0;
54: set_text();
55: if (nxyvec == 0)
56: growxy();
57: dx[0] = dy[0] = chop1 = chop2 = 0;
58: nxy = some = head = chop = 0;
59: for (i = 0; i < nattr; i++) {
60: ap = &attr[i];
61: switch (ap->a_type) {
62: default:
63: miscattrs(ap, &obat);
64: break;
65: case HEAD:
66: head += ap->a_val.i;
67: break;
68: case CHOP:
69: if (chop++ == 0)
70: chop1 = chop2 = ap->a_val.f;
71: else
72: chop2 = ap->a_val.f;
73: break;
74: case SAME:
75: dx[nxy] = prevdx;
76: dy[nxy] = prevdy;
77: obat.a_rad = prevrad;
78: obat.a_ht = prevh;
79: obat.a_wid = prevw;
80: some++;
81: break;
82: case LEFT:
83: dx[nxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
84: some++;
85: hvmode = L_DIR;
86: break;
87: case RIGHT:
88: dx[nxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
89: some++;
90: hvmode = R_DIR;
91: break;
92: case UP:
93: dy[nxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
94: some++;
95: hvmode = U_DIR;
96: break;
97: case DOWN:
98: dy[nxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
99: some++;
100: hvmode = D_DIR;
101: break;
102: case XLIST:
103: xlist = findvar(ap->a_val.p, VARNAME);
104: break;
105: case YLIST:
106: ylist = findvar(ap->a_val.p, VARNAME);
107: if (some) {
108: nx += dx[nxy];
109: ny += dy[nxy];
110: growxy();
111: }
112: first_xy(xlist, ylist, &x0, &y0);
113: dx[nxy] = x0 - nx;
114: dy[nxy] = y0 - ny;
115: while (next_xy(xlist, ylist, &x0, &y0)) {
116: nx += dx[nxy];
117: ny += dy[nxy];
118: growxy();
119: dx[nxy] = x0 - nx;
120: dy[nxy] = y0 - ny;
121: }
122: some++;
123: break;
124: case TO:
125: if (some) {
126: nx += dx[nxy];
127: ny += dy[nxy];
128: growxy();
129: }
130: ppos = ap->a_val.o;
131: dx[nxy] = Xformx(ppos, 1, ppos->o_x, ppos->o_y) - nx;
132: dy[nxy] = Xformy(ppos, 0, ppos->o_x, ppos->o_y) - ny;
133: some++;
134: break;
135: case BY:
136: if (some) {
137: nx += dx[nxy];
138: ny += dy[nxy];
139: growxy();
140: }
141: ppos = ap->a_val.o;
142: dx[nxy] = Xformx(ppos, 1, ppos->o_x, ppos->o_y);
143: dy[nxy] = Xformy(ppos, 0, ppos->o_x, ppos->o_y);
144: some++;
145: break;
146: case THEN: /* turn off any previous accumulation */
147: if (some) {
148: nx += dx[nxy];
149: ny += dy[nxy];
150: growxy();
151: dx[nxy] = dy[nxy] = some = 0;
152: }
153: break;
154: case FROM:
155: case AT:
156: ppos = ap->a_val.o;
157: nx = curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y);
158: ny = cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y);
159: break;
160: }
161: }
162: if (some) {
163: nx += dx[nxy];
164: ny += dy[nxy];
165: growxy();
166: defx = dx[nxy-1];
167: defy = dy[nxy-1];
168: } else {
169: defx *= xtab[hvmode];
170: defy *= ytab[hvmode];
171: dx[nxy] = defx;
172: dy[nxy] = defy;
173: growxy();
174: nx += defx;
175: ny += defy;
176: }
177: prevdx = defx;
178: prevdy = defy;
179: prevh = obat.a_ht;
180: prevw = obat.a_wid;
181: prevrad = obat.a_rad;
182: if (chop) {
183: if (chop1 == -1.0) /* just said "chop", so use default */
184: chop1 = getfval("circlerad");
185: if (chop2 == -1.0)
186: chop2 = getfval("circlerad");
187: x0 = dx[0] * dx[0] + dy[0] *dy[0];
188: if (chop1 > sqrt(x0)) {
189: yyerror("can't chop that much");
190: chop1 = x0;
191: }
192: theta = atan2(dy[0], dx[0]);
193: x0 = chop1 * cos(theta);
194: y0 = chop1 * sin(theta);
195: curx += x0;
196: cury += y0;
197: dx[0] -= x0;
198: dy[0] -= y0;
199:
200: x1 = dx[nxy-1] * dx[nxy-1] + dy[nxy-1] *dy[nxy-1];
201: if (chop2 > sqrt(x1)) {
202: yyerror("can't chop that much");
203: chop2 = x1;
204: }
205: theta = atan2(dy[nxy-1], dx[nxy-1]);
206: x1 = chop2 * cos(theta);
207: y1 = chop2 * sin(theta);
208: nx -= x1;
209: ny -= y1;
210: dx[nxy-1] -= x1;
211: dy[nxy-1] -= y1;
212: }
213: /* input file could specify ...to 3,2 to 3,2 ...
214: so eliminate repeated pts */
215: for (i = j = 0; i < nxy; i++) {
216: if (dx[i] == 0. && dy[i] == 0.)
217: continue;
218: else if (j != i) {
219: dx[j] = dx[i];
220: dy[j] = dy[i];
221: }
222: j++;
223: }
224: nxy = j;
225: p = makenode(type, N_VAL + 6 + 2 * nxy, obat.a_layer);
226: primattrs(p, &obat);
227: text_bounds(p);
228: prevrad = p->o_val[N_VAL].f = obat.a_rad;
229: p->o_val[N_VAL+3].f = nxy; /* note: segments, not points */
230: p->o_val[N_VAL+4].f = bbox[0] = bbox[2] = curx;
231: p->o_val[N_VAL+5].f = bbox[1] = bbox[3] = cury;
232:
233: for (i = 0, j = N_VAL+6; i < nxy; i++, j += 2) {
234: /* restoring absolute coordinates */
235: p->o_val[j].f = curx += dx[i];
236: p->o_val[j+1].f = cury += dy[i];
237: extreme(curx, cury, bbox); /* OVERestimate, for splines */
238: #if 0
239: if (type == LINE || type == ARROW)
240: extreme(curx, cury, bbox);
241: else if (type == SPLINE) {
242: if (i < nxy-1) {
243: /* to compute approx extreme of spline at p, */
244: /* compute midway between p-1 and p+1, */
245: /* then go 3/4 from there to p */
246: double ex, ey, xi, yi, xi1, yi1;
247:
248: xi = curx-dx[i];
249: yi = cury-dy[i]; /* p-1 */
250: xi1 = curx+dx[i+1];
251: yi1 = cury+dy[i+1]; /* p+1 */
252: ex = (curx+xi1)/2;
253: ey = (cury+yi1)/2; /* midpt */
254: ex += 0.75*(curx-ex); ey += 0.75*(cury-ey);
255: extreme(ex, ey, bbox);
256: }
257: else extreme(curx, cury, bbox);
258: }
259: #endif
260: }
261: if (head || type == ARROW) {
262: if (head == 0)
263: head = HEAD2; /* default arrow head */
264: p->o_attr |= head | arrowfill();
265: p->o_val[N_VAL+1].f = obat.a_wid;
266: p->o_val[N_VAL+2].f = obat.a_ht;
267: if (head & HEAD1)
268: track_head (p->o_val[N_VAL+6].f, p->o_val[N_VAL+7].f,
269: p->o_val[N_VAL+4].f, p->o_val[N_VAL+5].f,
270: prevw, prevh, bbox);
271: if (head & HEAD2) {
272: j = N_VAL + 2 + 2 * nxy;
273: track_head (p->o_val[j+0].f, p->o_val[j+1].f,
274: p->o_val[j+2].f, p->o_val[j+3].f,
275: prevw, prevh, bbox);
276: }
277: }
278: track_bounds(bbox[0]-p->o_weight/2, bbox[1]-p->o_weight/2,
279: bbox[2]+p->o_weight/2, bbox[3]+p->o_weight/2);
280: p->o_x = 0.5 * (bbox[0] + bbox[2]);
281: p->o_y = 0.5 * (bbox[1] + bbox[3]);
282: p->o_wid = bbox[2] - bbox[0];
283: p->o_ht = bbox[3] - bbox[1];
284: return(p);
285: }
286:
287: arrowfill () /* a bit of a kludge for an obsolescent feature; arroprevw */
288: { /* now is taken simply as odd (fill) or even (nofill) and */
289: /* has no implication of "number of lines drawn" as in pic */
290:
291: return (((int)getfval("arrowfill")) % 2) * HEADFILL;
292: }
293:
294: /* NOTE: DBK added bbox parameter to track_head 9/30/89. Only calls to
295: track_head are in linegen() above. The purpose is to get o_wid and o_ht
296: computed large enough so get_bounds won't lie about arrows. Note that
297: o_x and o_y may also be affected. */
298: static
299: track_head (x0, y0, x1, y1, w, h, bbox)
300: double x0, y0, x1, y1, w, h;
301: float bbox[];
302: {
303: double rot, hyp, phi;
304:
305: rot = atan2(w/2, h);
306: hyp = hypot(w/2, h);
307: phi = atan2(y1-y0, x1-x0) + M_PI - rot;
308: x0 = x1 + hyp * cos(phi); y0 = y1 + hyp * sin(phi);
309: extreme (x0, y0, Gbox);
310: extreme (x0, y0, bbox);
311: phi += 2 * rot;
312: x0 = x1 + hyp * cos(phi); y0 = y1 + hyp * sin(phi);
313: extreme (x0, y0, Gbox);
314: extreme (x0, y0, bbox);
315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.