27c8eb8ffd
to compute the overlapping ranges and combine the winding into a single destination. This computes coincidence more rigorously, fixing the edge cases exposed by this bug. Also, add the ability to debug and dump pathop structures from the coincident context. TBR=reed@google.com BUG=skia:3651 Review URL: https://codereview.chromium.org/1182493015
1363 lines
40 KiB
C++
Executable File
1363 lines
40 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("{{");
|
|
int index = 0;
|
|
do {
|
|
fPts[index].dump();
|
|
SkDebugf(", ");
|
|
} while (++index < 2);
|
|
fPts[index].dump();
|
|
SkDebugf("}, %1.9g", 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 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() ? NULL : 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 {
|
|
int last = SkPathOpsVerbToPoints(fVerb);
|
|
SkDebugf("seg=%d {{", 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 {
|
|
dumpPtsInner();
|
|
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) {
|
|
return;
|
|
}
|
|
SkDebugf("top:\n");
|
|
span = fTop;
|
|
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 {
|
|
SkDebugf("contour=%d\n", this->debugID());
|
|
const SkOpSegment* segment = &fHead;
|
|
do {
|
|
SkDebugf(" seg=%d ", segment->debugID());
|
|
segment->dumpPts();
|
|
} while ((segment = segment->next()));
|
|
}
|
|
|
|
void SkOpContour::dumpPtsX() const {
|
|
if (!this->fCount) {
|
|
SkDebugf("<empty>\n");
|
|
return;
|
|
}
|
|
const SkOpSegment* segment = &fHead;
|
|
do {
|
|
segment->dumpPts();
|
|
} while ((segment = segment->next()));
|
|
}
|
|
|
|
void SkOpContour::dumpSegment(int index) const {
|
|
debugSegment(index)->dump();
|
|
}
|
|
|
|
void SkOpContour::dumpSegments(SkPathOp op) const {
|
|
bool firstOp = false;
|
|
const SkOpContour* c = this;
|
|
do {
|
|
if (!firstOp && c->operand()) {
|
|
#if DEBUG_ACTIVE_OP
|
|
SkDebugf("op %s\n", SkPathOpsDebug::kPathOpStr[op]);
|
|
#endif
|
|
firstOp = true;
|
|
}
|
|
c->dumpPtsX();
|
|
} 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 NULL;
|
|
}
|
|
|
|
SkOpContour* SkOpGlobalState::debugContour(int id) {
|
|
SkOpContour* contour = fContourHead;
|
|
do {
|
|
if (contour->debugID() == id) {
|
|
return contour;
|
|
}
|
|
} while ((contour = contour->next()));
|
|
return NULL;
|
|
}
|
|
|
|
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 NULL;
|
|
}
|
|
|
|
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 NULL;
|
|
}
|
|
|
|
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 NULL;
|
|
}
|
|
#endif
|
|
|
|
#if DEBUG_T_SECT_DUMP > 1
|
|
int gDumpTSectNum;
|
|
#endif
|