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