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 |