| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2013 Google Inc. | 2  * Copyright 2013 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 | 7 | 
| 8 #include "SkMutex.h" | 8 #include "SkMutex.h" | 
| 9 #include "SkOpCoincidence.h" | 9 #include "SkOpCoincidence.h" | 
| 10 #include "SkOpContour.h" | 10 #include "SkOpContour.h" | 
| 11 #include "SkPath.h" | 11 #include "SkPath.h" | 
| 12 #include "SkPathOpsDebug.h" | 12 #include "SkPathOpsDebug.h" | 
| 13 #include "SkString.h" | 13 #include "SkString.h" | 
| 14 | 14 | 
|  | 15 #undef FAIL_IF | 
|  | 16 #define FAIL_IF(cond, coin) \ | 
|  | 17          do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while 
      (false) | 
|  | 18 | 
|  | 19 #undef FAIL_WITH_NULL_IF | 
|  | 20 #define FAIL_WITH_NULL_IF(cond, span) \ | 
|  | 21          do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while 
      (false) | 
|  | 22 | 
|  | 23 #undef RETURN_FALSE_IF | 
|  | 24 #define RETURN_FALSE_IF(cond, span) \ | 
|  | 25          do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while 
      (false) | 
|  | 26 | 
| 15 class SkCoincidentSpans; | 27 class SkCoincidentSpans; | 
| 16 | 28 | 
| 17 #if DEBUG_VALIDATE | 29 #if DEBUG_VALIDATE | 
| 18 extern bool FLAGS_runFail; | 30 extern bool FLAGS_runFail; | 
| 19 #endif | 31 #endif | 
| 20 | 32 | 
| 21 #if DEBUG_SORT | 33 #if DEBUG_SORT | 
| 22 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; | 34 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; | 
| 23 int SkPathOpsDebug::gSortCount; | 35 int SkPathOpsDebug::gSortCount; | 
| 24 #endif | 36 #endif | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 60     kCollapsedOppValue_Glitch, | 72     kCollapsedOppValue_Glitch, | 
| 61     kCollapsedSpan_Glitch, | 73     kCollapsedSpan_Glitch, | 
| 62     kCollapsedWindValue_Glitch, | 74     kCollapsedWindValue_Glitch, | 
| 63     kDeletedCoin_Glitch, | 75     kDeletedCoin_Glitch, | 
| 64     kExpandCoin_Glitch, | 76     kExpandCoin_Glitch, | 
| 65     kMarkCoinEnd_Glitch, | 77     kMarkCoinEnd_Glitch, | 
| 66     kMarkCoinInsert_Glitch, | 78     kMarkCoinInsert_Glitch, | 
| 67     kMarkCoinMissing_Glitch, | 79     kMarkCoinMissing_Glitch, | 
| 68     kMarkCoinStart_Glitch, | 80     kMarkCoinStart_Glitch, | 
| 69     kMergeContained_Glitch, | 81     kMergeContained_Glitch, | 
|  | 82     kMergeMatches_Glitch, | 
| 70     kMissingCoin_Glitch, | 83     kMissingCoin_Glitch, | 
| 71     kMissingDone_Glitch, | 84     kMissingDone_Glitch, | 
| 72     kMissingIntersection_Glitch, | 85     kMissingIntersection_Glitch, | 
| 73     kMoveMultiple_Glitch, | 86     kMoveMultiple_Glitch, | 
| 74     kMoveNearbyClearAll_Glitch, | 87     kMoveNearbyClearAll_Glitch, | 
| 75     kMoveNearbyClearAll2_Glitch, | 88     kMoveNearbyClearAll2_Glitch, | 
| 76     kMoveNearbyMerge_Glitch, | 89     kMoveNearbyMerge_Glitch, | 
| 77     kMoveNearbyMergeFinal_Glitch, | 90     kMoveNearbyMergeFinal_Glitch, | 
| 78     kMoveNearbyRelease_Glitch, | 91     kMoveNearbyRelease_Glitch, | 
| 79     kMoveNearbyReleaseFinal_Glitch, | 92     kMoveNearbyReleaseFinal_Glitch, | 
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 324             case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); brea
      k; | 337             case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); brea
      k; | 
| 325             case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; | 338             case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; | 
| 326             case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); br
      eak; | 339             case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); br
      eak; | 
| 327             case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; | 340             case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; | 
| 328             case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; | 341             case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; | 
| 329             case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; | 342             case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; | 
| 330             case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; | 343             case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; | 
| 331             case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; | 344             case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; | 
| 332             case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; | 345             case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; | 
| 333             case kMergeContained_Glitch: SkDebugf(" MergeContained"); break; | 346             case kMergeContained_Glitch: SkDebugf(" MergeContained"); break; | 
|  | 347             case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; | 
| 334             case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; | 348             case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; | 
| 335             case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; | 349             case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; | 
| 336             case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); 
      break; | 350             case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); 
      break; | 
| 337             case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; | 351             case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; | 
| 338             case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); br
      eak; | 352             case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); br
      eak; | 
| 339             case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); 
      break; | 353             case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); 
      break; | 
| 340             case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; | 354             case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; | 
| 341             case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal")
      ; break; | 355             case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal")
      ; break; | 
| 342             case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); brea
      k; | 356             case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); brea
      k; | 
