1 /* libs/graphics/sgl/SkScan_Path.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkScanPriv.h" 19 #include "SkBlitter.h" 20 #include "SkEdge.h" 21 #include "SkGeometry.h" 22 #include "SkPath.h" 23 #include "SkQuadClipper.h" 24 #include "SkRegion.h" 25 #include "SkTemplates.h" 26 27 #define USE_NEW_BUILDER 28 29 #define kEDGE_HEAD_Y SK_MinS32 30 #define kEDGE_TAIL_Y SK_MaxS32 31 32 #ifdef SK_DEBUG 33 static void validate_sort(const SkEdge* edge) 34 { 35 int y = kEDGE_HEAD_Y; 36 37 while (edge->fFirstY != SK_MaxS32) 38 { 39 edge->validate(); 40 SkASSERT(y <= edge->fFirstY); 41 42 y = edge->fFirstY; 43 edge = edge->fNext; 44 } 45 } 46 #else 47 #define validate_sort(edge) 48 #endif 49 50 static inline void remove_edge(SkEdge* edge) 51 { 52 edge->fPrev->fNext = edge->fNext; 53 edge->fNext->fPrev = edge->fPrev; 54 } 55 56 static inline void swap_edges(SkEdge* prev, SkEdge* next) 57 { 58 SkASSERT(prev->fNext == next && next->fPrev == prev); 59 60 // remove prev from the list 61 prev->fPrev->fNext = next; 62 next->fPrev = prev->fPrev; 63 64 // insert prev after next 65 prev->fNext = next->fNext; 66 next->fNext->fPrev = prev; 67 next->fNext = prev; 68 prev->fPrev = next; 69 } 70 71 static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) 72 { 73 SkFixed x = edge->fX; 74 75 for (;;) 76 { 77 SkEdge* prev = edge->fPrev; 78 79 // add 1 to curr_y since we may have added new edges (built from curves) 80 // that start on the next scanline 81 SkASSERT(prev && prev->fFirstY <= curr_y + 1); 82 83 if (prev->fX <= x) 84 break; 85 86 swap_edges(prev, edge); 87 } 88 } 89 90 static void insert_new_edges(SkEdge* newEdge, int curr_y) 91 { 92 SkASSERT(newEdge->fFirstY >= curr_y); 93 94 while (newEdge->fFirstY == curr_y) 95 { 96 SkEdge* next = newEdge->fNext; 97 backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); 98 newEdge = next; 99 } 100 } 101 102 #ifdef SK_DEBUG 103 static void validate_edges_for_y(const SkEdge* edge, int curr_y) 104 { 105 while (edge->fFirstY <= curr_y) 106 { 107 SkASSERT(edge->fPrev && edge->fNext); 108 SkASSERT(edge->fPrev->fNext == edge); 109 SkASSERT(edge->fNext->fPrev == edge); 110 SkASSERT(edge->fFirstY <= edge->fLastY); 111 112 SkASSERT(edge->fPrev->fX <= edge->fX); 113 edge = edge->fNext; 114 } 115 } 116 #else 117 #define validate_edges_for_y(edge, curr_y) 118 #endif 119 120 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 121 #pragma warning ( push ) 122 #pragma warning ( disable : 4701 ) 123 #endif 124 125 typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); 126 #define PREPOST_START true 127 #define PREPOST_END false 128 129 static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, 130 SkBlitter* blitter, int start_y, int stop_y, 131 PrePostProc proc) 132 { 133 validate_sort(prevHead->fNext); 134 135 int curr_y = start_y; 136 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness 137 int windingMask = (fillType & 1) ? 1 : -1; 138 139 for (;;) 140 { 141 int w = 0; 142 int left SK_INIT_TO_AVOID_WARNING; 143 bool in_interval = false; 144 SkEdge* currE = prevHead->fNext; 145 SkFixed prevX = prevHead->fX; 146 147 validate_edges_for_y(currE, curr_y); 148 149 if (proc) { 150 proc(blitter, curr_y, PREPOST_START); // pre-proc 151 } 152 153 while (currE->fFirstY <= curr_y) 154 { 155 SkASSERT(currE->fLastY >= curr_y); 156 157 int x = (currE->fX + SK_Fixed1/2) >> 16; 158 w += currE->fWinding; 159 if ((w & windingMask) == 0) // we finished an interval 160 { 161 SkASSERT(in_interval); 162 int width = x - left; 163 SkASSERT(width >= 0); 164 if (width) 165 blitter->blitH(left, curr_y, width); 166 in_interval = false; 167 } 168 else if (!in_interval) 169 { 170 left = x; 171 in_interval = true; 172 } 173 174 SkEdge* next = currE->fNext; 175 SkFixed newX; 176 177 if (currE->fLastY == curr_y) // are we done with this edge? 178 { 179 if (currE->fCurveCount < 0) 180 { 181 if (((SkCubicEdge*)currE)->updateCubic()) 182 { 183 SkASSERT(currE->fFirstY == curr_y + 1); 184 185 newX = currE->fX; 186 goto NEXT_X; 187 } 188 } 189 else if (currE->fCurveCount > 0) 190 { 191 if (((SkQuadraticEdge*)currE)->updateQuadratic()) 192 { 193 newX = currE->fX; 194 goto NEXT_X; 195 } 196 } 197 remove_edge(currE); 198 } 199 else 200 { 201 SkASSERT(currE->fLastY > curr_y); 202 newX = currE->fX + currE->fDX; 203 currE->fX = newX; 204 NEXT_X: 205 if (newX < prevX) // ripple currE backwards until it is x-sorted 206 backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); 207 else 208 prevX = newX; 209 } 210 currE = next; 211 SkASSERT(currE); 212 } 213 214 if (proc) { 215 proc(blitter, curr_y, PREPOST_END); // post-proc 216 } 217 218 curr_y += 1; 219 if (curr_y >= stop_y) 220 break; 221 222 // now currE points to the first edge with a Yint larger than curr_y 223 insert_new_edges(currE, curr_y); 224 } 225 } 226 227 /////////////////////////////////////////////////////////////////////////////// 228 229 // this guy overrides blitH, and will call its proxy blitter with the inverse 230 // of the spans it is given (clipped to the left/right of the cliprect) 231 // 232 // used to implement inverse filltypes on paths 233 // 234 class InverseBlitter : public SkBlitter { 235 public: 236 void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) { 237 fBlitter = blitter; 238 fFirstX = clip.fLeft << shift; 239 fLastX = clip.fRight << shift; 240 } 241 void prepost(int y, bool isStart) { 242 if (isStart) { 243 fPrevX = fFirstX; 244 } else { 245 int invWidth = fLastX - fPrevX; 246 if (invWidth > 0) { 247 fBlitter->blitH(fPrevX, y, invWidth); 248 } 249 } 250 } 251 252 // overrides 253 virtual void blitH(int x, int y, int width) { 254 int invWidth = x - fPrevX; 255 if (invWidth > 0) { 256 fBlitter->blitH(fPrevX, y, invWidth); 257 } 258 fPrevX = x + width; 259 } 260 261 // we do not expect to get called with these entrypoints 262 virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) { 263 SkASSERT(!"blitAntiH unexpected"); 264 } 265 virtual void blitV(int x, int y, int height, SkAlpha alpha) { 266 SkASSERT(!"blitV unexpected"); 267 } 268 virtual void blitRect(int x, int y, int width, int height) { 269 SkASSERT(!"blitRect unexpected"); 270 } 271 virtual void blitMask(const SkMask&, const SkIRect& clip) { 272 SkASSERT(!"blitMask unexpected"); 273 } 274 virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) { 275 SkASSERT(!"justAnOpaqueColor unexpected"); 276 return NULL; 277 } 278 279 private: 280 SkBlitter* fBlitter; 281 int fFirstX, fLastX, fPrevX; 282 }; 283 284 static void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) { 285 ((InverseBlitter*)blitter)->prepost(y, isStart); 286 } 287 288 /////////////////////////////////////////////////////////////////////////////// 289 290 #if defined _WIN32 && _MSC_VER >= 1300 291 #pragma warning ( pop ) 292 #endif 293 294 /* Our line edge relies on the maximum span being <= 512, so that it can 295 use FDot6 and keep the dx,dy in 16bits (for much faster slope divide). 296 This function returns true if the specified line is too big. 297 */ 298 static inline bool line_too_big(const SkPoint pts[2]) 299 { 300 SkScalar dx = pts[1].fX - pts[0].fX; 301 SkScalar dy = pts[1].fY - pts[0].fY; 302 303 return SkScalarAbs(dx) > SkIntToScalar(511) || 304 SkScalarAbs(dy) > SkIntToScalar(511); 305 } 306 307 #ifdef USE_NEW_BUILDER 308 #include "SkEdgeBuilder.h" 309 #else 310 static int build_edges(SkEdge edge[], const SkPath& path, 311 const SkIRect* clipRect, SkEdge* list[], int shiftUp) { 312 SkEdge** start = list; 313 SkPath::Iter iter(path, true); 314 SkPoint pts[4]; 315 SkPath::Verb verb; 316 317 SkQuadClipper qclipper; 318 if (clipRect) { 319 SkIRect r; 320 r.set(clipRect->fLeft >> shiftUp, clipRect->fTop >> shiftUp, 321 clipRect->fRight >> shiftUp, clipRect->fBottom >> shiftUp); 322 qclipper.setClip(r); 323 } 324 325 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 326 switch (verb) { 327 case SkPath::kLine_Verb: 328 if (edge->setLine(pts[0], pts[1], clipRect, shiftUp)) { 329 *list++ = edge; 330 edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 331 } 332 break; 333 case SkPath::kQuad_Verb: { 334 SkPoint tmp[5], clippedPts[3]; 335 SkPoint* p = tmp; 336 int count = SkChopQuadAtYExtrema(pts, tmp); 337 338 do { 339 const SkPoint* qpts = p; 340 if (clipRect) { 341 if (!qclipper.clipQuad(p, clippedPts)) { 342 goto NEXT_CHOPPED_QUAD; 343 } 344 qpts = clippedPts; 345 } 346 if (((SkQuadraticEdge*)edge)->setQuadratic(qpts, shiftUp)) { 347 *list++ = edge; 348 edge = (SkEdge*)((char*)edge + sizeof(SkQuadraticEdge)); 349 } 350 NEXT_CHOPPED_QUAD: 351 p += 2; 352 } while (--count >= 0); 353 break; 354 } 355 case SkPath::kCubic_Verb: { 356 SkPoint tmp[10]; 357 SkPoint* p = tmp; 358 int count = SkChopCubicAtYExtrema(pts, tmp); 359 SkASSERT(count >= 0 && count <= 2); 360 361 do { 362 if (((SkCubicEdge*)edge)->setCubic(p, clipRect, shiftUp)) 363 { 364 *list++ = edge; 365 edge = (SkEdge*)((char*)edge + sizeof(SkCubicEdge)); 366 } 367 p += 3; 368 } while (--count >= 0); 369 break; 370 } 371 default: 372 break; 373 } 374 } 375 return (int)(list - start); 376 } 377 378 #ifdef SK_DEBUG 379 /* 'quick' computation of the max sized needed to allocated for 380 our edgelist. 381 */ 382 static int worst_case_edge_count(const SkPath& path, size_t* storage) 383 { 384 size_t size = 0; 385 int edgeCount = 0; 386 387 SkPath::Iter iter(path, true); 388 SkPath::Verb verb; 389 390 while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) 391 { 392 switch (verb) { 393 case SkPath::kLine_Verb: 394 edgeCount += 1; 395 size += sizeof(SkQuadraticEdge); // treat line like Quad (in case its > 512) 396 break; 397 case SkPath::kQuad_Verb: 398 edgeCount += 2; // might need 2 edges when we chop on Y extrema 399 size += 2 * sizeof(SkQuadraticEdge); 400 break; 401 case SkPath::kCubic_Verb: 402 edgeCount += 3; // might need 3 edges when we chop on Y extrema 403 size += 3 * sizeof(SkCubicEdge); 404 break; 405 default: 406 break; 407 } 408 } 409 410 SkASSERT(storage); 411 *storage = size; 412 return edgeCount; 413 } 414 #endif 415 416 /* Much faster than worst_case_edge_count, but over estimates even more 417 */ 418 static int cheap_worst_case_edge_count(const SkPath& path, size_t* storage) { 419 int ptCount = path.getPoints(NULL, 0); 420 // worst case is curve, close, curve, close, as that is 421 // 2 lines per pt, or : pts * 2 422 // 2 quads + 1 line per 2 pts, or : pts * 3 / 2 423 // 3 cubics + 1 line per 3 pts : pts * 4 / 3 424 int edgeCount = ptCount << 1; 425 // worst storage, due to relative size of different edge types, is 426 // quads * 3 / 2 427 size_t quadSize = (ptCount * 3 >> 1) * sizeof(SkQuadraticEdge); 428 #if 0 429 size_t lineSize = (ptCount << 1) * sizeof(SkEdge); 430 size_t cubicSize = (ptCount * 3 / 4) * sizeof(SkCubicEdge); 431 SkASSERT(lineSize <= quadSize); 432 SkASSERT(cubicSize <= quadSize); 433 #endif 434 *storage = quadSize; 435 return edgeCount; 436 } 437 #endif 438 439 /////////////////////////////////////////////////////////////////////////////// 440 441 extern "C" { 442 static int edge_compare(const void* a, const void* b) { 443 const SkEdge* edgea = *(const SkEdge**)a; 444 const SkEdge* edgeb = *(const SkEdge**)b; 445 446 int valuea = edgea->fFirstY; 447 int valueb = edgeb->fFirstY; 448 449 if (valuea == valueb) { 450 valuea = edgea->fX; 451 valueb = edgeb->fX; 452 } 453 454 // this overflows if valuea >>> valueb or vice-versa 455 // return valuea - valueb; 456 // do perform the slower but safe compares 457 return (valuea < valueb) ? -1 : (valuea > valueb); 458 } 459 } 460 461 static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { 462 qsort(list, count, sizeof(SkEdge*), edge_compare); 463 464 // now make the edges linked in sorted order 465 for (int i = 1; i < count; i++) { 466 list[i - 1]->fNext = list[i]; 467 list[i]->fPrev = list[i - 1]; 468 } 469 470 *last = list[count - 1]; 471 return list[0]; 472 } 473 474 // clipRect may be null, even though we always have a clip. This indicates that 475 // the path is contained in the clip, and so we can ignore it during the blit 476 // 477 // clipRect (if no null) has already been shifted up 478 // 479 void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, 480 int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn) 481 { 482 SkASSERT(&path && blitter); 483 484 #ifdef USE_NEW_BUILDER 485 SkEdgeBuilder builder; 486 487 int count = builder.build(path, clipRect, shiftEdgesUp); 488 SkEdge** list = builder.edgeList(); 489 #else 490 size_t size; 491 int maxCount = cheap_worst_case_edge_count(path, &size); 492 493 #ifdef SK_DEBUG 494 { 495 size_t size2; 496 int maxCount2 = worst_case_edge_count(path, &size2); 497 498 SkASSERT(maxCount >= maxCount2 && size >= size2); 499 } 500 #endif 501 502 SkAutoMalloc memory(maxCount * sizeof(SkEdge*) + size); 503 SkEdge** list = (SkEdge**)memory.get(); 504 SkEdge* initialEdge = (SkEdge*)(list + maxCount); 505 int count = build_edges(initialEdge, path, clipRect, list, 506 shiftEdgesUp); 507 SkASSERT(count <= maxCount); 508 #endif 509 510 if (count < 2) { 511 return; 512 } 513 514 SkEdge headEdge, tailEdge, *last; 515 // this returns the first and last edge after they're sorted into a dlink list 516 SkEdge* edge = sort_edges(list, count, &last); 517 518 headEdge.fPrev = NULL; 519 headEdge.fNext = edge; 520 headEdge.fFirstY = kEDGE_HEAD_Y; 521 headEdge.fX = SK_MinS32; 522 edge->fPrev = &headEdge; 523 524 tailEdge.fPrev = last; 525 tailEdge.fNext = NULL; 526 tailEdge.fFirstY = kEDGE_TAIL_Y; 527 last->fNext = &tailEdge; 528 529 // now edge is the head of the sorted linklist 530 531 start_y <<= shiftEdgesUp; 532 stop_y <<= shiftEdgesUp; 533 if (clipRect && start_y < clipRect->fTop) { 534 start_y = clipRect->fTop; 535 } 536 if (clipRect && stop_y > clipRect->fBottom) { 537 stop_y = clipRect->fBottom; 538 } 539 540 InverseBlitter ib; 541 PrePostProc proc = NULL; 542 543 if (path.isInverseFillType()) { 544 ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); 545 blitter = &ib; 546 proc = PrePostInverseBlitterProc; 547 } 548 549 walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc); 550 } 551 552 void sk_blit_above_and_below(SkBlitter* blitter, const SkIRect& ir, 553 const SkRegion& clip) { 554 const SkIRect& cr = clip.getBounds(); 555 SkIRect tmp; 556 557 tmp.fLeft = cr.fLeft; 558 tmp.fRight = cr.fRight; 559 560 tmp.fTop = cr.fTop; 561 tmp.fBottom = ir.fTop; 562 if (!tmp.isEmpty()) { 563 blitter->blitRectRegion(tmp, clip); 564 } 565 566 tmp.fTop = ir.fBottom; 567 tmp.fBottom = cr.fBottom; 568 if (!tmp.isEmpty()) { 569 blitter->blitRectRegion(tmp, clip); 570 } 571 } 572 573 ///////////////////////////////////////////////////////////////////////////////////// 574 575 SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& ir) 576 { 577 fBlitter = NULL; // null means blit nothing 578 fClipRect = NULL; 579 580 if (clip) 581 { 582 fClipRect = &clip->getBounds(); 583 if (!SkIRect::Intersects(*fClipRect, ir)) // completely clipped out 584 return; 585 586 if (clip->isRect()) 587 { 588 if (fClipRect->contains(ir)) 589 fClipRect = NULL; 590 else 591 { 592 // only need a wrapper blitter if we're horizontally clipped 593 if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) 594 { 595 fRectBlitter.init(blitter, *fClipRect); 596 blitter = &fRectBlitter; 597 } 598 } 599 } 600 else 601 { 602 fRgnBlitter.init(blitter, clip); 603 blitter = &fRgnBlitter; 604 } 605 } 606 fBlitter = blitter; 607 } 608 609 /////////////////////////////////////////////////////////////////////////////// 610 611 void SkScan::FillPath(const SkPath& path, const SkRegion& clip, 612 SkBlitter* blitter) { 613 if (clip.isEmpty()) { 614 return; 615 } 616 617 SkIRect ir; 618 path.getBounds().round(&ir); 619 if (ir.isEmpty()) { 620 if (path.isInverseFillType()) { 621 blitter->blitRegion(clip); 622 } 623 return; 624 } 625 626 SkScanClipper clipper(blitter, &clip, ir); 627 628 blitter = clipper.getBlitter(); 629 if (blitter) { 630 if (path.isInverseFillType()) { 631 sk_blit_above_and_below(blitter, ir, clip); 632 } 633 sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 0, clip); 634 } else { 635 // what does it mean to not have a blitter if path.isInverseFillType??? 636 } 637 } 638 639 /////////////////////////////////////////////////////////////////////////////// 640 641 static int build_tri_edges(SkEdge edge[], const SkPoint pts[], 642 const SkIRect* clipRect, SkEdge* list[]) { 643 SkEdge** start = list; 644 645 if (edge->setLine(pts[0], pts[1], clipRect, 0)) { 646 *list++ = edge; 647 edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 648 } 649 if (edge->setLine(pts[1], pts[2], clipRect, 0)) { 650 *list++ = edge; 651 edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 652 } 653 if (edge->setLine(pts[2], pts[0], clipRect, 0)) { 654 *list++ = edge; 655 } 656 return (int)(list - start); 657 } 658 659 660 static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect, 661 SkBlitter* blitter, const SkIRect& ir) { 662 SkASSERT(pts && blitter); 663 664 SkEdge edgeStorage[3]; 665 SkEdge* list[3]; 666 667 int count = build_tri_edges(edgeStorage, pts, clipRect, list); 668 if (count < 2) { 669 return; 670 } 671 672 SkEdge headEdge, tailEdge, *last; 673 674 // this returns the first and last edge after they're sorted into a dlink list 675 SkEdge* edge = sort_edges(list, count, &last); 676 677 headEdge.fPrev = NULL; 678 headEdge.fNext = edge; 679 headEdge.fFirstY = kEDGE_HEAD_Y; 680 headEdge.fX = SK_MinS32; 681 edge->fPrev = &headEdge; 682 683 tailEdge.fPrev = last; 684 tailEdge.fNext = NULL; 685 tailEdge.fFirstY = kEDGE_TAIL_Y; 686 last->fNext = &tailEdge; 687 688 // now edge is the head of the sorted linklist 689 int stop_y = ir.fBottom; 690 if (clipRect && stop_y > clipRect->fBottom) { 691 stop_y = clipRect->fBottom; 692 } 693 int start_y = ir.fTop; 694 if (clipRect && start_y < clipRect->fTop) { 695 start_y = clipRect->fTop; 696 } 697 walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); 698 } 699 700 void SkScan::FillTriangle(const SkPoint pts[], const SkRegion* clip, 701 SkBlitter* blitter) { 702 if (clip && clip->isEmpty()) { 703 return; 704 } 705 706 SkRect r; 707 SkIRect ir; 708 r.set(pts, 3); 709 r.round(&ir); 710 if (ir.isEmpty()) { 711 return; 712 } 713 714 SkScanClipper clipper(blitter, clip, ir); 715 716 blitter = clipper.getBlitter(); 717 if (NULL != blitter) { 718 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); 719 } 720 } 721 722