xref: /OK3568_Linux_fs/external/xserver/mi/mifillarc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1989, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Author:  Bob Scheifler, MIT X Consortium
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun ********************************************************/
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
30*4882a593Smuzhiyun #include <dix-config.h>
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include <math.h>
34*4882a593Smuzhiyun #include <X11/X.h>
35*4882a593Smuzhiyun #include <X11/Xprotostr.h>
36*4882a593Smuzhiyun #include "regionstr.h"
37*4882a593Smuzhiyun #include "gcstruct.h"
38*4882a593Smuzhiyun #include "pixmapstr.h"
39*4882a593Smuzhiyun #include "mi.h"
40*4882a593Smuzhiyun #include "mifillarc.h"
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define QUADRANT (90 * 64)
43*4882a593Smuzhiyun #define HALFCIRCLE (180 * 64)
44*4882a593Smuzhiyun #define QUADRANT3 (270 * 64)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #ifndef M_PI
47*4882a593Smuzhiyun #define M_PI	3.14159265358979323846
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define Dsin(d)	sin((double)d*(M_PI/11520.0))
51*4882a593Smuzhiyun #define Dcos(d)	cos((double)d*(M_PI/11520.0))
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static void
miFillArcSetup(xArc * arc,miFillArcRec * info)54*4882a593Smuzhiyun miFillArcSetup(xArc * arc, miFillArcRec * info)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun     info->y = arc->height >> 1;
57*4882a593Smuzhiyun     info->dy = arc->height & 1;
58*4882a593Smuzhiyun     info->yorg = arc->y + info->y;
59*4882a593Smuzhiyun     info->dx = arc->width & 1;
60*4882a593Smuzhiyun     info->xorg = arc->x + (arc->width >> 1) + info->dx;
61*4882a593Smuzhiyun     info->dx = 1 - info->dx;
62*4882a593Smuzhiyun     if (arc->width == arc->height) {
63*4882a593Smuzhiyun         /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
64*4882a593Smuzhiyun         /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
65*4882a593Smuzhiyun         info->ym = 8;
66*4882a593Smuzhiyun         info->xm = 8;
67*4882a593Smuzhiyun         info->yk = info->y << 3;
68*4882a593Smuzhiyun         if (!info->dx) {
69*4882a593Smuzhiyun             info->xk = 0;
70*4882a593Smuzhiyun             info->e = -1;
71*4882a593Smuzhiyun         }
72*4882a593Smuzhiyun         else {
73*4882a593Smuzhiyun             info->y++;
74*4882a593Smuzhiyun             info->yk += 4;
75*4882a593Smuzhiyun             info->xk = -4;
76*4882a593Smuzhiyun             info->e = -(info->y << 3);
77*4882a593Smuzhiyun         }
78*4882a593Smuzhiyun     }
79*4882a593Smuzhiyun     else {
80*4882a593Smuzhiyun         /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
81*4882a593Smuzhiyun         /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
82*4882a593Smuzhiyun         info->ym = (arc->width * arc->width) << 3;
83*4882a593Smuzhiyun         info->xm = (arc->height * arc->height) << 3;
84*4882a593Smuzhiyun         info->yk = info->y * info->ym;
85*4882a593Smuzhiyun         if (!info->dy)
86*4882a593Smuzhiyun             info->yk -= info->ym >> 1;
87*4882a593Smuzhiyun         if (!info->dx) {
88*4882a593Smuzhiyun             info->xk = 0;
89*4882a593Smuzhiyun             info->e = -(info->xm >> 3);
90*4882a593Smuzhiyun         }
91*4882a593Smuzhiyun         else {
92*4882a593Smuzhiyun             info->y++;
93*4882a593Smuzhiyun             info->yk += info->ym;
94*4882a593Smuzhiyun             info->xk = -(info->xm >> 1);
95*4882a593Smuzhiyun             info->e = info->xk - info->yk;
96*4882a593Smuzhiyun         }
97*4882a593Smuzhiyun     }
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun static void
miFillArcDSetup(xArc * arc,miFillArcDRec * info)101*4882a593Smuzhiyun miFillArcDSetup(xArc * arc, miFillArcDRec * info)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun     /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
104*4882a593Smuzhiyun     /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
105*4882a593Smuzhiyun     info->y = arc->height >> 1;
106*4882a593Smuzhiyun     info->dy = arc->height & 1;
107*4882a593Smuzhiyun     info->yorg = arc->y + info->y;
108*4882a593Smuzhiyun     info->dx = arc->width & 1;
109*4882a593Smuzhiyun     info->xorg = arc->x + (arc->width >> 1) + info->dx;
110*4882a593Smuzhiyun     info->dx = 1 - info->dx;
111*4882a593Smuzhiyun     info->ym = ((double) arc->width) * (arc->width * 8);
112*4882a593Smuzhiyun     info->xm = ((double) arc->height) * (arc->height * 8);
113*4882a593Smuzhiyun     info->yk = info->y * info->ym;
114*4882a593Smuzhiyun     if (!info->dy)
115*4882a593Smuzhiyun         info->yk -= info->ym / 2.0;
116*4882a593Smuzhiyun     if (!info->dx) {
117*4882a593Smuzhiyun         info->xk = 0;
118*4882a593Smuzhiyun         info->e = -(info->xm / 8.0);
119*4882a593Smuzhiyun     }
120*4882a593Smuzhiyun     else {
121*4882a593Smuzhiyun         info->y++;
122*4882a593Smuzhiyun         info->yk += info->ym;
123*4882a593Smuzhiyun         info->xk = -info->xm / 2.0;
124*4882a593Smuzhiyun         info->e = info->xk - info->yk;
125*4882a593Smuzhiyun     }
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun static void
miGetArcEdge(xArc * arc,miSliceEdgePtr edge,int k,Bool top,Bool left)129*4882a593Smuzhiyun miGetArcEdge(xArc * arc, miSliceEdgePtr edge, int k, Bool top, Bool left)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun     int xady, y;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun     y = arc->height >> 1;
134*4882a593Smuzhiyun     if (!(arc->width & 1))
135*4882a593Smuzhiyun         y++;
136*4882a593Smuzhiyun     if (!top) {
137*4882a593Smuzhiyun         y = -y;
138*4882a593Smuzhiyun         if (arc->height & 1)
139*4882a593Smuzhiyun             y--;
140*4882a593Smuzhiyun     }
141*4882a593Smuzhiyun     xady = k + y * edge->dx;
142*4882a593Smuzhiyun     if (xady <= 0)
143*4882a593Smuzhiyun         edge->x = -((-xady) / edge->dy + 1);
144*4882a593Smuzhiyun     else
145*4882a593Smuzhiyun         edge->x = (xady - 1) / edge->dy;
146*4882a593Smuzhiyun     edge->e = xady - edge->x * edge->dy;
147*4882a593Smuzhiyun     if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
148*4882a593Smuzhiyun         edge->e = edge->dy - edge->e + 1;
149*4882a593Smuzhiyun     if (left)
150*4882a593Smuzhiyun         edge->x++;
151*4882a593Smuzhiyun     edge->x += arc->x + (arc->width >> 1);
152*4882a593Smuzhiyun     if (edge->dx > 0) {
153*4882a593Smuzhiyun         edge->deltax = 1;
154*4882a593Smuzhiyun         edge->stepx = edge->dx / edge->dy;
155*4882a593Smuzhiyun         edge->dx = edge->dx % edge->dy;
156*4882a593Smuzhiyun     }
157*4882a593Smuzhiyun     else {
158*4882a593Smuzhiyun         edge->deltax = -1;
159*4882a593Smuzhiyun         edge->stepx = -((-edge->dx) / edge->dy);
160*4882a593Smuzhiyun         edge->dx = (-edge->dx) % edge->dy;
161*4882a593Smuzhiyun     }
162*4882a593Smuzhiyun     if (!top) {
163*4882a593Smuzhiyun         edge->deltax = -edge->deltax;
164*4882a593Smuzhiyun         edge->stepx = -edge->stepx;
165*4882a593Smuzhiyun     }
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static void
miEllipseAngleToSlope(int angle,int width,int height,int * dxp,int * dyp,double * d_dxp,double * d_dyp)169*4882a593Smuzhiyun miEllipseAngleToSlope(int angle, int width, int height, int *dxp, int *dyp,
170*4882a593Smuzhiyun                       double *d_dxp, double *d_dyp)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun     int dx, dy;
173*4882a593Smuzhiyun     double d_dx, d_dy, scale;
174*4882a593Smuzhiyun     Bool negative_dx, negative_dy;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun     switch (angle) {
177*4882a593Smuzhiyun     case 0:
178*4882a593Smuzhiyun         *dxp = -1;
179*4882a593Smuzhiyun         *dyp = 0;
180*4882a593Smuzhiyun         if (d_dxp) {
181*4882a593Smuzhiyun             *d_dxp = width / 2.0;
182*4882a593Smuzhiyun             *d_dyp = 0;
183*4882a593Smuzhiyun         }
184*4882a593Smuzhiyun         break;
185*4882a593Smuzhiyun     case QUADRANT:
186*4882a593Smuzhiyun         *dxp = 0;
187*4882a593Smuzhiyun         *dyp = 1;
188*4882a593Smuzhiyun         if (d_dxp) {
189*4882a593Smuzhiyun             *d_dxp = 0;
190*4882a593Smuzhiyun             *d_dyp = -height / 2.0;
191*4882a593Smuzhiyun         }
192*4882a593Smuzhiyun         break;
193*4882a593Smuzhiyun     case HALFCIRCLE:
194*4882a593Smuzhiyun         *dxp = 1;
195*4882a593Smuzhiyun         *dyp = 0;
196*4882a593Smuzhiyun         if (d_dxp) {
197*4882a593Smuzhiyun             *d_dxp = -width / 2.0;
198*4882a593Smuzhiyun             *d_dyp = 0;
199*4882a593Smuzhiyun         }
200*4882a593Smuzhiyun         break;
201*4882a593Smuzhiyun     case QUADRANT3:
202*4882a593Smuzhiyun         *dxp = 0;
203*4882a593Smuzhiyun         *dyp = -1;
204*4882a593Smuzhiyun         if (d_dxp) {
205*4882a593Smuzhiyun             *d_dxp = 0;
206*4882a593Smuzhiyun             *d_dyp = height / 2.0;
207*4882a593Smuzhiyun         }
208*4882a593Smuzhiyun         break;
209*4882a593Smuzhiyun     default:
210*4882a593Smuzhiyun         d_dx = Dcos(angle) * width;
211*4882a593Smuzhiyun         d_dy = Dsin(angle) * height;
212*4882a593Smuzhiyun         if (d_dxp) {
213*4882a593Smuzhiyun             *d_dxp = d_dx / 2.0;
214*4882a593Smuzhiyun             *d_dyp = -d_dy / 2.0;
215*4882a593Smuzhiyun         }
216*4882a593Smuzhiyun         negative_dx = FALSE;
217*4882a593Smuzhiyun         if (d_dx < 0.0) {
218*4882a593Smuzhiyun             d_dx = -d_dx;
219*4882a593Smuzhiyun             negative_dx = TRUE;
220*4882a593Smuzhiyun         }
221*4882a593Smuzhiyun         negative_dy = FALSE;
222*4882a593Smuzhiyun         if (d_dy < 0.0) {
223*4882a593Smuzhiyun             d_dy = -d_dy;
224*4882a593Smuzhiyun             negative_dy = TRUE;
225*4882a593Smuzhiyun         }
226*4882a593Smuzhiyun         scale = d_dx;
227*4882a593Smuzhiyun         if (d_dy > d_dx)
228*4882a593Smuzhiyun             scale = d_dy;
229*4882a593Smuzhiyun         dx = floor((d_dx * 32768) / scale + 0.5);
230*4882a593Smuzhiyun         if (negative_dx)
231*4882a593Smuzhiyun             dx = -dx;
232*4882a593Smuzhiyun         *dxp = dx;
233*4882a593Smuzhiyun         dy = floor((d_dy * 32768) / scale + 0.5);
234*4882a593Smuzhiyun         if (negative_dy)
235*4882a593Smuzhiyun             dy = -dy;
236*4882a593Smuzhiyun         *dyp = dy;
237*4882a593Smuzhiyun         break;
238*4882a593Smuzhiyun     }
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun static void
miGetPieEdge(xArc * arc,int angle,miSliceEdgePtr edge,Bool top,Bool left)242*4882a593Smuzhiyun miGetPieEdge(xArc * arc, int angle, miSliceEdgePtr edge, Bool top, Bool left)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun     int k;
245*4882a593Smuzhiyun     int dx, dy;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     miEllipseAngleToSlope(angle, arc->width, arc->height, &dx, &dy, 0, 0);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun     if (dy == 0) {
250*4882a593Smuzhiyun         edge->x = left ? -65536 : 65536;
251*4882a593Smuzhiyun         edge->stepx = 0;
252*4882a593Smuzhiyun         edge->e = 0;
253*4882a593Smuzhiyun         edge->dx = -1;
254*4882a593Smuzhiyun         return;
255*4882a593Smuzhiyun     }
256*4882a593Smuzhiyun     if (dx == 0) {
257*4882a593Smuzhiyun         edge->x = arc->x + (arc->width >> 1);
258*4882a593Smuzhiyun         if (left && (arc->width & 1))
259*4882a593Smuzhiyun             edge->x++;
260*4882a593Smuzhiyun         else if (!left && !(arc->width & 1))
261*4882a593Smuzhiyun             edge->x--;
262*4882a593Smuzhiyun         edge->stepx = 0;
263*4882a593Smuzhiyun         edge->e = 0;
264*4882a593Smuzhiyun         edge->dx = -1;
265*4882a593Smuzhiyun         return;
266*4882a593Smuzhiyun     }
267*4882a593Smuzhiyun     if (dy < 0) {
268*4882a593Smuzhiyun         dx = -dx;
269*4882a593Smuzhiyun         dy = -dy;
270*4882a593Smuzhiyun     }
271*4882a593Smuzhiyun     k = (arc->height & 1) ? dx : 0;
272*4882a593Smuzhiyun     if (arc->width & 1)
273*4882a593Smuzhiyun         k += dy;
274*4882a593Smuzhiyun     edge->dx = dx << 1;
275*4882a593Smuzhiyun     edge->dy = dy << 1;
276*4882a593Smuzhiyun     miGetArcEdge(arc, edge, k, top, left);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun static void
miFillArcSliceSetup(xArc * arc,miArcSliceRec * slice,GCPtr pGC)280*4882a593Smuzhiyun miFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun     int angle1, angle2;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     angle1 = arc->angle1;
285*4882a593Smuzhiyun     if (arc->angle2 < 0) {
286*4882a593Smuzhiyun         angle2 = angle1;
287*4882a593Smuzhiyun         angle1 += arc->angle2;
288*4882a593Smuzhiyun     }
289*4882a593Smuzhiyun     else
290*4882a593Smuzhiyun         angle2 = angle1 + arc->angle2;
291*4882a593Smuzhiyun     while (angle1 < 0)
292*4882a593Smuzhiyun         angle1 += FULLCIRCLE;
293*4882a593Smuzhiyun     while (angle1 >= FULLCIRCLE)
294*4882a593Smuzhiyun         angle1 -= FULLCIRCLE;
295*4882a593Smuzhiyun     while (angle2 < 0)
296*4882a593Smuzhiyun         angle2 += FULLCIRCLE;
297*4882a593Smuzhiyun     while (angle2 >= FULLCIRCLE)
298*4882a593Smuzhiyun         angle2 -= FULLCIRCLE;
299*4882a593Smuzhiyun     slice->min_top_y = 0;
300*4882a593Smuzhiyun     slice->max_top_y = arc->height >> 1;
301*4882a593Smuzhiyun     slice->min_bot_y = 1 - (arc->height & 1);
302*4882a593Smuzhiyun     slice->max_bot_y = slice->max_top_y - 1;
303*4882a593Smuzhiyun     slice->flip_top = FALSE;
304*4882a593Smuzhiyun     slice->flip_bot = FALSE;
305*4882a593Smuzhiyun     if (pGC->arcMode == ArcPieSlice) {
306*4882a593Smuzhiyun         slice->edge1_top = (angle1 < HALFCIRCLE);
307*4882a593Smuzhiyun         slice->edge2_top = (angle2 <= HALFCIRCLE);
308*4882a593Smuzhiyun         if ((angle2 == 0) || (angle1 == HALFCIRCLE)) {
309*4882a593Smuzhiyun             if (angle2 ? slice->edge2_top : slice->edge1_top)
310*4882a593Smuzhiyun                 slice->min_top_y = slice->min_bot_y;
311*4882a593Smuzhiyun             else
312*4882a593Smuzhiyun                 slice->min_top_y = arc->height;
313*4882a593Smuzhiyun             slice->min_bot_y = 0;
314*4882a593Smuzhiyun         }
315*4882a593Smuzhiyun         else if ((angle1 == 0) || (angle2 == HALFCIRCLE)) {
316*4882a593Smuzhiyun             slice->min_top_y = slice->min_bot_y;
317*4882a593Smuzhiyun             if (angle1 ? slice->edge1_top : slice->edge2_top)
318*4882a593Smuzhiyun                 slice->min_bot_y = arc->height;
319*4882a593Smuzhiyun             else
320*4882a593Smuzhiyun                 slice->min_bot_y = 0;
321*4882a593Smuzhiyun         }
322*4882a593Smuzhiyun         else if (slice->edge1_top == slice->edge2_top) {
323*4882a593Smuzhiyun             if (angle2 < angle1) {
324*4882a593Smuzhiyun                 slice->flip_top = slice->edge1_top;
325*4882a593Smuzhiyun                 slice->flip_bot = !slice->edge1_top;
326*4882a593Smuzhiyun             }
327*4882a593Smuzhiyun             else if (slice->edge1_top) {
328*4882a593Smuzhiyun                 slice->min_top_y = 1;
329*4882a593Smuzhiyun                 slice->min_bot_y = arc->height;
330*4882a593Smuzhiyun             }
331*4882a593Smuzhiyun             else {
332*4882a593Smuzhiyun                 slice->min_bot_y = 0;
333*4882a593Smuzhiyun                 slice->min_top_y = arc->height;
334*4882a593Smuzhiyun             }
335*4882a593Smuzhiyun         }
336*4882a593Smuzhiyun         miGetPieEdge(arc, angle1, &slice->edge1,
337*4882a593Smuzhiyun                      slice->edge1_top, !slice->edge1_top);
338*4882a593Smuzhiyun         miGetPieEdge(arc, angle2, &slice->edge2,
339*4882a593Smuzhiyun                      slice->edge2_top, slice->edge2_top);
340*4882a593Smuzhiyun     }
341*4882a593Smuzhiyun     else {
342*4882a593Smuzhiyun         double w2, h2, x1, y1, x2, y2, dx, dy, scale;
343*4882a593Smuzhiyun         int signdx, signdy, y, k;
344*4882a593Smuzhiyun         Bool isInt1 = TRUE, isInt2 = TRUE;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun         w2 = (double) arc->width / 2.0;
347*4882a593Smuzhiyun         h2 = (double) arc->height / 2.0;
348*4882a593Smuzhiyun         if ((angle1 == 0) || (angle1 == HALFCIRCLE)) {
349*4882a593Smuzhiyun             x1 = angle1 ? -w2 : w2;
350*4882a593Smuzhiyun             y1 = 0.0;
351*4882a593Smuzhiyun         }
352*4882a593Smuzhiyun         else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3)) {
353*4882a593Smuzhiyun             x1 = 0.0;
354*4882a593Smuzhiyun             y1 = (angle1 == QUADRANT) ? h2 : -h2;
355*4882a593Smuzhiyun         }
356*4882a593Smuzhiyun         else {
357*4882a593Smuzhiyun             isInt1 = FALSE;
358*4882a593Smuzhiyun             x1 = Dcos(angle1) * w2;
359*4882a593Smuzhiyun             y1 = Dsin(angle1) * h2;
360*4882a593Smuzhiyun         }
361*4882a593Smuzhiyun         if ((angle2 == 0) || (angle2 == HALFCIRCLE)) {
362*4882a593Smuzhiyun             x2 = angle2 ? -w2 : w2;
363*4882a593Smuzhiyun             y2 = 0.0;
364*4882a593Smuzhiyun         }
365*4882a593Smuzhiyun         else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3)) {
366*4882a593Smuzhiyun             x2 = 0.0;
367*4882a593Smuzhiyun             y2 = (angle2 == QUADRANT) ? h2 : -h2;
368*4882a593Smuzhiyun         }
369*4882a593Smuzhiyun         else {
370*4882a593Smuzhiyun             isInt2 = FALSE;
371*4882a593Smuzhiyun             x2 = Dcos(angle2) * w2;
372*4882a593Smuzhiyun             y2 = Dsin(angle2) * h2;
373*4882a593Smuzhiyun         }
374*4882a593Smuzhiyun         dx = x2 - x1;
375*4882a593Smuzhiyun         dy = y2 - y1;
376*4882a593Smuzhiyun         if (arc->height & 1) {
377*4882a593Smuzhiyun             y1 -= 0.5;
378*4882a593Smuzhiyun             y2 -= 0.5;
379*4882a593Smuzhiyun         }
380*4882a593Smuzhiyun         if (arc->width & 1) {
381*4882a593Smuzhiyun             x1 += 0.5;
382*4882a593Smuzhiyun             x2 += 0.5;
383*4882a593Smuzhiyun         }
384*4882a593Smuzhiyun         if (dy < 0.0) {
385*4882a593Smuzhiyun             dy = -dy;
386*4882a593Smuzhiyun             signdy = -1;
387*4882a593Smuzhiyun         }
388*4882a593Smuzhiyun         else
389*4882a593Smuzhiyun             signdy = 1;
390*4882a593Smuzhiyun         if (dx < 0.0) {
391*4882a593Smuzhiyun             dx = -dx;
392*4882a593Smuzhiyun             signdx = -1;
393*4882a593Smuzhiyun         }
394*4882a593Smuzhiyun         else
395*4882a593Smuzhiyun             signdx = 1;
396*4882a593Smuzhiyun         if (isInt1 && isInt2) {
397*4882a593Smuzhiyun             slice->edge1.dx = dx * 2;
398*4882a593Smuzhiyun             slice->edge1.dy = dy * 2;
399*4882a593Smuzhiyun         }
400*4882a593Smuzhiyun         else {
401*4882a593Smuzhiyun             scale = (dx > dy) ? dx : dy;
402*4882a593Smuzhiyun             slice->edge1.dx = floor((dx * 32768) / scale + .5);
403*4882a593Smuzhiyun             slice->edge1.dy = floor((dy * 32768) / scale + .5);
404*4882a593Smuzhiyun         }
405*4882a593Smuzhiyun         if (!slice->edge1.dy) {
406*4882a593Smuzhiyun             if (signdx < 0) {
407*4882a593Smuzhiyun                 y = floor(y1 + 1.0);
408*4882a593Smuzhiyun                 if (y >= 0) {
409*4882a593Smuzhiyun                     slice->min_top_y = y;
410*4882a593Smuzhiyun                     slice->min_bot_y = arc->height;
411*4882a593Smuzhiyun                 }
412*4882a593Smuzhiyun                 else {
413*4882a593Smuzhiyun                     slice->max_bot_y = -y - (arc->height & 1);
414*4882a593Smuzhiyun                 }
415*4882a593Smuzhiyun             }
416*4882a593Smuzhiyun             else {
417*4882a593Smuzhiyun                 y = floor(y1);
418*4882a593Smuzhiyun                 if (y >= 0)
419*4882a593Smuzhiyun                     slice->max_top_y = y;
420*4882a593Smuzhiyun                 else {
421*4882a593Smuzhiyun                     slice->min_top_y = arc->height;
422*4882a593Smuzhiyun                     slice->min_bot_y = -y - (arc->height & 1);
423*4882a593Smuzhiyun                 }
424*4882a593Smuzhiyun             }
425*4882a593Smuzhiyun             slice->edge1_top = TRUE;
426*4882a593Smuzhiyun             slice->edge1.x = 65536;
427*4882a593Smuzhiyun             slice->edge1.stepx = 0;
428*4882a593Smuzhiyun             slice->edge1.e = 0;
429*4882a593Smuzhiyun             slice->edge1.dx = -1;
430*4882a593Smuzhiyun             slice->edge2 = slice->edge1;
431*4882a593Smuzhiyun             slice->edge2_top = FALSE;
432*4882a593Smuzhiyun         }
433*4882a593Smuzhiyun         else if (!slice->edge1.dx) {
434*4882a593Smuzhiyun             if (signdy < 0)
435*4882a593Smuzhiyun                 x1 -= 1.0;
436*4882a593Smuzhiyun             slice->edge1.x = ceil(x1);
437*4882a593Smuzhiyun             slice->edge1_top = signdy < 0;
438*4882a593Smuzhiyun             slice->edge1.x += arc->x + (arc->width >> 1);
439*4882a593Smuzhiyun             slice->edge1.stepx = 0;
440*4882a593Smuzhiyun             slice->edge1.e = 0;
441*4882a593Smuzhiyun             slice->edge1.dx = -1;
442*4882a593Smuzhiyun             slice->edge2_top = !slice->edge1_top;
443*4882a593Smuzhiyun             slice->edge2 = slice->edge1;
444*4882a593Smuzhiyun         }
445*4882a593Smuzhiyun         else {
446*4882a593Smuzhiyun             if (signdx < 0)
447*4882a593Smuzhiyun                 slice->edge1.dx = -slice->edge1.dx;
448*4882a593Smuzhiyun             if (signdy < 0)
449*4882a593Smuzhiyun                 slice->edge1.dx = -slice->edge1.dx;
450*4882a593Smuzhiyun             k = ceil(((x1 + x2) * slice->edge1.dy -
451*4882a593Smuzhiyun                       (y1 + y2) * slice->edge1.dx) / 2.0);
452*4882a593Smuzhiyun             slice->edge2.dx = slice->edge1.dx;
453*4882a593Smuzhiyun             slice->edge2.dy = slice->edge1.dy;
454*4882a593Smuzhiyun             slice->edge1_top = signdy < 0;
455*4882a593Smuzhiyun             slice->edge2_top = !slice->edge1_top;
456*4882a593Smuzhiyun             miGetArcEdge(arc, &slice->edge1, k,
457*4882a593Smuzhiyun                          slice->edge1_top, !slice->edge1_top);
458*4882a593Smuzhiyun             miGetArcEdge(arc, &slice->edge2, k,
459*4882a593Smuzhiyun                          slice->edge2_top, slice->edge2_top);
460*4882a593Smuzhiyun         }
461*4882a593Smuzhiyun     }
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun #define ADDSPANS() \
465*4882a593Smuzhiyun     pts->x = xorg - x; \
466*4882a593Smuzhiyun     pts->y = yorg - y; \
467*4882a593Smuzhiyun     *wids = slw; \
468*4882a593Smuzhiyun     pts++; \
469*4882a593Smuzhiyun     wids++; \
470*4882a593Smuzhiyun     if (miFillArcLower(slw)) \
471*4882a593Smuzhiyun     { \
472*4882a593Smuzhiyun 	pts->x = xorg - x; \
473*4882a593Smuzhiyun 	pts->y = yorg + y + dy; \
474*4882a593Smuzhiyun 	pts++; \
475*4882a593Smuzhiyun 	*wids++ = slw; \
476*4882a593Smuzhiyun     }
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun static int
miFillEllipseI(DrawablePtr pDraw,GCPtr pGC,xArc * arc,DDXPointPtr points,int * widths)479*4882a593Smuzhiyun miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun     int x, y, e;
482*4882a593Smuzhiyun     int yk, xk, ym, xm, dx, dy, xorg, yorg;
483*4882a593Smuzhiyun     int slw;
484*4882a593Smuzhiyun     miFillArcRec info;
485*4882a593Smuzhiyun     DDXPointPtr pts;
486*4882a593Smuzhiyun     int *wids;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun     miFillArcSetup(arc, &info);
489*4882a593Smuzhiyun     MIFILLARCSETUP();
490*4882a593Smuzhiyun     if (pGC->miTranslate) {
491*4882a593Smuzhiyun         xorg += pDraw->x;
492*4882a593Smuzhiyun         yorg += pDraw->y;
493*4882a593Smuzhiyun     }
494*4882a593Smuzhiyun     pts = points;
495*4882a593Smuzhiyun     wids = widths;
496*4882a593Smuzhiyun     while (y > 0) {
497*4882a593Smuzhiyun         MIFILLARCSTEP(slw);
498*4882a593Smuzhiyun         ADDSPANS();
499*4882a593Smuzhiyun     }
500*4882a593Smuzhiyun     return pts - points;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun static int
miFillEllipseD(DrawablePtr pDraw,GCPtr pGC,xArc * arc,DDXPointPtr points,int * widths)504*4882a593Smuzhiyun miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun     int x, y;
507*4882a593Smuzhiyun     int xorg, yorg, dx, dy, slw;
508*4882a593Smuzhiyun     double e, yk, xk, ym, xm;
509*4882a593Smuzhiyun     miFillArcDRec info;
510*4882a593Smuzhiyun     DDXPointPtr pts;
511*4882a593Smuzhiyun     int *wids;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     miFillArcDSetup(arc, &info);
514*4882a593Smuzhiyun     MIFILLARCSETUP();
515*4882a593Smuzhiyun     if (pGC->miTranslate) {
516*4882a593Smuzhiyun         xorg += pDraw->x;
517*4882a593Smuzhiyun         yorg += pDraw->y;
518*4882a593Smuzhiyun     }
519*4882a593Smuzhiyun     pts = points;
520*4882a593Smuzhiyun     wids = widths;
521*4882a593Smuzhiyun     while (y > 0) {
522*4882a593Smuzhiyun         MIFILLARCSTEP(slw);
523*4882a593Smuzhiyun         ADDSPANS();
524*4882a593Smuzhiyun     }
525*4882a593Smuzhiyun     return pts - points;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun #define ADDSPAN(l,r) \
529*4882a593Smuzhiyun     if (r >= l) \
530*4882a593Smuzhiyun     { \
531*4882a593Smuzhiyun 	pts->x = l; \
532*4882a593Smuzhiyun 	pts->y = ya; \
533*4882a593Smuzhiyun 	pts++; \
534*4882a593Smuzhiyun 	*wids++ = r - l + 1; \
535*4882a593Smuzhiyun     }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun #define ADDSLICESPANS(flip) \
538*4882a593Smuzhiyun     if (!flip) \
539*4882a593Smuzhiyun     { \
540*4882a593Smuzhiyun 	ADDSPAN(xl, xr); \
541*4882a593Smuzhiyun     } \
542*4882a593Smuzhiyun     else \
543*4882a593Smuzhiyun     { \
544*4882a593Smuzhiyun 	xc = xorg - x; \
545*4882a593Smuzhiyun 	ADDSPAN(xc, xr); \
546*4882a593Smuzhiyun 	xc += slw - 1; \
547*4882a593Smuzhiyun 	ADDSPAN(xl, xc); \
548*4882a593Smuzhiyun     }
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun static int
miFillArcSliceI(DrawablePtr pDraw,GCPtr pGC,xArc * arc,DDXPointPtr points,int * widths)551*4882a593Smuzhiyun miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun     int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
554*4882a593Smuzhiyun     int x, y, e;
555*4882a593Smuzhiyun     miFillArcRec info;
556*4882a593Smuzhiyun     miArcSliceRec slice;
557*4882a593Smuzhiyun     int ya, xl, xr, xc;
558*4882a593Smuzhiyun     DDXPointPtr pts;
559*4882a593Smuzhiyun     int *wids;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun     miFillArcSetup(arc, &info);
562*4882a593Smuzhiyun     miFillArcSliceSetup(arc, &slice, pGC);
563*4882a593Smuzhiyun     MIFILLARCSETUP();
564*4882a593Smuzhiyun     slw = arc->height;
565*4882a593Smuzhiyun     if (slice.flip_top || slice.flip_bot)
566*4882a593Smuzhiyun         slw += (arc->height >> 1) + 1;
567*4882a593Smuzhiyun     if (pGC->miTranslate) {
568*4882a593Smuzhiyun         xorg += pDraw->x;
569*4882a593Smuzhiyun         yorg += pDraw->y;
570*4882a593Smuzhiyun         slice.edge1.x += pDraw->x;
571*4882a593Smuzhiyun         slice.edge2.x += pDraw->x;
572*4882a593Smuzhiyun     }
573*4882a593Smuzhiyun     pts = points;
574*4882a593Smuzhiyun     wids = widths;
575*4882a593Smuzhiyun     while (y > 0) {
576*4882a593Smuzhiyun         MIFILLARCSTEP(slw);
577*4882a593Smuzhiyun         MIARCSLICESTEP(slice.edge1);
578*4882a593Smuzhiyun         MIARCSLICESTEP(slice.edge2);
579*4882a593Smuzhiyun         if (miFillSliceUpper(slice)) {
580*4882a593Smuzhiyun             ya = yorg - y;
581*4882a593Smuzhiyun             MIARCSLICEUPPER(xl, xr, slice, slw);
582*4882a593Smuzhiyun             ADDSLICESPANS(slice.flip_top);
583*4882a593Smuzhiyun         }
584*4882a593Smuzhiyun         if (miFillSliceLower(slice)) {
585*4882a593Smuzhiyun             ya = yorg + y + dy;
586*4882a593Smuzhiyun             MIARCSLICELOWER(xl, xr, slice, slw);
587*4882a593Smuzhiyun             ADDSLICESPANS(slice.flip_bot);
588*4882a593Smuzhiyun         }
589*4882a593Smuzhiyun     }
590*4882a593Smuzhiyun     return pts - points;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun static int
miFillArcSliceD(DrawablePtr pDraw,GCPtr pGC,xArc * arc,DDXPointPtr points,int * widths)594*4882a593Smuzhiyun miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun     int x, y;
597*4882a593Smuzhiyun     int dx, dy, xorg, yorg, slw;
598*4882a593Smuzhiyun     double e, yk, xk, ym, xm;
599*4882a593Smuzhiyun     miFillArcDRec info;
600*4882a593Smuzhiyun     miArcSliceRec slice;
601*4882a593Smuzhiyun     int ya, xl, xr, xc;
602*4882a593Smuzhiyun     DDXPointPtr pts;
603*4882a593Smuzhiyun     int *wids;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     miFillArcDSetup(arc, &info);
606*4882a593Smuzhiyun     miFillArcSliceSetup(arc, &slice, pGC);
607*4882a593Smuzhiyun     MIFILLARCSETUP();
608*4882a593Smuzhiyun     slw = arc->height;
609*4882a593Smuzhiyun     if (slice.flip_top || slice.flip_bot)
610*4882a593Smuzhiyun         slw += (arc->height >> 1) + 1;
611*4882a593Smuzhiyun     if (pGC->miTranslate) {
612*4882a593Smuzhiyun         xorg += pDraw->x;
613*4882a593Smuzhiyun         yorg += pDraw->y;
614*4882a593Smuzhiyun         slice.edge1.x += pDraw->x;
615*4882a593Smuzhiyun         slice.edge2.x += pDraw->x;
616*4882a593Smuzhiyun     }
617*4882a593Smuzhiyun     pts = points;
618*4882a593Smuzhiyun     wids = widths;
619*4882a593Smuzhiyun     while (y > 0) {
620*4882a593Smuzhiyun         MIFILLARCSTEP(slw);
621*4882a593Smuzhiyun         MIARCSLICESTEP(slice.edge1);
622*4882a593Smuzhiyun         MIARCSLICESTEP(slice.edge2);
623*4882a593Smuzhiyun         if (miFillSliceUpper(slice)) {
624*4882a593Smuzhiyun             ya = yorg - y;
625*4882a593Smuzhiyun             MIARCSLICEUPPER(xl, xr, slice, slw);
626*4882a593Smuzhiyun             ADDSLICESPANS(slice.flip_top);
627*4882a593Smuzhiyun         }
628*4882a593Smuzhiyun         if (miFillSliceLower(slice)) {
629*4882a593Smuzhiyun             ya = yorg + y + dy;
630*4882a593Smuzhiyun             MIARCSLICELOWER(xl, xr, slice, slw);
631*4882a593Smuzhiyun             ADDSLICESPANS(slice.flip_bot);
632*4882a593Smuzhiyun         }
633*4882a593Smuzhiyun     }
634*4882a593Smuzhiyun     return pts - points;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun /* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
638*4882a593Smuzhiyun  * Since we don't have to worry about overlapping segments, we can just
639*4882a593Smuzhiyun  * fill each arc as it comes.
640*4882a593Smuzhiyun  */
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun /* Limit the number of spans in a single draw request to avoid integer
643*4882a593Smuzhiyun  * overflow in the computation of the span buffer size.
644*4882a593Smuzhiyun  */
645*4882a593Smuzhiyun #define MAX_SPANS_PER_LOOP      (4 * 1024 * 1024)
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun void
miPolyFillArc(DrawablePtr pDraw,GCPtr pGC,int narcs_all,xArc * parcs)648*4882a593Smuzhiyun miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs_all, xArc * parcs)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun     while (narcs_all > 0) {
651*4882a593Smuzhiyun         int narcs;
652*4882a593Smuzhiyun         int i;
653*4882a593Smuzhiyun         xArc *arc;
654*4882a593Smuzhiyun         int nspans = 0;
655*4882a593Smuzhiyun         DDXPointPtr pts, points;
656*4882a593Smuzhiyun         int *wids, *widths;
657*4882a593Smuzhiyun         int n;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun         for (narcs = 0, arc = parcs; narcs < narcs_all; narcs++, arc++) {
660*4882a593Smuzhiyun             if (narcs && nspans + arc->height > MAX_SPANS_PER_LOOP)
661*4882a593Smuzhiyun                 break;
662*4882a593Smuzhiyun             nspans += arc->height;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun             /* A pie-slice arc may add another pile of spans */
665*4882a593Smuzhiyun             if (pGC->arcMode == ArcPieSlice &&
666*4882a593Smuzhiyun                 (-FULLCIRCLE < arc->angle2 && arc->angle2 < FULLCIRCLE))
667*4882a593Smuzhiyun                 nspans += (arc->height + 1) >> 1;
668*4882a593Smuzhiyun         }
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun         pts = points = malloc (sizeof (DDXPointRec) * nspans +
671*4882a593Smuzhiyun                                sizeof(int) * nspans);
672*4882a593Smuzhiyun         if (points) {
673*4882a593Smuzhiyun             wids = widths = (int *) (points + nspans);
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun             for (i = 0, arc = parcs; i < narcs; arc++, i++) {
676*4882a593Smuzhiyun                 if (miFillArcEmpty(arc))
677*4882a593Smuzhiyun                     continue;
678*4882a593Smuzhiyun                 if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
679*4882a593Smuzhiyun                 {
680*4882a593Smuzhiyun                     if (miCanFillArc(arc))
681*4882a593Smuzhiyun                         n = miFillEllipseI(pDraw, pGC, arc, pts, wids);
682*4882a593Smuzhiyun                     else
683*4882a593Smuzhiyun                         n = miFillEllipseD(pDraw, pGC, arc, pts, wids);
684*4882a593Smuzhiyun                 }
685*4882a593Smuzhiyun                 else
686*4882a593Smuzhiyun                 {
687*4882a593Smuzhiyun                     if (miCanFillArc(arc))
688*4882a593Smuzhiyun                         n = miFillArcSliceI(pDraw, pGC, arc, pts, wids);
689*4882a593Smuzhiyun                     else
690*4882a593Smuzhiyun                         n = miFillArcSliceD(pDraw, pGC, arc, pts, wids);
691*4882a593Smuzhiyun                 }
692*4882a593Smuzhiyun                 pts += n;
693*4882a593Smuzhiyun                 wids += n;
694*4882a593Smuzhiyun             }
695*4882a593Smuzhiyun             nspans = pts - points;
696*4882a593Smuzhiyun             if (nspans)
697*4882a593Smuzhiyun                 (*pGC->ops->FillSpans) (pDraw, pGC, nspans, points,
698*4882a593Smuzhiyun                                         widths, FALSE);
699*4882a593Smuzhiyun             free (points);
700*4882a593Smuzhiyun         }
701*4882a593Smuzhiyun         parcs += narcs;
702*4882a593Smuzhiyun         narcs_all -= narcs;
703*4882a593Smuzhiyun     }
704*4882a593Smuzhiyun }
705