| 343             case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFin
      al"); break; | 357             case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFin
      al"); break; | 
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 573     return cubic; | 587     return cubic; | 
| 574 } | 588 } | 
| 575 | 589 | 
| 576 void SkDRect::debugInit() { | 590 void SkDRect::debugInit() { | 
| 577     fLeft = fTop = fRight = fBottom = SK_ScalarNaN; | 591     fLeft = fTop = fRight = fBottom = SK_ScalarNaN; | 
| 578 } | 592 } | 
| 579 | 593 | 
| 580 #include "SkOpAngle.h" | 594 #include "SkOpAngle.h" | 
| 581 #include "SkOpSegment.h" | 595 #include "SkOpSegment.h" | 
| 582 | 596 | 
| 583 #if DEBUG_COINCIDENCE | 597 #if DEBUG_COINCIDENCE_VERBOSE | 
| 584 // commented-out lines keep this in sync with addT() | 598 // commented-out lines keep this in sync with addT() | 
| 585  const SkOpPtT* SkOpSegment::debugAddT(double t) const { | 599  const SkOpPtT* SkOpSegment::debugAddT(double t, const char* id, SkPathOpsDebug:
      :GlitchLog* log) const { | 
| 586     debugValidate(); | 600     debugValidate(); | 
| 587     SkPoint pt = this->ptAtT(t); | 601     SkPoint pt = this->ptAtT(t); | 
| 588     const SkOpSpanBase* span = &fHead; | 602     const SkOpSpanBase* span = &fHead; | 
| 589     do { | 603     do { | 
| 590         const SkOpPtT* result = span->ptT(); | 604         const SkOpPtT* result = span->ptT(); | 
| 591         if (t == result->fT || this->match(result, this, t, pt)) { | 605         if (t == result->fT || this->match(result, this, t, pt)) { | 
| 592 //             span->bumpSpanAdds(); | 606 //             span->bumpSpanAdds(); | 
| 593              return result; | 607              return result; | 
| 594         } | 608         } | 
| 595         if (t < result->fT) { | 609         if (t < result->fT) { | 
| 596             const SkOpSpan* prev = result->span()->prev(); | 610             const SkOpSpan* prev = result->span()->prev(); | 
| 597             FAIL_WITH_NULL_IF(!prev); | 611             FAIL_WITH_NULL_IF(!prev, span); | 
| 598             // marks in global state that new op span has been allocated | 612             // marks in global state that new op span has been allocated | 
| 599             this->globalState()->setAllocatedOpSpan(); | 613             this->globalState()->setAllocatedOpSpan(); | 
| 600 //             span->init(this, prev, t, pt); | 614 //             span->init(this, prev, t, pt); | 
| 601             this->debugValidate(); | 615             this->debugValidate(); | 
| 602 // #if DEBUG_ADD_T | 616 // #if DEBUG_ADD_T | 
| 603 //             SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, 
      t, | 617 //             SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, 
      t, | 
| 604 //                     span->segment()->debugID(), span->debugID()); | 618 //                     span->segment()->debugID(), span->debugID()); | 
| 605 // #endif | 619 // #endif | 
| 606 //             span->bumpSpanAdds(); | 620 //             span->bumpSpanAdds(); | 
| 607             return nullptr; | 621             return nullptr; | 
| 608         } | 622         } | 
| 609         FAIL_WITH_NULL_IF(span != &fTail); | 623         FAIL_WITH_NULL_IF(span != &fTail, span); | 
| 610     } while ((span = span->upCast()->next())); | 624     } while ((span = span->upCast()->next())); | 
| 611     SkASSERT(0); | 625     SkASSERT(0); | 
| 612     return nullptr;  // we never get here, but need this to satisfy compiler | 626     return nullptr;  // we never get here, but need this to satisfy compiler | 
| 613 } | 627 } | 
| 614 #endif | 628 #endif | 
| 615 | 629 | 
| 616 #if DEBUG_ANGLE | 630 #if DEBUG_ANGLE | 
| 617 void SkOpSegment::debugCheckAngleCoin() const { | 631 void SkOpSegment::debugCheckAngleCoin() const { | 
| 618     const SkOpSpanBase* base = &fHead; | 632     const SkOpSpanBase* base = &fHead; | 
| 619     const SkOpSpan* span; | 633     const SkOpSpan* span; | 
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 769             const SkOpCoincidence* coincidence = this->globalState()->coincidenc
      e(); | 783             const SkOpCoincidence* coincidence = this->globalState()->coincidenc
      e(); | 
| 770             const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); | 784             const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); | 
| 771             const SkOpPtT* rootPtT = ptT->span()->ptT(); | 785             const SkOpPtT* rootPtT = ptT->span()->ptT(); | 
| 772             const SkOpPtT* rootOppStart = oppStart->span()->ptT(); | 786             const SkOpPtT* rootOppStart = oppStart->span()->ptT(); | 
| 773             const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); | 787             const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); | 
| 774             if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootO
      ppEnd)) { | 788             if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootO
      ppEnd)) { | 
| 775                 goto swapBack; | 789                 goto swapBack; | 
| 776             } | 790             } | 
| 777             if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp))
       { | 791             if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp))
       { | 
| 778             // mark coincidence | 792             // mark coincidence | 
| 779 #if DEBUG_COINCIDENCE | 793 #if DEBUG_COINCIDENCE_VERBOSE | 
| 780 //                 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\
      n", __FUNCTION__, | 794 //                 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\
      n", __FUNCTION__, | 
| 781 //                         rootPriorPtT->debugID(), rootPtT->debugID(), rootOppS
      tart->debugID(), | 795 //                         rootPriorPtT->debugID(), rootPtT->debugID(), rootOppS
      tart->debugID(), | 
| 782 //                         rootOppEnd->debugID()); | 796 //                         rootOppEnd->debugID()); | 
| 783 #endif | 797 #endif | 
| 784                 log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, op
      pEnd); | 798                 log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, op
      pEnd); | 
| 785                 //   coincidences->add(rootPriorPtT, rootPtT, rootOppStart, root
      OppEnd); | 799                 //   coincidences->add(rootPriorPtT, rootPtT, rootOppStart, root
      OppEnd); | 
| 786                 // } | 800                 // } | 
| 787 #if DEBUG_COINCIDENCE | 801 #if DEBUG_COINCIDENCE | 
| 788 //                SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOpp
      Start, rootOppEnd); | 802 //                SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOpp
      Start, rootOppEnd); | 
| 789 #endif | 803 #endif | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 872                     } | 886                     } | 
| 873                     const SkOpPtT* matchPtT = startPtT; | 887                     const SkOpPtT* matchPtT = startPtT; | 
| 874                     do { | 888                     do { | 
| 875                         if (matchPtT->segment() == oppPtTSegment) { | 889                         if (matchPtT->segment() == oppPtTSegment) { | 
| 876                             goto foundMatch; | 890                             goto foundMatch; | 
| 877                         } | 891                         } | 
| 878                     } while ((matchPtT = matchPtT->next()) != startPtT); | 892                     } while ((matchPtT = matchPtT->next()) != startPtT); | 
| 879                     goto tryNextSpan; | 893                     goto tryNextSpan; | 
| 880             foundMatch:  // merge oppTest and oppSpan | 894             foundMatch:  // merge oppTest and oppSpan | 
| 881                     oppSegment->debugValidate(); | 895                     oppSegment->debugValidate(); | 
| 882                     if (oppTest == &oppSegment->fTail || oppTest == &oppSegment-
      >fHead) { | 896                     oppTest->debugMergeMatches(id, glitches, oppSpan); | 
| 883                         SkASSERT(oppSpan != &oppSegment->fHead); // don't expect
       collapse | 897                     oppTest->debugAddOpp(id, glitches, oppSpan); | 
| 884                         SkASSERT(oppSpan != &oppSegment->fTail); |  | 
| 885                         glitches->record(kMoveMultiple_Glitch, id, oppTest, oppS
      pan); |  | 
| 886                     } else { |  | 
| 887                         glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppT
      est); |  | 
| 888                     } |  | 
| 889                     oppSegment->debugValidate(); | 898                     oppSegment->debugValidate(); | 
| 890                     goto checkNextSpan; | 899                     goto checkNextSpan; | 
| 891                 } | 900                 } | 
| 892         tryNextSpan: | 901         tryNextSpan: | 
| 893                 ; | 902                 ; | 
| 894             } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())
      ); | 903             } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())
      ); | 
| 895         } while ((testPtT = testPtT->next()) != startPtT); | 904         } while ((testPtT = testPtT->next()) != startPtT); | 
| 896 checkNextSpan: | 905 checkNextSpan: | 
| 897         ; | 906         ; | 
| 898     } while ((test = test->final() ? nullptr : test->upCast()->next())); | 907     } while ((test = test->final() ? nullptr : test->upCast()->next())); | 
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1247 #ifdef SK_DEBUG | 1256 #ifdef SK_DEBUG | 
| 1248 void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpa
      nBase* over, | 1257 void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpa
      nBase* over, | 
