skia2/tests/PathOpsDebug.cpp
caryclark 26ad22ab61 Enabling clip stack flattening exercises path ops.
Iterating through the 903K skps that represent the
imagable 1M top web pages triggers a number of
bugs, some of which are addressed here.

Some web pages trigger intersecting cubic
representations of arc with their conic
counterparts. This exposed a flaw in coincident
detection that caused an infinite loop. The loop
alternatively extended the coincident section and,
determining the that the bounds of the curve pairs
did not overlap, deleted the extension.

Track the number of times the coincident detection
is called, and if it exceeds an empirically found
limit, assume that the curves are coincident and
force it to be so.

The loop count limit can be determined by enabling
DEBUG_T_SECT_LOOP_COUNT and running all tests. The
largest count is reported on completion.

Another class of bugs was caused by concident
detection duplicating nearly identical points that
had been merged earlier. To track these bugs, the
'handle coincidence' code was duplicated as a
const debug variety that reported if one of a
dozen or so irregularities are present; then it is
easier to see when a block of code that fixes one
irregularity regresses another.

Creating the debug const code version exposed some
non-debug code that could be const, and some that
was experimental and could be removed. Set
DEBUG_COINCIDENCE to track coincidence health and
handling.

For running on Chrome, DEBUG_VERIFY checks the
result of pathops against the same operation
using SkRegion to verify that the results are
nearly the same.

When visualizing the pathops work using
tools/pathops_visualizer.htm, set
DEBUG_DUMP_ALIGNMENT to see the curves after
they've been aligned for coincidence.

Other bugs fixed include detecting when a
section of a pair of curves have devolved into
lines and are coincident.

TBR=reed@google.com

Review URL: https://codereview.chromium.org/1394503003
2015-10-16 09:03:38 -07:00

