Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Side by Side Diff: src/pathops/SkOpSegment.cpp

Issue 14798004: path ops -- fix skp bugs (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698