| 1249         const SkOpGlobalState* debugState) const { | 1258         const SkOpGlobalState* debugState) const { | 
| 1250     SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); | 1259     SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); | 
| 1251     SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); | 1260     SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); | 
| 1252 } | 1261 } | 
| 1253 #endif | 1262 #endif | 
| 1254 | 1263 | 
| 1255 #if DEBUG_COINCIDENCE_VERBOSE | 1264 #if DEBUG_COINCIDENCE_VERBOSE | 
| 1256 /* Commented-out lines keep this in sync with expand */ | 1265 /* Commented-out lines keep this in sync with expand */ | 
|  | 1266 // expand the range by checking adjacent spans for coincidence | 
| 1257 bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l
      og) const { | 1267 bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l
      og) const { | 
| 1258     bool expanded = false; | 1268     bool expanded = false; | 
| 1259     const SkOpSegment* segment = coinPtTStart()->segment(); | 1269     const SkOpSegment* segment = coinPtTStart()->segment(); | 
| 1260     const SkOpSegment* oppSegment = oppPtTStart()->segment(); | 1270     const SkOpSegment* oppSegment = oppPtTStart()->segment(); | 
| 1261     do { | 1271     do { | 
| 1262         const SkOpSpan* start = coinPtTStart()->span()->upCast(); | 1272         const SkOpSpan* start = coinPtTStart()->span()->upCast(); | 
| 1263         const SkOpSpan* prev = start->prev(); | 1273         const SkOpSpan* prev = start->prev(); | 
| 1264         const SkOpPtT* oppPtT; | 1274         const SkOpPtT* oppPtT; | 
| 1265         if (!prev || !(oppPtT = prev->contains(oppSegment))) { | 1275         if (!prev || !(oppPtT = prev->contains(oppSegment))) { | 
| 1266             break; | 1276             break; | 
| 1267         } | 1277         } | 
| 1268         double midT = (prev->t() + start->t()) / 2; | 1278         double midT = (prev->t() + start->t()) / 2; | 
| 1269         if (!segment->isClose(midT, oppSegment)) { | 1279         if (!segment->isClose(midT, oppSegment)) { | 
| 1270             break; | 1280             break; | 
| 1271         } | 1281         } | 
| 1272         if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT); | 1282         if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT); | 
| 1273         expanded = true; | 1283         expanded = true; | 
| 1274     } while (false);  // actual continues while expansion is possible | 1284     } while (false);  // actual continues while expansion is possible | 
| 1275     do { | 1285     do { | 
| 1276         const SkOpSpanBase* end = coinPtTEnd()->span(); | 1286         const SkOpSpanBase* end = coinPtTEnd()->span(); | 
| 1277         SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); | 1287         SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); | 
|  | 1288         if (next && next->deleted()) { | 
|  | 1289             break; | 
|  | 1290         } | 
| 1278         const SkOpPtT* oppPtT; | 1291         const SkOpPtT* oppPtT; | 
| 1279         if (!next || !(oppPtT = next->contains(oppSegment))) { | 1292         if (!next || !(oppPtT = next->contains(oppSegment))) { | 
| 1280             break; | 1293             break; | 
| 1281         } | 1294         } | 
| 1282         double midT = (end->t() + next->t()) / 2; | 1295         double midT = (end->t() + next->t()) / 2; | 
| 1283         if (!segment->isClose(midT, oppSegment)) { | 1296         if (!segment->isClose(midT, oppSegment)) { | 
| 1284             break; | 1297             break; | 
| 1285         } | 1298         } | 
| 1286         if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT); | 1299         if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT); | 
| 1287         expanded = true; | 1300         expanded = true; | 
| 1288     } while (false);  // actual continues while expansion is possible | 1301     } while (false);  // actual continues while expansion is possible | 
| 1289     return expanded; | 1302     return expanded; | 
| 1290 } | 1303 } | 
| 1291 | 1304 | 
| 1292 #undef FAIL_IF |  | 
| 1293 #define FAIL_IF(cond)  do { if (cond) log->record(kAddExpandedFail_Glitch, id, c
      oin); } while (false) |  | 
| 1294 |  | 
| 1295 /* Commented-out lines keep this in sync with addExpanded */ | 1305 /* Commented-out lines keep this in sync with addExpanded */ | 
| 1296 // for each coincident pair, match the spans | 1306 // for each coincident pair, match the spans | 
| 1297 // if the spans don't match, add the mssing pt to the segment and loop it in the
       opposite span | 1307 // if the spans don't match, add the mssing pt to the segment and loop it in the
       opposite span | 
| 1298 void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
      * log) const { | 1308 void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
      * log) const { | 
| 1299     const SkCoincidentSpans* coin = this->fHead; | 1309     const SkCoincidentSpans* coin = this->fHead; | 
| 1300     if (!coin) { | 1310     if (!coin) { | 
| 1301         return; | 1311         return; | 
| 1302     } | 1312     } | 
| 1303     do { | 1313     do { | 
| 1304         const SkOpPtT* startPtT = coin->coinPtTStart(); | 1314         const SkOpPtT* startPtT = coin->coinPtTStart(); | 
| 1305         const SkOpPtT* oStartPtT = coin->oppPtTStart(); | 1315         const SkOpPtT* oStartPtT = coin->oppPtTStart(); | 
| 1306         SkASSERT(startPtT->contains(oStartPtT)); | 1316         SkASSERT(startPtT->contains(oStartPtT)); | 
| 1307         SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); | 1317         SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); | 
| 1308         const SkOpSpanBase* start = startPtT->span(); | 1318         const SkOpSpanBase* start = startPtT->span(); | 
| 1309         const SkOpSpanBase* oStart = oStartPtT->span(); | 1319         const SkOpSpanBase* oStart = oStartPtT->span(); | 
| 1310         const SkOpSpanBase* end = coin->coinPtTEnd()->span(); | 1320         const SkOpSpanBase* end = coin->coinPtTEnd()->span(); | 
| 1311         const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); | 1321         const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); | 
| 1312         FAIL_IF(oEnd->deleted()); | 1322         FAIL_IF(oEnd->deleted(), coin); | 
|  | 1323         FAIL_IF(!start->upCastable(), coin); | 
| 1313         const SkOpSpanBase* test = start->upCast()->next(); | 1324         const SkOpSpanBase* test = start->upCast()->next(); | 
| 1314         const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->u
      pCast()->next(); | 1325         const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->u
      pCast()->next(); | 
