obj* blockgen(obj *p, obj *q) /* handles [...] */ { int i, invis, at, with; double ddval, h, w, xwith, ywith; double x0, y0, x1, y1, cx, cy; obj *ppos; Attr *ap; invis = at = 0; with = xwith = ywith = 0; ddval = 0; w = p->o_val[2] - p->o_val[0]; h = p->o_val[3] - p->o_val[1]; cx = (p->o_val[2] + p->o_val[0]) / 2; /* geom ctr of [] wrt local orogin */ cy = (p->o_val[3] + p->o_val[1]) / 2; dprintf("cx,cy=%g,%g\n", cx, cy); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; break; case WIDTH: w = ap->a_val.f; break; case WITH: with = ap->a_val.i; /* corner */ break; case PLACE: /* actually with position ... */ ppos = ap->a_val.o; xwith = cx - ppos->o_x; ywith = cy - ppos->o_y; with = PLACE; break; case AT: case FROM: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: invis = INVIS; break; case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; } } if (with) { switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); p->o_x = curx; p->o_y = cury; p->o_nt1 = ntext1; p->o_nt2 = ntext; ntext1 = ntext; p->o_val[0] = w; p->o_val[1] = h; p->o_val[2] = cx; p->o_val[3] = cy; p->o_val[5] = q->o_nobj - 1; /* last item in [...] */ p->o_ddval = ddval; p->o_attr = invis; dprintf("[] %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; for (i = 0; i <= 5; i++) q->o_val[i] = p->o_val[i]; stack[nstack+1].p_symtab = NULL; /* so won't be found again */ blockadj(p); /* fix up coords for enclosed blocks */ return(p); }
obj *circgen(type) { static float rad[2] = { HT2, WID2 }; static float rad2[2] = { HT2, HT2 }; static float x0, y0, x1, y1, x2, y2; int i, at, t, invis, ddtype, with; float xwith, ywith; float r, r2, ddval; obj *p, *ppos; Attr *ap; at = invis = ddtype = 0; with = xwith = ywith = 0; t = (type == CIRCLE) ? 0 : 1; if (type == CIRCLE) r = r2 = getfval("circlerad"); else if (type == ELLIPSE) { r = getfval("ellipsewid") / 2; r2 = getfval("ellipseht") / 2; } 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 RADIUS: r = ap->a_val.f; break; case DIAMETER: case WIDTH: r = ap->a_val.f / 2; break; case HEIGHT: r2 = ap->a_val.f / 2; break; case SAME: r = rad[t]; r2 = rad2[t]; break; case WITH: with = ap->a_val.i; break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: invis = INVIS; 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; } } if (type == CIRCLE) r2 = r; /* probably superfluous */ if (with) { switch (with) { case NORTH: ywith = -r2; break; case SOUTH: ywith = r2; break; case EAST: xwith = -r; break; case WEST: xwith = r; break; case NE: xwith = -r * 0.707; ywith = -r2 * 0.707; break; case SE: xwith = -r * 0.707; ywith = r2 * 0.707; break; case NW: xwith = r * 0.707; ywith = -r2 * 0.707; break; case SW: xwith = r * 0.707; ywith = r2 * 0.707; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; } p = makenode(type, 2); p->o_val[0] = rad[t] = r; p->o_val[1] = rad2[t] = r2; if (r <= 0 || r2 <= 0) { yyerror("%s has invalid radius %g\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2); } p->o_attr = invis | ddtype; extreme(curx+r, cury+r2); extreme(curx-r, cury-r2); if (type == CIRCLE) dprintf("C %g %g %g\n", curx, cury, r); if (type == ELLIPSE) dprintf("E %g %g %g %g\n", curx, cury, r, r2); if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; return(p); }
obj *textgen(void) { int i, sub, nstr, at, with, hset, invis; double xwith, ywith, h, w, x0, y0, x1, y1; obj *p, *ppos; Attr *ap; at = with = nstr = hset = invis = 0; h = getfval("textht"); w = getfval("textwid"); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; hset++; break; case WIDTH: w = ap->a_val.f; break; case WITH: with = ap->a_val.i; break; case INVIS: invis = INVIS; break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case TEXTATTR: sub = ap->a_sub; if (ap->a_val.p == NULL) /* an isolated modifier */ text[ntext-1].t_type = sub; else { savetext(sub, ap->a_val.p); nstr++; } break; } } if (hset == 0) /* no explicit ht cmd */ h *= nstr; if (with) { xwith = ywith = 0.0; switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); dprintf("Text h %g w %g at %g,%g\n", h, w, curx, cury); p = makenode(TEXT, 2); p->o_attr = invis; p->o_val[0] = w; p->o_val[1] = h; if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; return(p); }
print() { obj *p; int i, j, k, m; float x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy; for (i = 0; i < nobj; i++) { p = objlist[i]; ox = p->o_x; oy = p->o_y; if (p->o_count >= 1) x1 = p->o_val[0]; if (p->o_count >= 2) y1 = p->o_val[1]; m = p->o_mode; switch (p->o_type) { case TROFF: troff(text[p->o_nt1].t_val); break; case BOX: case BLOCK: move(ox, oy); dotext(p); /* if there are any text strings */ x0 = ox - x1 / 2; y0 = oy - y1 / 2; x1 = ox + x1 / 2; y1 = oy + y1 / 2; if (p->o_attr & INVIS || p->o_type == BLOCK) ; /* nothing at all */ else if (p->o_attr & (DOTBIT|DASHBIT)) dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval); else box(x0, y0, x1, y1); if (ishor(m)) move(isright(m) ? x1 : x0, oy); /* right side */ else move(ox, isdown(m) ? y0 : y1); /* bottom */ break; case BLOCKEND: break; case CIRCLE: move(ox, oy); dotext(p); if ((p->o_attr & INVIS) == 0) circle(ox, oy, x1); if (ishor(m)) move(ox + isright(m) ? x1 : -x1, oy); else move(ox, oy + isup(m) ? x1 : -x1); break; case ELLIPSE: move(ox, oy); dotext(p); if ((p->o_attr & INVIS) == 0) ellipse(ox, oy, x1, y1); if (ishor(m)) move(ox + isright(m) ? x1 : -x1, oy); else move(ox, oy - isdown(m) ? y1 : -y1); break; case ARC: move(ox, oy); dotext(p); if (p->o_attr & HEAD1) arrow(x1 - (y1 - oy), y1 + (x1 - ox), x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead); if (p->o_attr & INVIS) /* probably wrong when it's cw */ move(x1, y1); else arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]); if (p->o_attr & HEAD2) arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox), p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5], -p->o_val[5]/p->o_val[6]/2, p->o_nhead); if (p->o_attr & CW_ARC) move(x1, y1); /* because drawn backwards */ break; case LINE: case ARROW: case SPLINE: move((ox + x1)/2, (oy + y1)/2); /* center */ dotext(p); if (p->o_attr & HEAD1) arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); if (p->o_attr & INVIS) move(x1, y1); else if (p->o_type == SPLINE) spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval); else { dx = ox; dy = oy; for (k=0, j=5; k < p->o_val[4]; k++, j += 2) { ndx = dx + p->o_val[j]; ndy = dy + p->o_val[j+1]; if (p->o_attr & (DOTBIT|DASHBIT)) dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval); else line(dx, dy, ndx, ndy); dx = ndx; dy = ndy; } } if (p->o_attr & HEAD2) { dx = ox; dy = oy; for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) { dx += p->o_val[j]; dy += p->o_val[j+1]; } arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); } break; case MOVE: case TEXT: move(ox, oy); dotext(p); break; } } }
obj *boxgen(void) { static double prevh = HT; static double prevw = WID; /* golden mean, sort of */ int i, at, battr, with; double ddval, fillval, xwith, ywith; double h, w, x0, y0, x1, y1; obj *p, *ppos; Attr *ap; h = getfval("boxht"); w = getfval("boxwid"); at = battr = with = 0; ddval = fillval = xwith = ywith = 0; for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; break; case WIDTH: w = ap->a_val.f; break; case SAME: h = prevh; w = prevw; break; case WITH: with = ap->a_val.i; /* corner */ break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: battr |= INVIS; break; case NOEDGE: battr |= NOEDGEBIT; break; case DOT: case DASH: battr |= ap->a_type==DOT ? DOTBIT : DASHBIT; if (ap->a_sub == DEFAULT) ddval = getfval("dashwid"); else ddval = ap->a_val.f; break; case FILL: battr |= FILLBIT; if (ap->a_sub == DEFAULT) fillval = getfval("fillval"); else fillval = ap->a_val.f; break; case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; } } if (with) { switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); p = makenode(BOX, 2); p->o_val[0] = w; p->o_val[1] = h; p->o_attr = battr; p->o_ddval = ddval; p->o_fillval = fillval; dprintf("B %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; prevh = h; prevw = w; return(p); }
obj * circgen(int type) { static double rad[2] = { HT2, WID2 }; static double rad2[2] = { HT2, HT2 }; struct objattr obat; double xwith, ywith, r, r2; int i, at, t, with; obj *p, *ppos; Attr *ap; obat.a_layer = (int)getfval("curlayer"); obat.a_flags = EDGED; obat.a_weight = obat.a_lcolor = obat.a_pcolor = obat.a_tcolor = -1; obat.a_dashpat.a = (float *)0; at = with = xwith = ywith = 0; if ((t = (type == CIRCLE) ? 0 : 1)) { r = getfval("ellipsewid") / 2; r2 = getfval("ellipseht") / 2; } else r = r2 = getfval("circlerad"); set_text(); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { default: miscattrs(ap, &obat); break; case RADIUS: r = ap->a_val.f; break; case DIAMETER: case WIDTH: r = ap->a_val.f / 2; break; case HEIGHT: r2 = ap->a_val.f / 2; break; case SAME: r = rad[t]; r2 = rad2[t]; break; case WITH: with = ap->a_val.i; break; case AT: ppos = ap->a_val.o; curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y); at++; break; } } if (type == CIRCLE) r2 = r; /* probably superfluous */ if (with) { if (pic_compat) /* map NE to 2nd, etc. */ with = with == NE ? 2 : with == NW ? 4 : with == SW ? 6 : with == SE ? 8 : with; switch (with) { case NORTH: ywith = -r2; break; case SOUTH: ywith = r2; break; case EAST: xwith = -r; break; case WEST: xwith = r; break; case NE: xwith = -r; ywith = -r2; break; case SE: xwith = -r; ywith = r2; break; case NW: xwith = r; ywith = -r2; break; case SW: xwith = r; ywith = r2; break; case CENTER: case START: case END: break; default: xwith = -r * xdelta[with % 8]; ywith = -r2 * ydelta[with % 8]; if (with % 2 == 0) { xwith *= M_SQRT1_2; ywith *= M_SQRT1_2; } break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; } if (r <= 0 || r2 <= 0) yyerror("%s has invalid radius %g", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2); p = makenode(type, N_VAL, obat.a_layer); p->o_wid = 2 * (rad[t] = r); p->o_ht = 2 * (rad2[t] = r2); primattrs(p, &obat); text_bounds(p); if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; r += p->o_weight/2; r2 += p->o_weight/2; track_bounds (p->o_x - r, p->o_y - r2, p->o_x + r, p->o_y + r2); return(p); }