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

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

Issue 585913002: fail early if coincidence can't be resolved (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 1264
1265 // FIXME: need to test this case: 1265 // FIXME: need to test this case:
1266 // contourA has two segments that are coincident 1266 // contourA has two segments that are coincident
1267 // contourB has two segments that are coincident in the same place 1267 // contourB has two segments that are coincident in the same place
1268 // each ends up with +2/0 pairs for winding count 1268 // each ends up with +2/0 pairs for winding count
1269 // since logic below doesn't transfer count (only increments/decrements) can thi s be 1269 // since logic below doesn't transfer count (only increments/decrements) can thi s be
1270 // resolved to +4/0 ? 1270 // resolved to +4/0 ?
1271 1271
1272 // set spans from start to end to increment the greater by one and decrement 1272 // set spans from start to end to increment the greater by one and decrement
1273 // the lesser 1273 // the lesser
1274 void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d ouble endT, 1274 bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d ouble endT,
1275 SkOpSegment* other) { 1275 SkOpSegment* other) {
1276 bool binary = fOperand != other->fOperand; 1276 bool binary = fOperand != other->fOperand;
1277 int index = 0; 1277 int index = 0;
1278 while (startPt != fTs[index].fPt) { 1278 while (startPt != fTs[index].fPt) {
1279 SkASSERT(index < fTs.count()); 1279 SkASSERT(index < fTs.count());
1280 ++index; 1280 ++index;
1281 } 1281 }
1282 double startT = fTs[index].fT; 1282 double startT = fTs[index].fT;
1283 while (index > 0 && precisely_equal(fTs[index - 1].fT, startT)) { 1283 while (index > 0 && precisely_equal(fTs[index - 1].fT, startT)) {
1284 --index; 1284 --index;
(...skipping 11 matching lines...) Expand all
1296 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 1296 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
1297 SkOpSpan* test = &fTs[index]; 1297 SkOpSpan* test = &fTs[index];
1298 const SkPoint* testPt = &test->fPt; 1298 const SkPoint* testPt = &test->fPt;
1299 double testT = test->fT; 1299 double testT = test->fT;
1300 SkOpSpan* oTest = &other->fTs[oIndex]; 1300 SkOpSpan* oTest = &other->fTs[oIndex];
1301 const SkPoint* oTestPt = &oTest->fPt; 1301 const SkPoint* oTestPt = &oTest->fPt;
1302 // paths with extreme data will fail this test and eject out of pathops alto gether later on 1302 // paths with extreme data will fail this test and eject out of pathops alto gether later on
1303 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 1303 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
1304 do { 1304 do {
1305 SkASSERT(test->fT < 1); 1305 SkASSERT(test->fT < 1);
1306 SkASSERT(oTest->fT < 1); 1306 if (oTest->fT == 1) {
1307 // paths with extreme data may be so mismatched that we fail here
1308 return false;
1309 }
1307 1310
1308 // consolidate the winding count even if done 1311 // consolidate the winding count even if done
1309 if ((test->fWindValue == 0 && test->fOppValue == 0) 1312 if ((test->fWindValue == 0 && test->fOppValue == 0)
1310 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) { 1313 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) {
1311 SkDEBUGCODE(int firstWind = test->fWindValue); 1314 SkDEBUGCODE(int firstWind = test->fWindValue);
1312 SkDEBUGCODE(int firstOpp = test->fOppValue); 1315 SkDEBUGCODE(int firstOpp = test->fOppValue);
1313 do { 1316 do {
1314 SkASSERT(firstWind == fTs[index].fWindValue); 1317 SkASSERT(firstWind == fTs[index].fWindValue);
1315 SkASSERT(firstOpp == fTs[index].fOppValue); 1318 SkASSERT(firstOpp == fTs[index].fOppValue);
1316 ++index; 1319 ++index;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 } 1405 }
1403 int outCount = outsidePts.count(); 1406 int outCount = outsidePts.count();
1404 if (!done() && outCount) { 1407 if (!done() && outCount) {
1405 addCoinOutsides(outsidePts[0], endPt, other); 1408 addCoinOutsides(outsidePts[0], endPt, other);
1406 } 1409 }
1407 if (!other->done() && oOutsidePts.count()) { 1410 if (!other->done() && oOutsidePts.count()) {
1408 other->addCoinOutsides(oOutsidePts[0], endPt, this); 1411 other->addCoinOutsides(oOutsidePts[0], endPt, this);
1409 } 1412 }
1410 setCoincidentRange(startPt, endPt, other); 1413 setCoincidentRange(startPt, endPt, other);
1411 other->setCoincidentRange(startPt, endPt, this); 1414 other->setCoincidentRange(startPt, endPt, this);
1415 return true;
1412 } 1416 }
1413 1417
1414 // FIXME: this doesn't prevent the same span from being added twice 1418 // FIXME: this doesn't prevent the same span from being added twice
1415 // fix in caller, SkASSERT here? 1419 // fix in caller, SkASSERT here?
1416 // FIXME: this may erroneously reject adds for cubic loops 1420 // FIXME: this may erroneously reject adds for cubic loops
1417 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind, 1421 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind,
1418 const SkPoint& pt, const SkPoint& pt2) { 1422 const SkPoint& pt, const SkPoint& pt2) {
1419 int tCount = fTs.count(); 1423 int tCount = fTs.count();
1420 for (int tIndex = 0; tIndex < tCount; ++tIndex) { 1424 for (int tIndex = 0; tIndex < tCount; ++tIndex) {
1421 const SkOpSpan& span = fTs[tIndex]; 1425 const SkOpSpan& span = fTs[tIndex];
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after
2415 missing.fPt)) { 2419 missing.fPt)) {
2416 continue; 2420 continue;
2417 } 2421 }
2418 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, miss ing.fSegment); 2422 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, miss ing.fSegment);
2419 const SkOpSpan& otherSpan = missingOther->span(otherTIndex); 2423 const SkOpSpan& otherSpan = missingOther->span(otherTIndex);
2420 if (otherSpan.fSmall) { 2424 if (otherSpan.fSmall) {
2421 const SkOpSpan* nextSpan = &otherSpan; 2425 const SkOpSpan* nextSpan = &otherSpan;
2422 do { 2426 do {
2423 ++nextSpan; 2427 ++nextSpan;
2424 } while (nextSpan->fSmall); 2428 } while (nextSpan->fSmall);
2425 missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, nextSpa n->fT, 2429 SkAssertResult(missing.fSegment->addTCoincident(missing.fPt, nextSpa n->fPt,
2426 missingOther); 2430 nextSpan->fT, missingOther));
2427 } else if (otherSpan.fT > 0) { 2431 } else if (otherSpan.fT > 0) {
2428 const SkOpSpan* priorSpan = &otherSpan; 2432 const SkOpSpan* priorSpan = &otherSpan;
2429 do { 2433 do {
2430 --priorSpan; 2434 --priorSpan;
2431 } while (priorSpan->fT == otherSpan.fT); 2435 } while (priorSpan->fT == otherSpan.fT);
2432 if (priorSpan->fSmall) { 2436 if (priorSpan->fSmall) {
2433 missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missin gOther); 2437 missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missin gOther);
2434 } 2438 }
2435 } 2439 }
2436 } 2440 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2487 } 2491 }
2488 } 2492 }
2489 // FIXME: again, be overly conservative to avoid breaking existing tests 2493 // FIXME: again, be overly conservative to avoid breaking existing tests
2490 const SkOpSpan& oSpan = oStartIndex < oEndIndex ? other->fTs[oStartIndex] 2494 const SkOpSpan& oSpan = oStartIndex < oEndIndex ? other->fTs[oStartIndex]
2491 : other->fTs[oEndIndex]; 2495 : other->fTs[oEndIndex];
2492 if (checkMultiple && !oSpan.fSmall) { 2496 if (checkMultiple && !oSpan.fSmall) {
2493 return; 2497 return;
2494 } 2498 }
2495 // SkASSERT(oSpan.fSmall); 2499 // SkASSERT(oSpan.fSmall);
2496 if (oStartIndex < oEndIndex) { 2500 if (oStartIndex < oEndIndex) {
2497 addTCoincident(span.fPt, next->fPt, next->fT, other); 2501 SkAssertResult(addTCoincident(span.fPt, next->fPt, next->fT, other));
2498 } else { 2502 } else {
2499 addTCancel(span.fPt, next->fPt, other); 2503 addTCancel(span.fPt, next->fPt, other);
2500 } 2504 }
2501 if (!checkMultiple) { 2505 if (!checkMultiple) {
2502 return; 2506 return;
2503 } 2507 }
2504 // check to see if either segment is coincident with a third segment -- if i t is, and if 2508 // check to see if either segment is coincident with a third segment -- if i t is, and if
2505 // the opposite segment is not already coincident with the third, make it so 2509 // the opposite segment is not already coincident with the third, make it so
2506 // OPTIMIZE: to make this check easier, add coincident and cancel could set a coincident bit 2510 // OPTIMIZE: to make this check easier, add coincident and cancel could set a coincident bit
2507 if (span.fWindValue != 1 || span.fOppValue != 0) { 2511 if (span.fWindValue != 1 || span.fOppValue != 0) {
(...skipping 24 matching lines...) Expand all
2532 SkPoint oMid = other->ptAtT((oTest->fOtherT + tTest->fT) / 2 ); 2536 SkPoint oMid = other->ptAtT((oTest->fOtherT + tTest->fT) / 2 );
2533 if (!SkDPoint::ApproximatelyEqual(mid, oMid)) { 2537 if (!SkDPoint::ApproximatelyEqual(mid, oMid)) {
2534 continue; 2538 continue;
2535 } 2539 }
2536 } 2540 }
2537 #if DEBUG_CONCIDENT 2541 #if DEBUG_CONCIDENT
2538 SkDebugf("%s coincident found=%d %1.9g %1.9g\n", __FUNCTION__, t estOther->fID, 2542 SkDebugf("%s coincident found=%d %1.9g %1.9g\n", __FUNCTION__, t estOther->fID,
2539 oTest->fOtherT, tTest->fT); 2543 oTest->fOtherT, tTest->fT);
2540 #endif 2544 #endif
2541 if (tTest->fT < oTest->fOtherT) { 2545 if (tTest->fT < oTest->fOtherT) {
2542 addTCoincident(span.fPt, next->fPt, next->fT, testOther); 2546 SkAssertResult(addTCoincident(span.fPt, next->fPt, next->fT, testOther));
2543 } else { 2547 } else {
2544 addTCancel(span.fPt, next->fPt, testOther); 2548 addTCancel(span.fPt, next->fPt, testOther);
2545 } 2549 }
2546 MissingSpan missing; 2550 MissingSpan missing;
2547 missing.fSegment = testOther; 2551 missing.fSegment = testOther;
2548 checkMultiple->push_back(missing); 2552 checkMultiple->push_back(missing);
2549 break; 2553 break;
2550 } 2554 }
2551 } 2555 }
2552 oTest = &oSpan; 2556 oTest = &oSpan;
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after
3421 if (test->fOther == other || test->fOtherT != 1) { 3425 if (test->fOther == other || test->fOtherT != 1) {
3422 continue; 3426 continue;
3423 } 3427 }
3424 SkPoint startPt, endPt; 3428 SkPoint startPt, endPt;
3425 double endT; 3429 double endT;
3426 if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { 3430 if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) {
3427 SkOpSegment* match = test->fOther; 3431 SkOpSegment* match = test->fOther;
3428 if (cancel) { 3432 if (cancel) {
3429 match->addTCancel(startPt, endPt, other); 3433 match->addTCancel(startPt, endPt, other);
3430 } else { 3434 } else {
3431 match->addTCoincident(startPt, endPt, endT, other); 3435 SkAssertResult(match->addTCoincident(startPt, endPt, endT, other ));
3432 } 3436 }
3433 return true; 3437 return true;
3434 } 3438 }
3435 } while (fTs[++tIndex].fT == 0); 3439 } while (fTs[++tIndex].fT == 0);
3436 return false; 3440 return false;
3437 } 3441 }
3438 3442
3439 // this span is excluded by the winding rule -- chase the ends 3443 // this span is excluded by the winding rule -- chase the ends
3440 // as long as they are unambiguous to mark connections as done 3444 // as long as they are unambiguous to mark connections as done
3441 // and give them the same winding value 3445 // and give them the same winding value
(...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after
4441 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 4445 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
4442 span->fWindValue = 0; 4446 span->fWindValue = 0;
4443 span->fOppValue = 0; 4447 span->fOppValue = 0;
4444 if (span->fTiny || span->fSmall) { 4448 if (span->fTiny || span->fSmall) {
4445 return; 4449 return;
4446 } 4450 }
4447 SkASSERT(!span->fDone); 4451 SkASSERT(!span->fDone);
4448 span->fDone = true; 4452 span->fDone = true;
4449 ++fDoneSpans; 4453 ++fDoneSpans;
4450 } 4454 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698