| 1315         if (!oTest) { | 1326         if (!oTest) { | 
| 1316             return; | 1327             return; | 
| 1317         } | 1328         } | 
| 1318         while (test != end || oTest != oEnd) { | 1329         while (test != end || oTest != oEnd) { | 
| 1319             if (!test->ptT()->contains(oTest->segment()) | 1330             if (!test->ptT()->contains(oTest->segment()) | 
| 1320                     || !oTest->ptT()->contains(start->segment())) { | 1331                     || !oTest->ptT()->contains(start->segment())) { | 
| 1321                 // use t ranges to guess which one is missing | 1332                 // use t ranges to guess which one is missing | 
| 1322                 double startRange = coin->coinPtTEnd()->fT - startPtT->fT; | 1333                 double startRange = coin->coinPtTEnd()->fT - startPtT->fT; | 
| 1323                 FAIL_IF(!startRange); | 1334                 FAIL_IF(!startRange, coin); | 
| 1324                 double startPart = (test->t() - startPtT->fT) / startRange; | 1335                 double startPart = (test->t() - startPtT->fT) / startRange; | 
| 1325                 double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT; | 1336                 double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT; | 
| 1326                 FAIL_IF(!oStartRange); | 1337                 FAIL_IF(!oStartRange, coin); | 
| 1327                 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; | 1338                 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; | 
| 1328                 FAIL_IF(startPart == oStartPart); | 1339                 FAIL_IF(startPart == oStartPart, coin); | 
| 1329                 bool startOver = false; | 1340                 bool startOver = false; | 
| 1330                 if (startPart < oStartPart) | 1341                 if (startPart < oStartPart) | 
| 1331                         log->record(kAddExpandedCoin_Glitch, id,  // strange deb
      ug formatting lines up with original | 1342                         log->record(kAddExpandedCoin_Glitch, id,  // strange deb
      ug formatting lines up with original | 
| 1332                                 oStartPtT->fT + oStartRange * startPart, test); | 1343                                 oStartPtT->fT + oStartRange * startPart, test); | 
| 1333                         else log->record(kAddExpandedCoin_Glitch, id, | 1344                         else log->record(kAddExpandedCoin_Glitch, id, | 
| 1334                                 startPtT->fT + startRange * oStartPart, oTest); | 1345                                 startPtT->fT + startRange * oStartPart, oTest); | 
| 1335                 if (false) { | 1346                 if (false) { | 
| 1336                     SkASSERT(0); | 1347                     SkASSERT(0); | 
| 1337                     return; | 1348                     return; | 
| 1338                 } | 1349                 } | 
| 1339                 if (startOver) { | 1350                 if (startOver) { | 
| 1340                     test = start; | 1351                     test = start; | 
| 1341                     oTest = oStart; | 1352                     oTest = oStart; | 
| 1342                 } | 1353                 } | 
| 1343             } | 1354             } | 
| 1344             if (test != end) { | 1355             if (test != end) { | 
|  | 1356                 if (!test->upCastable()) { | 
|  | 1357                     return; | 
|  | 1358                 } | 
| 1345                 test = test->upCast()->next(); | 1359                 test = test->upCast()->next(); | 
| 1346             } | 1360             } | 
| 1347             if (oTest != oEnd) { | 1361             if (oTest != oEnd) { | 
| 1348                 oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(
      ); | 1362                 oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(
      ); | 
| 1349                 if (!oTest) { | 1363                 if (!oTest) { | 
| 1350                     return; | 1364                     return; | 
| 1351                 } | 1365                 } | 
| 1352             } | 1366             } | 
| 1353         } | 1367         } | 
| 1354     } while ((coin = coin->next())); | 1368     } while ((coin = coin->next())); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1386         SkTSwap(oppTs, oppTe); | 1400         SkTSwap(oppTs, oppTe); | 
| 1387     } | 1401     } | 
| 1388     if (swap) { | 1402     if (swap) { | 
| 1389         SkTSwap(oppTs, oppTe); | 1403         SkTSwap(oppTs, oppTe); | 
| 1390     } | 1404     } | 
| 1391     const SkOpSegment* coinSeg = coinPtTStart->segment(); | 1405     const SkOpSegment* coinSeg = coinPtTStart->segment(); | 
| 1392     const SkOpSegment* oppSeg = oppPtTStart->segment(); | 1406     const SkOpSegment* oppSeg = oppPtTStart->segment(); | 
| 1393     if (coinSeg == oppSeg) { | 1407     if (coinSeg == oppSeg) { | 
| 1394         return; | 1408         return; | 
| 1395     } | 1409     } | 
| 1396     return this->debugAddOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe
      , id, log); | 1410     return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, opp
      Ts, oppTe); | 
| 1397 } | 1411 } | 
| 1398 | 1412 | 
| 1399 /* Commented-out lines keep this in sync addOrOverlap() */ | 1413 /* Commented-out lines keep this in sync addOrOverlap() */ | 
| 1400 void SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSe
      gment* oppSeg, | 1414 // If this is called by addEndMovedSpans(), a returned false propogates out to a
      n abort. | 
| 1401         double coinTs, double coinTe, double oppTs, double oppTe, const char* id
      , SkPathOpsDebug::GlitchLog* log) const { | 1415 // If this is called by AddIfMissing(), a returned false indicates there was not
      hing to add | 
|  | 1416 void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLo
      g* log, | 
|  | 1417         const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, | 
|  | 1418         double coinTs, double coinTe, double oppTs, double oppTe) const { | 
| 1402     SkTDArray<SkCoincidentSpans*> overlaps; | 1419     SkTDArray<SkCoincidentSpans*> overlaps; | 
| 1403     SkASSERT(!fTop);   // this is (correctly) reversed in addifMissing() | 1420     SkASSERT(!fTop);   // this is (correctly) reversed in addifMissing() | 
| 1404     if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs
      , oppTe, &overlaps)) { | 1421     if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs
      , oppTe, &overlaps)) { | 
| 1405         return; | 1422         return; | 
| 1406     } | 1423     } | 
| 1407     if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, | 1424     if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, | 
| 1408             coinTe, oppTs, oppTe, &overlaps)) { | 1425             coinTe, oppTs, oppTe, &overlaps)) { | 
| 1409         return; | 1426         return; | 
| 1410     } | 1427     } | 
| 1411     const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; | 1428     const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; | 
| 1412     for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps
       before continuing | 1429     for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps
       before continuing | 
| 1413         const SkCoincidentSpans* test = overlaps[index]; | 1430         const SkCoincidentSpans* test = overlaps[index]; | 
| 1414         if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { | 1431         if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { | 
| 1415             log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart())
      ; | 1432             log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart())
      ; | 
