plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

linegen.c (5351B)


      1 #include <stdio.h>
      2 #include <math.h>
      3 #include "pic.h"
      4 #include "y.tab.h"
      5 
      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;
     24 
     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;
    106 			}
    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;
    118 			}
    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;
    135 			}
    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;
    144 		}
    145 	}
    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;
    150 		}
    151 		for (i = 0; i < ndxy; i++) {
    152 			dx[i] -= xwith;
    153 			dy[i] -= ywith;
    154 		}
    155 		curx += xwith;
    156 		cury += ywith;
    157 	}
    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;
    172 	}
    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;
    185 
    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);
    195 	}
    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 */
    205 	}
    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;
    227 		}
    228 
    229 	}
    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]);
    235 	}
    236 	extreme(p->o_x, p->o_y);
    237 	extreme(curx, cury);
    238 	return(p);
    239 }