1 /**
2 ** scanellp.c ---- draw the outline or scan fill an ellipse
3 **
4 ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5 ** [e-mail: csaba@vuse.vanderbilt.edu]
6 **
7 ** This file is part of the GRX graphics library.
8 **
9 ** The GRX graphics library is free software; you can redistribute it
10 ** and/or modify it under some conditions; see the "copying.grx" file
11 ** for details.
12 **
13 ** This library is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 **
17 **/
18
19 #include "libgrx.h"
20 #include "allocate.h"
21 #include "arith.h"
22 #include "clipping.h"
23 #include "shapes.h"
24
25 #define MAXR 120 /* max radius for which Bresenham works */
26
_GrScanEllipse(int xc,int yc,int xa,int ya,GrFiller * f,GrFillArg c,int filled)27 void _GrScanEllipse(int xc,int yc,int xa,int ya,GrFiller *f,GrFillArg c,int filled)
28 {
29 int x1,x2,y1,y2;
30 if(xa < 0) xa = (-xa);
31 if(ya < 0) ya = (-ya);
32 x1 = xc - xa; y1 = yc - ya;
33 x2 = xc + xa; y2 = yc + ya;
34 clip_ordbox(CURC,x1,y1,x2,y2);
35 mouse_block(CURC,x1,y1,x2,y2);
36 setup_ALLOC();
37 if((xa == 0) || (ya == 0)) (*f->line)(
38 (x1 + CURC->gc_xoffset),
39 (y1 + CURC->gc_yoffset),
40 (x2 - x1),
41 (y2 - y1),
42 c
43 );
44 else if((xa > MAXR) || (ya > MAXR)) { /* Bresenham would overflow !! */
45 int (*points)[2] = ALLOC(sizeof(int) * 2 * GR_MAX_ELLIPSE_POINTS);
46 if(points != NULL) {
47 int count = GrGenerateEllipse(xc,yc,xa,ya,points);
48 if(filled) _GrScanConvexPoly(count,points,f,c);
49 else _GrDrawPolygon(count,points,f,c,TRUE);
50 FREE(points);
51 }
52 }
53 else {
54 int *scans = ALLOC(sizeof(int) * (ya + 1));
55 int row = ya;
56 int col = 0;
57 if(scans != NULL) {
58 long yasq = umul32(ya,ya);
59 long xasq = umul32(xa,xa);
60 long xasq2 = xasq + xasq;
61 long yasq2 = yasq + yasq;
62 long xasq4 = xasq2 + xasq2;
63 long yasq4 = yasq2 + yasq2;
64 long error = (xasq2 * (row - 1) * row) +
65 (yasq2 * (1 - xasq)) +
66 xasq;
67 while((xasq * row) > (yasq * col)) {
68 if(error >= 0) {
69 scans[row] = col;
70 row--;
71 error -= xasq4 * row;
72 }
73 error += yasq2 * (3 + (col << 1));
74 col++;
75 }
76 error = (yasq2 * (col + 1) * col) +
77 (xasq2 * ((row * (row - 2)) + 1)) +
78 (yasq * (1 - xasq2));
79 while(row >= 0) {
80 scans[row] = col;
81 if(error <= 0) {
82 col++;
83 error += yasq4 * col;
84 }
85 row--;
86 error += xasq2 * (2 - (row << 1));
87 }
88 for(row = y1; row <= y2; row++) {
89 col = iabs(yc - row);
90 if(!filled && (col < ya)) {
91 x1 = xc - scans[col];
92 x2 = xc - scans[col + 1];
93 if(x1 < x2) x2--;
94 do {
95 clip_ordxrange_(CURC,x1,x2,break,CLIP_EMPTY_MACRO_ARG);
96 (*f->scan)(
97 (x1 + CURC->gc_xoffset),
98 (row + CURC->gc_yoffset),
99 (x2 - x1 + 1),
100 c
101 );
102 } while (0);
103 x1 = xc + scans[col + 1];
104 x2 = xc + scans[col];
105 if(x1 < x2) x1++;
106 }
107 else {
108 x1 = xc - scans[col];
109 x2 = xc + scans[col];
110 }
111 clip_ordxrange_(CURC,x1,x2,continue,CLIP_EMPTY_MACRO_ARG);
112 (*f->scan)(
113 (x1 + CURC->gc_xoffset),
114 (row + CURC->gc_yoffset),
115 (x2 - x1 + 1),
116 c
117 );
118 }
119 FREE(scans);
120 }
121 }
122 reset_ALLOC();
123 mouse_unblock();
124 }
125
126