| 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 |