|  | #include <stdio.h> | 
|  | #include <math.h> | 
|  | #include "pic.h" | 
|  | #include "y.tab.h" | 
|  |  | 
|  | obj *linegen(int type) | 
|  | { | 
|  | static double prevdx = HT; | 
|  | static double prevdy = 0; | 
|  | static double prevw = HT10; | 
|  | static double prevh = HT5; | 
|  | int i, j, some, head, ddtype, invis, chop, battr, with; | 
|  | double ddval, chop1, chop2, x0, y0, x1, y1; | 
|  | double fillval = 0; | 
|  | double theta; | 
|  | double defx, defy, xwith, ywith; | 
|  | obj *p, *ppos; | 
|  | static int xtab[] = { 1, 0, -1, 0 };	/* R=0, U=1, L=2, D=3 */ | 
|  | static int ytab[] = { 0, 1, 0, -1 }; | 
|  | double dx[500], dy[500]; | 
|  | int ndxy; | 
|  | double nx, ny; | 
|  | Attr *ap, *chop_ap[4]; | 
|  |  | 
|  | nx = curx; | 
|  | ny = cury; | 
|  | defx = getfval("linewid"); | 
|  | defy = getfval("lineht"); | 
|  | prevh = getfval("arrowht"); | 
|  | prevw = getfval("arrowwid"); | 
|  | dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0; | 
|  | chop = chop1 = chop2 = 0; | 
|  | ddtype = ddval = xwith = ywith = 0; | 
|  | for (i = 0; i < nattr; i++) { | 
|  | ap = &attr[i]; | 
|  | switch (ap->a_type) { | 
|  | case TEXTATTR: | 
|  | savetext(ap->a_sub, ap->a_val.p); | 
|  | break; | 
|  | case HEAD: | 
|  | head += ap->a_val.i; | 
|  | break; | 
|  | case INVIS: | 
|  | invis = INVIS; | 
|  | break; | 
|  | case NOEDGE: | 
|  | battr |= NOEDGEBIT; | 
|  | break; | 
|  | case DOT: | 
|  | case DASH: | 
|  | ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; | 
|  | if (ap->a_sub == DEFAULT) | 
|  | ddval = getfval("dashwid"); | 
|  | else | 
|  | ddval = ap->a_val.f; | 
|  | break; | 
|  | case SAME: | 
|  | dx[ndxy] = prevdx; | 
|  | dy[ndxy] = prevdy; | 
|  | some++; | 
|  | break; | 
|  | case LEFT: | 
|  | dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; | 
|  | some++; | 
|  | hvmode = L_DIR; | 
|  | break; | 
|  | case RIGHT: | 
|  | dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; | 
|  | some++; | 
|  | hvmode = R_DIR; | 
|  | break; | 
|  | case UP: | 
|  | dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; | 
|  | some++; | 
|  | hvmode = U_DIR; | 
|  | break; | 
|  | case DOWN: | 
|  | dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; | 
|  | some++; | 
|  | hvmode = D_DIR; | 
|  | break; | 
|  | case HEIGHT:	/* length of arrowhead */ | 
|  | prevh = ap->a_val.f; | 
|  | break; | 
|  | case WIDTH:	/* width of arrowhead */ | 
|  | prevw = ap->a_val.f; | 
|  | break; | 
|  | case TO: | 
|  | if (some) { | 
|  | nx += dx[ndxy]; | 
|  | ny += dy[ndxy]; | 
|  | ndxy++; | 
|  | dx[ndxy] = dy[ndxy] = some = 0; | 
|  | } | 
|  | ppos = attr[i].a_val.o; | 
|  | dx[ndxy] = ppos->o_x - nx; | 
|  | dy[ndxy] = ppos->o_y - ny; | 
|  | some++; | 
|  | break; | 
|  | case BY: | 
|  | if (some) { | 
|  | nx += dx[ndxy]; | 
|  | ny += dy[ndxy]; | 
|  | ndxy++; | 
|  | dx[ndxy] = dy[ndxy] = some = 0; | 
|  | } | 
|  | ppos = ap->a_val.o; | 
|  | dx[ndxy] = ppos->o_x; | 
|  | dy[ndxy] = ppos->o_y; | 
|  | some++; | 
|  | break; | 
|  | case THEN:	/* turn off any previous accumulation */ | 
|  | if (some) { | 
|  | nx += dx[ndxy]; | 
|  | ny += dy[ndxy]; | 
|  | ndxy++; | 
|  | dx[ndxy] = dy[ndxy] = some = 0; | 
|  | } | 
|  | break; | 
|  | case FROM: | 
|  | case AT: | 
|  | ppos = ap->a_val.o; | 
|  | nx = curx = ppos->o_x; | 
|  | ny = cury = ppos->o_y; | 
|  | break; | 
|  | case WITH: | 
|  | with = ap->a_val.i; | 
|  | break; | 
|  | case CHOP: | 
|  | if (ap->a_sub != PLACENAME) { | 
|  | if( chop == 0) | 
|  | chop1 = chop2 = ap->a_val.f; | 
|  | else | 
|  | chop2 = ap->a_val.f; | 
|  | } | 
|  | chop_ap[chop++] = ap; | 
|  | break; | 
|  | case FILL: | 
|  | battr |= FILLBIT; | 
|  | if (ap->a_sub == DEFAULT) | 
|  | fillval = getfval("fillval"); | 
|  | else | 
|  | fillval = ap->a_val.f; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (with) {	/* this doesn't work at all */ | 
|  | switch (with) { | 
|  | case CENTER: | 
|  | xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break; | 
|  | } | 
|  | for (i = 0; i < ndxy; i++) { | 
|  | dx[i] -= xwith; | 
|  | dy[i] -= ywith; | 
|  | } | 
|  | curx += xwith; | 
|  | cury += ywith; | 
|  | } | 
|  | if (some) { | 
|  | nx += dx[ndxy]; | 
|  | ny += dy[ndxy]; | 
|  | ndxy++; | 
|  | defx = dx[ndxy-1]; | 
|  | defy = dy[ndxy-1]; | 
|  | } else { | 
|  | defx *= xtab[hvmode]; | 
|  | defy *= ytab[hvmode]; | 
|  | dx[ndxy] = defx; | 
|  | dy[ndxy] = defy; | 
|  | ndxy++; | 
|  | nx += defx; | 
|  | ny += defy; | 
|  | } | 
|  | prevdx = defx; | 
|  | prevdy = defy; | 
|  | if (chop) { | 
|  | if (chop == 1 && chop1 == 0)	/* just said "chop", so use default */ | 
|  | chop1 = chop2 = getfval("circlerad"); | 
|  | theta = atan2(dy[0], dx[0]); | 
|  | x0 = chop1 * cos(theta); | 
|  | y0 = chop1 * sin(theta); | 
|  | curx += x0; | 
|  | cury += y0; | 
|  | dx[0] -= x0; | 
|  | dy[0] -= y0; | 
|  |  | 
|  | theta = atan2(dy[ndxy-1], dx[ndxy-1]); | 
|  | x1 = chop2 * cos(theta); | 
|  | y1 = chop2 * sin(theta); | 
|  | nx -= x1; | 
|  | ny -= y1; | 
|  | dx[ndxy-1] -= x1; | 
|  | dy[ndxy-1] -= y1; | 
|  | dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n", | 
|  | x0, y0, x1, y1, curx, cury, nx, ny); | 
|  | } | 
|  | p = makenode(type, 5 + 2 * ndxy); | 
|  | curx = p->o_val[0] = nx; | 
|  | cury = p->o_val[1] = ny; | 
|  | if (head || type == ARROW) { | 
|  | p->o_nhead = getfval("arrowhead"); | 
|  | p->o_val[2] = prevw; | 
|  | p->o_val[3] = prevh; | 
|  | if (head == 0) | 
|  | head = HEAD2;	/* default arrow head */ | 
|  | } | 
|  | p->o_attr = head | invis | ddtype | battr; | 
|  | p->o_fillval = fillval; | 
|  | p->o_val[4] = ndxy; | 
|  | nx = p->o_x; | 
|  | ny = p->o_y; | 
|  | for (i = 0, j = 5; i < ndxy; i++, j += 2) { | 
|  | p->o_val[j] = dx[i]; | 
|  | p->o_val[j+1] = dy[i]; | 
|  | if (type == LINE || type == ARROW) | 
|  | extreme(nx += dx[i], ny += dy[i]); | 
|  | else if (type == SPLINE && i < ndxy-1) { | 
|  | /* to compute approx extreme of spline at p, | 
|  | /* compute midway between p-1 and p+1, | 
|  | /* then go 3/4 from there to p */ | 
|  | double ex, ey, xi, yi, xi1, yi1; | 
|  | xi = nx + dx[i]; yi = ny + dy[i];	/* p */ | 
|  | xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1];	/* p+1 */ | 
|  | ex = (nx+xi1)/2; ey = (ny+yi1)/2;	/* midway */ | 
|  | ex += 0.75*(xi-ex); ey += 0.75*(yi-ey); | 
|  | extreme(ex, ey); | 
|  | nx = xi; ny = yi; | 
|  | } | 
|  |  | 
|  | } | 
|  | p->o_ddval = ddval; | 
|  | if (dbg) { | 
|  | printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); | 
|  | for (i = 0, j = 5; i < ndxy; i++, j += 2) | 
|  | printf("%g %g\n", p->o_val[j], p->o_val[j+1]); | 
|  | } | 
|  | extreme(p->o_x, p->o_y); | 
|  | extreme(curx, cury); | 
|  | return(p); | 
|  | } |