#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 { dumpOne(true); SkDebugf("\n"); } void SkOpAngle::dumpOne(bool functionHeader) const { // fSegment->debugValidate(); const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd)); if (functionHeader) { SkDebugf("%s ", __FUNCTION__); } SkDebugf("[%d", fSegment->debugID()); SkDebugf("/%d", debugID()); SkDebugf("] next="); if (fNext) { SkDebugf("%d", fNext->fSegment->debugID()); SkDebugf("/%d", fNext->debugID()); } 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); SkDebugf(" windSum="); SkPathOpsDebug::WindingPrintf(mSpan.fWindSum); if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) { SkDebugf(" oppVal=%d", mSpan.fOppValue); SkDebugf(" oppSum="); SkPathOpsDebug::WindingPrintf(mSpan.fOppSum); } if (mSpan.fDone) { SkDebugf(" done"); } if (unorderable()) { SkDebugf(" unorderable"); } if (small()) { SkDebugf(" small"); } if (mSpan.fTiny) { SkDebugf(" tiny"); } if (fSegment->operand()) { SkDebugf(" operand"); } if (fStop) { SkDebugf(" stop"); } } void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const { const SkOpAngle* first = this; const SkOpAngle* next = this; const char* indent = ""; do { SkDebugf("%s", indent); next->dumpOne(false); if (segment == next->fSegment) { if (this == fNext) { SkDebugf(" << from"); } if (to == fNext) { SkDebugf(" << to"); } } SkDebugf("\n"); indent = " "; next = next->fNext; } while (next && next != first); } void SkOpAngle::dumpLoop() const { const SkOpAngle* first = this; const SkOpAngle* next = this; do { next->dumpOne(false); SkDebugf("\n"); 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 SkOpAngleSet::dump() const { // FIXME: unimplemented /* This requires access to the internal SkChunkAlloc data Defer implementing this until it is needed for debugging */ SkASSERT(0); } 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::dumpCoincidence(const SkCoincidence& coin) const { int thisIndex = coin.fSegments[0]; const SkOpSegment& s1 = fSegments[thisIndex]; int otherIndex = coin.fSegments[1]; const SkOpSegment& s2 = coin.fOther->fSegments[otherIndex]; SkDebugf("((SkOpSegment*) 0x%p) [%d] ((SkOpSegment*) 0x%p) [%d]\n", &s1, s1.debugID(), &s2, s2.debugID()); for (int index = 0; index < 2; ++index) { SkDebugf(" {%1.9gf, %1.9gf}", coin.fPts[0][index].fX, coin.fPts[0][index].fY); if (coin.fNearly[index]) { SkDebugf(" {%1.9gf, %1.9gf}", coin.fPts[1][index].fX, coin.fPts[1][index].fY); } SkDebugf(" seg1t=%1.9g seg2t=%1.9g\n", coin.fTs[0][index], coin.fTs[1][index]); } } void SkOpContour::dumpCoincidences() const { int count = fCoincidences.count(); if (count > 0) { SkDebugf("fCoincidences count=%d\n", count); for (int test = 0; test < count; ++test) { dumpCoincidence(fCoincidences[test]); } } count = fPartialCoincidences.count(); if (count == 0) { return; } SkDebugf("fPartialCoincidences count=%d\n", count); for (int test = 0; test < count; ++test) { dumpCoincidence(fPartialCoincidences[test]); } } void SkOpContour::dumpPt(int index) const { int segmentCount = fSegments.count(); for (int test = 0; test < segmentCount; ++test) { const SkOpSegment& segment = fSegments[test]; if (segment.debugID() == index) { fSegments[test].dumpPts(); } } } 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::dumpSpan(int index) const { int segmentCount = fSegments.count(); for (int test = 0; test < segmentCount; ++test) { const SkOpSegment& segment = fSegments[test]; if (segment.debugID() == index) { fSegments[test].dumpSpans(); } } } 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]); } } const SkTDArray<SkOpSpan>& SkOpSegment::debugSpans() const { return fTs; } void SkOpSegment::dumpAngles() const { SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID()); const SkOpAngle* fromAngle = NULL; const SkOpAngle* toAngle = NULL; for (int index = 0; index < count(); ++index) { const SkOpAngle* fAngle = fTs[index].fFromAngle; const SkOpAngle* tAngle = fTs[index].fToAngle; if (fromAngle == fAngle && toAngle == tAngle) { continue; } if (fAngle) { SkDebugf(" [%d] from=%d ", index, fAngle->debugID()); fAngle->dumpTo(this, tAngle); } if (tAngle) { SkDebugf(" [%d] to=%d ", index, tAngle->debugID()); tAngle->dumpTo(this, fAngle); } fromAngle = fAngle; toAngle = tAngle; } } 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::DumpCoincidence(const SkTArray<SkOpContour, true>& contours) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index].dumpCoincidences(); } } void SkPathOpsDebug::DumpCoincidence(const SkTArray<SkOpContour* , true>& contours) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index]->dumpCoincidences(); } } 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::DumpContourPt(const SkTArray<SkOpContour, true>& contours, int segmentID) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index].dumpPt(segmentID); } } void SkPathOpsDebug::DumpContourPt(const SkTArray<SkOpContour* , true>& contours, int segmentID) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index]->dumpPt(segmentID); } } 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::DumpContourSpan(const SkTArray<SkOpContour, true>& contours, int segmentID) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index].dumpSpan(segmentID); } } void SkPathOpsDebug::DumpContourSpan(const SkTArray<SkOpContour* , true>& contours, int segmentID) { int count = contours.count(); for (int index = 0; index < count; ++index) { contours[index]->dumpSpan(segmentID); } } 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->debugSpans().begin(); const SkOpSpan* last = candidate->debugSpans().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 (fWindSum != SK_MinS32) { SkDebugf(" windSum=%d", fWindSum); } if (fOppSum != SK_MinS32 && (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0)) { SkDebugf(" oppSum=%d", fOppSum); } SkDebugf(" windValue=%d", fWindValue); if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { SkDebugf(" oppValue=%d", fOppValue); } if (fFromAngle && fFromAngle->debugID()) { SkDebugf(" from=%d", fFromAngle->debugID()); } if (fToAngle && fToAngle->debugID()) { SkDebugf(" to=%d", fToAngle->debugID()); } if (fChased) { SkDebugf(" chased"); } if (fCoincident) { SkDebugf(" coincident"); } if (fDone) { SkDebugf(" done"); } if (fLoop) { SkDebugf(" loop"); } if (fMultiple) { SkDebugf(" multiple"); } if (fNear) { SkDebugf(" near"); } if (fSmall) { SkDebugf(" small"); } if (fTiny) { SkDebugf(" tiny"); } 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 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 *>& chase) { SkPathOpsDebug::DumpSpans(chase); } void Dump(const SkTDArray<SkOpSpan *>* chase) { SkPathOpsDebug::DumpSpans(*chase); } 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 DumpCoin(const SkTArray<class SkOpContour, true>& contours) { SkPathOpsDebug::DumpCoincidence(contours); } void DumpCoin(const SkTArray<class SkOpContour* , true>& contours) { SkPathOpsDebug::DumpCoincidence(contours); } void DumpCoin(const SkTArray<class SkOpContour, true>* contours) { SkPathOpsDebug::DumpCoincidence(*contours); } void DumpCoin(const SkTArray<class SkOpContour* , true>* contours) { SkPathOpsDebug::DumpCoincidence(*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 DumpSpan(const SkTArray<class SkOpContour, true>& contours, int segmentID) { SkPathOpsDebug::DumpContourSpan(contours, segmentID); } void DumpSpan(const SkTArray<class SkOpContour* , true>& contours, int segmentID) { SkPathOpsDebug::DumpContourSpan(contours, segmentID); } void DumpSpan(const SkTArray<class SkOpContour, true>* contours, int segmentID) { SkPathOpsDebug::DumpContourSpan(*contours, segmentID); } void DumpSpan(const SkTArray<class SkOpContour* , true>* contours, int segmentID) { SkPathOpsDebug::DumpContourSpan(*contours, segmentID); } 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); } void DumpPt(const SkTArray<class SkOpContour, true>& contours, int segmentID) { SkPathOpsDebug::DumpContourPt(contours, segmentID); } void DumpPt(const SkTArray<class SkOpContour* , true>& contours, int segmentID) { SkPathOpsDebug::DumpContourPt(contours, segmentID); } void DumpPt(const SkTArray<class SkOpContour, true>* contours, int segmentID) { SkPathOpsDebug::DumpContourPt(*contours, segmentID); } void DumpPt(const SkTArray<class SkOpContour* , true>* contours, int segmentID) { SkPathOpsDebug::DumpContourPt(*contours, segmentID); } 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(); }