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" |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 #if DEBUG_COINCIDENCE_VERBOSE | 262 #if DEBUG_COINCIDENCE_VERBOSE |
263 GlitchLog glitches; | 263 GlitchLog glitches; |
264 const SkOpContour* contour = contourList; | 264 const SkOpContour* contour = contourList; |
265 const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); | 265 const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); |
266 coincidence->debugCheckValid(id, &glitches); // don't call validate; spans m
ay be inconsistent | 266 coincidence->debugCheckValid(id, &glitches); // don't call validate; spans m
ay be inconsistent |
267 do { | 267 do { |
268 contour->debugCheckHealth(id, &glitches); | 268 contour->debugCheckHealth(id, &glitches); |
269 contour->debugMissingCoincidence(id, &glitches); | 269 contour->debugMissingCoincidence(id, &glitches); |
270 } while ((contour = contour->next())); | 270 } while ((contour = contour->next())); |
271 coincidence->debugRemoveCollapsed(id, &glitches); | 271 coincidence->debugRemoveCollapsed(id, &glitches); |
272 coincidence->debugAddMissing(id, &glitches); | 272 bool added; |
| 273 coincidence->debugAddMissing(id, &glitches, &added); |
273 coincidence->debugExpand(id, &glitches); | 274 coincidence->debugExpand(id, &glitches); |
274 coincidence->debugAddExpanded(id, &glitches); | 275 coincidence->debugAddExpanded(id, &glitches); |
275 coincidence->debugMark(id, &glitches); | 276 coincidence->debugMark(id, &glitches); |
276 coincidence->debugReorder(id, &glitches); | 277 coincidence->debugReorder(id, &glitches); |
277 unsigned mask = 0; | 278 unsigned mask = 0; |
278 for (int index = 0; index < glitches.fGlitches.count(); ++index) { | 279 for (int index = 0; index < glitches.fGlitches.count(); ++index) { |
279 const SpanGlitch& glitch = glitches.fGlitches[index]; | 280 const SpanGlitch& glitch = glitches.fGlitches[index]; |
280 mask |= 1 << glitch.fType; | 281 mask |= 1 << glitch.fType; |
281 } | 282 } |
282 for (int index = 0; index < kGlitchType_Count; ++index) { | 283 for (int index = 0; index < kGlitchType_Count; ++index) { |
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 return; | 1387 return; |
1387 } | 1388 } |
1388 log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coin
PtTEnd(), over1s, over1e); | 1389 log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coin
PtTEnd(), over1s, over1e); |
1389 this->debugValidate(); | 1390 this->debugValidate(); |
1390 return; | 1391 return; |
1391 } | 1392 } |
1392 | 1393 |
1393 /* Commented-out lines keep this in sync addIfMissing() */ | 1394 /* Commented-out lines keep this in sync addIfMissing() */ |
1394 // note that over1s, over1e, over2s, over2e are ordered | 1395 // note that over1s, over1e, over2s, over2e are ordered |
1395 void SkOpCoincidence::debugAddIfMissing(const char* id, SkPathOpsDebug::GlitchLo
g* log, const SkOpPtT* over1s, const SkOpPtT* over2s, | 1396 void SkOpCoincidence::debugAddIfMissing(const char* id, SkPathOpsDebug::GlitchLo
g* log, const SkOpPtT* over1s, const SkOpPtT* over2s, |
1396 double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegmen
t* oppSeg, | 1397 double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegmen
t* oppSeg, bool* added, |
1397 const SkOpPtT* over1e, const SkOpPtT* over2e) const { | 1398 const SkOpPtT* over1e, const SkOpPtT* over2e) const { |
1398 SkASSERT(tStart < tEnd); | 1399 SkASSERT(tStart < tEnd); |
1399 SkASSERT(over1s->fT < over1e->fT); | 1400 SkASSERT(over1s->fT < over1e->fT); |
1400 SkASSERT(between(over1s->fT, tStart, over1e->fT)); | 1401 SkASSERT(between(over1s->fT, tStart, over1e->fT)); |
1401 SkASSERT(between(over1s->fT, tEnd, over1e->fT)); | 1402 SkASSERT(between(over1s->fT, tEnd, over1e->fT)); |
1402 SkASSERT(over2s->fT < over2e->fT); | 1403 SkASSERT(over2s->fT < over2e->fT); |
1403 SkASSERT(between(over2s->fT, tStart, over2e->fT)); | 1404 SkASSERT(between(over2s->fT, tStart, over2e->fT)); |
1404 SkASSERT(between(over2s->fT, tEnd, over2e->fT)); | 1405 SkASSERT(between(over2s->fT, tEnd, over2e->fT)); |
1405 SkASSERT(over1s->segment() == over1e->segment()); | 1406 SkASSERT(over1s->segment() == over1e->segment()); |
1406 SkASSERT(over2s->segment() == over2e->segment()); | 1407 SkASSERT(over2s->segment() == over2e->segment()); |
1407 SkASSERT(over1s->segment() == over2s->segment()); | 1408 SkASSERT(over1s->segment() == over2s->segment()); |
1408 SkASSERT(over1s->segment() != coinSeg); | 1409 SkASSERT(over1s->segment() != coinSeg); |
1409 SkASSERT(over1s->segment() != oppSeg); | 1410 SkASSERT(over1s->segment() != oppSeg); |
1410 SkASSERT(coinSeg != oppSeg); | 1411 SkASSERT(coinSeg != oppSeg); |
1411 double coinTs, coinTe, oppTs, oppTe; | 1412 double coinTs, coinTe, oppTs, oppTe; |
1412 coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); | 1413 coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); |
1413 coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); | 1414 coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); |
1414 if (coinSeg->collapsed(coinTs, coinTe)) { | 1415 if (coinSeg->collapsed(coinTs, coinTe)) { |
1415 return log->record(kAddIfCollapsed_Glitch, id, coinSeg); | 1416 return log->record(kAddIfCollapsed_Glitch, id, coinSeg); |
1416 } | 1417 } |
1417 oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); | 1418 oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); |
1418 oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); | 1419 oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); |
1419 if (oppSeg->collapsed(oppTs, oppTe)) { | 1420 if (oppSeg->collapsed(oppTs, oppTe)) { |
1420 return log->record(kAddIfCollapsed_Glitch, id, oppSeg); | 1421 return log->record(kAddIfCollapsed_Glitch, id, oppSeg); |
1421 } | 1422 } |
1422 if (coinTs > coinTe) { | 1423 if (coinTs > coinTe) { |
1423 SkTSwap(coinTs, coinTe); | 1424 SkTSwap(coinTs, coinTe); |
1424 SkTSwap(oppTs, oppTe); | 1425 SkTSwap(oppTs, oppTe); |
1425 } | 1426 } |
1426 return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, opp
Ts, oppTe | 1427 return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, opp
Ts, oppTe, added |
1427 ); | 1428 ); |
1428 } | 1429 } |
1429 | 1430 |
1430 /* Commented-out lines keep this in sync addOrOverlap() */ | 1431 /* Commented-out lines keep this in sync addOrOverlap() */ |
1431 // If this is called by addEndMovedSpans(), a returned false propogates out to a
n abort. | 1432 // If this is called by addEndMovedSpans(), a returned false propogates out to a
n abort. |
1432 // If this is called by AddIfMissing(), a returned false indicates there was not
hing to add | 1433 // If this is called by AddIfMissing(), a returned false indicates there was not
hing to add |
1433 void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLo
g* log, | 1434 void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLo
g* log, |
1434 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, | 1435 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
1435 double coinTs, double coinTe, double oppTs, double oppTe) const { | 1436 double coinTs, double coinTe, double oppTs, double oppTe, bool* added) c
onst { |
1436 SkTDArray<SkCoincidentSpans*> overlaps; | 1437 SkTDArray<SkCoincidentSpans*> overlaps; |
1437 SkASSERT(!fTop); // this is (correctly) reversed in addifMissing() | 1438 SkASSERT(!fTop); // this is (correctly) reversed in addifMissing() |
1438 if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs
, oppTe, &overlaps)) { | 1439 if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs
, oppTe, |
| 1440 &overlaps)) { |
1439 return; | 1441 return; |
1440 } | 1442 } |
1441 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, | 1443 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, |
1442 coinTe, oppTs, oppTe, &overlaps)) { | 1444 coinTe, oppTs, oppTe, &overlaps)) { |
1443 return; | 1445 return; |
1444 } | 1446 } |
1445 const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; | 1447 const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; |
1446 for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps
before continuing | 1448 for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps
before continuing |
1447 const SkCoincidentSpans* test = overlaps[index]; | 1449 const SkCoincidentSpans* test = overlaps[index]; |
1448 if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { | 1450 if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1541 #endif | 1543 #endif |
1542 } | 1544 } |
1543 this->debugValidate(); | 1545 this->debugValidate(); |
1544 return (void) result; | 1546 return (void) result; |
1545 } | 1547 } |
1546 | 1548 |
1547 // Extra commented-out lines keep this in sync with addMissing() | 1549 // Extra commented-out lines keep this in sync with addMissing() |
1548 /* detects overlaps of different coincident runs on same segment */ | 1550 /* detects overlaps of different coincident runs on same segment */ |
1549 /* does not detect overlaps for pairs without any segments in common */ | 1551 /* does not detect overlaps for pairs without any segments in common */ |
1550 // returns true if caller should loop again | 1552 // returns true if caller should loop again |
1551 void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog*
log) const { | 1553 void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog*
log, bool* added) const { |
1552 const SkCoincidentSpans* outer = fHead; | 1554 const SkCoincidentSpans* outer = fHead; |
1553 if (!outer) { | 1555 if (!outer) { |
1554 return; | 1556 return; |
1555 } | 1557 } |
1556 // bool added = false; | 1558 // bool added = false; |
1557 // fTop = outer; | 1559 // fTop = outer; |
1558 // fHead = nullptr; | 1560 // fHead = nullptr; |
1559 do { | 1561 do { |
1560 // addifmissing can modify the list that this is walking | 1562 // addifmissing can modify the list that this is walking |
1561 // save head so that walker can iterate over old data unperturbed | 1563 // save head so that walker can iterate over old data unperturbed |
(...skipping 22 matching lines...) Expand all Loading... |
1584 SkASSERT(!innerOpp->done()); | 1586 SkASSERT(!innerOpp->done()); |
1585 // SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoi
n); | 1587 // SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoi
n); |
1586 // SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp)
; | 1588 // SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp)
; |
1587 if (outerCoin == innerCoin) { | 1589 if (outerCoin == innerCoin) { |
1588 const SkOpPtT* oce = outer->coinPtTEnd(); | 1590 const SkOpPtT* oce = outer->coinPtTEnd(); |
1589 SkASSERT(!oce->deleted()); | 1591 SkASSERT(!oce->deleted()); |
1590 const SkOpPtT* ice = inner->coinPtTEnd(); | 1592 const SkOpPtT* ice = inner->coinPtTEnd(); |
1591 SkASSERT(!ice->deleted()); | 1593 SkASSERT(!ice->deleted()); |
1592 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &o
verS, &overE)) { | 1594 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &o
verS, &overE)) { |
1593 this->debugAddIfMissing(id, log, ocs->starter(oce), ics->sta
rter(ice), | 1595 this->debugAddIfMissing(id, log, ocs->starter(oce), ics->sta
rter(ice), |
1594 overS, overE, outerOpp, innerOpp, | 1596 overS, overE, outerOpp, innerOpp, added, |
1595 ocs->debugEnder(oce), | 1597 ocs->debugEnder(oce), |
1596 ics->debugEnder(ice)); | 1598 ics->debugEnder(ice)); |
1597 } | 1599 } |
1598 } else if (outerCoin == innerOpp) { | 1600 } else if (outerCoin == innerOpp) { |
1599 const SkOpPtT* oce = outer->coinPtTEnd(); | 1601 const SkOpPtT* oce = outer->coinPtTEnd(); |
1600 SkASSERT(!oce->deleted()); | 1602 SkASSERT(!oce->deleted()); |
1601 const SkOpPtT* ioe = inner->oppPtTEnd(); | 1603 const SkOpPtT* ioe = inner->oppPtTEnd(); |
1602 SkASSERT(!ioe->deleted()); | 1604 SkASSERT(!ioe->deleted()); |
1603 if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &
overS, &overE)) { | 1605 if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &
overS, &overE)) { |
1604 this->debugAddIfMissing(id, log, ocs->starter(oce), ios->sta
rter(ioe), | 1606 this->debugAddIfMissing(id, log, ocs->starter(oce), ios->sta
rter(ioe), |
1605 overS, overE, outerOpp, innerCoin, | 1607 overS, overE, outerOpp, innerCoin, added, |
1606 ocs->debugEnder(oce), | 1608 ocs->debugEnder(oce), |
1607 ios->debugEnder(ioe)); | 1609 ios->debugEnder(ioe)); |
1608 } | 1610 } |
1609 } else if (outerOpp == innerCoin) { | 1611 } else if (outerOpp == innerCoin) { |
1610 const SkOpPtT* ooe = outer->oppPtTEnd(); | 1612 const SkOpPtT* ooe = outer->oppPtTEnd(); |
1611 SkASSERT(!ooe->deleted()); | 1613 SkASSERT(!ooe->deleted()); |
1612 const SkOpPtT* ice = inner->coinPtTEnd(); | 1614 const SkOpPtT* ice = inner->coinPtTEnd(); |
1613 SkASSERT(!ice->deleted()); | 1615 SkASSERT(!ice->deleted()); |
1614 SkASSERT(outerCoin != innerOpp); | 1616 SkASSERT(outerCoin != innerOpp); |
1615 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { | 1617 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { |
1616 this->debugAddIfMissing(id, log, oos->starter(ooe), ics->sta
rter(ice), | 1618 this->debugAddIfMissing(id, log, oos->starter(ooe), ics->sta
rter(ice), |
1617 overS, overE, outerCoin, innerOpp, | 1619 overS, overE, outerCoin, innerOpp, added, |
1618 oos->debugEnder(ooe), | 1620 oos->debugEnder(ooe), |
1619 ics->debugEnder(ice)); | 1621 ics->debugEnder(ice)); |
1620 } | 1622 } |
1621 } else if (outerOpp == innerOpp) { | 1623 } else if (outerOpp == innerOpp) { |
1622 const SkOpPtT* ooe = outer->oppPtTEnd(); | 1624 const SkOpPtT* ooe = outer->oppPtTEnd(); |
1623 SkASSERT(!ooe->deleted()); | 1625 SkASSERT(!ooe->deleted()); |
1624 const SkOpPtT* ioe = inner->oppPtTEnd(); | 1626 const SkOpPtT* ioe = inner->oppPtTEnd(); |
1625 SkASSERT(!ioe->deleted()); | 1627 SkASSERT(!ioe->deleted()); |
1626 SkASSERT(outerCoin != innerCoin); | 1628 SkASSERT(outerCoin != innerCoin); |
1627 if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { | 1629 if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { |
1628 this->debugAddIfMissing(id, log, oos->starter(ooe), ios->sta
rter(ioe), | 1630 this->debugAddIfMissing(id, log, oos->starter(ooe), ios->sta
rter(ioe), |
1629 overS, overE, outerCoin, innerCoin, | 1631 overS, overE, outerCoin, innerCoin, added, |
1630 oos->debugEnder(ooe), | 1632 oos->debugEnder(ooe), |
1631 ios->debugEnder(ioe)); | 1633 ios->debugEnder(ioe)); |
1632 } | 1634 } |
1633 } | 1635 } |
1634 this->debugValidate(); | 1636 this->debugValidate(); |
1635 } | 1637 } |
1636 } while ((outer = outer->next())); | 1638 } while ((outer = outer->next())); |
1637 // this->restoreHead(); | 1639 // this->restoreHead(); |
1638 return; | 1640 return; |
1639 } | 1641 } |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1966 // check for overlapping coincident spans | 1968 // check for overlapping coincident spans |
1967 const SkCoincidentSpans* test = head; | 1969 const SkCoincidentSpans* test = head; |
1968 while (test) { | 1970 while (test) { |
1969 const SkCoincidentSpans* next = test->next(); | 1971 const SkCoincidentSpans* next = test->next(); |
1970 DebugCheckOverlap(test, next, id, log); | 1972 DebugCheckOverlap(test, next, id, log); |
1971 DebugCheckOverlap(test, opt, id, log); | 1973 DebugCheckOverlap(test, opt, id, log); |
1972 test = next; | 1974 test = next; |
1973 } | 1975 } |
1974 } | 1976 } |
1975 | 1977 |
1976 #if DEBUG_COINCIDENCE_VERBOSE | |
1977 void SkOpCoincidence::debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLo
g* log) const { | |
1978 DebugCheckOverlapTop(fHead, fTop, id, log); | |
1979 DebugCheckOverlapTop(fTop, nullptr, id, log); | |
1980 } | |
1981 #endif | |
1982 | |
1983 static void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans
* opt, | 1978 static void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans
* opt, |
1984 const char* id, SkPathOpsDebug::GlitchLog* log) { | 1979 const char* id, SkPathOpsDebug::GlitchLog* log) { |
1985 // look for pts inside coincident spans that are not inside the opposite spa
ns | 1980 // look for pts inside coincident spans that are not inside the opposite spa
ns |
1986 const SkCoincidentSpans* coin = head; | 1981 const SkCoincidentSpans* coin = head; |
1987 while (coin) { | 1982 while (coin) { |
1988 SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), | 1983 SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), |
1989 coin->oppPtTStart()->segment())); | 1984 coin->oppPtTStart()->segment())); |
1990 SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); | 1985 SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); |
1991 SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); | 1986 SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); |
1992 SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); | 1987 SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2642 #endif | 2637 #endif |
2643 SkPath::FillType fillType = path.getFillType(); | 2638 SkPath::FillType fillType = path.getFillType(); |
2644 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); | 2639 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); |
2645 if (includeDeclaration) { | 2640 if (includeDeclaration) { |
2646 SkDebugf(" SkPath %s;\n", name); | 2641 SkDebugf(" SkPath %s;\n", name); |
2647 } | 2642 } |
2648 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 2643 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); |
2649 iter.setPath(path); | 2644 iter.setPath(path); |
2650 showPathContours(iter, name); | 2645 showPathContours(iter, name); |
2651 } | 2646 } |
OLD | NEW |