| 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();
|
| +}
|
|
|