Home | History | Annotate | Download | only in tests
      1 #include "SkOpContour.h"
      2 #include "SkIntersectionHelper.h"
      3 #include "SkOpSegment.h"
      4 #include "SkString.h"
      5 
      6 inline void DebugDumpDouble(double x) {
      7     if (x == floor(x)) {
      8         SkDebugf("%.0f", x);
      9     } else {
     10         SkDebugf("%1.19g", x);
     11     }
     12 }
     13 
     14 inline void DebugDumpFloat(float x) {
     15     if (x == floorf(x)) {
     16         SkDebugf("%.0f", x);
     17     } else {
     18         SkDebugf("%1.9gf", x);
     19     }
     20 }
     21 
     22 
     23 #if DEBUG_SHOW_TEST_NAME
     24 
     25 static void output_scalar(SkScalar num) {
     26     if (num == (int) num) {
     27         SkDebugf("%d", (int) num);
     28     } else {
     29         SkString str;
     30         str.printf("%1.9g", num);
     31         int width = (int) str.size();
     32         const char* cStr = str.c_str();
     33         while (cStr[width - 1] == '0') {
     34             --width;
     35         }
     36         str.resize(width);
     37         SkDebugf("%sf", str.c_str());
     38     }
     39 }
     40 
     41 static void output_points(const SkPoint* pts, int count) {
     42     for (int index = 0; index < count; ++index) {
     43         output_scalar(pts[index].fX);
     44         SkDebugf(", ");
     45         output_scalar(pts[index].fY);
     46         if (index + 1 < count) {
     47             SkDebugf(", ");
     48         }
     49     }
     50     SkDebugf(");\n");
     51 }
     52 
     53 static void showPathContours(SkPath::RawIter& iter, const char* pathName) {
     54     uint8_t verb;
     55     SkPoint pts[4];
     56     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
     57         switch (verb) {
     58             case SkPath::kMove_Verb:
     59                 SkDebugf("    %s.moveTo(", pathName);
     60                 output_points(&pts[0], 1);
     61                 continue;
     62             case SkPath::kLine_Verb:
     63                 SkDebugf("    %s.lineTo(", pathName);
     64                 output_points(&pts[1], 1);
     65                 break;
     66             case SkPath::kQuad_Verb:
     67                 SkDebugf("    %s.quadTo(", pathName);
     68                 output_points(&pts[1], 2);
     69                 break;
     70             case SkPath::kCubic_Verb:
     71                 SkDebugf("    %s.cubicTo(", pathName);
     72                 output_points(&pts[1], 3);
     73                 break;
     74             case SkPath::kClose_Verb:
     75                 SkDebugf("    %s.close();\n", pathName);
     76                 break;
     77             default:
     78                 SkDEBUGFAIL("bad verb");
     79                 return;
     80         }
     81     }
     82 }
     83 
     84 static const char* gFillTypeStr[] = {
     85     "kWinding_FillType",
     86     "kEvenOdd_FillType",
     87     "kInverseWinding_FillType",
     88     "kInverseEvenOdd_FillType"
     89 };
     90 
     91 void SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) {
     92     SkPath::RawIter iter(path);
     93 #define SUPPORT_RECT_CONTOUR_DETECTION 0
     94 #if SUPPORT_RECT_CONTOUR_DETECTION
     95     int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
     96     if (rectCount > 0) {
     97         SkTDArray<SkRect> rects;
     98         SkTDArray<SkPath::Direction> directions;
     99         rects.setCount(rectCount);
    100         directions.setCount(rectCount);
    101         path.rectContours(rects.begin(), directions.begin());
    102         for (int contour = 0; contour < rectCount; ++contour) {
    103             const SkRect& rect = rects[contour];
    104             SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
    105                     rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
    106                     ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
    107         }
    108         return;
    109     }
    110 #endif
    111     SkPath::FillType fillType = path.getFillType();
    112     SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType);
    113     if (includeDeclaration) {
    114         SkDebugf("    SkPath %s;\n", name);
    115     }
    116     SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]);
    117     iter.setPath(path);
    118     showPathContours(iter, name);
    119 }
    120 
    121 static void show_function_header(const char* functionName) {
    122     SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName);
    123     if (strcmp("skphealth_com76", functionName) == 0) {
    124         SkDebugf("found it\n");
    125     }
    126 }
    127 
    128 static const char* gOpStrs[] = {
    129     "kDifference_PathOp",
    130     "kIntersect_PathOp",
    131     "kUnion_PathOp",
    132     "kXor_PathOp",
    133     "kReverseDifference_PathOp",
    134 };
    135 
    136 static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) {
    137     SkDebugf("    testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]);
    138     SkDebugf("}\n");
    139 }
    140 
    141 SK_DECLARE_STATIC_MUTEX(gTestMutex);
    142 
    143 void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
    144         const char* testName) {
    145     SkAutoMutexAcquire ac(gTestMutex);
    146     show_function_header(testName);
    147     ShowOnePath(a, "path", true);
    148     ShowOnePath(b, "pathB", true);
    149     show_op(shapeOp, "path", "pathB");
    150 }
    151 #endif
    152 
    153 // if not defined by PathOpsDebug.cpp ...
    154 #if !defined SK_DEBUG && FORCE_RELEASE
    155 bool SkPathOpsDebug::ValidWind(int wind) {
    156     return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
    157 }
    158 
    159 void SkPathOpsDebug::WindingPrintf(int wind) {
    160     if (wind == SK_MinS32) {
    161         SkDebugf("?");
    162     } else {
    163         SkDebugf("%d", wind);
    164     }
    165 }
    166 #endif
    167 
    168 void SkOpAngle::dump() const {
    169     dumpOne(true);
    170     SkDebugf("\n");
    171 }
    172 
    173 void SkOpAngle::dumpOne(bool functionHeader) const {
    174 //    fSegment->debugValidate();
    175     const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd));
    176     if (functionHeader) {
    177         SkDebugf("%s ", __FUNCTION__);
    178     }
    179     SkDebugf("[%d", fSegment->debugID());
    180     SkDebugf("/%d", debugID());
    181     SkDebugf("] next=");
    182     if (fNext) {
    183         SkDebugf("%d", fNext->fSegment->debugID());
    184         SkDebugf("/%d", fNext->debugID());
    185     } else {
    186         SkDebugf("?");
    187     }
    188     SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
    189     SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fSegment->span(fStart).fT, fStart,
    190             fSegment->span(fEnd).fT, fEnd);
    191     SkDebugf(" sgn=%d windVal=%d", sign(), mSpan.fWindValue);
    192 
    193     SkDebugf(" windSum=");
    194     SkPathOpsDebug::WindingPrintf(mSpan.fWindSum);
    195     if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) {
    196         SkDebugf(" oppVal=%d", mSpan.fOppValue);
    197         SkDebugf(" oppSum=");
    198         SkPathOpsDebug::WindingPrintf(mSpan.fOppSum);
    199     }
    200     if (mSpan.fDone) {
    201         SkDebugf(" done");
    202     }
    203     if (unorderable()) {
    204         SkDebugf(" unorderable");
    205     }
    206     if (small()) {
    207         SkDebugf(" small");
    208     }
    209     if (mSpan.fTiny) {
    210         SkDebugf(" tiny");
    211     }
    212     if (fSegment->operand()) {
    213         SkDebugf(" operand");
    214     }
    215     if (fStop) {
    216         SkDebugf(" stop");
    217     }
    218 }
    219 
    220 void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
    221     const SkOpAngle* first = this;
    222     const SkOpAngle* next = this;
    223     const char* indent = "";
    224     do {
    225         SkDebugf("%s", indent);
    226         next->dumpOne(false);
    227         if (segment == next->fSegment) {
    228             if (this == fNext) {
    229                 SkDebugf(" << from");
    230             }
    231             if (to == fNext) {
    232                 SkDebugf(" << to");
    233             }
    234         }
    235         SkDebugf("\n");
    236         indent = "           ";
    237         next = next->fNext;
    238     } while (next && next != first);
    239 }
    240 
    241 void SkOpAngle::dumpLoop() const {
    242     const SkOpAngle* first = this;
    243     const SkOpAngle* next = this;
    244     do {
    245         next->dumpOne(false);
    246         SkDebugf("\n");
    247         next = next->fNext;
    248     } while (next && next != first);
    249 }
    250 
    251 void SkOpAngle::dumpPartials() const {
    252     const SkOpAngle* first = this;
    253     const SkOpAngle* next = this;
    254     do {
    255         next->fCurvePart.dumpNumber();
    256         next = next->fNext;
    257     } while (next && next != first);
    258 }
    259 
    260 void SkOpAngleSet::dump() const {
    261     // FIXME: unimplemented
    262 /* This requires access to the internal SkChunkAlloc data
    263    Defer implementing this until it is needed for debugging
    264 */
    265     SkASSERT(0);
    266 }
    267 
    268 void SkOpContour::dump() const {
    269     int segmentCount = fSegments.count();
    270     SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
    271     for (int test = 0; test < segmentCount; ++test) {
    272         SkDebugf("  [%d] ((SkOpSegment*) 0x%p) [%d]\n", test, &fSegments[test],
    273                 fSegments[test].debugID());
    274     }
    275 }
    276 
    277 void SkOpContour::dumpAngles() const {
    278     int segmentCount = fSegments.count();
    279     SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
    280     for (int test = 0; test < segmentCount; ++test) {
    281         SkDebugf("  [%d] ", test);
    282         fSegments[test].dumpAngles();
    283     }
    284 }
    285 
    286 void SkOpContour::dumpCoincidence(const SkCoincidence& coin) const {
    287     int thisIndex = coin.fSegments[0];
    288     const SkOpSegment& s1 = fSegments[thisIndex];
    289     int otherIndex = coin.fSegments[1];
    290     const SkOpSegment& s2 = coin.fOther->fSegments[otherIndex];
    291     SkDebugf("((SkOpSegment*) 0x%p) [%d]  ((SkOpSegment*) 0x%p) [%d]\n", &s1, s1.debugID(),
    292             &s2, s2.debugID());
    293     for (int index = 0; index < 2; ++index) {
    294         SkDebugf("    {%1.9gf, %1.9gf}", coin.fPts[0][index].fX, coin.fPts[0][index].fY);
    295         if (coin.fNearly[index]) {
    296             SkDebugf("    {%1.9gf, %1.9gf}", coin.fPts[1][index].fX, coin.fPts[1][index].fY);
    297         }
    298         SkDebugf("  seg1t=%1.9g seg2t=%1.9g\n", coin.fTs[0][index], coin.fTs[1][index]);
    299     }
    300 }
    301 
    302 void SkOpContour::dumpCoincidences() const {
    303     int count = fCoincidences.count();
    304     if (count > 0) {
    305         SkDebugf("fCoincidences count=%d\n", count);
    306         for (int test = 0; test < count; ++test) {
    307             dumpCoincidence(fCoincidences[test]);
    308         }
    309     }
    310     count = fPartialCoincidences.count();
    311     if (count == 0) {
    312         return;
    313     }
    314     SkDebugf("fPartialCoincidences count=%d\n", count);
    315     for (int test = 0; test < count; ++test) {
    316         dumpCoincidence(fPartialCoincidences[test]);
    317     }
    318 }
    319 
    320 void SkOpContour::dumpPt(int index) const {
    321     int segmentCount = fSegments.count();
    322     for (int test = 0; test < segmentCount; ++test) {
    323         const SkOpSegment& segment = fSegments[test];
    324         if (segment.debugID() == index) {
    325             fSegments[test].dumpPts();
    326         }
    327     }
    328 }
    329 
    330 void SkOpContour::dumpPts() const {
    331     int segmentCount = fSegments.count();
    332     SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
    333     for (int test = 0; test < segmentCount; ++test) {
    334         SkDebugf("  [%d] ", test);
    335         fSegments[test].dumpPts();
    336     }
    337 }
    338 
    339 void SkOpContour::dumpSpan(int index) const {
    340     int segmentCount = fSegments.count();
    341     for (int test = 0; test < segmentCount; ++test) {
    342         const SkOpSegment& segment = fSegments[test];
    343         if (segment.debugID() == index) {
    344             fSegments[test].dumpSpans();
    345         }
    346     }
    347 }
    348 
    349 void SkOpContour::dumpSpans() const {
    350     int segmentCount = fSegments.count();
    351     SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
    352     for (int test = 0; test < segmentCount; ++test) {
    353         SkDebugf("  [%d] ", test);
    354         fSegments[test].dumpSpans();
    355     }
    356 }
    357 
    358 void SkDCubic::dump() const {
    359     SkDebugf("{{");
    360     int index = 0;
    361     do {
    362         fPts[index].dump();
    363         SkDebugf(", ");
    364     } while (++index < 3);
    365     fPts[index].dump();
    366     SkDebugf("}}\n");
    367 }
    368 
    369 void SkDCubic::dumpNumber() const {
    370     SkDebugf("{{");
    371     int index = 0;
    372     bool dumpedOne = false;
    373     do {
    374         if (!(fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY)) {
    375             continue;
    376         }
    377         if (dumpedOne) {
    378             SkDebugf(", ");
    379         }
    380         fPts[index].dump();
    381         dumpedOne = true;
    382     } while (++index < 3);
    383     if (fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY) {
    384         if (dumpedOne) {
    385             SkDebugf(", ");
    386         }
    387         fPts[index].dump();
    388     }
    389     SkDebugf("}}\n");
    390 }
    391 
    392 void SkDLine::dump() const {
    393     SkDebugf("{{");
    394     fPts[0].dump();
    395     SkDebugf(", ");
    396     fPts[1].dump();
    397     SkDebugf("}}\n");
    398 }
    399 
    400 void SkDPoint::dump() const {
    401     SkDebugf("{");
    402     DebugDumpDouble(fX);
    403     SkDebugf(", ");
    404     DebugDumpDouble(fY);
    405     SkDebugf("}");
    406 }
    407 
    408 void SkDPoint::Dump(const SkPoint& pt) {
    409     SkDebugf("{");
    410     DebugDumpFloat(pt.fX);
    411     SkDebugf(", ");
    412     DebugDumpFloat(pt.fY);
    413     SkDebugf("}");
    414 }
    415 
    416 
    417 void SkDQuad::dumpComma(const char* comma) const {
    418     SkDebugf("{{");
    419     int index = 0;
    420     do {
    421         fPts[index].dump();
    422         SkDebugf(", ");
    423     } while (++index < 2);
    424     fPts[index].dump();
    425     SkDebugf("}}%s\n", comma ? comma : "");
    426 }
    427 
    428 void SkDQuad::dump() const {
    429     dumpComma("");
    430 }
    431 
    432 void SkIntersectionHelper::dump() const {
    433     SkDPoint::Dump(pts()[0]);
    434     SkDPoint::Dump(pts()[1]);
    435     if (verb() >= SkPath::kQuad_Verb) {
    436         SkDPoint::Dump(pts()[2]);
    437     }
    438     if (verb() >= SkPath::kCubic_Verb) {
    439         SkDPoint::Dump(pts()[3]);
    440     }
    441 }
    442 
    443 const SkTDArray<SkOpSpan>& SkOpSegment::debugSpans() const {
    444     return fTs;
    445 }
    446 
    447 void SkOpSegment::dumpAngles() const {
    448     SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
    449     const SkOpAngle* fromAngle = NULL;
    450     const SkOpAngle* toAngle = NULL;
    451     for (int index = 0; index < count(); ++index) {
    452         const SkOpAngle* fAngle = fTs[index].fFromAngle;
    453         const SkOpAngle* tAngle = fTs[index].fToAngle;
    454         if (fromAngle == fAngle && toAngle == tAngle) {
    455             continue;
    456         }
    457         if (fAngle) {
    458             SkDebugf("  [%d] from=%d ", index, fAngle->debugID());
    459             fAngle->dumpTo(this, tAngle);
    460         }
    461         if (tAngle) {
    462             SkDebugf("  [%d] to=%d   ", index, tAngle->debugID());
    463             tAngle->dumpTo(this, fAngle);
    464         }
    465         fromAngle = fAngle;
    466         toAngle = tAngle;
    467     }
    468 }
    469 
    470 void SkOpSegment::dumpContour(int firstID, int lastID) const {
    471     if (debugID() < 0) {
    472         return;
    473     }
    474     const SkOpSegment* test = this - (debugID() - 1);
    475     test += (firstID - 1);
    476     const SkOpSegment* last = test + (lastID - firstID);
    477     while (test <= last) {
    478         test->dumpSpans();
    479         ++test;
    480     }
    481 }
    482 
    483 void SkOpSegment::dumpPts() const {
    484     int last = SkPathOpsVerbToPoints(fVerb);
    485     SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
    486     int index = 0;
    487     do {
    488         SkDPoint::Dump(fPts[index]);
    489         SkDebugf(", ");
    490     } while (++index < last);
    491     SkDPoint::Dump(fPts[index]);
    492     SkDebugf("}}\n");
    493 }
    494 
    495 void SkOpSegment::dumpDPts() const {
    496     int count = SkPathOpsVerbToPoints(fVerb);
    497     SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
    498     int index = 0;
    499     do {
    500         SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
    501         dPt.dump();
    502         if (index != count) {
    503             SkDebugf(", ");
    504         }
    505     } while (++index <= count);
    506     SkDebugf("}}\n");
    507 }
    508 
    509 void SkOpSegment::dumpSpans() const {
    510     int count = this->count();
    511     SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
    512     for (int index = 0; index < count; ++index) {
    513         const SkOpSpan& span = this->span(index);
    514         SkDebugf("  [%d] ", index);
    515         span.dumpOne();
    516     }
    517 }
    518 
    519 void SkPathOpsDebug::DumpCoincidence(const SkTArray<SkOpContour, true>& contours) {
    520     int count = contours.count();
    521     for (int index = 0; index < count; ++index) {
    522         contours[index].dumpCoincidences();
    523     }
    524 }
    525 
    526 void SkPathOpsDebug::DumpCoincidence(const SkTArray<SkOpContour* , true>& contours) {
    527     int count = contours.count();
    528     for (int index = 0; index < count; ++index) {
    529         contours[index]->dumpCoincidences();
    530     }
    531 }
    532 
    533 void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour, true>& contours) {
    534     int count = contours.count();
    535     for (int index = 0; index < count; ++index) {
    536         contours[index].dump();
    537     }
    538 }
    539 
    540 void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour* , true>& contours) {
    541     int count = contours.count();
    542     for (int index = 0; index < count; ++index) {
    543         contours[index]->dump();
    544     }
    545 }
    546 
    547 void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour, true>& contours) {
    548     int count = contours.count();
    549     for (int index = 0; index < count; ++index) {
    550         contours[index].dumpAngles();
    551     }
    552 }
    553 
    554 void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour* , true>& contours) {
    555     int count = contours.count();
    556     for (int index = 0; index < count; ++index) {
    557         contours[index]->dumpAngles();
    558     }
    559 }
    560 
    561 void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour, true>& contours) {
    562     int count = contours.count();
    563     for (int index = 0; index < count; ++index) {
    564         contours[index].dumpPts();
    565     }
    566 }
    567 
    568 void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour* , true>& contours) {
    569     int count = contours.count();
    570     for (int index = 0; index < count; ++index) {
    571         contours[index]->dumpPts();
    572     }
    573 }
    574 
    575 void SkPathOpsDebug::DumpContourPt(const SkTArray<SkOpContour, true>& contours, int segmentID) {
    576     int count = contours.count();
    577     for (int index = 0; index < count; ++index) {
    578         contours[index].dumpPt(segmentID);
    579     }
    580 }
    581 
    582 void SkPathOpsDebug::DumpContourPt(const SkTArray<SkOpContour* , true>& contours, int segmentID) {
    583     int count = contours.count();
    584     for (int index = 0; index < count; ++index) {
    585         contours[index]->dumpPt(segmentID);
    586     }
    587 }
    588 
    589 void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour, true>& contours) {
    590     int count = contours.count();
    591     for (int index = 0; index < count; ++index) {
    592         contours[index].dumpSpans();
    593     }
    594 }
    595 
    596 void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour* , true>& contours) {
    597     int count = contours.count();
    598     for (int index = 0; index < count; ++index) {
    599         contours[index]->dumpSpans();
    600     }
    601 }
    602 
    603 void SkPathOpsDebug::DumpContourSpan(const SkTArray<SkOpContour, true>& contours, int segmentID) {
    604     int count = contours.count();
    605     for (int index = 0; index < count; ++index) {
    606         contours[index].dumpSpan(segmentID);
    607     }
    608 }
    609 
    610 void SkPathOpsDebug::DumpContourSpan(const SkTArray<SkOpContour* , true>& contours, int segmentID) {
    611     int count = contours.count();
    612     for (int index = 0; index < count; ++index) {
    613         contours[index]->dumpSpan(segmentID);
    614     }
    615 }
    616 
    617 void SkPathOpsDebug::DumpSpans(const SkTDArray<SkOpSpan *>& spans) {
    618     int count = spans.count();
    619     for (int index = 0; index < count; ++index) {
    620         const SkOpSpan* span = spans[index];
    621         const SkOpSpan& oSpan = span->fOther->span(span->fOtherIndex);
    622         const SkOpSegment* segment = oSpan.fOther;
    623         SkDebugf("((SkOpSegment*) 0x%p) [%d] ", segment, segment->debugID());
    624         SkDebugf("spanIndex:%d ", oSpan.fOtherIndex);
    625         span->dumpOne();
    626     }
    627 }
    628 
    629 // this does not require that other T index is initialized or correct
    630 const SkOpSegment* SkOpSpan::debugToSegment(ptrdiff_t* spanIndex) const {
    631     if (!fOther) {
    632         return NULL;
    633     }
    634     int oppCount = fOther->count();
    635     for (int index = 0; index < oppCount; ++index) {
    636         const SkOpSpan& otherSpan = fOther->span(index);
    637         double otherTestT = otherSpan.fT;
    638         if (otherTestT < fOtherT) {
    639             continue;
    640         }
    641         SkASSERT(otherTestT == fOtherT);
    642         const SkOpSegment* candidate = otherSpan.fOther;
    643         const SkOpSpan* first = candidate->debugSpans().begin();
    644         const SkOpSpan* last = candidate->debugSpans().end() - 1;
    645         if (first <= this && this <= last) {
    646             if (spanIndex) {
    647                 *spanIndex = this - first;
    648             }
    649             return candidate;
    650         }
    651     }
    652     SkASSERT(0);
    653     return NULL;
    654 }
    655 
    656 void SkOpSpan::dumpOne() const {
    657     SkDebugf("t=");
    658     DebugDumpDouble(fT);
    659     SkDebugf(" pt=");
    660     SkDPoint::Dump(fPt);
    661     if (fOther) {
    662         SkDebugf(" other.fID=%d", fOther->debugID());
    663         SkDebugf(" [%d] otherT=", fOtherIndex);
    664         DebugDumpDouble(fOtherT);
    665     } else {
    666         SkDebugf(" other.fID=? [?] otherT=?");
    667     }
    668     if (fWindSum != SK_MinS32) {
    669         SkDebugf(" windSum=%d", fWindSum);
    670     }
    671     if (fOppSum != SK_MinS32 && (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0)) {
    672         SkDebugf(" oppSum=%d", fOppSum);
    673     }
    674     SkDebugf(" windValue=%d", fWindValue);
    675     if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
    676         SkDebugf(" oppValue=%d", fOppValue);
    677     }
    678     if (fFromAngle && fFromAngle->debugID()) {
    679         SkDebugf(" from=%d", fFromAngle->debugID());
    680     }
    681     if (fToAngle && fToAngle->debugID()) {
    682         SkDebugf(" to=%d", fToAngle->debugID());
    683     }
    684     if (fChased) {
    685         SkDebugf(" chased");
    686     }
    687     if (fCoincident) {
    688         SkDebugf(" coincident");
    689     }
    690     if (fDone) {
    691         SkDebugf(" done");
    692     }
    693     if (fLoop) {
    694         SkDebugf(" loop");
    695     }
    696     if (fMultiple) {
    697         SkDebugf(" multiple");
    698     }
    699     if (fNear) {
    700         SkDebugf(" near");
    701     }
    702     if (fSmall) {
    703         SkDebugf(" small");
    704     }
    705     if (fTiny) {
    706         SkDebugf(" tiny");
    707     }
    708     SkDebugf("\n");
    709 }
    710 
    711 void SkOpSpan::dump() const {
    712     ptrdiff_t spanIndex;
    713     const SkOpSegment* segment = debugToSegment(&spanIndex);
    714     if (segment) {
    715         SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", segment, segment->debugID());
    716         SkDebugf("  [%d] ", spanIndex);
    717     } else {
    718         SkDebugf("((SkOpSegment*) ?) [?]\n");
    719         SkDebugf("  [?] ");
    720     }
    721     dumpOne();
    722 }
    723 
    724 void Dump(const SkTArray<class SkOpContour, true>& contours) {
    725     SkPathOpsDebug::DumpContours(contours);
    726 }
    727 
    728 void Dump(const SkTArray<class SkOpContour* , true>& contours) {
    729     SkPathOpsDebug::DumpContours(contours);
    730 }
    731 
    732 void Dump(const SkTArray<class SkOpContour, true>* contours) {
    733     SkPathOpsDebug::DumpContours(*contours);
    734 }
    735 
    736 void Dump(const SkTArray<class SkOpContour* , true>* contours) {
    737     SkPathOpsDebug::DumpContours(*contours);
    738 }
    739 
    740 void Dump(const SkTDArray<SkOpSpan *>& chase) {
    741     SkPathOpsDebug::DumpSpans(chase);
    742 }
    743 
    744 void Dump(const SkTDArray<SkOpSpan *>* chase) {
    745     SkPathOpsDebug::DumpSpans(*chase);
    746 }
    747 
    748 void DumpAngles(const SkTArray<class SkOpContour, true>& contours) {
    749     SkPathOpsDebug::DumpContourAngles(contours);
    750 }
    751 
    752 void DumpAngles(const SkTArray<class SkOpContour* , true>& contours) {
    753     SkPathOpsDebug::DumpContourAngles(contours);
    754 }
    755 
    756 void DumpAngles(const SkTArray<class SkOpContour, true>* contours) {
    757     SkPathOpsDebug::DumpContourAngles(*contours);
    758 }
    759 
    760 void DumpAngles(const SkTArray<class SkOpContour* , true>* contours) {
    761     SkPathOpsDebug::DumpContourAngles(*contours);
    762 }
    763 
    764 void DumpCoin(const SkTArray<class SkOpContour, true>& contours) {
    765     SkPathOpsDebug::DumpCoincidence(contours);
    766 }
    767 
    768 void DumpCoin(const SkTArray<class SkOpContour* , true>& contours) {
    769     SkPathOpsDebug::DumpCoincidence(contours);
    770 }
    771 
    772 void DumpCoin(const SkTArray<class SkOpContour, true>* contours) {
    773     SkPathOpsDebug::DumpCoincidence(*contours);
    774 }
    775 
    776 void DumpCoin(const SkTArray<class SkOpContour* , true>* contours) {
    777     SkPathOpsDebug::DumpCoincidence(*contours);
    778 }
    779 
    780 void DumpSpans(const SkTArray<class SkOpContour, true>& contours) {
    781     SkPathOpsDebug::DumpContourSpans(contours);
    782 }
    783 
    784 void DumpSpans(const SkTArray<class SkOpContour* , true>& contours) {
    785     SkPathOpsDebug::DumpContourSpans(contours);
    786 }
    787 
    788 void DumpSpans(const SkTArray<class SkOpContour, true>* contours) {
    789     SkPathOpsDebug::DumpContourSpans(*contours);
    790 }
    791 
    792 void DumpSpans(const SkTArray<class SkOpContour* , true>* contours) {
    793     SkPathOpsDebug::DumpContourSpans(*contours);
    794 }
    795 
    796 void DumpSpan(const SkTArray<class SkOpContour, true>& contours, int segmentID) {
    797     SkPathOpsDebug::DumpContourSpan(contours, segmentID);
    798 }
    799 
    800 void DumpSpan(const SkTArray<class SkOpContour* , true>& contours, int segmentID) {
    801     SkPathOpsDebug::DumpContourSpan(contours, segmentID);
    802 }
    803 
    804 void DumpSpan(const SkTArray<class SkOpContour, true>* contours, int segmentID) {
    805     SkPathOpsDebug::DumpContourSpan(*contours, segmentID);
    806 }
    807 
    808 void DumpSpan(const SkTArray<class SkOpContour* , true>* contours, int segmentID) {
    809     SkPathOpsDebug::DumpContourSpan(*contours, segmentID);
    810 }
    811 
    812 void DumpPts(const SkTArray<class SkOpContour, true>& contours) {
    813     SkPathOpsDebug::DumpContourPts(contours);
    814 }
    815 
    816 void DumpPts(const SkTArray<class SkOpContour* , true>& contours) {
    817     SkPathOpsDebug::DumpContourPts(contours);
    818 }
    819 
    820 void DumpPts(const SkTArray<class SkOpContour, true>* contours) {
    821     SkPathOpsDebug::DumpContourPts(*contours);
    822 }
    823 
    824 void DumpPts(const SkTArray<class SkOpContour* , true>* contours) {
    825     SkPathOpsDebug::DumpContourPts(*contours);
    826 }
    827 
    828 void DumpPt(const SkTArray<class SkOpContour, true>& contours, int segmentID) {
    829     SkPathOpsDebug::DumpContourPt(contours, segmentID);
    830 }
    831 
    832 void DumpPt(const SkTArray<class SkOpContour* , true>& contours, int segmentID) {
    833     SkPathOpsDebug::DumpContourPt(contours, segmentID);
    834 }
    835 
    836 void DumpPt(const SkTArray<class SkOpContour, true>* contours, int segmentID) {
    837     SkPathOpsDebug::DumpContourPt(*contours, segmentID);
    838 }
    839 
    840 void DumpPt(const SkTArray<class SkOpContour* , true>* contours, int segmentID) {
    841     SkPathOpsDebug::DumpContourPt(*contours, segmentID);
    842 }
    843 
    844 static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
    845     SkDebugf("<div id=\"quad%d\">\n", testNo);
    846     quad1.dumpComma(",");
    847     quad2.dump();
    848     SkDebugf("</div>\n\n");
    849 }
    850 
    851 static void dumpTestTrailer() {
    852     SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
    853     SkDebugf("    var testDivs = [\n");
    854 }
    855 
    856 static void dumpTestList(int testNo, double min) {
    857     SkDebugf("        quad%d,", testNo);
    858     if (min > 0) {
    859         SkDebugf("  // %1.9g", min);
    860     }
    861     SkDebugf("\n");
    862 }
    863 
    864 void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
    865     SkDebugf("\n");
    866     dumpTestCase(quad1, quad2, testNo);
    867     dumpTestTrailer();
    868     dumpTestList(testNo, 0);
    869     SkDebugf("\n");
    870 }
    871 
    872 void DumpT(const SkDQuad& quad, double t) {
    873     SkDLine line = {{quad.ptAtT(t), quad[0]}};
    874     line.dump();
    875 }
    876