Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "PathOpsTSectDebug.h"
      9 #include "SkOpCoincidence.h"
     10 #include "SkOpContour.h"
     11 #include "SkIntersectionHelper.h"
     12 #include "SkMutex.h"
     13 #include "SkOpSegment.h"
     14 #include "SkString.h"
     15 
     16 inline void DebugDumpDouble(double x) {
     17     if (x == floor(x)) {
     18         SkDebugf("%.0f", x);
     19     } else {
     20         SkDebugf("%1.19g", x);
     21     }
     22 }
     23 
     24 inline void DebugDumpFloat(float x) {
     25     if (x == floorf(x)) {
     26         SkDebugf("%.0f", x);
     27     } else {
     28         SkDebugf("%1.9gf", x);
     29     }
     30 }
     31 
     32 inline void DebugDumpHexFloat(float x) {
     33     SkDebugf("SkBits2Float(0x%08x)", SkFloat2Bits(x));
     34 }
     35 
     36 // if not defined by PathOpsDebug.cpp ...
     37 #if !defined SK_DEBUG && FORCE_RELEASE
     38 bool SkPathOpsDebug::ValidWind(int wind) {
     39     return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
     40 }
     41 
     42 void SkPathOpsDebug::WindingPrintf(int wind) {
     43     if (wind == SK_MinS32) {
     44         SkDebugf("?");
     45     } else {
     46         SkDebugf("%d", wind);
     47     }
     48 }
     49 #endif
     50 
     51 static void DumpID(int id) {
     52     SkDebugf("} ");
     53     if (id >= 0) {
     54         SkDebugf("id=%d", id);
     55     }
     56     SkDebugf("\n");
     57 }
     58 
     59 void SkDConic::dump() const {
     60     dumpInner();
     61     SkDebugf("},\n");
     62 }
     63 
     64 void SkDConic::dumpID(int id) const {
     65     dumpInner();
     66     DumpID(id);
     67 }
     68 
     69 void SkDConic::dumpInner() const {
     70     SkDebugf("{");
     71     fPts.dumpInner();
     72     SkDebugf("}}, %1.9gf", fWeight);
     73 }
     74 
     75 void SkDCubic::dump() const {
     76     this->dumpInner();
     77     SkDebugf("}},\n");
     78 }
     79 
     80 void SkDCubic::dumpID(int id) const {
     81     this->dumpInner();
     82     SkDebugf("}");
     83     DumpID(id);
     84 }
     85 
     86 static inline bool double_is_NaN(double x) { return x != x; }
     87 
     88 void SkDCubic::dumpInner() const {
     89     SkDebugf("{{");
     90     int index = 0;
     91     do {
     92         if (index != 0) {
     93             if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
     94                 return;
     95             }
     96             SkDebugf(", ");
     97         }
     98         fPts[index].dump();
     99     } while (++index < 3);
    100     if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
    101         return;
    102     }
    103     SkDebugf(", ");
    104     fPts[index].dump();
    105 }
    106 
    107 void SkDCurve::dump() const {
    108     dumpID(-1);
    109 }
    110 
    111 void SkDCurve::dumpID(int id) const {
    112 #ifndef SK_RELEASE
    113     switch(fVerb) {
    114         case SkPath::kLine_Verb:
    115             fLine.dumpID(id);
    116             break;
    117         case SkPath::kQuad_Verb:
    118             fQuad.dumpID(id);
    119             break;
    120         case SkPath::kConic_Verb:
    121             fConic.dumpID(id);
    122             break;
    123         case SkPath::kCubic_Verb:
    124             fCubic.dumpID(id);
    125             break;
    126         default:
    127             SkASSERT(0);
    128     }
    129 #else
    130     fCubic.dumpID(id);
    131 #endif
    132 }
    133 
    134 void SkDLine::dump() const {
    135     this->dumpInner();
    136     SkDebugf("}},\n");
    137 }
    138 
    139 void SkDLine::dumpID(int id) const {
    140     this->dumpInner();
    141     SkDebugf("}");
    142     DumpID(id);
    143 }
    144 
    145 void SkDLine::dumpInner() const {
    146     SkDebugf("{{");
    147     fPts[0].dump();
    148     SkDebugf(", ");
    149     fPts[1].dump();
    150 }
    151 
    152 void SkDPoint::dump() const {
    153     SkDebugf("{");
    154     DebugDumpDouble(fX);
    155     SkDebugf(", ");
    156     DebugDumpDouble(fY);
    157     SkDebugf("}");
    158 }
    159 
    160 void SkDPoint::Dump(const SkPoint& pt) {
    161     SkDebugf("{");
    162     DebugDumpFloat(pt.fX);
    163     SkDebugf(", ");
    164     DebugDumpFloat(pt.fY);
    165     SkDebugf("}");
    166 }
    167 
    168 void SkDPoint::DumpHex(const SkPoint& pt) {
    169     SkDebugf("{");
    170     DebugDumpHexFloat(pt.fX);
    171     SkDebugf(", ");
    172     DebugDumpHexFloat(pt.fY);
    173     SkDebugf("}");
    174 }
    175 
    176 void SkDQuad::dump() const {
    177     dumpInner();
    178     SkDebugf("}},\n");
    179 }
    180 
    181 void SkDQuad::dumpID(int id) const {
    182     dumpInner();
    183     SkDebugf("}");
    184     DumpID(id);
    185 }
    186 
    187 void SkDQuad::dumpInner() const {
    188     SkDebugf("{{");
    189     int index = 0;
    190     do {
    191         fPts[index].dump();
    192         SkDebugf(", ");
    193     } while (++index < 2);
    194     fPts[index].dump();
    195 }
    196 
    197 void SkIntersections::dump() const {
    198     SkDebugf("used=%d of %d", fUsed, fMax);
    199     for (int index = 0; index < fUsed; ++index) {
    200         SkDebugf(" t=(%s%1.9g,%s%1.9g) pt=(%1.9g,%1.9g)",
    201                 fIsCoincident[0] & (1 << index) ? "*" : "", fT[0][index],
    202                 fIsCoincident[1] & (1 << index) ? "*" : "", fT[1][index],
    203                 fPt[index].fX, fPt[index].fY);
    204         if (index < 2 && fNearlySame[index]) {
    205             SkDebugf(" pt2=(%1.9g,%1.9g)",fPt2[index].fX, fPt2[index].fY);
    206         }
    207     }
    208     SkDebugf("\n");
    209 }
    210 
    211 const SkOpAngle* SkPathOpsDebug::DebugAngleAngle(const SkOpAngle* angle, int id) {
    212     return angle->debugAngle(id);
    213 }
    214 
    215 SkOpContour* SkPathOpsDebug::DebugAngleContour(SkOpAngle* angle, int id) {
    216     return angle->debugContour(id);
    217 }
    218 
    219 const SkOpPtT* SkPathOpsDebug::DebugAnglePtT(const SkOpAngle* angle, int id) {
    220     return angle->debugPtT(id);
    221 }
    222 
    223 const SkOpSegment* SkPathOpsDebug::DebugAngleSegment(const SkOpAngle* angle, int id) {
    224     return angle->debugSegment(id);
    225 }
    226 
    227 const SkOpSpanBase* SkPathOpsDebug::DebugAngleSpan(const SkOpAngle* angle, int id) {
    228     return angle->debugSpan(id);
    229 }
    230 
    231 const SkOpAngle* SkPathOpsDebug::DebugContourAngle(SkOpContour* contour, int id) {
    232     return contour->debugAngle(id);
    233 }
    234 
    235 SkOpContour* SkPathOpsDebug::DebugContourContour(SkOpContour* contour, int id) {
    236     return contour->debugContour(id);
    237 }
    238 
    239 const SkOpPtT* SkPathOpsDebug::DebugContourPtT(SkOpContour* contour, int id) {
    240     return contour->debugPtT(id);
    241 }
    242 
    243 const SkOpSegment* SkPathOpsDebug::DebugContourSegment(SkOpContour* contour, int id) {
    244     return contour->debugSegment(id);
    245 }
    246 
    247 const SkOpSpanBase* SkPathOpsDebug::DebugContourSpan(SkOpContour* contour, int id) {
    248     return contour->debugSpan(id);
    249 }
    250 
    251 const SkOpAngle* SkPathOpsDebug::DebugCoincidenceAngle(SkOpCoincidence* coin, int id) {
    252     return coin->debugAngle(id);
    253 }
    254 
    255 SkOpContour* SkPathOpsDebug::DebugCoincidenceContour(SkOpCoincidence* coin, int id) {
    256     return coin->debugContour(id);
    257 }
    258 
    259 const SkOpPtT* SkPathOpsDebug::DebugCoincidencePtT(SkOpCoincidence* coin, int id) {
    260     return coin->debugPtT(id);
    261 }
    262 
    263 const SkOpSegment* SkPathOpsDebug::DebugCoincidenceSegment(SkOpCoincidence* coin, int id) {
    264     return coin->debugSegment(id);
    265 }
    266 
    267 const SkOpSpanBase* SkPathOpsDebug::DebugCoincidenceSpan(SkOpCoincidence* coin, int id) {
    268     return coin->debugSpan(id);
    269 }
    270 
    271 const SkOpAngle* SkPathOpsDebug::DebugPtTAngle(const SkOpPtT* ptT, int id) {
    272     return ptT->debugAngle(id);
    273 }
    274 
    275 SkOpContour* SkPathOpsDebug::DebugPtTContour(SkOpPtT* ptT, int id) {
    276     return ptT->debugContour(id);
    277 }
    278 
    279 const SkOpPtT* SkPathOpsDebug::DebugPtTPtT(const SkOpPtT* ptT, int id) {
    280     return ptT->debugPtT(id);
    281 }
    282 
    283 const SkOpSegment* SkPathOpsDebug::DebugPtTSegment(const SkOpPtT* ptT, int id) {
    284     return ptT->debugSegment(id);
    285 }
    286 
    287 const SkOpSpanBase* SkPathOpsDebug::DebugPtTSpan(const SkOpPtT* ptT, int id) {
    288     return ptT->debugSpan(id);
    289 }
    290 
    291 const SkOpAngle* SkPathOpsDebug::DebugSegmentAngle(const SkOpSegment* span, int id) {
    292     return span->debugAngle(id);
    293 }
    294 
    295 SkOpContour* SkPathOpsDebug::DebugSegmentContour(SkOpSegment* span, int id) {
    296     return span->debugContour(id);
    297 }
    298 
    299 const SkOpPtT* SkPathOpsDebug::DebugSegmentPtT(const SkOpSegment* span, int id) {
    300     return span->debugPtT(id);
    301 }
    302 
    303 const SkOpSegment* SkPathOpsDebug::DebugSegmentSegment(const SkOpSegment* span, int id) {
    304     return span->debugSegment(id);
    305 }
    306 
    307 const SkOpSpanBase* SkPathOpsDebug::DebugSegmentSpan(const SkOpSegment* span, int id) {
    308     return span->debugSpan(id);
    309 }
    310 
    311 const SkOpAngle* SkPathOpsDebug::DebugSpanAngle(const SkOpSpanBase* span, int id) {
    312     return span->debugAngle(id);
    313 }
    314 
    315 SkOpContour* SkPathOpsDebug::DebugSpanContour(SkOpSpanBase* span, int id) {
    316     return span->debugContour(id);
    317 }
    318 
    319 const SkOpPtT* SkPathOpsDebug::DebugSpanPtT(const SkOpSpanBase* span, int id) {
    320     return span->debugPtT(id);
    321 }
    322 
    323 const SkOpSegment* SkPathOpsDebug::DebugSpanSegment(const SkOpSpanBase* span, int id) {
    324     return span->debugSegment(id);
    325 }
    326 
    327 const SkOpSpanBase* SkPathOpsDebug::DebugSpanSpan(const SkOpSpanBase* span, int id) {
    328     return span->debugSpan(id);
    329 }
    330 
    331 #if DEBUG_COIN
    332 void SkPathOpsDebug::DumpCoinDict() {
    333     gCoinSumChangedDict.dump("unused coin algorithm", false);
    334     gCoinSumVisitedDict.dump("visited coin function", true);
    335 }
    336 
    337 void SkPathOpsDebug::CoinDict::dump(const char* str, bool visitCheck) const {
    338     int count = fDict.count();
    339     for (int index = 0; index < count; ++index) {
    340         const auto& entry = fDict[index];
    341         if (visitCheck || entry.fGlitchType == kUninitialized_Glitch) {
    342             SkDebugf("%s %s : line %d iteration %d", str, entry.fFunctionName,
    343                     entry.fLineNumber, entry.fIteration);
    344             DumpGlitchType(entry.fGlitchType);
    345             SkDebugf("\n");
    346         }
    347     }
    348 }
    349 #endif
    350 
    351 void SkOpContour::dumpContours() const {
    352     SkOpContour* contour = this->globalState()->contourHead();
    353     do {
    354         contour->dump();
    355     } while ((contour = contour->next()));
    356 }
    357 
    358 void SkOpContour::dumpContoursAll() const {
    359     SkOpContour* contour = this->globalState()->contourHead();
    360     do {
    361         contour->dumpAll();
    362     } while ((contour = contour->next()));
    363 }
    364 
    365 void SkOpContour::dumpContoursAngles() const {
    366     SkOpContour* contour = this->globalState()->contourHead();
    367     do {
    368         contour->dumpAngles();
    369     } while ((contour = contour->next()));
    370 }
    371 
    372 void SkOpContour::dumpContoursPts() const {
    373     SkOpContour* contour = this->globalState()->contourHead();
    374     do {
    375         contour->dumpPts();
    376     } while ((contour = contour->next()));
    377 }
    378 
    379 void SkOpContour::dumpContoursPt(int segmentID) const {
    380     SkOpContour* contour = this->globalState()->contourHead();
    381     do {
    382         contour->dumpPt(segmentID);
    383     } while ((contour = contour->next()));
    384 }
    385 
    386 void SkOpContour::dumpContoursSegment(int segmentID) const {
    387     SkOpContour* contour = this->globalState()->contourHead();
    388     do {
    389         contour->dumpSegment(segmentID);
    390     } while ((contour = contour->next()));
    391 }
    392 
    393 void SkOpContour::dumpContoursSpan(int spanID) const {
    394     SkOpContour* contour = this->globalState()->contourHead();
    395     do {
    396         contour->dumpSpan(spanID);
    397     } while ((contour = contour->next()));
    398 }
    399 
    400 void SkOpContour::dumpContoursSpans() const {
    401     SkOpContour* contour = this->globalState()->contourHead();
    402     do {
    403         contour->dumpSpans();
    404     } while ((contour = contour->next()));
    405 }
    406 
    407 template <typename TCurve, typename OppCurve>
    408 const SkTSpan<TCurve, OppCurve>* DebugSpan(const SkTSect<TCurve, OppCurve>* sect, int id) {
    409     return sect->debugSpan(id);
    410 }
    411 
    412 void DontCallDebugSpan(int id);
    413 void DontCallDebugSpan(int id) {  // exists to instantiate the templates
    414     SkDQuad quad;
    415     SkDConic conic;
    416     SkDCubic cubic;
    417     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    418     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    419     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    420     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    421     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    422     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    423     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    424     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    425     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    426     DebugSpan(&q1q2, id);
    427     DebugSpan(&q1k2, id);
    428     DebugSpan(&q1c2, id);
    429     DebugSpan(&k1q2, id);
    430     DebugSpan(&k1k2, id);
    431     DebugSpan(&k1c2, id);
    432     DebugSpan(&c1q2, id);
    433     DebugSpan(&c1k2, id);
    434     DebugSpan(&c1c2, id);
    435 }
    436 
    437 template <typename TCurve, typename OppCurve>
    438 const SkTSpan<TCurve, OppCurve>* DebugT(const SkTSect<TCurve, OppCurve>* sect, double t) {
    439     return sect->debugT(t);
    440 }
    441 
    442 void DontCallDebugT(double t);
    443 void DontCallDebugT(double t) {  // exists to instantiate the templates
    444     SkDQuad quad;
    445     SkDConic conic;
    446     SkDCubic cubic;
    447     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    448     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    449     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    450     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    451     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    452     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    453     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    454     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    455     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    456     DebugT(&q1q2, t);
    457     DebugT(&q1k2, t);
    458     DebugT(&q1c2, t);
    459     DebugT(&k1q2, t);
    460     DebugT(&k1k2, t);
    461     DebugT(&k1c2, t);
    462     DebugT(&c1q2, t);
    463     DebugT(&c1k2, t);
    464     DebugT(&c1c2, t);
    465 }
    466 
    467 template <typename TCurve, typename OppCurve>
    468 void Dump(const SkTSect<TCurve, OppCurve>* sect) {
    469     sect->dump();
    470 }
    471 
    472 void DontCallDumpTSect();
    473 void DontCallDumpTSect() {  // exists to instantiate the templates
    474     SkDQuad quad;
    475     SkDConic conic;
    476     SkDCubic cubic;
    477     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    478     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    479     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    480     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    481     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    482     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    483     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    484     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    485     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    486     Dump(&q1q2);
    487     Dump(&q1k2);
    488     Dump(&q1c2);
    489     Dump(&k1q2);
    490     Dump(&k1k2);
    491     Dump(&k1c2);
    492     Dump(&c1q2);
    493     Dump(&c1k2);
    494     Dump(&c1c2);
    495 }
    496 
    497 template <typename TCurve, typename OppCurve>
    498 void DumpBoth(SkTSect<TCurve, OppCurve>* sect1, SkTSect<OppCurve, TCurve>* sect2) {
    499     sect1->dumpBoth(sect2);
    500 }
    501 
    502 void DontCallDumpBoth();
    503 void DontCallDumpBoth() {  // exists to instantiate the templates
    504     SkDQuad quad;
    505     SkDConic conic;
    506     SkDCubic cubic;
    507     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    508     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    509     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    510     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    511     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    512     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    513     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    514     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    515     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    516     DumpBoth(&q1q2, &q1q2);
    517     DumpBoth(&q1k2, &k1q2);
    518     DumpBoth(&q1c2, &c1q2);
    519     DumpBoth(&k1q2, &q1k2);
    520     DumpBoth(&k1k2, &k1k2);
    521     DumpBoth(&k1c2, &c1k2);
    522     DumpBoth(&c1q2, &q1c2);
    523     DumpBoth(&c1k2, &k1c2);
    524     DumpBoth(&c1c2, &c1c2);
    525 }
    526 
    527 template <typename TCurve, typename OppCurve>
    528 void DumpBounded(SkTSect<TCurve, OppCurve>* sect1, int id) {
    529     sect1->dumpBounded(id);
    530 }
    531 
    532 void DontCallDumpBounded();
    533 void DontCallDumpBounded() {
    534     SkDQuad quad;
    535     SkDConic conic;
    536     SkDCubic cubic;
    537     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    538     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    539     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    540     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    541     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    542     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    543     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    544     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    545     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    546     DumpBounded(&q1q2, 0);
    547     DumpBounded(&q1k2, 0);
    548     DumpBounded(&q1c2, 0);
    549     DumpBounded(&k1q2, 0);
    550     DumpBounded(&k1k2, 0);
    551     DumpBounded(&k1c2, 0);
    552     DumpBounded(&c1q2, 0);
    553     DumpBounded(&c1k2, 0);
    554     DumpBounded(&c1c2, 0);
    555 }
    556 
    557 template <typename TCurve, typename OppCurve>
    558 void DumpBounds(SkTSect<TCurve, OppCurve>* sect1) {
    559     sect1->dumpBounds();
    560 }
    561 
    562 void DontCallDumpBounds();
    563 void DontCallDumpBounds() {
    564     SkDQuad quad;
    565     SkDConic conic;
    566     SkDCubic cubic;
    567     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    568     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    569     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    570     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    571     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    572     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    573     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    574     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    575     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    576     DumpBounds(&q1q2);
    577     DumpBounds(&q1k2);
    578     DumpBounds(&q1c2);
    579     DumpBounds(&k1q2);
    580     DumpBounds(&k1k2);
    581     DumpBounds(&k1c2);
    582     DumpBounds(&c1q2);
    583     DumpBounds(&c1k2);
    584     DumpBounds(&c1c2);
    585 }
    586 
    587 template <typename TCurve, typename OppCurve>
    588 void DumpCoin(SkTSect<TCurve, OppCurve>* sect1) {
    589     sect1->dumpCoin();
    590 }
    591 
    592 void DontCallDumpCoin();
    593 void DontCallDumpCoin() {  // exists to instantiate the templates
    594     SkDQuad quad;
    595     SkDConic conic;
    596     SkDCubic cubic;
    597     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    598     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    599     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    600     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    601     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    602     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    603     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    604     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    605     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    606     DumpCoin(&q1q2);
    607     DumpCoin(&q1k2);
    608     DumpCoin(&q1c2);
    609     DumpCoin(&k1q2);
    610     DumpCoin(&k1k2);
    611     DumpCoin(&k1c2);
    612     DumpCoin(&c1q2);
    613     DumpCoin(&c1k2);
    614     DumpCoin(&c1c2);
    615 }
    616 
    617 template <typename TCurve, typename OppCurve>
    618 void DumpCoinCurves(SkTSect<TCurve, OppCurve>* sect1) {
    619     sect1->dumpCoinCurves();
    620 }
    621 
    622 void DontCallDumpCoinCurves();
    623 void DontCallDumpCoinCurves() {  // exists to instantiate the templates
    624     SkDQuad quad;
    625     SkDConic conic;
    626     SkDCubic cubic;
    627     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    628     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    629     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    630     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    631     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    632     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    633     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    634     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    635     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    636     DumpCoinCurves(&q1q2);
    637     DumpCoinCurves(&q1k2);
    638     DumpCoinCurves(&q1c2);
    639     DumpCoinCurves(&k1q2);
    640     DumpCoinCurves(&k1k2);
    641     DumpCoinCurves(&k1c2);
    642     DumpCoinCurves(&c1q2);
    643     DumpCoinCurves(&c1k2);
    644     DumpCoinCurves(&c1c2);
    645 }
    646 
    647 template <typename TCurve, typename OppCurve>
    648 void DumpCurves(const SkTSect<TCurve, OppCurve>* sect) {
    649     sect->dumpCurves();
    650 }
    651 
    652 void DontCallDumpCurves();
    653 void DontCallDumpCurves() {  // exists to instantiate the templates
    654     SkDQuad quad;
    655     SkDConic conic;
    656     SkDCubic cubic;
    657     SkTSect<SkDQuad, SkDQuad> q1q2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    658     SkTSect<SkDQuad, SkDConic> q1k2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    659     SkTSect<SkDQuad, SkDCubic> q1c2(quad  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    660     SkTSect<SkDConic, SkDQuad> k1q2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    661     SkTSect<SkDConic, SkDConic> k1k2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    662     SkTSect<SkDConic, SkDCubic> k1c2(conic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    663     SkTSect<SkDCubic, SkDQuad> c1q2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    664     SkTSect<SkDCubic, SkDConic> c1k2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    665     SkTSect<SkDCubic, SkDCubic> c1c2(cubic  SkDEBUGPARAMS(nullptr)  PATH_OPS_DEBUG_T_SECT_PARAMS(1));
    666     DumpCurves(&q1q2);
    667     DumpCurves(&q1k2);
    668     DumpCurves(&q1c2);
    669     DumpCurves(&k1q2);
    670     DumpCurves(&k1k2);
    671     DumpCurves(&k1c2);
    672     DumpCurves(&c1q2);
    673     DumpCurves(&c1k2);
    674     DumpCurves(&c1c2);
    675 }
    676 
    677 template <typename TCurve, typename OppCurve>
    678 void Dump(const SkTSpan<TCurve, OppCurve>* span) {
    679     span->dump();
    680 }
    681 
    682 void DontCallDumpTSpan();
    683 void DontCallDumpTSpan() {  // exists to instantiate the templates
    684     SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
    685     SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
    686     SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
    687     SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
    688     SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
    689     SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
    690     SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
    691     SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
    692     SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
    693     Dump(&q1q2);
    694     Dump(&q1k2);
    695     Dump(&q1c2);
    696     Dump(&k1q2);
    697     Dump(&k1k2);
    698     Dump(&k1c2);
    699     Dump(&c1q2);
    700     Dump(&c1k2);
    701     Dump(&c1c2);
    702 }
    703 
    704 template <typename TCurve, typename OppCurve>
    705 void DumpAll(const SkTSpan<TCurve, OppCurve>* span) {
    706     span->dumpAll();
    707 }
    708 
    709 void DontCallDumpSpanAll();
    710 void DontCallDumpSpanAll() {  // exists to instantiate the templates
    711     SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
    712     SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
    713     SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
    714     SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
    715     SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
    716     SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
    717     SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
    718     SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
    719     SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
    720     DumpAll(&q1q2);
    721     DumpAll(&q1k2);
    722     DumpAll(&q1c2);
    723     DumpAll(&k1q2);
    724     DumpAll(&k1k2);
    725     DumpAll(&k1c2);
    726     DumpAll(&c1q2);
    727     DumpAll(&c1k2);
    728     DumpAll(&c1c2);
    729 }
    730 
    731 template <typename TCurve, typename OppCurve>
    732 void DumpBounded(const SkTSpan<TCurve, OppCurve>* span) {
    733     span->dumpBounded(0);
    734 }
    735 
    736 void DontCallDumpSpanBounded();
    737 void DontCallDumpSpanBounded() {  // exists to instantiate the templates
    738     SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
    739     SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
    740     SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
    741     SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
    742     SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
    743     SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
    744     SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
    745     SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
    746     SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
    747     DumpBounded(&q1q2);
    748     DumpBounded(&q1k2);
    749     DumpBounded(&q1c2);
    750     DumpBounded(&k1q2);
    751     DumpBounded(&k1k2);
    752     DumpBounded(&k1c2);
    753     DumpBounded(&c1q2);
    754     DumpBounded(&c1k2);
    755     DumpBounded(&c1c2);
    756 }
    757 
    758 template <typename TCurve, typename OppCurve>
    759 void DumpCoin(const SkTSpan<TCurve, OppCurve>* span) {
    760     span->dumpCoin();
    761 }
    762 
    763 void DontCallDumpSpanCoin();
    764 void DontCallDumpSpanCoin() {  // exists to instantiate the templates
    765     SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
    766     SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
    767     SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
    768     SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
    769     SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
    770     SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
    771     SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
    772     SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
    773     SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
    774     DumpCoin(&q1q2);
    775     DumpCoin(&q1k2);
    776     DumpCoin(&q1c2);
    777     DumpCoin(&k1q2);
    778     DumpCoin(&k1k2);
    779     DumpCoin(&k1c2);
    780     DumpCoin(&c1q2);
    781     DumpCoin(&c1k2);
    782     DumpCoin(&c1c2);
    783 }
    784 
    785 static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
    786     SkDebugf("\n<div id=\"quad%d\">\n", testNo);
    787     quad1.dumpInner();
    788     SkDebugf("}}, ");
    789     quad2.dump();
    790     SkDebugf("</div>\n\n");
    791 }
    792 
    793 static void dumpTestTrailer() {
    794     SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
    795     SkDebugf("    var testDivs = [\n");
    796 }
    797 
    798 static void dumpTestList(int testNo, double min) {
    799     SkDebugf("        quad%d,", testNo);
    800     if (min > 0) {
    801         SkDebugf("  // %1.9g", min);
    802     }
    803     SkDebugf("\n");
    804 }
    805 
    806 void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
    807     SkDebugf("\n");
    808     dumpTestCase(quad1, quad2, testNo);
    809     dumpTestTrailer();
    810     dumpTestList(testNo, 0);
    811     SkDebugf("\n");
    812 }
    813 
    814 void DumpT(const SkDQuad& quad, double t) {
    815     SkDLine line = {{quad.ptAtT(t), quad[0]}};
    816     line.dump();
    817 }
    818 
    819 const SkOpAngle* SkOpAngle::debugAngle(int id) const {
    820     return this->segment()->debugAngle(id);
    821 }
    822 
    823 const SkOpCoincidence* SkOpAngle::debugCoincidence() const {
    824     return this->segment()->debugCoincidence();
    825 }
    826 
    827 SkOpContour* SkOpAngle::debugContour(int id) const {
    828     return this->segment()->debugContour(id);
    829 }
    830 
    831 const SkOpPtT* SkOpAngle::debugPtT(int id) const {
    832     return this->segment()->debugPtT(id);
    833 }
    834 
    835 const SkOpSegment* SkOpAngle::debugSegment(int id) const {
    836     return this->segment()->debugSegment(id);
    837 }
    838 
    839 int SkOpAngle::debugSign() const {
    840     SkASSERT(fStart->t() != fEnd->t());
    841     return fStart->t() < fEnd->t() ? -1 : 1;
    842 }
    843 
    844 const SkOpSpanBase* SkOpAngle::debugSpan(int id) const {
    845     return this->segment()->debugSpan(id);
    846 }
    847 
    848 void SkOpAngle::dump() const {
    849     dumpOne(true);
    850     SkDebugf("\n");
    851 }
    852 
    853 void SkOpAngle::dumpOne(bool functionHeader) const {
    854 //    fSegment->debugValidate();
    855     const SkOpSegment* segment = this->segment();
    856     const SkOpSpan& mSpan = *fStart->starter(fEnd);
    857     if (functionHeader) {
    858         SkDebugf("%s ", __FUNCTION__);
    859     }
    860     SkDebugf("[%d", segment->debugID());
    861     SkDebugf("/%d", debugID());
    862     SkDebugf("] next=");
    863     if (fNext) {
    864         SkDebugf("%d", fNext->fStart->segment()->debugID());
    865         SkDebugf("/%d", fNext->debugID());
    866     } else {
    867         SkDebugf("?");
    868     }
    869     SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
    870     SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fStart->t(), fStart->debugID(),
    871                 fEnd->t(), fEnd->debugID());
    872     SkDebugf(" sgn=%d windVal=%d", this->debugSign(), mSpan.windValue());
    873 
    874     SkDebugf(" windSum=");
    875     SkPathOpsDebug::WindingPrintf(mSpan.windSum());
    876     if (mSpan.oppValue() != 0 || mSpan.oppSum() != SK_MinS32) {
    877         SkDebugf(" oppVal=%d", mSpan.oppValue());
    878         SkDebugf(" oppSum=");
    879         SkPathOpsDebug::WindingPrintf(mSpan.oppSum());
    880     }
    881     if (mSpan.done()) {
    882         SkDebugf(" done");
    883     }
    884     if (unorderable()) {
    885         SkDebugf(" unorderable");
    886     }
    887     if (segment->operand()) {
    888         SkDebugf(" operand");
    889     }
    890 }
    891 
    892 void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
    893     const SkOpAngle* first = this;
    894     const SkOpAngle* next = this;
    895     const char* indent = "";
    896     do {
    897         SkDebugf("%s", indent);
    898         next->dumpOne(false);
    899         if (segment == next->fStart->segment()) {
    900             if (this == fNext) {
    901                 SkDebugf(" << from");
    902             }
    903             if (to == fNext) {
    904                 SkDebugf(" << to");
    905             }
    906         }
    907         SkDebugf("\n");
    908         indent = "           ";
    909         next = next->fNext;
    910     } while (next && next != first);
    911 }
    912 
    913 void SkOpAngle::dumpCurves() const {
    914     const SkOpAngle* first = this;
    915     const SkOpAngle* next = this;
    916     do {
    917         next->fPart.fCurve.dumpID(next->segment()->debugID());
    918         next = next->fNext;
    919     } while (next && next != first);
    920 }
    921 
    922 void SkOpAngle::dumpLoop() const {
    923     const SkOpAngle* first = this;
    924     const SkOpAngle* next = this;
    925     do {
    926         next->dumpOne(false);
    927         SkDebugf("\n");
    928         next = next->fNext;
    929     } while (next && next != first);
    930 }
    931 
    932 void SkOpAngle::dumpTest() const {
    933     const SkOpAngle* first = this;
    934     const SkOpAngle* next = this;
    935     do {
    936         SkDebugf("{ ");
    937         SkOpSegment* segment = next->segment();
    938         segment->dumpPts();
    939         SkDebugf(", %d, %1.9g, %1.9g, {} },\n", SkPathOpsVerbToPoints(segment->verb()) + 1,
    940                 next->start()->t(), next->end()->t());
    941         next = next->fNext;
    942     } while (next && next != first);
    943 }
    944 
    945 bool SkOpPtT::debugMatchID(int id) const {
    946     int limit = this->debugLoopLimit(false);
    947     int loop = 0;
    948     const SkOpPtT* ptT = this;
    949     do {
    950         if (ptT->debugID() == id) {
    951             return true;
    952         }
    953     } while ((!limit || ++loop <= limit) && (ptT = ptT->next()) && ptT != this);
    954     return false;
    955 }
    956 
    957 const SkOpAngle* SkOpPtT::debugAngle(int id) const {
    958     return this->span()->debugAngle(id);
    959 }
    960 
    961 SkOpContour* SkOpPtT::debugContour(int id) const {
    962     return this->span()->debugContour(id);
    963 }
    964 
    965 const SkOpCoincidence* SkOpPtT::debugCoincidence() const {
    966     return this->span()->debugCoincidence();
    967 }
    968 
    969 const SkOpPtT* SkOpPtT::debugPtT(int id) const {
    970     return this->span()->debugPtT(id);
    971 }
    972 
    973 const SkOpSegment* SkOpPtT::debugSegment(int id) const {
    974     return this->span()->debugSegment(id);
    975 }
    976 
    977 const SkOpSpanBase* SkOpPtT::debugSpan(int id) const {
    978     return this->span()->debugSpan(id);
    979 }
    980 
    981 void SkOpPtT::dump() const {
    982     SkDebugf("seg=%d span=%d ptT=%d",
    983             this->segment()->debugID(), this->span()->debugID(), this->debugID());
    984     this->dumpBase();
    985     SkDebugf("\n");
    986 }
    987 
    988 void SkOpPtT::dumpAll() const {
    989     contour()->indentDump();
    990     const SkOpPtT* next = this;
    991     int limit = debugLoopLimit(true);
    992     int loop = 0;
    993     do {
    994         SkDebugf("%.*s", contour()->debugIndent(), "        ");
    995         SkDebugf("seg=%d span=%d ptT=%d",
    996                 next->segment()->debugID(), next->span()->debugID(), next->debugID());
    997         next->dumpBase();
    998         SkDebugf("\n");
    999         if (limit && ++loop >= limit) {
   1000             SkDebugf("*** abort loop ***\n");
   1001             break;
   1002         }
   1003     } while ((next = next->fNext) && next != this);
   1004     contour()->outdentDump();
   1005 }
   1006 
   1007 void SkOpPtT::dumpBase() const {
   1008     SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g)%s%s%s", this->fT, this->fPt.fX, this->fPt.fY,
   1009             this->fCoincident ? " coin" : "",
   1010             this->fDuplicatePt ? " dup" : "", this->fDeleted ? " deleted" : "");
   1011 }
   1012 
   1013 const SkOpAngle* SkOpSpanBase::debugAngle(int id) const {
   1014     return this->segment()->debugAngle(id);
   1015 }
   1016 
   1017 const SkOpCoincidence* SkOpSpanBase::debugCoincidence() const {
   1018     return this->segment()->debugCoincidence();
   1019 }
   1020 
   1021 SkOpContour* SkOpSpanBase::debugContour(int id) const {
   1022     return this->segment()->debugContour(id);
   1023 }
   1024 
   1025 const SkOpPtT* SkOpSpanBase::debugPtT(int id) const {
   1026     return this->segment()->debugPtT(id);
   1027 }
   1028 
   1029 const SkOpSegment* SkOpSpanBase::debugSegment(int id) const {
   1030     return this->segment()->debugSegment(id);
   1031 }
   1032 
   1033 const SkOpSpanBase* SkOpSpanBase::debugSpan(int id) const {
   1034     return this->segment()->debugSpan(id);
   1035 }
   1036 
   1037 void SkOpSpanBase::dump() const {
   1038     this->dumpHead();
   1039     this->fPtT.dump();
   1040 }
   1041 
   1042 void SkOpSpanBase::dumpHead() const {
   1043     SkDebugf("%.*s", contour()->debugIndent(), "        ");
   1044     SkDebugf("seg=%d span=%d", this->segment()->debugID(), this->debugID());
   1045     this->dumpBase();
   1046     SkDebugf("\n");
   1047 }
   1048 
   1049 void SkOpSpanBase::dumpAll() const {
   1050     this->dumpHead();
   1051     this->fPtT.dumpAll();
   1052 }
   1053 
   1054 void SkOpSpanBase::dumpBase() const {
   1055     if (this->fAligned) {
   1056         SkDebugf(" aligned");
   1057     }
   1058     if (this->fChased) {
   1059         SkDebugf(" chased");
   1060     }
   1061 #ifdef SK_DEBUG
   1062     if (this->fDebugDeleted) {
   1063         SkDebugf(" deleted");
   1064     }
   1065 #endif
   1066     if (!this->final()) {
   1067         this->upCast()->dumpSpan();
   1068     }
   1069     const SkOpSpanBase* coin = this->coinEnd();
   1070     if (this != coin) {
   1071         SkDebugf(" coinEnd seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
   1072     } else if (this->final() || !this->upCast()->isCoincident()) {
   1073         const SkOpPtT* oPt = this->ptT()->next();
   1074         SkDebugf(" seg/span=%d/%d", oPt->segment()->debugID(), oPt->span()->debugID());
   1075     }
   1076     SkDebugf(" adds=%d", fSpanAdds);
   1077 }
   1078 
   1079 void SkOpSpanBase::dumpCoin() const {
   1080     const SkOpSpan* span = this->upCastable();
   1081     if (!span) {
   1082         return;
   1083     }
   1084     if (!span->isCoincident()) {
   1085         return;
   1086     }
   1087     span->dumpCoin();
   1088 }
   1089 
   1090 void SkOpSpan::dumpCoin() const {
   1091     const SkOpSpan* coincident = fCoincident;
   1092     bool ok = debugCoinLoopCheck();
   1093     this->dump();
   1094     int loop = 0;
   1095     do {
   1096         coincident->dump();
   1097         if (!ok && ++loop > 10) {
   1098             SkDebugf("*** abort loop ***\n");
   1099             break;
   1100         }
   1101     } while ((coincident = coincident->fCoincident) != this);
   1102 }
   1103 
   1104 bool SkOpSpan::dumpSpan() const {
   1105     SkOpSpan* coin = fCoincident;
   1106     if (this != coin) {
   1107         SkDebugf(" coinStart seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
   1108     }
   1109     SkDebugf(" windVal=%d", this->windValue());
   1110     SkDebugf(" windSum=");
   1111     SkPathOpsDebug::WindingPrintf(this->windSum());
   1112     if (this->oppValue() != 0 || this->oppSum() != SK_MinS32) {
   1113         SkDebugf(" oppVal=%d", this->oppValue());
   1114         SkDebugf(" oppSum=");
   1115         SkPathOpsDebug::WindingPrintf(this->oppSum());
   1116     }
   1117     if (this->done()) {
   1118         SkDebugf(" done");
   1119     }
   1120     return this != coin;
   1121 }
   1122 
   1123 const SkOpAngle* SkOpSegment::debugAngle(int id) const {
   1124     return this->contour()->debugAngle(id);
   1125 }
   1126 
   1127 
   1128 const SkOpCoincidence* SkOpSegment::debugCoincidence() const {
   1129     return this->contour()->debugCoincidence();
   1130 }
   1131 
   1132 SkOpContour* SkOpSegment::debugContour(int id) const {
   1133     return this->contour()->debugContour(id);
   1134 }
   1135 
   1136 const SkOpPtT* SkOpSegment::debugPtT(int id) const {
   1137     return this->contour()->debugPtT(id);
   1138 }
   1139 
   1140 const SkOpSegment* SkOpSegment::debugSegment(int id) const {
   1141     return this->contour()->debugSegment(id);
   1142 }
   1143 
   1144 const SkOpSpanBase* SkOpSegment::debugSpan(int id) const {
   1145     return this->contour()->debugSpan(id);
   1146 }
   1147 
   1148 void SkOpSegment::dump() const {
   1149     SkDebugf("%.*s", contour()->debugIndent(), "        ");
   1150     this->dumpPts();
   1151     const SkOpSpanBase* span = &fHead;
   1152     contour()->indentDump();
   1153     do {
   1154         SkDebugf("%.*s span=%d ", contour()->debugIndent(), "        ", span->debugID());
   1155         span->ptT()->dumpBase();
   1156         span->dumpBase();
   1157         SkDebugf("\n");
   1158     } while (!span->final() && (span = span->upCast()->next()));
   1159     contour()->outdentDump();
   1160 }
   1161 
   1162 void SkOpSegment::dumpAll() const {
   1163     SkDebugf("%.*s", contour()->debugIndent(), "        ");
   1164     this->dumpPts();
   1165     const SkOpSpanBase* span = &fHead;
   1166     contour()->indentDump();
   1167     do {
   1168         span->dumpAll();
   1169     } while (!span->final() && (span = span->upCast()->next()));
   1170     contour()->outdentDump();
   1171 }
   1172 
   1173 void SkOpSegment::dumpAngles() const {
   1174     SkDebugf("seg=%d\n", debugID());
   1175     const SkOpSpanBase* span = &fHead;
   1176     do {
   1177         const SkOpAngle* fAngle = span->fromAngle();
   1178         const SkOpAngle* tAngle = span->final() ? nullptr : span->upCast()->toAngle();
   1179         if (fAngle) {
   1180             SkDebugf("  span=%d from=%d ", span->debugID(), fAngle->debugID());
   1181             fAngle->dumpTo(this, tAngle);
   1182         }
   1183         if (tAngle) {
   1184             SkDebugf("  span=%d to=%d   ", span->debugID(), tAngle->debugID());
   1185             tAngle->dumpTo(this, fAngle);
   1186         }
   1187     } while (!span->final() && (span = span->upCast()->next()));
   1188 }
   1189 
   1190 void SkOpSegment::dumpCoin() const {
   1191     const SkOpSpan* span = &fHead;
   1192     do {
   1193         span->dumpCoin();
   1194     } while ((span = span->next()->upCastable()));
   1195 }
   1196 
   1197 void SkOpSegment::dumpPtsInner(const char* prefix) const {
   1198     int last = SkPathOpsVerbToPoints(fVerb);
   1199     SkDebugf("%s=%d {{", prefix, this->debugID());
   1200     if (fVerb == SkPath::kConic_Verb) {
   1201         SkDebugf("{");
   1202     }
   1203     int index = 0;
   1204     do {
   1205         SkDPoint::Dump(fPts[index]);
   1206         SkDebugf(", ");
   1207     } while (++index < last);
   1208     SkDPoint::Dump(fPts[index]);
   1209     SkDebugf("}}");
   1210     if (fVerb == SkPath::kConic_Verb) {
   1211         SkDebugf(", %1.9gf}", fWeight);
   1212     }
   1213 }
   1214 
   1215 void SkOpSegment::dumpPts(const char* prefix) const {
   1216     dumpPtsInner(prefix);
   1217     SkDebugf("\n");
   1218 }
   1219 
   1220 void SkCoincidentSpans::dump() const {
   1221     SkDebugf("- seg=%d span=%d ptT=%d ", fCoinPtTStart->segment()->debugID(),
   1222         fCoinPtTStart->span()->debugID(), fCoinPtTStart->debugID());
   1223     fCoinPtTStart->dumpBase();
   1224     SkDebugf(" span=%d ptT=%d ", fCoinPtTEnd->span()->debugID(), fCoinPtTEnd->debugID());
   1225     fCoinPtTEnd->dumpBase();
   1226     if (fCoinPtTStart->segment()->operand()) {
   1227         SkDebugf(" operand");
   1228     }
   1229     if (fCoinPtTStart->segment()->isXor()) {
   1230         SkDebugf(" xor");
   1231     }
   1232     SkDebugf("\n");
   1233     SkDebugf("+ seg=%d span=%d ptT=%d ", fOppPtTStart->segment()->debugID(),
   1234         fOppPtTStart->span()->debugID(), fOppPtTStart->debugID());
   1235     fOppPtTStart->dumpBase();
   1236     SkDebugf(" span=%d ptT=%d ", fOppPtTEnd->span()->debugID(), fOppPtTEnd->debugID());
   1237     fOppPtTEnd->dumpBase();
   1238     if (fOppPtTStart->segment()->operand()) {
   1239         SkDebugf(" operand");
   1240     }
   1241     if (fOppPtTStart->segment()->isXor()) {
   1242         SkDebugf(" xor");
   1243     }
   1244     SkDebugf("\n");
   1245 }
   1246 
   1247 void SkOpCoincidence::dump() const {
   1248     SkCoincidentSpans* span = fHead;
   1249     while (span) {
   1250         span->dump();
   1251         span = span->next();
   1252     }
   1253     if (!fTop || fHead == fTop) {
   1254         return;
   1255     }
   1256     SkDebugf("top:\n");
   1257     span = fTop;
   1258     int count = 0;
   1259     while (span) {
   1260         span->dump();
   1261         span = span->next();
   1262         SkCoincidentSpans* check = fTop;
   1263         ++count;
   1264         for (int index = 0; index < count; ++index) {
   1265             if (span == check) {
   1266                 SkDebugf("(loops to #%d)\n", index);
   1267                 return;
   1268             }
   1269             check = check->next();
   1270         }
   1271     }
   1272 }
   1273 
   1274 void SkOpContour::dump() const {
   1275     SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
   1276     if (!fCount) {
   1277         return;
   1278     }
   1279     const SkOpSegment* segment = &fHead;
   1280     SkDEBUGCODE(fDebugIndent = 0);
   1281     this->indentDump();
   1282     do {
   1283         segment->dump();
   1284     } while ((segment = segment->next()));
   1285     this->outdentDump();
   1286 }
   1287 
   1288 void SkOpContour::dumpAll() const {
   1289     SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
   1290     if (!fCount) {
   1291         return;
   1292     }
   1293     const SkOpSegment* segment = &fHead;
   1294     SkDEBUGCODE(fDebugIndent = 0);
   1295     this->indentDump();
   1296     do {
   1297         segment->dumpAll();
   1298     } while ((segment = segment->next()));
   1299     this->outdentDump();
   1300 }
   1301 
   1302 
   1303 void SkOpContour::dumpAngles() const {
   1304     SkDebugf("contour=%d\n", this->debugID());
   1305     const SkOpSegment* segment = &fHead;
   1306     do {
   1307         SkDebugf("  seg=%d ", segment->debugID());
   1308         segment->dumpAngles();
   1309     } while ((segment = segment->next()));
   1310 }
   1311 
   1312 void SkOpContour::dumpPt(int index) const {
   1313     const SkOpSegment* segment = &fHead;
   1314     do {
   1315         if (segment->debugID() == index) {
   1316             segment->dumpPts();
   1317         }
   1318     } while ((segment = segment->next()));
   1319 }
   1320 
   1321 void SkOpContour::dumpPts(const char* prefix) const {
   1322     SkDebugf("contour=%d\n", this->debugID());
   1323     const SkOpSegment* segment = &fHead;
   1324     do {
   1325         SkDebugf("  %s=%d ", prefix, segment->debugID());
   1326         segment->dumpPts(prefix);
   1327     } while ((segment = segment->next()));
   1328 }
   1329 
   1330 void SkOpContour::dumpPtsX(const char* prefix) const {
   1331     if (!this->fCount) {
   1332         SkDebugf("<empty>\n");
   1333         return;
   1334     }
   1335     const SkOpSegment* segment = &fHead;
   1336     do {
   1337         segment->dumpPts(prefix);
   1338     } while ((segment = segment->next()));
   1339 }
   1340 
   1341 void SkOpContour::dumpSegment(int index) const {
   1342     debugSegment(index)->dump();
   1343 }
   1344 
   1345 void SkOpContour::dumpSegments(const char* prefix, SkPathOp op) const {
   1346     bool firstOp = false;
   1347     const SkOpContour* c = this;
   1348     do {
   1349         if (!firstOp && c->operand()) {
   1350 #if DEBUG_ACTIVE_OP
   1351             SkDebugf("op %s\n", SkPathOpsDebug::kPathOpStr[op]);
   1352 #endif
   1353             firstOp = true;
   1354         }
   1355         c->dumpPtsX(prefix);
   1356     } while ((c = c->next()));
   1357 }
   1358 
   1359 void SkOpContour::dumpSpan(int index) const {
   1360     debugSpan(index)->dump();
   1361 }
   1362 
   1363 void SkOpContour::dumpSpans() const {
   1364     SkDebugf("contour=%d\n", this->debugID());
   1365     const SkOpSegment* segment = &fHead;
   1366     do {
   1367         SkDebugf("  seg=%d ", segment->debugID());
   1368         segment->dump();
   1369     } while ((segment = segment->next()));
   1370 }
   1371 
   1372 void SkOpCurve::dump() const {
   1373     int count = SkPathOpsVerbToPoints(SkDEBUGRELEASE(fVerb, SkPath::kCubic_Verb));
   1374     SkDebugf("{{");
   1375     int index;
   1376     for (index = 0; index <= count - 1; ++index) {
   1377         SkDebugf("{%1.9gf,%1.9gf}, ", fPts[index].fX, fPts[index].fY);
   1378     }
   1379     SkDebugf("{%1.9gf,%1.9gf}}}\n", fPts[index].fX, fPts[index].fY);
   1380 }
   1381 
   1382 #ifdef SK_DEBUG
   1383 const SkOpAngle* SkOpGlobalState::debugAngle(int id) const {
   1384     const SkOpContour* contour = fContourHead;
   1385     do {
   1386         const SkOpSegment* segment = contour->first();
   1387         while (segment) {
   1388             const SkOpSpan* span = segment->head();
   1389             do {
   1390                 SkOpAngle* angle = span->fromAngle();
   1391                 if (angle && angle->debugID() == id) {
   1392                     return angle;
   1393                 }
   1394                 angle = span->toAngle();
   1395                 if (angle && angle->debugID() == id) {
   1396                     return angle;
   1397                 }
   1398             } while ((span = span->next()->upCastable()));
   1399             const SkOpSpanBase* tail = segment->tail();
   1400             SkOpAngle* angle = tail->fromAngle();
   1401             if (angle && angle->debugID() == id) {
   1402                 return angle;
   1403             }
   1404             segment = segment->next();
   1405         }
   1406     } while ((contour = contour->next()));
   1407     return nullptr;
   1408 }
   1409 
   1410 SkOpContour* SkOpGlobalState::debugContour(int id) const {
   1411     SkOpContour* contour = fContourHead;
   1412     do {
   1413         if (contour->debugID() == id) {
   1414             return contour;
   1415         }
   1416     } while ((contour = contour->next()));
   1417     return nullptr;
   1418 }
   1419 
   1420 const SkOpPtT* SkOpGlobalState::debugPtT(int id) const {
   1421     const SkOpContour* contour = fContourHead;
   1422     do {
   1423         const SkOpSegment* segment = contour->first();
   1424         while (segment) {
   1425             const SkOpSpan* span = segment->head();
   1426             do {
   1427                 const SkOpPtT* ptT = span->ptT();
   1428                 if (ptT->debugMatchID(id)) {
   1429                     return ptT;
   1430                 }
   1431             } while ((span = span->next()->upCastable()));
   1432             const SkOpSpanBase* tail = segment->tail();
   1433             const SkOpPtT* ptT = tail->ptT();
   1434             if (ptT->debugMatchID(id)) {
   1435                 return ptT;
   1436             }
   1437             segment = segment->next();
   1438         }
   1439     } while ((contour = contour->next()));
   1440     return nullptr;
   1441 }
   1442 
   1443 const SkOpSegment* SkOpGlobalState::debugSegment(int id) const {
   1444     const SkOpContour* contour = fContourHead;
   1445     do {
   1446         const SkOpSegment* segment = contour->first();
   1447         while (segment) {
   1448             if (segment->debugID() == id) {
   1449                 return segment;
   1450             }
   1451             segment = segment->next();
   1452         }
   1453     } while ((contour = contour->next()));
   1454     return nullptr;
   1455 }
   1456 
   1457 const SkOpSpanBase* SkOpGlobalState::debugSpan(int id) const {
   1458     const SkOpContour* contour = fContourHead;
   1459     do {
   1460         const SkOpSegment* segment = contour->first();
   1461         while (segment) {
   1462             const SkOpSpan* span = segment->head();
   1463             do {
   1464                 if (span->debugID() == id) {
   1465                     return span;
   1466                 }
   1467             } while ((span = span->next()->upCastable()));
   1468             const SkOpSpanBase* tail = segment->tail();
   1469             if (tail->debugID() == id) {
   1470                 return tail;
   1471             }
   1472             segment = segment->next();
   1473         }
   1474     } while ((contour = contour->next()));
   1475     return nullptr;
   1476 }
   1477 #endif
   1478 
   1479 #if DEBUG_T_SECT_DUMP > 1
   1480 int gDumpTSectNum;
   1481 #endif
   1482