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