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