From 3ebbd193dce0724e106ec9af627a3782676ae510 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 3 Apr 2017 23:12:14 -0400 Subject: svgpic: new program to convert pic to svg This is an experiment. Like tpic it's a copy-and-paste fork of pic. Change-Id: Ia22772bd5881c7904a6d8f8e0b46fde8cea89cbd Reviewed-on: https://plan9port-review.googlesource.com/2920 Reviewed-by: Russ Cox --- src/cmd/svgpic/linegen.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 src/cmd/svgpic/linegen.c (limited to 'src/cmd/svgpic/linegen.c') diff --git a/src/cmd/svgpic/linegen.c b/src/cmd/svgpic/linegen.c new file mode 100644 index 00000000..e0db5fc6 --- /dev/null +++ b/src/cmd/svgpic/linegen.c @@ -0,0 +1,239 @@ +#include +#include +#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; + + 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; + } + 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); +} -- cgit v1.2.3