diff options
-rw-r--r-- | src/pathops/SkOpCoincidence.cpp | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.h | 235 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTSect.h | 3 | ||||
-rw-r--r-- | tests/PathOpsDebug.cpp | 288 | ||||
-rw-r--r-- | tests/PathOpsSimplifyFailTest.cpp | 51 | ||||
-rw-r--r-- | tests/PathOpsTSectDebug.h | 2 |
7 files changed, 487 insertions, 107 deletions
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp index 8fa42a5c4e..3251ec4371 100644 --- a/src/pathops/SkOpCoincidence.cpp +++ b/src/pathops/SkOpCoincidence.cpp @@ -691,7 +691,7 @@ bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, if (overlap && os && oe && overlap->contains(os, oe)) { return true; } - SkASSERT(!cs || !cs->deleted()); + FAIL_IF(cs && cs->deleted()); FAIL_IF(os && os->deleted()); SkASSERT(!ce || !ce->deleted()); FAIL_IF(oe && oe->deleted()); @@ -1098,7 +1098,7 @@ bool SkOpCoincidence::apply(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { FAIL_IF(windValue == -1); start->setWindValue(windValue); start->setOppValue(oppValue); - FAIL_IF(oWindValue == -1); + FAIL_IF(oWindValue <= -1); oStart->setWindValue(oWindValue); oStart->setOppValue(oOppValue); if (!windValue && !oppValue) { diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp index f13b958a84..346db4b340 100644 --- a/src/pathops/SkPathOpsDebug.cpp +++ b/src/pathops/SkPathOpsDebug.cpp @@ -47,8 +47,6 @@ const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor", "rdi #if defined SK_DEBUG || !FORCE_RELEASE -const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; - int SkPathOpsDebug::gContourID = 0; int SkPathOpsDebug::gSegmentID = 0; @@ -3124,3 +3122,12 @@ void SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) { } #endif + +// global path dumps for msvs Visual Studio 17 to use from Immediate Window +void Dump(const SkPath& path) { + path.dump(); +} + +void DumpHex(const SkPath& path) { + path.dumpHex(); +} diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index afdfb32be1..9aec715de1 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -14,7 +14,36 @@ #include <stdio.h> enum class SkOpPhase : char; +struct SkDQuad; +class SkOpAngle; +class SkOpCoincidence; +class SkOpContour; class SkOpContourHead; +class SkOpPtT; +class SkOpSegment; +class SkOpSpan; +class SkOpSpanBase; +struct SkDPoint; +struct SkDLine; +struct SkDQuad; +struct SkDConic; +struct SkDCubic; +template<typename TCurve, typename OppCurve> class SkTSect; + +// dummy classes to fool msvs Visual Studio 2018 Immediate Window +#define DummyClasses(a, b) \ +class SkDebugTCoincident##a##b; \ +class SkDebugTSect##a##b; \ +class SkDebugTSpan##a##b + +DummyClasses(Quad, Quad); +DummyClasses(Conic, Quad); +DummyClasses(Conic, Conic); +DummyClasses(Cubic, Quad); +DummyClasses(Cubic, Conic); +DummyClasses(Cubic, Cubic); + +#undef DummyClasses #ifdef SK_RELEASE #define FORCE_RELEASE 1 @@ -97,7 +126,7 @@ class SkOpContourHead; #define DEBUG_PERP 1 #define DEBUG_SHOW_TEST_NAME 1 #define DEBUG_SORT 1 -#define DEBUG_T_SECT 0 +#define DEBUG_T_SECT 0 // enabling may trigger validate asserts even though op does not fail #define DEBUG_T_SECT_DUMP 0 // Use 1 normally. Use 2 to number segments, 3 for script output #define DEBUG_T_SECT_LOOP_COUNT 0 #define DEBUG_VALIDATE 1 @@ -233,8 +262,6 @@ class SkOpContourHead; class SkPathOpsDebug { public: - static const char* kLVerbStr[]; - #if DEBUG_COIN struct GlitchLog; @@ -311,7 +338,18 @@ public: #if DEBUG_ACTIVE_OP static const char* kPathOpStr[]; #endif + static bool gRunFail; + static bool gVeryVerbose; + +#if DEBUG_ACTIVE_SPANS + static SkString gActiveSpans; +#endif +#if DEBUG_DUMP_VERIFY + static bool gDumpOp; + static bool gVerifyOp; +#endif + static const char* OpStr(SkPathOp ); static void MathematicaIze(char* str, size_t bufferSize); static bool ValidWind(int winding); static void WindingPrintf(int winding); @@ -324,86 +362,157 @@ public: SkPathOpsDebug::DeleteNameStr))) static void BumpTestName(char* ); #endif - static const char* OpStr(SkPathOp ); static void ShowActiveSpans(SkOpContourHead* contourList); static void ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration); static void ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name); - static bool ChaseContains(const SkTDArray<class SkOpSpanBase*>& , const class SkOpSpanBase* ); + static bool ChaseContains(const SkTDArray<SkOpSpanBase*>& , const SkOpSpanBase* ); static void CheckHealth(class SkOpContourHead* contourList); - static const class SkOpAngle* DebugAngleAngle(const class SkOpAngle*, int id); - static class SkOpContour* DebugAngleContour(class SkOpAngle*, int id); - static const class SkOpPtT* DebugAnglePtT(const class SkOpAngle*, int id); - static const class SkOpSegment* DebugAngleSegment(const class SkOpAngle*, int id); - static const class SkOpSpanBase* DebugAngleSpan(const class SkOpAngle*, int id); - - static const class SkOpAngle* DebugContourAngle(class SkOpContour*, int id); - static class SkOpContour* DebugContourContour(class SkOpContour*, int id); - static const class SkOpPtT* DebugContourPtT(class SkOpContour*, int id); - static const class SkOpSegment* DebugContourSegment(class SkOpContour*, int id); - static const class SkOpSpanBase* DebugContourSpan(class SkOpContour*, int id); - - static const class SkOpAngle* DebugCoincidenceAngle(class SkOpCoincidence*, int id); - static class SkOpContour* DebugCoincidenceContour(class SkOpCoincidence*, int id); - static const class SkOpPtT* DebugCoincidencePtT(class SkOpCoincidence*, int id); - static const class SkOpSegment* DebugCoincidenceSegment(class SkOpCoincidence*, int id); - static const class SkOpSpanBase* DebugCoincidenceSpan(class SkOpCoincidence*, int id); - - static const class SkOpAngle* DebugPtTAngle(const class SkOpPtT*, int id); - static class SkOpContour* DebugPtTContour(class SkOpPtT*, int id); - static const class SkOpPtT* DebugPtTPtT(const class SkOpPtT*, int id); - static const class SkOpSegment* DebugPtTSegment(const class SkOpPtT*, int id); - static const class SkOpSpanBase* DebugPtTSpan(const class SkOpPtT*, int id); - - static const class SkOpAngle* DebugSegmentAngle(const class SkOpSegment*, int id); - static class SkOpContour* DebugSegmentContour(class SkOpSegment*, int id); - static const class SkOpPtT* DebugSegmentPtT(const class SkOpSegment*, int id); - static const class SkOpSegment* DebugSegmentSegment(const class SkOpSegment*, int id); - static const class SkOpSpanBase* DebugSegmentSpan(const class SkOpSegment*, int id); - - static const class SkOpAngle* DebugSpanAngle(const class SkOpSpanBase*, int id); - static class SkOpContour* DebugSpanContour(class SkOpSpanBase*, int id); - static const class SkOpPtT* DebugSpanPtT(const class SkOpSpanBase*, int id); - static const class SkOpSegment* DebugSpanSegment(const class SkOpSpanBase*, int id); - static const class SkOpSpanBase* DebugSpanSpan(const class SkOpSpanBase*, int id); - #if DEBUG_COIN - static void DumpCoinDict(); - static void DumpGlitchType(GlitchType ); + static void DumpCoinDict(); + static void DumpGlitchType(GlitchType ); #endif - static bool gRunFail; - static bool gVeryVerbose; +}; -#if DEBUG_DUMP_VERIFY - static bool gDumpOp; - static bool gVerifyOp; +// Visual Studio 2017 does not permit calling member functions from the Immediate Window. +// Global functions work fine, however. Use globals within a namespace rather than +// static members inside a class. +namespace SkOpDebug { + const SkOpAngle* AngleAngle(const SkOpAngle*, int id); + SkOpContour* AngleContour(SkOpAngle*, int id); + const SkOpPtT* AnglePtT(const SkOpAngle*, int id); + const SkOpSegment* AngleSegment(const SkOpAngle*, int id); + const SkOpSpanBase* AngleSpan(const SkOpAngle*, int id); + + const SkOpAngle* ContourAngle(SkOpContour*, int id); + SkOpContour* ContourContour(SkOpContour*, int id); + const SkOpPtT* ContourPtT(SkOpContour*, int id); + const SkOpSegment* ContourSegment(SkOpContour*, int id); + const SkOpSpanBase* ContourSpan(SkOpContour*, int id); + + const SkOpAngle* CoincidenceAngle(SkOpCoincidence*, int id); + SkOpContour* CoincidenceContour(SkOpCoincidence*, int id); + const SkOpPtT* CoincidencePtT(SkOpCoincidence*, int id); + const SkOpSegment* CoincidenceSegment(SkOpCoincidence*, int id); + const SkOpSpanBase* CoincidenceSpan(SkOpCoincidence*, int id); + + const SkOpAngle* PtTAngle(const SkOpPtT*, int id); + SkOpContour* PtTContour(SkOpPtT*, int id); + const SkOpPtT* PtTPtT(const SkOpPtT*, int id); + const SkOpSegment* PtTSegment(const SkOpPtT*, int id); + const SkOpSpanBase* PtTSpan(const SkOpPtT*, int id); + + const SkOpAngle* SegmentAngle(const SkOpSegment*, int id); + SkOpContour* SegmentContour(SkOpSegment*, int id); + const SkOpPtT* SegmentPtT(const SkOpSegment*, int id); + const SkOpSegment* SegmentSegment(const SkOpSegment*, int id); + const SkOpSpanBase* SegmentSpan(const SkOpSegment*, int id); + + const SkOpAngle* SpanAngle(const SkOpSpanBase*, int id); + SkOpContour* SpanContour(SkOpSpanBase*, int id); + const SkOpPtT* SpanPtT(const SkOpSpanBase*, int id); + const SkOpSegment* SpanSegment(const SkOpSpanBase*, int id); + const SkOpSpanBase* SpanSpan(const SkOpSpanBase*, int id); - static void DumpOp(const SkPath& one, const SkPath& two, SkPathOp op, +#if DEBUG_DUMP_VERIFY + void DumpOp(const SkPath& one, const SkPath& two, SkPathOp op, const char* testName); - static void DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op, + void DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op, const char* testName); - static void DumpSimplify(const SkPath& path, const char* testName); - static void DumpSimplify(FILE* file, const SkPath& path, const char* testName); - static void ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op); - static void ReportSimplifyFail(const SkPath& path); - static void VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op, + void DumpSimplify(const SkPath& path, const char* testName); + void DumpSimplify(FILE* file, const SkPath& path, const char* testName); + void ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op); + void ReportSimplifyFail(const SkPath& path); + void VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op, const SkPath& result); - static void VerifySimplify(const SkPath& path, const SkPath& result); + void VerifySimplify(const SkPath& path, const SkPath& result); #endif -#if DEBUG_ACTIVE_SPANS - static SkString gActiveSpans; -#endif - -}; - -struct SkDQuad; + // global path dumps for msvs Visual Studio 17 to use from Immediate Window + void Dump(const SkOpContour& ); + void DumpAll(const SkOpContour& ); + void DumpAngles(const SkOpContour& ); + void DumpContours(const SkOpContour& ); + void DumpContoursAll(const SkOpContour& ); + void DumpContoursAngles(const SkOpContour& ); + void DumpContoursPts(const SkOpContour& ); + void DumpContoursPt(const SkOpContour& , int segmentID); + void DumpContoursSegment(const SkOpContour& , int segmentID); + void DumpContoursSpan(const SkOpContour& , int segmentID); + void DumpContoursSpans(const SkOpContour& ); + void DumpPt(const SkOpContour& , int ); + void DumpPts(const SkOpContour& , const char* prefix = "seg"); + void DumpSegment(const SkOpContour& , int ); + void DumpSegments(const SkOpContour& , const char* prefix = "seg", SkPathOp op = (SkPathOp) -1); + void DumpSpan(const SkOpContour& , int ); + void DumpSpans(const SkOpContour& ); + + void Dump(const SkOpSegment& ); + void DumpAll(const SkOpSegment& ); + void DumpAngles(const SkOpSegment& ); + void DumpCoin(const SkOpSegment& ); + void DumpPts(const SkOpSegment& , const char* prefix = "seg"); + + void Dump(const SkOpPtT& ); + void DumpAll(const SkOpPtT& ); + + void Dump(const SkOpSpanBase& ); + void DumpCoin(const SkOpSpanBase& ); + void DumpAll(const SkOpSpanBase& ); + + void DumpCoin(const SkOpSpan& ); + bool DumpSpan(const SkOpSpan& ); + + void Dump(const SkDConic& ); + void DumpID(const SkDConic& , int id); + + void Dump(const SkDCubic& ); + void DumpID(const SkDCubic& , int id); + + void Dump(const SkDLine& ); + void DumpID(const SkDLine& , int id); + + void Dump(const SkDQuad& ); + void DumpID(const SkDQuad& , int id); + + void Dump(const SkDPoint& ); + +// dummy declarations to fool msvs Visual Studio 2018 Immediate Window +#define DummyDeclarations(a, b) \ + void Dump(const SkDebugTCoincident##a##b& ); \ + \ + void Dump(const SkDebugTSect##a##b& ); \ + void DumpBoth(const SkDebugTSect##a##b& , SkDebugTSect##a##b* ); \ + void DumpBounded(const SkDebugTSect##a##b& , int id); \ + void DumpBounds(const SkDebugTSect##a##b& ); \ + void DumpCoin(const SkDebugTSect##a##b& ); \ + void DumpCoinCurves(const SkDebugTSect##a##b& ); \ + void DumpCurves(const SkDebugTSect##a##b& ); \ + \ + void Dump(const SkDebugTSpan##a##b& ); \ + void DumpAll(const SkDebugTSpan##a##b& ); \ + void DumpBounded(const SkDebugTSpan##a##b& , int id); \ + void DumpBounds(const SkDebugTSpan##a##b& ); \ + void DumpCoin(const SkDebugTSpan##a##b& ) + + DummyDeclarations(Quad, Quad); + DummyDeclarations(Conic, Quad); + DummyDeclarations(Conic, Conic); + DummyDeclarations(Cubic, Quad); + DummyDeclarations(Cubic, Conic); + DummyDeclarations(Cubic, Cubic); +#undef DummyDeclarations +} // generates tools/path_sorter.htm and path_visualizer.htm compatible data void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo); void DumpT(const SkDQuad& quad, double t); +// global path dumps for msvs Visual Studio 17 to use from Immediate Window +void Dump(const SkPath& path); +void DumpHex(const SkPath& path); + #endif diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h index 833e735da6..1e78f2a108 100644 --- a/src/pathops/SkPathOpsTSect.h +++ b/src/pathops/SkPathOpsTSect.h @@ -415,6 +415,7 @@ SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing( next->fPrev = result; } result->resetBounds(fCurve); + // world may not be consistent to call validate here result->validate(); return result; } @@ -1797,6 +1798,7 @@ void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first final->fPrev = first; } first->fNext = final; + // world may not be ready for validation here first->validate(); } @@ -1888,6 +1890,7 @@ bool SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) { if (next->fStartT > next->fEndT) { return false; } + // world may not be ready for validate here next->validate(); } } else { diff --git a/tests/PathOpsDebug.cpp b/tests/PathOpsDebug.cpp index 8324f37dd4..942f99c7ae 100644 --- a/tests/PathOpsDebug.cpp +++ b/tests/PathOpsDebug.cpp @@ -208,130 +208,134 @@ void SkIntersections::dump() const { SkDebugf("\n"); } -const SkOpAngle* SkPathOpsDebug::DebugAngleAngle(const SkOpAngle* angle, int id) { +namespace SkOpDebug { + +const ::SkOpAngle* AngleAngle(const ::SkOpAngle* angle, int id) { return angle->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugAngleContour(SkOpAngle* angle, int id) { +::SkOpContour* AngleContour(::SkOpAngle* angle, int id) { return angle->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugAnglePtT(const SkOpAngle* angle, int id) { +const ::SkOpPtT* AnglePtT(const ::SkOpAngle* angle, int id) { return angle->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugAngleSegment(const SkOpAngle* angle, int id) { +const ::SkOpSegment* AngleSegment(const ::SkOpAngle* angle, int id) { return angle->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugAngleSpan(const SkOpAngle* angle, int id) { +const ::SkOpSpanBase* AngleSpan(const ::SkOpAngle* angle, int id) { return angle->debugSpan(id); } -const SkOpAngle* SkPathOpsDebug::DebugContourAngle(SkOpContour* contour, int id) { +const ::SkOpAngle* ContourAngle(::SkOpContour* contour, int id) { return contour->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugContourContour(SkOpContour* contour, int id) { +::SkOpContour* ContourContour(::SkOpContour* contour, int id) { return contour->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugContourPtT(SkOpContour* contour, int id) { +const ::SkOpPtT* ContourPtT(::SkOpContour* contour, int id) { return contour->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugContourSegment(SkOpContour* contour, int id) { +const ::SkOpSegment* ContourSegment(::SkOpContour* contour, int id) { return contour->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugContourSpan(SkOpContour* contour, int id) { +const ::SkOpSpanBase* ContourSpan(::SkOpContour* contour, int id) { return contour->debugSpan(id); } -const SkOpAngle* SkPathOpsDebug::DebugCoincidenceAngle(SkOpCoincidence* coin, int id) { +const ::SkOpAngle* CoincidenceAngle(::SkOpCoincidence* coin, int id) { return coin->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugCoincidenceContour(SkOpCoincidence* coin, int id) { +::SkOpContour* CoincidenceContour(::SkOpCoincidence* coin, int id) { return coin->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugCoincidencePtT(SkOpCoincidence* coin, int id) { +const ::SkOpPtT* CoincidencePtT(::SkOpCoincidence* coin, int id) { return coin->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugCoincidenceSegment(SkOpCoincidence* coin, int id) { +const ::SkOpSegment* CoincidenceSegment(::SkOpCoincidence* coin, int id) { return coin->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugCoincidenceSpan(SkOpCoincidence* coin, int id) { +const ::SkOpSpanBase* CoincidenceSpan(::SkOpCoincidence* coin, int id) { return coin->debugSpan(id); } -const SkOpAngle* SkPathOpsDebug::DebugPtTAngle(const SkOpPtT* ptT, int id) { +const ::SkOpAngle* PtTAngle(const ::SkOpPtT* ptT, int id) { return ptT->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugPtTContour(SkOpPtT* ptT, int id) { +::SkOpContour* PtTContour(::SkOpPtT* ptT, int id) { return ptT->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugPtTPtT(const SkOpPtT* ptT, int id) { +const ::SkOpPtT* PtTPtT(const ::SkOpPtT* ptT, int id) { return ptT->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugPtTSegment(const SkOpPtT* ptT, int id) { +const ::SkOpSegment* PtTSegment(const ::SkOpPtT* ptT, int id) { return ptT->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugPtTSpan(const SkOpPtT* ptT, int id) { +const ::SkOpSpanBase* PtTSpan(const ::SkOpPtT* ptT, int id) { return ptT->debugSpan(id); } -const SkOpAngle* SkPathOpsDebug::DebugSegmentAngle(const SkOpSegment* span, int id) { +const ::SkOpAngle* SegmentAngle(const ::SkOpSegment* span, int id) { return span->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugSegmentContour(SkOpSegment* span, int id) { +::SkOpContour* SegmentContour(::SkOpSegment* span, int id) { return span->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugSegmentPtT(const SkOpSegment* span, int id) { +const ::SkOpPtT* SegmentPtT(const ::SkOpSegment* span, int id) { return span->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugSegmentSegment(const SkOpSegment* span, int id) { +const ::SkOpSegment* SegmentSegment(const ::SkOpSegment* span, int id) { return span->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugSegmentSpan(const SkOpSegment* span, int id) { +const ::SkOpSpanBase* SegmentSpan(const ::SkOpSegment* span, int id) { return span->debugSpan(id); } -const SkOpAngle* SkPathOpsDebug::DebugSpanAngle(const SkOpSpanBase* span, int id) { +const ::SkOpAngle* SpanAngle(const ::SkOpSpanBase* span, int id) { return span->debugAngle(id); } -SkOpContour* SkPathOpsDebug::DebugSpanContour(SkOpSpanBase* span, int id) { +::SkOpContour* SpanContour(::SkOpSpanBase* span, int id) { return span->debugContour(id); } -const SkOpPtT* SkPathOpsDebug::DebugSpanPtT(const SkOpSpanBase* span, int id) { +const ::SkOpPtT* SpanPtT(const ::SkOpSpanBase* span, int id) { return span->debugPtT(id); } -const SkOpSegment* SkPathOpsDebug::DebugSpanSegment(const SkOpSpanBase* span, int id) { +const ::SkOpSegment* SpanSegment(const ::SkOpSpanBase* span, int id) { return span->debugSegment(id); } -const SkOpSpanBase* SkPathOpsDebug::DebugSpanSpan(const SkOpSpanBase* span, int id) { +const ::SkOpSpanBase* SpanSpan(const ::SkOpSpanBase* span, int id) { return span->debugSpan(id); } +} // namespace SkPathOpsDebug + #if DEBUG_COIN void SkPathOpsDebug::DumpCoinDict() { - gCoinSumChangedDict.dump("unused coin algorithm", false); - gCoinSumVisitedDict.dump("visited coin function", true); + SkPathOpsDebug::gCoinSumChangedDict.dump("unused coin algorithm", false); + SkPathOpsDebug::gCoinSumVisitedDict.dump("visited coin function", true); } void SkPathOpsDebug::CoinDict::dump(const char* str, bool visitCheck) const { @@ -1479,3 +1483,223 @@ const SkOpSpanBase* SkOpGlobalState::debugSpan(int id) const { #if DEBUG_T_SECT_DUMP > 1 int gDumpTSectNum; #endif + +// global path dumps for msvs Visual Studio 17 to use from Immediate Window +namespace SkOpDebug { + + void Dump(const SkOpContour& contour) { + contour.dump(); + } + + void DumpAll(const SkOpContour& contour) { + contour.dumpAll(); + } + + void DumpAngles(const SkOpContour& contour) { + contour.dumpAngles(); + } + + void DumpContours(const SkOpContour& contour) { + contour.dumpContours(); + } + + void DumpContoursAll(const SkOpContour& contour) { + contour.dumpContoursAll(); + } + + void DumpContoursAngles(const SkOpContour& contour) { + contour.dumpContoursAngles(); + } + + void DumpContoursPts(const SkOpContour& contour) { + contour.dumpContoursPts(); + } + + void DumpContoursPt(const SkOpContour& contour, int segmentID) { + contour.dumpContoursPt(segmentID); + } + + void DumpContoursSegment(const SkOpContour& contour, int segmentID) { + contour.dumpContoursSegment(segmentID); + } + + void DumpContoursSpan(const SkOpContour& contour, int segmentID) { + contour.dumpContoursSpan(segmentID); + } + + void DumpContoursSpans(const SkOpContour& contour) { + contour.dumpContoursSpans(); + } + + void DumpPt(const SkOpContour& contour, int pt) { + contour.dumpPt(pt); + } + + void DumpPts(const SkOpContour& contour, const char* prefix) { + contour.dumpPts(prefix); + } + + void DumpSegment(const SkOpContour& contour, int seg) { + contour.dumpSegment(seg); + } + + void DumpSegments(const SkOpContour& contour, const char* prefix, SkPathOp op) { + contour.dumpSegments(prefix, op); + } + + void DumpSpan(const SkOpContour& contour, int span) { + contour.dumpSpan(span); + } + + void DumpSpans(const SkOpContour& contour ) { + contour.dumpSpans(); + } + + void Dump(const SkOpSegment& segment) { + segment.dump(); + } + + void DumpAll(const SkOpSegment& segment) { + segment.dumpAll(); + } + + void DumpAngles(const SkOpSegment& segment) { + segment.dumpAngles(); + } + + void DumpCoin(const SkOpSegment& segment) { + segment.dumpCoin(); + } + + void DumpPts(const SkOpSegment& segment, const char* prefix) { + segment.dumpPts(prefix); + } + + void Dump(const SkOpPtT& ptT) { + ptT.dump(); + } + + void DumpAll(const SkOpPtT& ptT) { + ptT.dumpAll(); + } + + void Dump(const SkOpSpanBase& spanBase) { + spanBase.dump(); + } + + void DumpCoin(const SkOpSpanBase& spanBase) { + spanBase.dumpCoin(); + } + + void DumpAll(const SkOpSpanBase& spanBase) { + spanBase.dumpAll(); + } + + void DumpCoin(const SkOpSpan& span) { + span.dumpCoin(); + } + + bool DumpSpan(const SkOpSpan& span) { + return span.dumpSpan(); + } + + void Dump(const SkDConic& conic) { + conic.dump(); + } + + void DumpID(const SkDConic& conic, int id) { + conic.dumpID(id); + } + + void Dump(const SkDCubic& cubic) { + cubic.dump(); + } + + void DumpID(const SkDCubic& cubic, int id) { + cubic.dumpID(id); + } + + void Dump(const SkDLine& line) { + line.dump(); + } + + void DumpID(const SkDLine& line, int id) { + line.dumpID(id); + } + + void Dump(const SkDQuad& quad) { + quad.dump(); + } + + void DumpID(const SkDQuad& quad, int id) { + quad.dumpID(id); + } + + void Dump(const SkDPoint& point) { + point.dump(); + } + +// dummy definitions to fool msvs Visual Studio 2018 Immediate Window +#define DummyDefinitions(a, b) \ + \ + void Dump(const SkDebugTCoincident##a##b& curve) { \ + ((const SkTCoincident<SkD##a, SkD##b>& ) curve).dump(); \ + } \ + \ + void Dump(const SkDebugTSect##a##b& curve) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dump(); \ + } \ + \ + void DumpBoth(const SkDebugTSect##a##b& curve, SkDebugTSect##a##b* opp) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpBoth((SkTSect<SkD##b, SkD##a>* ) opp); \ + } \ + \ + void DumpBounded(const SkDebugTSect##a##b& curve, int id) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpBounded(id); \ + } \ + \ + void DumpBounds(const SkDebugTSect##a##b& curve) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpBounds(); \ + } \ + \ + void DumpCoin(const SkDebugTSect##a##b& curve) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpCoin(); \ + } \ + \ + void DumpCoinCurves(const SkDebugTSect##a##b& curve) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpCoinCurves(); \ + } \ + \ + void DumpCurves(const SkDebugTSect##a##b& curve) { \ + ((const SkTSect<SkD##a, SkD##b>& ) curve).dumpCurves(); \ + } \ + \ + void Dump(const SkDebugTSpan##a##b& curve) { \ + ((const SkTSpan<SkD##a, SkD##b>& ) curve).dump(); \ + } \ + \ + void DumpAll(const SkDebugTSpan##a##b& curve) { \ + ((const SkTSpan<SkD##a, SkD##b>& ) curve).dumpAll(); \ + } \ + \ + void DumpBounded(const SkDebugTSpan##a##b& curve, int id) { \ + ((const SkTSpan<SkD##a, SkD##b>& ) curve).dumpBounded(id); \ + } \ + \ + void DumpBounds(const SkDebugTSpan##a##b& curve) { \ + ((const SkTSpan<SkD##a, SkD##b>& ) curve).dumpBounds(); \ + } \ + \ + void DumpCoin(const SkDebugTSpan##a##b& curve) { \ + ((const SkTSpan<SkD##a, SkD##b>& ) curve).dumpCoin(); \ + } + + DummyDefinitions(Quad, Quad); + DummyDefinitions(Conic, Quad); + DummyDefinitions(Conic, Conic); + DummyDefinitions(Cubic, Quad); + DummyDefinitions(Cubic, Conic); + DummyDefinitions(Cubic, Cubic); + +#undef DummyDefinitions +} diff --git a/tests/PathOpsSimplifyFailTest.cpp b/tests/PathOpsSimplifyFailTest.cpp index 58179a2175..eb43ae65ad 100644 --- a/tests/PathOpsSimplifyFailTest.cpp +++ b/tests/PathOpsSimplifyFailTest.cpp @@ -217,20 +217,57 @@ path.close(); static void fuzz_x3(skiatest::Reporter* reporter, const char* filename) { SkPath path; -path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-path.cubicTo(SkBits2Float(0x92743420), SkBits2Float(0x74747474), SkBits2Float(0x0f747c74), SkBits2Float(0xff538565), SkBits2Float(0x74744374), SkBits2Float(0x20437474)); // -7.70571e-28f, 7.74708e+31f, 1.20541e-29f, -2.8116e+38f, 7.74102e+31f, 1.65557e-19f
-path.conicTo(SkBits2Float(0x7474926d), SkBits2Float(0x7c747474), SkBits2Float(0x00170f74), SkBits2Float(0x3a7410d7), SkBits2Float(0x3a3a3a3a)); // 7.7508e+31f, 5.07713e+36f, 2.11776e-39f, 0.000931037f, 0.000710401f
-path.quadTo(SkBits2Float(0x203a3a3a), SkBits2Float(0x7459f43a), SkBits2Float(0x74747474), SkBits2Float(0x2043ad6e)); // 1.57741e-19f, 6.90724e+31f, 7.74708e+31f, 1.65745e-19f
-path.conicTo(SkBits2Float(0x7474b374), SkBits2Float(0x74747474), SkBits2Float(0x0f747c74), SkBits2Float(0xff537065), SkBits2Float(0x74744374)); // 7.75488e+31f, 7.74708e+31f, 1.20541e-29f, -2.81051e+38f, 7.74102e+31f
-path.cubicTo(SkBits2Float(0x3a3a3a3a), SkBits2Float(0x3a2c103a), SkBits2Float(0x7474263a), SkBits2Float(0x74976507), SkBits2Float(0x000000ff), SkBits2Float(0x00000000)); // 0.000710401f, 0.00065637f, 7.7374e+31f, 9.59578e+31f, 3.57331e-43f, 0
+path.setFillType(SkPath::kWinding_FillType); +path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 +path.cubicTo(SkBits2Float(0x92743420), SkBits2Float(0x74747474), SkBits2Float(0x0f747c74), SkBits2Float(0xff538565), SkBits2Float(0x74744374), SkBits2Float(0x20437474)); // -7.70571e-28f, 7.74708e+31f, 1.20541e-29f, -2.8116e+38f, 7.74102e+31f, 1.65557e-19f +path.conicTo(SkBits2Float(0x7474926d), SkBits2Float(0x7c747474), SkBits2Float(0x00170f74), SkBits2Float(0x3a7410d7), SkBits2Float(0x3a3a3a3a)); // 7.7508e+31f, 5.07713e+36f, 2.11776e-39f, 0.000931037f, 0.000710401f +path.quadTo(SkBits2Float(0x203a3a3a), SkBits2Float(0x7459f43a), SkBits2Float(0x74747474), SkBits2Float(0x2043ad6e)); // 1.57741e-19f, 6.90724e+31f, 7.74708e+31f, 1.65745e-19f +path.conicTo(SkBits2Float(0x7474b374), SkBits2Float(0x74747474), SkBits2Float(0x0f747c74), SkBits2Float(0xff537065), SkBits2Float(0x74744374)); // 7.75488e+31f, 7.74708e+31f, 1.20541e-29f, -2.81051e+38f, 7.74102e+31f +path.cubicTo(SkBits2Float(0x3a3a3a3a), SkBits2Float(0x3a2c103a), SkBits2Float(0x7474263a), SkBits2Float(0x74976507), SkBits2Float(0x000000ff), SkBits2Float(0x00000000)); // 0.000710401f, 0.00065637f, 7.7374e+31f, 9.59578e+31f, 3.57331e-43f, 0 testSimplifyFuzz(reporter, path, filename); } +static void fuzz_k1(skiatest::Reporter* reporter, const char* filename) { + SkPath path; +path.setFillType(SkPath::kWinding_FillType); +path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 +path.conicTo(SkBits2Float(0x2073732f), SkBits2Float(0x73f17f00), SkBits2Float(0x737b7b73), SkBits2Float(0x73916773), SkBits2Float(0x00738773)); // 2.0621e-19f, 3.82666e+31f, 1.99245e+31f, 2.30402e+31f, 1.06097e-38f +path.lineTo(SkBits2Float(0x5803736d), SkBits2Float(0x807b5ba1)); // 5.78127e+14f, -1.13286e-38f +path.cubicTo(SkBits2Float(0x7b7f7f7b), SkBits2Float(0x7373737b), SkBits2Float(0x1b617380), SkBits2Float(0x48541b10), SkBits2Float(0x73817373), SkBits2Float(0x00717373)); // 1.32662e+36f, 1.92882e+31f, 1.86489e-22f, 217196, 2.05123e+31f, 1.04188e-38f +path.moveTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b738364), SkBits2Float(0x73607380), SkBits2Float(0x7b738362), SkBits2Float(0x00007180), SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.26439e+36f, 1.77829e+31f, 1.26439e+36f, 4.07161e-41f, 1.92882e+31f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b737364), SkBits2Float(0x73607380), SkBits2Float(0x7b738366), SkBits2Float(0x73737380), SkBits2Float(0x73738873), SkBits2Float(0x96737353)); // 1.26407e+36f, 1.77829e+31f, 1.26439e+36f, 1.92882e+31f, 1.92947e+31f, -1.96658e-25f +path.moveTo(SkBits2Float(0x00640000), SkBits2Float(0x73737373)); // 9.18355e-39f, 1.92882e+31f +path.lineTo(SkBits2Float(0x40005d7b), SkBits2Float(0x58435460)); // 2.00571f, 8.59069e+14f +path.cubicTo(SkBits2Float(0x7b7f7f7b), SkBits2Float(0x7373737b), SkBits2Float(0x1b617380), SkBits2Float(0x48400010), SkBits2Float(0x73817373), SkBits2Float(0x00717373)); // 1.32662e+36f, 1.92882e+31f, 1.86489e-22f, 196608, 2.05123e+31f, 1.04188e-38f +path.moveTo(SkBits2Float(0x06737376), SkBits2Float(0x50001073)); // 4.5788e-35f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b737364), SkBits2Float(0x73737373), SkBits2Float(0x53737388), SkBits2Float(0x00967373), SkBits2Float(0x00640000), SkBits2Float(0x73737373)); // 1.26407e+36f, 1.92882e+31f, 1.04562e+12f, 1.38167e-38f, 9.18355e-39f, 1.92882e+31f +path.lineTo(SkBits2Float(0x40005d7b), SkBits2Float(0x5843546d)); // 2.00571f, 8.59069e+14f +path.cubicTo(SkBits2Float(0x7b7f7f7b), SkBits2Float(0x7373737b), SkBits2Float(0x1b617380), SkBits2Float(0x4840001e), SkBits2Float(0x73817373), SkBits2Float(0x007e7373)); // 1.32662e+36f, 1.92882e+31f, 1.86489e-22f, 196608, 2.05123e+31f, 1.16127e-38f +path.moveTo(SkBits2Float(0x06737376), SkBits2Float(0x50001073)); // 4.5788e-35f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b737364), SkBits2Float(0x73607380), SkBits2Float(0x01008366), SkBits2Float(0x73737380), SkBits2Float(0x737d8873), SkBits2Float(0x7b4e7b53)); // 1.26407e+36f, 1.77829e+31f, 2.36042e-38f, 1.92882e+31f, 2.0087e+31f, 1.07211e+36f +path.cubicTo(SkBits2Float(0x667b7b7b), SkBits2Float(0x73737b7b), SkBits2Float(0x73739167), SkBits2Float(0x40007387), SkBits2Float(0x5803736d), SkBits2Float(0x807b5ba1)); // 2.96898e+23f, 1.92907e+31f, 1.92974e+31f, 2.00705f, 5.78127e+14f, -1.13286e-38f +path.cubicTo(SkBits2Float(0x7b7f7f7b), SkBits2Float(0x7373737b), SkBits2Float(0x1b617380), SkBits2Float(0x48401b10), SkBits2Float(0x73817373), SkBits2Float(0x00717373)); // 1.32662e+36f, 1.92882e+31f, 1.86489e-22f, 196716, 2.05123e+31f, 1.04188e-38f +path.moveTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b737364), SkBits2Float(0x73607380), SkBits2Float(0x7b738366), SkBits2Float(0x00007180), SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.26407e+36f, 1.77829e+31f, 1.26439e+36f, 4.07161e-41f, 1.92882e+31f, 8.59425e+09f +path.cubicTo(SkBits2Float(0x7b737364), SkBits2Float(0x73607380), SkBits2Float(0x79738366), SkBits2Float(0x79797979), SkBits2Float(0xff000079), SkBits2Float(0xf2f2f2ff)); // 1.26407e+36f, 1.77829e+31f, 7.90246e+34f, 8.09591e+34f, -1.70144e+38f, -9.62421e+30f +path.cubicTo(SkBits2Float(0x6579796a), SkBits2Float(0x79795979), SkBits2Float(0x4d4d7b57), SkBits2Float(0x4d574d66), SkBits2Float(0x7968ac4d), SkBits2Float(0x79797979)); // 7.36318e+22f, 8.09185e+34f, 2.15463e+08f, 2.25761e+08f, 7.55067e+34f, 8.09591e+34f +path.quadTo(SkBits2Float(0xf2f27b79), SkBits2Float(0x867b9c7b), SkBits2Float(0xddf2f2f2), SkBits2Float(0x1379796a)); // -9.60571e+30f, -4.73228e-35f, -2.18829e+18f, 3.14881e-27f +path.lineTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.close(); +path.moveTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.quadTo(SkBits2Float(0xe7797979), SkBits2Float(0xf2794d4d), SkBits2Float(0x79a8ddf2), SkBits2Float(0x13132513)); // -1.17811e+24f, -4.93793e+30f, 1.09601e+35f, 1.85723e-27f +path.lineTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.close(); +path.moveTo(SkBits2Float(0x7373739a), SkBits2Float(0x50001073)); // 1.92882e+31f, 8.59425e+09f +path.quadTo(SkBits2Float(0x7b9c7b79), SkBits2Float(0xf4f2d886), SkBits2Float(0xf4f4f4f4), SkBits2Float(0xf4f4f4f4)); // 1.62501e+36f, -1.53922e+32f, -1.5526e+32f, -1.5526e+32f + testSimplifyFuzz(reporter, path, filename); +} #define TEST(test) test(reporter, #test) DEF_TEST(PathOpsSimplifyFail, reporter) { + TEST(fuzz_k1); TEST(fuzz_x3); TEST(fuzz763_2); TEST(fuzz763_1); diff --git a/tests/PathOpsTSectDebug.h b/tests/PathOpsTSectDebug.h index 209152104b..7b0f19d877 100644 --- a/tests/PathOpsTSectDebug.h +++ b/tests/PathOpsTSectDebug.h @@ -67,7 +67,7 @@ void SkTSect<TCurve, OppCurve>::dumpBoth(SkTSect<OppCurve, TCurve>* opp) const { SkDebugf("%d ", ++gDumpTSectNum); #endif this->dump(); - SkDebugf(" "); + SkDebugf("\n"); opp->dump(); SkDebugf("\n"); #elif DEBUG_T_SECT_DUMP == 3 |