URI:
       tpltroff.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpltroff.c (7600B)
       ---
            1 #include <stdio.h>
            2 #include <math.h>
            3 #include <string.h>
            4 #include "pic.h"
            5 extern int dbg;
            6 
            7 #define        abs(n)        (n >= 0 ? n : -(n))
            8 #define        max(x,y)        ((x)>(y) ? (x) : (y))
            9 
           10 char        *textshift = "\\v'.2m'";        /* move text this far down */
           11 
           12 /* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
           13 /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
           14 /* default output is 6x6 inches */
           15 
           16 
           17 double        xscale;
           18 double        yscale;
           19 
           20 double        hpos        = 0;        /* current horizontal position in output coordinate system */
           21 double        vpos        = 0;        /* current vertical position; 0 is top of page */
           22 
           23 double        htrue        = 0;        /* where we really are */
           24 double        vtrue        = 0;
           25 
           26 double        X0, Y0;                /* left bottom of input */
           27 double        X1, Y1;                /* right top of input */
           28 
           29 double        hmax;                /* right end of output */
           30 double        vmax;                /* top of output (down is positive) */
           31 
           32 extern        double        deltx;
           33 extern        double        delty;
           34 extern        double        xmin, ymin, xmax, ymax;
           35 
           36 double        xconv(double), yconv(double), xsc(double), ysc(double);
           37 void        space(double, double, double, double);
           38 void        hgoto(double), vgoto(double), hmot(double), vmot(double);
           39 void        move(double, double), movehv(double, double);
           40 void        cont(double, double);
           41 
           42 void openpl(char *s)        /* initialize device; s is residue of .PS invocation line */
           43 {
           44         double maxw, maxh, ratio = 1;
           45         double odeltx = deltx, odelty = delty;
           46 
           47         hpos = vpos = 0;
           48         maxw = getfval("maxpswid");
           49         maxh = getfval("maxpsht");
           50         if (deltx > maxw) {        /* shrink horizontal */
           51                 ratio = maxw / deltx;
           52                 deltx *= ratio;
           53                 delty *= ratio;
           54         }
           55         if (delty > maxh) {        /* shrink vertical */
           56                 ratio = maxh / delty;
           57                 deltx *= ratio;
           58                 delty *= ratio;
           59         }
           60         if (ratio != 1) {
           61                 fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty);
           62                 fprintf(stderr, " %g X %g\n", deltx, delty);
           63         }
           64         space(xmin, ymin, xmax, ymax);
           65         printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
           66         printf("... %.3fi %.3fi %.3fi %.3fi\n",
           67                 xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
           68         printf(".nr 00 \\n(.u\n");
           69         printf(".nf\n");
           70         printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
           71                 /* assumes \n comes as part of s */
           72 }
           73 
           74 void space(double x0, double y0, double x1, double y1)        /* set limits of page */
           75 {
           76         X0 = x0;
           77         Y0 = y0;
           78         X1 = x1;
           79         Y1 = y1;
           80         xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
           81         yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
           82 }
           83 
           84 double xconv(double x)        /* convert x from external to internal form */
           85 {
           86         return (x-X0) * xscale;
           87 }
           88 
           89 double xsc(double x)        /* convert x from external to internal form, scaling only */
           90 {
           91 
           92         return (x) * xscale;
           93 }
           94 
           95 double yconv(double y)        /* convert y from external to internal form */
           96 {
           97         return (Y1-y) * yscale;
           98 }
           99 
          100 double ysc(double y)        /* convert y from external to internal form, scaling only */
          101 {
          102         return (y) * yscale;
          103 }
          104 
          105 void closepl(char *PEline)        /* clean up after finished */
          106 {
          107         movehv(0.0, 0.0);        /* get back to where we started */
          108         if (strchr(PEline, 'F') == NULL) {
          109                 printf(".sp 1+%.3fi\n", yconv(ymin));
          110         }
          111         printf("%s\n", PEline);
          112         printf(".if \\n(00 .fi\n");
          113 }
          114 
          115 void move(double x, double y)        /* go to position x, y in external coords */
          116 {
          117         hgoto(xconv(x));
          118         vgoto(yconv(y));
          119 }
          120 
          121 void movehv(double h, double v)        /* go to internal position h, v */
          122 {
          123         hgoto(h);
          124         vgoto(v);
          125 }
          126 
          127 void hmot(double n)        /* generate n units of horizontal motion */
          128 {
          129         hpos += n;
          130 }
          131 
          132 void vmot(double n)        /* generate n units of vertical motion */
          133 {
          134         vpos += n;
          135 }
          136 
          137 void hgoto(double n)
          138 {
          139         hpos = n;
          140 }
          141 
          142 void vgoto(double n)
          143 {
          144         vpos = n;
          145 }
          146 
          147 void hvflush(void)        /* get to proper point for output */
          148 {
          149         if (fabs(hpos-htrue) >= 0.0005) {
          150                 printf("\\h'%.3fi'", hpos - htrue);
          151                 htrue = hpos;
          152         }
          153         if (fabs(vpos-vtrue) >= 0.0005) {
          154                 printf("\\v'%.3fi'", vpos - vtrue);
          155                 vtrue = vpos;
          156         }
          157 }
          158 
          159 void flyback(void)        /* return to upper left corner (entry point) */
          160 {
          161         printf(".sp -1\n");
          162         htrue = vtrue = 0;
          163 }
          164 
          165 void printlf(int n, char *f)
          166 {
          167         if (f)
          168                 printf(".lf %d %s\n", n, f);
          169         else
          170                 printf(".lf %d\n", n);
          171 }
          172 
          173 void troff(char *s)        /* output troff right here */
          174 {
          175         printf("%s\n", s);
          176 }
          177 
          178 void label(char *s, int t, int nh)        /* text s of type t nh half-lines up */
          179 {
          180         int q;
          181         char *p;
          182 
          183         if (!s)
          184                 return;
          185         hvflush();
          186         dprintf("label: %s %o %d\n", s, t, nh);
          187         printf("%s", textshift);        /* shift down and left */
          188         if (t & ABOVE)
          189                 nh++;
          190         else if (t & BELOW)
          191                 nh--;
          192         if (nh)
          193                 printf("\\v'%du*\\n(.vu/2u'", -nh);
          194         /* just in case the text contains a quote: */
          195         q = 0;
          196         for (p = s; *p; p++)
          197                 if (*p == '\'') {
          198                         q = 1;
          199                         break;
          200                 }
          201         t &= ~(ABOVE|BELOW);
          202         if (t & LJUST) {
          203                 printf("%s", s);
          204         } else if (t & RJUST) {
          205                 if (q)
          206                         printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
          207                 else
          208                         printf("\\h'-\\w'%s'u'%s", s, s);
          209         } else {        /* CENTER */
          210                 if (q)
          211                         printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
          212                 else
          213                         printf("\\h'-\\w'%s'u/2u'%s", s, s);
          214         }
          215         printf("\n");
          216         flyback();
          217 }
          218 
          219 void line(double x0, double y0, double x1, double y1)        /* draw line from x0,y0 to x1,y1 */
          220 {
          221         move(x0, y0);
          222         cont(x1, y1);
          223 }
          224 
          225 void arrow(double x0, double y0, double x1, double y1, double w, double h,
          226          double ang, int nhead)         /* draw arrow (without shaft) */
          227 {
          228         double alpha, rot, drot, hyp;
          229         double dx, dy;
          230         int i;
          231 
          232         rot = atan2(w / 2, h);
          233         hyp = sqrt(w/2 * w/2 + h * h);
          234         alpha = atan2(y1-y0, x1-x0) + ang;
          235         if (nhead < 2)
          236                 nhead = 2;
          237         dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
          238         for (i = nhead-1; i >= 0; i--) {
          239                 drot = 2 * rot / (double) (nhead-1) * (double) i;
          240                 dx = hyp * cos(alpha + PI - rot + drot);
          241                 dy = hyp * sin(alpha + PI - rot + drot);
          242                 dprintf("dx,dy = %g,%g\n", dx, dy);
          243                 line(x1+dx, y1+dy, x1, y1);
          244         }
          245 }
          246 
          247 double lastgray = 0;
          248 
          249 void fillstart(double v)        /* this works only for postscript, obviously. */
          250 {                                /* uses drechsler's dpost conventions... */
          251         hvflush();
          252         printf("\\X'BeginObject %g setgray'\n", v);
          253         lastgray = v;
          254         flyback();
          255 }
          256 
          257 void fillend(int vis, int fill)
          258 {
          259         hvflush();
          260         printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
          261                 !vis ? lastgray : 0.0,
          262                 vis ? "stroke" : "");
          263         /* for dashed: [50] 0 setdash just before stroke. */
          264         lastgray = 0;
          265         flyback();
          266 }
          267 
          268 void box(double x0, double y0, double x1, double y1)
          269 {
          270         move(x0, y0);
          271         cont(x0, y1);
          272         cont(x1, y1);
          273         cont(x1, y0);
          274         cont(x0, y0);
          275 }
          276 
          277 void cont(double x, double y)        /* continue line from here to x,y */
          278 {
          279         double h1, v1;
          280         double dh, dv;
          281 
          282         h1 = xconv(x);
          283         v1 = yconv(y);
          284         dh = h1 - hpos;
          285         dv = v1 - vpos;
          286         hvflush();
          287         printf("\\D'l%.3fi %.3fi'\n", dh, dv);
          288         flyback();        /* expensive */
          289         hpos = h1;
          290         vpos = v1;
          291 }
          292 
          293 void circle(double x, double y, double r)
          294 {
          295         move(x-r, y);
          296         hvflush();
          297         printf("\\D'c%.3fi'\n", xsc(2 * r));
          298         flyback();
          299 }
          300 
          301 void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
          302 {
          303         int i;
          304         double dx, dy;
          305         double xerr, yerr;
          306 
          307         move(x, y);
          308         hvflush();
          309         xerr = yerr = 0.0;
          310         printf("\\D'~");
          311         for (i = 0; i < 2 * n; i += 2) {
          312                 dx = xsc(xerr += p[i]);
          313                 xerr -= dx/xscale;
          314                 dy = ysc(yerr += p[i+1]);
          315                 yerr -= dy/yscale;
          316                 printf(" %.3fi %.3fi", dx, -dy);        /* WATCH SIGN */
          317         }
          318         printf("'\n");
          319         flyback();
          320 }
          321 
          322 void ellipse(double x, double y, double r1, double r2)
          323 {
          324         double ir1, ir2;
          325 
          326         move(x-r1, y);
          327         hvflush();
          328         ir1 = xsc(r1);
          329         ir2 = ysc(r2);
          330         printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
          331         flyback();
          332 }
          333 
          334 void arc(double x, double y, double x0, double y0, double x1, double y1)        /* draw arc with center x,y */
          335 {
          336 
          337         move(x0, y0);
          338         hvflush();
          339         printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
          340                 xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y));        /* WATCH SIGNS */
          341         flyback();
          342 }
          343 
          344 void dot(void) {
          345         hvflush();
          346         /* what character to draw here depends on what's available. */
          347         /* on the 202, l. is good but small. */
          348         /* in general, use a smaller, shifted period and hope */
          349 
          350         printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
          351         flyback();
          352 }