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
16inline void DebugDumpDouble(double x) {
17    if (x == floor(x)) {
18        SkDebugf("%.0f", x);
19    } else {
20        SkDebugf("%1.19g", x);
21    }
22}
23
24inline void DebugDumpFloat(float x) {
25    if (x == floorf(x)) {
26        SkDebugf("%.0f", x);
27    } else {
28        SkDebugf("%1.9gf", x);
29    }
30}
31
32inline 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
38bool SkPathOpsDebug::ValidWind(int wind) {
39    return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
40}
41
42void SkPathOpsDebug::WindingPrintf(int wind) {
43    if (wind == SK_MinS32) {
44        SkDebugf("?");
45    } else {
46        SkDebugf("%d", wind);
47    }
48}
49#endif
50
51static void DumpID(int id) {
52    SkDebugf("} ");
53    if (id >= 0) {
54        SkDebugf("id=%d", id);
55    }
56    SkDebugf("\n");
57}
58
59void SkDConic::dump() const {
60    dumpInner();
61    SkDebugf("},\n");
62}
63
64void SkDConic::dumpID(int id) const {
65    dumpInner();
66    DumpID(id);
67}
68
69void SkDConic::dumpInner() const {
70    SkDebugf("{");
71    fPts.dumpInner();
72    SkDebugf("}}, %1.9gf", fWeight);
73}
74
75void SkDCubic::dump() const {
76    this->dumpInner();
77    SkDebugf("}},\n");
78}
79
80void SkDCubic::dumpID(int id) const {
81    this->dumpInner();
82    SkDebugf("}");
83    DumpID(id);
84}
85
86static inline bool double_is_NaN(double x) { return x != x; }
87
88void 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
107void SkDCurve::dump() const {
108    dumpID(-1);
109}
110
111void 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
134void SkDLine::dump() const {
135    this->dumpInner();
136    SkDebugf("}},\n");
137}
138
139void SkDLine::dumpID(int id) const {
140    this->dumpInner();
141    SkDebugf("}");
142    DumpID(id);
143}
144
145void SkDLine::dumpInner() const {
146    SkDebugf("{{");
147    fPts[0].dump();
148    SkDebugf(", ");
149    fPts[1].dump();
150}
151
152void SkDPoint::dump() const {
153    SkDebugf("{");
154    DebugDumpDouble(fX);
155    SkDebugf(", ");
156    DebugDumpDouble(fY);
157    SkDebugf("}");
158}
159
160void SkDPoint::Dump(const SkPoint& pt) {
161    SkDebugf("{");
162    DebugDumpFloat(pt.fX);
163    SkDebugf(", ");
164    DebugDumpFloat(pt.fY);
165    SkDebugf("}");
166}
167
168void SkDPoint::DumpHex(const SkPoint& pt) {
169    SkDebugf("{");
170    DebugDumpHexFloat(pt.fX);
171    SkDebugf(", ");
172    DebugDumpHexFloat(pt.fY);
173    SkDebugf("}");
174}
175
176void SkDQuad::dump() const {
177    dumpInner();
178    SkDebugf("}},\n");
179}
180
181void SkDQuad::dumpID(int id) const {
182    dumpInner();
183    SkDebugf("}");
184    DumpID(id);
185}
186
187void 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
197void 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
211const SkOpAngle* SkPathOpsDebug::DebugAngleAngle(const SkOpAngle* angle, int id) {
212    return angle->debugAngle(id);
213}
214
215SkOpContour* SkPathOpsDebug::DebugAngleContour(SkOpAngle* angle, int id) {
216    return angle->debugContour(id);
217}
218
219const SkOpPtT* SkPathOpsDebug::DebugAnglePtT(const SkOpAngle* angle, int id) {
220    return angle->debugPtT(id);
221}
222
223const SkOpSegment* SkPathOpsDebug::DebugAngleSegment(const SkOpAngle* angle, int id) {
224    return angle->debugSegment(id);
225}
226
227const SkOpSpanBase* SkPathOpsDebug::DebugAngleSpan(const SkOpAngle* angle, int id) {
228    return angle->debugSpan(id);
229}
230
231const SkOpAngle* SkPathOpsDebug::DebugContourAngle(SkOpContour* contour, int id) {
232    return contour->debugAngle(id);
233}
234
235SkOpContour* SkPathOpsDebug::DebugContourContour(SkOpContour* contour, int id) {
236    return contour->debugContour(id);
237}
238
239const SkOpPtT* SkPathOpsDebug::DebugContourPtT(SkOpContour* contour, int id) {
240    return contour->debugPtT(id);
241}
242
243const SkOpSegment* SkPathOpsDebug::DebugContourSegment(SkOpContour* contour, int id) {
244    return contour->debugSegment(id);
245}
246
247const SkOpSpanBase* SkPathOpsDebug::DebugContourSpan(SkOpContour* contour, int id) {
248    return contour->debugSpan(id);
249}
250
251const SkOpAngle* SkPathOpsDebug::DebugCoincidenceAngle(SkOpCoincidence* coin, int id) {
252    return coin->debugAngle(id);
253}
254
255SkOpContour* SkPathOpsDebug::DebugCoincidenceContour(SkOpCoincidence* coin, int id) {
256    return coin->debugContour(id);
257}
258
259const SkOpPtT* SkPathOpsDebug::DebugCoincidencePtT(SkOpCoincidence* coin, int id) {
260    return coin->debugPtT(id);
261}
262
263const SkOpSegment* SkPathOpsDebug::DebugCoincidenceSegment(SkOpCoincidence* coin, int id) {
264    return coin->debugSegment(id);
265}
266
267const SkOpSpanBase* SkPathOpsDebug::DebugCoincidenceSpan(SkOpCoincidence* coin, int id) {
268    return coin->debugSpan(id);
269}
270
271const SkOpAngle* SkPathOpsDebug::DebugPtTAngle(const SkOpPtT* ptT, int id) {
272    return ptT->debugAngle(id);
273}
274
275SkOpContour* SkPathOpsDebug::DebugPtTContour(SkOpPtT* ptT, int id) {
276    return ptT->debugContour(id);
277}
278
279const SkOpPtT* SkPathOpsDebug::DebugPtTPtT(const SkOpPtT* ptT, int id) {
280    return ptT->debugPtT(id);
281}
282
283const SkOpSegment* SkPathOpsDebug::DebugPtTSegment(const SkOpPtT* ptT, int id) {
284    return ptT->debugSegment(id);
285}
286
287const SkOpSpanBase* SkPathOpsDebug::DebugPtTSpan(const SkOpPtT* ptT, int id) {
288    return ptT->debugSpan(id);
289}
290
291const SkOpAngle* SkPathOpsDebug::DebugSegmentAngle(const SkOpSegment* span, int id) {
292    return span->debugAngle(id);
293}
294
295SkOpContour* SkPathOpsDebug::DebugSegmentContour(SkOpSegment* span, int id) {
296    return span->debugContour(id);
297}
298
299const SkOpPtT* SkPathOpsDebug::DebugSegmentPtT(const SkOpSegment* span, int id) {
300    return span->debugPtT(id);
301}
302
303const SkOpSegment* SkPathOpsDebug::DebugSegmentSegment(const SkOpSegment* span, int id) {
304    return span->debugSegment(id);
305}
306
307const SkOpSpanBase* SkPathOpsDebug::DebugSegmentSpan(const SkOpSegment* span, int id) {
308    return span->debugSpan(id);
309}
310
311const SkOpAngle* SkPathOpsDebug::DebugSpanAngle(const SkOpSpanBase* span, int id) {
312    return span->debugAngle(id);
313}
314
315SkOpContour* SkPathOpsDebug::DebugSpanContour(SkOpSpanBase* span, int id) {
316    return span->debugContour(id);
317}
318
319const SkOpPtT* SkPathOpsDebug::DebugSpanPtT(const SkOpSpanBase* span, int id) {
320    return span->debugPtT(id);
321}
322
323const SkOpSegment* SkPathOpsDebug::DebugSpanSegment(const SkOpSpanBase* span, int id) {
324    return span->debugSegment(id);
325}
326
327const SkOpSpanBase* SkPathOpsDebug::DebugSpanSpan(const SkOpSpanBase* span, int id) {
328    return span->debugSpan(id);
329}
330
331#if DEBUG_COIN
332void SkPathOpsDebug::DumpCoinDict() {
333    gCoinSumChangedDict.dump("unused coin algorithm", false);
334    gCoinSumVisitedDict.dump("visited coin function", true);
335}
336
337void 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
351void SkOpContour::dumpContours() const {
352    SkOpContour* contour = this->globalState()->contourHead();
353    do {
354        contour->dump();
355    } while ((contour = contour->next()));
356}
357
358void SkOpContour::dumpContoursAll() const {
359    SkOpContour* contour = this->globalState()->contourHead();
360    do {
361        contour->dumpAll();
362    } while ((contour = contour->next()));
363}
364
365void SkOpContour::dumpContoursAngles() const {
366    SkOpContour* contour = this->globalState()->contourHead();
367    do {
368        contour->dumpAngles();
369    } while ((contour = contour->next()));
370}
371
372void SkOpContour::dumpContoursPts() const {
373    SkOpContour* contour = this->globalState()->contourHead();
374    do {
375        contour->dumpPts();
376    } while ((contour = contour->next()));
377}
378
379void SkOpContour::dumpContoursPt(int segmentID) const {
380    SkOpContour* contour = this->globalState()->contourHead();
381    do {
382        contour->dumpPt(segmentID);
383    } while ((contour = contour->next()));
384}
385
386void SkOpContour::dumpContoursSegment(int segmentID) const {
387    SkOpContour* contour = this->globalState()->contourHead();
388    do {
389        contour->dumpSegment(segmentID);
390    } while ((contour = contour->next()));
391}
392
393void SkOpContour::dumpContoursSpan(int spanID) const {
394    SkOpContour* contour = this->globalState()->contourHead();
395    do {
396        contour->dumpSpan(spanID);
397    } while ((contour = contour->next()));
398}
399
400void SkOpContour::dumpContoursSpans() const {
401    SkOpContour* contour = this->globalState()->contourHead();
402    do {
403        contour->dumpSpans();
404    } while ((contour = contour->next()));
405}
406
407template <typename TCurve, typename OppCurve>
408const SkTSpan<TCurve, OppCurve>* DebugSpan(const SkTSect<TCurve, OppCurve>* sect, int id) {
409    return sect->debugSpan(id);
410}
411
412void DontCallDebugSpan(int id);
413void 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
437template <typename TCurve, typename OppCurve>
438const SkTSpan<TCurve, OppCurve>* DebugT(const SkTSect<TCurve, OppCurve>* sect, double t) {
439    return sect->debugT(t);
440}
441
442void DontCallDebugT(double t);
443void 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
467template <typename TCurve, typename OppCurve>
468void Dump(const SkTSect<TCurve, OppCurve>* sect) {
469    sect->dump();
470}
471
472void DontCallDumpTSect();
473void 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
497template <typename TCurve, typename OppCurve>
498void DumpBoth(SkTSect<TCurve, OppCurve>* sect1, SkTSect<OppCurve, TCurve>* sect2) {
499    sect1->dumpBoth(sect2);
500}
501
502void DontCallDumpBoth();
503void 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
527template <typename TCurve, typename OppCurve>
528void DumpBounded(SkTSect<TCurve, OppCurve>* sect1, int id) {
529    sect1->dumpBounded(id);
530}
531
532void DontCallDumpBounded();
533void 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
557template <typename TCurve, typename OppCurve>
558void DumpBounds(SkTSect<TCurve, OppCurve>* sect1) {
559    sect1->dumpBounds();
560}
561
562void DontCallDumpBounds();
563void 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
587template <typename TCurve, typename OppCurve>
588void DumpCoin(SkTSect<TCurve, OppCurve>* sect1) {
589    sect1->dumpCoin();
590}
591
592void DontCallDumpCoin();
593void 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
617template <typename TCurve, typename OppCurve>
618void DumpCoinCurves(SkTSect<TCurve, OppCurve>* sect1) {
619    sect1->dumpCoinCurves();
620}
621
622void DontCallDumpCoinCurves();
623void 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
647template <typename TCurve, typename OppCurve>
648void DumpCurves(const SkTSect<TCurve, OppCurve>* sect) {
649    sect->dumpCurves();
650}
651
652void DontCallDumpCurves();
653void 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
677template <typename TCurve, typename OppCurve>
678void Dump(const SkTSpan<TCurve, OppCurve>* span) {
679    span->dump();
680}
681
682void DontCallDumpTSpan();
683void 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
704template <typename TCurve, typename OppCurve>
705void DumpAll(const SkTSpan<TCurve, OppCurve>* span) {
706    span->dumpAll();
707}
708
709void DontCallDumpSpanAll();
710void 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
731template <typename TCurve, typename OppCurve>
732void DumpBounded(const SkTSpan<TCurve, OppCurve>* span) {
733    span->dumpBounded(0);
734}
735
736void DontCallDumpSpanBounded();
737void 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
758template <typename TCurve, typename OppCurve>
759void DumpCoin(const SkTSpan<TCurve, OppCurve>* span) {
760    span->dumpCoin();
761}
762
763void DontCallDumpSpanCoin();
764void 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
785static 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
793static void dumpTestTrailer() {
794    SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
795    SkDebugf("    var testDivs = [\n");
796}
797
798static 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
806void 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
814void DumpT(const SkDQuad& quad, double t) {
815    SkDLine line = {{quad.ptAtT(t), quad[0]}};
816    line.dump();
817}
818
819const SkOpAngle* SkOpAngle::debugAngle(int id) const {
820    return this->segment()->debugAngle(id);
821}
822
823const SkOpCoincidence* SkOpAngle::debugCoincidence() const {
824    return this->segment()->debugCoincidence();
825}
826
827SkOpContour* SkOpAngle::debugContour(int id) const {
828    return this->segment()->debugContour(id);
829}
830
831const SkOpPtT* SkOpAngle::debugPtT(int id) const {
832    return this->segment()->debugPtT(id);
833}
834
835const SkOpSegment* SkOpAngle::debugSegment(int id) const {
836    return this->segment()->debugSegment(id);
837}
838
839int SkOpAngle::debugSign() const {
840    SkASSERT(fStart->t() != fEnd->t());
841    return fStart->t() < fEnd->t() ? -1 : 1;
842}
843
844const SkOpSpanBase* SkOpAngle::debugSpan(int id) const {
845    return this->segment()->debugSpan(id);
846}
847
848void SkOpAngle::dump() const {
849    dumpOne(true);
850    SkDebugf("\n");
851}
852
853void 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
892void 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
913void 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
922void 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
932void 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
945bool 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
957const SkOpAngle* SkOpPtT::debugAngle(int id) const {
958    return this->span()->debugAngle(id);
959}
960
961SkOpContour* SkOpPtT::debugContour(int id) const {
962    return this->span()->debugContour(id);
963}
964
965const SkOpCoincidence* SkOpPtT::debugCoincidence() const {
966    return this->span()->debugCoincidence();
967}
968
969const SkOpPtT* SkOpPtT::debugPtT(int id) const {
970    return this->span()->debugPtT(id);
971}
972
973const SkOpSegment* SkOpPtT::debugSegment(int id) const {
974    return this->span()->debugSegment(id);
975}
976
977const SkOpSpanBase* SkOpPtT::debugSpan(int id) const {
978    return this->span()->debugSpan(id);
979}
980
981void 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
988void 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
1007void 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
1013const SkOpAngle* SkOpSpanBase::debugAngle(int id) const {
1014    return this->segment()->debugAngle(id);
1015}
1016
1017const SkOpCoincidence* SkOpSpanBase::debugCoincidence() const {
1018    return this->segment()->debugCoincidence();
1019}
1020
1021SkOpContour* SkOpSpanBase::debugContour(int id) const {
1022    return this->segment()->debugContour(id);
1023}
1024
1025const SkOpPtT* SkOpSpanBase::debugPtT(int id) const {
1026    return this->segment()->debugPtT(id);
1027}
1028
1029const SkOpSegment* SkOpSpanBase::debugSegment(int id) const {
1030    return this->segment()->debugSegment(id);
1031}
1032
1033const SkOpSpanBase* SkOpSpanBase::debugSpan(int id) const {
1034    return this->segment()->debugSpan(id);
1035}
1036
1037void SkOpSpanBase::dump() const {
1038    this->dumpHead();
1039    this->fPtT.dump();
1040}
1041
1042void 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
1049void SkOpSpanBase::dumpAll() const {
1050    this->dumpHead();
1051    this->fPtT.dumpAll();
1052}
1053
1054void 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
1079void 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
1090void 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
1104bool 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
1123const SkOpAngle* SkOpSegment::debugAngle(int id) const {
1124    return this->contour()->debugAngle(id);
1125}
1126
1127
1128const SkOpCoincidence* SkOpSegment::debugCoincidence() const {
1129    return this->contour()->debugCoincidence();
1130}
1131
1132SkOpContour* SkOpSegment::debugContour(int id) const {
1133    return this->contour()->debugContour(id);
1134}
1135
1136const SkOpPtT* SkOpSegment::debugPtT(int id) const {
1137    return this->contour()->debugPtT(id);
1138}
1139
1140const SkOpSegment* SkOpSegment::debugSegment(int id) const {
1141    return this->contour()->debugSegment(id);
1142}
1143
1144const SkOpSpanBase* SkOpSegment::debugSpan(int id) const {
1145    return this->contour()->debugSpan(id);
1146}
1147
1148void 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
1162void 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
1173void 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
1190void SkOpSegment::dumpCoin() const {
1191    const SkOpSpan* span = &fHead;
1192    do {
1193        span->dumpCoin();
1194    } while ((span = span->next()->upCastable()));
1195}
1196
1197void 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
1215void SkOpSegment::dumpPts(const char* prefix) const {
1216    dumpPtsInner(prefix);
1217    SkDebugf("\n");
1218}
1219
1220void 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
1247void 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
1274void 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
1288void 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
1303void 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
1312void 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
1321void 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
1330void 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
1341void SkOpContour::dumpSegment(int index) const {
1342    debugSegment(index)->dump();
1343}
1344
1345void 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
1359void SkOpContour::dumpSpan(int index) const {
1360    debugSpan(index)->dump();
1361}
1362
1363void 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
1372void 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
1383const 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
1410SkOpContour* 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
1420const 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
1443const 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
1457const 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
1480int gDumpTSectNum;
1481#endif
1482