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