1*45c5cf59Sslatteng /* pltroff.c	(Berkeley)	1.5	83/10/07
2b50294ceSslatteng  *	This version has code generators to drive the old-style troff
3b50294ceSslatteng  *	that produces output for the Graphic Systems C/A/T.
4b50294ceSslatteng  *	Very few people actually have a C/A/T; they instead typically
5b50294ceSslatteng  *	use some other typesetter that simulates it.  This is slow and
6b50294ceSslatteng  *	rather silly, but compatibility with the past is important.
7b50294ceSslatteng  *	Or so they say.  Anyway ...
8b50294ceSslatteng 
9b50294ceSslatteng  *	The code generator can be turned on to old-style troff by setting
10b50294ceSslatteng  *	the constant OLDTROFF with a #define statement;  this will also
11b50294ceSslatteng  *	have the effect of setting the default typesetter to the C/A/T
12b50294ceSslatteng  *	in a consistent manner.
13b50294ceSslatteng  */
14b50294ceSslatteng 
15b50294ceSslatteng #include <stdio.h>
16b50294ceSslatteng #include <math.h>
17b50294ceSslatteng extern int dbg;
18b50294ceSslatteng 
19b50294ceSslatteng /* this is the place to define OLDTROFF if you're going to */
20b50294ceSslatteng #ifdef	OLDTROFF
21b50294ceSslatteng #	define	OLDSTYLE	1
22*45c5cf59Sslatteng #	define  MAXMOT		8192
23b50294ceSslatteng #else
24b50294ceSslatteng #	define	OLDSTYLE	0
25*45c5cf59Sslatteng #	define  MAXMOT		32768
26b50294ceSslatteng #endif
27b50294ceSslatteng 
28b50294ceSslatteng #define	abs(n)	(n >= 0 ? n : -(n))
29b50294ceSslatteng #define	max(x,y)	((x)>(y) ? (x) : (y))
30b50294ceSslatteng #define	PI	3.141592654
31b50294ceSslatteng #define	PI2	PI/2
32b50294ceSslatteng 
33b50294ceSslatteng extern	int	res;
34b50294ceSslatteng extern	int	DX;	/* step size in x */
35b50294ceSslatteng extern	int	DY;	/* step size in y */
36b50294ceSslatteng 
37b50294ceSslatteng int	minline	= 245;	/* draw lines shorter than this with dots on 202 */
38b50294ceSslatteng 			/* ought to be point-size dependent, but what's that? */
39b50294ceSslatteng 			/* this is big enough to handle 202 up to 36 points */
40b50294ceSslatteng int	drawdot	= '.';	/* character to use when drawing */
41b50294ceSslatteng 
42b50294ceSslatteng int	useDline	= 1;	/* if set, produce \D for all lines */
43b50294ceSslatteng extern	float	hshift;	/* how much to move left by for text */
44b50294ceSslatteng extern	float	vshift;	/* how much down */
45b50294ceSslatteng 
46b50294ceSslatteng /* scaling stuff, specific to typesetter */
47b50294ceSslatteng /* defined by s command as X0,Y0 to X1,Y1 */
48b50294ceSslatteng /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
49b50294ceSslatteng /* default output is 6x6 inches */
50b50294ceSslatteng 
51b50294ceSslatteng 
52b50294ceSslatteng float	xscale;
53b50294ceSslatteng float	yscale;
54b50294ceSslatteng 
55b50294ceSslatteng int	hpos	= 0;	/* current horizontal position in output coordinate system */
56b50294ceSslatteng int	vpos	= 0;	/* current vertical position; 0 is top of page */
57b50294ceSslatteng 
58b50294ceSslatteng int	htrue	= 0;	/* where we really are */
59b50294ceSslatteng int	vtrue	= 0;
60b50294ceSslatteng 
61b50294ceSslatteng float	X0, Y0;		/* left bottom of input */
62b50294ceSslatteng float	X1, Y1;		/* right top of input */
63b50294ceSslatteng 
64b50294ceSslatteng int	hmax;		/* right end of output */
65b50294ceSslatteng int	vmax;		/* top of output (down is positive) */
66b50294ceSslatteng 
67b50294ceSslatteng extern	float	deltx;
68b50294ceSslatteng extern	float	delty;
69ef733981Sslatteng extern	float	xbound;
70ef733981Sslatteng extern	float	ybound;
71b50294ceSslatteng extern	float	xmin, ymin, xmax, ymax, sxmin, symin, sxmax, symax;
72b50294ceSslatteng extern	int	crop;
73b50294ceSslatteng 
openpl(s)74b50294ceSslatteng openpl(s)	/* initialize device */
75b50294ceSslatteng 	char *s;	/* residue of .PS invocation line */
76b50294ceSslatteng {
77b50294ceSslatteng 	float maxdelt;
78b50294ceSslatteng 
79b50294ceSslatteng 	hpos = vpos = 0;
80b50294ceSslatteng 	hmax = vmax = 6 * res;	/* default = 6 x 6 */
81ef733981Sslatteng 	if (deltx > xbound) {		/* default 8 inches */
82b50294ceSslatteng 		fprintf(stderr, "pic: %g X %g picture shrunk to", deltx, delty);
83ef733981Sslatteng 		deltx *= xbound/deltx;
84ef733981Sslatteng 		delty *= xbound/deltx;
85ef733981Sslatteng 		fprintf(stderr, " %g X %g\n", deltx, delty);
86ef733981Sslatteng 	}
87ef733981Sslatteng 	if (delty > ybound) {		/* default 10 inches */
88ef733981Sslatteng 		fprintf(stderr, "pic: %g X %g picture shrunk to", deltx, delty);
89ef733981Sslatteng 		deltx *= ybound/delty;
90ef733981Sslatteng 		delty *= ybound/delty;
91b50294ceSslatteng 		fprintf(stderr, " %g X %g\n", deltx, delty);
92b50294ceSslatteng 	}
93b50294ceSslatteng 	if (deltx > 0 && delty > 0) {	/* have to change default size */
94b50294ceSslatteng 		hmax = res * deltx;
95b50294ceSslatteng 		vmax = res * delty;
96b50294ceSslatteng 	}
97b50294ceSslatteng 	if (crop) {
98b50294ceSslatteng 		if (xmax == xmin)
99b50294ceSslatteng 			space(xmin, ymin, xmin + ymax-ymin, ymax);
100b50294ceSslatteng 		else
101b50294ceSslatteng 			space(xmin, ymin, xmax, ymin + xmax-xmin);	/* assumes 1:1 aspect ratio */
102b50294ceSslatteng 	}
103b50294ceSslatteng 	else
104b50294ceSslatteng 		space(sxmin, symin, sxmax, symax);
105b50294ceSslatteng 	printf("... %g %g %g %g %g %g %g %g\n",
106b50294ceSslatteng 		xmin, ymin, xmax, ymax, sxmin, symin, sxmax, symax);
107b50294ceSslatteng 	printf("... %du %du %du %du %du %du %du %du\n",
108b50294ceSslatteng 		xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax),
109b50294ceSslatteng 		xconv(sxmin), yconv(symin), xconv(sxmax), yconv(symax));
110b50294ceSslatteng 	printf(".PS %d %d %s", yconv(ymin), xconv(xmax), s);
111b50294ceSslatteng 		/* assumes \n comes as part of s */
112*45c5cf59Sslatteng 	if (xconv(xmax) >= MAXMOT || yconv(ymax) >= MAXMOT) {	/* internal troff limit: 15 bits for motion */
113b50294ceSslatteng 		fprintf(stderr, "picture too high or wide");
114b50294ceSslatteng 		exit(1);
115b50294ceSslatteng 	}
116b50294ceSslatteng 	printf(".br\n");
117b50294ceSslatteng }
118b50294ceSslatteng 
closepl(type)119b50294ceSslatteng closepl(type)	/* clean up after finished */
120b50294ceSslatteng {
121b50294ceSslatteng 	movehv(0, 0);	/* get back to where we started */
122b50294ceSslatteng 	if (type == 'F')
123b50294ceSslatteng 		printf(".PF\n");
124b50294ceSslatteng 	else {
125b50294ceSslatteng 		printf(".sp 1+%du\n", yconv(ymin));
126b50294ceSslatteng 		printf(".PE\n");
127b50294ceSslatteng 	}
128b50294ceSslatteng }
129b50294ceSslatteng 
move(x,y)130b50294ceSslatteng move(x, y)	/* go to position x, y in external coords */
131b50294ceSslatteng 	float x, y;
132b50294ceSslatteng {
133b50294ceSslatteng 	hgoto(xconv(x));
134b50294ceSslatteng 	vgoto(yconv(y));
135b50294ceSslatteng }
136b50294ceSslatteng 
movehv(h,v)137b50294ceSslatteng movehv(h, v)	/* go to internal position h, v */
138b50294ceSslatteng 	int h, v;
139b50294ceSslatteng {
140b50294ceSslatteng 	hgoto(h);
141b50294ceSslatteng 	vgoto(v);
142b50294ceSslatteng }
143b50294ceSslatteng 
hmot(n)144b50294ceSslatteng hmot(n)	/* generate n units of horizontal motion */
145b50294ceSslatteng 	int n;
146b50294ceSslatteng {
147b50294ceSslatteng 	hpos += n;
148b50294ceSslatteng }
149b50294ceSslatteng 
vmot(n)150b50294ceSslatteng vmot(n)	/* generate n units of vertical motion */
151b50294ceSslatteng 	int n;
152b50294ceSslatteng {
153b50294ceSslatteng 	vpos += n;
154b50294ceSslatteng }
155b50294ceSslatteng 
hgoto(n)156b50294ceSslatteng hgoto(n)
157b50294ceSslatteng {
158b50294ceSslatteng 	hpos = n;
159b50294ceSslatteng }
160b50294ceSslatteng 
vgoto(n)161b50294ceSslatteng vgoto(n)
162b50294ceSslatteng {
163b50294ceSslatteng 	vpos = n;
164b50294ceSslatteng }
165b50294ceSslatteng 
hvflush()166b50294ceSslatteng hvflush()	/* get to proper point for output */
167b50294ceSslatteng {
168b50294ceSslatteng 	if (hpos != htrue) {
169b50294ceSslatteng 		printf("\\h'%du'", hpos - htrue);
170b50294ceSslatteng 		htrue = hpos;
171b50294ceSslatteng 	}
172b50294ceSslatteng 	if (vpos != vtrue) {
173b50294ceSslatteng 		printf("\\v'%du'", vpos - vtrue);
174b50294ceSslatteng 		vtrue = vpos;
175b50294ceSslatteng 	}
176b50294ceSslatteng }
177b50294ceSslatteng 
flyback()178b50294ceSslatteng flyback()	/* return to upper left corner (entry point) */
179b50294ceSslatteng {
180b50294ceSslatteng 	printf(".sp -1\n");
181b50294ceSslatteng 	htrue = vtrue = 0;
182b50294ceSslatteng }
183b50294ceSslatteng 
troff(s)184b50294ceSslatteng troff(s)	/* output troff right here */
185b50294ceSslatteng 	char *s;
186b50294ceSslatteng {
187b50294ceSslatteng 	printf("%s\n", s);
188b50294ceSslatteng }
189b50294ceSslatteng 
label(s,t,nh)190b50294ceSslatteng label(s, t, nh)	/* text s of type t nh half-lines up */
191b50294ceSslatteng 	char *s;
192b50294ceSslatteng 	int t, nh;
193b50294ceSslatteng {
194b50294ceSslatteng 	int q;
195b50294ceSslatteng 	char *p;
196b50294ceSslatteng 
197b50294ceSslatteng 	hvflush();
198b50294ceSslatteng 	printf("\\h'-%.1fm'\\v'%.1fm'", hshift, vshift);	/* shift down and left */
199b50294ceSslatteng 			/*  .3 .3 is best for PO in circuit diagrams */
200b50294ceSslatteng 	if (t == 'A')
201b50294ceSslatteng 		nh++;
202b50294ceSslatteng 	else if (t == 'B')
203b50294ceSslatteng 		nh--;
204b50294ceSslatteng 	if (nh)
205b50294ceSslatteng 		printf("\\v'%du*\\n(.vu/2u'", -nh);
206b50294ceSslatteng 	/* just in case the text contains a quote: */
207b50294ceSslatteng 	q = 0;
208b50294ceSslatteng 	for (p = s; *p; p++)
209b50294ceSslatteng 		if (*p == '\'') {
210b50294ceSslatteng 			q = 1;
211b50294ceSslatteng 			break;
212b50294ceSslatteng 		}
213b50294ceSslatteng 	switch (t) {
214b50294ceSslatteng 	case 'L':
215b50294ceSslatteng 	default:
216b50294ceSslatteng 		printf("%s", s);
217b50294ceSslatteng 		break;
218b50294ceSslatteng 	case 'C':
219b50294ceSslatteng 	case 'A':
220b50294ceSslatteng 	case 'B':
221b50294ceSslatteng 		if (q)
222b50294ceSslatteng 			printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts", s, s, s);
223b50294ceSslatteng 		else
224b50294ceSslatteng 			printf("\\h'-\\w'%s'u/2u'%s\\h'-\\w'%s'u/2u'", s, s, s);
225b50294ceSslatteng 		break;
226b50294ceSslatteng 	case 'R':
227b50294ceSslatteng 		if (q)
228b50294ceSslatteng 			printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
229b50294ceSslatteng 		else
230b50294ceSslatteng 			printf("\\h'-\\w'%s'u'%s", s, s);
231b50294ceSslatteng 		break;
232b50294ceSslatteng 	}
233b50294ceSslatteng 	/* don't need these if flyback called immediately */
234b50294ceSslatteng 	printf("\n");
235b50294ceSslatteng 	flyback();
236b50294ceSslatteng }
237b50294ceSslatteng 
line(x0,y0,x1,y1)238b50294ceSslatteng line(x0, y0, x1, y1)	/* draw line from x0,y0 to x1,y1 */
239b50294ceSslatteng 	float x0, y0, x1, y1;
240b50294ceSslatteng {
241b50294ceSslatteng 	move(x0, y0);
242b50294ceSslatteng 	cont(x1, y1);
243b50294ceSslatteng }
244b50294ceSslatteng 
arrow(x0,y0,x1,y1,w,h)245b50294ceSslatteng arrow(x0, y0, x1, y1, w, h)	/* draw arrow (without line), head wid w & len h */
246b50294ceSslatteng 	float x0, y0, x1, y1, w, h;
247b50294ceSslatteng {
248b50294ceSslatteng 	double alpha, rot, hyp;
249b50294ceSslatteng 	float dx, dy;
250b50294ceSslatteng 
251b50294ceSslatteng 	rot = atan2( w / 2, h );
252b50294ceSslatteng 	hyp = sqrt(w/2 * w/2 + h * h);
253b50294ceSslatteng 	alpha = atan2(y1-y0, x1-x0);
254b50294ceSslatteng 	if (dbg)
255b50294ceSslatteng 		printf("rot=%f, hyp=%f, alpha=%f\n", rot, hyp, alpha);
256b50294ceSslatteng 	dx = hyp * cos(alpha + PI + rot);
257b50294ceSslatteng 	dy = hyp * sin(alpha + PI + rot);
258b50294ceSslatteng 	if (dbg) printf("dx,dy = %g,%g\n", dx, dy);
259b50294ceSslatteng 	line(x1+dx, y1+dy, x1, y1);
260b50294ceSslatteng 	dx = hyp * cos(alpha + PI - rot);
261b50294ceSslatteng 	dy = hyp * sin(alpha + PI - rot);
262b50294ceSslatteng 	if (dbg) printf("dx,dy = %g,%g\n", dx, dy);
263b50294ceSslatteng 	line(x1+dx, y1+dy, x1, y1);
264b50294ceSslatteng }
265b50294ceSslatteng 
box(x0,y0,x1,y1)266b50294ceSslatteng box(x0, y0, x1, y1)
267b50294ceSslatteng 	float x0, y0, x1, y1;
268b50294ceSslatteng {
269b50294ceSslatteng 	move(x0, y0);
270b50294ceSslatteng 	cont(x0, y1);
271b50294ceSslatteng 	cont(x1, y1);
272b50294ceSslatteng 	cont(x1, y0);
273b50294ceSslatteng 	cont(x0, y0);
274b50294ceSslatteng }
275b50294ceSslatteng 
cont(x,y)276b50294ceSslatteng cont(x, y)	/* continue line from here to x,y */
277b50294ceSslatteng 	float x, y;
278b50294ceSslatteng {
279b50294ceSslatteng 	int h1, v1;
280b50294ceSslatteng 	int dh, dv;
281b50294ceSslatteng 
282b50294ceSslatteng 	h1 = xconv(x);
283b50294ceSslatteng 	v1 = yconv(y);
284b50294ceSslatteng 	dh = h1 - hpos;
285b50294ceSslatteng 	dv = v1 - vpos;
286b50294ceSslatteng 	downsize();
287b50294ceSslatteng 	hvflush();
288b50294ceSslatteng 	if (!useDline && dv == 0 && abs(dh) > minline)	/* horizontal */
289b50294ceSslatteng 		printf("\\l'%du'\n", dh);
290b50294ceSslatteng 	else if (!useDline && dh == 0 && abs(dv) > minline) {	/* vertical */
291dc34213eSslatteng 		printf("\\v'-.25m'\\L'%du\\(br'\\v'.25m'\n", dv);
292dc34213eSslatteng 					/* add -.25m correction if use \(br */
293b50294ceSslatteng 	} else {
294b50294ceSslatteng 		if (OLDSTYLE)
295b50294ceSslatteng 			drawline(dh, dv);
296b50294ceSslatteng 		else
297b50294ceSslatteng 			printf("\\D'l%du %du'\n", dh, dv);
298b50294ceSslatteng 	}
299b50294ceSslatteng 	upsize();
300b50294ceSslatteng 	flyback();	/* expensive */
301b50294ceSslatteng 	hpos = h1;
302b50294ceSslatteng 	vpos = v1;
303b50294ceSslatteng }
304b50294ceSslatteng 
circle(x,y,r)305b50294ceSslatteng circle(x, y, r)
306b50294ceSslatteng 	float x, y, r;
307b50294ceSslatteng {
308b50294ceSslatteng 	int d;
309b50294ceSslatteng 
310b50294ceSslatteng 	downsize();
311b50294ceSslatteng 	d = xsc(2 * r);
312b50294ceSslatteng 	move(x-r, y);
313b50294ceSslatteng 	hvflush();
314b50294ceSslatteng 	if (OLDSTYLE)
315b50294ceSslatteng 		drawcircle(d);
316b50294ceSslatteng 	else
317b50294ceSslatteng 		printf("\\D'c%du'\n", d);
318b50294ceSslatteng 	upsize();
319b50294ceSslatteng 	flyback();
320b50294ceSslatteng }
321b50294ceSslatteng 
spline(x,y,n,p)322b50294ceSslatteng spline(x, y, n, p)
323b50294ceSslatteng 	float x, y, *p;
324b50294ceSslatteng 	float n;
325b50294ceSslatteng {
326b50294ceSslatteng 	int i, j, dx, dy;
327b50294ceSslatteng 	char temp[1000];
328b50294ceSslatteng 
329b50294ceSslatteng 	downsize();
330b50294ceSslatteng 	move(x, y);
331b50294ceSslatteng 	hvflush();
332b50294ceSslatteng 	if (OLDSTYLE) {
333b50294ceSslatteng 		temp[0] = 0;
334b50294ceSslatteng 		for (i = 0; i < 2 * n; i += 2) {
335b50294ceSslatteng 			dx = xsc(p[i]);
336b50294ceSslatteng 			dy = ysc(p[i+1]);
337b50294ceSslatteng 			sprintf(&temp[strlen(temp)], " %d %d", dx, dy);
338b50294ceSslatteng 		}
339b50294ceSslatteng 		drawspline(temp);
340b50294ceSslatteng 	}
341b50294ceSslatteng 	else {
342b50294ceSslatteng 		printf("\\D'~");
343b50294ceSslatteng 		for (i = 0; i < 2 * n; i += 2) {
344b50294ceSslatteng 			dx = xsc(p[i]);
345b50294ceSslatteng 			dy = ysc(p[i+1]);
346b50294ceSslatteng 			printf(" %du %du", dx, dy);
347b50294ceSslatteng 		}
348b50294ceSslatteng 		printf("'\n");
349b50294ceSslatteng 	}
350b50294ceSslatteng 	upsize();
351b50294ceSslatteng 	flyback();
352b50294ceSslatteng }
353b50294ceSslatteng 
ellipse(x,y,r1,r2)354b50294ceSslatteng ellipse(x, y, r1, r2)
355b50294ceSslatteng 	float x, y, r1, r2;
356b50294ceSslatteng {
357b50294ceSslatteng 	int ir1, ir2;
358b50294ceSslatteng 
359b50294ceSslatteng 	downsize();
360b50294ceSslatteng 	move(x-r1, y);
361b50294ceSslatteng 	hvflush();
362b50294ceSslatteng 	ir1 = xsc(r1);
363b50294ceSslatteng 	ir2 = ysc(r2);
364b50294ceSslatteng 	if (OLDSTYLE)
365b50294ceSslatteng 		drawellipse(2 * ir1, 2 * abs(ir2));
366b50294ceSslatteng 	else
367b50294ceSslatteng 		printf("\\D'e%du %du'\n", 2 * ir1, 2 * abs(ir2));
368b50294ceSslatteng 	upsize();
369b50294ceSslatteng 	flyback();
370b50294ceSslatteng }
371b50294ceSslatteng 
arc(x,y,x0,y0,x1,y1,r)372b50294ceSslatteng arc(x, y, x0, y0, x1, y1, r)	/* draw arc with center x,y */
373b50294ceSslatteng 	float x, y, x0, y0, x1, y1, r;
374b50294ceSslatteng {
375b50294ceSslatteng 
376b50294ceSslatteng 	downsize();
377b50294ceSslatteng 	move(x0, y0);
378b50294ceSslatteng 	hvflush();
379b50294ceSslatteng 	if (OLDSTYLE) {
380b50294ceSslatteng 		drawarc(xsc(x1-x0), ysc(y1-y0), xsc(r));
381b50294ceSslatteng 	} else {
382b50294ceSslatteng 		printf("\\D'a%du %du %du %du'\n",
383b50294ceSslatteng 			xsc(x-x0), ysc(y-y0), xsc(x1-x), ysc(y1-y));
384b50294ceSslatteng 	}
385b50294ceSslatteng 	upsize();
386b50294ceSslatteng 	flyback();
387b50294ceSslatteng }
388b50294ceSslatteng 
erase()389b50294ceSslatteng erase()	/* get to bottom of frame */
390b50294ceSslatteng {
391b50294ceSslatteng 	return;	/* for now, ignore them */
392b50294ceSslatteng }
393b50294ceSslatteng 
point(x,y)394b50294ceSslatteng point(x, y)	/* put point at x,y */
395b50294ceSslatteng 	float x, y;
396b50294ceSslatteng {
397b50294ceSslatteng 	static char *temp = ".";
398b50294ceSslatteng 
399b50294ceSslatteng 	move(x, y);
400b50294ceSslatteng 	label(temp, 'L');
401b50294ceSslatteng }
402b50294ceSslatteng 
space(x0,y0,x1,y1)403b50294ceSslatteng space(x0, y0, x1, y1)	/* set limits of page */
404b50294ceSslatteng 	float x0, y0, x1, y1;
405b50294ceSslatteng {
406b50294ceSslatteng 	if (x0 == x1)
407b50294ceSslatteng 		x1 = x0 + 1;
408b50294ceSslatteng 	if (y0 == y1)
409b50294ceSslatteng 		y1 = y0 - 1;	/* kludge */
410b50294ceSslatteng 	X0 = x0;
411b50294ceSslatteng 	Y0 = y0;
412b50294ceSslatteng 	X1 = x1;
413b50294ceSslatteng 	Y1 = y1;
414b50294ceSslatteng 	xscale = hmax / (X1-X0);
415b50294ceSslatteng 	yscale = vmax / (Y0-Y1);
416b50294ceSslatteng }
417b50294ceSslatteng 
xconv(x)418b50294ceSslatteng xconv(x)	/* convert x from external to internal form */
419b50294ceSslatteng 	float x;
420b50294ceSslatteng {
421b50294ceSslatteng 	int v;
422b50294ceSslatteng 
423b50294ceSslatteng 	v = (x-X0) * xscale + 0.5;
424b50294ceSslatteng 	if (OLDSTYLE) {
425b50294ceSslatteng 		v = (v + DX - 1) / DX;
426b50294ceSslatteng 		v *= DX;
427b50294ceSslatteng 	}
428b50294ceSslatteng 	return v;
429b50294ceSslatteng }
430b50294ceSslatteng 
xsc(x)431b50294ceSslatteng xsc(x)	/* convert x from external to internal form, scaling only */
432b50294ceSslatteng 	float x;
433b50294ceSslatteng {
434b50294ceSslatteng 	int v;
435b50294ceSslatteng 
436b50294ceSslatteng 	v = (x) * xscale + 0.5;
437b50294ceSslatteng 	if (OLDSTYLE) {
438b50294ceSslatteng 		v = (v + DX - 1) / DX;
439b50294ceSslatteng 		v *= DX;
440b50294ceSslatteng 	}
441b50294ceSslatteng 	return v;
442b50294ceSslatteng }
443b50294ceSslatteng 
yconv(y)444b50294ceSslatteng yconv(y)	/* convert y from external to internal form */
445b50294ceSslatteng 	float y;
446b50294ceSslatteng {
447b50294ceSslatteng 	int v;
448b50294ceSslatteng 
449b50294ceSslatteng 	y += Y1 - ymax;
450b50294ceSslatteng 	v = (y-Y1) * yscale + 0.5;
451b50294ceSslatteng 	if (OLDSTYLE) {
452b50294ceSslatteng 		v = (v + DY - 1) / DY;
453b50294ceSslatteng 		v *= DY;
454b50294ceSslatteng 	}
455b50294ceSslatteng 	return v;
456b50294ceSslatteng }
457b50294ceSslatteng 
ysc(y)458b50294ceSslatteng ysc(y)	/* convert y from external to internal form, scaling only */
459b50294ceSslatteng 	float y;
460b50294ceSslatteng {
461b50294ceSslatteng 	int v;
462b50294ceSslatteng 
463b50294ceSslatteng 	v = (y) * yscale + 0.5;
464b50294ceSslatteng 	if (OLDSTYLE) {
465b50294ceSslatteng 		v = (v + DY - 1) / DY;
466b50294ceSslatteng 		v *= DY;
467b50294ceSslatteng 	}
468b50294ceSslatteng 	return v;
469b50294ceSslatteng }
470b50294ceSslatteng 
linemod(s)471b50294ceSslatteng linemod(s)
472b50294ceSslatteng 	char *s;
473b50294ceSslatteng {
474b50294ceSslatteng }
475b50294ceSslatteng 
dot()476b50294ceSslatteng dot() {
477b50294ceSslatteng 	hvflush();
478*45c5cf59Sslatteng 	if (OLDSTYLE) printf("\\&.\n");
479*45c5cf59Sslatteng 	else printf("\\D'l 0 0'\n");
480b50294ceSslatteng 	flyback();
481b50294ceSslatteng }
482b50294ceSslatteng 
483b50294ceSslatteng #ifndef	OLDTROFF
484b50294ceSslatteng 
485b50294ceSslatteng 	/* satisfy the loader... */
486b50294ceSslatteng 
drawline()487b50294ceSslatteng drawline(){;}
drawcircle()488b50294ceSslatteng drawcircle(){;}
drawspline()489b50294ceSslatteng drawspline(){;}
drawellipse()490b50294ceSslatteng drawellipse(){;}
drawarc()491b50294ceSslatteng drawarc(){;}
upsize()492b50294ceSslatteng upsize(){;}
downsize()493b50294ceSslatteng downsize(){;}
494b50294ceSslatteng 
495b50294ceSslatteng #endif
496b50294ceSslatteng 
497b50294ceSslatteng #ifdef	OLDTROFF
498b50294ceSslatteng 
499b50294ceSslatteng 	/* these are for real */
500b50294ceSslatteng 
501b50294ceSslatteng int	drawsize	= 2;	/* shrink point size by this factor */
502b50294ceSslatteng 
503b50294ceSslatteng #define	sgn(n)	((n > 0) ? 1 : ((n < 0) ? -1 : 0))
504b50294ceSslatteng #define	arcmove(x,y)	{ hgoto(x); vmot(-vpos-(y)); }
505b50294ceSslatteng 
put1(c)506b50294ceSslatteng put1(c) /* output one character, usually a dot */
507b50294ceSslatteng {
508b50294ceSslatteng 	static int nput = 0;
509b50294ceSslatteng 
510b50294ceSslatteng 	if (nput++ > 100) {	/* crude approx: troff input buffer ~ 400 */
511b50294ceSslatteng 		nput = 0;
512b50294ceSslatteng 		printf("\n");	/* someday this will give a spurious break */
513b50294ceSslatteng 		flyback();
514b50294ceSslatteng 		printf("\\\&");
515b50294ceSslatteng 	}
516b50294ceSslatteng 	hvflush();	/* crude! */
517b50294ceSslatteng 	printf("\\z%c", c);
518b50294ceSslatteng }
519b50294ceSslatteng 
downsize()520b50294ceSslatteng downsize()	/* set size lower to make it lighter */
521b50294ceSslatteng {
522b50294ceSslatteng 	if (drawsize != 1) {
523b50294ceSslatteng 		printf(".nr .. \\n(.s/%d\n", drawsize);
524b50294ceSslatteng 		printf(".ps \\n(..\n");
525b50294ceSslatteng 	}
526b50294ceSslatteng }
527b50294ceSslatteng 
upsize()528b50294ceSslatteng upsize()	/* undo downsize */
529b50294ceSslatteng {
530b50294ceSslatteng 	printf(".ps\n");	/* God help anyone who fiddles .ps */
531b50294ceSslatteng }
532b50294ceSslatteng 
drawline(dx,dy)533b50294ceSslatteng drawline(dx, dy)	/* draw line from here to dx, dy */
534b50294ceSslatteng int dx, dy;
535b50294ceSslatteng {
536b50294ceSslatteng 	int xd, yd;
537b50294ceSslatteng 	float val, slope;
538b50294ceSslatteng 	int i, numdots;
539b50294ceSslatteng 	int dirmot, perp;
540b50294ceSslatteng 	int motincr, perpincr;
541b50294ceSslatteng 	int ohpos, ovpos, osize;
542b50294ceSslatteng 	float incrway;
543b50294ceSslatteng 
544b50294ceSslatteng         ohpos = hpos;
545b50294ceSslatteng 	ovpos = vpos;
546b50294ceSslatteng 	xd = dx / DX;
547b50294ceSslatteng 	yd = dy / DX;
548b50294ceSslatteng 	printf("\\\&");
549b50294ceSslatteng 	put1(drawdot);
550b50294ceSslatteng 	if (xd == 0) {
551b50294ceSslatteng 		numdots = abs (yd);
552b50294ceSslatteng 		motincr = DX * sgn (yd);
553b50294ceSslatteng 		for (i = 0; i < numdots; i++) {
554b50294ceSslatteng 			vmot(motincr);
555b50294ceSslatteng 			put1(drawdot);
556b50294ceSslatteng 		}
557b50294ceSslatteng 		vgoto(ovpos + dy);
558b50294ceSslatteng 		printf("\n");
559b50294ceSslatteng 		return;
560b50294ceSslatteng 	}
561b50294ceSslatteng 	if (yd == 0) {
562b50294ceSslatteng 		numdots = abs (xd);
563b50294ceSslatteng 		motincr = DX * sgn (xd);
564b50294ceSslatteng 		for (i = 0; i < numdots; i++) {
565b50294ceSslatteng 			hmot(motincr);
566b50294ceSslatteng 			put1(drawdot);
567b50294ceSslatteng 		}
568b50294ceSslatteng 		hgoto(ohpos + dx);
569b50294ceSslatteng 		printf("\n");
570b50294ceSslatteng 		return;
571b50294ceSslatteng 	}
572b50294ceSslatteng 	if (abs (xd) > abs (yd)) {
573b50294ceSslatteng 		val = slope = (float) xd/yd;
574b50294ceSslatteng 		numdots = abs (xd);
575b50294ceSslatteng 		dirmot = 'h';
576b50294ceSslatteng 		perp = 'v';
577b50294ceSslatteng 		motincr = DX * sgn (xd);
578b50294ceSslatteng 		perpincr = DX * sgn (yd);
579b50294ceSslatteng 	}
580b50294ceSslatteng 	else {
581b50294ceSslatteng 		val = slope = (float) yd/xd;
582b50294ceSslatteng 		numdots = abs (yd);
583b50294ceSslatteng 		dirmot = 'v';
584b50294ceSslatteng 		perp = 'h';
585b50294ceSslatteng 		motincr = DX * sgn (yd);
586b50294ceSslatteng 		perpincr = DX * sgn (xd);
587b50294ceSslatteng 	}
588b50294ceSslatteng 	incrway = sgn ((int) slope);
589b50294ceSslatteng 	for (i = 0; i < numdots; i++) {
590b50294ceSslatteng 		val -= incrway;
591b50294ceSslatteng 		if (dirmot == 'h')
592b50294ceSslatteng 			hmot(motincr);
593b50294ceSslatteng 		else
594b50294ceSslatteng 			vmot(motincr);
595b50294ceSslatteng 		if (val * slope < 0) {
596b50294ceSslatteng 			if (perp == 'h')
597b50294ceSslatteng 				hmot(perpincr);
598b50294ceSslatteng 			else
599b50294ceSslatteng 				vmot(perpincr);
600b50294ceSslatteng 			val += slope;
601b50294ceSslatteng 		}
602b50294ceSslatteng 		put1(drawdot);
603b50294ceSslatteng 	}
604b50294ceSslatteng 	hgoto(ohpos + dx);
605b50294ceSslatteng 	vgoto(ovpos + dy);
606b50294ceSslatteng 	printf("\n");
607b50294ceSslatteng }
608b50294ceSslatteng 
drawspline(s)609b50294ceSslatteng drawspline(s)	/* draw spline curve */
610b50294ceSslatteng 	char *s;
611b50294ceSslatteng {
612b50294ceSslatteng 	int x[50], y[50], xp, yp, pxp, pyp;
613b50294ceSslatteng 	float t1, t2, t3, w;
614b50294ceSslatteng 	int i, j, steps, N, prevsteps;
615b50294ceSslatteng 
616b50294ceSslatteng 	N = sscanf(s, "%d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d ",
617b50294ceSslatteng 	&x[2], &y[2], &x[3], &y[3], &x[4], &y[4], &x[5], &y[5], &x[6], &y[6], &x[7], &y[7], &x[8], &y[8], &x[9], &y[9], &x[10], &y[10], &x[11], &y[11], &x[12], &y[12],
618b50294ceSslatteng &x[13], &y[13], &x[14], &y[14], &x[15], &y[15], &x[16], &y[16], &x[17], &y[17], &x[18], &y[18], &x[19], &y[19], &x[20], &y[20], &x[21], &y[21], &x[22], &y[22], &x[23], &y[23], &x[24], &y[24],
619b50294ceSslatteng &x[25], &y[25], &x[26], &y[26], &x[27], &y[27], &x[28], &y[28], &x[29], &y[29], &x[30], &y[30], &x[31], &y[31], &x[32], &y[32], &x[33], &y[33], &x[34], &y[34], &x[35], &y[35], &x[36], &y[36],
620b50294ceSslatteng &x[37], &y[37]);
621b50294ceSslatteng 	N = N/2 + 2;
622b50294ceSslatteng 	x[0] = x[1] = hpos;
623b50294ceSslatteng 	y[0] = y[1] = vpos;
624b50294ceSslatteng 	for (i = 1; i < N; i++) {
625b50294ceSslatteng 		x[i+1] += x[i];
626b50294ceSslatteng 		y[i+1] += y[i];
627b50294ceSslatteng 	}
628b50294ceSslatteng 	x[N] = x[N-1];
629b50294ceSslatteng 	y[N] = y[N-1];
630b50294ceSslatteng 	prevsteps = 0;
631b50294ceSslatteng 	pxp = pyp = -9999;
632b50294ceSslatteng 	printf("\\\&");
633b50294ceSslatteng 	for (i = 0; i < N-1; i++) {	/* interval */
634b50294ceSslatteng 		steps = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
635b50294ceSslatteng 		steps /= DX;
636b50294ceSslatteng 		for (j = 0; j < steps; j++) {	/* points within */
637b50294ceSslatteng 			w = (float) j / steps;
638b50294ceSslatteng 			t1 = 0.5 * w * w;
639b50294ceSslatteng 			w = w - 0.5;
640b50294ceSslatteng 			t2 = 0.75 - w * w;
641b50294ceSslatteng 			w = w - 0.5;
642b50294ceSslatteng 			t3 = 0.5 * w * w;
643b50294ceSslatteng 			xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
644b50294ceSslatteng 			yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
645b50294ceSslatteng 			xp = round(xp, DX);
646b50294ceSslatteng 			yp = round(yp, DY);
647b50294ceSslatteng 			if (xp != pxp || yp != pyp) {
648b50294ceSslatteng 				hgoto(xp);
649b50294ceSslatteng 				vgoto(yp);
650b50294ceSslatteng 				put1(drawdot);
651b50294ceSslatteng 				pxp = xp;
652b50294ceSslatteng 				pyp = yp;
653b50294ceSslatteng 			}
654b50294ceSslatteng 		}
655b50294ceSslatteng 	}
656b50294ceSslatteng 	printf("\n");
657b50294ceSslatteng }
658b50294ceSslatteng 
drawcirc(d)659b50294ceSslatteng drawcirc(d)
660b50294ceSslatteng {
661b50294ceSslatteng 	int xc, yc;
662b50294ceSslatteng 
663b50294ceSslatteng 	xc = hpos;
664b50294ceSslatteng 	yc = vpos;
665b50294ceSslatteng 	printf("\\\&");
666b50294ceSslatteng 	conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
667b50294ceSslatteng 	hgoto(xc + d);	/* circle goes to right side */
668b50294ceSslatteng 	vgoto(yc);
669b50294ceSslatteng 	printf("\n");
670b50294ceSslatteng }
671b50294ceSslatteng 
dist(x1,y1,x2,y2)672b50294ceSslatteng dist(x1, y1, x2, y2)	/* integer distance from x1,y1 to x2,y2 */
673b50294ceSslatteng {
674b50294ceSslatteng 	float dx, dy;
675b50294ceSslatteng 
676b50294ceSslatteng 	dx = x2 - x1;
677b50294ceSslatteng 	dy = y2 - y1;
678b50294ceSslatteng 	return sqrt(dx*dx + dy*dy) + 0.5;
679b50294ceSslatteng }
680b50294ceSslatteng 
drawarc(x,y,r)681b50294ceSslatteng drawarc(x, y, r)
682b50294ceSslatteng {
683b50294ceSslatteng 	int x0, y0;
684b50294ceSslatteng 	float dx, dy, phi, d, ht, ang;
685b50294ceSslatteng 
686b50294ceSslatteng 	if (r == 0)
687b50294ceSslatteng 		r = 1;
688b50294ceSslatteng 	if (r < 0)
689b50294ceSslatteng 		ang = PI / 2;
690b50294ceSslatteng 	else
691b50294ceSslatteng 		ang = -(PI / 2);
692b50294ceSslatteng 	dx = x / 2;
693b50294ceSslatteng 	dy = y / 2;
694b50294ceSslatteng 	phi = atan2(dy, dx) + ang;
695b50294ceSslatteng 	while ((d = (float)r * r - (dx*dx + dy*dy)) < 0.0)
696b50294ceSslatteng 		r *= 2;
697b50294ceSslatteng 	ht = sqrt(d);
698b50294ceSslatteng 	x0 = hpos + dx + ht * cos(phi) + 0.5;
699b50294ceSslatteng 	y0 = vpos + dy + ht * sin(phi) + 0.5;
700b50294ceSslatteng 	printf("\\\&");
701b50294ceSslatteng 	conicarc(x0, -y0, hpos, -vpos, hpos+x, -vpos-y, r, r);
702b50294ceSslatteng 	printf("\n");
703b50294ceSslatteng }
704b50294ceSslatteng 
drawellip(a,b)705b50294ceSslatteng drawellip(a, b)
706b50294ceSslatteng {
707b50294ceSslatteng 	int xc, yc;
708b50294ceSslatteng 
709b50294ceSslatteng 	xc = hpos;
710b50294ceSslatteng 	yc = vpos;
711b50294ceSslatteng 	printf("\\\&");
712b50294ceSslatteng 	conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
713b50294ceSslatteng 	hgoto(xc + a);
714b50294ceSslatteng 	vgoto(yc);
715b50294ceSslatteng 	printf("\n");
716b50294ceSslatteng }
717b50294ceSslatteng 
718b50294ceSslatteng #define sqr(x) (long int)(x)*(x)
719b50294ceSslatteng 
conicarc(x,y,x0,y0,x1,y1,a,b)720b50294ceSslatteng conicarc(x, y, x0, y0, x1, y1, a, b)
721b50294ceSslatteng {
722b50294ceSslatteng 	/* based on Bresenham, CACM, Feb 77, pp 102-3 */
723b50294ceSslatteng 	/* by Chris Van Wyk */
724b50294ceSslatteng 	/* capitalized vars are an internal reference frame */
725b50294ceSslatteng 	long dotcount = 0;
726b50294ceSslatteng 	int	xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
727b50294ceSslatteng 	M1x, M1y, M2x, M2y, M3x, M3y,
728b50294ceSslatteng 	Q, move, Xc, Yc;
729b50294ceSslatteng 	int	delta;
730b50294ceSslatteng 	float	xc, yc;
731b50294ceSslatteng 	float	radius, slope;
732b50294ceSslatteng 	float	xstep, ystep;
733b50294ceSslatteng 	if (a != b)	/* an arc of an ellipse; internally, will still think of circle */
734b50294ceSslatteng 		if (a > b) {
735b50294ceSslatteng 			xstep = (float)a / b;
736b50294ceSslatteng 			ystep = 1;
737b50294ceSslatteng 			radius = b;
738b50294ceSslatteng 		}
739b50294ceSslatteng 		else
740b50294ceSslatteng 		 {
741b50294ceSslatteng 			xstep = 1;
742b50294ceSslatteng 			ystep = (float)b / a;
743b50294ceSslatteng 			radius = a;
744b50294ceSslatteng 		}
745b50294ceSslatteng 	else	/* a circular arc; radius is computed from center and first point */	 {
746b50294ceSslatteng 		xstep = ystep = 1;
747b50294ceSslatteng 		radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
748b50294ceSslatteng 	}
749b50294ceSslatteng 
750b50294ceSslatteng 
751b50294ceSslatteng 	xc = x0;
752b50294ceSslatteng 	yc = y0;
753b50294ceSslatteng 	/* now, use start and end point locations to figure out
754b50294ceSslatteng    the angle at which start and end happen; use these
755b50294ceSslatteng    angles with known radius to figure out where start
756b50294ceSslatteng    and end should be */
757b50294ceSslatteng 	slope = atan2((double)(y0 - y), (double)(x0 - x)
758b50294ceSslatteng 	    );
759b50294ceSslatteng 	if ((slope == 0.0)
760b50294ceSslatteng 	     && (x0 < x)
761b50294ceSslatteng 	    )
762b50294ceSslatteng 		slope = 3.14159265;
763b50294ceSslatteng 	x0 = x + radius * cos(slope)
764b50294ceSslatteng 	 + 0.5;
765b50294ceSslatteng 	y0 = y + radius * sin(slope)
766b50294ceSslatteng 	 + 0.5;
767b50294ceSslatteng 	slope = atan2((double)(y1 - y), (double)(x1 - x)
768b50294ceSslatteng 	    );
769b50294ceSslatteng 	if ((slope == 0.0)
770b50294ceSslatteng 	     && (x1 < x)
771b50294ceSslatteng 	    )
772b50294ceSslatteng 		slope = 3.14159265;
773b50294ceSslatteng 	x1 = x + radius * cos(slope)
774b50294ceSslatteng 	 + 0.5;
775b50294ceSslatteng 	y1 = y + radius * sin(slope)
776b50294ceSslatteng 	 + 0.5;
777b50294ceSslatteng 	/* step 2: translate to zero-centered circle */
778b50294ceSslatteng 	xs = x0 - x;
779b50294ceSslatteng 	ys = y0 - y;
780b50294ceSslatteng 	xt = x1 - x;
781b50294ceSslatteng 	yt = y1 - y;
782b50294ceSslatteng 	/* step 3: normalize to first quadrant */
783b50294ceSslatteng 	if (xs < 0)
784b50294ceSslatteng 		if (ys < 0) {
785b50294ceSslatteng 			Xs = abs(ys);
786b50294ceSslatteng 			Ys = abs(xs);
787b50294ceSslatteng 			qs = 3;
788b50294ceSslatteng 			M1x = 0;
789b50294ceSslatteng 			M1y = -1;
790b50294ceSslatteng 			M2x = 1;
791b50294ceSslatteng 			M2y = -1;
792b50294ceSslatteng 			M3x = 1;
793b50294ceSslatteng 			M3y = 0;
794b50294ceSslatteng 		}
795b50294ceSslatteng 		else {
796b50294ceSslatteng 			Xs = abs(xs);
797b50294ceSslatteng 			Ys = abs(ys);
798b50294ceSslatteng 			qs = 2;
799b50294ceSslatteng 			M1x = -1;
800b50294ceSslatteng 			M1y = 0;
801b50294ceSslatteng 			M2x = -1;
802b50294ceSslatteng 			M2y = -1;
803b50294ceSslatteng 			M3x = 0;
804b50294ceSslatteng 			M3y = -1;
805b50294ceSslatteng 		}
806b50294ceSslatteng 	else if (ys < 0) {
807b50294ceSslatteng 		Xs = abs(xs);
808b50294ceSslatteng 		Ys = abs(ys);
809b50294ceSslatteng 		qs = 0;
810b50294ceSslatteng 		M1x = 1;
811b50294ceSslatteng 		M1y = 0;
812b50294ceSslatteng 		M2x = 1;
813b50294ceSslatteng 		M2y = 1;
814b50294ceSslatteng 		M3x = 0;
815b50294ceSslatteng 		M3y = 1;
816b50294ceSslatteng 	} else {
817b50294ceSslatteng 		Xs = abs(ys);
818b50294ceSslatteng 		Ys = abs(xs);
819b50294ceSslatteng 		qs = 1;
820b50294ceSslatteng 		M1x = 0;
821b50294ceSslatteng 		M1y = 1;
822b50294ceSslatteng 		M2x = -1;
823b50294ceSslatteng 		M2y = 1;
824b50294ceSslatteng 		M3x = -1;
825b50294ceSslatteng 		M3y = 0;
826b50294ceSslatteng 	}
827b50294ceSslatteng 
828b50294ceSslatteng 
829b50294ceSslatteng 	Xc = Xs;
830b50294ceSslatteng 	Yc = Ys;
831b50294ceSslatteng 	if (xt < 0)
832b50294ceSslatteng 		if (yt < 0) {
833b50294ceSslatteng 			Xt = abs(yt);
834b50294ceSslatteng 			Yt = abs(xt);
835b50294ceSslatteng 			qt = 3;
836b50294ceSslatteng 		}
837b50294ceSslatteng 		else {
838b50294ceSslatteng 			Xt = abs(xt);
839b50294ceSslatteng 			Yt = abs(yt);
840b50294ceSslatteng 			qt = 2;
841b50294ceSslatteng 		}
842b50294ceSslatteng 	else if (yt < 0) {
843b50294ceSslatteng 		Xt = abs(xt);
844b50294ceSslatteng 		Yt = abs(yt);
845b50294ceSslatteng 		qt = 0;
846b50294ceSslatteng 	} else {
847b50294ceSslatteng 		Xt = abs(yt);
848b50294ceSslatteng 		Yt = abs(xt);
849b50294ceSslatteng 		qt = 1;
850b50294ceSslatteng 	}
851b50294ceSslatteng 
852b50294ceSslatteng 
853b50294ceSslatteng 	/* step 4: calculate number of quadrant crossings */
854b50294ceSslatteng 	if (((4 + qt - qs)
855b50294ceSslatteng 	     % 4 == 0)
856b50294ceSslatteng 	     && (Xt <= Xs)
857b50294ceSslatteng 	     && (Yt >= Ys)
858b50294ceSslatteng 	    )
859b50294ceSslatteng 		Q = 3;
860b50294ceSslatteng 	else
861b50294ceSslatteng 		Q = (4 + qt - qs) % 4 - 1;
862b50294ceSslatteng 	/* step 5: calculate initial decision difference */
863b50294ceSslatteng 	delta = sqr(Xs + 1)
864b50294ceSslatteng 	 + sqr(Ys - 1)
865b50294ceSslatteng 	-sqr(xs)
866b50294ceSslatteng 	-sqr(ys);
867b50294ceSslatteng 	/* here begins the work of drawing
868b50294ceSslatteng    we hope it ends here too */
869b50294ceSslatteng 	while ((Q >= 0)
870b50294ceSslatteng 	     || ((Q > -2)
871b50294ceSslatteng 	     && ((Xt > Xc)
872b50294ceSslatteng 	     || (Yt < Yc)
873b50294ceSslatteng 	    )
874b50294ceSslatteng 	    )
875b50294ceSslatteng 	    ) {
876b50294ceSslatteng 		if (dotcount++ % DX == 0)
877b50294ceSslatteng 			putdot(round((int) xc, DX), round((int) yc, DY));
878b50294ceSslatteng 		if (Yc < 0.5) {
879b50294ceSslatteng 			/* reinitialize */
880b50294ceSslatteng 			Xs = Xc = 0;
881b50294ceSslatteng 			Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
882b50294ceSslatteng 			delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
883b50294ceSslatteng 			Q--;
884b50294ceSslatteng 			M1x = M3x;
885b50294ceSslatteng 			M1y = M3y;
886b50294ceSslatteng 			 {
887b50294ceSslatteng 				int	T;
888b50294ceSslatteng 				T = M2y;
889b50294ceSslatteng 				M2y = M2x;
890b50294ceSslatteng 				M2x = -T;
891b50294ceSslatteng 				T = M3y;
892b50294ceSslatteng 				M3y = M3x;
893b50294ceSslatteng 				M3x = -T;
894b50294ceSslatteng 			}
895b50294ceSslatteng 		} else {
896b50294ceSslatteng 			if (delta <= 0)
897b50294ceSslatteng 				if (2 * delta + 2 * Yc - 1 <= 0)
898b50294ceSslatteng 					move = 1;
899b50294ceSslatteng 				else
900b50294ceSslatteng 					move = 2;
901b50294ceSslatteng 			else if (2 * delta - 2 * Xc - 1 <= 0)
902b50294ceSslatteng 				move = 2;
903b50294ceSslatteng 			else
904b50294ceSslatteng 				move = 3;
905b50294ceSslatteng 			switch (move) {
906b50294ceSslatteng 			case 1:
907b50294ceSslatteng 				Xc++;
908b50294ceSslatteng 				delta += 2 * Xc + 1;
909b50294ceSslatteng 				xc += M1x * xstep;
910b50294ceSslatteng 				yc += M1y * ystep;
911b50294ceSslatteng 				break;
912b50294ceSslatteng 			case 2:
913b50294ceSslatteng 				Xc++;
914b50294ceSslatteng 				Yc--;
915b50294ceSslatteng 				delta += 2 * Xc - 2 * Yc + 2;
916b50294ceSslatteng 				xc += M2x * xstep;
917b50294ceSslatteng 				yc += M2y * ystep;
918b50294ceSslatteng 				break;
919b50294ceSslatteng 			case 3:
920b50294ceSslatteng 				Yc--;
921b50294ceSslatteng 				delta -= 2 * Yc + 1;
922b50294ceSslatteng 				xc += M3x * xstep;
923b50294ceSslatteng 				yc += M3y * ystep;
924b50294ceSslatteng 				break;
925b50294ceSslatteng 			}
926b50294ceSslatteng 		}
927b50294ceSslatteng 	}
928b50294ceSslatteng 
929b50294ceSslatteng 
930b50294ceSslatteng }
931b50294ceSslatteng 
putdot(x,y)932b50294ceSslatteng putdot(x, y)
933b50294ceSslatteng {
934b50294ceSslatteng 	arcmove(x, y);
935b50294ceSslatteng 	put1(drawdot);
936b50294ceSslatteng }
937b50294ceSslatteng 
round(x,dx)938b50294ceSslatteng round(x, dx)	/* round x relative to dx */
939b50294ceSslatteng {
940b50294ceSslatteng 	x = (x + dx - 1) / dx;
941b50294ceSslatteng 	return x * dx;
942b50294ceSslatteng }
943e08db0e5Sslatteng #endif
944