1/* 2 3XAAPolylinesWideSolid does not maintain a span list and subsequently does 4not follow the "touch-each-pixel-once" rules for wide lines and arcs. 5This means it can only be used in the case where we have 6miSpansEasyRop(pGC->alu). Since we clip spans on the fly, we 7limited usage of this function to one rect situations. This 8function is used only for solid lines. 9 10 Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu) 11Original mi code written by Keith Packard. 12 13*/ 14 15#ifdef HAVE_XORG_CONFIG_H 16#include <xorg-config.h> 17#endif 18 19#include <math.h> 20 21#include "misc.h" 22#include "xf86.h" 23#include "xf86_OSproc.h" 24 25#include <X11/X.h> 26#include "windowstr.h" 27#include "gcstruct.h" 28#include "regionstr.h" 29#include "miwideline.h" 30#include "mi.h" 31#include "xf86str.h" 32#include "xaa.h" 33#include "xaalocal.h" 34 35#define DRAW_POINT(pScrn, x, y) \ 36 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \ 37 else XAAPointHelper(pScrn, x, y) 38 39#define FILL_RECT(pScrn, x, y, w, h) \ 40 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); \ 41 else XAAFillRectHelper(pScrn, x, y, w, h) 42 43#define FILL_SPAN(pScrn, x, y, w) \ 44 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, 1); \ 45 else XAASpanHelper(pScrn, x, y, w) 46 47 48#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ 49 if (ybase == edgey) { \ 50 if (edgeleft) { \ 51 if (edge->x > xcl) \ 52 xcl = edge->x; \ 53 } else { \ 54 if (edge->x < xcr) \ 55 xcr = edge->x; \ 56 } \ 57 edgey++; \ 58 edge->x += edge->stepx; \ 59 edge->e += edge->dx; \ 60 if (edge->e > 0) { \ 61 edge->x += edge->signdx; \ 62 edge->e -= edge->dy; \ 63 } \ 64 } 65 66static void 67XAAPointHelper(ScrnInfoPtr pScrn, int x, int y) 68{ 69 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 70 BoxPtr extents = infoRec->ClipBox; 71 72 if((x >= extents->x1) && (x < extents->x2) && 73 (y >= extents->y1) && (y < extents->y2)) 74 (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); 75} 76 77static void 78XAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy) 79{ 80 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 81 BoxPtr extents = infoRec->ClipBox; 82 int x2 = x1 + dx; 83 int y2 = y1 + dy; 84 85 if(x1 < extents->x1) x1 = extents->x1; 86 if(x2 >= extents->x2) x2 = extents->x2; 87 if((dx = x2 - x1)<1) return; 88 if(y1 < extents->y1) y1 = extents->y1; 89 if(y2 >= extents->y2) y2 = extents->y2; 90 if((dy = y2 - y1)<1) return; 91 92 (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y1, dx, dy); 93} 94 95 96static void 97XAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width) 98{ 99 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 100 BoxPtr extents = infoRec->ClipBox; 101 int x2; 102 103 if((y < extents->y1) || (y >= extents->y2)) return; 104 105 x2 = x1 + width; 106 if(x1 < extents->x1) x1 = extents->x1; 107 if(x2 > extents->x2) x2 = extents->x2; 108 width = x2 - x1; 109 110 if(width > 0) 111 (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y, width, 1); 112 113} 114 115#define FixError(x, dx, dy, e, sign, step, h) { \ 116 e += (h) * dx; \ 117 x += (h) * step; \ 118 if(e > 0) { \ 119 x += e * sign/dy; \ 120 e %= dy; \ 121 if(e) { \ 122 x += sign; \ 123 e -= dy; \ 124 } \ 125 } \ 126} 127 128 129static void 130XAAFillPolyHelper ( 131 GCPtr pGC, 132 int y, /* start y coordinate */ 133 int overall_height, /* height of entire segment */ 134 PolyEdgePtr left, PolyEdgePtr right, 135 int left_count, int right_count ) 136{ 137 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 138 BoxPtr extents = infoRec->ClipBox; 139 int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx; 140 int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx; 141 int height, left_height, right_height; 142 int xorg; 143 Bool hardClip; 144 145 if((y >= extents->y2) || ((y + overall_height) <= extents->y1)) 146 return; 147 148 /* Muffle compiler */ 149 left_x = left_e = left_stepx = left_signdx = left_dy = left_dx = 0; 150 right_x = right_e = right_stepx = right_signdx = right_dy = right_dx = 0; 151 152 left_height = right_height = 0; 153 xorg = 0; 154 155 hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 156 157 while ((left_count || left_height) && (right_count || right_height)) { 158 if (!left_height && left_count) { 159 left_height = left->height; 160 left_x = left->x + xorg; 161 left_stepx = left->stepx; 162 left_signdx = left->signdx; 163 left_e = left->e; 164 left_dy = left->dy; 165 left_dx = left->dx; 166 left_count--; 167 left++; 168 } 169 if (!right_height && right_count) { 170 right_height = right->height; 171 right_x = right->x + xorg + 1; 172 right_stepx = right->stepx; 173 right_signdx = right->signdx; 174 right_e = right->e; 175 right_dy = right->dy; 176 right_dx = right->dx; 177 right_count--; 178 right++; 179 } 180 181 height = (left_height > right_height) ? right_height : left_height; 182 183 left_height -= height; 184 right_height -= height; 185 186 if(hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) { 187 int right_DX, left_DX; 188 189 right_DX = (right_dx * right_signdx) + (right_stepx * right_dy); 190 left_DX = (left_dx * left_signdx) + (left_stepx * left_dy); 191 192 (*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn, y, height, 193 left_x, left_DX, left_dy, left_e, 194 right_x - 1, right_DX, right_dy, right_e); 195 196 FixError(left_x, left_dx, left_dy, left_e, left_signdx, 197 left_stepx, height); 198 FixError(right_x, right_dx, right_dy, right_e, right_signdx, 199 right_stepx, height); 200 y += height; 201 continue; 202 } 203 204 while (height--) { 205 if(right_x > left_x) { 206 FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x); 207 } 208 y++; 209 210 left_x += left_stepx; 211 left_e += left_dx; 212 if (left_e > 0) { 213 left_x += left_signdx; 214 left_e -= left_dy; 215 } 216 right_x += right_stepx; 217 right_e += right_dx; 218 if (right_e > 0) { 219 right_x += right_signdx; 220 right_e -= right_dy; 221 } 222 223 } 224 } 225} 226 227 228 229static void 230XAAWideSegment ( 231 GCPtr pGC, 232 int x1, int y1, int x2, int y2, 233 Bool projectLeft, Bool projectRight, 234 LineFacePtr leftFace, LineFacePtr rightFace ) 235{ 236 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 237 double l, L, r; 238 double xa, ya; 239 double projectXoff, projectYoff; 240 double k; 241 double maxy; 242 int x, y; 243 int dx, dy; 244 int finaly; 245 PolyEdgePtr left, right; 246 PolyEdgePtr top, bottom; 247 int lefty, righty, topy, bottomy; 248 int signdx; 249 PolyEdgeRec lefts[2], rights[2]; 250 LineFacePtr tface; 251 int lw = pGC->lineWidth; 252 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 253 254 /* draw top-to-bottom always */ 255 if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) { 256 x = x1; 257 x1 = x2; 258 x2 = x; 259 260 y = y1; 261 y1 = y2; 262 y2 = y; 263 264 x = projectLeft; 265 projectLeft = projectRight; 266 projectRight = x; 267 268 tface = leftFace; 269 leftFace = rightFace; 270 rightFace = tface; 271 } 272 273 dy = y2 - y1; 274 signdx = 1; 275 dx = x2 - x1; 276 if (dx < 0) 277 signdx = -1; 278 279 leftFace->x = x1; 280 leftFace->y = y1; 281 leftFace->dx = dx; 282 leftFace->dy = dy; 283 284 rightFace->x = x2; 285 rightFace->y = y2; 286 rightFace->dx = -dx; 287 rightFace->dy = -dy; 288 289 if (!dy) { 290 rightFace->xa = 0; 291 rightFace->ya = (double) lw / 2.0; 292 rightFace->k = -(double) (lw * dx) / 2.0; 293 leftFace->xa = 0; 294 leftFace->ya = -rightFace->ya; 295 leftFace->k = rightFace->k; 296 x = x1; 297 if (projectLeft) 298 x -= (lw >> 1); 299 y = y1 - (lw >> 1); 300 dx = x2 - x; 301 if (projectRight) 302 dx += ((lw + 1) >> 1); 303 dy = lw; 304 FILL_RECT(infoRec->pScrn, x, y, dx, dy); 305 } else if (!dx) { 306 leftFace->xa = (double) lw / 2.0; 307 leftFace->ya = 0; 308 leftFace->k = (double) (lw * dy) / 2.0; 309 rightFace->xa = -leftFace->xa; 310 rightFace->ya = 0; 311 rightFace->k = leftFace->k; 312 y = y1; 313 if (projectLeft) 314 y -= lw >> 1; 315 x = x1 - (lw >> 1); 316 dy = y2 - y; 317 if (projectRight) 318 dy += ((lw + 1) >> 1); 319 dx = lw; 320 FILL_RECT(infoRec->pScrn, x, y, dx, dy); 321 } else { 322 l = ((double) lw) / 2.0; 323 L = sqrt((double)(dx*dx + dy*dy)); 324 325 if (dx < 0) { 326 right = &rights[1]; 327 left = &lefts[0]; 328 top = &rights[0]; 329 bottom = &lefts[1]; 330 } else { 331 right = &rights[0]; 332 left = &lefts[1]; 333 top = &lefts[0]; 334 bottom = &rights[1]; 335 } 336 r = l / L; 337 338 /* coord of upper bound at integral y */ 339 ya = -r * dx; 340 xa = r * dy; 341 342 projectXoff = -ya; 343 projectYoff = xa; 344 345 /* xa * dy - ya * dx */ 346 k = l * L; 347 348 leftFace->xa = xa; 349 leftFace->ya = ya; 350 leftFace->k = k; 351 rightFace->xa = -xa; 352 rightFace->ya = -ya; 353 rightFace->k = k; 354 355 if (projectLeft) 356 righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 357 k, dx, dy, x1, y1, 0, right); 358 else 359 righty = miPolyBuildEdge (xa, ya, 360 k, dx, dy, x1, y1, 0, right); 361 362 /* coord of lower bound at integral y */ 363 ya = -ya; 364 xa = -xa; 365 366 /* xa * dy - ya * dx */ 367 k = - k; 368 369 if (projectLeft) 370 lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 371 k, dx, dy, x1, y1, 1, left); 372 else 373 lefty = miPolyBuildEdge (xa, ya, 374 k, dx, dy, x1, y1, 1, left); 375 376 /* coord of top face at integral y */ 377 378 if (signdx > 0) { 379 ya = -ya; 380 xa = -xa; 381 } 382 383 if (projectLeft) { 384 double xap = xa - projectXoff; 385 double yap = ya - projectYoff; 386 topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 387 -dy, dx, x1, y1, dx > 0, top); 388 } 389 else 390 topy = miPolyBuildEdge(xa, ya, 0.0, 391 -dy, dx, x1, y1, dx > 0, top); 392 393 /* coord of bottom face at integral y */ 394 395 if (projectRight) { 396 double xap = xa + projectXoff; 397 double yap = ya + projectYoff; 398 bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 399 -dy, dx, x2, y2, dx < 0, bottom); 400 maxy = -ya + projectYoff; 401 } else { 402 bottomy = miPolyBuildEdge (xa, ya, 0.0, 403 -dy, dx, x2, y2, dx < 0, bottom); 404 maxy = -ya; 405 } 406 407 finaly = ICEIL (maxy) + y2; 408 409 if (dx < 0) { 410 left->height = bottomy - lefty; 411 right->height = finaly - righty; 412 top->height = righty - topy; 413 } else { 414 right->height = bottomy - righty; 415 left->height = finaly - lefty; 416 top->height = lefty - topy; 417 } 418 bottom->height = finaly - bottomy; 419 XAAFillPolyHelper (pGC, topy, 420 bottom->height + bottomy - topy, lefts, rights, 2, 2); 421 } 422} 423 424 425static void 426XAALineArcI (GCPtr pGC, int xorg, int yorg) 427{ 428 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 429 int x, y, e, ex; 430 int slw = pGC->lineWidth; 431 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 432 433 y = (slw >> 1) + 1; 434 if (slw & 1) 435 e = - ((y << 2) + 3); 436 else 437 e = - (y << 3); 438 ex = -4; 439 x = 0; 440 while (y) { 441 e += (y << 3) - 4; 442 while (e >= 0) { 443 x++; 444 e += (ex = -((x << 3) + 4)); 445 } 446 y--; 447 slw = (x << 1) + 1; 448 if ((e == ex) && (slw > 1)) 449 slw--; 450 451 FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw); 452 453 if ((y != 0) && ((slw > 1) || (e != ex))) { 454 FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw); 455 } 456 } 457} 458 459 460static void 461XAALineArcD ( 462 GCPtr pGC, 463 double xorg, 464 double yorg, 465 PolyEdgePtr edge1, 466 int edgey1, 467 Bool edgeleft1, 468 PolyEdgePtr edge2, 469 int edgey2, 470 Bool edgeleft2 ) 471{ 472 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 473 double radius, x0, y0, el, er, yk, xlk, xrk, k; 474 int xbase, ybase, y, boty, xl, xr, xcl, xcr; 475 int ymin, ymax; 476 Bool edge1IsMin, edge2IsMin; 477 int ymin1, ymin2; 478 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 479 480 481 xbase = floor(xorg); 482 x0 = xorg - xbase; 483 ybase = ICEIL (yorg); 484 y0 = yorg - ybase; 485 486 xlk = x0 + x0 + 1.0; 487 xrk = x0 + x0 - 1.0; 488 yk = y0 + y0 - 1.0; 489 radius = ((double)pGC->lineWidth) / 2.0; 490 y = floor(radius - y0 + 1.0); 491 ybase -= y; 492 ymin = ybase; 493 ymax = 65536; 494 edge1IsMin = FALSE; 495 ymin1 = edgey1; 496 if (edge1->dy >= 0) { 497 if (!edge1->dy) { 498 if (edgeleft1) 499 edge1IsMin = TRUE; 500 else 501 ymax = edgey1; 502 edgey1 = 65536; 503 } else if ((edge1->signdx < 0) == edgeleft1) 504 edge1IsMin = TRUE; 505 } 506 edge2IsMin = FALSE; 507 ymin2 = edgey2; 508 if (edge2->dy >= 0) { 509 if (!edge2->dy) { 510 if (edgeleft2) 511 edge2IsMin = TRUE; 512 else 513 ymax = edgey2; 514 edgey2 = 65536; 515 } else if ((edge2->signdx < 0) == edgeleft2) 516 edge2IsMin = TRUE; 517 } 518 if (edge1IsMin) { 519 ymin = ymin1; 520 if (edge2IsMin && (ymin1 > ymin2)) 521 ymin = ymin2; 522 } else if (edge2IsMin) 523 ymin = ymin2; 524 el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); 525 er = el + xrk; 526 xl = 1; 527 xr = 0; 528 if (x0 < 0.5) { 529 xl = 0; 530 el -= xlk; 531 } 532 boty = (y0 < -0.5) ? 1 : 0; 533 if (ybase + y - boty > ymax) 534 boty = ymax - ybase - y; 535 while (y > boty) { 536 k = (y << 1) + yk; 537 er += k; 538 while (er > 0.0) { 539 xr++; 540 er += xrk - (xr << 1); 541 } 542 el += k; 543 while (el >= 0.0) { 544 xl--; 545 el += (xl << 1) - xlk; 546 } 547 y--; 548 ybase++; 549 if (ybase < ymin) 550 continue; 551 xcl = xl + xbase; 552 xcr = xr + xbase; 553 CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 554 CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 555 if(xcr >= xcl) { 556 FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); 557 } 558 } 559 er = xrk - (xr << 1) - er; 560 el = (xl << 1) - xlk - el; 561 boty = floor(-y0 - radius + 1.0); 562 if (ybase + y - boty > ymax) 563 boty = ymax - ybase - y; 564 while (y > boty) { 565 k = (y << 1) + yk; 566 er -= k; 567 while ((er >= 0.0) && (xr >= 0)) { 568 xr--; 569 er += xrk - (xr << 1); 570 } 571 el -= k; 572 while ((el > 0.0) && (xl <= 0)) { 573 xl++; 574 el += (xl << 1) - xlk; 575 } 576 y--; 577 ybase++; 578 if (ybase < ymin) 579 continue; 580 xcl = xl + xbase; 581 xcr = xr + xbase; 582 CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 583 CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 584 if(xcr >= xcl) { 585 FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); 586 } 587 } 588} 589 590 591static void 592XAALineArc ( 593 GCPtr pGC, 594 LineFacePtr leftFace, 595 LineFacePtr rightFace, 596 double xorg, 597 double yorg, 598 Bool isInt ) 599{ 600 int xorgi, yorgi; 601 PolyEdgeRec edge1, edge2; 602 int edgey1, edgey2; 603 Bool edgeleft1, edgeleft2; 604 605 if (isInt) { 606 xorgi = leftFace ? leftFace->x : rightFace->x; 607 yorgi = leftFace ? leftFace->y : rightFace->y; 608 } else { /* Muffle compiler */ 609 xorgi = yorgi = 0; 610 } 611 edgey1 = 65536; 612 edgey2 = 65536; 613 edge1.x = 0; /* not used, keep memory checkers happy */ 614 edge1.dy = -1; 615 edge2.x = 0; /* not used, keep memory checkers happy */ 616 edge2.dy = -1; 617 edgeleft1 = FALSE; 618 edgeleft2 = FALSE; 619 620 if ((pGC->lineWidth > 2) && 621 ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || 622 (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) { 623 if (isInt) { 624 xorg = (double) xorgi; 625 yorg = (double) yorgi; 626 } 627 628 if (leftFace && rightFace) 629 miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, 630 &edgey1, &edgey2, &edgeleft1, &edgeleft2); 631 else if (leftFace) 632 edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); 633 else if (rightFace) 634 edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); 635 636 isInt = FALSE; 637 } 638 639 if (isInt) { 640 if(pGC->lineWidth == 1) { 641 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 642 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 643 DRAW_POINT(infoRec->pScrn, xorgi, yorgi); 644 } else 645 XAALineArcI(pGC, xorgi, yorgi); 646 } else 647 XAALineArcD(pGC, xorg, yorg, &edge1, edgey1, edgeleft1, 648 &edge2, edgey2, edgeleft2); 649 650} 651 652 653static void 654XAALineJoin ( 655 GCPtr pGC, 656 LineFacePtr pLeft, 657 LineFacePtr pRight ) 658{ 659 double mx = 0, my = 0; 660 double denom = 0; 661 PolyVertexRec vertices[4]; 662 PolySlopeRec slopes[4]; 663 int edgecount; 664 PolyEdgeRec left[4], right[4]; 665 int nleft, nright; 666 int y, height; 667 int swapslopes; 668 int joinStyle = pGC->joinStyle; 669 int lw = pGC->lineWidth; 670 671 if (lw == 1) { 672 /* Lines going in the same direction have no join */ 673 if ((pLeft->dx >= 0) == (pRight->dx <= 0)) 674 return; 675 if (joinStyle != JoinRound) { 676 denom = - pLeft->dx * (double)pRight->dy + pRight->dx * 677 (double)pLeft->dy; 678 if (denom == 0.0) 679 return; /* no join to draw */ 680 } 681 if (joinStyle != JoinMiter) { 682 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 683 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 684 DRAW_POINT(infoRec->pScrn, pLeft->x, pLeft->y); 685 return; 686 } 687 } else { 688 if (joinStyle == JoinRound) { 689 XAALineArc(pGC, pLeft, pRight,(double)0.0, (double)0.0, TRUE); 690 return; 691 } 692 denom = - pLeft->dx * (double)pRight->dy + pRight->dx * 693 (double)pLeft->dy; 694 if (denom == 0.0) 695 return; /* no join to draw */ 696 } 697 698 swapslopes = 0; 699 if (denom > 0) { 700 pLeft->xa = -pLeft->xa; 701 pLeft->ya = -pLeft->ya; 702 pLeft->dx = -pLeft->dx; 703 pLeft->dy = -pLeft->dy; 704 } else { 705 swapslopes = 1; 706 pRight->xa = -pRight->xa; 707 pRight->ya = -pRight->ya; 708 pRight->dx = -pRight->dx; 709 pRight->dy = -pRight->dy; 710 } 711 712 vertices[0].x = pRight->xa; 713 vertices[0].y = pRight->ya; 714 slopes[0].dx = -pRight->dy; 715 slopes[0].dy = pRight->dx; 716 slopes[0].k = 0; 717 718 vertices[1].x = 0; 719 vertices[1].y = 0; 720 slopes[1].dx = pLeft->dy; 721 slopes[1].dy = -pLeft->dx; 722 slopes[1].k = 0; 723 724 vertices[2].x = pLeft->xa; 725 vertices[2].y = pLeft->ya; 726 727 if (joinStyle == JoinMiter) { 728 my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - 729 pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/ 730 denom; 731 if (pLeft->dy != 0) 732 mx = pLeft->xa + (my - pLeft->ya) * 733 (double) pLeft->dx / (double) pLeft->dy; 734 else 735 mx = pRight->xa + (my - pRight->ya) * 736 (double) pRight->dx / (double) pRight->dy; 737 738 /* check miter limit */ 739 if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) 740 joinStyle = JoinBevel; 741 } 742 743 if (joinStyle == JoinMiter) { 744 slopes[2].dx = pLeft->dx; 745 slopes[2].dy = pLeft->dy; 746 slopes[2].k = pLeft->k; 747 if (swapslopes) { 748 slopes[2].dx = -slopes[2].dx; 749 slopes[2].dy = -slopes[2].dy; 750 slopes[2].k = -slopes[2].k; 751 } 752 vertices[3].x = mx; 753 vertices[3].y = my; 754 slopes[3].dx = pRight->dx; 755 slopes[3].dy = pRight->dy; 756 slopes[3].k = pRight->k; 757 if (swapslopes) { 758 slopes[3].dx = -slopes[3].dx; 759 slopes[3].dy = -slopes[3].dy; 760 slopes[3].k = -slopes[3].k; 761 } 762 edgecount = 4; 763 } else { 764 double scale, dx, dy, adx, ady; 765 766 adx = dx = pRight->xa - pLeft->xa; 767 ady = dy = pRight->ya - pLeft->ya; 768 if (adx < 0) 769 adx = -adx; 770 if (ady < 0) 771 ady = -ady; 772 scale = ady; 773 if (adx > ady) 774 scale = adx; 775 slopes[2].dx = (dx * 65536) / scale; 776 slopes[2].dy = (dy * 65536) / scale; 777 slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - 778 (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; 779 edgecount = 3; 780 } 781 782 y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, 783 left, right, &nleft, &nright, &height); 784 XAAFillPolyHelper(pGC, y, height, left, right, nleft, nright); 785} 786 787 788void 789XAAPolylinesWideSolid ( 790 DrawablePtr pDrawable, 791 GCPtr pGC, 792 int mode, 793 int npt, 794 DDXPointPtr pPts ) 795{ 796 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 797 int x1, y1, x2, y2; 798 Bool projectLeft, projectRight; 799 LineFaceRec leftFace, rightFace, prevRightFace, firstFace; 800 int first = TRUE; 801 Bool somethingDrawn = FALSE; 802 Bool selfJoin = FALSE; 803 int xorg = pDrawable->x; 804 int yorg = pDrawable->y; 805 Bool hardClip = FALSE; 806 807 if(!RegionNumRects(pGC->pCompositeClip)) 808 return; 809 810 if(RegionNumRects(pGC->pCompositeClip) != 1) { 811 miWideLine(pDrawable, pGC, mode, npt, pPts); 812 return; 813 } 814 815 x2 = pPts->x; 816 y2 = pPts->y; 817 if (npt > 1) { 818 if (mode == CoordModePrevious) { 819 int nptTmp; 820 register DDXPointPtr pPtsTmp; 821 822 x1 = x2; 823 y1 = y2; 824 nptTmp = npt; 825 pPtsTmp = pPts + 1; 826 while (--nptTmp) { 827 x1 += pPtsTmp->x; 828 y1 += pPtsTmp->y; 829 ++pPtsTmp; 830 } 831 if ((x2 == x1) && (y2 == y1)) 832 selfJoin = TRUE; 833 } else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y)) 834 selfJoin = TRUE; 835 } 836 837 projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin); 838 projectRight = FALSE; 839 840 (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu, 841 pGC->planemask); 842 843 infoRec->ClipBox = &pGC->pCompositeClip->extents; 844 845 if(infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) { 846 hardClip = TRUE; 847 (*infoRec->SetClippingRectangle)(infoRec->pScrn, 848 infoRec->ClipBox->x1, infoRec->ClipBox->y1, 849 infoRec->ClipBox->x2 - 1, infoRec->ClipBox->y2 - 1); 850 } 851 852 x2 += xorg; 853 y2 += yorg; 854 while (--npt) { 855 x1 = x2; 856 y1 = y2; 857 ++pPts; 858 x2 = pPts->x; 859 y2 = pPts->y; 860 if (mode == CoordModePrevious) { 861 x2 += x1; 862 y2 += y1; 863 } else { 864 x2 += xorg; 865 y2 += yorg; 866 } 867 if ((x1 != x2) || (y1 != y2)) { 868 somethingDrawn = TRUE; 869 if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin) 870 projectRight = TRUE; 871 XAAWideSegment(pGC, x1, y1, x2, y2, 872 projectLeft, projectRight, &leftFace, &rightFace); 873 if (first) { 874 if (selfJoin) 875 firstFace = leftFace; 876 else if (pGC->capStyle == CapRound) { 877 if (pGC->lineWidth == 1) { 878 DRAW_POINT(infoRec->pScrn, x1, y1); 879 } else 880 XAALineArc(pGC,&leftFace, (LineFacePtr) NULL, 881 (double)0.0, (double)0.0,TRUE); 882 } 883 } else 884 XAALineJoin (pGC, &leftFace, &prevRightFace); 885 886 prevRightFace = rightFace; 887 first = FALSE; 888 projectLeft = FALSE; 889 } 890 if (npt == 1 && somethingDrawn) { 891 if (selfJoin) 892 XAALineJoin (pGC, &firstFace, &rightFace); 893 else if (pGC->capStyle == CapRound) { 894 if (pGC->lineWidth == 1) { 895 DRAW_POINT(infoRec->pScrn, x2, y2); 896 } else 897 XAALineArc (pGC, (LineFacePtr) NULL, &rightFace, 898 (double)0.0, (double)0.0,TRUE); 899 } 900 } 901 } 902 /* handle crock where all points are coincedent */ 903 if (!somethingDrawn) { 904 projectLeft = (pGC->capStyle == CapProjecting); 905 XAAWideSegment (pGC, x2, y2, x2, y2, projectLeft, projectLeft, 906 &leftFace, &rightFace); 907 if (pGC->capStyle == CapRound) { 908 XAALineArc (pGC, &leftFace, (LineFacePtr) NULL, 909 (double)0.0, (double)0.0, TRUE); 910 rightFace.dx = -1; /* sleezy hack to make it work */ 911 XAALineArc (pGC, (LineFacePtr) NULL, &rightFace, 912 (double)0.0, (double)0.0, TRUE); 913 } 914 } 915 916 infoRec->ClipBox = NULL; 917 if(hardClip) 918 (*infoRec->DisableClipping)(infoRec->pScrn); 919 920 SET_SYNC_FLAG(infoRec); 921} 922