e4097e3a0b
This fixes the last bug discovered by iterating through the 800K skp corpus representing the top 1M websites. For every clip on the stack, the paths are replaced with the pathop intersection. The resulting draw is compared with the original draw for pixel errors. At least two prominent bugs remain. In one, the winding value is confused by a cubic with an inflection. In the other, a quad/cubic pair, nearly coincident, fails to find an intersection. These minor changes include ignoring very tiny self-intersections of cubics, and processing degenerate edges that don't connect to anything else. R=reed@android.com TBR=reed Author: caryclark@google.com Review URL: https://codereview.chromium.org/340103002
744 lines
21 KiB
C++
Executable File
744 lines
21 KiB
C++
Executable File
#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();
|
|
}
|