]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/pic/pltroff.c
rio, kbdfs: increase read buffer for high latency kbdfs support
[plan9front.git] / sys / src / cmd / pic / pltroff.c
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 double fabs(double x)
148 {
149         return x < 0 ? -x : x;
150 }
151
152 void hvflush(void)      /* get to proper point for output */
153 {
154         if (fabs(hpos-htrue) >= 0.0005) {
155                 printf("\\h'%.3fi'", hpos - htrue);
156                 htrue = hpos;
157         }
158         if (fabs(vpos-vtrue) >= 0.0005) {
159                 printf("\\v'%.3fi'", vpos - vtrue);
160                 vtrue = vpos;
161         }
162 }
163
164 void flyback(void)      /* return to upper left corner (entry point) */
165 {
166         printf(".sp -1\n");
167         htrue = vtrue = 0;
168 }
169
170 void printlf(int n, char *f)
171 {
172         if (f)
173                 printf(".lf %d %s\n", n, f);
174         else
175                 printf(".lf %d\n", n);
176 }
177
178 void troff(char *s)     /* output troff right here */
179 {
180         printf("%s\n", s);
181 }
182
183 void label(char *s, int t, int nh)      /* text s of type t nh half-lines up */
184 {
185         int q;
186         char *p;
187
188         if (!s)
189                 return;
190         hvflush();
191         dprintf("label: %s %o %d\n", s, t, nh);
192         printf("%s", textshift);        /* shift down and left */
193         if (t & ABOVE)
194                 nh++;
195         else if (t & BELOW)
196                 nh--;
197         if (nh)
198                 printf("\\v'%du*\\n(.vu/2u'", -nh);
199         /* just in case the text contains a quote: */
200         q = 0;
201         for (p = s; *p; p++)
202                 if (*p == '\'') {
203                         q = 1;
204                         break;
205                 }
206         t &= ~(ABOVE|BELOW);
207         if (t & LJUST) {
208                 printf("%s", s);
209         } else if (t & RJUST) {
210                 if (q)
211                         printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
212                 else
213                         printf("\\h'-\\w'%s'u'%s", s, s);
214         } else {        /* CENTER */
215                 if (q)
216                         printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
217                 else
218                         printf("\\h'-\\w'%s'u/2u'%s", s, s);
219         }
220         printf("\n");
221         flyback();
222 }
223
224 void line(double x0, double y0, double x1, double y1)   /* draw line from x0,y0 to x1,y1 */
225 {
226         move(x0, y0);
227         cont(x1, y1);
228 }
229
230 void arrow(double x0, double y0, double x1, double y1, double w, double h,
231          double ang, int nhead)         /* draw arrow (without shaft) */
232 {
233         double alpha, rot, drot, hyp;
234         double dx, dy;
235         int i;
236
237         rot = atan2(w / 2, h);
238         hyp = sqrt(w/2 * w/2 + h * h);
239         alpha = atan2(y1-y0, x1-x0) + ang;
240         if (nhead < 2)
241                 nhead = 2;
242         dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
243         for (i = nhead-1; i >= 0; i--) {
244                 drot = 2 * rot / (double) (nhead-1) * (double) i;
245                 dx = hyp * cos(alpha + PI - rot + drot);
246                 dy = hyp * sin(alpha + PI - rot + drot);
247                 dprintf("dx,dy = %g,%g\n", dx, dy);
248                 line(x1+dx, y1+dy, x1, y1);
249         }
250 }
251
252 double lastgray = 0;
253
254 void fillstart(double v)        /* this works only for postscript, obviously. */
255 {                               /* uses drechsler's dpost conventions... */
256         hvflush();
257         printf("\\X'BeginObject %g setgray'\n", v);
258         lastgray = v;
259         flyback();
260 }
261
262 void fillend(int vis, int fill)
263 {
264         hvflush();
265         printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
266                 !vis ? lastgray : 0.0,
267                 vis ? "stroke" : "");
268         /* for dashed: [50] 0 setdash just before stroke. */
269         lastgray = 0;
270         flyback();
271 }
272
273 void box(double x0, double y0, double x1, double y1)
274 {
275         move(x0, y0);
276         cont(x0, y1);
277         cont(x1, y1);
278         cont(x1, y0);
279         cont(x0, y0);
280 }
281
282 void cont(double x, double y)   /* continue line from here to x,y */
283 {
284         double h1, v1;
285         double dh, dv;
286
287         h1 = xconv(x);
288         v1 = yconv(y);
289         dh = h1 - hpos;
290         dv = v1 - vpos;
291         hvflush();
292         printf("\\D'l%.3fi %.3fi'\n", dh, dv);
293         flyback();      /* expensive */
294         hpos = h1;
295         vpos = v1;
296 }
297
298 void circle(double x, double y, double r)
299 {
300         move(x-r, y);
301         hvflush();
302         printf("\\D'c%.3fi'\n", xsc(2 * r));
303         flyback();
304 }
305
306 void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
307 {
308         int i;
309         double dx, dy;
310         double xerr, yerr;
311
312         move(x, y);
313         hvflush();
314         xerr = yerr = 0.0;
315         printf("\\D'~");
316         for (i = 0; i < 2 * n; i += 2) {
317                 dx = xsc(xerr += p[i]);
318                 xerr -= dx/xscale;
319                 dy = ysc(yerr += p[i+1]);
320                 yerr -= dy/yscale;
321                 printf(" %.3fi %.3fi", dx, -dy);        /* WATCH SIGN */
322         }
323         printf("'\n");
324         flyback();
325 }
326
327 void ellipse(double x, double y, double r1, double r2)
328 {
329         double ir1, ir2;
330
331         move(x-r1, y);
332         hvflush();
333         ir1 = xsc(r1);
334         ir2 = ysc(r2);
335         printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
336         flyback();
337 }
338
339 void arc(double x, double y, double x0, double y0, double x1, double y1)        /* draw arc with center x,y */
340 {
341
342         move(x0, y0);
343         hvflush();
344         printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
345                 xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y));  /* WATCH SIGNS */
346         flyback();
347 }
348
349 void dot(void) {
350         hvflush();
351         /* what character to draw here depends on what's available. */
352         /* on the 202, l. is good but small. */
353         /* in general, use a smaller, shifted period and hope */
354
355         printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
356         flyback();
357 }