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