1416 lines
42 KiB
C++
Executable File

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "PathOpsTSectDebug.h"
#include "SkOpCoincidence.h"
#include "SkOpContour.h"
#include "SkIntersectionHelper.h"
#include "SkMutex.h"
#include "SkOpSegment.h"
#include "SkString.h"
extern bool FLAGS_runFail;
inline void DebugDumpDouble(double x) {
if (x == floor(x)) {
SkDebugf("%.0f", x);
} else {
SkDebugf("%1.19g", x);
}
}
inline void DebugDumpFloat(float x) {
if (x == floorf(x)) {
SkDebugf("%.0f", x);
} else {
SkDebugf("%1.9gf", x);
}
}
inline void DebugDumpHexFloat(float x) {
SkDebugf("SkBits2Float(0x%08x)", SkFloat2Bits(x));
}
// if not defined by PathOpsDebug.cpp ...
#if !defined SK_DEBUG && FORCE_RELEASE
bool SkPathOpsDebug::ValidWind(int wind) {
return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
}
void SkPathOpsDebug::WindingPrintf(int wind) {
if (wind == SK_MinS32) {
SkDebugf("?");
} else {
SkDebugf("%d", wind);
}
}
#endif
void SkDConic::dump() const {
dumpInner();
SkDebugf("},\n");
}
void SkDConic::dumpID(int id) const {
dumpInner();
SkDebugf("} id=%d\n", id);
}
void SkDConic::dumpInner() const {
SkDebugf("{");
fPts.dumpInner();
SkDebugf("}}, %1.9gf", fWeight);
}
void SkDCubic::dump() const {
this->dumpInner();
SkDebugf("}},\n");
}
void SkDCubic::dumpID(int id) const {
this->dumpInner();
SkDebugf("}} id=%d\n", id);
}
static inline bool double_is_NaN(double x) { return x != x; }
void SkDCubic::dumpInner() const {
SkDebugf("{{");
int index = 0;
do {
if (index != 0) {
if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
return;
}
SkDebugf(", ");
}
fPts[index].dump();
} while (++index < 3);
if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
return;
}
SkDebugf(", ");
fPts[index].dump();
}
void SkDCurve::dumpID(int id) const {
#ifndef SK_RELEASE
switch(fVerb) {
case SkPath::kLine_Verb:
fLine.dumpID(id);
break;
case SkPath::kQuad_Verb:
fQuad.dumpID(id);
break;
case SkPath::kConic_Verb:
fConic.dumpID(id);
break;
case SkPath::kCubic_Verb:
fCubic.dumpID(id);
break;
default:
SkASSERT(0);
}
#else
fCubic.dumpID(id);
#endif
}
void SkDLine::dump() const {
this->dumpInner();
SkDebugf("}},\n");
}
void SkDLine::dumpID(int id) const {
this->dumpInner();
SkDebugf("}} id=%d\n", id);
}
void SkDLine::dumpInner() const {
SkDebugf("{{");
fPts[0].dump();
SkDebugf(", ");
fPts[1].dump();
}
void SkDPoint::dump() const {
SkDebugf("{");
DebugDumpDouble(fX);
SkDebugf(", ");
DebugDumpDouble(fY);
SkDebugf("}");
}
void SkDPoint::Dump(const SkPoint& pt) {
SkDebugf("{");
DebugDumpFloat(pt.fX);
SkDebugf(", ");
DebugDumpFloat(pt.fY);
SkDebugf("}");
}
void SkDPoint::DumpHex(const SkPoint& pt) {
SkDebugf("{");
DebugDumpHexFloat(pt.fX);
SkDebugf(", ");
DebugDumpHexFloat(pt.fY);
SkDebugf("}");
}
void SkDQuad::dump() const {
dumpInner();
SkDebugf("}},\n");
}
void SkDQuad::dumpID(int id) const {
dumpInner();
SkDebugf("}} id=%d\n", id);
}
void SkDQuad::dumpInner() const {
SkDebugf("{{");
int index = 0;
do {
fPts[index].dump();
SkDebugf(", ");
} while (++index < 2);
fPts[index].dump();
}
void SkIntersections::dump() const {
SkDebugf("used=%d of %d", fUsed, fMax);
for (int index = 0; index < fUsed; ++index) {
SkDebugf(" t=(%s%1.9g,%s%1.9g) pt=(%1.9g,%1.9g)",
fIsCoincident[0] & (1 << index) ? "*" : "", fT[0][index],
fIsCoincident[1] & (1 << index) ? "*" : "", fT[1][index],
fPt[index].fX, fPt[index].fY);
if (index < 2 && fNearlySame[index]) {
SkDebugf(" pt2=(%1.9g,%1.9g)",fPt2[index].fX, fPt2[index].fY);
}
}
SkDebugf("\n");
}
const SkOpAngle* SkPathOpsDebug::DebugAngleAngle(const SkOpAngle* angle, int id) {
return angle->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugAngleContour(SkOpAngle* angle, int id) {
return angle->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugAnglePtT(const SkOpAngle* angle, int id) {
return angle->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugAngleSegment(const SkOpAngle* angle, int id) {
return angle->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugAngleSpan(const SkOpAngle* angle, int id) {
return angle->debugSpan(id);
}
const SkOpAngle* SkPathOpsDebug::DebugContourAngle(SkOpContour* contour, int id) {
return contour->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugContourContour(SkOpContour* contour, int id) {
return contour->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugContourPtT(SkOpContour* contour, int id) {
return contour->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugContourSegment(SkOpContour* contour, int id) {
return contour->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugContourSpan(SkOpContour* contour, int id) {
return contour->debugSpan(id);
}
const SkOpAngle* SkPathOpsDebug::DebugCoincidenceAngle(SkOpCoincidence* coin, int id) {
return coin->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugCoincidenceContour(SkOpCoincidence* coin, int id) {
return coin->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugCoincidencePtT(SkOpCoincidence* coin, int id) {
return coin->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugCoincidenceSegment(SkOpCoincidence* coin, int id) {
return coin->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugCoincidenceSpan(SkOpCoincidence* coin, int id) {
return coin->debugSpan(id);
}
const SkOpAngle* SkPathOpsDebug::DebugPtTAngle(const SkOpPtT* ptT, int id) {
return ptT->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugPtTContour(SkOpPtT* ptT, int id) {
return ptT->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugPtTPtT(const SkOpPtT* ptT, int id) {
return ptT->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugPtTSegment(const SkOpPtT* ptT, int id) {
return ptT->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugPtTSpan(const SkOpPtT* ptT, int id) {
return ptT->debugSpan(id);
}
const SkOpAngle* SkPathOpsDebug::DebugSegmentAngle(const SkOpSegment* span, int id) {
return span->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugSegmentContour(SkOpSegment* span, int id) {
return span->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugSegmentPtT(const SkOpSegment* span, int id) {
return span->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugSegmentSegment(const SkOpSegment* span, int id) {
return span->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugSegmentSpan(const SkOpSegment* span, int id) {
return span->debugSpan(id);
}
const SkOpAngle* SkPathOpsDebug::DebugSpanAngle(const SkOpSpanBase* span, int id) {
return span->debugAngle(id);
}
SkOpContour* SkPathOpsDebug::DebugSpanContour(SkOpSpanBase* span, int id) {
return span->debugContour(id);
}
const SkOpPtT* SkPathOpsDebug::DebugSpanPtT(const SkOpSpanBase* span, int id) {
return span->debugPtT(id);
}
const SkOpSegment* SkPathOpsDebug::DebugSpanSegment(const SkOpSpanBase* span, int id) {
return span->debugSegment(id);
}
const SkOpSpanBase* SkPathOpsDebug::DebugSpanSpan(const SkOpSpanBase* span, int id) {
return span->debugSpan(id);
}
void SkOpContour::dumpContours() const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dump();
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursAll() const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpAll();
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursAngles() const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpAngles();
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursPts() const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpPts();
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursPt(int segmentID) const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpPt(segmentID);
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursSegment(int segmentID) const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpSegment(segmentID);
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursSpan(int spanID) const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpSpan(spanID);
} while ((contour = contour->next()));
}
void SkOpContour::dumpContoursSpans() const {
SkOpContour* contour = this->globalState()->contourHead();
do {
contour->dumpSpans();
} while ((contour = contour->next()));
}
template <typename TCurve, typename OppCurve>
const SkTSpan<TCurve, OppCurve>* DebugSpan(const SkTSect<TCurve, OppCurve>* sect, int id) {
return sect->debugSpan(id);
}
void DontCallDebugSpan(int id);
void DontCallDebugSpan(int id) { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DebugSpan(&q1q2, id);
DebugSpan(&q1k2, id);
DebugSpan(&q1c2, id);
DebugSpan(&k1q2, id);
DebugSpan(&k1k2, id);
DebugSpan(&k1c2, id);
DebugSpan(&c1q2, id);
DebugSpan(&c1k2, id);
DebugSpan(&c1c2, id);
}
template <typename TCurve, typename OppCurve>
const SkTSpan<TCurve, OppCurve>* DebugT(const SkTSect<TCurve, OppCurve>* sect, double t) {
return sect->debugT(t);
}
void DontCallDebugT(double t);
void DontCallDebugT(double t) { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DebugT(&q1q2, t);
DebugT(&q1k2, t);
DebugT(&q1c2, t);
DebugT(&k1q2, t);
DebugT(&k1k2, t);
DebugT(&k1c2, t);
DebugT(&c1q2, t);
DebugT(&c1k2, t);
DebugT(&c1c2, t);
}
template <typename TCurve, typename OppCurve>
void Dump(const SkTSect<TCurve, OppCurve>* sect) {
sect->dump();
}
void DontCallDumpTSect();
void DontCallDumpTSect() { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
Dump(&q1q2);
Dump(&q1k2);
Dump(&q1c2);
Dump(&k1q2);
Dump(&k1k2);
Dump(&k1c2);
Dump(&c1q2);
Dump(&c1k2);
Dump(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpBoth(SkTSect<TCurve, OppCurve>* sect1, SkTSect<OppCurve, TCurve>* sect2) {
sect1->dumpBoth(sect2);
}
void DontCallDumpBoth();
void DontCallDumpBoth() { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpBoth(&q1q2, &q1q2);
DumpBoth(&q1k2, &k1q2);
DumpBoth(&q1c2, &c1q2);
DumpBoth(&k1q2, &q1k2);
DumpBoth(&k1k2, &k1k2);
DumpBoth(&k1c2, &c1k2);
DumpBoth(&c1q2, &q1c2);
DumpBoth(&c1k2, &k1c2);
DumpBoth(&c1c2, &c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpBounded(SkTSect<TCurve, OppCurve>* sect1, int id) {
sect1->dumpBounded(id);
}
void DontCallDumpBounded();
void DontCallDumpBounded() {
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpBounded(&q1q2, 0);
DumpBounded(&q1k2, 0);
DumpBounded(&q1c2, 0);
DumpBounded(&k1q2, 0);
DumpBounded(&k1k2, 0);
DumpBounded(&k1c2, 0);
DumpBounded(&c1q2, 0);
DumpBounded(&c1k2, 0);
DumpBounded(&c1c2, 0);
}
template <typename TCurve, typename OppCurve>
void DumpBounds(SkTSect<TCurve, OppCurve>* sect1) {
sect1->dumpBounds();
}
void DontCallDumpBounds();
void DontCallDumpBounds() {
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpBounds(&q1q2);
DumpBounds(&q1k2);
DumpBounds(&q1c2);
DumpBounds(&k1q2);
DumpBounds(&k1k2);
DumpBounds(&k1c2);
DumpBounds(&c1q2);
DumpBounds(&c1k2);
DumpBounds(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpCoin(SkTSect<TCurve, OppCurve>* sect1) {
sect1->dumpCoin();
}
void DontCallDumpCoin();
void DontCallDumpCoin() { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpCoin(&q1q2);
DumpCoin(&q1k2);
DumpCoin(&q1c2);
DumpCoin(&k1q2);
DumpCoin(&k1k2);
DumpCoin(&k1c2);
DumpCoin(&c1q2);
DumpCoin(&c1k2);
DumpCoin(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpCoinCurves(SkTSect<TCurve, OppCurve>* sect1) {
sect1->dumpCoinCurves();
}
void DontCallDumpCoinCurves();
void DontCallDumpCoinCurves() { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpCoinCurves(&q1q2);
DumpCoinCurves(&q1k2);
DumpCoinCurves(&q1c2);
DumpCoinCurves(&k1q2);
DumpCoinCurves(&k1k2);
DumpCoinCurves(&k1c2);
DumpCoinCurves(&c1q2);
DumpCoinCurves(&c1k2);
DumpCoinCurves(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpCurves(const SkTSect<TCurve, OppCurve>* sect) {
sect->dumpCurves();
}
void DontCallDumpCurves();
void DontCallDumpCurves() { // exists to instantiate the templates
SkDQuad quad;
SkDConic conic;
SkDCubic cubic;
SkTSect<SkDQuad, SkDQuad> q1q2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDConic> q1k2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDQuad, SkDCubic> q1c2(quad PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDQuad> k1q2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDConic> k1k2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDConic, SkDCubic> k1c2(conic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDQuad> c1q2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDConic> c1k2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
SkTSect<SkDCubic, SkDCubic> c1c2(cubic PATH_OPS_DEBUG_T_SECT_PARAMS(1));
DumpCurves(&q1q2);
DumpCurves(&q1k2);
DumpCurves(&q1c2);
DumpCurves(&k1q2);
DumpCurves(&k1k2);
DumpCurves(&k1c2);
DumpCurves(&c1q2);
DumpCurves(&c1k2);
DumpCurves(&c1c2);
}
template <typename TCurve, typename OppCurve>
void Dump(const SkTSpan<TCurve, OppCurve>* span) {
span->dump();
}
void DontCallDumpTSpan();
void DontCallDumpTSpan() { // exists to instantiate the templates
SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
Dump(&q1q2);
Dump(&q1k2);
Dump(&q1c2);
Dump(&k1q2);
Dump(&k1k2);
Dump(&k1c2);
Dump(&c1q2);
Dump(&c1k2);
Dump(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpAll(const SkTSpan<TCurve, OppCurve>* span) {
span->dumpAll();
}
void DontCallDumpSpanAll();
void DontCallDumpSpanAll() { // exists to instantiate the templates
SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
DumpAll(&q1q2);
DumpAll(&q1k2);
DumpAll(&q1c2);
DumpAll(&k1q2);
DumpAll(&k1k2);
DumpAll(&k1c2);
DumpAll(&c1q2);
DumpAll(&c1k2);
DumpAll(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpBounded(const SkTSpan<TCurve, OppCurve>* span) {
span->dumpBounded(0);
}
void DontCallDumpSpanBounded();
void DontCallDumpSpanBounded() { // exists to instantiate the templates
SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
DumpBounded(&q1q2);
DumpBounded(&q1k2);
DumpBounded(&q1c2);
DumpBounded(&k1q2);
DumpBounded(&k1k2);
DumpBounded(&k1c2);
DumpBounded(&c1q2);
DumpBounded(&c1k2);
DumpBounded(&c1c2);
}
template <typename TCurve, typename OppCurve>
void DumpCoin(const SkTSpan<TCurve, OppCurve>* span) {
span->dumpCoin();
}
void DontCallDumpSpanCoin();
void DontCallDumpSpanCoin() { // exists to instantiate the templates
SkTSpan<SkDQuad, SkDQuad> q1q2; q1q2.debugInit();
SkTSpan<SkDQuad, SkDConic> q1k2; q1k2.debugInit();
SkTSpan<SkDQuad, SkDCubic> q1c2; q1c2.debugInit();
SkTSpan<SkDConic, SkDQuad> k1q2; k1q2.debugInit();
SkTSpan<SkDConic, SkDConic> k1k2; k1k2.debugInit();
SkTSpan<SkDConic, SkDCubic> k1c2; k1c2.debugInit();
SkTSpan<SkDCubic, SkDQuad> c1q2; c1q2.debugInit();
SkTSpan<SkDCubic, SkDConic> c1k2; c1k2.debugInit();
SkTSpan<SkDCubic, SkDCubic> c1c2; c1c2.debugInit();
DumpCoin(&q1q2);
DumpCoin(&q1k2);
DumpCoin(&q1c2);
DumpCoin(&k1q2);
DumpCoin(&k1k2);
DumpCoin(&k1c2);
DumpCoin(&c1q2);
DumpCoin(&c1k2);
DumpCoin(&c1c2);
}
static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
SkDebugf("\n<div id=\"quad%d\">\n", testNo);
quad1.dumpInner();
SkDebugf("}}, ");
quad2.dump();
SkDebugf("</div>\n\n");
}
static void dumpTestTrailer() {
SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
SkDebugf(" var testDivs = [\n");
}
static void dumpTestList(int testNo, double min) {
SkDebugf(" quad%d,", testNo);
if (min > 0) {
SkDebugf(" // %1.9g", min);
}
SkDebugf("\n");
}
void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
SkDebugf("\n");
dumpTestCase(quad1, quad2, testNo);
dumpTestTrailer();
dumpTestList(testNo, 0);
SkDebugf("\n");
}
void DumpT(const SkDQuad& quad, double t) {
SkDLine line = {{quad.ptAtT(t), quad[0]}};
line.dump();
}
const SkOpAngle* SkOpAngle::debugAngle(int id) const {
return this->segment()->debugAngle(id);
}
SkOpContour* SkOpAngle::debugContour(int id) {
return this->segment()->debugContour(id);
}
const SkOpPtT* SkOpAngle::debugPtT(int id) const {
return this->segment()->debugPtT(id);
}
const SkOpSegment* SkOpAngle::debugSegment(int id) const {
return this->segment()->debugSegment(id);
}
int SkOpAngle::debugSign() const {
SkASSERT(fStart->t() != fEnd->t());
return fStart->t() < fEnd->t() ? -1 : 1;
}
const SkOpSpanBase* SkOpAngle::debugSpan(int id) const {
return this->segment()->debugSpan(id);
}
void SkOpAngle::dump() const {
dumpOne(true);
SkDebugf("\n");
}
void SkOpAngle::dumpOne(bool functionHeader) const {
// fSegment->debugValidate();
const SkOpSegment* segment = this->segment();
const SkOpSpan& mSpan = *fStart->starter(fEnd);
if (functionHeader) {
SkDebugf("%s ", __FUNCTION__);
}
SkDebugf("[%d", segment->debugID());
SkDebugf("/%d", debugID());
SkDebugf("] next=");
if (fNext) {
SkDebugf("%d", fNext->fStart->segment()->debugID());
SkDebugf("/%d", fNext->debugID());
} else {
SkDebugf("?");
}
SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fStart->t(), fStart->debugID(),
fEnd->t(), fEnd->debugID());
SkDebugf(" sgn=%d windVal=%d", this->debugSign(), mSpan.windValue());
SkDebugf(" windSum=");
SkPathOpsDebug::WindingPrintf(mSpan.windSum());
if (mSpan.oppValue() != 0 || mSpan.oppSum() != SK_MinS32) {
SkDebugf(" oppVal=%d", mSpan.oppValue());
SkDebugf(" oppSum=");
SkPathOpsDebug::WindingPrintf(mSpan.oppSum());
}
if (mSpan.done()) {
SkDebugf(" done");
}
if (unorderable()) {
SkDebugf(" unorderable");
}
if (segment->operand()) {
SkDebugf(" operand");
}
}
void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
const char* indent = "";
do {
SkDebugf("%s", indent);
next->dumpOne(false);
if (segment == next->fStart->segment()) {
if (this == fNext) {
SkDebugf(" << from");
}
if (to == fNext) {
SkDebugf(" << to");
}
}
SkDebugf("\n");
indent = " ";
next = next->fNext;
} while (next && next != first);
}
void SkOpAngle::dumpCurves() const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
do {
next->fCurvePart.dumpID(next->segment()->debugID());
next = next->fNext;
} while (next && next != first);
}
void SkOpAngle::dumpLoop() const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
do {
next->dumpOne(false);
SkDebugf("\n");
next = next->fNext;
} while (next && next != first);
}
void SkOpAngle::dumpTest() const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
do {
SkDebugf("{ ");
SkOpSegment* segment = next->segment();
segment->dumpPts();
SkDebugf(", %d, %1.9g, %1.9g, {} },\n", SkPathOpsVerbToPoints(segment->verb()) + 1,
next->start()->t(), next->end()->t());
next = next->fNext;
} while (next && next != first);
}
bool SkOpPtT::debugMatchID(int id) const {
int limit = this->debugLoopLimit(false);
int loop = 0;
const SkOpPtT* ptT = this;
do {
if (ptT->debugID() == id) {
return true;
}
} while ((!limit || ++loop <= limit) && (ptT = ptT->next()) && ptT != this);
return false;
}
const SkOpAngle* SkOpPtT::debugAngle(int id) const {
return this->span()->debugAngle(id);
}
SkOpContour* SkOpPtT::debugContour(int id) {
return this->span()->debugContour(id);
}
const SkOpPtT* SkOpPtT::debugPtT(int id) const {
return this->span()->debugPtT(id);
}
const SkOpSegment* SkOpPtT::debugSegment(int id) const {
return this->span()->debugSegment(id);
}
const SkOpSpanBase* SkOpPtT::debugSpan(int id) const {
return this->span()->debugSpan(id);
}
void SkOpPtT::dump() const {
SkDebugf("seg=%d span=%d ptT=%d",
this->segment()->debugID(), this->span()->debugID(), this->debugID());
this->dumpBase();
SkDebugf("\n");
}
void SkOpPtT::dumpAll() const {
contour()->indentDump();
const SkOpPtT* next = this;
int limit = debugLoopLimit(true);
int loop = 0;
do {
SkDebugf("%.*s", contour()->debugIndent(), " ");
SkDebugf("seg=%d span=%d ptT=%d",
next->segment()->debugID(), next->span()->debugID(), next->debugID());
next->dumpBase();
SkDebugf("\n");
if (limit && ++loop >= limit) {
SkDebugf("*** abort loop ***\n");
break;
}
} while ((next = next->fNext) && next != this);
contour()->outdentDump();
}
void SkOpPtT::dumpBase() const {
SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g)%s%s", this->fT, this->fPt.fX, this->fPt.fY,
this->fDuplicatePt ? " dup" : "", this->fDeleted ? " deleted" : "");
}
const SkOpAngle* SkOpSpanBase::debugAngle(int id) const {
return this->segment()->debugAngle(id);
}
SkOpContour* SkOpSpanBase::debugContour(int id) {
return this->segment()->debugContour(id);
}
const SkOpPtT* SkOpSpanBase::debugPtT(int id) const {
return this->segment()->debugPtT(id);
}
const SkOpSegment* SkOpSpanBase::debugSegment(int id) const {
return this->segment()->debugSegment(id);
}
const SkOpSpanBase* SkOpSpanBase::debugSpan(int id) const {
return this->segment()->debugSpan(id);
}
void SkOpSpanBase::dump() const {
this->dumpAll();
SkDebugf("\n");
}
void SkOpSpanBase::dumpAll() const {
SkDebugf("%.*s", contour()->debugIndent(), " ");
SkDebugf("seg=%d span=%d", this->segment()->debugID(), this->debugID());
this->dumpBase();
SkDebugf("\n");
this->fPtT.dumpAll();
}
void SkOpSpanBase::dumpBase() const {
if (this->fAligned) {
SkDebugf(" aligned");
}
if (this->fChased) {
SkDebugf(" chased");
}
if (!this->final()) {
this->upCast()->dumpSpan();
}
const SkOpSpanBase* coin = this->coinEnd();
if (this != coin) {
SkDebugf(" coinEnd seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
} else if (this->final() || !this->upCast()->isCoincident()) {
const SkOpPtT* oPt = this->ptT()->next();
SkDebugf(" seg/span=%d/%d", oPt->segment()->debugID(), oPt->span()->debugID());
}
SkDebugf(" adds=%d", fSpanAdds);
}
void SkOpSpanBase::dumpCoin() const {
const SkOpSpan* span = this->upCastable();
if (!span) {
return;
}
if (!span->isCoincident()) {
return;
}
span->dumpCoin();
}
void SkOpSpan::dumpCoin() const {
const SkOpSpan* coincident = fCoincident;
bool ok = debugCoinLoopCheck();
this->dump();
int loop = 0;
do {
coincident->dump();
if (!ok && ++loop > 10) {
SkDebugf("*** abort loop ***\n");
break;
}
} while ((coincident = coincident->fCoincident) != this);
}
bool SkOpSpan::dumpSpan() const {
SkOpSpan* coin = fCoincident;
if (this != coin) {
SkDebugf(" coinStart seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
}
SkDebugf(" windVal=%d", this->windValue());
SkDebugf(" windSum=");
SkPathOpsDebug::WindingPrintf(this->windSum());
if (this->oppValue() != 0 || this->oppSum() != SK_MinS32) {
SkDebugf(" oppVal=%d", this->oppValue());
SkDebugf(" oppSum=");
SkPathOpsDebug::WindingPrintf(this->oppSum());
}
if (this->done()) {
SkDebugf(" done");
}
return this != coin;
}
const SkOpAngle* SkOpSegment::debugAngle(int id) const {
return this->contour()->debugAngle(id);
}
SkOpContour* SkOpSegment::debugContour(int id) {
return this->contour()->debugContour(id);
}
const SkOpPtT* SkOpSegment::debugPtT(int id) const {
return this->contour()->debugPtT(id);
}
const SkOpSegment* SkOpSegment::debugSegment(int id) const {
return this->contour()->debugSegment(id);
}
const SkOpSpanBase* SkOpSegment::debugSpan(int id) const {
return this->contour()->debugSpan(id);
}
void SkOpSegment::dump() const {
SkDebugf("%.*s", contour()->debugIndent(), " ");
this->dumpPts();
const SkOpSpanBase* span = &fHead;
contour()->indentDump();
do {
SkDebugf("%.*s span=%d ", contour()->debugIndent(), " ", span->debugID());
span->ptT()->dumpBase();
span->dumpBase();
SkDebugf("\n");
} while (!span->final() && (span = span->upCast()->next()));
contour()->outdentDump();
}
void SkOpSegment::dumpAll() const {
SkDebugf("%.*s", contour()->debugIndent(), " ");
this->dumpPts();
const SkOpSpanBase* span = &fHead;
contour()->indentDump();
do {
span->dumpAll();
} while (!span->final() && (span = span->upCast()->next()));
contour()->outdentDump();
}
void SkOpSegment::dumpAngles() const {
SkDebugf("seg=%d\n", debugID());
const SkOpSpanBase* span = &fHead;
do {
const SkOpAngle* fAngle = span->fromAngle();
const SkOpAngle* tAngle = span->final() ? nullptr : span->upCast()->toAngle();
if (fAngle) {
SkDebugf(" span=%d from=%d ", span->debugID(), fAngle->debugID());
fAngle->dumpTo(this, tAngle);
}
if (tAngle) {
SkDebugf(" span=%d to=%d ", span->debugID(), tAngle->debugID());
tAngle->dumpTo(this, fAngle);
}
} while (!span->final() && (span = span->upCast()->next()));
}
void SkOpSegment::dumpCoin() const {
const SkOpSpan* span = &fHead;
do {
span->dumpCoin();
} while ((span = span->next()->upCastable()));
}
void SkOpSegment::dumpPtsInner(const char* prefix) const {
int last = SkPathOpsVerbToPoints(fVerb);
SkDebugf("%s=%d {{", prefix, this->debugID());
if (fVerb == SkPath::kConic_Verb) {
SkDebugf("{");
}
int index = 0;
do {
SkDPoint::Dump(fPts[index]);
SkDebugf(", ");
} while (++index < last);
SkDPoint::Dump(fPts[index]);
SkDebugf("}}");
if (fVerb == SkPath::kConic_Verb) {
SkDebugf(", %1.9gf}", fWeight);
}
}
void SkOpSegment::dumpPts(const char* prefix) const {
dumpPtsInner(prefix);
SkDebugf("\n");
}
void SkCoincidentSpans::dump() const {
SkDebugf("- seg=%d span=%d ptT=%d ", fCoinPtTStart->segment()->debugID(),
fCoinPtTStart->span()->debugID(), fCoinPtTStart->debugID());
fCoinPtTStart->dumpBase();
SkDebugf(" span=%d ptT=%d ", fCoinPtTEnd->span()->debugID(), fCoinPtTEnd->debugID());
fCoinPtTEnd->dumpBase();
if (fCoinPtTStart->segment()->operand()) {
SkDebugf(" operand");
}
if (fCoinPtTStart->segment()->isXor()) {
SkDebugf(" xor");
}
SkDebugf("\n");
SkDebugf("+ seg=%d span=%d ptT=%d ", fOppPtTStart->segment()->debugID(),
fOppPtTStart->span()->debugID(), fOppPtTStart->debugID());
fOppPtTStart->dumpBase();
SkDebugf(" span=%d ptT=%d ", fOppPtTEnd->span()->debugID(), fOppPtTEnd->debugID());
fOppPtTEnd->dumpBase();
if (fOppPtTStart->segment()->operand()) {
SkDebugf(" operand");
}
if (fOppPtTStart->segment()->isXor()) {
SkDebugf(" xor");
}
SkDebugf("\n");
}
void SkOpCoincidence::dump() const {
SkCoincidentSpans* span = fHead;
while (span) {
span->dump();
span = span->fNext;
}
if (!fTop || fHead == fTop) {
return;
}
SkDebugf("top:\n");
span = fTop;
if (fHead) {
span->dump();
return;
}
while (span) {
span->dump();
span = span->fNext;
}
}
void SkOpContour::dump() const {
SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
if (!fCount) {
return;
}
const SkOpSegment* segment = &fHead;
SkDEBUGCODE(fDebugIndent = 0);
this->indentDump();
do {
segment->dump();
} while ((segment = segment->next()));
this->outdentDump();
}
void SkOpContour::dumpAll() const {
SkDebugf("contour=%d count=%d op=%d xor=%d\n", this->debugID(), fCount, fOperand, fXor);
if (!fCount) {
return;
}
const SkOpSegment* segment = &fHead;
SkDEBUGCODE(fDebugIndent = 0);
this->indentDump();
do {
segment->dumpAll();
} while ((segment = segment->next()));
this->outdentDump();
}
void SkOpContour::dumpAngles() const {
SkDebugf("contour=%d\n", this->debugID());
const SkOpSegment* segment = &fHead;
do {
SkDebugf(" seg=%d ", segment->debugID());
segment->dumpAngles();
} while ((segment = segment->next()));
}
void SkOpContour::dumpPt(int index) const {
const SkOpSegment* segment = &fHead;
do {
if (segment->debugID() == index) {
segment->dumpPts();
}
} while ((segment = segment->next()));
}
void SkOpContour::dumpPts(const char* prefix) const {
SkDebugf("contour=%d\n", this->debugID());
const SkOpSegment* segment = &fHead;
do {
SkDebugf(" %s=%d ", prefix, segment->debugID());
segment->dumpPts(prefix);
} while ((segment = segment->next()));
}
void SkOpContour::dumpPtsX(const char* prefix) const {
if (!this->fCount) {
SkDebugf("<empty>\n");
return;
}
const SkOpSegment* segment = &fHead;
do {
segment->dumpPts(prefix);
} while ((segment = segment->next()));
}
void SkOpContour::dumpSegment(int index) const {
debugSegment(index)->dump();
}
void SkOpContour::dumpSegments(const char* prefix, SkPathOp op) const {
bool firstOp = false;
const SkOpContour* c = this;
do {
if (!firstOp && c->operand() && op >= 0) {
#if DEBUG_ACTIVE_OP
SkDebugf("op %s\n", SkPathOpsDebug::kPathOpStr[op]);
#endif
firstOp = true;
}
c->dumpPtsX(prefix);
} while ((c = c->next()));
}
void SkOpContour::dumpSpan(int index) const {
debugSpan(index)->dump();
}
void SkOpContour::dumpSpans() const {
SkDebugf("contour=%d\n", this->debugID());
const SkOpSegment* segment = &fHead;
do {
SkDebugf(" seg=%d ", segment->debugID());
segment->dump();
} while ((segment = segment->next()));
}
void SkOpCurve::dump() const {
int count = SkPathOpsVerbToPoints(SkDEBUGRELEASE(fVerb, SkPath::kCubic_Verb));
SkDebugf("{{");
int index;
for (index = 0; index <= count - 1; ++index) {
SkDebugf("{%1.9gf,%1.9gf}, ", fPts[index].fX, fPts[index].fY);
}
SkDebugf("{%1.9gf,%1.9gf}}}\n", fPts[index].fX, fPts[index].fY);
}
#ifdef SK_DEBUG
const SkOpAngle* SkOpGlobalState::debugAngle(int id) const {
const SkOpContour* contour = fContourHead;
do {
const SkOpSegment* segment = contour->first();
while (segment) {
const SkOpSpan* span = segment->head();
do {
SkOpAngle* angle = span->fromAngle();
if (angle && angle->debugID() == id) {
return angle;
}
angle = span->toAngle();
if (angle && angle->debugID() == id) {
return angle;
}
} while ((span = span->next()->upCastable()));
const SkOpSpanBase* tail = segment->tail();
SkOpAngle* angle = tail->fromAngle();
if (angle && angle->debugID() == id) {
return angle;
}
segment = segment->next();
}
} while ((contour = contour->next()));
return nullptr;
}
SkOpContour* SkOpGlobalState::debugContour(int id) {
SkOpContour* contour = fContourHead;
do {
if (contour->debugID() == id) {
return contour;
}
} while ((contour = contour->next()));
return nullptr;
}
const SkOpPtT* SkOpGlobalState::debugPtT(int id) const {
const SkOpContour* contour = fContourHead;
do {
const SkOpSegment* segment = contour->first();
while (segment) {
const SkOpSpan* span = segment->head();
do {
const SkOpPtT* ptT = span->ptT();
if (ptT->debugMatchID(id)) {
return ptT;
}
} while ((span = span->next()->upCastable()));
const SkOpSpanBase* tail = segment->tail();
const SkOpPtT* ptT = tail->ptT();
if (ptT->debugMatchID(id)) {
return ptT;
}
segment = segment->next();
}
} while ((contour = contour->next()));
return nullptr;
}
const SkOpSegment* SkOpGlobalState::debugSegment(int id) const {
const SkOpContour* contour = fContourHead;
do {
const SkOpSegment* segment = contour->first();
while (segment) {
if (segment->debugID() == id) {
return segment;
}
segment = segment->next();
}
} while ((contour = contour->next()));
return nullptr;
}
const SkOpSpanBase* SkOpGlobalState::debugSpan(int id) const {
const SkOpContour* contour = fContourHead;
do {
const SkOpSegment* segment = contour->first();
while (segment) {
const SkOpSpan* span = segment->head();
do {
if (span->debugID() == id) {
return span;
}
} while ((span = span->next()->upCastable()));
const SkOpSpanBase* tail = segment->tail();
if (tail->debugID() == id) {
return tail;
}
segment = segment->next();
}
} while ((contour = contour->next()));
return nullptr;
}
#endif
#if DEBUG_T_SECT_DUMP > 1
int gDumpTSectNum;
#endif