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