Blob


1 #include <stdio.h>
2 #include <math.h>
3 #include "pic.h"
4 #include "y.tab.h"
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;
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;
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;
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;
136 break;
137 case FILL:
138 battr |= FILLBIT;
139 if (ap->a_sub == DEFAULT)
140 fillval = getfval("fillval");
141 else
142 fillval = ap->a_val.f;
143 break;
146 if (with) { /* this doesn't work at all */
147 switch (with) {
148 case CENTER:
149 xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
151 for (i = 0; i < ndxy; i++) {
152 dx[i] -= xwith;
153 dy[i] -= ywith;
155 curx += xwith;
156 cury += ywith;
158 if (some) {
159 nx += dx[ndxy];
160 ny += dy[ndxy];
161 ndxy++;
162 defx = dx[ndxy-1];
163 defy = dy[ndxy-1];
164 } else {
165 defx *= xtab[hvmode];
166 defy *= ytab[hvmode];
167 dx[ndxy] = defx;
168 dy[ndxy] = defy;
169 ndxy++;
170 nx += defx;
171 ny += defy;
173 prevdx = defx;
174 prevdy = defy;
175 if (chop) {
176 if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
177 chop1 = chop2 = getfval("circlerad");
178 theta = atan2(dy[0], dx[0]);
179 x0 = chop1 * cos(theta);
180 y0 = chop1 * sin(theta);
181 curx += x0;
182 cury += y0;
183 dx[0] -= x0;
184 dy[0] -= y0;
186 theta = atan2(dy[ndxy-1], dx[ndxy-1]);
187 x1 = chop2 * cos(theta);
188 y1 = chop2 * sin(theta);
189 nx -= x1;
190 ny -= y1;
191 dx[ndxy-1] -= x1;
192 dy[ndxy-1] -= y1;
193 dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
194 x0, y0, x1, y1, curx, cury, nx, ny);
196 p = makenode(type, 5 + 2 * ndxy);
197 curx = p->o_val[0] = nx;
198 cury = p->o_val[1] = ny;
199 if (head || type == ARROW) {
200 p->o_nhead = getfval("arrowhead");
201 p->o_val[2] = prevw;
202 p->o_val[3] = prevh;
203 if (head == 0)
204 head = HEAD2; /* default arrow head */
206 p->o_attr = head | invis | ddtype | battr;
207 p->o_fillval = fillval;
208 p->o_val[4] = ndxy;
209 nx = p->o_x;
210 ny = p->o_y;
211 for (i = 0, j = 5; i < ndxy; i++, j += 2) {
212 p->o_val[j] = dx[i];
213 p->o_val[j+1] = dy[i];
214 if (type == LINE || type == ARROW)
215 extreme(nx += dx[i], ny += dy[i]);
216 else if (type == SPLINE && i < ndxy-1) {
217 /* to compute approx extreme of spline at p,
218 /* compute midway between p-1 and p+1,
219 /* then go 3/4 from there to p */
220 double ex, ey, xi, yi, xi1, yi1;
221 xi = nx + dx[i]; yi = ny + dy[i]; /* p */
222 xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
223 ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
224 ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
225 extreme(ex, ey);
226 nx = xi; ny = yi;
230 p->o_ddval = ddval;
231 if (dbg) {
232 printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
233 for (i = 0, j = 5; i < ndxy; i++, j += 2)
234 printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
236 extreme(p->o_x, p->o_y);
237 extreme(curx, cury);
238 return(p);