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/misc.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 src/cmd/svgpic/misc.c (limited to 'src/cmd/svgpic/misc.c') diff --git a/src/cmd/svgpic/misc.c b/src/cmd/svgpic/misc.c new file mode 100644 index 00000000..e888fafc --- /dev/null +++ b/src/cmd/svgpic/misc.c @@ -0,0 +1,441 @@ +#include +#include +#include +#include +#include "pic.h" +#include "y.tab.h" + +int whatpos(obj *p, int corner, double *px, double *py); +void makeattr(int type, int sub, YYSTYPE val); +YYSTYPE getblk(obj *, char *); + +int +setdir(int n) /* set direction (hvmode) from LEFT, RIGHT, etc. */ +{ + switch (n) { + case UP: hvmode = U_DIR; break; + case DOWN: hvmode = D_DIR; break; + case LEFT: hvmode = L_DIR; break; + case RIGHT: hvmode = R_DIR; break; + } + return(hvmode); +} + +int +curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */ +{ + switch (hvmode) { + case R_DIR: return RIGHT; + case L_DIR: return LEFT; + case U_DIR: return UP; + case D_DIR: return DOWN; + } + ERROR "can't happen curdir" FATAL; + return 0; +} + +double +getcomp(obj *p, int t) /* return component of a position */ +{ + switch (t) { + case DOTX: + return p->o_x; + case DOTY: + return p->o_y; + case DOTWID: + switch (p->o_type) { + case BOX: + case BLOCK: + case TEXT: + return p->o_val[0]; + case CIRCLE: + case ELLIPSE: + return 2 * p->o_val[0]; + case LINE: + case ARROW: + return p->o_val[0] - p->o_x; + case PLACE: + return 0; + } + case DOTHT: + switch (p->o_type) { + case BOX: + case BLOCK: + case TEXT: + return p->o_val[1]; + case CIRCLE: + case ELLIPSE: + return 2 * p->o_val[1]; + case LINE: + case ARROW: + return p->o_val[1] - p->o_y; + case PLACE: + return 0; + } + case DOTRAD: + switch (p->o_type) { + case CIRCLE: + case ELLIPSE: + return p->o_val[0]; + } + } + ERROR "you asked for a weird dimension or position" WARNING; + return 0; +} + +double exprlist[100]; +int nexpr = 0; + +void exprsave(double f) +{ + exprlist[nexpr++] = f; +} + +char *sprintgen(char *fmt) +{ + char buf[1000]; + + sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]); + nexpr = 0; + free(fmt); + return tostring(buf); +} + +void makefattr(int type, int sub, double f) /* double attr */ +{ + YYSTYPE val; + val.f = f; + makeattr(type, sub, val); +} + +void makeoattr(int type, obj *o) /* obj* attr */ +{ + YYSTYPE val; + val.o = o; + makeattr(type, 0, val); +} + +void makeiattr(int type, int i) /* int attr */ +{ + YYSTYPE val; + val.i = i; + makeattr(type, 0, val); +} + +void maketattr(int sub, char *p) /* text attribute: takes two */ +{ + YYSTYPE val; + val.p = p; + makeattr(TEXTATTR, sub, val); +} + +void addtattr(int sub) /* add text attrib to existing item */ +{ + attr[nattr-1].a_sub |= sub; +} + +void makevattr(char *p) /* varname attribute */ +{ + YYSTYPE val; + val.p = p; + makeattr(VARNAME, 0, val); +} + +void makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */ +{ + if (type == 0 && val.i == 0) { /* clear table for next stat */ + nattr = 0; + return; + } + if (nattr >= nattrlist) + attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr)); + dprintf("attr %d: %d %d %d\n", nattr, type, sub, val.i); + attr[nattr].a_type = type; + attr[nattr].a_sub = sub; + attr[nattr].a_val = val; + nattr++; +} + +void printexpr(double f) /* print expression for debugging */ +{ + printf("%g\n", f); +} + +void printpos(obj *p) /* print position for debugging */ +{ + printf("%g, %g\n", p->o_x, p->o_y); +} + +char *tostring(char *s) +{ + register char *p; + + p = malloc(strlen(s)+1); + if (p == NULL) + ERROR "out of space in tostring on %s", s FATAL; + strcpy(p, s); + return(p); +} + +obj *makepos(double x, double y) /* make a position cell */ +{ + obj *p; + + p = makenode(PLACE, 0); + p->o_x = x; + p->o_y = y; + return(p); +} + +obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */ +{ + obj *p; + + dprintf("fraction = %.2f\n", f); + p = makenode(PLACE, 0); + p->o_x = p1->o_x + f * (p2->o_x - p1->o_x); + p->o_y = p1->o_y + f * (p2->o_y - p1->o_y); + return(p); +} + +obj *getpos(obj *p, int corner) /* find position of point */ +{ + double x, y; + + whatpos(p, corner, &x, &y); + return makepos(x, y); +} + +int whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */ +{ + double x, y, x1, y1; + + x1 = y1 = 0.0; /* Botch? (gcc) */ + + dprintf("whatpos %p %d %d\n", (void*)p, p->o_type, corner); + x = p->o_x; + y = p->o_y; + if (p->o_type != PLACE && p->o_type != MOVE) { + x1 = p->o_val[0]; + y1 = p->o_val[1]; + } + switch (p->o_type) { + case PLACE: + break; + case BOX: + case BLOCK: + case TEXT: + switch (corner) { + case NORTH: y += y1 / 2; break; + case SOUTH: y -= y1 / 2; break; + case EAST: x += x1 / 2; break; + case WEST: x -= x1 / 2; break; + case NE: x += x1 / 2; y += y1 / 2; break; + case SW: x -= x1 / 2; y -= y1 / 2; break; + case SE: x += x1 / 2; y -= y1 / 2; break; + case NW: x -= x1 / 2; y += y1 / 2; break; + case START: + if (p->o_type == BLOCK) + return whatpos(objlist[(int)p->o_val[2]], START, px, py); + case END: + if (p->o_type == BLOCK) + return whatpos(objlist[(int)p->o_val[3]], END, px, py); + } + break; + case ARC: + switch (corner) { + case START: + if (p->o_attr & CW_ARC) { + x = p->o_val[2]; y = p->o_val[3]; + } else { + x = x1; y = y1; + } + break; + case END: + if (p->o_attr & CW_ARC) { + x = x1; y = y1; + } else { + x = p->o_val[2]; y = p->o_val[3]; + } + break; + } + if (corner == START || corner == END) + break; + x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y)); + /* Fall Through! */ + case CIRCLE: + case ELLIPSE: + switch (corner) { + case NORTH: y += y1; break; + case SOUTH: y -= y1; break; + case EAST: x += x1; break; + case WEST: x -= x1; break; + case NE: x += 0.707 * x1; y += 0.707 * y1; break; + case SE: x += 0.707 * x1; y -= 0.707 * y1; break; + case NW: x -= 0.707 * x1; y += 0.707 * y1; break; + case SW: x -= 0.707 * x1; y -= 0.707 * y1; break; + } + break; + case LINE: + case SPLINE: + case ARROW: + switch (corner) { + case START: break; /* already in place */ + case END: x = x1; y = y1; break; + default: /* change! */ + case CENTER: x = (x+x1)/2; y = (y+y1)/2; break; + case NORTH: if (y1 > y) { x = x1; y = y1; } break; + case SOUTH: if (y1 < y) { x = x1; y = y1; } break; + case EAST: if (x1 > x) { x = x1; y = y1; } break; + case WEST: if (x1 < x) { x = x1; y = y1; } break; + } + break; + case MOVE: + /* really ought to be same as line... */ + break; + } + dprintf("whatpos returns %g %g\n", x, y); + *px = x; + *py = y; + return 1; +} + +obj *gethere(void) /* make a place for curx,cury */ +{ + dprintf("gethere %g %g\n", curx, cury); + return(makepos(curx, cury)); +} + +obj *getlast(int n, int t) /* find n-th previous occurrence of type t */ +{ + int i, k; + obj *p; + + k = n; + for (i = nobj-1; i >= 0; i--) { + p = objlist[i]; + if (p->o_type == BLOCKEND) { + i = p->o_val[4]; + continue; + } + if (p->o_type != t) + continue; + if (--k > 0) + continue; /* not there yet */ + dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y); + return(p); + } + ERROR "there is no %dth last", n WARNING; + return(NULL); +} + +obj *getfirst(int n, int t) /* find n-th occurrence of type t */ +{ + int i, k; + obj *p; + + k = n; + for (i = 0; i < nobj; i++) { + p = objlist[i]; + if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */ + i = p->o_val[5] + 1; + continue; + } + if (p->o_type != t) + continue; + if (--k > 0) + continue; /* not there yet */ + dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y); + return(p); + } + ERROR "there is no %dth ", n WARNING; + return(NULL); +} + +double getblkvar(obj *p, char *s) /* find variable s2 in block p */ +{ + YYSTYPE y; + + y = getblk(p, s); + return y.f; +} + +obj *getblock(obj *p, char *s) /* find variable s in block p */ +{ + YYSTYPE y; + + y = getblk(p, s); + return y.o; +} + +YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */ +{ + static YYSTYPE bug; + struct symtab *stp; + + if (p->o_type != BLOCK) { + ERROR ".%s is not in that block", s WARNING; + return(bug); + } + for (stp = p->o_symtab; stp != NULL; stp = stp->s_next) + if (strcmp(s, stp->s_name) == 0) { + dprintf("getblk %s found x,y= %g,%g\n", + s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y); + return(stp->s_val); + } + ERROR "there is no .%s in that []", s WARNING; + return(bug); +} + +obj *fixpos(obj *p, double x, double y) +{ + dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y); + return makepos(p->o_x + x, p->o_y + y); +} + +obj *addpos(obj *p, obj *q) +{ + dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y); + return makepos(p->o_x+q->o_x, p->o_y+q->o_y); +} + +obj *subpos(obj *p, obj *q) +{ + dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y); + return makepos(p->o_x-q->o_x, p->o_y-q->o_y); +} + +obj *makenode(int type, int n) +{ + obj *p; + + p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat)); + if (p == NULL) + ERROR "out of space in makenode" FATAL; + p->o_type = type; + p->o_count = n; + p->o_nobj = nobj; + p->o_mode = hvmode; + p->o_x = curx; + p->o_y = cury; + p->o_nt1 = ntext1; + p->o_nt2 = ntext; + ntext1 = ntext; /* ready for next caller */ + if (nobj >= nobjlist) + objlist = (obj **) grow((char *) objlist, "objlist", + nobjlist *= 2, sizeof(obj *)); + objlist[nobj++] = p; + return(p); +} + +void extreme(double x, double y) /* record max and min x and y values */ +{ + if (x > xmax) + xmax = x; + if (y > ymax) + ymax = y; + if (x < xmin) + xmin = x; + if (y < ymin) + ymin = y; +} -- cgit v1.2.3