]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/mizerarc.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / mi / mizerarc.c
1 /************************************************************
2
3 Copyright (c) 1989  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26 Author:  Bob Scheifler, MIT X Consortium
27
28 ********************************************************/
29
30 /* $XConsortium: mizerarc.c,v 5.36 94/04/17 20:28:04 dpw Exp $ */
31
32 /* Derived from:
33  * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
34  * by M. L. V. Pitteway
35  * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
36  */
37
38 #include <math.h>
39 #include "X.h"
40 #include "Xprotostr.h"
41 #include "miscstruct.h"
42 #include "gcstruct.h"
43 #include "pixmapstr.h"
44 #include "mi.h"
45 #include "mizerarc.h"
46
47 #define FULLCIRCLE (360 * 64)
48 #define OCTANT (45 * 64)
49 #define QUADRANT (90 * 64)
50 #define HALFCIRCLE (180 * 64)
51 #define QUADRANT3 (270 * 64)
52
53 #ifndef M_PI
54 #define M_PI    3.14159265358979323846
55 #endif
56
57 #define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
58                  ((d) == HALFCIRCLE ? 0.0 : \
59                  ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
60
61 #define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
62                  ((d) == HALFCIRCLE ? -1.0 : \
63                  ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
64
65 #define EPSILON45 64
66
67 typedef struct {
68     int skipStart;
69     int haveStart;
70     DDXPointRec startPt;
71     int haveLast;
72     int skipLast;
73     DDXPointRec endPt;
74     int dashIndex;
75     int dashOffset;
76     int dashIndexInit;
77     int dashOffsetInit;
78 } DashInfo;
79
80 static miZeroArcPtRec oob = {65536, 65536, 0};
81
82 /*
83  * (x - l)^2 / (W/2)^2  + (y + H/2)^2 / (H/2)^2 = 1
84  *
85  * where l is either 0 or .5
86  *
87  * alpha = 4(W^2)
88  * beta = 4(H^2)
89  * gamma = 0
90  * u = 2(W^2)H
91  * v = 4(H^2)l
92  * k = -4(H^2)(l^2)
93  *
94  */
95
96 Bool
97 miZeroArcSetup(arc, info, ok360)
98     register xArc *arc;
99     register miZeroArcRec *info;
100     Bool ok360;
101 {
102     int l;
103     int angle1, angle2;
104     int startseg, endseg;
105     int startAngle, endAngle;
106     int i, overlap;
107     miZeroArcPtRec start, end;
108
109     l = arc->width & 1;
110     if (arc->width == arc->height)
111     {
112         info->alpha = 4;
113         info->beta = 4;
114         info->k1 = -8;
115         info->k3 = -16;
116         info->b = 12;
117         info->a = (arc->width << 2) - 12;
118         info->d = 17 - (arc->width << 1);
119         if (l)
120         {
121             info->b -= 4;
122             info->a += 4;
123             info->d -= 7;
124         }
125     }
126     else if (!arc->width || !arc->height)
127     {
128         info->alpha = 0;
129         info->beta = 0;
130         info->k1 = 0;
131         info->k3 = 0;
132         info->a = -(int)arc->height;
133         info->b = 0;
134         info->d = -1;
135     }
136     else
137     {
138         /* initial conditions */
139         info->alpha = (arc->width * arc->width) << 2;
140         info->beta = (arc->height * arc->height) << 2;
141         info->k1 = info->beta << 1;
142         info->k3 = info->k1 + (info->alpha << 1);
143         info->b = l ? 0 : -info->beta;
144         info->a = info->alpha * arc->height;
145         info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
146         if (l)
147             info->d -= info->beta >> 2;
148         info->a -= info->b;
149         /* take first step, d < 0 always */
150         info->b -= info->k1;
151         info->a += info->k1;
152         info->d += info->b;
153         /* octant change, b < 0 always */
154         info->k1 = -info->k1;
155         info->k3 = -info->k3;
156         info->b = -info->b;
157         info->d = info->b - info->a - info->d;
158         info->a = info->a - (info->b << 1);
159     }
160     info->dx = 1;
161     info->dy = 0;
162     info->w = (arc->width + 1) >> 1;
163     info->h = arc->height >> 1;
164     info->xorg = arc->x + (arc->width >> 1);
165     info->yorg = arc->y;
166     info->xorgo = info->xorg + l;
167     info->yorgo = info->yorg + arc->height;
168     if (!arc->width)
169     {
170         if (!arc->height)
171         {
172             info->x = 0;
173             info->y = 0;
174             info->initialMask = 0;
175             info->startAngle = 0;
176             info->endAngle = 0;
177             info->start = oob;
178             info->end = oob;
179             return FALSE;
180         }
181         info->x = 0;
182         info->y = 1;
183     }
184     else
185     {
186         info->x = 1;
187         info->y = 0;
188     }
189     angle1 = arc->angle1;
190     angle2 = arc->angle2;
191     if ((angle1 == 0) && (angle2 >= FULLCIRCLE))
192     {
193         startAngle = 0;
194         endAngle = 0;
195     }
196     else
197     {
198         if (angle2 > FULLCIRCLE)
199             angle2 = FULLCIRCLE;
200         else if (angle2 < -FULLCIRCLE)
201             angle2 = -FULLCIRCLE;
202         if (angle2 < 0)
203         {
204             startAngle = angle1 + angle2;
205             endAngle = angle1;
206         }
207         else
208         {
209             startAngle = angle1;
210             endAngle = angle1 + angle2;
211         }
212         if (startAngle < 0)
213             startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
214         if (startAngle >= FULLCIRCLE)
215             startAngle = startAngle % FULLCIRCLE;
216         if (endAngle < 0)
217             endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
218         if (endAngle >= FULLCIRCLE)
219             endAngle = endAngle % FULLCIRCLE;
220     }
221     info->startAngle = startAngle;
222     info->endAngle = endAngle;
223     if (ok360 && (startAngle == endAngle) && arc->angle2 &&
224         arc->width && arc->height)
225     {
226         info->initialMask = 0xf;
227         info->start = oob;
228         info->end = oob;
229         return TRUE;
230     }
231     startseg = startAngle / OCTANT;
232     if (!arc->height || (((startseg + 1) & 2) && arc->width))
233     {
234         start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
235         if (start.x < 0)
236             start.x = -start.x;
237         start.y = -1;
238     }
239     else
240     {
241         start.y = Dsin(startAngle) * (arc->height / 2.0);
242         if (start.y < 0)
243             start.y = -start.y;
244         start.y = info->h - start.y;
245         start.x = 65536;
246     }
247     endseg = endAngle / OCTANT;
248     if (!arc->height || (((endseg + 1) & 2) && arc->width))
249     {
250         end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
251         if (end.x < 0)
252             end.x = -end.x;
253         end.y = -1;
254     }
255     else
256     {
257         end.y = Dsin(endAngle) * (arc->height / 2.0);
258         if (end.y < 0)
259             end.y = -end.y;
260         end.y = info->h - end.y;
261         end.x = 65536;
262     }
263     info->firstx = start.x;
264     info->firsty = start.y;
265     info->initialMask = 0;
266     overlap = arc->angle2 && (endAngle <= startAngle);
267     for (i = 0; i < 4; i++)
268     {
269         if (overlap ?
270             ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
271             ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
272             info->initialMask |= (1 << i);
273     }
274     start.mask = info->initialMask;
275     end.mask = info->initialMask;
276     startseg >>= 1;
277     endseg >>= 1;
278     overlap = overlap && (endseg == startseg);
279     if (start.x != end.x || start.y != end.y || !overlap)
280     {
281         if (startseg & 1)
282         {
283             if (!overlap)
284                 info->initialMask &= ~(1 << startseg);
285             if (start.x > end.x || start.y > end.y)
286                 end.mask &= ~(1 << startseg);
287         }
288         else
289         {
290             start.mask &= ~(1 << startseg);
291             if (((start.x < end.x || start.y < end.y) ||
292                  (start.x == end.x && start.y == end.y && (endseg & 1))) &&
293                 !overlap)
294                 end.mask &= ~(1 << startseg);
295         }
296         if (endseg & 1)
297         {
298             end.mask &= ~(1 << endseg);
299             if (((start.x > end.x || start.y > end.y) ||
300                  (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
301                 !overlap)
302                 start.mask &= ~(1 << endseg);
303         }
304         else
305         {
306             if (!overlap)
307                 info->initialMask &= ~(1 << endseg);
308             if (start.x < end.x || start.y < end.y)
309                 start.mask &= ~(1 << endseg);
310         }
311     }
312     /* take care of case when start and stop are both near 45 */
313     /* handle here rather than adding extra code to pixelization loops */
314     if (startAngle &&
315         ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0)))
316     {
317         i = (startAngle + OCTANT) % OCTANT;
318         if (i < EPSILON45 || i > OCTANT - EPSILON45)
319         {
320             i = (endAngle + OCTANT) % OCTANT;
321             if (i < EPSILON45 || i > OCTANT - EPSILON45)
322             {
323                 if (start.y < 0)
324                 {
325                     i = Dsin(startAngle) * (arc->height / 2.0);
326                     if (i < 0)
327                         i = -i;
328                     if (info->h - i == end.y)
329                         start.mask = end.mask;
330                 }
331                 else
332                 {
333                     i = Dsin(endAngle) * (arc->height / 2.0);
334                     if (i < 0)
335                         i = -i;
336                     if (info->h - i == start.y)
337                         end.mask = start.mask;
338                 }
339             }
340         }
341     }
342     if (startseg & 1)
343     {
344         info->start = start;
345         info->end = oob;
346     }
347     else
348     {
349         info->end = start;
350         info->start = oob;
351     }
352     if (endseg & 1)
353     {
354         info->altend = end;
355         if (info->altend.x < info->end.x || info->altend.y < info->end.y)
356         {
357             miZeroArcPtRec tmp;
358             tmp = info->altend;
359             info->altend = info->end;
360             info->end = tmp;
361         }
362         info->altstart = oob;
363     }
364     else
365     {
366         info->altstart = end;
367         if (info->altstart.x < info->start.x ||
368             info->altstart.y < info->start.y)
369         {
370             miZeroArcPtRec tmp;
371             tmp = info->altstart;
372             info->altstart = info->start;
373             info->start = tmp;
374         }
375         info->altend = oob;
376     }
377     if (!info->start.x || !info->start.y)
378     {
379         info->initialMask = info->start.mask;
380         info->start = info->altstart;
381     }
382     if (!arc->width && (arc->height == 1))
383     {
384         /* kludge! */
385         info->initialMask |= info->end.mask;
386         info->initialMask |= info->initialMask << 1;
387         info->end.x = 0;
388         info->end.mask = 0;
389     }
390     return FALSE;
391 }
392
393 #define Pixelate(xval,yval) \
394     { \
395         pts->x = xval; \
396         pts->y = yval; \
397         pts++; \
398     }
399
400 #define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
401
402 DDXPointPtr
403 miZeroArcPts(arc, pts)
404     xArc *arc;
405     register DDXPointPtr pts;
406 {
407     miZeroArcRec info;
408     register int x, y, a, b, d, mask;
409     register int k1, k3, dx, dy;
410     Bool do360;
411
412     do360 = miZeroArcSetup(arc, &info, TRUE);
413     MIARCSETUP();
414     mask = info.initialMask;
415     if (!(arc->width & 1))
416     {
417         DoPix(1, info.xorgo, info.yorg);
418         DoPix(3, info.xorgo, info.yorgo);
419     }
420     if (!info.end.x || !info.end.y)
421     {
422         mask = info.end.mask;
423         info.end = info.altend;
424     }
425     if (do360 && (arc->width == arc->height) && !(arc->width & 1))
426     {
427         int yorgh = info.yorg + info.h;
428         int xorghp = info.xorg + info.h;
429         int xorghn = info.xorg - info.h;
430
431         while (1)
432         {
433             Pixelate(info.xorg + x, info.yorg + y);
434             Pixelate(info.xorg - x, info.yorg + y);
435             Pixelate(info.xorg - x, info.yorgo - y);
436             Pixelate(info.xorg + x, info.yorgo - y);
437             if (a < 0)
438                 break;
439             Pixelate(xorghp - y, yorgh - x);
440             Pixelate(xorghn + y, yorgh - x);
441             Pixelate(xorghn + y, yorgh + x);
442             Pixelate(xorghp - y, yorgh + x);
443             MIARCCIRCLESTEP(;);
444         }
445         if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
446             pts -= 4;
447         x = info.w;
448         y = info.h;
449     }
450     else if (do360)
451     {
452         while (y < info.h || x < info.w)
453         {
454             MIARCOCTANTSHIFT(;);
455             Pixelate(info.xorg + x, info.yorg + y);
456             Pixelate(info.xorgo - x, info.yorg + y);
457             Pixelate(info.xorgo - x, info.yorgo - y);
458             Pixelate(info.xorg + x, info.yorgo - y);
459             MIARCSTEP(;,;);
460         }
461     }
462     else
463     {
464         while (y < info.h || x < info.w)
465         {
466             MIARCOCTANTSHIFT(;);
467             if ((x == info.start.x) || (y == info.start.y))
468             {
469                 mask = info.start.mask;
470                 info.start = info.altstart;
471             }
472             DoPix(0, info.xorg + x, info.yorg + y);
473             DoPix(1, info.xorgo - x, info.yorg + y);
474             DoPix(2, info.xorgo - x, info.yorgo - y);
475             DoPix(3, info.xorg + x, info.yorgo - y);
476             if ((x == info.end.x) || (y == info.end.y))
477             {
478                 mask = info.end.mask;
479                 info.end = info.altend;
480             }
481             MIARCSTEP(;,;);
482         }
483     }
484     if ((x == info.start.x) || (y == info.start.y))
485         mask = info.start.mask;
486     DoPix(0, info.xorg + x, info.yorg + y);
487     DoPix(2, info.xorgo - x, info.yorgo - y);
488     if (arc->height & 1)
489     {
490         DoPix(1, info.xorgo - x, info.yorg + y);
491         DoPix(3, info.xorg + x, info.yorgo - y);
492     }
493     return pts;
494 }
495
496 #undef DoPix
497 #define DoPix(idx,xval,yval) \
498     if (mask & (1 << idx)) \
499     { \
500         arcPts[idx]->x = xval; \
501         arcPts[idx]->y = yval; \
502         arcPts[idx]++; \
503     }
504
505 static void
506 miZeroArcDashPts(pGC, arc, dinfo, points, maxPts, evenPts, oddPts)
507     GCPtr pGC;
508     xArc *arc;
509     DashInfo *dinfo;
510     int maxPts;
511     register DDXPointPtr points, *evenPts, *oddPts;
512 {
513     miZeroArcRec info;
514     register int x, y, a, b, d, mask;
515     register int k1, k3, dx, dy;
516     int dashRemaining;
517     DDXPointPtr arcPts[4];
518     DDXPointPtr startPts[5], endPts[5];
519     int deltas[5];
520     DDXPointPtr startPt, pt, lastPt, pts;
521     int i, j, delta, ptsdelta, seg, startseg;
522
523     for (i = 0; i < 4; i++)
524         arcPts[i] = points + (i * maxPts);
525     (void)miZeroArcSetup(arc, &info, FALSE);
526     MIARCSETUP();
527     mask = info.initialMask;
528     startseg = info.startAngle / QUADRANT;
529     startPt = arcPts[startseg];
530     if (!(arc->width & 1))
531     {
532         DoPix(1, info.xorgo, info.yorg);
533         DoPix(3, info.xorgo, info.yorgo);
534     }
535     if (!info.end.x || !info.end.y)
536     {
537         mask = info.end.mask;
538         info.end = info.altend;
539     }
540     while (y < info.h || x < info.w)
541     {
542         MIARCOCTANTSHIFT(;);
543         if ((x == info.firstx) || (y == info.firsty))
544             startPt = arcPts[startseg];
545         if ((x == info.start.x) || (y == info.start.y))
546         {
547             mask = info.start.mask;
548             info.start = info.altstart;
549         }
550         DoPix(0, info.xorg + x, info.yorg + y);
551         DoPix(1, info.xorgo - x, info.yorg + y);
552         DoPix(2, info.xorgo - x, info.yorgo - y);
553         DoPix(3, info.xorg + x, info.yorgo - y);
554         if ((x == info.end.x) || (y == info.end.y))
555         {
556             mask = info.end.mask;
557             info.end = info.altend;
558         }
559         MIARCSTEP(;,;);
560     }
561     if ((x == info.firstx) || (y == info.firsty))
562         startPt = arcPts[startseg];
563     if ((x == info.start.x) || (y == info.start.y))
564         mask = info.start.mask;
565     DoPix(0, info.xorg + x, info.yorg + y);
566     DoPix(2, info.xorgo - x, info.yorgo - y);
567     if (arc->height & 1)
568     {
569         DoPix(1, info.xorgo - x, info.yorg + y);
570         DoPix(3, info.xorg + x, info.yorgo - y);
571     }
572     for (i = 0; i < 4; i++)
573     {
574         seg = (startseg + i) & 3;
575         pt = points + (seg * maxPts);
576         if (seg & 1)
577         {
578             startPts[i] = pt;
579             endPts[i] = arcPts[seg];
580             deltas[i] = 1;
581         }
582         else
583         {
584             startPts[i] = arcPts[seg] - 1;
585             endPts[i] = pt - 1;
586             deltas[i] = -1;
587         }
588     }
589     startPts[4] = startPts[0];
590     endPts[4] = startPt;
591     startPts[0] = startPt;
592     if (startseg & 1)
593     {
594         if (startPts[4] != endPts[4])
595             endPts[4]--;
596         deltas[4] = 1;
597     }
598     else
599     {
600         if (startPts[0] > startPts[4])
601             startPts[0]--;
602         if (startPts[4] < endPts[4])
603             endPts[4]--;
604         deltas[4] = -1;
605     }
606     if (arc->angle2 < 0)
607     {
608         DDXPointPtr tmps, tmpe;
609         int tmpd;
610
611         tmpd = deltas[0];
612         tmps = startPts[0] - tmpd;
613         tmpe = endPts[0] - tmpd;
614         startPts[0] = endPts[4] - deltas[4];
615         endPts[0] = startPts[4] - deltas[4];
616         deltas[0] = -deltas[4];
617         startPts[4] = tmpe;
618         endPts[4] = tmps;
619         deltas[4] = -tmpd;
620         tmpd = deltas[1];
621         tmps = startPts[1] - tmpd;
622         tmpe = endPts[1] - tmpd;
623         startPts[1] = endPts[3] - deltas[3];
624         endPts[1] = startPts[3] - deltas[3];
625         deltas[1] = -deltas[3];
626         startPts[3] = tmpe;
627         endPts[3] = tmps;
628         deltas[3] = -tmpd;
629         tmps = startPts[2] - deltas[2];
630         startPts[2] = endPts[2] - deltas[2];
631         endPts[2] = tmps;
632         deltas[2] = -deltas[2];
633     }
634     for (i = 0; i < 5 && startPts[i] == endPts[i]; i++)
635         ;
636     if (i == 5)
637         return;
638     pt = startPts[i];
639     for (j = 4; startPts[j] == endPts[j]; j--)
640         ;
641     lastPt = endPts[j] - deltas[j];
642     if (dinfo->haveLast &&
643         (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
644     {
645         startPts[i] += deltas[i];
646     }
647     else
648     {
649         dinfo->dashIndex = dinfo->dashIndexInit;
650         dinfo->dashOffset = dinfo->dashOffsetInit;
651     }
652     if (!dinfo->skipStart && (info.startAngle != info.endAngle))
653     {
654         dinfo->startPt = *pt;
655         dinfo->haveStart = TRUE;
656     }
657     else if (!dinfo->skipLast && dinfo->haveStart &&
658              (lastPt->x == dinfo->startPt.x) &&
659              (lastPt->y == dinfo->startPt.y) &&
660              (lastPt != startPts[i]))
661         endPts[j] = lastPt;
662     if (info.startAngle != info.endAngle)
663     {
664         dinfo->haveLast = TRUE;
665         dinfo->endPt = *lastPt;
666     }
667     dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
668     for (i = 0; i < 5; i++)
669     {
670         pt = startPts[i];
671         lastPt = endPts[i];
672         delta = deltas[i];
673         while (pt != lastPt)
674         {
675             if (dinfo->dashIndex & 1)
676             {
677                 pts = *oddPts;
678                 ptsdelta = -1;
679             }
680             else
681             {
682                 pts = *evenPts;
683                 ptsdelta = 1;
684             }
685             while ((pt != lastPt) && --dashRemaining >= 0)
686             {
687                 *pts = *pt;
688                 pts += ptsdelta;
689                 pt += delta;
690             }
691             if (dinfo->dashIndex & 1)
692                 *oddPts = pts;
693             else
694                 *evenPts = pts;
695             if (dashRemaining <= 0)
696             {
697                 if (++(dinfo->dashIndex) == pGC->numInDashList)
698                     dinfo->dashIndex = 0;
699                 dashRemaining = pGC->dash[dinfo->dashIndex];
700             }
701         }
702     }
703     dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
704 }
705
706 void
707 miZeroPolyArc(pDraw, pGC, narcs, parcs)
708     DrawablePtr pDraw;
709     GCPtr       pGC;
710     int         narcs;
711     xArc        *parcs;
712 {
713     int maxPts = 0;
714     register int n, maxw;
715     register xArc *arc;
716     register int i;
717     DDXPointPtr points, pts, oddPts;
718     register DDXPointPtr pt;
719     int numPts;
720     Bool dospans;
721     int *widths;
722     XID fgPixel = pGC->fgPixel;
723     DashInfo dinfo;
724
725     for (arc = parcs, i = narcs; --i >= 0; arc++)
726     {
727         if (!miCanZeroArc(arc))
728             miPolyArc(pDraw, pGC, 1, arc);
729         else
730         {
731             if (arc->width > arc->height)
732                 n = arc->width + (arc->height >> 1);
733             else
734                 n = arc->height + (arc->width >> 1);
735             if (n > maxPts)
736                 maxPts = n;
737         }
738     }
739     if (!maxPts)
740         return;
741     numPts = maxPts << 2;
742     dospans = (pGC->lineStyle != LineSolid) || (pGC->fillStyle != FillSolid);
743     if (dospans)
744     {
745         widths = (int *)ALLOCATE_LOCAL(sizeof(int) * numPts);
746         if (!widths)
747             return;
748         maxw = 0;
749     }
750     if (pGC->lineStyle != LineSolid)
751     {
752         numPts <<= 1;
753         dinfo.haveStart = FALSE;
754         dinfo.skipStart = FALSE;
755         dinfo.haveLast = FALSE;
756         dinfo.dashIndexInit = 0;
757         dinfo.dashOffsetInit = 0;
758         miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
759                    (unsigned char *) pGC->dash, (int)pGC->numInDashList,
760                    &dinfo.dashOffsetInit);
761     }
762     points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * numPts);
763     if (!points)
764     {
765         if (dospans)
766         {
767             DEALLOCATE_LOCAL(widths);
768         }
769         return;
770     }
771     for (arc = parcs, i = narcs; --i >= 0; arc++)
772     {
773         if (miCanZeroArc(arc))
774         {
775             if (pGC->lineStyle == LineSolid)
776                 pts = miZeroArcPts(arc, points);
777             else
778             {
779                 pts = points;
780                 oddPts = &points[(numPts >> 1) - 1];
781                 dinfo.skipLast = i;
782                 miZeroArcDashPts(pGC, arc, &dinfo,
783                                  oddPts + 1, maxPts, &pts, &oddPts);
784                 dinfo.skipStart = TRUE;
785             }
786             n = pts - points;
787             if (!dospans)
788                 (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
789             else
790             {
791                 if (n > maxw)
792                 {
793                     while (maxw < n)
794                         widths[maxw++] = 1;
795                 }
796                 if (pGC->miTranslate)
797                 {
798                     for (pt = points; pt != pts; pt++)
799                     {
800                         pt->x += pDraw->x;
801                         pt->y += pDraw->y;
802                     }
803                 }
804                 (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
805             }
806             if (pGC->lineStyle != LineDoubleDash)
807                 continue;
808             if ((pGC->fillStyle == FillSolid) ||
809                 (pGC->fillStyle == FillStippled))
810             {
811                 DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0);
812                 ValidateGC(pDraw, pGC);
813             }
814             pts = &points[numPts >> 1];
815             oddPts++;
816             n = pts - oddPts;
817             if (!dospans)
818                 (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
819             else
820             {
821                 if (n > maxw)
822                 {
823                     while (maxw < n)
824                         widths[maxw++] = 1;
825                 }
826                 if (pGC->miTranslate)
827                 {
828                     for (pt = oddPts; pt != pts; pt++)
829                     {
830                         pt->x += pDraw->x;
831                         pt->y += pDraw->y;
832                     }
833                 }
834                 (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
835             }
836             if ((pGC->fillStyle == FillSolid) ||
837                 (pGC->fillStyle == FillStippled))
838             {
839                 DoChangeGC(pGC, GCForeground, &fgPixel, 0);
840                 ValidateGC(pDraw, pGC);
841             }
842         }
843     }
844     DEALLOCATE_LOCAL(points);
845     if (dospans)
846     {
847         DEALLOCATE_LOCAL(widths);
848     }
849 }