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