plan9port

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

linegen.c (4704B)


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