aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/pic/pltroff.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/pic/pltroff.c')
-rw-r--r--src/cmd/pic/pltroff.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/cmd/pic/pltroff.c b/src/cmd/pic/pltroff.c
new file mode 100644
index 00000000..d3e3151b
--- /dev/null
+++ b/src/cmd/pic/pltroff.c
@@ -0,0 +1,357 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "pic.h"
+extern int dbg;
+
+#define abs(n) (n >= 0 ? n : -(n))
+#define max(x,y) ((x)>(y) ? (x) : (y))
+
+char *textshift = "\\v'.2m'"; /* move text this far down */
+
+/* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
+/* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
+/* default output is 6x6 inches */
+
+
+double xscale;
+double yscale;
+
+double hpos = 0; /* current horizontal position in output coordinate system */
+double vpos = 0; /* current vertical position; 0 is top of page */
+
+double htrue = 0; /* where we really are */
+double vtrue = 0;
+
+double X0, Y0; /* left bottom of input */
+double X1, Y1; /* right top of input */
+
+double hmax; /* right end of output */
+double vmax; /* top of output (down is positive) */
+
+extern double deltx;
+extern double delty;
+extern double xmin, ymin, xmax, ymax;
+
+double xconv(double), yconv(double), xsc(double), ysc(double);
+void space(double, double, double, double);
+void hgoto(double), vgoto(double), hmot(double), vmot(double);
+void move(double, double), movehv(double, double);
+void cont(double, double);
+
+void openpl(char *s) /* initialize device; s is residue of .PS invocation line */
+{
+ double maxw, maxh, ratio = 1;
+ double odeltx = deltx, odelty = delty;
+
+ hpos = vpos = 0;
+ maxw = getfval("maxpswid");
+ maxh = getfval("maxpsht");
+ if (deltx > maxw) { /* shrink horizontal */
+ ratio = maxw / deltx;
+ deltx *= ratio;
+ delty *= ratio;
+ }
+ if (delty > maxh) { /* shrink vertical */
+ ratio = maxh / delty;
+ deltx *= ratio;
+ delty *= ratio;
+ }
+ if (ratio != 1) {
+ fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty);
+ fprintf(stderr, " %g X %g\n", deltx, delty);
+ }
+ space(xmin, ymin, xmax, ymax);
+ printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
+ printf("... %.3fi %.3fi %.3fi %.3fi\n",
+ xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
+ printf(".nr 00 \\n(.u\n");
+ printf(".nf\n");
+ printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
+ /* assumes \n comes as part of s */
+}
+
+void space(double x0, double y0, double x1, double y1) /* set limits of page */
+{
+ X0 = x0;
+ Y0 = y0;
+ X1 = x1;
+ Y1 = y1;
+ xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
+ yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
+}
+
+double xconv(double x) /* convert x from external to internal form */
+{
+ return (x-X0) * xscale;
+}
+
+double xsc(double x) /* convert x from external to internal form, scaling only */
+{
+
+ return (x) * xscale;
+}
+
+double yconv(double y) /* convert y from external to internal form */
+{
+ return (Y1-y) * yscale;
+}
+
+double ysc(double y) /* convert y from external to internal form, scaling only */
+{
+ return (y) * yscale;
+}
+
+void closepl(char *PEline) /* clean up after finished */
+{
+ movehv(0.0, 0.0); /* get back to where we started */
+ if (strchr(PEline, 'F') == NULL) {
+ printf(".sp 1+%.3fi\n", yconv(ymin));
+ }
+ printf("%s\n", PEline);
+ printf(".if \\n(00 .fi\n");
+}
+
+void move(double x, double y) /* go to position x, y in external coords */
+{
+ hgoto(xconv(x));
+ vgoto(yconv(y));
+}
+
+void movehv(double h, double v) /* go to internal position h, v */
+{
+ hgoto(h);
+ vgoto(v);
+}
+
+void hmot(double n) /* generate n units of horizontal motion */
+{
+ hpos += n;
+}
+
+void vmot(double n) /* generate n units of vertical motion */
+{
+ vpos += n;
+}
+
+void hgoto(double n)
+{
+ hpos = n;
+}
+
+void vgoto(double n)
+{
+ vpos = n;
+}
+
+double fabs(double x)
+{
+ return x < 0 ? -x : x;
+}
+
+void hvflush(void) /* get to proper point for output */
+{
+ if (fabs(hpos-htrue) >= 0.0005) {
+ printf("\\h'%.3fi'", hpos - htrue);
+ htrue = hpos;
+ }
+ if (fabs(vpos-vtrue) >= 0.0005) {
+ printf("\\v'%.3fi'", vpos - vtrue);
+ vtrue = vpos;
+ }
+}
+
+void flyback(void) /* return to upper left corner (entry point) */
+{
+ printf(".sp -1\n");
+ htrue = vtrue = 0;
+}
+
+void printlf(int n, char *f)
+{
+ if (f)
+ printf(".lf %d %s\n", n, f);
+ else
+ printf(".lf %d\n", n);
+}
+
+void troff(char *s) /* output troff right here */
+{
+ printf("%s\n", s);
+}
+
+void label(char *s, int t, int nh) /* text s of type t nh half-lines up */
+{
+ int q;
+ char *p;
+
+ if (!s)
+ return;
+ hvflush();
+ dprintf("label: %s %o %d\n", s, t, nh);
+ printf("%s", textshift); /* shift down and left */
+ if (t & ABOVE)
+ nh++;
+ else if (t & BELOW)
+ nh--;
+ if (nh)
+ printf("\\v'%du*\\n(.vu/2u'", -nh);
+ /* just in case the text contains a quote: */
+ q = 0;
+ for (p = s; *p; p++)
+ if (*p == '\'') {
+ q = 1;
+ break;
+ }
+ t &= ~(ABOVE|BELOW);
+ if (t & LJUST) {
+ printf("%s", s);
+ } else if (t & RJUST) {
+ if (q)
+ printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
+ else
+ printf("\\h'-\\w'%s'u'%s", s, s);
+ } else { /* CENTER */
+ if (q)
+ printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
+ else
+ printf("\\h'-\\w'%s'u/2u'%s", s, s);
+ }
+ printf("\n");
+ flyback();
+}
+
+void line(double x0, double y0, double x1, double y1) /* draw line from x0,y0 to x1,y1 */
+{
+ move(x0, y0);
+ cont(x1, y1);
+}
+
+void arrow(double x0, double y0, double x1, double y1, double w, double h,
+ double ang, int nhead) /* draw arrow (without shaft) */
+{
+ double alpha, rot, drot, hyp;
+ double dx, dy;
+ int i;
+
+ rot = atan2(w / 2, h);
+ hyp = sqrt(w/2 * w/2 + h * h);
+ alpha = atan2(y1-y0, x1-x0) + ang;
+ if (nhead < 2)
+ nhead = 2;
+ dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
+ for (i = nhead-1; i >= 0; i--) {
+ drot = 2 * rot / (double) (nhead-1) * (double) i;
+ dx = hyp * cos(alpha + PI - rot + drot);
+ dy = hyp * sin(alpha + PI - rot + drot);
+ dprintf("dx,dy = %g,%g\n", dx, dy);
+ line(x1+dx, y1+dy, x1, y1);
+ }
+}
+
+double lastgray = 0;
+
+void fillstart(double v) /* this works only for postscript, obviously. */
+{ /* uses drechsler's dpost conventions... */
+ hvflush();
+ printf("\\X'BeginObject %g setgray'\n", v);
+ lastgray = v;
+ flyback();
+}
+
+void fillend(int vis, int fill)
+{
+ hvflush();
+ printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
+ !vis ? lastgray : 0.0,
+ vis ? "stroke" : "");
+ /* for dashed: [50] 0 setdash just before stroke. */
+ lastgray = 0;
+ flyback();
+}
+
+void box(double x0, double y0, double x1, double y1)
+{
+ move(x0, y0);
+ cont(x0, y1);
+ cont(x1, y1);
+ cont(x1, y0);
+ cont(x0, y0);
+}
+
+void cont(double x, double y) /* continue line from here to x,y */
+{
+ double h1, v1;
+ double dh, dv;
+
+ h1 = xconv(x);
+ v1 = yconv(y);
+ dh = h1 - hpos;
+ dv = v1 - vpos;
+ hvflush();
+ printf("\\D'l%.3fi %.3fi'\n", dh, dv);
+ flyback(); /* expensive */
+ hpos = h1;
+ vpos = v1;
+}
+
+void circle(double x, double y, double r)
+{
+ move(x-r, y);
+ hvflush();
+ printf("\\D'c%.3fi'\n", xsc(2 * r));
+ flyback();
+}
+
+void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
+{
+ int i;
+ double dx, dy;
+ double xerr, yerr;
+
+ move(x, y);
+ hvflush();
+ xerr = yerr = 0.0;
+ printf("\\D'~");
+ for (i = 0; i < 2 * n; i += 2) {
+ dx = xsc(xerr += p[i]);
+ xerr -= dx/xscale;
+ dy = ysc(yerr += p[i+1]);
+ yerr -= dy/yscale;
+ printf(" %.3fi %.3fi", dx, -dy); /* WATCH SIGN */
+ }
+ printf("'\n");
+ flyback();
+}
+
+void ellipse(double x, double y, double r1, double r2)
+{
+ double ir1, ir2;
+
+ move(x-r1, y);
+ hvflush();
+ ir1 = xsc(r1);
+ ir2 = ysc(r2);
+ printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
+ flyback();
+}
+
+void arc(double x, double y, double x0, double y0, double x1, double y1) /* draw arc with center x,y */
+{
+
+ move(x0, y0);
+ hvflush();
+ printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
+ xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y)); /* WATCH SIGNS */
+ flyback();
+}
+
+void dot(void) {
+ hvflush();
+ /* what character to draw here depends on what's available. */
+ /* on the 202, l. is good but small. */
+ /* in general, use a smaller, shifted period and hope */
+
+ printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
+ flyback();
+}