13e12c5d1SDavid du Colombier #include <stdio.h>
23e12c5d1SDavid du Colombier #include <math.h>
33e12c5d1SDavid du Colombier #include "pic.h"
43e12c5d1SDavid du Colombier #include "y.tab.h"
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier void dotext(obj *);
73e12c5d1SDavid du Colombier void dotline(double, double, double, double, int, double);
83e12c5d1SDavid du Colombier void dotbox(double, double, double, double, int, double);
93e12c5d1SDavid du Colombier void ellipse(double, double, double, double);
103e12c5d1SDavid du Colombier void circle(double, double, double);
113e12c5d1SDavid du Colombier void arc(double, double, double, double, double, double);
123e12c5d1SDavid du Colombier void arrow(double, double, double, double, double, double, double, int);
133e12c5d1SDavid du Colombier void line(double, double, double, double);
143e12c5d1SDavid du Colombier void box(double, double, double, double);
153e12c5d1SDavid du Colombier void spline(double x, double y, double n, ofloat *p, int dashed, double ddval);
163e12c5d1SDavid du Colombier void move(double, double);
173e12c5d1SDavid du Colombier void troff(char *);
183e12c5d1SDavid du Colombier void dot(void);
197dd7cddfSDavid du Colombier void fillstart(double), fillend(int vis, int noedge);
203e12c5d1SDavid du Colombier
print(void)213e12c5d1SDavid du Colombier void print(void)
223e12c5d1SDavid du Colombier {
233e12c5d1SDavid du Colombier obj *p;
243e12c5d1SDavid du Colombier int i, j, k, m;
257dd7cddfSDavid du Colombier int fill, vis, invis;
263e12c5d1SDavid du Colombier double x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy;
273e12c5d1SDavid du Colombier
283e12c5d1SDavid du Colombier for (i = 0; i < nobj; i++) {
293e12c5d1SDavid du Colombier p = objlist[i];
303e12c5d1SDavid du Colombier ox = p->o_x;
313e12c5d1SDavid du Colombier oy = p->o_y;
323e12c5d1SDavid du Colombier if (p->o_count >= 1)
333e12c5d1SDavid du Colombier x1 = p->o_val[0];
343e12c5d1SDavid du Colombier if (p->o_count >= 2)
353e12c5d1SDavid du Colombier y1 = p->o_val[1];
363e12c5d1SDavid du Colombier m = p->o_mode;
377dd7cddfSDavid du Colombier fill = p->o_attr & FILLBIT;
387dd7cddfSDavid du Colombier invis = p->o_attr & INVIS;
397dd7cddfSDavid du Colombier vis = !invis;
403e12c5d1SDavid du Colombier switch (p->o_type) {
413e12c5d1SDavid du Colombier case TROFF:
423e12c5d1SDavid du Colombier troff(text[p->o_nt1].t_val);
433e12c5d1SDavid du Colombier break;
443e12c5d1SDavid du Colombier case BOX:
453e12c5d1SDavid du Colombier case BLOCK:
463e12c5d1SDavid du Colombier x0 = ox - x1 / 2;
473e12c5d1SDavid du Colombier y0 = oy - y1 / 2;
483e12c5d1SDavid du Colombier x1 = ox + x1 / 2;
493e12c5d1SDavid du Colombier y1 = oy + y1 / 2;
507dd7cddfSDavid du Colombier if (fill) {
513e12c5d1SDavid du Colombier move(x0, y0);
523e12c5d1SDavid du Colombier fillstart(p->o_fillval);
533e12c5d1SDavid du Colombier }
54*14f51593SDavid du Colombier if (p->o_type == BLOCK){
557dd7cddfSDavid du Colombier ; /* nothing at all */
56*14f51593SDavid du Colombier }else if (invis && !fill){
573e12c5d1SDavid du Colombier ; /* nothing at all */
58*14f51593SDavid du Colombier }else if (p->o_attr & (DOTBIT|DASHBIT))
593e12c5d1SDavid du Colombier dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval);
603e12c5d1SDavid du Colombier else
613e12c5d1SDavid du Colombier box(x0, y0, x1, y1);
627dd7cddfSDavid du Colombier if (fill)
637dd7cddfSDavid du Colombier fillend(vis, fill);
643e12c5d1SDavid du Colombier move(ox, oy);
653e12c5d1SDavid du Colombier dotext(p); /* if there are any text strings */
663e12c5d1SDavid du Colombier if (ishor(m))
673e12c5d1SDavid du Colombier move(isright(m) ? x1 : x0, oy); /* right side */
683e12c5d1SDavid du Colombier else
693e12c5d1SDavid du Colombier move(ox, isdown(m) ? y0 : y1); /* bottom */
703e12c5d1SDavid du Colombier break;
713e12c5d1SDavid du Colombier case BLOCKEND:
723e12c5d1SDavid du Colombier break;
733e12c5d1SDavid du Colombier case CIRCLE:
747dd7cddfSDavid du Colombier if (fill)
753e12c5d1SDavid du Colombier fillstart(p->o_fillval);
767dd7cddfSDavid du Colombier if (vis || fill)
773e12c5d1SDavid du Colombier circle(ox, oy, x1);
787dd7cddfSDavid du Colombier if (fill)
797dd7cddfSDavid du Colombier fillend(vis, fill);
803e12c5d1SDavid du Colombier move(ox, oy);
813e12c5d1SDavid du Colombier dotext(p);
823e12c5d1SDavid du Colombier if (ishor(m))
833e12c5d1SDavid du Colombier move(ox + isright(m) ? x1 : -x1, oy);
843e12c5d1SDavid du Colombier else
853e12c5d1SDavid du Colombier move(ox, oy + isup(m) ? x1 : -x1);
863e12c5d1SDavid du Colombier break;
873e12c5d1SDavid du Colombier case ELLIPSE:
887dd7cddfSDavid du Colombier if (fill)
893e12c5d1SDavid du Colombier fillstart(p->o_fillval);
907dd7cddfSDavid du Colombier if (vis || fill)
913e12c5d1SDavid du Colombier ellipse(ox, oy, x1, y1);
927dd7cddfSDavid du Colombier if (fill)
937dd7cddfSDavid du Colombier fillend(vis, fill);
943e12c5d1SDavid du Colombier move(ox, oy);
953e12c5d1SDavid du Colombier dotext(p);
963e12c5d1SDavid du Colombier if (ishor(m))
973e12c5d1SDavid du Colombier move(ox + isright(m) ? x1 : -x1, oy);
983e12c5d1SDavid du Colombier else
993e12c5d1SDavid du Colombier move(ox, oy - isdown(m) ? y1 : -y1);
1003e12c5d1SDavid du Colombier break;
1013e12c5d1SDavid du Colombier case ARC:
1027dd7cddfSDavid du Colombier if (fill) {
1033e12c5d1SDavid du Colombier move(ox, oy);
1047dd7cddfSDavid du Colombier fillstart(p->o_fillval);
1057dd7cddfSDavid du Colombier }
1063e12c5d1SDavid du Colombier if (p->o_attr & HEAD1)
1073e12c5d1SDavid du Colombier arrow(x1 - (y1 - oy), y1 + (x1 - ox),
1083e12c5d1SDavid du Colombier x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead);
1097dd7cddfSDavid du Colombier if (invis && !fill)
1103e12c5d1SDavid du Colombier /* probably wrong when it's cw */
1113e12c5d1SDavid du Colombier move(x1, y1);
1123e12c5d1SDavid du Colombier else
1133e12c5d1SDavid du Colombier arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]);
1143e12c5d1SDavid du Colombier if (p->o_attr & HEAD2)
1153e12c5d1SDavid du Colombier arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
1163e12c5d1SDavid du Colombier 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);
1177dd7cddfSDavid du Colombier if (fill)
1187dd7cddfSDavid du Colombier fillend(vis, fill);
1193e12c5d1SDavid du Colombier if (p->o_attr & CW_ARC)
1203e12c5d1SDavid du Colombier move(x1, y1); /* because drawn backwards */
1217dd7cddfSDavid du Colombier move(ox, oy);
1227dd7cddfSDavid du Colombier dotext(p);
1233e12c5d1SDavid du Colombier break;
1243e12c5d1SDavid du Colombier case LINE:
1253e12c5d1SDavid du Colombier case ARROW:
1263e12c5d1SDavid du Colombier case SPLINE:
1277dd7cddfSDavid du Colombier if (fill) {
1287dd7cddfSDavid du Colombier move(ox, oy);
1297dd7cddfSDavid du Colombier fillstart(p->o_fillval);
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier if (vis && p->o_attr & HEAD1)
1323e12c5d1SDavid du Colombier 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);
1337dd7cddfSDavid du Colombier if (invis && !fill)
1343e12c5d1SDavid du Colombier move(x1, y1);
1353e12c5d1SDavid du Colombier else if (p->o_type == SPLINE)
1363e12c5d1SDavid du Colombier spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval);
1373e12c5d1SDavid du Colombier else {
1383e12c5d1SDavid du Colombier dx = ox;
1393e12c5d1SDavid du Colombier dy = oy;
1403e12c5d1SDavid du Colombier for (k=0, j=5; k < p->o_val[4]; k++, j += 2) {
1413e12c5d1SDavid du Colombier ndx = dx + p->o_val[j];
1423e12c5d1SDavid du Colombier ndy = dy + p->o_val[j+1];
1433e12c5d1SDavid du Colombier if (p->o_attr & (DOTBIT|DASHBIT))
1443e12c5d1SDavid du Colombier dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval);
1453e12c5d1SDavid du Colombier else
1463e12c5d1SDavid du Colombier line(dx, dy, ndx, ndy);
1473e12c5d1SDavid du Colombier dx = ndx;
1483e12c5d1SDavid du Colombier dy = ndy;
1493e12c5d1SDavid du Colombier }
1503e12c5d1SDavid du Colombier }
1517dd7cddfSDavid du Colombier if (vis && p->o_attr & HEAD2) {
1523e12c5d1SDavid du Colombier dx = ox;
1533e12c5d1SDavid du Colombier dy = oy;
1543e12c5d1SDavid du Colombier for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) {
1553e12c5d1SDavid du Colombier dx += p->o_val[j];
1563e12c5d1SDavid du Colombier dy += p->o_val[j+1];
1573e12c5d1SDavid du Colombier }
1583e12c5d1SDavid du Colombier arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
1593e12c5d1SDavid du Colombier }
1607dd7cddfSDavid du Colombier if (fill)
1617dd7cddfSDavid du Colombier fillend(vis, fill);
1627dd7cddfSDavid du Colombier move((ox + x1)/2, (oy + y1)/2); /* center */
1637dd7cddfSDavid du Colombier dotext(p);
1643e12c5d1SDavid du Colombier break;
1653e12c5d1SDavid du Colombier case MOVE:
1667dd7cddfSDavid du Colombier move(ox, oy);
1677dd7cddfSDavid du Colombier break;
1683e12c5d1SDavid du Colombier case TEXT:
1693e12c5d1SDavid du Colombier move(ox, oy);
1707dd7cddfSDavid du Colombier if (vis)
1713e12c5d1SDavid du Colombier dotext(p);
1723e12c5d1SDavid du Colombier break;
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier }
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier
dotline(double x0,double y0,double x1,double y1,int ddtype,double ddval)1773e12c5d1SDavid du Colombier void dotline(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted line */
1783e12c5d1SDavid du Colombier {
1793e12c5d1SDavid du Colombier static double prevval = 0.05; /* 20 per inch by default */
1803e12c5d1SDavid du Colombier int i, numdots;
1813e12c5d1SDavid du Colombier double a, b, dx, dy;
1823e12c5d1SDavid du Colombier
1833e12c5d1SDavid du Colombier if (ddval == 0)
1843e12c5d1SDavid du Colombier ddval = prevval;
1853e12c5d1SDavid du Colombier prevval = ddval;
1863e12c5d1SDavid du Colombier /* don't save dot/dash value */
1873e12c5d1SDavid du Colombier dx = x1 - x0;
1883e12c5d1SDavid du Colombier dy = y1 - y0;
1893e12c5d1SDavid du Colombier if (ddtype & DOTBIT) {
1903e12c5d1SDavid du Colombier numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
1913e12c5d1SDavid du Colombier if (numdots > 0)
1923e12c5d1SDavid du Colombier for (i = 0; i <= numdots; i++) {
1933e12c5d1SDavid du Colombier a = (double) i / (double) numdots;
1943e12c5d1SDavid du Colombier move(x0 + (a * dx), y0 + (a * dy));
1953e12c5d1SDavid du Colombier dot();
1963e12c5d1SDavid du Colombier }
1973e12c5d1SDavid du Colombier } else if (ddtype & DASHBIT) {
1983e12c5d1SDavid du Colombier double d, dashsize, spacesize;
1993e12c5d1SDavid du Colombier d = sqrt(dx*dx + dy*dy);
2003e12c5d1SDavid du Colombier if (d <= 2 * prevval) {
2013e12c5d1SDavid du Colombier line(x0, y0, x1, y1);
2023e12c5d1SDavid du Colombier return;
2033e12c5d1SDavid du Colombier }
2043e12c5d1SDavid du Colombier numdots = d / (2 * prevval) + 1; /* ceiling */
2053e12c5d1SDavid du Colombier dashsize = prevval;
2063e12c5d1SDavid du Colombier spacesize = (d - numdots * dashsize) / (numdots - 1);
2073e12c5d1SDavid du Colombier for (i = 0; i < numdots-1; i++) {
2083e12c5d1SDavid du Colombier a = i * (dashsize + spacesize) / d;
2093e12c5d1SDavid du Colombier b = a + dashsize / d;
2103e12c5d1SDavid du Colombier line(x0 + (a*dx), y0 + (a*dy), x0 + (b*dx), y0 + (b*dy));
2113e12c5d1SDavid du Colombier a = b;
2123e12c5d1SDavid du Colombier b = a + spacesize / d;
2133e12c5d1SDavid du Colombier move(x0 + (a*dx), y0 + (a*dy));
2143e12c5d1SDavid du Colombier }
2153e12c5d1SDavid du Colombier line(x0 + (b * dx), y0 + (b * dy), x1, y1);
2163e12c5d1SDavid du Colombier }
2173e12c5d1SDavid du Colombier prevval = 0.05;
2183e12c5d1SDavid du Colombier }
2193e12c5d1SDavid du Colombier
dotbox(double x0,double y0,double x1,double y1,int ddtype,double ddval)2203e12c5d1SDavid du Colombier void dotbox(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted or dashed box */
2213e12c5d1SDavid du Colombier {
2223e12c5d1SDavid du Colombier dotline(x0, y0, x1, y0, ddtype, ddval);
2233e12c5d1SDavid du Colombier dotline(x1, y0, x1, y1, ddtype, ddval);
2243e12c5d1SDavid du Colombier dotline(x1, y1, x0, y1, ddtype, ddval);
2253e12c5d1SDavid du Colombier dotline(x0, y1, x0, y0, ddtype, ddval);
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier
dotext(obj * p)2283e12c5d1SDavid du Colombier void dotext(obj *p) /* print text strings of p in proper vertical spacing */
2293e12c5d1SDavid du Colombier {
2303e12c5d1SDavid du Colombier int i, nhalf;
2313e12c5d1SDavid du Colombier void label(char *, int, int);
2323e12c5d1SDavid du Colombier
2333e12c5d1SDavid du Colombier nhalf = p->o_nt2 - p->o_nt1 - 1;
2343e12c5d1SDavid du Colombier for (i = p->o_nt1; i < p->o_nt2; i++) {
2353e12c5d1SDavid du Colombier label(text[i].t_val, text[i].t_type, nhalf);
2363e12c5d1SDavid du Colombier nhalf -= 2;
2373e12c5d1SDavid du Colombier }
2383e12c5d1SDavid du Colombier }
239