|  | #include "SkOpContour.h" | 
|  | #include "SkIntersectionHelper.h" | 
|  | #include "SkOpSegment.h" | 
|  | #include "SkString.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 DEBUG_SHOW_TEST_NAME | 
|  |  | 
|  | static void output_scalar(SkScalar num) { | 
|  | if (num == (int) num) { | 
|  | SkDebugf("%d", (int) num); | 
|  | } else { | 
|  | SkString str; | 
|  | str.printf("%1.9g", num); | 
|  | int width = (int) str.size(); | 
|  | const char* cStr = str.c_str(); | 
|  | while (cStr[width - 1] == '0') { | 
|  | --width; | 
|  | } | 
|  | str.resize(width); | 
|  | SkDebugf("%sf", str.c_str()); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void output_points(const SkPoint* pts, int count) { | 
|  | for (int index = 0; index < count; ++index) { | 
|  | output_scalar(pts[index].fX); | 
|  | SkDebugf(", "); | 
|  | output_scalar(pts[index].fY); | 
|  | if (index + 1 < count) { | 
|  | SkDebugf(", "); | 
|  | } | 
|  | } | 
|  | SkDebugf(");\n"); | 
|  | } | 
|  |  | 
|  | static void showPathContours(SkPath::RawIter& iter, const char* pathName) { | 
|  | uint8_t verb; | 
|  | SkPoint pts[4]; | 
|  | while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 
|  | switch (verb) { | 
|  | case SkPath::kMove_Verb: | 
|  | SkDebugf("    %s.moveTo(", pathName); | 
|  | output_points(&pts[0], 1); | 
|  | continue; | 
|  | case SkPath::kLine_Verb: | 
|  | SkDebugf("    %s.lineTo(", pathName); | 
|  | output_points(&pts[1], 1); | 
|  | break; | 
|  | case SkPath::kQuad_Verb: | 
|  | SkDebugf("    %s.quadTo(", pathName); | 
|  | output_points(&pts[1], 2); | 
|  | break; | 
|  | case SkPath::kCubic_Verb: | 
|  | SkDebugf("    %s.cubicTo(", pathName); | 
|  | output_points(&pts[1], 3); | 
|  | break; | 
|  | case SkPath::kClose_Verb: | 
|  | SkDebugf("    %s.close();\n", pathName); | 
|  | break; | 
|  | default: | 
|  | SkDEBUGFAIL("bad verb"); | 
|  | return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static const char* gFillTypeStr[] = { | 
|  | "kWinding_FillType", | 
|  | "kEvenOdd_FillType", | 
|  | "kInverseWinding_FillType", | 
|  | "kInverseEvenOdd_FillType" | 
|  | }; | 
|  |  | 
|  | void SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { | 
|  | SkPath::RawIter iter(path); | 
|  | #define SUPPORT_RECT_CONTOUR_DETECTION 0 | 
|  | #if SUPPORT_RECT_CONTOUR_DETECTION | 
|  | int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0; | 
|  | if (rectCount > 0) { | 
|  | SkTDArray<SkRect> rects; | 
|  | SkTDArray<SkPath::Direction> directions; | 
|  | rects.setCount(rectCount); | 
|  | directions.setCount(rectCount); | 
|  | path.rectContours(rects.begin(), directions.begin()); | 
|  | for (int contour = 0; contour < rectCount; ++contour) { | 
|  | const SkRect& rect = rects[contour]; | 
|  | SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, | 
|  | rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction | 
|  | ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); | 
|  | } | 
|  | return; | 
|  | } | 
|  | #endif | 
|  | SkPath::FillType fillType = path.getFillType(); | 
|  | SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); | 
|  | if (includeDeclaration) { | 
|  | SkDebugf("    SkPath %s;\n", name); | 
|  | } | 
|  | SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 
|  | iter.setPath(path); | 
|  | showPathContours(iter, name); | 
|  | } | 
|  |  | 
|  | static void show_function_header(const char* functionName) { | 
|  | SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); | 
|  | if (strcmp("skphealth_com76", functionName) == 0) { | 
|  | SkDebugf("found it\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static const char* gOpStrs[] = { | 
|  | "kDifference_PathOp", | 
|  | "kIntersect_PathOp", | 
|  | "kUnion_PathOp", | 
|  | "kXor_PathOp", | 
|  | "kReverseDifference_PathOp", | 
|  | }; | 
|  |  | 
|  | static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { | 
|  | SkDebugf("    testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); | 
|  | SkDebugf("}\n"); | 
|  | } | 
|  |  | 
|  | SK_DECLARE_STATIC_MUTEX(gTestMutex); | 
|  |  | 
|  | void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, | 
|  | const char* testName) { | 
|  | SkAutoMutexAcquire ac(gTestMutex); | 
|  | show_function_header(testName); | 
|  | ShowOnePath(a, "path", true); | 
|  | ShowOnePath(b, "pathB", true); | 
|  | show_op(shapeOp, "path", "pathB"); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | // 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(); | 
|  | } |