Imported Upstream version 1.15.1
[deb_xorg-server.git] / mi / mizerarc.c
CommitLineData
a09e091a
JB
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/* Derived from:
30 * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
31 * by M. L. V. Pitteway
32 * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
33 */
34
35#ifdef HAVE_DIX_CONFIG_H
36#include <dix-config.h>
37#endif
38
39#include <math.h>
40#include <X11/X.h>
41#include <X11/Xprotostr.h>
42#include "regionstr.h"
43#include "gcstruct.h"
44#include "pixmapstr.h"
45#include "mi.h"
46#include "mizerarc.h"
47
48#define FULLCIRCLE (360 * 64)
49#define OCTANT (45 * 64)
50#define QUADRANT (90 * 64)
51#define HALFCIRCLE (180 * 64)
52#define QUADRANT3 (270 * 64)
53
54#ifndef M_PI
55#define M_PI 3.14159265358979323846
56#endif
57
58#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
59 ((d) == HALFCIRCLE ? 0.0 : \
60 ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
61
62#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
63 ((d) == HALFCIRCLE ? -1.0 : \
64 ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
65
66#define EPSILON45 64
67
68typedef struct {
69 int skipStart;
70 int haveStart;
71 DDXPointRec startPt;
72 int haveLast;
73 int skipLast;
74 DDXPointRec endPt;
75 int dashIndex;
76 int dashOffset;
77 int dashIndexInit;
78 int dashOffsetInit;
79} DashInfo;
80
81static miZeroArcPtRec oob = { 65536, 65536, 0 };
82
83/*
84 * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1
85 *
86 * where l is either 0 or .5
87 *
88 * alpha = 4(W^2)
89 * beta = 4(H^2)
90 * gamma = 0
91 * u = 2(W^2)H
92 * v = 4(H^2)l
93 * k = -4(H^2)(l^2)
94 *
95 */
96
97Bool
98miZeroArcSetup(xArc * arc, miZeroArcRec * info, Bool ok360)
99{
100 int l;
101 int angle1, angle2;
102 int startseg, endseg;
103 int startAngle, endAngle;
104 int i, overlap;
105 miZeroArcPtRec start, end;
106
107 l = arc->width & 1;
108 if (arc->width == arc->height) {
109 info->alpha = 4;
110 info->beta = 4;
111 info->k1 = -8;
112 info->k3 = -16;
113 info->b = 12;
114 info->a = (arc->width << 2) - 12;
115 info->d = 17 - (arc->width << 1);
116 if (l) {
117 info->b -= 4;
118 info->a += 4;
119 info->d -= 7;
120 }
121 }
122 else if (!arc->width || !arc->height) {
123 info->alpha = 0;
124 info->beta = 0;
125 info->k1 = 0;
126 info->k3 = 0;
127 info->a = -(int) arc->height;
128 info->b = 0;
129 info->d = -1;
130 }
131 else {
132 /* initial conditions */
133 info->alpha = (arc->width * arc->width) << 2;
134 info->beta = (arc->height * arc->height) << 2;
135 info->k1 = info->beta << 1;
136 info->k3 = info->k1 + (info->alpha << 1);
137 info->b = l ? 0 : -info->beta;
138 info->a = info->alpha * arc->height;
139 info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
140 if (l)
141 info->d -= info->beta >> 2;
142 info->a -= info->b;
143 /* take first step, d < 0 always */
144 info->b -= info->k1;
145 info->a += info->k1;
146 info->d += info->b;
147 /* octant change, b < 0 always */
148 info->k1 = -info->k1;
149 info->k3 = -info->k3;
150 info->b = -info->b;
151 info->d = info->b - info->a - info->d;
152 info->a = info->a - (info->b << 1);
153 }
154 info->dx = 1;
155 info->dy = 0;
156 info->w = (arc->width + 1) >> 1;
157 info->h = arc->height >> 1;
158 info->xorg = arc->x + (arc->width >> 1);
159 info->yorg = arc->y;
160 info->xorgo = info->xorg + l;
161 info->yorgo = info->yorg + arc->height;
162 if (!arc->width) {
163 if (!arc->height) {
164 info->x = 0;
165 info->y = 0;
166 info->initialMask = 0;
167 info->startAngle = 0;
168 info->endAngle = 0;
169 info->start = oob;
170 info->end = oob;
171 return FALSE;
172 }
173 info->x = 0;
174 info->y = 1;
175 }
176 else {
177 info->x = 1;
178 info->y = 0;
179 }
180 angle1 = arc->angle1;
181 angle2 = arc->angle2;
182 if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) {
183 startAngle = 0;
184 endAngle = 0;
185 }
186 else {
187 if (angle2 > FULLCIRCLE)
188 angle2 = FULLCIRCLE;
189 else if (angle2 < -FULLCIRCLE)
190 angle2 = -FULLCIRCLE;
191 if (angle2 < 0) {
192 startAngle = angle1 + angle2;
193 endAngle = angle1;
194 }
195 else {
196 startAngle = angle1;
197 endAngle = angle1 + angle2;
198 }
199 if (startAngle < 0)
200 startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
201 if (startAngle >= FULLCIRCLE)
202 startAngle = startAngle % FULLCIRCLE;
203 if (endAngle < 0)
204 endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
205 if (endAngle >= FULLCIRCLE)
206 endAngle = endAngle % FULLCIRCLE;
207 }
208 info->startAngle = startAngle;
209 info->endAngle = endAngle;
210 if (ok360 && (startAngle == endAngle) && arc->angle2 &&
211 arc->width && arc->height) {
212 info->initialMask = 0xf;
213 info->start = oob;
214 info->end = oob;
215 return TRUE;
216 }
217 startseg = startAngle / OCTANT;
218 if (!arc->height || (((startseg + 1) & 2) && arc->width)) {
219 start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
220 if (start.x < 0)
221 start.x = -start.x;
222 start.y = -1;
223 }
224 else {
225 start.y = Dsin(startAngle) * (arc->height / 2.0);
226 if (start.y < 0)
227 start.y = -start.y;
228 start.y = info->h - start.y;
229 start.x = 65536;
230 }
231 endseg = endAngle / OCTANT;
232 if (!arc->height || (((endseg + 1) & 2) && arc->width)) {
233 end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
234 if (end.x < 0)
235 end.x = -end.x;
236 end.y = -1;
237 }
238 else {
239 end.y = Dsin(endAngle) * (arc->height / 2.0);
240 if (end.y < 0)
241 end.y = -end.y;
242 end.y = info->h - end.y;
243 end.x = 65536;
244 }
245 info->firstx = start.x;
246 info->firsty = start.y;
247 info->initialMask = 0;
248 overlap = arc->angle2 && (endAngle <= startAngle);
249 for (i = 0; i < 4; i++) {
250 if (overlap ?
251 ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
252 ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
253 info->initialMask |= (1 << i);
254 }
255 start.mask = info->initialMask;
256 end.mask = info->initialMask;
257 startseg >>= 1;
258 endseg >>= 1;
259 overlap = overlap && (endseg == startseg);
260 if (start.x != end.x || start.y != end.y || !overlap) {
261 if (startseg & 1) {
262 if (!overlap)
263 info->initialMask &= ~(1 << startseg);
264 if (start.x > end.x || start.y > end.y)
265 end.mask &= ~(1 << startseg);
266 }
267 else {
268 start.mask &= ~(1 << startseg);
269 if (((start.x < end.x || start.y < end.y) ||
270 (start.x == end.x && start.y == end.y && (endseg & 1))) &&
271 !overlap)
272 end.mask &= ~(1 << startseg);
273 }
274 if (endseg & 1) {
275 end.mask &= ~(1 << endseg);
276 if (((start.x > end.x || start.y > end.y) ||
277 (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
278 !overlap)
279 start.mask &= ~(1 << endseg);
280 }
281 else {
282 if (!overlap)
283 info->initialMask &= ~(1 << endseg);
284 if (start.x < end.x || start.y < end.y)
285 start.mask &= ~(1 << endseg);
286 }
287 }
288 /* take care of case when start and stop are both near 45 */
289 /* handle here rather than adding extra code to pixelization loops */
290 if (startAngle &&
291 ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) {
292 i = (startAngle + OCTANT) % OCTANT;
293 if (i < EPSILON45 || i > OCTANT - EPSILON45) {
294 i = (endAngle + OCTANT) % OCTANT;
295 if (i < EPSILON45 || i > OCTANT - EPSILON45) {
296 if (start.y < 0) {
297 i = Dsin(startAngle) * (arc->height / 2.0);
298 if (i < 0)
299 i = -i;
300 if (info->h - i == end.y)
301 start.mask = end.mask;
302 }
303 else {
304 i = Dsin(endAngle) * (arc->height / 2.0);
305 if (i < 0)
306 i = -i;
307 if (info->h - i == start.y)
308 end.mask = start.mask;
309 }
310 }
311 }
312 }
313 if (startseg & 1) {
314 info->start = start;
315 info->end = oob;
316 }
317 else {
318 info->end = start;
319 info->start = oob;
320 }
321 if (endseg & 1) {
322 info->altend = end;
323 if (info->altend.x < info->end.x || info->altend.y < info->end.y) {
324 miZeroArcPtRec tmp;
325
326 tmp = info->altend;
327 info->altend = info->end;
328 info->end = tmp;
329 }
330 info->altstart = oob;
331 }
332 else {
333 info->altstart = end;
334 if (info->altstart.x < info->start.x ||
335 info->altstart.y < info->start.y) {
336 miZeroArcPtRec tmp;
337
338 tmp = info->altstart;
339 info->altstart = info->start;
340 info->start = tmp;
341 }
342 info->altend = oob;
343 }
344 if (!info->start.x || !info->start.y) {
345 info->initialMask = info->start.mask;
346 info->start = info->altstart;
347 }
348 if (!arc->width && (arc->height == 1)) {
349 /* kludge! */
350 info->initialMask |= info->end.mask;
351 info->initialMask |= info->initialMask << 1;
352 info->end.x = 0;
353 info->end.mask = 0;
354 }
355 return FALSE;
356}
357
358#define Pixelate(xval,yval) \
359 { \
360 pts->x = xval; \
361 pts->y = yval; \
362 pts++; \
363 }
364
365#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
366
367static DDXPointPtr
368miZeroArcPts(xArc * arc, DDXPointPtr pts)
369{
370 miZeroArcRec info;
371 int x, y, a, b, d, mask;
372 int k1, k3, dx, dy;
373 Bool do360;
374
375 do360 = miZeroArcSetup(arc, &info, TRUE);
376 MIARCSETUP();
377 mask = info.initialMask;
378 if (!(arc->width & 1)) {
379 DoPix(1, info.xorgo, info.yorg);
380 DoPix(3, info.xorgo, info.yorgo);
381 }
382 if (!info.end.x || !info.end.y) {
383 mask = info.end.mask;
384 info.end = info.altend;
385 }
386 if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
387 int yorgh = info.yorg + info.h;
388 int xorghp = info.xorg + info.h;
389 int xorghn = info.xorg - info.h;
390
391 while (1) {
392 Pixelate(info.xorg + x, info.yorg + y);
393 Pixelate(info.xorg - x, info.yorg + y);
394 Pixelate(info.xorg - x, info.yorgo - y);
395 Pixelate(info.xorg + x, info.yorgo - y);
396 if (a < 0)
397 break;
398 Pixelate(xorghp - y, yorgh - x);
399 Pixelate(xorghn + y, yorgh - x);
400 Pixelate(xorghn + y, yorgh + x);
401 Pixelate(xorghp - y, yorgh + x);
402 MIARCCIRCLESTEP(;
403 );
404 }
405 if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
406 pts -= 4;
407 x = info.w;
408 y = info.h;
409 }
410 else if (do360) {
411 while (y < info.h || x < info.w) {
412 MIARCOCTANTSHIFT(;
413 );
414 Pixelate(info.xorg + x, info.yorg + y);
415 Pixelate(info.xorgo - x, info.yorg + y);
416 Pixelate(info.xorgo - x, info.yorgo - y);
417 Pixelate(info.xorg + x, info.yorgo - y);
418 MIARCSTEP(;
419 ,;
420 );
421 }
422 }
423 else {
424 while (y < info.h || x < info.w) {
425 MIARCOCTANTSHIFT(;
426 );
427 if ((x == info.start.x) || (y == info.start.y)) {
428 mask = info.start.mask;
429 info.start = info.altstart;
430 }
431 DoPix(0, info.xorg + x, info.yorg + y);
432 DoPix(1, info.xorgo - x, info.yorg + y);
433 DoPix(2, info.xorgo - x, info.yorgo - y);
434 DoPix(3, info.xorg + x, info.yorgo - y);
435 if ((x == info.end.x) || (y == info.end.y)) {
436 mask = info.end.mask;
437 info.end = info.altend;
438 }
439 MIARCSTEP(;
440 ,;
441 );
442 }
443 }
444 if ((x == info.start.x) || (y == info.start.y))
445 mask = info.start.mask;
446 DoPix(0, info.xorg + x, info.yorg + y);
447 DoPix(2, info.xorgo - x, info.yorgo - y);
448 if (arc->height & 1) {
449 DoPix(1, info.xorgo - x, info.yorg + y);
450 DoPix(3, info.xorg + x, info.yorgo - y);
451 }
452 return pts;
453}
454
455#undef DoPix
456#define DoPix(idx,xval,yval) \
457 if (mask & (1 << idx)) \
458 { \
459 arcPts[idx]->x = xval; \
460 arcPts[idx]->y = yval; \
461 arcPts[idx]++; \
462 }
463
464static void
465miZeroArcDashPts(GCPtr pGC,
466 xArc * arc,
467 DashInfo * dinfo,
468 DDXPointPtr points,
469 int maxPts, DDXPointPtr * evenPts, DDXPointPtr * oddPts)
470{
471 miZeroArcRec info;
472 int x, y, a, b, d, mask;
473 int k1, k3, dx, dy;
474 int dashRemaining;
475 DDXPointPtr arcPts[4];
476 DDXPointPtr startPts[5], endPts[5];
477 int deltas[5];
478 DDXPointPtr startPt, pt, lastPt, pts;
479 int i, j, delta, ptsdelta, seg, startseg;
480
481 for (i = 0; i < 4; i++)
482 arcPts[i] = points + (i * maxPts);
483 (void) miZeroArcSetup(arc, &info, FALSE);
484 MIARCSETUP();
485 mask = info.initialMask;
486 startseg = info.startAngle / QUADRANT;
487 startPt = arcPts[startseg];
488 if (!(arc->width & 1)) {
489 DoPix(1, info.xorgo, info.yorg);
490 DoPix(3, info.xorgo, info.yorgo);
491 }
492 if (!info.end.x || !info.end.y) {
493 mask = info.end.mask;
494 info.end = info.altend;
495 }
496 while (y < info.h || x < info.w) {
497 MIARCOCTANTSHIFT(;
498 );
499 if ((x == info.firstx) || (y == info.firsty))
500 startPt = arcPts[startseg];
501 if ((x == info.start.x) || (y == info.start.y)) {
502 mask = info.start.mask;
503 info.start = info.altstart;
504 }
505 DoPix(0, info.xorg + x, info.yorg + y);
506 DoPix(1, info.xorgo - x, info.yorg + y);
507 DoPix(2, info.xorgo - x, info.yorgo - y);
508 DoPix(3, info.xorg + x, info.yorgo - y);
509 if ((x == info.end.x) || (y == info.end.y)) {
510 mask = info.end.mask;
511 info.end = info.altend;
512 }
513 MIARCSTEP(;
514 ,;
515 );
516 }
517 if ((x == info.firstx) || (y == info.firsty))
518 startPt = arcPts[startseg];
519 if ((x == info.start.x) || (y == info.start.y))
520 mask = info.start.mask;
521 DoPix(0, info.xorg + x, info.yorg + y);
522 DoPix(2, info.xorgo - x, info.yorgo - y);
523 if (arc->height & 1) {
524 DoPix(1, info.xorgo - x, info.yorg + y);
525 DoPix(3, info.xorg + x, info.yorgo - y);
526 }
527 for (i = 0; i < 4; i++) {
528 seg = (startseg + i) & 3;
529 pt = points + (seg * maxPts);
530 if (seg & 1) {
531 startPts[i] = pt;
532 endPts[i] = arcPts[seg];
533 deltas[i] = 1;
534 }
535 else {
536 startPts[i] = arcPts[seg] - 1;
537 endPts[i] = pt - 1;
538 deltas[i] = -1;
539 }
540 }
541 startPts[4] = startPts[0];
542 endPts[4] = startPt;
543 startPts[0] = startPt;
544 if (startseg & 1) {
545 if (startPts[4] != endPts[4])
546 endPts[4]--;
547 deltas[4] = 1;
548 }
549 else {
550 if (startPts[0] > startPts[4])
551 startPts[0]--;
552 if (startPts[4] < endPts[4])
553 endPts[4]--;
554 deltas[4] = -1;
555 }
556 if (arc->angle2 < 0) {
557 DDXPointPtr tmps, tmpe;
558 int tmpd;
559
560 tmpd = deltas[0];
561 tmps = startPts[0] - tmpd;
562 tmpe = endPts[0] - tmpd;
563 startPts[0] = endPts[4] - deltas[4];
564 endPts[0] = startPts[4] - deltas[4];
565 deltas[0] = -deltas[4];
566 startPts[4] = tmpe;
567 endPts[4] = tmps;
568 deltas[4] = -tmpd;
569 tmpd = deltas[1];
570 tmps = startPts[1] - tmpd;
571 tmpe = endPts[1] - tmpd;
572 startPts[1] = endPts[3] - deltas[3];
573 endPts[1] = startPts[3] - deltas[3];
574 deltas[1] = -deltas[3];
575 startPts[3] = tmpe;
576 endPts[3] = tmps;
577 deltas[3] = -tmpd;
578 tmps = startPts[2] - deltas[2];
579 startPts[2] = endPts[2] - deltas[2];
580 endPts[2] = tmps;
581 deltas[2] = -deltas[2];
582 }
583 for (i = 0; i < 5 && startPts[i] == endPts[i]; i++);
584 if (i == 5)
585 return;
586 pt = startPts[i];
587 for (j = 4; startPts[j] == endPts[j]; j--);
588 lastPt = endPts[j] - deltas[j];
589 if (dinfo->haveLast &&
590 (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) {
591 startPts[i] += deltas[i];
592 }
593 else {
594 dinfo->dashIndex = dinfo->dashIndexInit;
595 dinfo->dashOffset = dinfo->dashOffsetInit;
596 }
597 if (!dinfo->skipStart && (info.startAngle != info.endAngle)) {
598 dinfo->startPt = *pt;
599 dinfo->haveStart = TRUE;
600 }
601 else if (!dinfo->skipLast && dinfo->haveStart &&
602 (lastPt->x == dinfo->startPt.x) &&
603 (lastPt->y == dinfo->startPt.y) && (lastPt != startPts[i]))
604 endPts[j] = lastPt;
605 if (info.startAngle != info.endAngle) {
606 dinfo->haveLast = TRUE;
607 dinfo->endPt = *lastPt;
608 }
609 dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
610 for (i = 0; i < 5; i++) {
611 pt = startPts[i];
612 lastPt = endPts[i];
613 delta = deltas[i];
614 while (pt != lastPt) {
615 if (dinfo->dashIndex & 1) {
616 pts = *oddPts;
617 ptsdelta = -1;
618 }
619 else {
620 pts = *evenPts;
621 ptsdelta = 1;
622 }
623 while ((pt != lastPt) && --dashRemaining >= 0) {
624 *pts = *pt;
625 pts += ptsdelta;
626 pt += delta;
627 }
628 if (dinfo->dashIndex & 1)
629 *oddPts = pts;
630 else
631 *evenPts = pts;
632 if (dashRemaining <= 0) {
633 if (++(dinfo->dashIndex) == pGC->numInDashList)
634 dinfo->dashIndex = 0;
635 dashRemaining = pGC->dash[dinfo->dashIndex];
636 }
637 }
638 }
639 dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
640}
641
642void
643miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
644{
645 int maxPts = 0;
646 int n, maxw = 0;
647 xArc *arc;
648 int i;
649 DDXPointPtr points, pts, oddPts = NULL;
650 DDXPointPtr pt;
651 int numPts;
652 Bool dospans;
653 int *widths = NULL;
654 XID fgPixel = pGC->fgPixel;
655 DashInfo dinfo;
656
657 for (arc = parcs, i = narcs; --i >= 0; arc++) {
658 if (!miCanZeroArc(arc))
659 miPolyArc(pDraw, pGC, 1, arc);
660 else {
661 if (arc->width > arc->height)
662 n = arc->width + (arc->height >> 1);
663 else
664 n = arc->height + (arc->width >> 1);
665 if (n > maxPts)
666 maxPts = n;
667 }
668 }
669 if (!maxPts)
670 return;
671 numPts = maxPts << 2;
672 dospans = (pGC->fillStyle != FillSolid);
673 if (dospans) {
674 widths = malloc(sizeof(int) * numPts);
675 if (!widths)
676 return;
677 maxw = 0;
678 }
679 if (pGC->lineStyle != LineSolid) {
680 numPts <<= 1;
681 dinfo.haveStart = FALSE;
682 dinfo.skipStart = FALSE;
683 dinfo.haveLast = FALSE;
684 dinfo.dashIndexInit = 0;
685 dinfo.dashOffsetInit = 0;
686 miStepDash((int) pGC->dashOffset, &dinfo.dashIndexInit,
687 (unsigned char *) pGC->dash, (int) pGC->numInDashList,
688 &dinfo.dashOffsetInit);
689 }
690 points = malloc(sizeof(DDXPointRec) * numPts);
691 if (!points) {
692 if (dospans) {
693 free(widths);
694 }
695 return;
696 }
697 for (arc = parcs, i = narcs; --i >= 0; arc++) {
698 if (miCanZeroArc(arc)) {
699 if (pGC->lineStyle == LineSolid)
700 pts = miZeroArcPts(arc, points);
701 else {
702 pts = points;
703 oddPts = &points[(numPts >> 1) - 1];
704 dinfo.skipLast = i;
705 miZeroArcDashPts(pGC, arc, &dinfo,
706 oddPts + 1, maxPts, &pts, &oddPts);
707 dinfo.skipStart = TRUE;
708 }
709 n = pts - points;
710 if (!dospans)
711 (*pGC->ops->PolyPoint) (pDraw, pGC, CoordModeOrigin, n, points);
712 else {
713 if (n > maxw) {
714 while (maxw < n)
715 widths[maxw++] = 1;
716 }
717 if (pGC->miTranslate) {
718 for (pt = points; pt != pts; pt++) {
719 pt->x += pDraw->x;
720 pt->y += pDraw->y;
721 }
722 }
723 (*pGC->ops->FillSpans) (pDraw, pGC, n, points, widths, FALSE);
724 }
725 if (pGC->lineStyle != LineDoubleDash)
726 continue;
727 if ((pGC->fillStyle == FillSolid) ||
728 (pGC->fillStyle == FillStippled)) {
729 ChangeGCVal gcval;
730
731 gcval.val = pGC->bgPixel;
732 ChangeGC(NullClient, pGC, GCForeground, &gcval);
733 ValidateGC(pDraw, pGC);
734 }
735 pts = &points[numPts >> 1];
736 oddPts++;
737 n = pts - oddPts;
738 if (!dospans)
739 (*pGC->ops->PolyPoint) (pDraw, pGC, CoordModeOrigin, n, oddPts);
740 else {
741 if (n > maxw) {
742 while (maxw < n)
743 widths[maxw++] = 1;
744 }
745 if (pGC->miTranslate) {
746 for (pt = oddPts; pt != pts; pt++) {
747 pt->x += pDraw->x;
748 pt->y += pDraw->y;
749 }
750 }
751 (*pGC->ops->FillSpans) (pDraw, pGC, n, oddPts, widths, FALSE);
752 }
753 if ((pGC->fillStyle == FillSolid) ||
754 (pGC->fillStyle == FillStippled)) {
755 ChangeGCVal gcval;
756
757 gcval.val = fgPixel;
758 ChangeGC(NullClient, pGC, GCForeground, &gcval);
759 ValidateGC(pDraw, pGC);
760 }
761 }
762 }
763 free(points);
764 if (dospans) {
765 free(widths);
766 }
767}