Index: tests/PathOpsDebug.cpp |
diff --git a/tests/PathOpsDebug.cpp b/tests/PathOpsDebug.cpp |
new file mode 100755 |
index 0000000000000000000000000000000000000000..5c3563ed0fef325b4ff7b6e4a3ffba72f42db5f4 |
--- /dev/null |
+++ b/tests/PathOpsDebug.cpp |
@@ -0,0 +1,568 @@ |
+#include "SkOpContour.h" |
+#include "SkIntersectionHelper.h" |
+#include "SkOpSegment.h" |
+ |
+inline void DebugDumpDouble(double x) { |
+ if (x == floor(x)) { |
+ SkDebugf("%.0f", x); |
+ } else { |
+ SkDebugf("%1.19g", x); |
+ } |
+} |
+ |
+inline void DebugDumpFloat(float x) { |
+ if (x == floorf(x)) { |
+ SkDebugf("%.0f", x); |
+ } else { |
+ SkDebugf("%1.9gf", x); |
+ } |
+} |
+ |
+// if not defined by PathOpsDebug.cpp ... |
+#if !defined SK_DEBUG && FORCE_RELEASE |
+bool SkPathOpsDebug::ValidWind(int wind) { |
+ return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; |
+} |
+ |
+void SkPathOpsDebug::WindingPrintf(int wind) { |
+ if (wind == SK_MinS32) { |
+ SkDebugf("?"); |
+ } else { |
+ SkDebugf("%d", wind); |
+ } |
+} |
+#endif |
+ |
+void SkOpAngle::dump() const { |
+#if DEBUG_SORT |
+ debugOne(false); |
+#endif |
+ SkDebugf("\n"); |
+} |
+ |
+void SkOpAngle::dumpFromTo(const SkOpSegment* segment, int from, int to) const { |
+#if DEBUG_SORT && DEBUG_ANGLE |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = this; |
+ const char* indent = ""; |
+ do { |
+ SkDebugf("%s", indent); |
+ next->debugOne(false); |
+ if (segment == next->fSegment) { |
+ if (fNext && from == fNext->debugID()) { |
+ SkDebugf(" << from"); |
+ } |
+ if (fNext && to == fNext->debugID()) { |
+ SkDebugf(" << to"); |
+ } |
+ } |
+ SkDebugf("\n"); |
+ indent = " "; |
+ next = next->fNext; |
+ } while (next && next != first); |
+#endif |
+} |
+ |
+void SkOpAngle::dumpLoop() const { |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = this; |
+ do { |
+ next->dump(); |
+ next = next->fNext; |
+ } while (next && next != first); |
+} |
+ |
+void SkOpAngle::dumpPartials() const { |
+ const SkOpAngle* first = this; |
+ const SkOpAngle* next = this; |
+ do { |
+ next->fCurvePart.dumpNumber(); |
+ next = next->fNext; |
+ } while (next && next != first); |
+} |
+ |
+void SkOpContour::dump() const { |
+ int segmentCount = fSegments.count(); |
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID()); |
+ for (int test = 0; test < segmentCount; ++test) { |
+ SkDebugf(" [%d] ((SkOpSegment*) 0x%p) [%d]\n", test, &fSegments[test], |
+ fSegments[test].debugID()); |
+ } |
+} |
+ |
+void SkOpContour::dumpAngles() const { |
+ int segmentCount = fSegments.count(); |
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID()); |
+ for (int test = 0; test < segmentCount; ++test) { |
+ SkDebugf(" [%d] ", test); |
+ fSegments[test].dumpAngles(); |
+ } |
+} |
+ |
+void SkOpContour::dumpPts() const { |
+ int segmentCount = fSegments.count(); |
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID()); |
+ for (int test = 0; test < segmentCount; ++test) { |
+ SkDebugf(" [%d] ", test); |
+ fSegments[test].dumpPts(); |
+ } |
+} |
+ |
+void SkOpContour::dumpSpans() const { |
+ int segmentCount = fSegments.count(); |
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID()); |
+ for (int test = 0; test < segmentCount; ++test) { |
+ SkDebugf(" [%d] ", test); |
+ fSegments[test].dumpSpans(); |
+ } |
+} |
+ |
+void SkDCubic::dump() const { |
+ SkDebugf("{{"); |
+ int index = 0; |
+ do { |
+ fPts[index].dump(); |
+ SkDebugf(", "); |
+ } while (++index < 3); |
+ fPts[index].dump(); |
+ SkDebugf("}}\n"); |
+} |
+ |
+void SkDCubic::dumpNumber() const { |
+ SkDebugf("{{"); |
+ int index = 0; |
+ bool dumpedOne = false; |
+ do { |
+ if (!(fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY)) { |
+ continue; |
+ } |
+ if (dumpedOne) { |
+ SkDebugf(", "); |
+ } |
+ fPts[index].dump(); |
+ dumpedOne = true; |
+ } while (++index < 3); |
+ if (fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY) { |
+ if (dumpedOne) { |
+ SkDebugf(", "); |
+ } |
+ fPts[index].dump(); |
+ } |
+ SkDebugf("}}\n"); |
+} |
+ |
+void SkDLine::dump() const { |
+ SkDebugf("{{"); |
+ fPts[0].dump(); |
+ SkDebugf(", "); |
+ fPts[1].dump(); |
+ SkDebugf("}}\n"); |
+} |
+ |
+void SkDPoint::dump() const { |
+ SkDebugf("{"); |
+ DebugDumpDouble(fX); |
+ SkDebugf(", "); |
+ DebugDumpDouble(fY); |
+ SkDebugf("}"); |
+} |
+ |
+void SkDPoint::Dump(const SkPoint& pt) { |
+ SkDebugf("{"); |
+ DebugDumpFloat(pt.fX); |
+ SkDebugf(", "); |
+ DebugDumpFloat(pt.fY); |
+ SkDebugf("}"); |
+} |
+ |
+ |
+void SkDQuad::dumpComma(const char* comma) const { |
+ SkDebugf("{{"); |
+ int index = 0; |
+ do { |
+ fPts[index].dump(); |
+ SkDebugf(", "); |
+ } while (++index < 2); |
+ fPts[index].dump(); |
+ SkDebugf("}}%s\n", comma ? comma : ""); |
+} |
+ |
+void SkDQuad::dump() const { |
+ dumpComma(""); |
+} |
+ |
+void SkIntersectionHelper::dump() const { |
+ SkDPoint::Dump(pts()[0]); |
+ SkDPoint::Dump(pts()[1]); |
+ if (verb() >= SkPath::kQuad_Verb) { |
+ SkDPoint::Dump(pts()[2]); |
+ } |
+ if (verb() >= SkPath::kCubic_Verb) { |
+ SkDPoint::Dump(pts()[3]); |
+ } |
+} |
+ |
+void SkOpSegment::dumpAngles() const { |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID()); |
+ int fromIndex = -1, toIndex = -1; |
+ for (int index = 0; index < count(); ++index) { |
+ int fIndex = fTs[index].fFromAngleIndex; |
+ int tIndex = fTs[index].fToAngleIndex; |
+ if (fromIndex == fIndex && tIndex == toIndex) { |
+ continue; |
+ } |
+ if (fIndex >= 0) { |
+ SkDebugf(" [%d] from=%d ", index, fIndex); |
+ const SkOpAngle& angle = this->angle(fIndex); |
+ angle.dumpFromTo(this, fIndex, tIndex); |
+ } |
+ if (tIndex >= 0) { |
+ SkDebugf(" [%d] to=%d ", index, tIndex); |
+ const SkOpAngle& angle = this->angle(tIndex); |
+ angle.dumpFromTo(this, fIndex, tIndex); |
+ } |
+ fromIndex = fIndex; |
+ toIndex = tIndex; |
+ } |
+} |
+ |
+void SkOpSegment::dumpContour(int firstID, int lastID) const { |
+ if (debugID() < 0) { |
+ return; |
+ } |
+ const SkOpSegment* test = this - (debugID() - 1); |
+ test += (firstID - 1); |
+ const SkOpSegment* last = test + (lastID - firstID); |
+ while (test <= last) { |
+ test->dumpSpans(); |
+ ++test; |
+ } |
+} |
+ |
+void SkOpSegment::dumpPts() const { |
+ int last = SkPathOpsVerbToPoints(fVerb); |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID()); |
+ int index = 0; |
+ do { |
+ SkDPoint::Dump(fPts[index]); |
+ SkDebugf(", "); |
+ } while (++index < last); |
+ SkDPoint::Dump(fPts[index]); |
+ SkDebugf("}}\n"); |
+} |
+ |
+void SkOpSegment::dumpDPts() const { |
+ int count = SkPathOpsVerbToPoints(fVerb); |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID()); |
+ int index = 0; |
+ do { |
+ SkDPoint dPt = {fPts[index].fX, fPts[index].fY}; |
+ dPt.dump(); |
+ if (index != count) { |
+ SkDebugf(", "); |
+ } |
+ } while (++index <= count); |
+ SkDebugf("}}\n"); |
+} |
+ |
+void SkOpSegment::dumpSpans() const { |
+ int count = this->count(); |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID()); |
+ for (int index = 0; index < count; ++index) { |
+ const SkOpSpan& span = this->span(index); |
+ SkDebugf(" [%d] ", index); |
+ span.dumpOne(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) { |
+ int count = angles.count(); |
+ for (int index = 0; index < count; ++index) { |
+ angles[index].dump(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) { |
+ int count = angles.count(); |
+ for (int index = 0; index < count; ++index) { |
+ angles[index]->dump(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour, true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index].dump(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour* , true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index]->dump(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour, true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index].dumpAngles(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour* , true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index]->dumpAngles(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour, true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index].dumpPts(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour* , true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index]->dumpPts(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour, true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index].dumpSpans(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour* , true>& contours) { |
+ int count = contours.count(); |
+ for (int index = 0; index < count; ++index) { |
+ contours[index]->dumpSpans(); |
+ } |
+} |
+ |
+void SkPathOpsDebug::DumpSpans(const SkTDArray<SkOpSpan *>& spans) { |
+ int count = spans.count(); |
+ for (int index = 0; index < count; ++index) { |
+ const SkOpSpan* span = spans[index]; |
+ const SkOpSpan& oSpan = span->fOther->span(span->fOtherIndex); |
+ const SkOpSegment* segment = oSpan.fOther; |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] ", segment, segment->debugID()); |
+ SkDebugf("spanIndex:%d ", oSpan.fOtherIndex); |
+ span->dumpOne(); |
+ } |
+} |
+ |
+// this does not require that other T index is initialized or correct |
+const SkOpSegment* SkOpSpan::debugToSegment(ptrdiff_t* spanIndex) const { |
+ if (!fOther) { |
+ return NULL; |
+ } |
+ int oppCount = fOther->count(); |
+ for (int index = 0; index < oppCount; ++index) { |
+ const SkOpSpan& otherSpan = fOther->span(index); |
+ double otherTestT = otherSpan.fT; |
+ if (otherTestT < fOtherT) { |
+ continue; |
+ } |
+ SkASSERT(otherTestT == fOtherT); |
+ const SkOpSegment* candidate = otherSpan.fOther; |
+ const SkOpSpan* first = candidate->spans().begin(); |
+ const SkOpSpan* last = candidate->spans().end() - 1; |
+ if (first <= this && this <= last) { |
+ if (spanIndex) { |
+ *spanIndex = this - first; |
+ } |
+ return candidate; |
+ } |
+ } |
+ SkASSERT(0); |
+ return NULL; |
+} |
+ |
+void SkOpSpan::dumpOne() const { |
+ SkDebugf("t="); |
+ DebugDumpDouble(fT); |
+ SkDebugf(" pt="); |
+ SkDPoint::Dump(fPt); |
+ if (fOther) { |
+ SkDebugf(" other.fID=%d", fOther->debugID()); |
+ SkDebugf(" [%d] otherT=", fOtherIndex); |
+ DebugDumpDouble(fOtherT); |
+ } else { |
+ SkDebugf(" other.fID=? [?] otherT=?"); |
+ } |
+#if DEBUG_WINDING |
+ SkDebugf(" windSum="); |
+ SkPathOpsDebug::WindingPrintf(fWindSum); |
+#endif |
+ if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { |
+#if DEBUG_WINDING |
+ SkDebugf(" oppSum="); |
+ SkPathOpsDebug::WindingPrintf(fOppSum); |
+#endif |
+ } |
+ SkDebugf(" windValue=%d", fWindValue); |
+ if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { |
+ SkDebugf(" oppValue=%d", fOppValue); |
+ } |
+ SkDebugf(" from=%d", fFromAngleIndex); |
+ SkDebugf(" to=%d", fToAngleIndex); |
+ if (fDone) { |
+ SkDebugf(" done"); |
+ } |
+ if (fUnsortableStart) { |
+ SkDebugf(" unsortable-start"); |
+ } |
+ if (fUnsortableEnd) { |
+ SkDebugf(" unsortable-end"); |
+ } |
+ if (fTiny) { |
+ SkDebugf(" tiny"); |
+ } |
+ if (fSmall) { |
+ SkDebugf(" small"); |
+ } |
+ if (fLoop) { |
+ SkDebugf(" loop"); |
+ } |
+ SkDebugf("\n"); |
+} |
+ |
+void SkOpSpan::dump() const { |
+ ptrdiff_t spanIndex; |
+ const SkOpSegment* segment = debugToSegment(&spanIndex); |
+ if (segment) { |
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", segment, segment->debugID()); |
+ SkDebugf(" [%d] ", spanIndex); |
+ } else { |
+ SkDebugf("((SkOpSegment*) ?) [?]\n"); |
+ SkDebugf(" [?] "); |
+ } |
+ dumpOne(); |
+} |
+ |
+void Dump(const SkTArray<class SkOpAngle, true>& angles) { |
+ SkPathOpsDebug::DumpAngles(angles); |
+} |
+ |
+void Dump(const SkTArray<class SkOpAngle* , true>& angles) { |
+ SkPathOpsDebug::DumpAngles(angles); |
+} |
+ |
+void Dump(const SkTArray<class SkOpAngle, true>* angles) { |
+ SkPathOpsDebug::DumpAngles(*angles); |
+} |
+ |
+void Dump(const SkTArray<class SkOpAngle* , true>* angles) { |
+ SkPathOpsDebug::DumpAngles(*angles); |
+} |
+ |
+void Dump(const SkTArray<class SkOpContour, true>& contours) { |
+ SkPathOpsDebug::DumpContours(contours); |
+} |
+ |
+void Dump(const SkTArray<class SkOpContour* , true>& contours) { |
+ SkPathOpsDebug::DumpContours(contours); |
+} |
+ |
+void Dump(const SkTArray<class SkOpContour, true>* contours) { |
+ SkPathOpsDebug::DumpContours(*contours); |
+} |
+ |
+void Dump(const SkTArray<class SkOpContour* , true>* contours) { |
+ SkPathOpsDebug::DumpContours(*contours); |
+} |
+ |
+void Dump(const SkTDArray<SkOpSpan *>& chaseArray) { |
+ SkPathOpsDebug::DumpSpans(chaseArray); |
+} |
+ |
+void Dump(const SkTDArray<SkOpSpan *>* chaseArray) { |
+ SkPathOpsDebug::DumpSpans(*chaseArray); |
+} |
+ |
+void DumpAngles(const SkTArray<class SkOpContour, true>& contours) { |
+ SkPathOpsDebug::DumpContourAngles(contours); |
+} |
+ |
+void DumpAngles(const SkTArray<class SkOpContour* , true>& contours) { |
+ SkPathOpsDebug::DumpContourAngles(contours); |
+} |
+ |
+void DumpAngles(const SkTArray<class SkOpContour, true>* contours) { |
+ SkPathOpsDebug::DumpContourAngles(*contours); |
+} |
+ |
+void DumpAngles(const SkTArray<class SkOpContour* , true>* contours) { |
+ SkPathOpsDebug::DumpContourAngles(*contours); |
+} |
+ |
+void DumpSpans(const SkTArray<class SkOpContour, true>& contours) { |
+ SkPathOpsDebug::DumpContourSpans(contours); |
+} |
+ |
+void DumpSpans(const SkTArray<class SkOpContour* , true>& contours) { |
+ SkPathOpsDebug::DumpContourSpans(contours); |
+} |
+ |
+void DumpSpans(const SkTArray<class SkOpContour, true>* contours) { |
+ SkPathOpsDebug::DumpContourSpans(*contours); |
+} |
+ |
+void DumpSpans(const SkTArray<class SkOpContour* , true>* contours) { |
+ SkPathOpsDebug::DumpContourSpans(*contours); |
+} |
+ |
+void DumpPts(const SkTArray<class SkOpContour, true>& contours) { |
+ SkPathOpsDebug::DumpContourPts(contours); |
+} |
+ |
+void DumpPts(const SkTArray<class SkOpContour* , true>& contours) { |
+ SkPathOpsDebug::DumpContourPts(contours); |
+} |
+ |
+void DumpPts(const SkTArray<class SkOpContour, true>* contours) { |
+ SkPathOpsDebug::DumpContourPts(*contours); |
+} |
+ |
+void DumpPts(const SkTArray<class SkOpContour* , true>* contours) { |
+ SkPathOpsDebug::DumpContourPts(*contours); |
+} |
+ |
+static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) { |
+ SkDebugf("<div id=\"quad%d\">\n", testNo); |
+ quad1.dumpComma(","); |
+ quad2.dump(); |
+ SkDebugf("</div>\n\n"); |
+} |
+ |
+static void dumpTestTrailer() { |
+ SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n"); |
+ SkDebugf(" var testDivs = [\n"); |
+} |
+ |
+static void dumpTestList(int testNo, double min) { |
+ SkDebugf(" quad%d,", testNo); |
+ if (min > 0) { |
+ SkDebugf(" // %1.9g", min); |
+ } |
+ SkDebugf("\n"); |
+} |
+ |
+void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) { |
+ SkDebugf("\n"); |
+ dumpTestCase(quad1, quad2, testNo); |
+ dumpTestTrailer(); |
+ dumpTestList(testNo, 0); |
+ SkDebugf("\n"); |
+} |
+ |
+void DumpT(const SkDQuad& quad, double t) { |
+ SkDLine line = {{quad.ptAtT(t), quad[0]}}; |
+ line.dump(); |
+} |