/* Output routines for SVG */ void svgprelude (double n, double s, double e, double w, double lth) { double hsize, vsize; gslinethick = 0.8; printf ("\n"); printf ("\n"); printf ("\n",VERSIONDATE); hsize = (e - w + (2 * lth)) / fsc; vsize = (n - s + (2 * lth)) / fsc; printf ("\n", Ceil (hsize + 0.5), Ceil (vsize + 0.5)); printf ("\n"); printf ("\n"); } void svgpostlude (void) { printf ("\n"); } /* output substrings */ void space (void) { putchar (' '); } void quote (void) { putchar ('"'); } void svgsetstroke (double lth) { if (lth == gslinethick) { return; } printf (" stroke-width=\""); wfloat (&output, (lth / 72) * dpPPI); printf ("\"\n"); } void svgsoutline (nametype * so) { printf (" stroke=\""); wstring (&output, so); printf ("\"\n"); } void fillgray (double fll) { printf (" fill=\""); if (fll == 0.0) { printf ("black"); } else if (fll == 0.25) { printf ("darkgray"); } else if (fll == 0.5) { printf ("gray"); } else if (fll == 0.75) { printf ("lightgray"); } else if (fll == 1.0) { printf ("white"); } else { printf ("rgb("); fprintf (output, "%ld", (long) floor ((fll * 255) + 0.5)); putchar (','); fprintf (output, "%ld", (long) floor ((fll * 255) + 0.5)); putchar (','); fprintf (output, "%ld", (long) floor ((fll * 255) + 0.5)); putchar (')'); } printf ("\"\n"); } void svglineoptions (primitive * node, int lnspec) { double param,fact,thk; if (node->lthick >= 0.0) { svgsetstroke(node->lthick); } if (node->ptype == Xblock) { lnspec = Xinvis; } if ((outlinestr != NULL) && (lnspec != Xinvis)) { svgsoutline(outlinestr); } switch (lnspec) { case Xdashed: param = qenv (node, Xdashwid, node->lparam) / fsc; printf (" stroke-dasharray=\""); wfloat (&output, param * 7 / 6); putchar (','); wfloat (&output, param * 5 / 6); printf ("\"\n"); break; case Xdotted: if (!ismdistmax(node->lparam)) { param = node->lparam; } else { if (node->lthick >= 0) { thk = node->lthick; } else { thk = qenv(node, Xlinethick, node->lthick); } if (thk >= 2) { fact = 2.5; } else if (thk < 1) { fact = 5.0; } else { fact = 7.5 - (thk * 2.5); } param = (thk / 72) * scale * fact; } printf (" stroke-linecap=\"round\""); printf (" stroke-dasharray=\"0.5,"); wfloat (&output, param / fsc); printf ("\"\n"); break; case Xinvis: printf (" stroke=\"none\"\n"); break; } } void svgfilloptions (primitive * node, double fill, nametype * sh, int lnspec, boolean poly) { fill = ((long) floor ((fill * 1000000L) + 0.5)) / 1000000.0; switch (node->ptype) { case Xbox: case Xblock: printf ("= 0.0) && (fill <= 1.0)) { fillgray (fill); } else if (node->ptype == Xstring) { fillgray (0.0); } svglineoptions (node, lnspec); } void svgendpath (void) { printf (" />\n"); } void svgparam (char * p, double x) { printf (" %s=\"", p); wfloat (&output, x / fsc); quote (); } void svgcoord (char * s1, char * s2, double x, double y) { svgparam (s1, x); svgparam (s2, xfheight - y); } void svgwpos (postype p) { wfloat (&output, p.xpos / fsc); putchar (','); wfloat (&output, (xfheight - p.ypos) / fsc); } void svgwprop (postype p1, postype p2, double a, double b, double c) { pprop (p1, &p2, a, b, c); svgwpos (p2); } void svgwstring (nametype * p) { int i; Char c; boolean waswhite = false; boolean iswhite; int FORLIM; if (p == NULL) { return; } if (p->segmnt == NULL) { return; } FORLIM = p->len; for (i = 0; i < FORLIM; i++) { c = p->segmnt[p->seginx + i]; iswhite = ((c == etxch) || (c == nlch) || (c == tabch) || (c == ' ')); if ((!iswhite) || (!waswhite)) { putchar (c); } waswhite = iswhite; } } void svgwtext (primitive * node, nametype * tp, double x, double y) { int nstr = 0; nametype *tx; boolean L, R, A, B; double v, lineskip, xheight, dx, dy; if ((tp == NULL) || (node == NULL)) { return; } tx = tp; while (tx != NULL) { nstr++; tx = tx->nextname; } v = nstr - 1 + dptextratio; if ((node->ptype == Xstring) && (nstr > 0) && (v != 0)) { lineskip = node->boxheight_ / v; } else { lineskip = venv (node, Xtextht) / dptextratio; } xheight = lineskip * dptextratio; y += (v * lineskip / 2) - xheight; /* string bottom */ do { printf ("ptype != Xstring) { printf (" stroke-width=\"0.2pt\" fill=\"black\""); } else { if (node->lthick < 0) { svgsetstroke (0.2); } svgfilloptions (node, node->boxfill_, node->shadedp, lspec (node->spec), false); } v = venv (node, Xtextoffset); checkjust (tp, &A, &B, &L, &R); if (node->ptype == Xstring) { dx = node->boxradius_; } else { dx = 0.0; } if (L) { printf(" text-anchor=\"start\"\n"); if (node->ptype != Xstring) { dx = v; } } else if (R) { printf(" text-anchor=\"end\"\n"); if (node->ptype != Xstring) { dx = -v; } } /* JD additions */ /* 1 - save A, B, L, R */ printf(" data-position=\"%c\"\n", A ? 'A' : B ? 'B' : L ? 'L' : R ? 'R' : 'X'); /* 2 - Save positional data */ #define DPRINT(name_lit, value) \ printf(" data-" name_lit "=\"%g\"\n", (double) (value)) DPRINT("x", x); DPRINT("y", y); DPRINT("v", v); DPRINT("lineskip", lineskip); DPRINT("xheight", xheight); DPRINT("fsc", fsc); DPRINT("xfheight", xfheight); dy = 0.0; if (node->ptype != Xstring) { if (A) { dy = (xheight / 2) + v; } else if (B) { dy = (xheight / (-2)) - v; } } DPRINT("dx", dx); DPRINT("dy", dy); printf(" data-ptype=\"%s\"\n", node->ptype == Xstring ? "Xstring" : ""); svgcoord ("x", "y", Max (0.0, x + dx), Max (0.0, y + dy)); if (tp->len > 40) { putchar ('\n'); } putchar ('>'); svgwstring (tp); printf ("\n"); y -= lineskip; tp = tp->nextname; } while (tp != NULL); } void svgwarc (postype E, double r, double angle, double ccw) { printf (" A "); wfloat (&output, fabs (r) / fsc); space (); wfloat (&output, fabs (r) / fsc); printf (" 0 "); if (fabs (angle) > pi) { putchar ('1'); } else { putchar ('0'); } if (ccw > 0) { printf (" 0 "); } else { printf (" 1 "); } svgwpos (E); if (angle == 0) { putchar ('\n'); } } void svgarcahead (postype C, int atyp, postype * point, nametype * sou, double ht, double wid, double lth, double radius, double angle) { postype P, Q, Co, Ci, Px, Cox, Cix, Ao, Ai; double ccw, lwi; boolean startarrow; arcahead (C, *point, atyp, ht, wid, lth, radius, angle, &P, &Co, &Ci, &Px, &Cox, &Cix, &Ao, &Ai, &ccw, &lwi, &startarrow); radius = fabs (radius); /* Trace arrowhead outline */ printf (" 0.0) { svgsetstroke (lth); } if (sou != NULL) { svgsoutline (sou); } printf (" points=\""); svgwprop (P, L, x - y, y, x); space (); svgwpos (P); putchar ('\n'); svgwprop (P, R, x - y, y, x); } else if (atyp == 3) { printf ("= 0.0) && (fill <= 1.0)) { fillgray (fill); } else { printf (" fill=\"black\"\n"); } printf (" points=\""); svgwpos (Px); space (); svgwpos (Lx); putchar ('\n'); svgwpos (*point); space (); svgwpos (Rx); } else { printf ("= 0.0) && (fill <= 1.0)) { fillgray (fill); } else { printf (" fill=\"black\"\n"); } printf (" points=\""); svgwpos (Lx); space (); svgwpos (*point); putchar ('\n'); svgwpos (Rx); } quote (); svgendpath (); *point = P; } void svgsplinesegment (primitive * tv, int splc, int splt) { if (tv == NULL) { return; } if (splt == 1) { printf ("aat.xpos / fsc); printf ("\" y1=\""); wfloat (&output, tv->aat.ypos / fsc); printf ("\" x2=\""); wfloat (&output, tv->endpos_.xpos / fsc); printf ("\" y2=\""); wfloat (&output, tv->endpos_.ypos / fsc); svgendpath (); return; } if (ismdistmax (tv->aradius_)) { if (splc == splt) { /* 1st seg */ printf (" d=\"M "); svgwpos (tv->aat); printf ("\n C "); svgwprop (tv->aat, tv->endpos_, 5.0, 1.0, 6.0); space (); svgwprop (tv->aat, tv->endpos_, 2.0, 1.0, 3.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 1.0, 2.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 5.0, 6.0); putchar ('\n'); return; } if (splc > 1) { /* interior segment */ svgwprop (tv->aat, tv->endpos_, 5.0, 1.0, 6.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 1.0, 2.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 5.0, 6.0); putchar ('\n'); return; } svgwprop (tv->aat, tv->endpos_, 5.0, 1.0, 6.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 1.0, 2.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 2.0, 3.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 5.0, 6.0); putchar ('\n'); svgwpos (tv->endpos_); quote (); svgendpath (); /* last segment */ return; } if ((splc == splt) && (splc > 1)) { printf (" d=\"M "); svgwpos (tv->aat); printf ("\n C "); svgwprop (tv->aat, tv->endpos_, 1 - tv->aradius_, tv->aradius_, 1.0); space (); return; } if (splc > 1) { svgwprop (tv->aat, tv->endpos_, 0.5 + (tv->aradius_ / 2), 0.5 - (tv->aradius_ / 2), 1.0); space (); svgwprop (tv->aat, tv->endpos_, 1.0, 1.0, 2.0); space (); svgwprop (tv->aat, tv->endpos_, 0.5 - (tv->aradius_ / 2), 0.5 + (tv->aradius_ / 2), 1.0); space (); return; } svgwprop (tv->aat, tv->endpos_, tv->aradius_, 1 - tv->aradius_, 1.0); space (); svgwpos (tv->endpos_); quote (); svgendpath (); } /* node is always <> nil */ void svgdraw (primitive * node) { int lsp; postype X1, X2; primitive *lastseg, *tx, *primp; double lth; int TEMP; getlinespec (node, &lsp, &lastseg); shadestr = node->shadedp; outlinestr = node->outlinep; lth = qenv (node, Xlinethick, node->lthick); /* printobject(node); */ switch (node->ptype) { case Xbox: initnesw (); nesw (node); if (drawn (node, lsp, node->boxfill_)) { svgfilloptions (node, node->boxfill_, node->shadedp, lsp, false); svgcoord ("x", "y", node->aat.xpos - (fabs (node->boxwidth_) / 2), node->aat.ypos + (fabs (node->boxheight_) / 2)); if (node->boxradius_ > 0.0) { svgparam ("rx", node->boxradius_); svgparam ("ry", node->boxradius_); } svgparam ("width", fabs (node->boxwidth_)); svgparam ("height", fabs (node->boxheight_)); svgendpath (); } svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case Xblock: svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case Xellipse: if (drawn (node, lsp, node->ellipsefill_)) { svgfilloptions (node, node->ellipsefill_, node->shadedp, lsp, false); svgcoord ("cx", "cy", node->aat.xpos, node->aat.ypos); svgparam ("rx", 0.5 * fabs (node->ellipsewidth_)); svgparam ("ry", 0.5 * fabs (node->ellipseheight_)); svgendpath (); } svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case Xcircle: if (drawn (node, lsp, node->circlefill_)) { svgfilloptions (node, node->circlefill_, node->shadedp, lsp, false); svgcoord ("cx", "cy", node->aat.xpos, node->aat.ypos); svgparam ("r", fabs (node->circleradius_)); svgendpath (); } svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case Xline: case Xarrow: case Xmove: if (firstsegment (node)) { snode = node; getlinshade (node, &lastseg, &shadestr, &outlinestr, &fillfrac, &hasfill); if (hasfill) { printf ("= 0) && (fillfrac <= 1)) { fillgray (fillfrac); } else { printf (" fill=\""); wstring (&output, shadestr); printf ("\"\n"); } printf (" points=\""); svgwpos (node->aat); tx = node; while (tx != NULL) { putchar ('\n'); svgwpos (tx->endpos_); tx = tx->son; } printf ("\" />\n"); fillfrac = -1.0; shadestr = NULL; } if (lsp != Xinvis) { lth = qenv (lastseg, Xlinethick, lastseg->lthick); TEMP = ahlex (lastseg->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xlefthead)) { svgahead (ahnum (lastseg->lineatype_), &node->aat, node->endpos_, outlinestr, qenv (lastseg, Xarrowht, lastseg->lineheight_), qenv (lastseg, Xarrowwid, lastseg->linewidth_), lth, fillfrac); } TEMP = ahlex (lastseg->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xrighthead)) { svgahead (ahnum (lastseg->lineatype_), &lastseg->endpos_, lastseg->aat, outlinestr, qenv (lastseg, Xarrowht, lastseg->lineheight_), qenv (lastseg, Xarrowwid, lastseg->linewidth_), lth, fillfrac); } if (node->son == NULL) { svgfilloptions (lastseg, fillfrac, shadestr, lsp, false); svgcoord ("x1", "y1", node->aat.xpos, node->aat.ypos); svgcoord ("x2", "y2", node->endpos_.xpos, node->endpos_.ypos); svgendpath (); } else { svgfilloptions (lastseg, fillfrac, shadestr, lsp, true); printf (" points=\""); svgwpos (node->aat); space (); } } } else if (lsp != Xinvis) { svgwpos (node->aat); putchar ('\n'); if (node->son == NULL) { svgwpos (node->endpos_); quote (); svgendpath (); } } if (node->son == NULL) { while (snode != NULL) { primp = snode; if (primp->textp != NULL) { svgwtext (node, primp->textp, 0.5 * (primp->endpos_.xpos + primp->aat.xpos), 0.5 * (primp->aat.ypos + primp->endpos_.ypos)); } snode = snode->son; } } break; case Xspline: if (firstsegment (node)) { snode = node; getlinshade (node, &lastseg, &shadestr, &outlinestr, &fillfrac, &hasfill); node->lthick = lastseg->lthick; node->lparam = lastseg->lparam; if (hasfill) { printf ("= 0) && (fillfrac <= 1)) { fillgray (fillfrac); } else { printf (" fill=\""); wstring (&output, shadestr); printf ("\"\n"); } spltot = primdepth (node); splcount = spltot; tx = node; while (tx != NULL) { svgsplinesegment (tx, splcount, spltot); splcount--; tx = tx->son; } fillfrac = -1.0; shadestr = NULL; } if (lsp != Xinvis) { lth = qenv (lastseg, Xlinethick, lastseg->lthick); TEMP = ahlex (lastseg->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xlefthead)) { svgahead (ahnum (lastseg->lineatype_), &node->aat, node->endpos_, outlinestr, qenv (lastseg, Xarrowht, lastseg->lineheight_), qenv (lastseg, Xarrowwid, lastseg->linewidth_), lth, node->linefill_); } TEMP = ahlex (lastseg->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xrighthead)) { svgahead (ahnum (lastseg->lineatype_), &lastseg->endpos_, lastseg->aat, outlinestr, qenv (lastseg, Xarrowht, lastseg->lineheight_), qenv (lastseg, Xarrowwid, lastseg->linewidth_), lth, node->linefill_); } spltot = primdepth (node); splcount = spltot; svgfilloptions (node, fillfrac, shadestr, lsp, false); } } if (lsp != Xinvis) { svgsplinesegment (node, splcount, spltot); } splcount--; break; case Xarc: X1 = arcstart (node); X2 = arcend (node); getlinshade (node, &lastseg, &shadestr, &outlinestr, &fillfrac, &hasfill); if (hasfill) { printf ("= 0) && (fillfrac <= 1)) { fillgray (fillfrac); } else { printf (" fill=\""); wstring (&output, shadestr); printf ("\"\n"); } printf (" d=\"M "); svgwpos (X1); putchar ('\n'); svgwarc (X2, node->aradius_, node->arcangle_, node->arcangle_); quote (); svgendpath (); fillfrac = -1.0; shadestr = NULL; } if (lsp != Xinvis) { lth = qenv (lastseg, Xlinethick, lastseg->lthick); TEMP = ahlex (node->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xlefthead)) { svgarcahead(node->aat, ahnum(node->lineatype_), &X1, outlinestr, qenv(node, Xarrowht, node->lineheight_), qenv(node, Xarrowwid, node->linewidth_), lth, fabs(node->aradius_),node->arcangle_); node->startangle_ = datan(X1.ypos - node->aat.ypos,X1.xpos - node->aat.xpos); } TEMP = ahlex(node->lineatype_); if ((TEMP == Xdoublehead) || (TEMP == Xrighthead)) { svgarcahead(node->aat, ahnum(node->lineatype_), &X2, outlinestr, qenv(node, Xarrowht, node->lineheight_), qenv(node, Xarrowwid, node->linewidth_), lth, -fabs(node->aradius_),node->arcangle_); setangles(&node->startangle_, &node->arcangle_, node->aat, X1.xpos, X1.ypos, X2.xpos, X2.ypos); } printf ("aradius_, node->arcangle_, node->arcangle_); quote (); svgendpath (); } svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case Xstring: svgwtext (node, node->textp, node->aat.xpos, node->aat.ypos); break; case XLaTeX: if (node->textp != NULL) { wstring (&output, node->textp); putchar ('\n'); } break; } } /* svgdraw */