| Index: src/pathops/SkPathOpsDebug.cpp
|
| diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
|
| index 0331f34e8a74d91ffb34f8b6d0b0d7f88f7cab25..7db93f5e969b5ba53689be47c5f9936f76601e20 100644
|
| --- a/src/pathops/SkPathOpsDebug.cpp
|
| +++ b/src/pathops/SkPathOpsDebug.cpp
|
| @@ -7,13 +7,6 @@
|
|
|
| #include "SkPathOpsDebug.h"
|
| #include "SkPath.h"
|
| -#if DEBUG_ANGLE
|
| -#include "SkString.h"
|
| -#endif
|
| -
|
| -#if DEBUG_VALIDATE
|
| -extern bool FLAGS_runFail;
|
| -#endif
|
|
|
| #if defined SK_DEBUG || !FORCE_RELEASE
|
|
|
| @@ -33,10 +26,10 @@
|
| const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
|
| #endif
|
|
|
| -bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray,
|
| - const SkOpSpanBase* span) {
|
| +bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpan *>& chaseArray,
|
| + const SkOpSpan* span) {
|
| for (int index = 0; index < chaseArray.count(); ++index) {
|
| - const SkOpSpanBase* entry = chaseArray[index];
|
| + const SkOpSpan* entry = chaseArray[index];
|
| if (entry == span) {
|
| return true;
|
| }
|
| @@ -72,8 +65,6 @@
|
| SkDebugf("%d", wind);
|
| }
|
| }
|
| -#endif // defined SK_DEBUG || !FORCE_RELEASE
|
| -
|
|
|
| #if DEBUG_SHOW_TEST_NAME
|
| void* SkPathOpsDebug::CreateNameStr() {
|
| @@ -106,159 +97,10 @@
|
| }
|
| #endif
|
|
|
| +#endif // defined SK_DEBUG || !FORCE_RELEASE
|
| +
|
| #include "SkOpAngle.h"
|
| #include "SkOpSegment.h"
|
| -
|
| -#if DEBUG_SWAP_TOP
|
| -int SkOpSegment::debugInflections(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
|
| - if (fVerb != SkPath::kCubic_Verb) {
|
| - return false;
|
| - }
|
| - SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t());
|
| - double inflections[2];
|
| - return dst.findInflections(inflections);
|
| -}
|
| -#endif
|
| -
|
| -SkOpAngle* SkOpSegment::debugLastAngle() {
|
| - SkOpAngle* result = NULL;
|
| - SkOpSpan* span = this->head();
|
| - do {
|
| - if (span->toAngle()) {
|
| - SkASSERT(!result);
|
| - result = span->toAngle();
|
| - }
|
| - } while ((span = span->next()->upCastable()));
|
| - SkASSERT(result);
|
| - return result;
|
| -}
|
| -
|
| -void SkOpSegment::debugReset() {
|
| - this->init(this->fPts, this->contour(), this->verb());
|
| -}
|
| -
|
| -#if DEBUG_ACTIVE_SPANS
|
| -void SkOpSegment::debugShowActiveSpans() const {
|
| - debugValidate();
|
| - if (done()) {
|
| - return;
|
| - }
|
| - int lastId = -1;
|
| - double lastT = -1;
|
| - const SkOpSpan* span = &fHead;
|
| - do {
|
| - if (span->done()) {
|
| - continue;
|
| - }
|
| - if (lastId == fID && lastT == span->t()) {
|
| - continue;
|
| - }
|
| - lastId = fID;
|
| - lastT = span->t();
|
| - SkDebugf("%s id=%d", __FUNCTION__, fID);
|
| - SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| - for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| - SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| - }
|
| - const SkOpPtT* ptT = span->ptT();
|
| - SkDebugf(") t=%1.9g (%1.9g,%1.9g)", ptT->fT, ptT->fPt.fX, ptT->fPt.fY);
|
| - SkDebugf(" tEnd=%1.9g", span->next()->t());
|
| - SkDebugf(" windSum=");
|
| - if (span->windSum() == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", span->windSum());
|
| - }
|
| - SkDebugf(" windValue=%d oppValue=%d", span->windValue(), span->oppValue());
|
| - SkDebugf("\n");
|
| - } while ((span = span->next()->upCastable()));
|
| -}
|
| -#endif
|
| -
|
| -#if DEBUG_MARK_DONE
|
| -void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) {
|
| - const SkPoint& pt = span->ptT()->fPt;
|
| - SkDebugf("%s id=%d", fun, fID);
|
| - SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| - for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| - SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| - }
|
| - SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
|
| - span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t());
|
| - if (winding == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", winding);
|
| - }
|
| - SkDebugf(" windSum=");
|
| - if (span->windSum() == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", span->windSum());
|
| - }
|
| - SkDebugf(" windValue=%d\n", span->windValue());
|
| -}
|
| -
|
| -void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding,
|
| - int oppWinding) {
|
| - const SkPoint& pt = span->ptT()->fPt;
|
| - SkDebugf("%s id=%d", fun, fID);
|
| - SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| - for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| - SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| - }
|
| - SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
|
| - span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding);
|
| - if (winding == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", winding);
|
| - }
|
| - SkDebugf(" newOppSum=");
|
| - if (oppWinding == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", oppWinding);
|
| - }
|
| - SkDebugf(" oppSum=");
|
| - if (span->oppSum() == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", span->oppSum());
|
| - }
|
| - SkDebugf(" windSum=");
|
| - if (span->windSum() == SK_MinS32) {
|
| - SkDebugf("?");
|
| - } else {
|
| - SkDebugf("%d", span->windSum());
|
| - }
|
| - SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue());
|
| -}
|
| -
|
| -#endif
|
| -
|
| -#if DEBUG_ANGLE
|
| -SkString SkOpAngle::debugPart() const {
|
| - SkString result;
|
| - switch (this->segment()->verb()) {
|
| - case SkPath::kLine_Verb:
|
| - result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart),
|
| - this->segment()->debugID());
|
| - break;
|
| - case SkPath::kQuad_Verb:
|
| - result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart),
|
| - this->segment()->debugID());
|
| - break;
|
| - case SkPath::kCubic_Verb:
|
| - result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart),
|
| - this->segment()->debugID());
|
| - break;
|
| - default:
|
| - SkASSERT(0);
|
| - }
|
| - return result;
|
| -}
|
| -#endif
|
|
|
| #if DEBUG_SORT
|
| void SkOpAngle::debugLoop() const {
|
| @@ -269,59 +111,25 @@
|
| SkDebugf("\n");
|
| next = next->fNext;
|
| } while (next && next != first);
|
| - next = first;
|
| - do {
|
| - next->debugValidate();
|
| - next = next->fNext;
|
| - } while (next && next != first);
|
| -}
|
| -#endif
|
| -
|
| -void SkOpAngle::debugValidate() const {
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_ANGLE
|
| +void SkOpAngle::debugSameAs(const SkOpAngle* compare) const {
|
| + SK_ALWAYSBREAK(fSegment == compare->fSegment);
|
| + const SkOpSpan& startSpan = fSegment->span(fStart);
|
| + const SkOpSpan& oStartSpan = fSegment->span(compare->fStart);
|
| + SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle);
|
| + SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle);
|
| + const SkOpSpan& endSpan = fSegment->span(fEnd);
|
| + const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
|
| + SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle);
|
| + SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle);
|
| +}
|
| +#endif
|
| +
|
| #if DEBUG_VALIDATE
|
| - const SkOpAngle* first = this;
|
| - const SkOpAngle* next = this;
|
| - int wind = 0;
|
| - int opp = 0;
|
| - int lastXor = -1;
|
| - int lastOppXor = -1;
|
| - do {
|
| - if (next->unorderable()) {
|
| - return;
|
| - }
|
| - const SkOpSpan* minSpan = next->start()->starter(next->end());
|
| - if (minSpan->windValue() == SK_MinS32) {
|
| - return;
|
| - }
|
| - bool op = next->segment()->operand();
|
| - bool isXor = next->segment()->isXor();
|
| - bool oppXor = next->segment()->oppXor();
|
| - SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM));
|
| - SkASSERT(!DEBUG_LIMIT_WIND_SUM
|
| - || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM));
|
| - bool useXor = op ? oppXor : isXor;
|
| - SkASSERT(lastXor == -1 || lastXor == (int) useXor);
|
| - lastXor = (int) useXor;
|
| - wind += next->sign() * (op ? minSpan->oppValue() : minSpan->windValue());
|
| - if (useXor) {
|
| - wind &= 1;
|
| - }
|
| - useXor = op ? isXor : oppXor;
|
| - SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor);
|
| - lastOppXor = (int) useXor;
|
| - opp += next->sign() * (op ? minSpan->windValue() : minSpan->oppValue());
|
| - if (useXor) {
|
| - opp &= 1;
|
| - }
|
| - next = next->fNext;
|
| - } while (next && next != first);
|
| - SkASSERT(wind == 0);
|
| - SkASSERT(opp == 0 || !FLAGS_runFail);
|
| -#endif
|
| -}
|
| -
|
| void SkOpAngle::debugValidateNext() const {
|
| -#if !FORCE_RELEASE
|
| const SkOpAngle* first = this;
|
| const SkOpAngle* next = first;
|
| SkTDArray<const SkOpAngle*>(angles);
|
| @@ -337,137 +145,422 @@
|
| return;
|
| }
|
| } while (true);
|
| -#endif
|
| -}
|
| +}
|
| +
|
| +void SkOpAngle::debugValidateLoop() const {
|
| + const SkOpAngle* first = this;
|
| + const SkOpAngle* next = first;
|
| + SK_ALWAYSBREAK(first->next() != first);
|
| + int signSum = 0;
|
| + int oppSum = 0;
|
| + bool firstOperand = fSegment->operand();
|
| + bool unorderable = false;
|
| + do {
|
| + unorderable |= next->fUnorderable;
|
| + const SkOpSegment* segment = next->fSegment;
|
| + bool operandsMatch = firstOperand == segment->operand();
|
| + signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(next);
|
| + oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(next);
|
| + const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
|
| + if (segment->_xor()) {
|
| +// SK_ALWAYSBREAK(span.fWindValue == 1);
|
| +// SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1);
|
| + }
|
| + if (segment->oppXor()) {
|
| + SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1);
|
| +// SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1);
|
| + }
|
| + next = next->next();
|
| + if (!next) {
|
| + return;
|
| + }
|
| + } while (next != first);
|
| + if (unorderable) {
|
| + return;
|
| + }
|
| + SK_ALWAYSBREAK(!signSum || fSegment->_xor());
|
| + SK_ALWAYSBREAK(!oppSum || fSegment->oppXor());
|
| + int lastWinding;
|
| + int lastOppWinding;
|
| + int winding;
|
| + int oppWinding;
|
| + do {
|
| + const SkOpSegment* segment = next->fSegment;
|
| + const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
|
| + winding = span.fWindSum;
|
| + if (winding != SK_MinS32) {
|
| +// SK_ALWAYSBREAK(winding != 0);
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
|
| + lastWinding = winding;
|
| + int diffWinding = segment->spanSign(next);
|
| + if (!segment->_xor()) {
|
| + SK_ALWAYSBREAK(diffWinding != 0);
|
| + bool sameSign = (winding > 0) == (diffWinding > 0);
|
| + winding -= sameSign ? diffWinding : -diffWinding;
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
|
| + SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
|
| + if (!sameSign) {
|
| + SkTSwap(winding, lastWinding);
|
| + }
|
| + }
|
| + lastOppWinding = oppWinding = span.fOppSum;
|
| + if (oppWinding != SK_MinS32 && !segment->oppXor()) {
|
| + int oppDiffWinding = segment->oppSign(next);
|
| +// SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor());
|
| + if (oppDiffWinding) {
|
| + bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0);
|
| + oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding;
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
|
| + SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding));
|
| + if (!oppSameSign) {
|
| + SkTSwap(oppWinding, lastOppWinding);
|
| + }
|
| + }
|
| + }
|
| + firstOperand = segment->operand();
|
| + break;
|
| + }
|
| + SK_ALWAYSBREAK(span.fOppSum == SK_MinS32);
|
| + next = next->next();
|
| + } while (next != first);
|
| + if (winding == SK_MinS32) {
|
| + return;
|
| + }
|
| + SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding));
|
| + first = next;
|
| + next = next->next();
|
| + do {
|
| + const SkOpSegment* segment = next->fSegment;
|
| + lastWinding = winding;
|
| + lastOppWinding = oppWinding;
|
| + bool operandsMatch = firstOperand == segment->operand();
|
| + if (operandsMatch) {
|
| + if (!segment->_xor()) {
|
| + winding -= segment->spanSign(next);
|
| + SK_ALWAYSBREAK(winding != lastWinding);
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
|
| + }
|
| + if (!segment->oppXor()) {
|
| + int oppDiffWinding = segment->oppSign(next);
|
| + if (oppWinding != SK_MinS32) {
|
| + oppWinding -= oppDiffWinding;
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
|
| + } else {
|
| + SK_ALWAYSBREAK(oppDiffWinding == 0);
|
| + }
|
| + }
|
| + } else {
|
| + if (!segment->oppXor()) {
|
| + winding -= segment->oppSign(next);
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
|
| + }
|
| + if (!segment->_xor()) {
|
| + oppWinding -= segment->spanSign(next);
|
| + SK_ALWAYSBREAK(oppWinding != lastOppWinding);
|
| + SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
|
| + }
|
| + }
|
| + bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
|
| + int sumWinding = useInner ? winding : lastWinding;
|
| + bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWinding);
|
| + int oppSumWinding = oppUseInner ? oppWinding : lastOppWinding;
|
| + if (!operandsMatch) {
|
| + SkTSwap(useInner, oppUseInner);
|
| + SkTSwap(sumWinding, oppSumWinding);
|
| + }
|
| + const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
|
| + if (winding == -lastWinding) {
|
| + if (span.fWindSum != SK_MinS32) {
|
| + SkDebugf("%s useInner=%d spanSign=%d lastWinding=%d winding=%d windSum=%d\n",
|
| + __FUNCTION__,
|
| + useInner, segment->spanSign(next), lastWinding, winding, span.fWindSum);
|
| + }
|
| + }
|
| + if (oppWinding != SK_MinS32) {
|
| + if (span.fOppSum != SK_MinS32) {
|
| + SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor());
|
| + }
|
| + } else {
|
| + SK_ALWAYSBREAK(!firstOperand);
|
| + SK_ALWAYSBREAK(!segment->operand());
|
| + SK_ALWAYSBREAK(!span.fOppValue);
|
| + }
|
| + next = next->next();
|
| + } while (next != first);
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_SWAP_TOP
|
| +bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
|
| + if (fVerb != SkPath::kCubic_Verb) {
|
| + return false;
|
| + }
|
| + SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
|
| + return dst.controlsContainedByEnds();
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_CONCIDENT
|
| +// SK_ALWAYSBREAK if pair has not already been added
|
| +void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
|
| + for (int i = 0; i < fTs.count(); ++i) {
|
| + if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
|
| + return;
|
| + }
|
| + }
|
| + SK_ALWAYSBREAK(0);
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_ANGLE
|
| +void SkOpSegment::debugCheckPointsEqualish(int tStart, int tEnd) const {
|
| + const SkPoint& basePt = fTs[tStart].fPt;
|
| + while (++tStart < tEnd) {
|
| + const SkPoint& cmpPt = fTs[tStart].fPt;
|
| + SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_SWAP_TOP
|
| +int SkOpSegment::debugInflections(int tStart, int tEnd) const {
|
| + if (fVerb != SkPath::kCubic_Verb) {
|
| + return false;
|
| + }
|
| + SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
|
| + double inflections[2];
|
| + return dst.findInflections(inflections);
|
| +}
|
| +#endif
|
| +
|
| +const SkOpAngle* SkOpSegment::debugLastAngle() const {
|
| + const SkOpAngle* result = NULL;
|
| + for (int index = 0; index < count(); ++index) {
|
| + const SkOpSpan& span = this->span(index);
|
| + if (span.fToAngle) {
|
| + SkASSERT(!result);
|
| + result = span.fToAngle;
|
| + }
|
| + }
|
| + SkASSERT(result);
|
| + return result;
|
| +}
|
| +
|
| +void SkOpSegment::debugReset() {
|
| + fTs.reset();
|
| + fAngles.reset();
|
| +}
|
| +
|
| +#if DEBUG_CONCIDENT
|
| +void SkOpSegment::debugShowTs(const char* prefix) const {
|
| + SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
|
| + int lastWind = -1;
|
| + int lastOpp = -1;
|
| + double lastT = -1;
|
| + int i;
|
| + for (i = 0; i < fTs.count(); ++i) {
|
| + bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
|
| + || lastOpp != fTs[i].fOppValue;
|
| + if (change && lastWind >= 0) {
|
| + SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
|
| + lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
|
| + }
|
| + if (change) {
|
| + SkDebugf(" [o=%d", fTs[i].fOther->fID);
|
| + lastWind = fTs[i].fWindValue;
|
| + lastOpp = fTs[i].fOppValue;
|
| + lastT = fTs[i].fT;
|
| + } else {
|
| + SkDebugf(",%d", fTs[i].fOther->fID);
|
| + }
|
| + }
|
| + if (i <= 0) {
|
| + return;
|
| + }
|
| + SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
|
| + lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
|
| + if (fOperand) {
|
| + SkDebugf(" operand");
|
| + }
|
| + if (done()) {
|
| + SkDebugf(" done");
|
| + }
|
| + SkDebugf("\n");
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
|
| +void SkOpSegment::debugShowActiveSpans() const {
|
| + debugValidate();
|
| + if (done()) {
|
| + return;
|
| + }
|
| +#if DEBUG_ACTIVE_SPANS_SHORT_FORM
|
| + int lastId = -1;
|
| + double lastT = -1;
|
| +#endif
|
| + for (int i = 0; i < fTs.count(); ++i) {
|
| + if (fTs[i].fDone) {
|
| + continue;
|
| + }
|
| + SK_ALWAYSBREAK(i < fTs.count() - 1);
|
| +#if DEBUG_ACTIVE_SPANS_SHORT_FORM
|
| + if (lastId == fID && lastT == fTs[i].fT) {
|
| + continue;
|
| + }
|
| + lastId = fID;
|
| + lastT = fTs[i].fT;
|
| +#endif
|
| + SkDebugf("%s id=%d", __FUNCTION__, fID);
|
| + SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| + for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| + SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| + }
|
| + const SkOpSpan* span = &fTs[i];
|
| + SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
|
| + int iEnd = i + 1;
|
| + while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
|
| + ++iEnd;
|
| + }
|
| + SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
|
| + const SkOpSegment* other = fTs[i].fOther;
|
| + SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
|
| + other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
|
| + if (fTs[i].fWindSum == SK_MinS32) {
|
| + SkDebugf("?");
|
| + } else {
|
| + SkDebugf("%d", fTs[i].fWindSum);
|
| + }
|
| + SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
|
| +void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
|
| + const SkPoint& pt = xyAtT(&span);
|
| + SkDebugf("%s id=%d", fun, fID);
|
| + SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| + for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| + SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| + }
|
| + SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
|
| + fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
|
| + SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
|
| + span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
|
| + (&span)[1].fT, winding);
|
| + if (span.fWindSum == SK_MinS32) {
|
| + SkDebugf("?");
|
| + } else {
|
| + SkDebugf("%d", span.fWindSum);
|
| + }
|
| + SkDebugf(" windValue=%d\n", span.fWindValue);
|
| +}
|
| +
|
| +void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
|
| + int oppWinding) {
|
| + const SkPoint& pt = xyAtT(&span);
|
| + SkDebugf("%s id=%d", fun, fID);
|
| + SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
|
| + for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
|
| + SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
|
| + }
|
| + SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
|
| + fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
|
| + SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
|
| + span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
|
| + (&span)[1].fT, winding, oppWinding);
|
| + if (span.fOppSum == SK_MinS32) {
|
| + SkDebugf("?");
|
| + } else {
|
| + SkDebugf("%d", span.fOppSum);
|
| + }
|
| + SkDebugf(" windSum=");
|
| + if (span.fWindSum == SK_MinS32) {
|
| + SkDebugf("?");
|
| + } else {
|
| + SkDebugf("%d", span.fWindSum);
|
| + }
|
| + SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue);
|
| +}
|
| +#endif
|
| +
|
| +#if DEBUG_SHOW_WINDING
|
| +int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
|
| + if (!(1 << fID & ofInterest)) {
|
| + return 0;
|
| + }
|
| + int sum = 0;
|
| + SkTArray<char, true> slots(slotCount * 2);
|
| + memset(slots.begin(), ' ', slotCount * 2);
|
| + for (int i = 0; i < fTs.count(); ++i) {
|
| + // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
|
| + // continue;
|
| + // }
|
| + sum += fTs[i].fWindValue;
|
| + slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
|
| + sum += fTs[i].fOppValue;
|
| + slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
|
| + }
|
| + SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
|
| + slots.begin() + slotCount);
|
| + return sum;
|
| +}
|
| +#endif
|
|
|
| void SkOpSegment::debugValidate() const {
|
| #if DEBUG_VALIDATE
|
| - const SkOpSpanBase* span = &fHead;
|
| - double lastT = -1;
|
| - const SkOpSpanBase* prev = NULL;
|
| - int count = 0;
|
| + int count = fTs.count();
|
| + SK_ALWAYSBREAK(count >= 2);
|
| + SK_ALWAYSBREAK(fTs[0].fT == 0);
|
| + SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
|
| int done = 0;
|
| - do {
|
| - if (!span->final()) {
|
| - ++count;
|
| - done += span->upCast()->done() ? 1 : 0;
|
| - }
|
| - SkASSERT(span->segment() == this);
|
| - SkASSERT(!prev || prev->upCast()->next() == span);
|
| - SkASSERT(!prev || prev == span->prev());
|
| - prev = span;
|
| - double t = span->ptT()->fT;
|
| - SkASSERT(lastT < t);
|
| - lastT = t;
|
| - span->debugValidate();
|
| - } while (!span->final() && (span = span->upCast()->next()));
|
| - SkASSERT(count == fCount);
|
| - SkASSERT(done == fDoneCount);
|
| - SkASSERT(span->final());
|
| - span->debugValidate();
|
| -#endif
|
| -}
|
| -
|
| -bool SkOpSpanBase::debugCoinEndLoopCheck() const {
|
| - int loop = 0;
|
| - const SkOpSpanBase* next = this;
|
| - SkOpSpanBase* nextCoin;
|
| - do {
|
| - nextCoin = next->fCoinEnd;
|
| - SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin);
|
| - for (int check = 1; check < loop - 1; ++check) {
|
| - const SkOpSpanBase* checkCoin = this->fCoinEnd;
|
| - const SkOpSpanBase* innerCoin = checkCoin;
|
| - for (int inner = check + 1; inner < loop; ++inner) {
|
| - innerCoin = innerCoin->fCoinEnd;
|
| - if (checkCoin == innerCoin) {
|
| - SkDebugf("*** bad coincident end loop ***\n");
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - ++loop;
|
| - } while ((next = nextCoin) && next != this);
|
| - return true;
|
| -}
|
| -
|
| -void SkOpSpanBase::debugValidate() const {
|
| -#if DEBUG_VALIDATE
|
| - const SkOpPtT* ptT = &fPtT;
|
| - SkASSERT(ptT->span() == this);
|
| - do {
|
| -// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt));
|
| - ptT->debugValidate();
|
| - ptT = ptT->next();
|
| - } while (ptT != &fPtT);
|
| - SkASSERT(this->debugCoinEndLoopCheck());
|
| - if (!this->final()) {
|
| - SkASSERT(this->upCast()->debugCoinLoopCheck());
|
| - }
|
| - if (fFromAngle) {
|
| - fFromAngle->debugValidate();
|
| - }
|
| - if (!this->final() && this->upCast()->toAngle()) {
|
| - this->upCast()->toAngle()->debugValidate();
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -bool SkOpSpan::debugCoinLoopCheck() const {
|
| - int loop = 0;
|
| - const SkOpSpan* next = this;
|
| - SkOpSpan* nextCoin;
|
| - do {
|
| - nextCoin = next->fCoincident;
|
| - SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin);
|
| - for (int check = 1; check < loop - 1; ++check) {
|
| - const SkOpSpan* checkCoin = this->fCoincident;
|
| - const SkOpSpan* innerCoin = checkCoin;
|
| - for (int inner = check + 1; inner < loop; ++inner) {
|
| - innerCoin = innerCoin->fCoincident;
|
| - if (checkCoin == innerCoin) {
|
| - SkDebugf("*** bad coincident loop ***\n");
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - ++loop;
|
| - } while ((next = nextCoin) && next != this);
|
| - return true;
|
| -}
|
| -
|
| -#include "SkOpContour.h"
|
| -
|
| -int SkOpPtT::debugLoopLimit(bool report) const {
|
| - int loop = 0;
|
| - const SkOpPtT* next = this;
|
| - do {
|
| - for (int check = 1; check < loop - 1; ++check) {
|
| - const SkOpPtT* checkPtT = this->fNext;
|
| - const SkOpPtT* innerPtT = checkPtT;
|
| - for (int inner = check + 1; inner < loop; ++inner) {
|
| - innerPtT = innerPtT->fNext;
|
| - if (checkPtT == innerPtT) {
|
| - if (report) {
|
| - SkDebugf("*** bad ptT loop ***\n");
|
| - }
|
| - return loop;
|
| - }
|
| - }
|
| - }
|
| - ++loop;
|
| - } while ((next = next->fNext) && next != this);
|
| - return 0;
|
| -}
|
| -
|
| -void SkOpPtT::debugValidate() const {
|
| -#if DEBUG_VALIDATE
|
| - if (contour()->globalState()->phase() == SkOpGlobalState::kIntersecting) {
|
| - return;
|
| - }
|
| - SkASSERT(fNext);
|
| - SkASSERT(fNext != this);
|
| - SkASSERT(fNext->fNext);
|
| - SkASSERT(debugLoopLimit(false) == 0);
|
| -#endif
|
| -}
|
| + double t = -1;
|
| + const SkOpSpan* last = NULL;
|
| + bool tinyTFound = false;
|
| + bool hasLoop = false;
|
| + for (int i = 0; i < count; ++i) {
|
| + const SkOpSpan& span = fTs[i];
|
| + SK_ALWAYSBREAK(t <= span.fT);
|
| + t = span.fT;
|
| + int otherIndex = span.fOtherIndex;
|
| + const SkOpSegment* other = span.fOther;
|
| + SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
|
| + const SkOpSpan& otherSpan = other->fTs[otherIndex];
|
| + SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
|
| + SK_ALWAYSBREAK(otherSpan.fOtherT == t);
|
| + SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
|
| + done += span.fDone;
|
| + if (last) {
|
| + SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
|
| + bool tsEqual = last->fT == span.fT;
|
| + bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
|
| + SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
|
| + bool pointsEqual = last->fPt == span.fPt;
|
| + bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
|
| +#if 0 // bufferOverflow test triggers this
|
| + SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
|
| +#endif
|
| +// SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
|
| + SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
|
| + SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
|
| + SK_ALWAYSBREAK(!last->fTiny || last->fDone);
|
| + SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
|
| + SK_ALWAYSBREAK(!last->fSmall || last->fDone);
|
| +// SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
|
| +// SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone);
|
| + if (last->fTiny) {
|
| + tinyTFound |= !tsPreciselyEqual;
|
| + } else {
|
| + tinyTFound = false;
|
| + }
|
| + }
|
| + last = &span;
|
| + hasLoop |= last->fLoop;
|
| + }
|
| + SK_ALWAYSBREAK(done == fDoneSpans);
|
| +// if (fAngles.count() ) {
|
| +// fAngles.begin()->debugValidateLoop();
|
| +// }
|
| +#endif
|
| +}
|
|
|