mizerarc.c revision 05b261ec
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 98_X_EXPORT Bool 99miZeroArcSetup(arc, info, ok360) 100 xArc *arc; 101 miZeroArcRec *info; 102 Bool ok360; 103{ 104 int l; 105 int angle1, angle2; 106 int startseg, endseg; 107 int startAngle, endAngle; 108 int i, overlap; 109 miZeroArcPtRec start, end; 110 111 l = arc->width & 1; 112 if (arc->width == arc->height) 113 { 114 info->alpha = 4; 115 info->beta = 4; 116 info->k1 = -8; 117 info->k3 = -16; 118 info->b = 12; 119 info->a = (arc->width << 2) - 12; 120 info->d = 17 - (arc->width << 1); 121 if (l) 122 { 123 info->b -= 4; 124 info->a += 4; 125 info->d -= 7; 126 } 127 } 128 else if (!arc->width || !arc->height) 129 { 130 info->alpha = 0; 131 info->beta = 0; 132 info->k1 = 0; 133 info->k3 = 0; 134 info->a = -(int)arc->height; 135 info->b = 0; 136 info->d = -1; 137 } 138 else 139 { 140 /* initial conditions */ 141 info->alpha = (arc->width * arc->width) << 2; 142 info->beta = (arc->height * arc->height) << 2; 143 info->k1 = info->beta << 1; 144 info->k3 = info->k1 + (info->alpha << 1); 145 info->b = l ? 0 : -info->beta; 146 info->a = info->alpha * arc->height; 147 info->d = info->b - (info->a >> 1) - (info->alpha >> 2); 148 if (l) 149 info->d -= info->beta >> 2; 150 info->a -= info->b; 151 /* take first step, d < 0 always */ 152 info->b -= info->k1; 153 info->a += info->k1; 154 info->d += info->b; 155 /* octant change, b < 0 always */ 156 info->k1 = -info->k1; 157 info->k3 = -info->k3; 158 info->b = -info->b; 159 info->d = info->b - info->a - info->d; 160 info->a = info->a - (info->b << 1); 161 } 162 info->dx = 1; 163 info->dy = 0; 164 info->w = (arc->width + 1) >> 1; 165 info->h = arc->height >> 1; 166 info->xorg = arc->x + (arc->width >> 1); 167 info->yorg = arc->y; 168 info->xorgo = info->xorg + l; 169 info->yorgo = info->yorg + arc->height; 170 if (!arc->width) 171 { 172 if (!arc->height) 173 { 174 info->x = 0; 175 info->y = 0; 176 info->initialMask = 0; 177 info->startAngle = 0; 178 info->endAngle = 0; 179 info->start = oob; 180 info->end = oob; 181 return FALSE; 182 } 183 info->x = 0; 184 info->y = 1; 185 } 186 else 187 { 188 info->x = 1; 189 info->y = 0; 190 } 191 angle1 = arc->angle1; 192 angle2 = arc->angle2; 193 if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) 194 { 195 startAngle = 0; 196 endAngle = 0; 197 } 198 else 199 { 200 if (angle2 > FULLCIRCLE) 201 angle2 = FULLCIRCLE; 202 else if (angle2 < -FULLCIRCLE) 203 angle2 = -FULLCIRCLE; 204 if (angle2 < 0) 205 { 206 startAngle = angle1 + angle2; 207 endAngle = angle1; 208 } 209 else 210 { 211 startAngle = angle1; 212 endAngle = angle1 + angle2; 213 } 214 if (startAngle < 0) 215 startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; 216 if (startAngle >= FULLCIRCLE) 217 startAngle = startAngle % FULLCIRCLE; 218 if (endAngle < 0) 219 endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; 220 if (endAngle >= FULLCIRCLE) 221 endAngle = endAngle % FULLCIRCLE; 222 } 223 info->startAngle = startAngle; 224 info->endAngle = endAngle; 225 if (ok360 && (startAngle == endAngle) && arc->angle2 && 226 arc->width && arc->height) 227 { 228 info->initialMask = 0xf; 229 info->start = oob; 230 info->end = oob; 231 return TRUE; 232 } 233 startseg = startAngle / OCTANT; 234 if (!arc->height || (((startseg + 1) & 2) && arc->width)) 235 { 236 start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0); 237 if (start.x < 0) 238 start.x = -start.x; 239 start.y = -1; 240 } 241 else 242 { 243 start.y = Dsin(startAngle) * (arc->height / 2.0); 244 if (start.y < 0) 245 start.y = -start.y; 246 start.y = info->h - start.y; 247 start.x = 65536; 248 } 249 endseg = endAngle / OCTANT; 250 if (!arc->height || (((endseg + 1) & 2) && arc->width)) 251 { 252 end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0); 253 if (end.x < 0) 254 end.x = -end.x; 255 end.y = -1; 256 } 257 else 258 { 259 end.y = Dsin(endAngle) * (arc->height / 2.0); 260 if (end.y < 0) 261 end.y = -end.y; 262 end.y = info->h - end.y; 263 end.x = 65536; 264 } 265 info->firstx = start.x; 266 info->firsty = start.y; 267 info->initialMask = 0; 268 overlap = arc->angle2 && (endAngle <= startAngle); 269 for (i = 0; i < 4; i++) 270 { 271 if (overlap ? 272 ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) : 273 ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle))) 274 info->initialMask |= (1 << i); 275 } 276 start.mask = info->initialMask; 277 end.mask = info->initialMask; 278 startseg >>= 1; 279 endseg >>= 1; 280 overlap = overlap && (endseg == startseg); 281 if (start.x != end.x || start.y != end.y || !overlap) 282 { 283 if (startseg & 1) 284 { 285 if (!overlap) 286 info->initialMask &= ~(1 << startseg); 287 if (start.x > end.x || start.y > end.y) 288 end.mask &= ~(1 << startseg); 289 } 290 else 291 { 292 start.mask &= ~(1 << startseg); 293 if (((start.x < end.x || start.y < end.y) || 294 (start.x == end.x && start.y == end.y && (endseg & 1))) && 295 !overlap) 296 end.mask &= ~(1 << startseg); 297 } 298 if (endseg & 1) 299 { 300 end.mask &= ~(1 << endseg); 301 if (((start.x > end.x || start.y > end.y) || 302 (start.x == end.x && start.y == end.y && !(startseg & 1))) && 303 !overlap) 304 start.mask &= ~(1 << endseg); 305 } 306 else 307 { 308 if (!overlap) 309 info->initialMask &= ~(1 << endseg); 310 if (start.x < end.x || start.y < end.y) 311 start.mask &= ~(1 << endseg); 312 } 313 } 314 /* take care of case when start and stop are both near 45 */ 315 /* handle here rather than adding extra code to pixelization loops */ 316 if (startAngle && 317 ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) 318 { 319 i = (startAngle + OCTANT) % OCTANT; 320 if (i < EPSILON45 || i > OCTANT - EPSILON45) 321 { 322 i = (endAngle + OCTANT) % OCTANT; 323 if (i < EPSILON45 || i > OCTANT - EPSILON45) 324 { 325 if (start.y < 0) 326 { 327 i = Dsin(startAngle) * (arc->height / 2.0); 328 if (i < 0) 329 i = -i; 330 if (info->h - i == end.y) 331 start.mask = end.mask; 332 } 333 else 334 { 335 i = Dsin(endAngle) * (arc->height / 2.0); 336 if (i < 0) 337 i = -i; 338 if (info->h - i == start.y) 339 end.mask = start.mask; 340 } 341 } 342 } 343 } 344 if (startseg & 1) 345 { 346 info->start = start; 347 info->end = oob; 348 } 349 else 350 { 351 info->end = start; 352 info->start = oob; 353 } 354 if (endseg & 1) 355 { 356 info->altend = end; 357 if (info->altend.x < info->end.x || info->altend.y < info->end.y) 358 { 359 miZeroArcPtRec tmp; 360 tmp = info->altend; 361 info->altend = info->end; 362 info->end = tmp; 363 } 364 info->altstart = oob; 365 } 366 else 367 { 368 info->altstart = end; 369 if (info->altstart.x < info->start.x || 370 info->altstart.y < info->start.y) 371 { 372 miZeroArcPtRec tmp; 373 tmp = info->altstart; 374 info->altstart = info->start; 375 info->start = tmp; 376 } 377 info->altend = oob; 378 } 379 if (!info->start.x || !info->start.y) 380 { 381 info->initialMask = info->start.mask; 382 info->start = info->altstart; 383 } 384 if (!arc->width && (arc->height == 1)) 385 { 386 /* kludge! */ 387 info->initialMask |= info->end.mask; 388 info->initialMask |= info->initialMask << 1; 389 info->end.x = 0; 390 info->end.mask = 0; 391 } 392 return FALSE; 393} 394 395#define Pixelate(xval,yval) \ 396 { \ 397 pts->x = xval; \ 398 pts->y = yval; \ 399 pts++; \ 400 } 401 402#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval); 403 404static DDXPointPtr 405miZeroArcPts(xArc *arc, DDXPointPtr pts) 406{ 407 miZeroArcRec info; 408 int x, y, a, b, d, mask; 409 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 505static void 506miZeroArcDashPts( 507 GCPtr pGC, 508 xArc *arc, 509 DashInfo *dinfo, 510 DDXPointPtr points, 511 int maxPts, 512 DDXPointPtr *evenPts, 513 DDXPointPtr *oddPts ) 514{ 515 miZeroArcRec info; 516 int x, y, a, b, d, mask; 517 int k1, k3, dx, dy; 518 int dashRemaining; 519 DDXPointPtr arcPts[4]; 520 DDXPointPtr startPts[5], endPts[5]; 521 int deltas[5]; 522 DDXPointPtr startPt, pt, lastPt, pts; 523 int i, j, delta, ptsdelta, seg, startseg; 524 525 for (i = 0; i < 4; i++) 526 arcPts[i] = points + (i * maxPts); 527 (void)miZeroArcSetup(arc, &info, FALSE); 528 MIARCSETUP(); 529 mask = info.initialMask; 530 startseg = info.startAngle / QUADRANT; 531 startPt = arcPts[startseg]; 532 if (!(arc->width & 1)) 533 { 534 DoPix(1, info.xorgo, info.yorg); 535 DoPix(3, info.xorgo, info.yorgo); 536 } 537 if (!info.end.x || !info.end.y) 538 { 539 mask = info.end.mask; 540 info.end = info.altend; 541 } 542 while (y < info.h || x < info.w) 543 { 544 MIARCOCTANTSHIFT(;); 545 if ((x == info.firstx) || (y == info.firsty)) 546 startPt = arcPts[startseg]; 547 if ((x == info.start.x) || (y == info.start.y)) 548 { 549 mask = info.start.mask; 550 info.start = info.altstart; 551 } 552 DoPix(0, info.xorg + x, info.yorg + y); 553 DoPix(1, info.xorgo - x, info.yorg + y); 554 DoPix(2, info.xorgo - x, info.yorgo - y); 555 DoPix(3, info.xorg + x, info.yorgo - y); 556 if ((x == info.end.x) || (y == info.end.y)) 557 { 558 mask = info.end.mask; 559 info.end = info.altend; 560 } 561 MIARCSTEP(;,;); 562 } 563 if ((x == info.firstx) || (y == info.firsty)) 564 startPt = arcPts[startseg]; 565 if ((x == info.start.x) || (y == info.start.y)) 566 mask = info.start.mask; 567 DoPix(0, info.xorg + x, info.yorg + y); 568 DoPix(2, info.xorgo - x, info.yorgo - y); 569 if (arc->height & 1) 570 { 571 DoPix(1, info.xorgo - x, info.yorg + y); 572 DoPix(3, info.xorg + x, info.yorgo - y); 573 } 574 for (i = 0; i < 4; i++) 575 { 576 seg = (startseg + i) & 3; 577 pt = points + (seg * maxPts); 578 if (seg & 1) 579 { 580 startPts[i] = pt; 581 endPts[i] = arcPts[seg]; 582 deltas[i] = 1; 583 } 584 else 585 { 586 startPts[i] = arcPts[seg] - 1; 587 endPts[i] = pt - 1; 588 deltas[i] = -1; 589 } 590 } 591 startPts[4] = startPts[0]; 592 endPts[4] = startPt; 593 startPts[0] = startPt; 594 if (startseg & 1) 595 { 596 if (startPts[4] != endPts[4]) 597 endPts[4]--; 598 deltas[4] = 1; 599 } 600 else 601 { 602 if (startPts[0] > startPts[4]) 603 startPts[0]--; 604 if (startPts[4] < endPts[4]) 605 endPts[4]--; 606 deltas[4] = -1; 607 } 608 if (arc->angle2 < 0) 609 { 610 DDXPointPtr tmps, tmpe; 611 int tmpd; 612 613 tmpd = deltas[0]; 614 tmps = startPts[0] - tmpd; 615 tmpe = endPts[0] - tmpd; 616 startPts[0] = endPts[4] - deltas[4]; 617 endPts[0] = startPts[4] - deltas[4]; 618 deltas[0] = -deltas[4]; 619 startPts[4] = tmpe; 620 endPts[4] = tmps; 621 deltas[4] = -tmpd; 622 tmpd = deltas[1]; 623 tmps = startPts[1] - tmpd; 624 tmpe = endPts[1] - tmpd; 625 startPts[1] = endPts[3] - deltas[3]; 626 endPts[1] = startPts[3] - deltas[3]; 627 deltas[1] = -deltas[3]; 628 startPts[3] = tmpe; 629 endPts[3] = tmps; 630 deltas[3] = -tmpd; 631 tmps = startPts[2] - deltas[2]; 632 startPts[2] = endPts[2] - deltas[2]; 633 endPts[2] = tmps; 634 deltas[2] = -deltas[2]; 635 } 636 for (i = 0; i < 5 && startPts[i] == endPts[i]; i++) 637 ; 638 if (i == 5) 639 return; 640 pt = startPts[i]; 641 for (j = 4; startPts[j] == endPts[j]; j--) 642 ; 643 lastPt = endPts[j] - deltas[j]; 644 if (dinfo->haveLast && 645 (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) 646 { 647 startPts[i] += deltas[i]; 648 } 649 else 650 { 651 dinfo->dashIndex = dinfo->dashIndexInit; 652 dinfo->dashOffset = dinfo->dashOffsetInit; 653 } 654 if (!dinfo->skipStart && (info.startAngle != info.endAngle)) 655 { 656 dinfo->startPt = *pt; 657 dinfo->haveStart = TRUE; 658 } 659 else if (!dinfo->skipLast && dinfo->haveStart && 660 (lastPt->x == dinfo->startPt.x) && 661 (lastPt->y == dinfo->startPt.y) && 662 (lastPt != startPts[i])) 663 endPts[j] = lastPt; 664 if (info.startAngle != info.endAngle) 665 { 666 dinfo->haveLast = TRUE; 667 dinfo->endPt = *lastPt; 668 } 669 dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset; 670 for (i = 0; i < 5; i++) 671 { 672 pt = startPts[i]; 673 lastPt = endPts[i]; 674 delta = deltas[i]; 675 while (pt != lastPt) 676 { 677 if (dinfo->dashIndex & 1) 678 { 679 pts = *oddPts; 680 ptsdelta = -1; 681 } 682 else 683 { 684 pts = *evenPts; 685 ptsdelta = 1; 686 } 687 while ((pt != lastPt) && --dashRemaining >= 0) 688 { 689 *pts = *pt; 690 pts += ptsdelta; 691 pt += delta; 692 } 693 if (dinfo->dashIndex & 1) 694 *oddPts = pts; 695 else 696 *evenPts = pts; 697 if (dashRemaining <= 0) 698 { 699 if (++(dinfo->dashIndex) == pGC->numInDashList) 700 dinfo->dashIndex = 0; 701 dashRemaining = pGC->dash[dinfo->dashIndex]; 702 } 703 } 704 } 705 dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining; 706} 707 708_X_EXPORT void 709miZeroPolyArc(pDraw, pGC, narcs, parcs) 710 DrawablePtr pDraw; 711 GCPtr pGC; 712 int narcs; 713 xArc *parcs; 714{ 715 int maxPts = 0; 716 int n, maxw = 0; 717 xArc *arc; 718 int i; 719 DDXPointPtr points, pts, oddPts; 720 DDXPointPtr pt; 721 int numPts; 722 Bool dospans; 723 int *widths = NULL; 724 XID fgPixel = pGC->fgPixel; 725 DashInfo dinfo; 726 727 for (arc = parcs, i = narcs; --i >= 0; arc++) 728 { 729 if (!miCanZeroArc(arc)) 730 miPolyArc(pDraw, pGC, 1, arc); 731 else 732 { 733 if (arc->width > arc->height) 734 n = arc->width + (arc->height >> 1); 735 else 736 n = arc->height + (arc->width >> 1); 737 if (n > maxPts) 738 maxPts = n; 739 } 740 } 741 if (!maxPts) 742 return; 743 numPts = maxPts << 2; 744 dospans = (pGC->fillStyle != FillSolid); 745 if (dospans) 746 { 747 widths = (int *)ALLOCATE_LOCAL(sizeof(int) * numPts); 748 if (!widths) 749 return; 750 maxw = 0; 751 } 752 if (pGC->lineStyle != LineSolid) 753 { 754 numPts <<= 1; 755 dinfo.haveStart = FALSE; 756 dinfo.skipStart = FALSE; 757 dinfo.haveLast = FALSE; 758 dinfo.dashIndexInit = 0; 759 dinfo.dashOffsetInit = 0; 760 miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit, 761 (unsigned char *) pGC->dash, (int)pGC->numInDashList, 762 &dinfo.dashOffsetInit); 763 } 764 points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * numPts); 765 if (!points) 766 { 767 if (dospans) 768 { 769 DEALLOCATE_LOCAL(widths); 770 } 771 return; 772 } 773 for (arc = parcs, i = narcs; --i >= 0; arc++) 774 { 775 if (miCanZeroArc(arc)) 776 { 777 if (pGC->lineStyle == LineSolid) 778 pts = miZeroArcPts(arc, points); 779 else 780 { 781 pts = points; 782 oddPts = &points[(numPts >> 1) - 1]; 783 dinfo.skipLast = i; 784 miZeroArcDashPts(pGC, arc, &dinfo, 785 oddPts + 1, maxPts, &pts, &oddPts); 786 dinfo.skipStart = TRUE; 787 } 788 n = pts - points; 789 if (!dospans) 790 (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points); 791 else 792 { 793 if (n > maxw) 794 { 795 while (maxw < n) 796 widths[maxw++] = 1; 797 } 798 if (pGC->miTranslate) 799 { 800 for (pt = points; pt != pts; pt++) 801 { 802 pt->x += pDraw->x; 803 pt->y += pDraw->y; 804 } 805 } 806 (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE); 807 } 808 if (pGC->lineStyle != LineDoubleDash) 809 continue; 810 if ((pGC->fillStyle == FillSolid) || 811 (pGC->fillStyle == FillStippled)) 812 { 813 DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0); 814 ValidateGC(pDraw, pGC); 815 } 816 pts = &points[numPts >> 1]; 817 oddPts++; 818 n = pts - oddPts; 819 if (!dospans) 820 (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts); 821 else 822 { 823 if (n > maxw) 824 { 825 while (maxw < n) 826 widths[maxw++] = 1; 827 } 828 if (pGC->miTranslate) 829 { 830 for (pt = oddPts; pt != pts; pt++) 831 { 832 pt->x += pDraw->x; 833 pt->y += pDraw->y; 834 } 835 } 836 (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE); 837 } 838 if ((pGC->fillStyle == FillSolid) || 839 (pGC->fillStyle == FillStippled)) 840 { 841 DoChangeGC(pGC, GCForeground, &fgPixel, 0); 842 ValidateGC(pDraw, pGC); 843 } 844 } 845 } 846 DEALLOCATE_LOCAL(points); 847 if (dospans) 848 { 849 DEALLOCATE_LOCAL(widths); 850 } 851} 852