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 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