| 1416         } | 1433         } | 
| 1417         if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { | 1434         if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { | 
| 1418             log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd()); | 1435             log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd()); | 
| 1419         } | 1436         } | 
| 1420         if (overlap->flipped() | 1437         if (overlap->flipped() | 
| 1421                 ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT | 1438                 ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT | 
| 1422                 : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { | 1439                 : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { | 
| 1423             log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart()); | 1440             log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart()); | 
| 1424         } | 1441         } | 
| 1425         if (overlap->flipped() | 1442         if (overlap->flipped() | 
| 1426                 ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT | 1443                 ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT | 
| 1427                 : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { | 1444                 : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { | 
| 1428             log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd()); | 1445             log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd()); | 
| 1429         } | 1446         } | 
| 1430         if (!fHead) { | 1447         if (!fHead) { this->debugRelease(id, log, fHead, test); | 
| 1431             SkAssertResult(true); | 1448             this->debugRelease(id, log, fTop, test); | 
| 1432         } | 1449         } | 
| 1433     } | 1450     } | 
| 1434     const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); | 1451     const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); | 
| 1435     const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); | 1452     const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); | 
| 1436     if (overlap && cs && ce && overlap->contains(cs, ce)) { | 1453     RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); | 
| 1437         return; | 1454     RETURN_FALSE_IF(cs != ce || !cs, coinSeg); | 
| 1438     } |  | 
| 1439     SkASSERT(cs != ce || !cs); |  | 
| 1440     const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); | 1455     const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); | 
| 1441     const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); | 1456     const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); | 
| 1442     if (overlap && os && oe && overlap->contains(os, oe)) { | 1457     RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); | 
| 1443         return; |  | 
| 1444     } |  | 
| 1445     SkASSERT(true || !cs || !cs->deleted()); | 1458     SkASSERT(true || !cs || !cs->deleted()); | 
| 1446     SkASSERT(true || !os || !os->deleted()); | 1459     SkASSERT(true || !os || !os->deleted()); | 
| 1447     SkASSERT(true || !ce || !ce->deleted()); | 1460     SkASSERT(true || !ce || !ce->deleted()); | 
| 1448     SkASSERT(true || !oe || !oe->deleted()); | 1461     SkASSERT(true || !oe || !oe->deleted()); | 
| 1449     const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullp
      tr; | 1462     const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullp
      tr; | 
| 1450     const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullp
      tr; | 1463     const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullp
      tr; | 
| 1451     if (csExisting && csExisting == ceExisting) { | 1464     RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); | 
| 1452         return; | 1465     RETURN_FALSE_IF(csExisting && (csExisting == ce || | 
| 1453     } | 1466             csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); | 
| 1454     if (csExisting && (csExisting == ce || csExisting->contains(ceExisting ? ceE
      xisting : ce))) { | 1467     RETURN_FALSE_IF(ceExisting && (ceExisting == cs || | 
| 1455         return; | 1468             ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); | 
| 1456     } |  | 
| 1457     if (ceExisting && (ceExisting == cs || ceExisting->contains(csExisting ? csE
      xisting : cs))) { |  | 
| 1458         return; |  | 
| 1459     } |  | 
| 1460     const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr
      ; | 1469     const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr
      ; | 
| 1461     const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr
      ; | 1470     const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr
      ; | 
| 1462     if (osExisting && osExisting == oeExisting) { | 1471     RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); | 
| 1463         return; | 1472     RETURN_FALSE_IF(osExisting && (osExisting == oe || | 
| 1464     } | 1473             osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); | 
| 1465     if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeE
      xisting : oe))) { | 1474     RETURN_FALSE_IF(oeExisting && (oeExisting == os || | 
| 1466         return; | 1475             oeExisting->contains(osExisting ? osExisting : os)), oppSeg); | 
| 1467     } |  | 
| 1468     if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osE
      xisting : os))) { |  | 
| 1469         return; |  | 
| 1470     } |  | 
| 1471     bool csDeleted = false, osDeleted = false, ceDeleted = false,  oeDeleted = f
      alse; | 1476     bool csDeleted = false, osDeleted = false, ceDeleted = false,  oeDeleted = f
      alse; | 
| 1472     this->debugValidate(); | 1477     this->debugValidate(); | 
| 1473     if (!cs || !os) { | 1478     if (!cs || !os) { | 
| 1474         if (!cs) | 1479         if (!cs) | 
| 1475             cs = coinSeg->debugAddT(coinTs); | 1480             cs = coinSeg->debugAddT(coinTs, id, log); | 
| 1476         if (!os) | 1481         if (!os) | 
| 1477             os = oppSeg->debugAddT(oppTs); | 1482             os = oppSeg->debugAddT(oppTs, id, log); | 
| 1478         if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDe
      leted, &osDeleted); | 1483 //      RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); | 
|  | 1484         if (cs && os) cs->span()->debugAddOpp(id, log, os->span()); | 
| 1479 //         cs = csWritable; | 1485 //         cs = csWritable; | 
| 1480 //         os = osWritable; | 1486 //         os = osWritable->active(); | 
| 1481         if ((ce && ce->deleted()) || (oe && oe->deleted())) { | 1487         RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg)
      ; | 
| 1482             return; |  | 
| 1483         } |  | 
| 1484     } | 1488     } | 
| 1485     if (!ce || !oe) { | 1489     if (!ce || !oe) { | 
| 1486         if (!ce) | 1490         if (!ce) | 
| 1487             ce = coinSeg->debugAddT(coinTe); | 1491             ce = coinSeg->debugAddT(coinTe, id, log); | 
| 1488         if (!oe) | 1492         if (!oe) | 
| 1489             oe = oppSeg->debugAddT(oppTe); | 1493             oe = oppSeg->debugAddT(oppTe, id, log); | 
| 1490         if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDe
      leted, &oeDeleted); | 1494         if (ce && oe) ce->span()->debugAddOpp(id, log, oe->span()); | 
| 1491 //         ce = ceWritable; | 1495 //         ce = ceWritable; | 
| 1492 //         oe = oeWritable; | 1496 //         oe = oeWritable; | 
| 1493     } | 1497     } | 
| 1494     this->debugValidate(); | 1498     this->debugValidate(); | 
| 1495     if (csDeleted || osDeleted || ceDeleted || oeDeleted) { | 1499     RETURN_FALSE_IF(csDeleted, coinSeg); | 
| 1496         return; | 1500     RETURN_FALSE_IF(osDeleted, oppSeg); | 
| 1497     } | 1501     RETURN_FALSE_IF(ceDeleted, coinSeg); | 
| 1498     if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) { | 1502     RETURN_FALSE_IF(oeDeleted, oppSeg); | 
| 1499         return; | 1503     RETURN_FALSE_IF(!cs || !ce || cs->contains(ce) || !os || !oe || os->contains
      (oe), coinSeg); | 
| 1500     } |  | 
| 1501 //     bool result = true; | 1504 //     bool result = true; | 
| 1502     if (overlap) { | 1505     if (overlap) { | 
| 1503         if (overlap->coinPtTStart()->segment() == coinSeg) { | 1506         if (overlap->coinPtTStart()->segment() == coinSeg) { | 
| 1504                 log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinT
      e, oppSeg, oppTs, oppTe); | 1507                 log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinT
      e, oppSeg, oppTs, oppTe); | 
| 1505         } else { | 1508         } else { | 
| 1506             if (oppTs > oppTe) { | 1509             if (oppTs > oppTe) { | 
| 1507                 SkTSwap(coinTs, coinTe); | 1510                 SkTSwap(coinTs, coinTe); | 
| 1508                 SkTSwap(oppTs, oppTe); | 1511                 SkTSwap(oppTs, oppTe); | 
| 1509             } | 1512             } | 
| 1510             log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coin
      Seg, coinTs, coinTe); | 1513             log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coin
      Seg, coinTs, coinTe); | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1592                 } | 1595                 } | 
