Index: src/pathops/SkPathOpsDebug.cpp |
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp |
index b68ab2acf889bb2cf88be3445038ae45384cb6d5..4e4216310f0a5d6a73ccd49005776115ead49dc1 100644 |
--- a/src/pathops/SkPathOpsDebug.cpp |
+++ b/src/pathops/SkPathOpsDebug.cpp |
@@ -26,6 +26,17 @@ int SkPathOpsDebug::gSortCount; |
const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; |
#endif |
+bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpan *>& chaseArray, |
+ const SkOpSpan* span) { |
+ for (int index = 0; index < chaseArray.count(); ++index) { |
+ const SkOpSpan* entry = chaseArray[index]; |
+ if (entry == span) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { |
size_t len = strlen(str); |
bool num = false; |
@@ -81,81 +92,521 @@ void SkPathOpsDebug::BumpTestName(char* test) { |
} |
#endif |
+#if !DEBUG_SHOW_TEST_NAME // enable when building without extended test |
+void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) { |
+} |
+#endif |
+ |
+#endif // defined SK_DEBUG || !FORCE_RELEASE |
+ |
+#include "SkOpAngle.h" |
#include "SkOpSegment.h" |
-void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) { |
- int count = angles.count(); |
- for (int index = 0; index < count; ++index) { |
- angles[index].dump(); |
- } |
+#if DEBUG_SORT |
+void SkOpAngle::debugLoop() const { |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = this; |
+ do { |
+ next->debugOne(true); |
+ SkDebugf("\n"); |
+ next = next->fNext; |
+ } while (next && next != first); |
} |
-void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) { |
- int count = angles.count(); |
- for (int index = 0; index < count; ++index) { |
- angles[index]->dump(); |
+void SkOpAngle::debugOne(bool functionHeader) const { |
+// fSegment->debugValidate(); |
+ const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd)); |
+ if (functionHeader) { |
+ SkDebugf("%s ", __FUNCTION__); |
} |
-} |
-#endif // SK_DEBUG || !FORCE_RELEASE |
+ SkDebugf("[%d", fSegment->debugID()); |
+#if DEBUG_ANGLE |
+ SkDebugf("/%d", fID); |
+#endif |
+ SkDebugf("] next="); |
+ if (fNext) { |
+ SkDebugf("%d", fNext->fSegment->debugID()); |
+#if DEBUG_ANGLE |
+ SkDebugf("/%d", fNext->fID); |
+#endif |
+ } else { |
+ SkDebugf("?"); |
+ } |
+ SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd); |
+ SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fSegment->span(fStart).fT, fStart, |
+ fSegment->span(fEnd).fT, fEnd); |
+ SkDebugf(" sgn=%d windVal=%d", sign(), mSpan.fWindValue); |
-#ifdef SK_DEBUG |
-void SkOpSpan::dump() const { |
- SkDebugf("t="); |
- DebugDumpDouble(fT); |
- SkDebugf(" pt="); |
- SkDPoint::dump(fPt); |
- SkDebugf(" other.fID=%d", fOther->debugID()); |
- SkDebugf(" [%d] otherT=", fOtherIndex); |
- DebugDumpDouble(fOtherT); |
+#if DEBUG_WINDING |
SkDebugf(" windSum="); |
- SkPathOpsDebug::WindingPrintf(fWindSum); |
- if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { |
+ SkPathOpsDebug::WindingPrintf(mSpan.fWindSum); |
+#endif |
+ if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) { |
+ SkDebugf(" oppVal=%d", mSpan.fOppValue); |
+#if DEBUG_WINDING |
SkDebugf(" oppSum="); |
- SkPathOpsDebug::WindingPrintf(fOppSum); |
- } |
- SkDebugf(" windValue=%d", fWindValue); |
- if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { |
- SkDebugf(" oppValue=%d", fOppValue); |
+ SkPathOpsDebug::WindingPrintf(mSpan.fOppSum); |
+#endif |
} |
- if (fDone) { |
+ if (mSpan.fDone) { |
SkDebugf(" done"); |
} |
- if (fUnsortableStart) { |
- SkDebugf(" unsortable-start"); |
+ if (unorderable()) { |
+ SkDebugf(" unorderable"); |
} |
- if (fUnsortableEnd) { |
- SkDebugf(" unsortable-end"); |
+ if (small()) { |
+ SkDebugf(" small"); |
} |
- if (fTiny) { |
+ if (mSpan.fTiny) { |
SkDebugf(" tiny"); |
- } else if (fSmall) { |
- SkDebugf(" small"); |
} |
- if (fLoop) { |
- SkDebugf(" loop"); |
+ if (fSegment->operand()) { |
+ SkDebugf(" operand"); |
+ } |
+ if (fStop) { |
+ SkDebugf(" stop"); |
} |
- SkDebugf("\n"); |
} |
+#endif |
-void Dump(const SkTArray<class SkOpAngle, true>& angles) { |
- SkPathOpsDebug::DumpAngles(angles); |
+#if DEBUG_ANGLE |
+void SkOpAngle::debugSameAs(const SkOpAngle* compare) const { |
+ SK_DEBUGBREAK(fSegment == compare->fSegment); |
+ const SkOpSpan& startSpan = fSegment->span(fStart); |
+ const SkOpSpan& oStartSpan = fSegment->span(compare->fStart); |
+ SK_DEBUGBREAK(startSpan.fToAngleIndex == oStartSpan.fToAngleIndex); |
+ SK_DEBUGBREAK(startSpan.fFromAngleIndex == oStartSpan.fFromAngleIndex); |
+ const SkOpSpan& endSpan = fSegment->span(fEnd); |
+ const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd); |
+ SK_DEBUGBREAK(endSpan.fToAngleIndex == oEndSpan.fToAngleIndex); |
+ SK_DEBUGBREAK(endSpan.fFromAngleIndex == oEndSpan.fFromAngleIndex); |
} |
+#endif |
-void Dump(const SkTArray<class SkOpAngle* , true>& angles) { |
- SkPathOpsDebug::DumpAngles(angles); |
+#if DEBUG_VALIDATE |
+void SkOpAngle::debugValidateNext() const { |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = first; |
+ SkTDArray<const SkOpAngle*>(angles); |
+ do { |
+ SK_DEBUGBREAK(next->fSegment->debugContains(next)); |
+ angles.push(next); |
+ next = next->next(); |
+ if (next == first) { |
+ break; |
+ } |
+ SK_DEBUGBREAK(!angles.contains(next)); |
+ if (!next) { |
+ return; |
+ } |
+ } while (true); |
} |
-void Dump(const SkTArray<class SkOpAngle, true>* angles) { |
- SkPathOpsDebug::DumpAngles(*angles); |
+void SkOpAngle::debugValidateLoop() const { |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = first; |
+ SK_DEBUGBREAK(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_DEBUGBREAK(span.fWindValue == 1); |
+// SK_DEBUGBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1); |
+ } |
+ if (segment->oppXor()) { |
+ SK_DEBUGBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1); |
+// SK_DEBUGBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1); |
+ } |
+ next = next->next(); |
+ if (!next) { |
+ return; |
+ } |
+ } while (next != first); |
+ if (unorderable) { |
+ return; |
+ } |
+ SK_DEBUGBREAK(!signSum || fSegment->_xor()); |
+ SK_DEBUGBREAK(!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_DEBUGBREAK(winding != 0); |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
+ lastWinding = winding; |
+ int diffWinding = segment->spanSign(next); |
+ if (!segment->_xor()) { |
+ SK_DEBUGBREAK(diffWinding != 0); |
+ bool sameSign = (winding > 0) == (diffWinding > 0); |
+ winding -= sameSign ? diffWinding : -diffWinding; |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
+ SK_DEBUGBREAK(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_DEBUGBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor()); |
+ if (oppDiffWinding) { |
+ bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0); |
+ oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding; |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
+ SK_DEBUGBREAK(abs(oppWinding) <= abs(lastOppWinding)); |
+ if (!oppSameSign) { |
+ SkTSwap(oppWinding, lastOppWinding); |
+ } |
+ } |
+ } |
+ firstOperand = segment->operand(); |
+ break; |
+ } |
+ SK_DEBUGBREAK(span.fOppSum == SK_MinS32); |
+ next = next->next(); |
+ } while (next != first); |
+ if (winding == SK_MinS32) { |
+ return; |
+ } |
+ SK_DEBUGBREAK(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_DEBUGBREAK(winding != lastWinding); |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
+ } |
+ if (!segment->oppXor()) { |
+ int oppDiffWinding = segment->oppSign(next); |
+ if (oppWinding != SK_MinS32) { |
+ oppWinding -= oppDiffWinding; |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
+ } else { |
+ SK_DEBUGBREAK(oppDiffWinding == 0); |
+ } |
+ } |
+ } else { |
+ if (!segment->oppXor()) { |
+ winding -= segment->oppSign(next); |
+ SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
+ } |
+ if (!segment->_xor()) { |
+ oppWinding -= segment->spanSign(next); |
+ SK_DEBUGBREAK(oppWinding != lastOppWinding); |
+ SK_DEBUGBREAK(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_DEBUGBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor()); |
+ } |
+ } else { |
+ SK_DEBUGBREAK(!firstOperand); |
+ SK_DEBUGBREAK(!segment->operand()); |
+ SK_DEBUGBREAK(!span.fOppValue); |
+ } |
+ next = next->next(); |
+ } while (next != first); |
} |
+#endif |
-void Dump(const SkTArray<class SkOpAngle* , true>* angles) { |
- SkPathOpsDebug::DumpAngles(*angles); |
+#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_DEBUGBREAK 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_DEBUGBREAK(0); |
+} |
#endif |
-#if !FORCE_RELEASE && 0 // enable when building without extended test |
-void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) { |
+#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_DEBUGBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt)); |
+ } |
} |
#endif |
+ |
+#if DEBUG_VALIDATE |
+bool SkOpSegment::debugContains(const SkOpAngle* angle) const { |
+ for (int index = 0; index < fAngles.count(); ++index) { |
+ if (&fAngles[index] == angle) { |
+ return true; |
+ } |
+ } |
+ for (int index = 0; index < fSingletonAngles.count(); ++index) { |
+ if (&fSingletonAngles[index] == angle) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+#endif |
+ |
+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_DEBUGBREAK(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_DEBUGBREAK(&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_DEBUGBREAK(&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\n", span.fWindValue); |
+} |
+#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 |
+ int count = fTs.count(); |
+ SK_DEBUGBREAK(count >= 2); |
+ SK_DEBUGBREAK(fTs[0].fT == 0); |
+ SK_DEBUGBREAK(fTs[count - 1].fT == 1); |
+ int done = 0; |
+ 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_DEBUGBREAK(t <= span.fT); |
+ t = span.fT; |
+ int otherIndex = span.fOtherIndex; |
+ const SkOpSegment* other = span.fOther; |
+ SK_DEBUGBREAK(other != this || fVerb == SkPath::kCubic_Verb); |
+ const SkOpSpan& otherSpan = other->fTs[otherIndex]; |
+ SK_DEBUGBREAK(otherSpan.fPt == span.fPt); |
+ SK_DEBUGBREAK(otherSpan.fOtherT == t); |
+ SK_DEBUGBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]); |
+ done += span.fDone; |
+ if (last) { |
+ bool tsEqual = last->fT == span.fT; |
+ bool tsPreciselyEqual = precisely_equal(last->fT, span.fT); |
+ SK_DEBUGBREAK(!tsEqual || tsPreciselyEqual); |
+ bool pointsEqual = last->fPt == span.fPt; |
+ bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt); |
+#if 0 // bufferOverflow test triggers this |
+ SK_DEBUGBREAK(!tsPreciselyEqual || pointsNearlyEqual); |
+#endif |
+// SK_DEBUGBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound); |
+ SK_DEBUGBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop); |
+ SK_DEBUGBREAK(!last->fTiny || pointsEqual); |
+ SK_DEBUGBREAK(!last->fTiny || last->fDone); |
+ SK_DEBUGBREAK(!last->fSmall || pointsNearlyEqual); |
+ SK_DEBUGBREAK(!last->fSmall || last->fDone); |
+// SK_DEBUGBREAK(!last->fSmall || last->fTiny); |
+// SK_DEBUGBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone); |
+ if (last->fTiny) { |
+ tinyTFound |= !tsPreciselyEqual; |
+ } else { |
+ tinyTFound = false; |
+ } |
+ } |
+ last = &span; |
+ hasLoop |= last->fLoop; |
+ } |
+ SK_DEBUGBREAK(done == fDoneSpans); |
+ if (fAngles.count() ) { |
+ fAngles.begin()->debugValidateLoop(); |
+ } |
+#endif |
+} |