blob: af60318532633d901304c0a91430eeb1c77a4e30 [file] [log] [blame]
#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();
}