| 1593             } | 1596             } | 
| 1594             this->debugValidate(); | 1597             this->debugValidate(); | 
| 1595         } | 1598         } | 
| 1596     } while ((outer = outer->next())); | 1599     } while ((outer = outer->next())); | 
| 1597     // this->restoreHead(); | 1600     // this->restoreHead(); | 
| 1598     return; | 1601     return; | 
| 1599 } | 1602 } | 
| 1600 | 1603 | 
| 1601 // Commented-out lines keep this in sync with release() | 1604 // Commented-out lines keep this in sync with release() | 
|  | 1605 void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* lo
      g, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { | 
|  | 1606     const SkCoincidentSpans* head = coin; | 
|  | 1607     const SkCoincidentSpans* prev = nullptr; | 
|  | 1608     const SkCoincidentSpans* next; | 
|  | 1609     do { | 
|  | 1610         next = coin->next(); | 
|  | 1611         if (coin == remove) { | 
|  | 1612             if (prev) { | 
|  | 1613 //                prev->setNext(next); | 
|  | 1614             } else if (head == fHead) { | 
|  | 1615 //                fHead = next; | 
|  | 1616             } else { | 
|  | 1617 //                fTop = next; | 
|  | 1618             } | 
|  | 1619             log->record(kReleasedSpan_Glitch, id, coin); | 
|  | 1620         } | 
|  | 1621         prev = coin; | 
|  | 1622     } while ((coin = next)); | 
|  | 1623     return; | 
|  | 1624 } | 
|  | 1625 | 
| 1602 void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* lo
      g, const SkOpSegment* deleted) const { | 1626 void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* lo
      g, const SkOpSegment* deleted) const { | 
| 1603     const SkCoincidentSpans* coin = fHead; | 1627     const SkCoincidentSpans* coin = fHead; | 
| 1604     if (!coin) { | 1628     if (!coin) { | 
| 1605         return; | 1629         return; | 
| 1606     } | 1630     } | 
| 1607     do { | 1631     do { | 
| 1608         if (coin->coinPtTStart()->segment() == deleted | 1632         if (coin->coinPtTStart()->segment() == deleted | 
| 1609                 || coin->coinPtTEnd()->segment() == deleted | 1633                 || coin->coinPtTEnd()->segment() == deleted | 
| 1610                 || coin->oppPtTStart()->segment() == deleted | 1634                 || coin->oppPtTStart()->segment() == deleted | 
| 1611                 || coin->oppPtTEnd()->segment() == deleted) { | 1635                 || coin->oppPtTEnd()->segment() == deleted) { | 
| 1612             log->record(kReleasedSpan_Glitch, id, coin); | 1636             log->record(kReleasedSpan_Glitch, id, coin); | 
| 1613         } | 1637         } | 
| 1614     } while ((coin = coin->next())); | 1638     } while ((coin = coin->next())); | 
| 1615 } | 1639 } | 
| 1616 | 1640 | 
|  | 1641 | 
| 1617 // Commented-out lines keep this in sync with reorder() | 1642 // Commented-out lines keep this in sync with reorder() | 
| 1618 // iterate through all coincident pairs, looking for ranges greater than 1 | 1643 // iterate through all coincident pairs, looking for ranges greater than 1 | 
| 1619 // if found, see if the opposite pair can match it -- which may require | 1644 // if found, see if the opposite pair can match it -- which may require | 
| 1620 // reordering the ptT pairs | 1645 // reordering the ptT pairs | 
| 1621 void SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* lo
      g) const { | 1646 void SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* lo
      g) const { | 
| 1622     const SkCoincidentSpans* coin = fHead; | 1647     const SkCoincidentSpans* coin = fHead; | 
| 1623     if (!coin) { | 1648     if (!coin) { | 
| 1624         return; | 1649         return; | 
| 1625     } | 1650     } | 
| 1626     do { | 1651     do { | 
| 1627         // most commonly, concidence are one span long; check for that first | 1652         // most commonly, concidence are one span long; check for that first | 
| 1628         int intervals = coin->spanCount(); | 1653         int intervals = coin->spanCount(); | 
| 1629         if (intervals = 1) { | 1654         if (intervals <= 0) { | 
|  | 1655             return; | 
|  | 1656         } | 
|  | 1657         if (1 == intervals) { | 
| 1630 #if DEBUG_COINCIDENCE_VERBOSE | 1658 #if DEBUG_COINCIDENCE_VERBOSE | 
| 1631             // SkASSERT(!coin->debugExpand(nullptr, nullptr)); | 1659             // SkASSERT(!coin->debugExpand(nullptr, nullptr)); | 
| 1632 #endif | 1660 #endif | 
| 1633             continue; | 1661             continue; | 
| 1634         } | 1662         } | 
| 1635         coin->debugExpand(id, log); | 1663         coin->debugExpand(id, log); | 
| 1636         if (coin->spanCount() <= 0) { | 1664         if (coin->spanCount() <= 0) { | 
| 1637             return; | 1665             return; | 
| 1638         } | 1666         } | 
| 1639         // check to see if every span in coin has a mate in opp | 1667         // check to see if every span in coin has a mate in opp | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1702 } | 1730 } | 
| 1703 | 1731 | 
| 1704 // Commented-out lines keep this in sync with mark() | 1732 // Commented-out lines keep this in sync with mark() | 
| 1705 /* this sets up the coincidence links in the segments when the coincidence cross
      es multiple spans */ | 1733 /* this sets up the coincidence links in the segments when the coincidence cross
      es multiple spans */ | 
| 1706 void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) 
      const { | 1734 void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) 
      const { | 
| 1707     const SkCoincidentSpans* coin = fHead; | 1735     const SkCoincidentSpans* coin = fHead; | 
| 1708     if (!coin) { | 1736     if (!coin) { | 
| 1709         return; | 1737         return; | 
| 1710     } | 1738     } | 
| 1711     do { | 1739     do { | 
|  | 1740         if (!coin->coinPtTStartWritable()->span()->upCastable()) { | 
|  | 1741             return; | 
|  | 1742         } | 
| 1712         const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); | 1743         const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); | 
| 1713 //         SkASSERT(start->deleted()); | 1744 //         SkASSERT(start->deleted()); | 
| 1714         const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); | 1745         const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); | 
| 1715 //         SkASSERT(end->deleted()); | 1746 //         SkASSERT(end->deleted()); | 
| 1716         const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); | 1747         const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); | 
| 1717 //         SkASSERT(oStart->deleted()); | 1748 //         SkASSERT(oStart->deleted()); | 
| 1718         const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); | 1749         const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); | 
| 1719 //         SkASSERT(oEnd->deleted()); | 1750 //         SkASSERT(oEnd->deleted()); | 
| 1720         bool flipped = coin->flipped(); | 1751         bool flipped = coin->flipped(); | 
| 1721         if (flipped) { | 1752         if (flipped) { | 
| 1722             SkTSwap(oStart, oEnd); | 1753             SkTSwap(oStart, oEnd); | 
| 1723         } | 1754         } | 
| 1724         /* coin and opp spans may not match up. Mark the ends, and then let the 
      interior | 1755         /* coin and opp spans may not match up. Mark the ends, and then let the 
      interior | 
| 1725            get marked as many times as the spans allow */ | 1756            get marked as many times as the spans allow */ | 
| 1726         start->debugInsertCoincidence(id, log, oStart->upCast()); | 1757         start->debugInsertCoincidence(id, log, oStart->upCast()); | 
| 1727         end->debugInsertCoinEnd(id, log, oEnd); | 1758         end->debugInsertCoinEnd(id, log, oEnd); | 
| 1728         const SkOpSegment* segment = start->segment(); | 1759         const SkOpSegment* segment = start->segment(); | 
| 1729         const SkOpSegment* oSegment = oStart->segment(); | 1760         const SkOpSegment* oSegment = oStart->segment(); | 
| 1730         const SkOpSpanBase* next = start; | 1761         const SkOpSpanBase* next = start; | 
| 1731         const SkOpSpanBase* oNext = oStart; | 1762         const SkOpSpanBase* oNext = oStart; | 
| 1732         while ((next = next->upCast()->next()) != end) { | 1763         while ((next = next->upCast()->next()) != end) { | 
|  | 1764             if (!next->upCastable()) { | 
|  | 1765                 return; | 
|  | 1766             } | 
| 1733             if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flippe
      d), false) { | 1767             if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flippe
      d), false) { | 
| 1734                 return; | 1768                 return; | 
| 1735             } | 1769             } | 
| 1736         } | 1770         } | 
| 1737         while ((oNext = oNext->upCast()->next()) != oEnd) { | 1771         while ((oNext = oNext->upCast()->next()) != oEnd) { | 
|  | 1772             if (!oNext->upCastable()) { | 
|  | 1773                 return; | 
|  | 1774             } | 
| 1738             if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flippe
      d), false) { | 1775             if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flippe
      d), false) { | 
| 1739                 return; | 1776                 return; | 
| 1740             } | 1777             } | 
| 1741         } | 1778         } | 
| 1742     } while ((coin = coin->next())); | 1779     } while ((coin = coin->next())); | 
| 1743     return; | 1780     return; | 
| 1744 } | 1781 } | 
| 1745 #endif | 1782 #endif | 
| 1746 | 1783 | 
| 1747 #if DEBUG_COINCIDENCE_VERBOSE | 1784 #if DEBUG_COINCIDENCE_VERBOSE | 
| 1748 // Commented-out lines keep this in sync with markCollapsed() | 1785 // Commented-out lines keep this in sync with markCollapsed() | 
| 1749 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL
      og* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { | 1786 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL
      og* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { | 
|  | 1787     const SkCoincidentSpans* head = coin; | 
| 1750     while (coin) { | 1788     while (coin) { | 
| 1751         if (coin->collapsed(test)) { | 1789         if (coin->collapsed(test)) { | 
| 1752             if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinP
      tTEnd()->fT)) { | 1790             if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinP
      tTEnd()->fT)) { | 
| 1753                 log->record(kCollapsedCoin_Glitch, id, coin); | 1791                 log->record(kCollapsedCoin_Glitch, id, coin); | 
| 1754             } | 1792             } | 
| 1755             if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtT
      End()->fT)) { | 1793             if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtT
      End()->fT)) { | 
| 1756                 log->record(kCollapsedCoin_Glitch, id, coin); | 1794                 log->record(kCollapsedCoin_Glitch, id, coin); | 
| 1757             } | 1795             } | 
|  | 1796             this->debugRelease(id, log, head, coin); | 
| 1758         } | 1797         } | 
| 1759         coin = coin->next(); | 1798         coin = coin->next(); | 
| 1760     } | 1799     } | 
| 1761 } | 1800 } | 
| 1762 | 1801 | 
| 1763 // Commented-out lines keep this in sync with markCollapsed() | 1802 // Commented-out lines keep this in sync with markCollapsed() | 
| 1764 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL
      og* log, const SkOpPtT* test) const { | 1803 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL
      og* log, const SkOpPtT* test) const { | 
| 1765     this->debugMarkCollapsed(id, log, fHead, test); | 1804     this->debugMarkCollapsed(id, log, fHead, test); | 
| 1766     this->debugMarkCollapsed(id, log, fTop, test); | 1805     this->debugMarkCollapsed(id, log, fTop, test); | 
| 1767 } | 1806 } | 
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2028     } while (!span->final() && (span = span->upCast()->next())); | 2067     } while (!span->final() && (span = span->upCast()->next())); | 
| 2029     SkASSERT(count == fCount); | 2068     SkASSERT(count == fCount); | 
| 2030     SkASSERT(done == fDoneCount); | 2069     SkASSERT(done == fDoneCount); | 
| 2031     SkASSERT(count >= fDoneCount); | 2070     SkASSERT(count >= fDoneCount); | 
| 2032     SkASSERT(span->final()); | 2071     SkASSERT(span->final()); | 
| 2033     span->debugValidate(); | 2072     span->debugValidate(); | 
| 2034 #endif | 2073 #endif | 
| 2035 } | 2074 } | 
| 2036 | 2075 | 
| 2037 #if DEBUG_COINCIDENCE_VERBOSE | 2076 #if DEBUG_COINCIDENCE_VERBOSE | 
| 2038 // Commented-out lines keep this in sync with addOppAndMerge() | 2077 | 
| 2039 // If the added points envelop adjacent spans, merge them in. | 2078 // Commented-out lines keep this in sync with addOpp() | 
| 2040 void SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog
      * log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const { | 2079 void SkOpSpanBase::debugAddOpp(const char* id, SkPathOpsDebug::GlitchLog* log, c
      onst SkOpSpanBase* opp) const { | 
| 2041     const SkOpPtT* oppPrev = this->ptT()->debugOppPrev(opp->ptT()); | 2080     const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); | 
| 2042     if (oppPrev) { | 2081     if (!oppPrev) { | 
| 2043         this->ptT()->debugAddOpp(opp->ptT(), oppPrev); |  | 
| 2044         this->debugCheckForCollapsedCoincidence(id, log); |  | 
| 2045     } |  | 
| 2046     // compute bounds of points in span |  | 
| 2047     SkPathOpsBounds bounds; |  | 
| 2048     bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin); |  | 
| 2049     const SkOpPtT* head = this->ptT(); |  | 
| 2050     const SkOpPtT* nextPt = head; |  | 
| 2051     do { |  | 
| 2052         bounds.add(nextPt->fPt); |  | 
| 2053     } while ((nextPt = nextPt->next()) != head); |  | 
| 2054     if (!bounds.width() && !bounds.height()) { |  | 
| 2055         return; | 2082         return; | 
| 2056     } | 2083     } | 
| 2057     this->debugMergeContained(id, log, bounds, spanDeleted); | 2084     this->debugMergeMatches(id, log, opp); | 
| 2058     opp->debugMergeContained(id, log, bounds, oppDeleted); | 2085     this->ptT()->debugAddOpp(opp->ptT(), oppPrev); | 
|  | 2086     this->debugCheckForCollapsedCoincidence(id, log); | 
| 2059 } | 2087 } | 
| 2060 | 2088 | 
| 2061 // Commented-out lines keep this in sync with checkForCollapsedCoincidence() | 2089 // Commented-out lines keep this in sync with checkForCollapsedCoincidence() | 
| 2062 void SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDe
      bug::GlitchLog* log) const { | 2090 void SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDe
      bug::GlitchLog* log) const { | 
| 2063     const SkOpCoincidence* coins = this->globalState()->coincidence(); | 2091     const SkOpCoincidence* coins = this->globalState()->coincidence(); | 
| 2064     if (coins->isEmpty()) { | 2092     if (coins->isEmpty()) { | 
| 2065         return; | 2093         return; | 
| 2066     } | 2094     } | 
| 2067 // the insert above may have put both ends of a coincident run in the same span | 2095 // the insert above may have put both ends of a coincident run in the same span | 
| 2068 // for each coincident ptT in loop; see if its opposite in is also in the loop | 2096 // for each coincident ptT in loop; see if its opposite in is also in the loop | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2144             current = next; | 2172             current = next; | 
| 2145         } else { | 2173         } else { | 
| 2146             log->record(kMergeContained_Glitch, id, next, current); | 2174             log->record(kMergeContained_Glitch, id, next, current); | 
| 2147             current = next; | 2175             current = next; | 
| 2148         } | 2176         } | 
| 2149     } | 2177     } | 
| 2150 #if DEBUG_COINCIDENCE | 2178 #if DEBUG_COINCIDENCE | 
| 2151     // this->globalState()->coincidence()->debugValidate(); | 2179     // this->globalState()->coincidence()->debugValidate(); | 
| 2152 #endif | 2180 #endif | 
| 2153 } | 2181 } | 
|  | 2182 | 
|  | 2183 // Commented-out lines keep this in sync with mergeMatches() | 
|  | 2184 // Look to see if pt-t linked list contains same segment more than once | 
|  | 2185 // if so, and if each pt-t is directly pointed to by spans in that segment, | 
|  | 2186 // merge them | 
|  | 2187 // keep the points, but remove spans so that the segment doesn't have 2 or more | 
|  | 2188 // spans pointing to the same pt-t loop at different loop elements | 
|  | 2189 void SkOpSpanBase::debugMergeMatches(const char* id, SkPathOpsDebug::GlitchLog* 
      log, const SkOpSpanBase* opp) const { | 
|  | 2190     const SkOpPtT* test = &fPtT; | 
|  | 2191     const SkOpPtT* testNext; | 
|  | 2192     const SkOpPtT* stop = test; | 
|  | 2193     do { | 
|  | 2194         testNext = test->next(); | 
|  | 2195         if (test->deleted()) { | 
|  | 2196             continue; | 
|  | 2197         } | 
|  | 2198         const SkOpSpanBase* testBase = test->span(); | 
|  | 2199         SkASSERT(testBase->ptT() == test); | 
|  | 2200         const SkOpSegment* segment = test->segment(); | 
|  | 2201         if (segment->done()) { | 
|  | 2202             continue; | 
|  | 2203         } | 
|  | 2204         const SkOpPtT* inner = opp->ptT(); | 
|  | 2205         const SkOpPtT* innerStop = inner; | 
|  | 2206         do { | 
|  | 2207             if (inner->segment() != segment) { | 
|  | 2208                 continue; | 
|  | 2209             } | 
|  | 2210             if (inner->deleted()) { | 
|  | 2211                 continue; | 
|  | 2212             } | 
|  | 2213             const SkOpSpanBase* innerBase = inner->span(); | 
|  | 2214             SkASSERT(innerBase->ptT() == inner); | 
|  | 2215             // when the intersection is first detected, the span base is marked 
      if there are | 
|  | 2216             // more than one point in the intersection. | 
|  | 2217 //            if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint())
       { | 
|  | 2218                 if (!zero_or_one(inner->fT)) { | 
|  | 2219                     log->record(kMergeMatches_Glitch, id, innerBase, test); | 
|  | 2220                 } else { | 
|  | 2221                     SkASSERT(inner->fT != test->fT); | 
|  | 2222                     if (!zero_or_one(test->fT)) { | 
|  | 2223                         log->record(kMergeMatches_Glitch, id, testBase, inner); | 
|  | 2224                     } else { | 
|  | 2225                         log->record(kMergeMatches_Glitch, id, segment); | 
|  | 2226 //                        SkDEBUGCODE(testBase->debugSetDeleted()); | 
|  | 2227 //                        test->setDeleted(); | 
|  | 2228 //                        SkDEBUGCODE(innerBase->debugSetDeleted()); | 
|  | 2229 //                        inner->setDeleted(); | 
|  | 2230                     } | 
|  | 2231                 } | 
|  | 2232 #ifdef SK_DEBUG   // assert if another undeleted entry points to segment | 
|  | 2233                 const SkOpPtT* debugInner = inner; | 
|  | 2234                 while ((debugInner = debugInner->next()) != innerStop) { | 
|  | 2235                     if (debugInner->segment() != segment) { | 
|  | 2236                         continue; | 
|  | 2237                     } | 
|  | 2238                     if (debugInner->deleted()) { | 
|  | 2239                         continue; | 
|  | 2240                     } | 
|  | 2241                     SkOPASSERT(0); | 
|  | 2242                 } | 
|  | 2243 #endif | 
|  | 2244                 break; | 
|  | 2245 //            } | 
|  | 2246             break; | 
|  | 2247         } while ((inner = inner->next()) != innerStop); | 
|  | 2248     } while ((test = testNext) != stop); | 
|  | 2249     this->debugCheckForCollapsedCoincidence(id, log); | 
|  | 2250 } | 
|  | 2251 | 
| 2154 #endif | 2252 #endif | 
| 2155 | 2253 | 
| 2156 void SkOpSpanBase::debugResetCoinT() const { | 2254 void SkOpSpanBase::debugResetCoinT() const { | 
| 2157 #if DEBUG_COINCIDENCE_ORDER | 2255 #if DEBUG_COINCIDENCE_ORDER | 
| 2158     const SkOpPtT* ptT = &fPtT; | 2256     const SkOpPtT* ptT = &fPtT; | 
| 2159     do { | 2257     do { | 
| 2160         ptT->debugResetCoinT(); | 2258         ptT->debugResetCoinT(); | 
| 2161         ptT = ptT->next(); | 2259         ptT = ptT->next(); | 
| 2162     } while (ptT != &fPtT); | 2260     } while (ptT != &fPtT); | 
| 2163 #endif | 2261 #endif | 
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2503 #endif | 2601 #endif | 
| 2504     SkPath::FillType fillType = path.getFillType(); | 2602     SkPath::FillType fillType = path.getFillType(); | 
| 2505     SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
      seEvenOdd_FillType); | 2603     SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
      seEvenOdd_FillType); | 
| 2506     if (includeDeclaration) { | 2604     if (includeDeclaration) { | 
| 2507         SkDebugf("    SkPath %s;\n", name); | 2605         SkDebugf("    SkPath %s;\n", name); | 
| 2508     } | 2606     } | 
| 2509     SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 2607     SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 
| 2510     iter.setPath(path); | 2608     iter.setPath(path); | 
| 2511     showPathContours(iter, name); | 2609     showPathContours(iter, name); | 
| 2512 } | 2610 } | 
| OLD | NEW | 
|---|