• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkPath.h"
9 #include "include/core/SkPoint.h"
10 #include "include/core/SkTypes.h"
11 #include "include/pathops/SkPathOps.h"
12 #include "include/private/base/SkDebug.h"
13 #include "include/private/base/SkFloatBits.h"
14 #include "include/private/base/SkMath.h"
15 #include "src/base/SkArenaAlloc.h"
16 #include "src/pathops/SkIntersections.h"
17 #include "src/pathops/SkOpAngle.h"
18 #include "src/pathops/SkOpCoincidence.h"
19 #include "src/pathops/SkOpContour.h"
20 #include "src/pathops/SkOpSegment.h"
21 #include "src/pathops/SkOpSpan.h"
22 #include "src/pathops/SkPathOpsConic.h"
23 #include "src/pathops/SkPathOpsCubic.h"
24 #include "src/pathops/SkPathOpsCurve.h"
25 #include "src/pathops/SkPathOpsLine.h"
26 #include "src/pathops/SkPathOpsPoint.h"
27 #include "src/pathops/SkPathOpsQuad.h"
28 #include "src/pathops/SkPathOpsRect.h"
29 #include "src/pathops/SkPathOpsTSect.h"
30 #include "src/pathops/SkPathOpsTypes.h"
31 #include "tests/PathOpsDebug.h"
32 
33 #include <algorithm>
34 #include <cfloat>
35 #include <cmath>
36 #include <cstdint>
37 
38 bool PathOpsDebug::gJson;
39 bool PathOpsDebug::gMarkJsonFlaky;
40 bool PathOpsDebug::gOutFirst;
41 bool PathOpsDebug::gCheckForDuplicateNames;
42 bool PathOpsDebug::gOutputSVG;
43 FILE* PathOpsDebug::gOut;
44 
DebugDumpDouble(double x)45 inline void DebugDumpDouble(double x) {
46     if (x == floor(x)) {
47         SkDebugf("%.0f", x);
48     } else {
49         SkDebugf("%1.19g", x);
50     }
51 }
52 
DebugDumpFloat(float x)53 inline void DebugDumpFloat(float x) {
54     if (x == floorf(x)) {
55         SkDebugf("%.0f", x);
56     } else {
57         SkDebugf("%1.9gf", x);
58     }
59 }
60 
DebugDumpHexFloat(float x)61 inline void DebugDumpHexFloat(float x) {
62     SkDebugf("SkBits2Float(0x%08x)", SkFloat2Bits(x));
63 }
64 
65 // if not defined by PathOpsDebug.cpp ...
66 #if !defined SK_DEBUG && FORCE_RELEASE
ValidWind(int wind)67 bool SkPathOpsDebug::ValidWind(int wind) {
68     return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
69 }
70 
WindingPrintf(int wind)71 void SkPathOpsDebug::WindingPrintf(int wind) {
72     if (wind == SK_MinS32) {
73         SkDebugf("?");
74     } else {
75         SkDebugf("%d", wind);
76     }
77 }
78 #endif
79 
DumpID(int id)80 static void DumpID(int id) {
81     SkDebugf("} ");
82     if (id >= 0) {
83         SkDebugf("id=%d", id);
84     }
85     SkDebugf("\n");
86 }
87 
dump() const88 void SkDConic::dump() const {
89     dumpInner();
90     SkDebugf("},\n");
91 }
92 
dumpID(int id) const93 void SkDConic::dumpID(int id) const {
94     dumpInner();
95     DumpID(id);
96 }
97 
dumpInner() const98 void SkDConic::dumpInner() const {
99     SkDebugf("{");
100     fPts.dumpInner();
101     SkDebugf("}}, %1.9gf", fWeight);
102 }
103 
dump() const104 void SkDCubic::dump() const {
105     this->dumpInner();
106     SkDebugf("}},\n");
107 }
108 
dumpID(int id) const109 void SkDCubic::dumpID(int id) const {
110     this->dumpInner();
111     SkDebugf("}");
112     DumpID(id);
113 }
114 
double_is_NaN(double x)115 static inline bool double_is_NaN(double x) { return x != x; }
116 
dumpInner() const117 void SkDCubic::dumpInner() const {
118     SkDebugf("{{");
119     int index = 0;
120     do {
121         if (index != 0) {
122             if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
123                 return;
124             }
125             SkDebugf(", ");
126         }
127         fPts[index].dump();
128     } while (++index < 3);
129     if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
130         return;
131     }
132     SkDebugf(", ");
133     fPts[index].dump();
134 }
135 
dump() const136 void SkDCurve::dump() const {
137     dumpID(-1);
138 }
139 
dumpID(int id) const140 void SkDCurve::dumpID(int id) const {
141 #ifndef SK_RELEASE
142     switch(fVerb) {
143         case SkPath::kLine_Verb:
144             fLine.dumpID(id);
145             break;
146         case SkPath::kQuad_Verb:
147             fQuad.dumpID(id);
148             break;
149         case SkPath::kConic_Verb:
150             fConic.dumpID(id);
151             break;
152         case SkPath::kCubic_Verb:
153             fCubic.dumpID(id);
154             break;
155         default:
156             SkASSERT(0);
157     }
158 #else
159     fCubic.dumpID(id);
160 #endif
161 }
162 
dump() const163 void SkDLine::dump() const {
164     this->dumpInner();
165     SkDebugf("}},\n");
166 }
167 
dumpID(int id) const168 void SkDLine::dumpID(int id) const {
169     this->dumpInner();
170     SkDebugf("}");
171     DumpID(id);
172 }
173 
dumpInner() const174 void SkDLine::dumpInner() const {
175     SkDebugf("{{");
176     fPts[0].dump();
177     SkDebugf(", ");
178     fPts[1].dump();
179 }
180 
dump() const181 void SkDPoint::dump() const {
182     SkDebugf("{");
183     DebugDumpDouble(fX);
184     SkDebugf(", ");
185     DebugDumpDouble(fY);
186     SkDebugf("}");
187 }
188 
Dump(const SkPoint & pt)189 void SkDPoint::Dump(const SkPoint& pt) {
190     SkDebugf("{");
191     DebugDumpFloat(pt.fX);
192     SkDebugf(", ");
193     DebugDumpFloat(pt.fY);
194     SkDebugf("}");
195 }
196 
DumpHex(const SkPoint & pt)197 void SkDPoint::DumpHex(const SkPoint& pt) {
198     SkDebugf("{");
199     DebugDumpHexFloat(pt.fX);
200     SkDebugf(", ");
201     DebugDumpHexFloat(pt.fY);
202     SkDebugf("}");
203 }
204 
dump() const205 void SkDQuad::dump() const {
206     dumpInner();
207     SkDebugf("}},\n");
208 }
209 
dumpID(int id) const210 void SkDQuad::dumpID(int id) const {
211     dumpInner();
212     SkDebugf("}");
213     DumpID(id);
214 }
215 
dumpInner() const216 void SkDQuad::dumpInner() const {
217     SkDebugf("{{");
218     int index = 0;
219     do {
220         fPts[index].dump();
221         SkDebugf(", ");
222     } while (++index < 2);
223     fPts[index].dump();
224 }
225 
dump() const226 void SkIntersections::dump() const {
227     SkDebugf("used=%d of %d", fUsed, fMax);
228     for (int index = 0; index < fUsed; ++index) {
229         SkDebugf(" t=(%s%1.9g,%s%1.9g) pt=(%1.9g,%1.9g)",
230                 fIsCoincident[0] & (1 << index) ? "*" : "", fT[0][index],
231                 fIsCoincident[1] & (1 << index) ? "*" : "", fT[1][index],
232                 fPt[index].fX, fPt[index].fY);
233         if (index < 2 && fNearlySame[index]) {
234             SkDebugf(" pt2=(%1.9g,%1.9g)",fPt2[index].fX, fPt2[index].fY);
235         }
236     }
237     SkDebugf("\n");
238 }
239 
AngleAngle(const SkOpAngle * angle,int id)240 const SkOpAngle* AngleAngle(const SkOpAngle* angle, int id) {
241     return angle->debugAngle(id);
242 }
243 
AngleContour(SkOpAngle * angle,int id)244 SkOpContour* AngleContour(SkOpAngle* angle, int id) {
245     return angle->debugContour(id);
246 }
247 
AnglePtT(const SkOpAngle * angle,int id)248 const SkOpPtT* AnglePtT(const SkOpAngle* angle, int id) {
249     return angle->debugPtT(id);
250 }
251 
AngleSegment(const SkOpAngle * angle,int id)252 const SkOpSegment* AngleSegment(const SkOpAngle* angle, int id) {
253     return angle->debugSegment(id);
254 }
255 
AngleSpan(const SkOpAngle * angle,int id)256 const SkOpSpanBase* AngleSpan(const SkOpAngle* angle, int id) {
257     return angle->debugSpan(id);
258 }
259 
ContourAngle(SkOpContour * contour,int id)260 const SkOpAngle* ContourAngle(SkOpContour* contour, int id) {
261     return contour->debugAngle(id);
262 }
263 
ContourContour(SkOpContour * contour,int id)264 SkOpContour* ContourContour(SkOpContour* contour, int id) {
265     return contour->debugContour(id);
266 }
267 
ContourPtT(SkOpContour * contour,int id)268 const SkOpPtT* ContourPtT(SkOpContour* contour, int id) {
269     return contour->debugPtT(id);
270 }
271 
ContourSegment(SkOpContour * contour,int id)272 const SkOpSegment* ContourSegment(SkOpContour* contour, int id) {
273     return contour->debugSegment(id);
274 }
275 
ContourSpan(SkOpContour * contour,int id)276 const SkOpSpanBase* ContourSpan(SkOpContour* contour, int id) {
277     return contour->debugSpan(id);
278 }
279 
CoincidenceAngle(SkOpCoincidence * coin,int id)280 const SkOpAngle* CoincidenceAngle(SkOpCoincidence* coin, int id) {
281     return coin->debugAngle(id);
282 }
283 
CoincidenceContour(SkOpCoincidence * coin,int id)284 SkOpContour* CoincidenceContour(SkOpCoincidence* coin, int id) {
285     return coin->debugContour(id);
286 }
287 
CoincidencePtT(SkOpCoincidence * coin,int id)288 const SkOpPtT* CoincidencePtT(SkOpCoincidence* coin, int id) {
289     return coin->debugPtT(id);
290 }
291 
CoincidenceSegment(SkOpCoincidence * coin,int id)292 const SkOpSegment* CoincidenceSegment(SkOpCoincidence* coin, int id) {
293     return coin->debugSegment(id);
294 }
295 
CoincidenceSpan(SkOpCoincidence * coin,int id)296 const SkOpSpanBase* CoincidenceSpan(SkOpCoincidence* coin, int id) {
297     return coin->debugSpan(id);
298 }
299 
PtTAngle(const SkOpPtT * ptT,int id)300 const SkOpAngle* PtTAngle(const SkOpPtT* ptT, int id) {
301     return ptT->debugAngle(id);
302 }
303 
PtTContour(SkOpPtT * ptT,int id)304 SkOpContour* PtTContour(SkOpPtT* ptT, int id) {
305     return ptT->debugContour(id);
306 }
307 
PtTPtT(const SkOpPtT * ptT,int id)308 const SkOpPtT* PtTPtT(const SkOpPtT* ptT, int id) {
309     return ptT->debugPtT(id);
310 }
311 
PtTSegment(const SkOpPtT * ptT,int id)312 const SkOpSegment* PtTSegment(const SkOpPtT* ptT, int id) {
313     return ptT->debugSegment(id);
314 }
315 
PtTSpan(const SkOpPtT * ptT,int id)316 const SkOpSpanBase* PtTSpan(const SkOpPtT* ptT, int id) {
317     return ptT->debugSpan(id);
318 }
319 
SegmentAngle(const SkOpSegment * span,int id)320 const SkOpAngle* SegmentAngle(const SkOpSegment* span, int id) {
321     return span->debugAngle(id);
322 }
323 
SegmentContour(SkOpSegment * span,int id)324 SkOpContour* SegmentContour(SkOpSegment* span, int id) {
325     return span->debugContour(id);
326 }
327 
SegmentPtT(const SkOpSegment * span,int id)328 const SkOpPtT* SegmentPtT(const SkOpSegment* span, int id) {
329     return span->debugPtT(id);
330 }
331 
SegmentSegment(const SkOpSegment * span,int id)332 const SkOpSegment* SegmentSegment(const SkOpSegment* span, int id) {
333     return span->debugSegment(id);
334 }
335 
SegmentSpan(const SkOpSegment * span,int id)336 const SkOpSpanBase* SegmentSpan(const SkOpSegment* span, int id) {
337     return span->debugSpan(id);
338 }
339 
SpanAngle(const SkOpSpanBase * span,int id)340 const SkOpAngle* SpanAngle(const SkOpSpanBase* span, int id) {
341     return span->debugAngle(id);
342 }
343 
SpanContour(SkOpSpanBase * span,int id)344 SkOpContour* SpanContour(SkOpSpanBase* span, int id) {
345     return span->debugContour(id);
346 }
347 
SpanPtT(const SkOpSpanBase * span,int id)348 const SkOpPtT* SpanPtT(const SkOpSpanBase* span, int id) {
349     return span->debugPtT(id);
350 }
351 
SpanSegment(const SkOpSpanBase * span,int id)352 const SkOpSegment* SpanSegment(const SkOpSpanBase* span, int id) {
353     return span->debugSegment(id);
354 }
355 
SpanSpan(const SkOpSpanBase * span,int id)356 const SkOpSpanBase* SpanSpan(const SkOpSpanBase* span, int id) {
357     return span->debugSpan(id);
358 }
359 
360 #if DEBUG_COIN
DumpCoinDict()361 void SkPathOpsDebug::DumpCoinDict() {
362     SkPathOpsDebug::gCoinSumChangedDict.dump("unused coin algorithm", false);
363     SkPathOpsDebug::gCoinSumVisitedDict.dump("visited coin function", true);
364 }
365 
dump(const char * str,bool visitCheck) const366 void SkPathOpsDebug::CoinDict::dump(const char* str, bool visitCheck) const {
367     int count = fDict.count();
368     for (int index = 0; index < count; ++index) {
369         const auto& entry = fDict[index];
370         if (visitCheck || entry.fGlitchType == kUninitialized_Glitch) {
371             SkDebugf("%s %s : line %d iteration %d", str, entry.fFunctionName,
372                     entry.fLineNumber, entry.fIteration);
373             DumpGlitchType(entry.fGlitchType);
374             SkDebugf("\n");
375         }
376     }
377 }
378 #endif
379 
dumpContours() const380 void SkOpContour::dumpContours() const {
381     SkOpContour* contour = this->globalState()->contourHead();
382     do {
383         contour->dump();
384     } while ((contour = contour->next()));
385 }
386 
dumpContoursAll() const387 void SkOpContour::dumpContoursAll() const {
388     SkOpContour* contour = this->globalState()->contourHead();
389     do {
390         contour->dumpAll();
391     } while ((contour = contour->next()));
392 }
393 
dumpContoursAngles() const394 void SkOpContour::dumpContoursAngles() const {
395     SkOpContour* contour = this->globalState()->contourHead();
396     do {
397         contour->dumpAngles();
398     } while ((contour = contour->next()));
399 }
400 
dumpContoursPts() const401 void SkOpContour::dumpContoursPts() const {
402     SkOpContour* contour = this->globalState()->contourHead();
403     do {
404         contour->dumpPts();
405     } while ((contour = contour->next()));
406 }
407 
dumpContoursPt(int segmentID) const408 void SkOpContour::dumpContoursPt(int segmentID) const {
409     SkOpContour* contour = this->globalState()->contourHead();
410     do {
411         contour->dumpPt(segmentID);
412     } while ((contour = contour->next()));
413 }
414 
dumpContoursSegment(int segmentID) const415 void SkOpContour::dumpContoursSegment(int segmentID) const {
416     SkOpContour* contour = this->globalState()->contourHead();
417     do {
418         contour->dumpSegment(segmentID);
419     } while ((contour = contour->next()));
420 }
421 
dumpContoursSpan(int spanID) const422 void SkOpContour::dumpContoursSpan(int spanID) const {
423     SkOpContour* contour = this->globalState()->contourHead();
424     do {
425         contour->dumpSpan(spanID);
426     } while ((contour = contour->next()));
427 }
428 
dumpContoursSpans() const429 void SkOpContour::dumpContoursSpans() const {
430     SkOpContour* contour = this->globalState()->contourHead();
431     do {
432         contour->dumpSpans();
433     } while ((contour = contour->next()));
434 }
435 
436 #ifdef SK_DEBUG
DebugSpan(const SkTSect * sect,int id)437 const SkTSpan* DebugSpan(const SkTSect* sect, int id) {
438     return sect->debugSpan(id);
439 }
440 
DebugT(const SkTSect * sect,double t)441 const SkTSpan* DebugT(const SkTSect* sect, double t) {
442     return sect->debugT(t);
443 }
444 #endif
445 
Dump(const SkTSect * sect)446 void Dump(const SkTSect* sect) {
447     sect->dump();
448 }
449 
DumpBoth(SkTSect * sect1,SkTSect * sect2)450 void DumpBoth(SkTSect* sect1, SkTSect* sect2) {
451     sect1->dumpBoth(sect2);
452 }
453 
DumpBounded(SkTSect * sect1,int id)454 void DumpBounded(SkTSect* sect1, int id) {
455     sect1->dumpBounded(id);
456 }
457 
DumpBounds(SkTSect * sect1)458 void DumpBounds(SkTSect* sect1) {
459     sect1->dumpBounds();
460 }
461 
DumpCoin(SkTSect * sect1)462 void DumpCoin(SkTSect* sect1) {
463     sect1->dumpCoin();
464 }
465 
DumpCoinCurves(SkTSect * sect1)466 void DumpCoinCurves(SkTSect* sect1) {
467     sect1->dumpCoinCurves();
468 }
469 
DumpCurves(const SkTSect * sect)470 void DumpCurves(const SkTSect* sect) {
471     sect->dumpCurves();
472 }
473 
Dump(const SkTSpan * span)474 void Dump(const SkTSpan* span) {
475     span->dump();
476 }
477 
DumpAll(const SkTSpan * span)478 void DumpAll(const SkTSpan* span) {
479     span->dumpAll();
480 }
481 
DumpBounded(const SkTSpan * span)482 void DumpBounded(const SkTSpan* span) {
483     span->dumpBounded(0);
484 }
485 
DumpCoin(const SkTSpan * span)486 void DumpCoin(const SkTSpan* span) {
487     span->dumpCoin();
488 }
489 
dumpTestCase(const SkDQuad & quad1,const SkDQuad & quad2,int testNo)490 static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
491     SkDebugf("\n<div id=\"quad%d\">\n", testNo);
492     quad1.dumpInner();
493     SkDebugf("}}, ");
494     quad2.dump();
495     SkDebugf("</div>\n\n");
496 }
497 
dumpTestTrailer()498 static void dumpTestTrailer() {
499     SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
500     SkDebugf("    var testDivs = [\n");
501 }
502 
dumpTestList(int testNo,double min)503 static void dumpTestList(int testNo, double min) {
504     SkDebugf("        quad%d,", testNo);
505     if (min > 0) {
506         SkDebugf("  // %1.9g", min);
507     }
508     SkDebugf("\n");
509 }
510 
DumpQ(const SkDQuad & quad1,const SkDQuad & quad2,int testNo)511 void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
512     SkDebugf("\n");
513     dumpTestCase(quad1, quad2, testNo);
514     dumpTestTrailer();
515     dumpTestList(testNo, 0);
516     SkDebugf("\n");
517 }
518 
DumpT(const SkDQuad & quad,double t)519 void DumpT(const SkDQuad& quad, double t) {
520     SkDLine line = {{quad.ptAtT(t), quad[0]}};
521     line.dump();
522 }
523 
debugAngle(int id) const524 const SkOpAngle* SkOpAngle::debugAngle(int id) const {
525     return this->segment()->debugAngle(id);
526 }
527 
debugCoincidence() const528 const SkOpCoincidence* SkOpAngle::debugCoincidence() const {
529     return this->segment()->debugCoincidence();
530 }
531 
debugContour(int id) const532 SkOpContour* SkOpAngle::debugContour(int id) const {
533     return this->segment()->debugContour(id);
534 }
535 
debugPtT(int id) const536 const SkOpPtT* SkOpAngle::debugPtT(int id) const {
537     return this->segment()->debugPtT(id);
538 }
539 
debugSegment(int id) const540 const SkOpSegment* SkOpAngle::debugSegment(int id) const {
541     return this->segment()->debugSegment(id);
542 }
543 
debugSign() const544 int SkOpAngle::debugSign() const {
545     SkASSERT(fStart->t() != fEnd->t());
546     return fStart->t() < fEnd->t() ? -1 : 1;
547 }
548 
debugSpan(int id) const549 const SkOpSpanBase* SkOpAngle::debugSpan(int id) const {
550     return this->segment()->debugSpan(id);
551 }
552 
dump() const553 void SkOpAngle::dump() const {
554     dumpOne(true);
555     SkDebugf("\n");
556 }
557 
dumpOne(bool functionHeader) const558 void SkOpAngle::dumpOne(bool functionHeader) const {
559 //    fSegment->debugValidate();
560     const SkOpSegment* segment = this->segment();
561     const SkOpSpan& mSpan = *fStart->starter(fEnd);
562     if (functionHeader) {
563         SkDebugf("%s ", __FUNCTION__);
564     }
565     SkDebugf("[%d", segment->debugID());
566     SkDebugf("/%d", debugID());
567     SkDebugf("] next=");
568     if (fNext) {
569         SkDebugf("%d", fNext->fStart->segment()->debugID());
570         SkDebugf("/%d", fNext->debugID());
571     } else {
572         SkDebugf("?");
573     }
574     SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
575     SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fStart->t(), fStart->debugID(),
576                 fEnd->t(), fEnd->debugID());
577     SkDebugf(" sgn=%d windVal=%d", this->debugSign(), mSpan.windValue());
578 
579     SkDebugf(" windSum=");
580     SkPathOpsDebug::WindingPrintf(mSpan.windSum());
581     if (mSpan.oppValue() != 0 || mSpan.oppSum() != SK_MinS32) {
582         SkDebugf(" oppVal=%d", mSpan.oppValue());
583         SkDebugf(" oppSum=");
584         SkPathOpsDebug::WindingPrintf(mSpan.oppSum());
585     }
586     if (mSpan.done()) {
587         SkDebugf(" done");
588     }
589     if (unorderable()) {
590         SkDebugf(" unorderable");
591     }
592     if (segment->operand()) {
593         SkDebugf(" operand");
594     }
595 }
596 
dumpTo(const SkOpSegment * segment,const SkOpAngle * to) const597 void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
598     const SkOpAngle* first = this;
599     const SkOpAngle* next = this;
600     const char* indent = "";
601     do {
602         SkDebugf("%s", indent);
603         next->dumpOne(false);
604         if (segment == next->fStart->segment()) {
605             if (this == fNext) {
606                 SkDebugf(" << from");
607             }
608             if (to == fNext) {
609                 SkDebugf(" << to");
610             }
611         }
612         SkDebugf("\n");
613         indent = "           ";
614         next = next->fNext;
615     } while (next && next != first);
616 }
617 
dumpCurves() const618 void SkOpAngle::dumpCurves() const {
619     const SkOpAngle* first = this;
620     const SkOpAngle* next = this;
621     do {
622         next->fPart.fCurve.dumpID(next->segment()->debugID());
623         next = next->fNext;
624     } while (next && next != first);
625 }
626 
dumpLoop() const627 void SkOpAngle::dumpLoop() const {
628     const SkOpAngle* first = this;
629     const SkOpAngle* next = this;
630     do {
631         next->dumpOne(false);
632         SkDebugf("\n");
633         next = next->fNext;
634     } while (next && next != first);
635 }
636 
dumpTest() const637 void SkOpAngle::dumpTest() const {
638     const SkOpAngle* first = this;
639     const SkOpAngle* next = this;
640     do {
641         SkDebugf("{ ");
642         SkOpSegment* segment = next->segment();
643         segment->dumpPts();
644         SkDebugf(", %d, %1.9g, %1.9g, {} },\n", SkPathOpsVerbToPoints(segment->verb()) + 1,
645                 next->start()->t(), next->end()->t());
646         next = next->fNext;
647     } while (next && next != first);
648 }
649 
debugMatchID(int id) const650 bool SkOpPtT::debugMatchID(int id) const {
651     int limit = this->debugLoopLimit(false);
652     int loop = 0;
653     const SkOpPtT* ptT = this;
654     do {
655         if (ptT->debugID() == id) {
656             return true;
657         }
658     } while ((!limit || ++loop <= limit) && (ptT = ptT->next()) && ptT != this);
659     return false;
660 }
661 
debugAngle(int id) const662 const SkOpAngle* SkOpPtT::debugAngle(int id) const {
663     return this->span()->debugAngle(id);
664 }
665 
debugContour(int id) const666 SkOpContour* SkOpPtT::debugContour(int id) const {
667     return this->span()->debugContour(id);
668 }
669 
debugCoincidence() const670 const SkOpCoincidence* SkOpPtT::debugCoincidence() const {
671     return this->span()->debugCoincidence();
672 }
673 
debugPtT(int id) const674 const SkOpPtT* SkOpPtT::debugPtT(int id) const {
675     return this->span()->debugPtT(id);
676 }
677 
debugSegment(int id) const678 const SkOpSegment* SkOpPtT::debugSegment(int id) const {
679     return this->span()->debugSegment(id);
680 }
681 
debugSpan(int id) const682 const SkOpSpanBase* SkOpPtT::debugSpan(int id) const {
683     return this->span()->debugSpan(id);
684 }
685 
dump() const686 void SkOpPtT::dump() const {
687     SkDebugf("seg=%d span=%d ptT=%d",
688             this->segment()->debugID(), this->span()->debugID(), this->debugID());
689     this->dumpBase();
690     SkDebugf("\n");
691 }
692 
dumpAll() const693 void SkOpPtT::dumpAll() const {
694     contour()->indentDump();
695     const SkOpPtT* next = this;
696     int limit = debugLoopLimit(true);
697     int loop = 0;
698     do {
699         SkDebugf("%.*s", contour()->debugIndent(), "        ");
700         SkDebugf("seg=%d span=%d ptT=%d",
701                 next->segment()->debugID(), next->span()->debugID(), next->debugID());
702         next->dumpBase();
703         SkDebugf("\n");
704         if (limit && ++loop >= limit) {
705             SkDebugf("*** abort loop ***\n");
706             break;
707         }
708     } while ((next = next->fNext) && next != this);
709     contour()->outdentDump();
710 }
711 
dumpBase() const712 void SkOpPtT::dumpBase() const {
713     SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g)%s%s%s", this->fT, this->fPt.fX, this->fPt.fY,
714             this->fCoincident ? " coin" : "",
715             this->fDuplicatePt ? " dup" : "", this->fDeleted ? " deleted" : "");
716 }
717 
debugAngle(int id) const718 const SkOpAngle* SkOpSpanBase::debugAngle(int id) const {
719     return this->segment()->debugAngle(id);
720 }
721 
debugCoincidence() const722 const SkOpCoincidence* SkOpSpanBase::debugCoincidence() const {
723     return this->segment()->debugCoincidence();
724 }
725 
debugContour(int id) const726 SkOpContour* SkOpSpanBase::debugContour(int id) const {
727     return this->segment()->debugContour(id);
728 }
729 
debugPtT(int id) const730 const SkOpPtT* SkOpSpanBase::debugPtT(int id) const {
731     return this->segment()->debugPtT(id);
732 }
733 
debugSegment(int id) const734 const SkOpSegment* SkOpSpanBase::debugSegment(int id) const {
735     return this->segment()->debugSegment(id);
736 }
737 
debugSpan(int id) const738 const SkOpSpanBase* SkOpSpanBase::debugSpan(int id) const {
739     return this->segment()->debugSpan(id);
740 }
741 
dump() const742 void SkOpSpanBase::dump() const {
743     this->dumpHead();
744     this->fPtT.dump();
745 }
746 
dumpHead() const747 void SkOpSpanBase::dumpHead() const {
748     SkDebugf("%.*s", contour()->debugIndent(), "        ");
749     SkDebugf("seg=%d span=%d", this->segment()->debugID(), this->debugID());
750     this->dumpBase();
751     SkDebugf("\n");
752 }
753 
dumpAll() const754 void SkOpSpanBase::dumpAll() const {
755     this->dumpHead();
756     this->fPtT.dumpAll();
757 }
758 
dumpBase() const759 void SkOpSpanBase::dumpBase() const {
760     if (this->fAligned) {
761         SkDebugf(" aligned");
762     }
763     if (this->fChased) {
764         SkDebugf(" chased");
765     }
766 #ifdef SK_DEBUG
767     if (this->fDebugDeleted) {
768         SkDebugf(" deleted");
769     }
770 #endif
771     if (!this->final()) {
772         this->upCast()->dumpSpan();
773     }
774     const SkOpSpanBase* coin = this->coinEnd();
775     if (this != coin) {
776         SkDebugf(" coinEnd seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
777     } else if (this->final() || !this->upCast()->isCoincident()) {
778         const SkOpPtT* oPt = this->ptT()->next();
779         SkDebugf(" seg/span=%d/%d", oPt->segment()->debugID(), oPt->span()->debugID());
780     }
781     SkDebugf(" adds=%d", fSpanAdds);
782 }
783 
dumpCoin() const784 void SkOpSpanBase::dumpCoin() const {
785     const SkOpSpan* span = this->upCastable();
786     if (!span) {
787         return;
788     }
789     if (!span->isCoincident()) {
790         return;
791     }
792     span->dumpCoin();
793 }
794 
dumpCoin() const795 void SkOpSpan::dumpCoin() const {
796     const SkOpSpan* coincident = fCoincident;
797     bool ok = debugCoinLoopCheck();
798     this->dump();
799     int loop = 0;
800     do {
801         coincident->dump();
802         if (!ok && ++loop > 10) {
803             SkDebugf("*** abort loop ***\n");
804             break;
805         }
806     } while ((coincident = coincident->fCoincident) != this);
807 }
808 
dumpSpan() const809 bool SkOpSpan::dumpSpan() const {
810     SkOpSpan* coin = fCoincident;
811     if (this != coin) {
812         SkDebugf(" coinStart seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
813     }
814     SkDebugf(" windVal=%d", this->windValue());
815     SkDebugf(" windSum=");
816     SkPathOpsDebug::WindingPrintf(this->windSum());
817     if (this->oppValue() != 0 || this->oppSum() != SK_MinS32) {
818         SkDebugf(" oppVal=%d", this->oppValue());
819         SkDebugf(" oppSum=");
820         SkPathOpsDebug::WindingPrintf(this->oppSum());
821     }
822     if (this->done()) {
823         SkDebugf(" done");
824     }
825     return this != coin;
826 }
827 
debugAngle(int id) const828 const SkOpAngle* SkOpSegment::debugAngle(int id) const {
829     return this->contour()->debugAngle(id);
830 }
831 
debugCoincidence() const832 const SkOpCoincidence* SkOpSegment::debugCoincidence() const {
833     return this->contour()->debugCoincidence();
834 }
835 
debugContour(int id) const836 SkOpContour* SkOpSegment::debugContour(int id) const {
837     return this->contour()->debugContour(id);
838 }
839 
debugPtT(int id) const840 const SkOpPtT* SkOpSegment::debugPtT(int id) const {
841     return this->contour()->debugPtT(id);
842 }
843 
debugSegment(int id) const844 const SkOpSegment* SkOpSegment::debugSegment(int id) const {
845     return this->contour()->debugSegment(id);
846 }
847 
debugSpan(int id) const848 const SkOpSpanBase* SkOpSegment::debugSpan(int id) const {
849     return this->contour()->debugSpan(id);
850 }
851 
dump() const852 void SkOpSegment::dump() const {
853     SkDebugf("%.*s", contour()->debugIndent(), "        ");
854     this->dumpPts();
855     const SkOpSpanBase* span = &fHead;
856     contour()->indentDump();
857     do {
858         SkDebugf("%.*s span=%d ", contour()->debugIndent(), "        ", span->debugID());
859         span->ptT()->dumpBase();
860         span->dumpBase();
861         SkDebugf("\n");
862     } while (!span->final() && (span = span->upCast()->next()));
863     contour()->outdentDump();
864 }
865 
dumpAll() const866 void SkOpSegment::dumpAll() const {
867     SkDebugf("%.*s", contour()->debugIndent(), "        ");
868     this->dumpPts();
869     const SkOpSpanBase* span = &fHead;
870     contour()->indentDump();
871     do {
872         span->dumpAll();
873     } while (!span->final() && (span = span->upCast()->next()));
874     contour()->outdentDump();
875 }
876 
dumpAngles() const877 void SkOpSegment::dumpAngles() const {
878     SkDebugf("seg=%d\n", debugID());
879     const SkOpSpanBase* span = &fHead;
880     do {
881         const SkOpAngle* fAngle = span->fromAngle();
882         const SkOpAngle* tAngle = span->final() ? nullptr : span->upCast()->toAngle();
883         if (fAngle) {
884             SkDebugf("  span=%d from=%d ", span->debugID(), fAngle->debugID());
885             fAngle->dumpTo(this, tAngle);
886         }
887         if (tAngle) {
888             SkDebugf("  span=%d to=%d   ", span->debugID(), tAngle->debugID());
889             tAngle->dumpTo(this, fAngle);
890         }
891     } while (!span->final() && (span = span->upCast()->next()));
892 }
893 
dumpCoin() const894 void SkOpSegment::dumpCoin() const {
895     const SkOpSpan* span = &fHead;
896     do {
897         span->dumpCoin();
898     } while ((span = span->next()->upCastable()));
899 }
900 
dumpPtsInner(const char * prefix) const901 void SkOpSegment::dumpPtsInner(const char* prefix) const {
902     int last = SkPathOpsVerbToPoints(fVerb);
903     SkDebugf("%s=%d {{", prefix, this->debugID());
904     if (fVerb == SkPath::kConic_Verb) {
905         SkDebugf("{");
906     }
907     int index = 0;
908     do {
909         SkDPoint::Dump(fPts[index]);
910         SkDebugf(", ");
911     } while (++index < last);
912     SkDPoint::Dump(fPts[index]);
913     SkDebugf("}}");
914     if (fVerb == SkPath::kConic_Verb) {
915         SkDebugf(", %1.9gf}", fWeight);
916     }
917 }
918 
dumpPts(const char * prefix) const919 void SkOpSegment::dumpPts(const char* prefix) const {
920     dumpPtsInner(prefix);
921     SkDebugf("\n");
922 }
923 
dump() const924 void SkCoincidentSpans::dump() const {
925     SkDebugf("- seg=%d span=%d ptT=%d ", fCoinPtTStart->segment()->debugID(),
926         fCoinPtTStart->span()->debugID(), fCoinPtTStart->debugID());
927     fCoinPtTStart->dumpBase();
928     SkDebugf(" span=%d ptT=%d ", fCoinPtTEnd->span()->debugID(), fCoinPtTEnd->debugID());
929     fCoinPtTEnd->dumpBase();
930     if (fCoinPtTStart->segment()->operand()) {
931         SkDebugf(" operand");
932     }
933     if (fCoinPtTStart->segment()->isXor()) {
934         SkDebugf(" xor");
935     }
936     SkDebugf("\n");
937     SkDebugf("+ seg=%d span=%d ptT=%d ", fOppPtTStart->segment()->debugID(),
938         fOppPtTStart->span()->debugID(), fOppPtTStart->debugID());
939     fOppPtTStart->dumpBase();
940     SkDebugf(" span=%d ptT=%d ", fOppPtTEnd->span()->debugID(), fOppPtTEnd->debugID());
941     fOppPtTEnd->dumpBase();
942     if (fOppPtTStart->segment()->operand()) {
943         SkDebugf(" operand");
944     }
945     if (fOppPtTStart->segment()->isXor()) {
946         SkDebugf(" xor");
947     }
948     SkDebugf("\n");
949 }
950 
dump() const951 void SkOpCoincidence::dump() const {
952     SkCoincidentSpans* span = fHead;
953     while (span) {
954         span->dump();
955         span = span->next();
956     }
957     if (!fTop || fHead == fTop) {
958         return;
959     }
960     SkDebugf("top:\n");
961     span = fTop;
962     int count = 0;
963     while (span) {
964         span->dump();
965         span = span->next();
966         SkCoincidentSpans* check = fTop;
967         ++count;
968         for (int index = 0; index < count; ++index) {
969             if (span == check) {
970                 SkDebugf("(loops to #%d)\n", index);
971                 return;
972             }
973             check = check->next();
974         }
975     }
976 }
977 
dump() const978 void SkOpContour::dump() const {
979     SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
980     if (!fCount) {
981         return;
982     }
983     const SkOpSegment* segment = &fHead;
984     SkDEBUGCODE(fDebugIndent = 0);
985     this->indentDump();
986     do {
987         segment->dump();
988     } while ((segment = segment->next()));
989     this->outdentDump();
990 }
991 
dumpAll() const992 void SkOpContour::dumpAll() const {
993     SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
994     if (!fCount) {
995         return;
996     }
997     const SkOpSegment* segment = &fHead;
998     SkDEBUGCODE(fDebugIndent = 0);
999     this->indentDump();
1000     do {
1001         segment->dumpAll();
1002     } while ((segment = segment->next()));
1003     this->outdentDump();
1004 }
1005 
1006 
dumpAngles() const1007 void SkOpContour::dumpAngles() const {
1008     SkDebugf("contour=%d\n", this->debugID());
1009     const SkOpSegment* segment = &fHead;
1010     do {
1011         SkDebugf("  seg=%d ", segment->debugID());
1012         segment->dumpAngles();
1013     } while ((segment = segment->next()));
1014 }
1015 
dumpPt(int index) const1016 void SkOpContour::dumpPt(int index) const {
1017     const SkOpSegment* segment = &fHead;
1018     do {
1019         if (segment->debugID() == index) {
1020             segment->dumpPts();
1021         }
1022     } while ((segment = segment->next()));
1023 }
1024 
dumpPts(const char * prefix) const1025 void SkOpContour::dumpPts(const char* prefix) const {
1026     SkDebugf("contour=%d\n", this->debugID());
1027     const SkOpSegment* segment = &fHead;
1028     do {
1029         SkDebugf("  %s=%d ", prefix, segment->debugID());
1030         segment->dumpPts(prefix);
1031     } while ((segment = segment->next()));
1032 }
1033 
dumpPtsX(const char * prefix) const1034 void SkOpContour::dumpPtsX(const char* prefix) const {
1035     if (!this->fCount) {
1036         SkDebugf("<empty>\n");
1037         return;
1038     }
1039     const SkOpSegment* segment = &fHead;
1040     do {
1041         segment->dumpPts(prefix);
1042     } while ((segment = segment->next()));
1043 }
1044 
dumpSegment(int index) const1045 void SkOpContour::dumpSegment(int index) const {
1046     debugSegment(index)->dump();
1047 }
1048 
dumpSegments(const char * prefix,SkPathOp op) const1049 void SkOpContour::dumpSegments(const char* prefix, SkPathOp op) const {
1050     bool firstOp = false;
1051     const SkOpContour* c = this;
1052     do {
1053         if (!firstOp && c->operand()) {
1054 #if DEBUG_ACTIVE_OP
1055             SkDebugf("op %s\n", SkPathOpsDebug::kPathOpStr[op]);
1056 #endif
1057             firstOp = true;
1058         }
1059         c->dumpPtsX(prefix);
1060     } while ((c = c->next()));
1061 }
1062 
dumpSpan(int index) const1063 void SkOpContour::dumpSpan(int index) const {
1064     debugSpan(index)->dump();
1065 }
1066 
dumpSpans() const1067 void SkOpContour::dumpSpans() const {
1068     SkDebugf("contour=%d\n", this->debugID());
1069     const SkOpSegment* segment = &fHead;
1070     do {
1071         SkDebugf("  seg=%d ", segment->debugID());
1072         segment->dump();
1073     } while ((segment = segment->next()));
1074 }
1075 
dump() const1076 void SkOpCurve::dump() const {
1077     int count = SkPathOpsVerbToPoints(SkDEBUGRELEASE(fVerb, SkPath::kCubic_Verb));
1078     SkDebugf("{{");
1079     int index;
1080     for (index = 0; index <= count - 1; ++index) {
1081         SkDebugf("{%1.9gf,%1.9gf}, ", fPts[index].fX, fPts[index].fY);
1082     }
1083     SkDebugf("{%1.9gf,%1.9gf}}}\n", fPts[index].fX, fPts[index].fY);
1084 }
1085 
1086 #ifdef SK_DEBUG
debugAngle(int id) const1087 const SkOpAngle* SkOpGlobalState::debugAngle(int id) const {
1088     const SkOpContour* contour = fContourHead;
1089     do {
1090         const SkOpSegment* segment = contour->first();
1091         while (segment) {
1092             const SkOpSpan* span = segment->head();
1093             do {
1094                 SkOpAngle* angle = span->fromAngle();
1095                 if (angle && angle->debugID() == id) {
1096                     return angle;
1097                 }
1098                 angle = span->toAngle();
1099                 if (angle && angle->debugID() == id) {
1100                     return angle;
1101                 }
1102             } while ((span = span->next()->upCastable()));
1103             const SkOpSpanBase* tail = segment->tail();
1104             SkOpAngle* angle = tail->fromAngle();
1105             if (angle && angle->debugID() == id) {
1106                 return angle;
1107             }
1108             segment = segment->next();
1109         }
1110     } while ((contour = contour->next()));
1111     return nullptr;
1112 }
1113 
debugContour(int id) const1114 SkOpContour* SkOpGlobalState::debugContour(int id) const {
1115     SkOpContour* contour = fContourHead;
1116     do {
1117         if (contour->debugID() == id) {
1118             return contour;
1119         }
1120     } while ((contour = contour->next()));
1121     return nullptr;
1122 }
1123 
debugPtT(int id) const1124 const SkOpPtT* SkOpGlobalState::debugPtT(int id) const {
1125     const SkOpContour* contour = fContourHead;
1126     do {
1127         const SkOpSegment* segment = contour->first();
1128         while (segment) {
1129             const SkOpSpan* span = segment->head();
1130             do {
1131                 const SkOpPtT* ptT = span->ptT();
1132                 if (ptT->debugMatchID(id)) {
1133                     return ptT;
1134                 }
1135             } while ((span = span->next()->upCastable()));
1136             const SkOpSpanBase* tail = segment->tail();
1137             const SkOpPtT* ptT = tail->ptT();
1138             if (ptT->debugMatchID(id)) {
1139                 return ptT;
1140             }
1141             segment = segment->next();
1142         }
1143     } while ((contour = contour->next()));
1144     return nullptr;
1145 }
1146 
debugSegment(int id) const1147 const SkOpSegment* SkOpGlobalState::debugSegment(int id) const {
1148     const SkOpContour* contour = fContourHead;
1149     do {
1150         const SkOpSegment* segment = contour->first();
1151         while (segment) {
1152             if (segment->debugID() == id) {
1153                 return segment;
1154             }
1155             segment = segment->next();
1156         }
1157     } while ((contour = contour->next()));
1158     return nullptr;
1159 }
1160 
debugSpan(int id) const1161 const SkOpSpanBase* SkOpGlobalState::debugSpan(int id) const {
1162     const SkOpContour* contour = fContourHead;
1163     do {
1164         const SkOpSegment* segment = contour->first();
1165         while (segment) {
1166             const SkOpSpan* span = segment->head();
1167             do {
1168                 if (span->debugID() == id) {
1169                     return span;
1170                 }
1171             } while ((span = span->next()->upCastable()));
1172             const SkOpSpanBase* tail = segment->tail();
1173             if (tail->debugID() == id) {
1174                 return tail;
1175             }
1176             segment = segment->next();
1177         }
1178     } while ((contour = contour->next()));
1179     return nullptr;
1180 }
1181 #endif
1182 
dumpIsCoincidentStr() const1183 char SkTCoincident::dumpIsCoincidentStr() const {
1184     if (!!fMatch != fMatch) {
1185         return '?';
1186     }
1187     return fMatch ? '*' : 0;
1188 }
1189 
dump() const1190 void SkTCoincident::dump() const {
1191     SkDebugf("t=%1.9g pt=(%1.9g,%1.9g)%s\n", fPerpT, fPerpPt.fX, fPerpPt.fY,
1192             fMatch ? " match" : "");
1193 }
1194 
1195 #ifdef SK_DEBUG
1196 
debugSpan(int id) const1197 const SkTSpan* SkTSect::debugSpan(int id) const {
1198     const SkTSpan* test = fHead;
1199     do {
1200         if (test->debugID() == id) {
1201             return test;
1202         }
1203     } while ((test = test->next()));
1204     return nullptr;
1205 }
1206 
debugT(double t) const1207 const SkTSpan* SkTSect::debugT(double t) const {
1208     const SkTSpan* test = fHead;
1209     const SkTSpan* closest = nullptr;
1210     double bestDist = DBL_MAX;
1211     do {
1212         if (between(test->fStartT, t, test->fEndT)) {
1213             return test;
1214         }
1215         double testDist = std::min(fabs(test->fStartT - t), fabs(test->fEndT - t));
1216         if (bestDist > testDist) {
1217             bestDist = testDist;
1218             closest = test;
1219         }
1220     } while ((test = test->next()));
1221     SkASSERT(closest);
1222     return closest;
1223 }
1224 
1225 #endif
1226 
dump() const1227 void SkTSect::dump() const {
1228     dumpCommon(fHead);
1229 }
1230 
1231 extern int gDumpTSectNum;
1232 
dumpBoth(SkTSect * opp) const1233 void SkTSect::dumpBoth(SkTSect* opp) const {
1234 #if DEBUG_T_SECT_DUMP <= 2
1235 #if DEBUG_T_SECT_DUMP == 2
1236     SkDebugf("%d ", ++gDumpTSectNum);
1237 #endif
1238     this->dump();
1239     SkDebugf("\n");
1240     opp->dump();
1241     SkDebugf("\n");
1242 #elif DEBUG_T_SECT_DUMP == 3
1243     SkDebugf("<div id=\"sect%d\">\n", ++gDumpTSectNum);
1244     if (this->fHead) {
1245         this->dumpCurves();
1246     }
1247     if (opp->fHead) {
1248         opp->dumpCurves();
1249     }
1250     SkDebugf("</div>\n\n");
1251 #endif
1252 }
1253 
dumpBounded(int id) const1254 void SkTSect::dumpBounded(int id) const {
1255 #ifdef SK_DEBUG
1256     const SkTSpan* bounded = debugSpan(id);
1257     if (!bounded) {
1258         SkDebugf("no span matches %d\n", id);
1259         return;
1260     }
1261     const SkTSpan* test = bounded->debugOpp()->fHead;
1262     do {
1263         if (test->findOppSpan(bounded)) {
1264             test->dump();
1265             SkDebugf(" ");
1266         }
1267     } while ((test = test->next()));
1268     SkDebugf("\n");
1269 #endif
1270 }
1271 
dumpBounds() const1272 void SkTSect::dumpBounds() const {
1273     const SkTSpan* test = fHead;
1274     do {
1275         test->dumpBounds();
1276     } while ((test = test->next()));
1277 }
1278 
dumpCoin() const1279 void SkTSect::dumpCoin() const {
1280     dumpCommon(fCoincident);
1281 }
1282 
dumpCoinCurves() const1283 void SkTSect::dumpCoinCurves() const {
1284     dumpCommonCurves(fCoincident);
1285 }
1286 
dumpCommon(const SkTSpan * test) const1287 void SkTSect::dumpCommon(const SkTSpan* test) const {
1288     SkDebugf("id=%d", debugID());
1289     if (!test) {
1290         SkDebugf(" (empty)");
1291         return;
1292     }
1293     do {
1294         SkDebugf(" ");
1295         test->dump();
1296     } while ((test = test->next()));
1297 }
1298 
dumpCommonCurves(const SkTSpan * test) const1299 void SkTSect::dumpCommonCurves(const SkTSpan* test) const {
1300 #if DEBUG_T_SECT
1301     do {
1302         test->fPart->dumpID(test->debugID());
1303     } while ((test = test->next()));
1304 #endif
1305 }
1306 
dumpCurves() const1307 void SkTSect::dumpCurves() const {
1308     dumpCommonCurves(fHead);
1309 }
1310 
1311 #ifdef SK_DEBUG
1312 
debugSpan(int id) const1313 const SkTSpan* SkTSpan::debugSpan(int id) const {
1314     return fDebugSect->debugSpan(id);
1315 }
1316 
debugT(double t) const1317 const SkTSpan* SkTSpan::debugT(double t) const {
1318     return fDebugSect->debugT(t);
1319 }
1320 
1321 #endif
1322 
dumpAll() const1323 void SkTSpan::dumpAll() const {
1324     dumpID();
1325     SkDebugf("=(%g,%g) [", fStartT, fEndT);
1326     const SkTSpanBounded* testBounded = fBounded;
1327     while (testBounded) {
1328         const SkTSpan* span = testBounded->fBounded;
1329         const SkTSpanBounded* next = testBounded->fNext;
1330         span->dumpID();
1331         SkDebugf("=(%g,%g)", span->fStartT, span->fEndT);
1332         if (next) {
1333             SkDebugf(" ");
1334         }
1335         testBounded = next;
1336     }
1337     SkDebugf("]\n");
1338 }
1339 
dump() const1340 void SkTSpan::dump() const {
1341     dumpID();
1342     SkDebugf("=(%g,%g) [", fStartT, fEndT);
1343     const SkTSpanBounded* testBounded = fBounded;
1344     while (testBounded) {
1345         const SkTSpan* span = testBounded->fBounded;
1346         const SkTSpanBounded* next = testBounded->fNext;
1347         span->dumpID();
1348         if (next) {
1349             SkDebugf(",");
1350         }
1351         testBounded = next;
1352     }
1353     SkDebugf("]");
1354 }
1355 
dumpBounded(int id) const1356 void SkTSpan::dumpBounded(int id) const {
1357     SkDEBUGCODE(fDebugSect->dumpBounded(id));
1358 }
1359 
dumpBounds() const1360 void SkTSpan::dumpBounds() const {
1361     dumpID();
1362     SkDebugf(" bounds=(%1.9g,%1.9g, %1.9g,%1.9g) boundsMax=%1.9g%s\n",
1363             fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom, fBoundsMax,
1364             fCollapsed ? " collapsed" : "");
1365 }
1366 
dumpCoin() const1367 void SkTSpan::dumpCoin() const {
1368     dumpID();
1369     SkDebugf(" coinStart ");
1370     fCoinStart.dump();
1371     SkDebugf(" coinEnd ");
1372     fCoinEnd.dump();
1373 }
1374 
dumpID() const1375 void SkTSpan::dumpID() const {
1376     char cS = fCoinStart.dumpIsCoincidentStr();
1377     if (cS) {
1378         SkDebugf("%c", cS);
1379     }
1380     SkDebugf("%d", debugID());
1381     char cE = fCoinEnd.dumpIsCoincidentStr();
1382     if (cE) {
1383         SkDebugf("%c", cE);
1384     }
1385 }
1386 
1387 #if DEBUG_T_SECT_DUMP > 1
1388 int gDumpTSectNum;
1389 #endif
1390 
1391 // global path dumps for msvs Visual Studio 17 to use from Immediate Window
Dump(const SkOpContour & contour)1392 void Dump(const SkOpContour& contour) {
1393     contour.dump();
1394 }
1395 
DumpAll(const SkOpContour & contour)1396 void DumpAll(const SkOpContour& contour) {
1397     contour.dumpAll();
1398 }
1399 
DumpAngles(const SkOpContour & contour)1400 void DumpAngles(const SkOpContour& contour) {
1401     contour.dumpAngles();
1402 }
1403 
DumpContours(const SkOpContour & contour)1404 void DumpContours(const SkOpContour& contour) {
1405     contour.dumpContours();
1406 }
1407 
DumpContoursAll(const SkOpContour & contour)1408 void DumpContoursAll(const SkOpContour& contour) {
1409     contour.dumpContoursAll();
1410 }
1411 
DumpContoursAngles(const SkOpContour & contour)1412 void DumpContoursAngles(const SkOpContour& contour) {
1413     contour.dumpContoursAngles();
1414 }
1415 
DumpContoursPts(const SkOpContour & contour)1416 void DumpContoursPts(const SkOpContour& contour) {
1417     contour.dumpContoursPts();
1418 }
1419 
DumpContoursPt(const SkOpContour & contour,int segmentID)1420 void DumpContoursPt(const SkOpContour& contour, int segmentID) {
1421     contour.dumpContoursPt(segmentID);
1422 }
1423 
DumpContoursSegment(const SkOpContour & contour,int segmentID)1424 void DumpContoursSegment(const SkOpContour& contour, int segmentID) {
1425     contour.dumpContoursSegment(segmentID);
1426 }
1427 
DumpContoursSpan(const SkOpContour & contour,int segmentID)1428 void DumpContoursSpan(const SkOpContour& contour, int segmentID) {
1429     contour.dumpContoursSpan(segmentID);
1430 }
1431 
DumpContoursSpans(const SkOpContour & contour)1432 void DumpContoursSpans(const SkOpContour& contour) {
1433     contour.dumpContoursSpans();
1434 }
1435 
DumpPt(const SkOpContour & contour,int pt)1436 void DumpPt(const SkOpContour& contour, int pt) {
1437     contour.dumpPt(pt);
1438 }
1439 
DumpPts(const SkOpContour & contour,const char * prefix)1440 void DumpPts(const SkOpContour& contour, const char* prefix) {
1441     contour.dumpPts(prefix);
1442 }
1443 
DumpSegment(const SkOpContour & contour,int seg)1444 void DumpSegment(const SkOpContour& contour, int seg) {
1445     contour.dumpSegment(seg);
1446 }
1447 
DumpSegments(const SkOpContour & contour,const char * prefix,SkPathOp op)1448 void DumpSegments(const SkOpContour& contour, const char* prefix, SkPathOp op) {
1449     contour.dumpSegments(prefix, op);
1450 }
1451 
DumpSpan(const SkOpContour & contour,int span)1452 void DumpSpan(const SkOpContour& contour, int span) {
1453     contour.dumpSpan(span);
1454 }
1455 
DumpSpans(const SkOpContour & contour)1456 void DumpSpans(const SkOpContour& contour ) {
1457     contour.dumpSpans();
1458 }
1459 
Dump(const SkOpSegment & segment)1460 void Dump(const SkOpSegment& segment) {
1461     segment.dump();
1462 }
1463 
DumpAll(const SkOpSegment & segment)1464 void DumpAll(const SkOpSegment& segment) {
1465     segment.dumpAll();
1466 }
1467 
DumpAngles(const SkOpSegment & segment)1468 void DumpAngles(const SkOpSegment& segment) {
1469     segment.dumpAngles();
1470 }
1471 
DumpCoin(const SkOpSegment & segment)1472 void DumpCoin(const SkOpSegment& segment) {
1473     segment.dumpCoin();
1474 }
1475 
DumpPts(const SkOpSegment & segment,const char * prefix)1476 void DumpPts(const SkOpSegment& segment, const char* prefix) {
1477     segment.dumpPts(prefix);
1478 }
1479 
Dump(const SkOpPtT & ptT)1480 void Dump(const SkOpPtT& ptT) {
1481     ptT.dump();
1482 }
1483 
DumpAll(const SkOpPtT & ptT)1484 void DumpAll(const SkOpPtT& ptT) {
1485     ptT.dumpAll();
1486 }
1487 
Dump(const SkOpSpanBase & spanBase)1488 void Dump(const SkOpSpanBase& spanBase) {
1489     spanBase.dump();
1490 }
1491 
DumpCoin(const SkOpSpanBase & spanBase)1492 void DumpCoin(const SkOpSpanBase& spanBase) {
1493     spanBase.dumpCoin();
1494 }
1495 
DumpAll(const SkOpSpanBase & spanBase)1496 void DumpAll(const SkOpSpanBase& spanBase) {
1497     spanBase.dumpAll();
1498 }
1499 
DumpCoin(const SkOpSpan & span)1500 void DumpCoin(const SkOpSpan& span) {
1501     span.dumpCoin();
1502 }
1503 
DumpSpan(const SkOpSpan & span)1504 bool DumpSpan(const SkOpSpan& span) {
1505     return span.dumpSpan();
1506 }
1507 
Dump(const SkDConic & conic)1508 void Dump(const SkDConic& conic) {
1509     conic.dump();
1510 }
1511 
DumpID(const SkDConic & conic,int id)1512 void DumpID(const SkDConic& conic, int id) {
1513     conic.dumpID(id);
1514 }
1515 
Dump(const SkDCubic & cubic)1516 void Dump(const SkDCubic& cubic) {
1517     cubic.dump();
1518 }
1519 
DumpID(const SkDCubic & cubic,int id)1520 void DumpID(const SkDCubic& cubic, int id) {
1521     cubic.dumpID(id);
1522 }
1523 
Dump(const SkDLine & line)1524 void Dump(const SkDLine& line) {
1525     line.dump();
1526 }
1527 
DumpID(const SkDLine & line,int id)1528 void DumpID(const SkDLine& line, int id) {
1529     line.dumpID(id);
1530 }
1531 
Dump(const SkDQuad & quad)1532 void Dump(const SkDQuad& quad) {
1533     quad.dump();
1534 }
1535 
DumpID(const SkDQuad & quad,int id)1536 void DumpID(const SkDQuad& quad, int id) {
1537     quad.dumpID(id);
1538 }
1539 
Dump(const SkDPoint & point)1540 void Dump(const SkDPoint& point) {
1541     point.dump();
1542 }
1543 
Dump(const SkOpAngle & angle)1544 void Dump(const SkOpAngle& angle) {
1545     angle.dump();
1546 }
1547 
debugAddAngle(double startT,double endT)1548 void SkOpSegment::debugAddAngle(double startT, double endT) {
1549     SkOpPtT* startPtT = startT == 0 ? fHead.ptT() : startT == 1 ? fTail.ptT()
1550             : this->addT(startT);
1551     SkOpPtT* endPtT = endT == 0 ? fHead.ptT() : endT == 1 ? fTail.ptT()
1552             : this->addT(endT);
1553     SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>();
1554     SkOpSpanBase* startSpan = &fHead;
1555     while (startSpan->ptT() != startPtT) {
1556         startSpan = startSpan->upCast()->next();
1557     }
1558     SkOpSpanBase* endSpan = &fHead;
1559     while (endSpan->ptT() != endPtT) {
1560         endSpan = endSpan->upCast()->next();
1561     }
1562     angle->set(startSpan, endSpan);
1563     if (startT < endT) {
1564         startSpan->upCast()->setToAngle(angle);
1565         endSpan->setFromAngle(angle);
1566     } else {
1567         endSpan->upCast()->setToAngle(angle);
1568         startSpan->setFromAngle(angle);
1569     }
1570 }
1571