| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include "SkOpCoincidence.h" | 7 #include "SkOpCoincidence.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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 SkOpPtT* newPtT = this->addT(newT); | 255 SkOpPtT* newPtT = this->addT(newT); |
| 256 *startOver |= this->globalState()->allocatedOpSpan(); | 256 *startOver |= this->globalState()->allocatedOpSpan(); |
| 257 if (!newPtT) { | 257 if (!newPtT) { |
| 258 return false; | 258 return false; |
| 259 } | 259 } |
| 260 newPtT->fPt = this->ptAtT(newT); | 260 newPtT->fPt = this->ptAtT(newT); |
| 261 // const cast away to change linked list; pt/t values stays unchanged | 261 // const cast away to change linked list; pt/t values stays unchanged |
| 262 SkOpPtT* oppPrev = test->ptT()->oppPrev(newPtT); | 262 SkOpPtT* oppPrev = test->ptT()->oppPrev(newPtT); |
| 263 if (oppPrev) { | 263 if (oppPrev) { |
| 264 SkOpSpanBase* writableTest = const_cast<SkOpSpanBase*>(test); | 264 SkOpSpanBase* writableTest = const_cast<SkOpSpanBase*>(test); |
| 265 writableTest->mergeMatches(newPtT->span()); |
| 265 writableTest->ptT()->addOpp(newPtT, oppPrev); | 266 writableTest->ptT()->addOpp(newPtT, oppPrev); |
| 266 writableTest->checkForCollapsedCoincidence(); | 267 writableTest->checkForCollapsedCoincidence(); |
| 267 } | 268 } |
| 268 return true; | 269 return true; |
| 269 } | 270 } |
| 270 | 271 |
| 271 // Please keep this in sync with debugAddT() | 272 // Please keep this in sync with debugAddT() |
| 272 SkOpPtT* SkOpSegment::addT(double t) { | 273 SkOpPtT* SkOpSegment::addT(double t) { |
| 273 debugValidate(); | 274 debugValidate(); |
| 274 SkPoint pt = this->ptAtT(t); | 275 SkPoint pt = this->ptAtT(t); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 } | 349 } |
| 349 | 350 |
| 350 // Quads and conics collapse if the end points are the same, because | 351 // Quads and conics collapse if the end points are the same, because |
| 351 // the curve doesn't enclose an area. | 352 // the curve doesn't enclose an area. |
| 352 bool SkOpSegment::collapsed() const { | 353 bool SkOpSegment::collapsed() const { |
| 353 // FIXME: cubics can have also collapsed -- need to check if the | 354 // FIXME: cubics can have also collapsed -- need to check if the |
| 354 // control points are on a line with the end points | 355 // control points are on a line with the end points |
| 355 return fVerb < SkPath::kCubic_Verb && fHead.pt() == fTail.pt(); | 356 return fVerb < SkPath::kCubic_Verb && fHead.pt() == fTail.pt(); |
| 356 } | 357 } |
| 357 | 358 |
| 359 bool SkOpSegment::collapsed(double s, double e) const { |
| 360 const SkOpSpanBase* span = &fHead; |
| 361 do { |
| 362 if (span->collapsed(s, e)) { |
| 363 return true; |
| 364 } |
| 365 } while (span->upCastable() && (span = span->upCast()->next())); |
| 366 return false; |
| 367 } |
| 368 |
| 358 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, | 369 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, |
| 359 SkOpAngle::IncludeType includeType) { | 370 SkOpAngle::IncludeType includeType) { |
| 360 SkOpSegment* baseSegment = baseAngle->segment(); | 371 SkOpSegment* baseSegment = baseAngle->segment(); |
| 361 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); | 372 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); |
| 362 int sumSuWinding; | 373 int sumSuWinding; |
| 363 bool binary = includeType >= SkOpAngle::kBinarySingle; | 374 bool binary = includeType >= SkOpAngle::kBinarySingle; |
| 364 if (binary) { | 375 if (binary) { |
| 365 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); | 376 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); |
| 366 if (baseSegment->operand()) { | 377 if (baseSegment->operand()) { |
| 367 SkTSwap<int>(sumMiWinding, sumSuWinding); | 378 SkTSwap<int>(sumMiWinding, sumSuWinding); |
| (...skipping 925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 } | 1304 } |
| 1294 SkOpPtT* matchPtT = startPtT; | 1305 SkOpPtT* matchPtT = startPtT; |
| 1295 do { | 1306 do { |
| 1296 if (matchPtT->segment() == oppPtTSegment) { | 1307 if (matchPtT->segment() == oppPtTSegment) { |
| 1297 goto foundMatch; | 1308 goto foundMatch; |
| 1298 } | 1309 } |
| 1299 } while ((matchPtT = matchPtT->next()) != startPtT); | 1310 } while ((matchPtT = matchPtT->next()) != startPtT); |
| 1300 goto tryNextSpan; | 1311 goto tryNextSpan; |
| 1301 foundMatch: // merge oppTest and oppSpan | 1312 foundMatch: // merge oppTest and oppSpan |
| 1302 oppSegment->debugValidate(); | 1313 oppSegment->debugValidate(); |
| 1303 if (oppTest == &oppSegment->fTail || oppTest == &oppSegment-
>fHead) { | 1314 oppTest->mergeMatches(oppSpan); |
| 1304 SkASSERT(oppSpan != &oppSegment->fHead); // don't expect
collapse | 1315 oppTest->addOpp(oppSpan); |
| 1305 SkASSERT(oppSpan != &oppSegment->fTail); | |
| 1306 oppTest->merge(oppSpan->upCast()); | |
| 1307 } else { | |
| 1308 oppSpan->merge(oppTest->upCast()); | |
| 1309 } | |
| 1310 oppSegment->debugValidate(); | 1316 oppSegment->debugValidate(); |
| 1311 goto checkNextSpan; | 1317 goto checkNextSpan; |
| 1312 } | 1318 } |
| 1313 tryNextSpan: | 1319 tryNextSpan: |
| 1314 ; | 1320 ; |
| 1315 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())
); | 1321 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())
); |
| 1316 } while ((testPtT = testPtT->next()) != startPtT); | 1322 } while ((testPtT = testPtT->next()) != startPtT); |
| 1317 checkNextSpan: | 1323 checkNextSpan: |
| 1318 ; | 1324 ; |
| 1319 } while ((test = test->final() ? nullptr : test->upCast()->next())); | 1325 } while ((test = test->final() ? nullptr : test->upCast()->next())); |
| 1320 debugValidate(); | 1326 debugValidate(); |
| 1321 return true; | 1327 return true; |
| 1322 } | 1328 } |
| 1323 | 1329 |
| 1324 // adjacent spans may have points close by | 1330 // adjacent spans may have points close by |
| 1325 bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* c
heckSpan) const { | 1331 bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* c
heckSpan) const { |
| 1326 const SkOpPtT* refHead = refSpan->ptT(); | 1332 const SkOpPtT* refHead = refSpan->ptT(); |
| 1327 const SkOpPtT* checkHead = checkSpan->ptT(); | 1333 const SkOpPtT* checkHead = checkSpan->ptT(); |
| 1328 // if the first pt pair from adjacent spans are far apart, assume that all are f
ar enough apart | 1334 // if the first pt pair from adjacent spans are far apart, assume that all are f
ar enough apart |
| 1329 if (!SkDPoint::RoughlyEqual(refHead->fPt, checkHead->fPt)) { | 1335 if (!SkDPoint::WayRoughlyEqual(refHead->fPt, checkHead->fPt)) { |
| 1330 #if DEBUG_COINCIDENCE | 1336 #if DEBUG_COINCIDENCE |
| 1331 // verify that no combination of points are close | 1337 // verify that no combination of points are close |
| 1332 const SkOpPtT* dBugRef = refHead; | 1338 const SkOpPtT* dBugRef = refHead; |
| 1333 do { | 1339 do { |
| 1334 const SkOpPtT* dBugCheck = checkHead; | 1340 const SkOpPtT* dBugCheck = checkHead; |
| 1335 do { | 1341 do { |
| 1336 SkASSERT(!SkDPoint::ApproximatelyEqual(dBugRef->fPt, dBugCheck->
fPt)); | 1342 SkOPASSERT(!SkDPoint::ApproximatelyEqual(dBugRef->fPt, dBugCheck
->fPt)); |
| 1337 dBugCheck = dBugCheck->next(); | 1343 dBugCheck = dBugCheck->next(); |
| 1338 } while (dBugCheck != checkHead); | 1344 } while (dBugCheck != checkHead); |
| 1339 dBugRef = dBugRef->next(); | 1345 dBugRef = dBugRef->next(); |
| 1340 } while (dBugRef != refHead); | 1346 } while (dBugRef != refHead); |
| 1341 #endif | 1347 #endif |
| 1342 return false; | 1348 return false; |
| 1343 } | 1349 } |
| 1344 // check only unique points | 1350 // check only unique points |
| 1345 SkScalar distSqBest = SK_ScalarMax; | 1351 SkScalar distSqBest = SK_ScalarMax; |
| 1346 const SkOpPtT* refBest = nullptr; | 1352 const SkOpPtT* refBest = nullptr; |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1677 SkDLine ray = {{{midPt.fX, midPt.fY}, {partMidPt.fX + dxdy.fY, partMidPt
.fY - dxdy.fX}}}; | 1683 SkDLine ray = {{{midPt.fX, midPt.fY}, {partMidPt.fX + dxdy.fY, partMidPt
.fY - dxdy.fX}}}; |
| 1678 SkDCurve oppPart; | 1684 SkDCurve oppPart; |
| 1679 opp->subDivide(priorPtT->span(), ptT->span(), &oppPart); | 1685 opp->subDivide(priorPtT->span(), ptT->span(), &oppPart); |
| 1680 (*CurveDIntersectRay[opp->verb()])(oppPart, ray, &i); | 1686 (*CurveDIntersectRay[opp->verb()])(oppPart, ray, &i); |
| 1681 // measure distance and see if it's small enough to denote coincidence | 1687 // measure distance and see if it's small enough to denote coincidence |
| 1682 for (int index = 0; index < i.used(); ++index) { | 1688 for (int index = 0; index < i.used(); ++index) { |
| 1683 if (!between(0, i[0][index], 1)) { | 1689 if (!between(0, i[0][index], 1)) { |
| 1684 continue; | 1690 continue; |
| 1685 } | 1691 } |
| 1686 SkDPoint oppPt = i.pt(index); | 1692 SkDPoint oppPt = i.pt(index); |
| 1687 if (oppPt.approximatelyEqual(midPt)) { | 1693 if (oppPt.approximatelyDEqual(midPt)) { |
| 1688 // the coincidence can occur at almost any angle | 1694 // the coincidence can occur at almost any angle |
| 1689 coincident = true; | 1695 coincident = true; |
| 1690 } | 1696 } |
| 1691 } | 1697 } |
| 1692 } | 1698 } |
| 1693 return coincident; | 1699 return coincident; |
| 1694 } | 1700 } |
| 1695 | 1701 |
| 1696 void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { | 1702 void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { |
| 1697 SkOpSpan* span = this->head(); | 1703 SkOpSpan* span = this->head(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 int absOut = SkTAbs(outerWinding); | 1772 int absOut = SkTAbs(outerWinding); |
| 1767 int absIn = SkTAbs(innerWinding); | 1773 int absIn = SkTAbs(innerWinding); |
| 1768 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; | 1774 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; |
| 1769 return result; | 1775 return result; |
| 1770 } | 1776 } |
| 1771 | 1777 |
| 1772 int SkOpSegment::windSum(const SkOpAngle* angle) const { | 1778 int SkOpSegment::windSum(const SkOpAngle* angle) const { |
| 1773 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); | 1779 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); |
| 1774 return minSpan->windSum(); | 1780 return minSpan->windSum(); |
| 1775 } | 1781 } |
| OLD | NEW |