| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include "SkIntersections.h" | 7 #include "SkIntersections.h" |
| 8 #include "SkOpSegment.h" | 8 #include "SkOpSegment.h" |
| 9 #include "SkPathWriter.h" | 9 #include "SkPathWriter.h" |
| 10 #include "SkTSort.h" | 10 #include "SkTSort.h" |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 SkOpSpan* span; | 443 SkOpSpan* span; |
| 444 if (insertedAt >= 0) { | 444 if (insertedAt >= 0) { |
| 445 span = fTs.insert(insertedAt); | 445 span = fTs.insert(insertedAt); |
| 446 } else { | 446 } else { |
| 447 insertedAt = tCount; | 447 insertedAt = tCount; |
| 448 span = fTs.append(); | 448 span = fTs.append(); |
| 449 } | 449 } |
| 450 span->fT = newT; | 450 span->fT = newT; |
| 451 span->fOther = other; | 451 span->fOther = other; |
| 452 span->fPt = pt; | 452 span->fPt = pt; |
| 453 #if 0 |
| 454 // cubics, for instance, may not be exact enough to satisfy this check (e.g.
, cubicOp69d) |
| 455 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) |
| 456 && approximately_equal(xyAtT(newT).fY, pt.fY)); |
| 457 #endif |
| 453 span->fWindSum = SK_MinS32; | 458 span->fWindSum = SK_MinS32; |
| 454 span->fOppSum = SK_MinS32; | 459 span->fOppSum = SK_MinS32; |
| 455 span->fWindValue = 1; | 460 span->fWindValue = 1; |
| 456 span->fOppValue = 0; | 461 span->fOppValue = 0; |
| 457 span->fTiny = false; | 462 span->fTiny = false; |
| 458 span->fLoop = false; | 463 span->fLoop = false; |
| 459 if ((span->fDone = newT == 1)) { | 464 if ((span->fDone = newT == 1)) { |
| 460 ++fDoneSpans; | 465 ++fDoneSpans; |
| 461 } | 466 } |
| 462 span->fUnsortableStart = false; | 467 span->fUnsortableStart = false; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 } | 531 } |
| 527 } | 532 } |
| 528 ++fDoneSpans; | 533 ++fDoneSpans; |
| 529 ++more; | 534 ++more; |
| 530 } | 535 } |
| 531 return insertedAt; | 536 return insertedAt; |
| 532 } | 537 } |
| 533 | 538 |
| 534 // set spans from start to end to decrement by one | 539 // set spans from start to end to decrement by one |
| 535 // note this walks other backwards | 540 // note this walks other backwards |
| 536 // FIMXE: there's probably an edge case that can be constructed where | 541 // FIXME: there's probably an edge case that can be constructed where |
| 537 // two span in one segment are separated by float epsilon on one span but | 542 // two span in one segment are separated by float epsilon on one span but |
| 538 // not the other, if one segment is very small. For this | 543 // not the other, if one segment is very small. For this |
| 539 // case the counts asserted below may or may not be enough to separate the | 544 // case the counts asserted below may or may not be enough to separate the |
| 540 // spans. Even if the counts work out, what if the spans aren't correctly | 545 // spans. Even if the counts work out, what if the spans aren't correctly |
| 541 // sorted? It feels better in such a case to match the span's other span | 546 // sorted? It feels better in such a case to match the span's other span |
| 542 // pointer since both coincident segments must contain the same spans. | 547 // pointer since both coincident segments must contain the same spans. |
| 548 // FIXME? It seems that decrementing by one will fail for complex paths that |
| 549 // have three or more coincident edges. Shouldn't this subtract the difference |
| 550 // between the winding values? |
| 543 void SkOpSegment::addTCancel(double startT, double endT, SkOpSegment* other, | 551 void SkOpSegment::addTCancel(double startT, double endT, SkOpSegment* other, |
| 544 double oStartT, double oEndT) { | 552 double oStartT, double oEndT) { |
| 545 SkASSERT(!approximately_negative(endT - startT)); | 553 SkASSERT(!approximately_negative(endT - startT)); |
| 546 SkASSERT(!approximately_negative(oEndT - oStartT)); | 554 SkASSERT(!approximately_negative(oEndT - oStartT)); |
| 547 bool binary = fOperand != other->fOperand; | 555 bool binary = fOperand != other->fOperand; |
| 548 int index = 0; | 556 int index = 0; |
| 549 while (!approximately_negative(startT - fTs[index].fT)) { | 557 while (!approximately_negative(startT - fTs[index].fT)) { |
| 550 ++index; | 558 ++index; |
| 551 } | 559 } |
| 552 int oIndex = other->fTs.count(); | 560 int oIndex = other->fTs.count(); |
| 553 while (approximately_positive(other->fTs[--oIndex].fT - oEndT)) | 561 while (approximately_positive(other->fTs[--oIndex].fT - oEndT)) |
| 554 ; | 562 ; |
| 555 double tRatio = (oEndT - oStartT) / (endT - startT); | 563 double tRatio = (oEndT - oStartT) / (endT - startT); |
| 556 SkOpSpan* test = &fTs[index]; | 564 SkOpSpan* test = &fTs[index]; |
| 557 SkOpSpan* oTest = &other->fTs[oIndex]; | 565 SkOpSpan* oTest = &other->fTs[oIndex]; |
| 558 SkTDArray<double> outsideTs; | 566 SkTDArray<double> outsideTs; |
| 559 SkTDArray<double> oOutsideTs; | 567 SkTDArray<double> oOutsideTs; |
| 560 do { | 568 do { |
| 561 bool decrement = test->fWindValue && oTest->fWindValue && !binary; | 569 bool decrement = test->fWindValue && oTest->fWindValue; |
| 562 bool track = test->fWindValue || oTest->fWindValue; | 570 bool track = test->fWindValue || oTest->fWindValue; |
| 571 bool bigger = test->fWindValue >= oTest->fWindValue; |
| 563 double testT = test->fT; | 572 double testT = test->fT; |
| 564 double oTestT = oTest->fT; | 573 double oTestT = oTest->fT; |
| 565 SkOpSpan* span = test; | 574 SkOpSpan* span = test; |
| 566 do { | 575 do { |
| 567 if (decrement) { | 576 if (decrement) { |
| 568 decrementSpan(span); | 577 if (binary && bigger) { |
| 578 span->fOppValue--; |
| 579 } else { |
| 580 decrementSpan(span); |
| 581 } |
| 569 } else if (track && span->fT < 1 && oTestT < 1) { | 582 } else if (track && span->fT < 1 && oTestT < 1) { |
| 570 TrackOutside(&outsideTs, span->fT, oTestT); | 583 TrackOutside(&outsideTs, span->fT, oTestT); |
| 571 } | 584 } |
| 572 span = &fTs[++index]; | 585 span = &fTs[++index]; |
| 573 } while (approximately_negative(span->fT - testT)); | 586 } while (approximately_negative(span->fT - testT)); |
| 574 SkOpSpan* oSpan = oTest; | 587 SkOpSpan* oSpan = oTest; |
| 575 double otherTMatchStart = oEndT - (span->fT - startT) * tRatio; | 588 double otherTMatchStart = oEndT - (span->fT - startT) * tRatio; |
| 576 double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio; | 589 double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio; |
| 577 SkDEBUGCODE(int originalWindValue = oSpan->fWindValue); | 590 SkDEBUGCODE(int originalWindValue = oSpan->fWindValue); |
| 578 while (approximately_negative(otherTMatchStart - oSpan->fT) | 591 while (approximately_negative(otherTMatchStart - oSpan->fT) |
| 579 && !approximately_negative(otherTMatchEnd - oSpan->fT)) { | 592 && !approximately_negative(otherTMatchEnd - oSpan->fT)) { |
| 580 #ifdef SK_DEBUG | 593 #ifdef SK_DEBUG |
| 581 SkASSERT(originalWindValue == oSpan->fWindValue); | 594 SkASSERT(originalWindValue == oSpan->fWindValue); |
| 582 #endif | 595 #endif |
| 583 if (decrement) { | 596 if (decrement) { |
| 584 other->decrementSpan(oSpan); | 597 if (binary && !bigger) { |
| 598 oSpan->fOppValue--; |
| 599 } else { |
| 600 other->decrementSpan(oSpan); |
| 601 } |
| 585 } else if (track && oSpan->fT < 1 && testT < 1) { | 602 } else if (track && oSpan->fT < 1 && testT < 1) { |
| 586 TrackOutside(&oOutsideTs, oSpan->fT, testT); | 603 TrackOutside(&oOutsideTs, oSpan->fT, testT); |
| 587 } | 604 } |
| 588 if (!oIndex) { | 605 if (!oIndex) { |
| 589 break; | 606 break; |
| 590 } | 607 } |
| 591 oSpan = &other->fTs[--oIndex]; | 608 oSpan = &other->fTs[--oIndex]; |
| 592 } | 609 } |
| 593 test = span; | 610 test = span; |
| 594 oTest = oSpan; | 611 oTest = oSpan; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 int otherInsertedAt = other->addT(this, pt, otherT); | 768 int otherInsertedAt = other->addT(this, pt, otherT); |
| 752 addOtherT(insertedAt, otherT, otherInsertedAt); | 769 addOtherT(insertedAt, otherT, otherInsertedAt); |
| 753 other->addOtherT(otherInsertedAt, t, insertedAt); | 770 other->addOtherT(otherInsertedAt, t, insertedAt); |
| 754 matchWindingValue(insertedAt, t, borrowWind); | 771 matchWindingValue(insertedAt, t, borrowWind); |
| 755 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); | 772 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); |
| 756 } | 773 } |
| 757 | 774 |
| 758 void SkOpSegment::addTwoAngles(int start, int end, SkTDArray<SkOpAngle>* angles)
const { | 775 void SkOpSegment::addTwoAngles(int start, int end, SkTDArray<SkOpAngle>* angles)
const { |
| 759 // add edge leading into junction | 776 // add edge leading into junction |
| 760 int min = SkMin32(end, start); | 777 int min = SkMin32(end, start); |
| 761 if (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0) { | 778 if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) { |
| 762 addAngle(angles, end, start); | 779 addAngle(angles, end, start); |
| 763 } | 780 } |
| 764 // add edge leading away from junction | 781 // add edge leading away from junction |
| 765 int step = SkSign32(end - start); | 782 int step = SkSign32(end - start); |
| 766 int tIndex = nextExactSpan(end, step); | 783 int tIndex = nextExactSpan(end, step); |
| 767 min = SkMin32(end, tIndex); | 784 min = SkMin32(end, tIndex); |
| 768 if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0)) { | 785 if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0)) { |
| 769 addAngle(angles, end, tIndex); | 786 addAngle(angles, end, tIndex); |
| 770 } | 787 } |
| 771 } | 788 } |
| 772 | 789 |
| 773 int SkOpSegment::advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int inde
x) { | 790 int SkOpSegment::advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int inde
x) { |
| 774 SkOpSpan* const test = &fTs[index]; | 791 SkOpSpan* const test = &fTs[index]; |
| 775 SkOpSpan* end; | 792 SkOpSpan* end; |
| 776 do { | 793 do { |
| 777 end = &fTs[++index]; | 794 end = &fTs[++index]; |
| 778 } while (approximately_negative(end->fT - test->fT)); | 795 } while (approximately_negative(end->fT - test->fT)); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 } | 922 } |
| 906 } | 923 } |
| 907 if (segment->windSum(angle) == SK_MinS32) { | 924 if (segment->windSum(angle) == SK_MinS32) { |
| 908 if (opp) { | 925 if (opp) { |
| 909 if (UseInnerWinding(oMaxWinding, oWinding)) { | 926 if (UseInnerWinding(oMaxWinding, oWinding)) { |
| 910 oMaxWinding = oWinding; | 927 oMaxWinding = oWinding; |
| 911 } | 928 } |
| 912 if (oppoSign && UseInnerWinding(maxWinding, winding)) { | 929 if (oppoSign && UseInnerWinding(maxWinding, winding)) { |
| 913 maxWinding = winding; | 930 maxWinding = winding; |
| 914 } | 931 } |
| 932 #ifdef SK_DEBUG |
| 933 SkASSERT(abs(maxWinding) <= gDebugMaxWindSum); |
| 934 SkASSERT(abs(oMaxWinding) <= gDebugMaxWindSum); |
| 935 #endif |
| 915 (void) segment->markAndChaseWinding(angle, oMaxWinding, maxWindi
ng); | 936 (void) segment->markAndChaseWinding(angle, oMaxWinding, maxWindi
ng); |
| 916 } else { | 937 } else { |
| 917 if (UseInnerWinding(maxWinding, winding)) { | 938 if (UseInnerWinding(maxWinding, winding)) { |
| 918 maxWinding = winding; | 939 maxWinding = winding; |
| 919 } | 940 } |
| 920 if (oppoSign && UseInnerWinding(oMaxWinding, oWinding)) { | 941 if (oppoSign && UseInnerWinding(oMaxWinding, oWinding)) { |
| 921 oMaxWinding = oWinding; | 942 oMaxWinding = oWinding; |
| 922 } | 943 } |
| 944 #ifdef SK_DEBUG |
| 945 SkASSERT(abs(maxWinding) <= gDebugMaxWindSum); |
| 946 SkASSERT(abs(binary ? oMaxWinding : 0) <= gDebugMaxWindSum); |
| 947 #endif |
| 923 (void) segment->markAndChaseWinding(angle, maxWinding, | 948 (void) segment->markAndChaseWinding(angle, maxWinding, |
| 924 binary ? oMaxWinding : 0); | 949 binary ? oMaxWinding : 0); |
| 925 } | 950 } |
| 926 } | 951 } |
| 927 } while (++nextIndex != lastIndex); | 952 } while (++nextIndex != lastIndex); |
| 928 int minIndex = SkMin32(startIndex, endIndex); | 953 int minIndex = SkMin32(startIndex, endIndex); |
| 929 return windSum(minIndex); | 954 return windSum(minIndex); |
| 930 } | 955 } |
| 931 | 956 |
| 932 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi
tT, | 957 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi
tT, |
| (...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2234 *last = &fTs[end]; | 2259 *last = &fTs[end]; |
| 2235 return NULL; | 2260 return NULL; |
| 2236 } | 2261 } |
| 2237 const SkOpSpan& endSpan = fTs[end]; | 2262 const SkOpSpan& endSpan = fTs[end]; |
| 2238 SkOpSegment* other = endSpan.fOther; | 2263 SkOpSegment* other = endSpan.fOther; |
| 2239 *index = endSpan.fOtherIndex; | 2264 *index = endSpan.fOtherIndex; |
| 2240 SkASSERT(*index >= 0); | 2265 SkASSERT(*index >= 0); |
| 2241 int otherEnd = other->nextExactSpan(*index, step); | 2266 int otherEnd = other->nextExactSpan(*index, step); |
| 2242 SkASSERT(otherEnd >= 0); | 2267 SkASSERT(otherEnd >= 0); |
| 2243 *min = SkMin32(*index, otherEnd); | 2268 *min = SkMin32(*index, otherEnd); |
| 2269 if (other->fTs[*min].fTiny) { |
| 2270 *last = NULL; |
| 2271 return NULL; |
| 2272 } |
| 2244 return other; | 2273 return other; |
| 2245 } | 2274 } |
| 2246 | 2275 |
| 2247 // This has callers for two different situations: one establishes the end | 2276 // This has callers for two different situations: one establishes the end |
| 2248 // of the current span, and one establishes the beginning of the next span | 2277 // of the current span, and one establishes the beginning of the next span |
| 2249 // (thus the name). When this is looking for the end of the current span, | 2278 // (thus the name). When this is looking for the end of the current span, |
| 2250 // coincidence is found when the beginning Ts contain -step and the end | 2279 // coincidence is found when the beginning Ts contain -step and the end |
| 2251 // contains step. When it is looking for the beginning of the next, the | 2280 // contains step. When it is looking for the beginning of the next, the |
| 2252 // first Ts found can be ignored and the last Ts should contain -step. | 2281 // first Ts found can be ignored and the last Ts should contain -step. |
| 2253 // OPTIMIZATION: probably should split into two functions | 2282 // OPTIMIZATION: probably should split into two functions |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2482 for (int index = 0; index < count; ++index) { | 2511 for (int index = 0; index < count; ++index) { |
| 2483 if (fTs[index].fT == t) { | 2512 if (fTs[index].fT == t) { |
| 2484 return fTs[index].fWindValue; | 2513 return fTs[index].fWindValue; |
| 2485 } | 2514 } |
| 2486 } | 2515 } |
| 2487 SkASSERT(0); | 2516 SkASSERT(0); |
| 2488 return 0; | 2517 return 0; |
| 2489 } | 2518 } |
| 2490 | 2519 |
| 2491 void SkOpSegment::zeroSpan(SkOpSpan* span) { | 2520 void SkOpSegment::zeroSpan(SkOpSpan* span) { |
| 2492 SkASSERT(span->fWindValue > 0 || span->fOppValue > 0); | 2521 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); |
| 2493 span->fWindValue = 0; | 2522 span->fWindValue = 0; |
| 2494 span->fOppValue = 0; | 2523 span->fOppValue = 0; |
| 2495 SkASSERT(!span->fDone); | 2524 SkASSERT(!span->fDone); |
| 2496 span->fDone = true; | 2525 span->fDone = true; |
| 2497 ++fDoneSpans; | 2526 ++fDoneSpans; |
| 2498 } | 2527 } |
| 2499 | 2528 |
| 2500 #if DEBUG_SWAP_TOP | 2529 #if DEBUG_SWAP_TOP |
| 2501 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const { | 2530 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const { |
| 2502 if (fVerb != SkPath::kCubic_Verb) { | 2531 if (fVerb != SkPath::kCubic_Verb) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2550 if (fOperand) { | 2579 if (fOperand) { |
| 2551 SkDebugf(" operand"); | 2580 SkDebugf(" operand"); |
| 2552 } | 2581 } |
| 2553 if (done()) { | 2582 if (done()) { |
| 2554 SkDebugf(" done"); | 2583 SkDebugf(" done"); |
| 2555 } | 2584 } |
| 2556 SkDebugf("\n"); | 2585 SkDebugf("\n"); |
| 2557 } | 2586 } |
| 2558 #endif | 2587 #endif |
| 2559 | 2588 |
| 2560 #if DEBUG_ACTIVE_SPANS | 2589 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
| 2561 void SkOpSegment::debugShowActiveSpans() const { | 2590 void SkOpSegment::debugShowActiveSpans() const { |
| 2562 if (done()) { | 2591 if (done()) { |
| 2563 return; | 2592 return; |
| 2564 } | 2593 } |
| 2565 #if DEBUG_ACTIVE_SPANS_SHORT_FORM | 2594 #if DEBUG_ACTIVE_SPANS_SHORT_FORM |
| 2566 int lastId = -1; | 2595 int lastId = -1; |
| 2567 double lastT = -1; | 2596 double lastT = -1; |
| 2568 #endif | 2597 #endif |
| 2569 for (int i = 0; i < fTs.count(); ++i) { | 2598 for (int i = 0; i < fTs.count(); ++i) { |
| 2570 SkASSERT(&fTs[i] == &fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOther-> | 2599 SkASSERT(&fTs[i] == &fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOther-> |
| 2571 fTs[fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOtherIndex]); | 2600 fTs[fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOtherIndex]); |
| 2572 if (fTs[i].fDone) { | 2601 if (fTs[i].fDone) { |
| 2573 continue; | 2602 continue; |
| 2574 } | 2603 } |
| 2604 SkASSERT(i < fTs.count() - 1); |
| 2575 #if DEBUG_ACTIVE_SPANS_SHORT_FORM | 2605 #if DEBUG_ACTIVE_SPANS_SHORT_FORM |
| 2576 if (lastId == fID && lastT == fTs[i].fT) { | 2606 if (lastId == fID && lastT == fTs[i].fT) { |
| 2577 continue; | 2607 continue; |
| 2578 } | 2608 } |
| 2579 lastId = fID; | 2609 lastId = fID; |
| 2580 lastT = fTs[i].fT; | 2610 lastT = fTs[i].fT; |
| 2581 #endif | 2611 #endif |
| 2582 SkDebugf("%s id=%d", __FUNCTION__, fID); | 2612 SkDebugf("%s id=%d", __FUNCTION__, fID); |
| 2583 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); | 2613 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 2584 for (int vIndex = 1; vIndex <= fVerb; ++vIndex) { | 2614 for (int vIndex = 1; vIndex <= fVerb; ++vIndex) { |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2790 sum += fTs[i].fWindValue; | 2820 sum += fTs[i].fWindValue; |
| 2791 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); | 2821 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); |
| 2792 sum += fTs[i].fOppValue; | 2822 sum += fTs[i].fOppValue; |
| 2793 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); | 2823 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); |
| 2794 } | 2824 } |
| 2795 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, | 2825 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, |
| 2796 slots.begin() + slotCount); | 2826 slots.begin() + slotCount); |
| 2797 return sum; | 2827 return sum; |
| 2798 } | 2828 } |
| 2799 #endif | 2829 #endif |
| OLD | NEW |