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