123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- /*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkPathOpsDebug_DEFINED
- #define SkPathOpsDebug_DEFINED
- #include "include/core/SkString.h"
- #include "include/core/SkTypes.h"
- #include "include/pathops/SkPathOps.h"
- #include <stdlib.h>
- #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;
- class SkTSect;
- // define this when running fuzz
- // #define IS_FUZZING_WITH_LIBFUZZER
- // 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
- #else
- #define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging
- #endif
- #define DEBUG_UNDER_DEVELOPMENT 0
- #define ONE_OFF_DEBUG 0
- #define ONE_OFF_DEBUG_MATHEMATICA 0
- #if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_ANDROID)
- #define SK_RAND(seed) rand()
- #else
- #define SK_RAND(seed) rand_r(&seed)
- #endif
- #ifdef SK_BUILD_FOR_WIN
- #define SK_SNPRINTF _snprintf
- #else
- #define SK_SNPRINTF snprintf
- #endif
- #define WIND_AS_STRING(x) char x##Str[12]; \
- if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
- else SK_SNPRINTF(x##Str, sizeof(x##Str), "%d", x)
- #if FORCE_RELEASE
- #define DEBUG_ACTIVE_OP 0
- #define DEBUG_ACTIVE_SPANS 0
- #define DEBUG_ADD_INTERSECTING_TS 0
- #define DEBUG_ADD_T 0
- #define DEBUG_ALIGNMENT 0
- #define DEBUG_ANGLE 0
- #define DEBUG_ASSEMBLE 0
- #define DEBUG_COINCIDENCE 0 // sanity checking
- #define DEBUG_COINCIDENCE_DUMP 0 // accumulate and dump which algorithms fired
- #define DEBUG_COINCIDENCE_ORDER 0 // for well behaved curves, check if pairs match up in t-order
- #define DEBUG_COINCIDENCE_VERBOSE 0 // usually whether the next function generates coincidence
- #define DEBUG_CUBIC_BINARY_SEARCH 0
- #define DEBUG_CUBIC_SPLIT 0
- #define DEBUG_DUMP_SEGMENTS 0
- #define DEBUG_DUMP_VERIFY 0
- #define DEBUG_FLOW 0
- #define DEBUG_LIMIT_WIND_SUM 0
- #define DEBUG_MARK_DONE 0
- #define DEBUG_PATH_CONSTRUCTION 0
- #define DEBUG_PERP 0
- #define DEBUG_SHOW_TEST_NAME 0
- #define DEBUG_SORT 0
- #define DEBUG_T_SECT 0
- #define DEBUG_T_SECT_DUMP 0
- #define DEBUG_T_SECT_LOOP_COUNT 0
- #define DEBUG_VALIDATE 0
- #define DEBUG_WINDING 0
- #define DEBUG_WINDING_AT_T 0
- #else
- #define DEBUG_ACTIVE_OP 1
- #define DEBUG_ACTIVE_SPANS 1
- #define DEBUG_ADD_INTERSECTING_TS 1
- #define DEBUG_ADD_T 1
- #define DEBUG_ALIGNMENT 0
- #define DEBUG_ANGLE 1
- #define DEBUG_ASSEMBLE 1
- #define DEBUG_COINCIDENCE 1
- #define DEBUG_COINCIDENCE_DUMP 0
- #define DEBUG_COINCIDENCE_ORDER 0 // tight arc quads may generate out-of-order coincidence spans
- #define DEBUG_COINCIDENCE_VERBOSE 1
- #define DEBUG_CUBIC_BINARY_SEARCH 0
- #define DEBUG_CUBIC_SPLIT 1
- #define DEBUG_DUMP_VERIFY 0
- #define DEBUG_DUMP_SEGMENTS 1
- #define DEBUG_FLOW 1
- #define DEBUG_LIMIT_WIND_SUM 15
- #define DEBUG_MARK_DONE 1
- #define DEBUG_PATH_CONSTRUCTION 1
- #define DEBUG_PERP 1
- #define DEBUG_SHOW_TEST_NAME 1
- #define DEBUG_SORT 1
- #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
- #define DEBUG_WINDING 1
- #define DEBUG_WINDING_AT_T 1
- #endif
- #ifdef SK_RELEASE
- #define SkDEBUGRELEASE(a, b) b
- #define SkDEBUGPARAMS(...)
- #else
- #define SkDEBUGRELEASE(a, b) a
- #define SkDEBUGPARAMS(...) , __VA_ARGS__
- #endif
- #if DEBUG_VALIDATE == 0
- #define PATH_OPS_DEBUG_VALIDATE_PARAMS(...)
- #else
- #define PATH_OPS_DEBUG_VALIDATE_PARAMS(...) , __VA_ARGS__
- #endif
- #if DEBUG_T_SECT == 0
- #define PATH_OPS_DEBUG_T_SECT_RELEASE(a, b) b
- #define PATH_OPS_DEBUG_T_SECT_PARAMS(...)
- #define PATH_OPS_DEBUG_T_SECT_CODE(...)
- #else
- #define PATH_OPS_DEBUG_T_SECT_RELEASE(a, b) a
- #define PATH_OPS_DEBUG_T_SECT_PARAMS(...) , __VA_ARGS__
- #define PATH_OPS_DEBUG_T_SECT_CODE(...) __VA_ARGS__
- #endif
- #if DEBUG_T_SECT_DUMP > 1
- extern int gDumpTSectNum;
- #endif
- #if DEBUG_COINCIDENCE || DEBUG_COINCIDENCE_DUMP
- #define DEBUG_COIN 1
- #else
- #define DEBUG_COIN 0
- #endif
- #if DEBUG_COIN
- #define DEBUG_COIN_DECLARE_ONLY_PARAMS() \
- int lineNo, SkOpPhase phase, int iteration
- #define DEBUG_COIN_DECLARE_PARAMS() \
- , DEBUG_COIN_DECLARE_ONLY_PARAMS()
- #define DEBUG_COIN_ONLY_PARAMS() \
- __LINE__, SkOpPhase::kNoChange, 0
- #define DEBUG_COIN_PARAMS() \
- , DEBUG_COIN_ONLY_PARAMS()
- #define DEBUG_ITER_ONLY_PARAMS(iteration) \
- __LINE__, SkOpPhase::kNoChange, iteration
- #define DEBUG_ITER_PARAMS(iteration) \
- , DEBUG_ITER_ONLY_PARAMS(iteration)
- #define DEBUG_PHASE_ONLY_PARAMS(phase) \
- __LINE__, SkOpPhase::phase, 0
- #define DEBUG_PHASE_PARAMS(phase) \
- , DEBUG_PHASE_ONLY_PARAMS(phase)
- #define DEBUG_SET_PHASE() \
- this->globalState()->debugSetPhase(__func__, lineNo, phase, iteration)
- #define DEBUG_STATIC_SET_PHASE(obj) \
- obj->globalState()->debugSetPhase(__func__, lineNo, phase, iteration)
- #elif DEBUG_VALIDATE
- #define DEBUG_COIN_DECLARE_ONLY_PARAMS() \
- SkOpPhase phase
- #define DEBUG_COIN_DECLARE_PARAMS() \
- , DEBUG_COIN_DECLARE_ONLY_PARAMS()
- #define DEBUG_COIN_ONLY_PARAMS() \
- SkOpPhase::kNoChange
- #define DEBUG_COIN_PARAMS() \
- , DEBUG_COIN_ONLY_PARAMS()
- #define DEBUG_ITER_ONLY_PARAMS(iteration) \
- SkOpPhase::kNoChange
- #define DEBUG_ITER_PARAMS(iteration) \
- , DEBUG_ITER_ONLY_PARAMS(iteration)
- #define DEBUG_PHASE_ONLY_PARAMS(phase) \
- SkOpPhase::phase
- #define DEBUG_PHASE_PARAMS(phase) \
- , DEBUG_PHASE_ONLY_PARAMS(phase)
- #define DEBUG_SET_PHASE() \
- this->globalState()->debugSetPhase(phase)
- #define DEBUG_STATIC_SET_PHASE(obj) \
- obj->globalState()->debugSetPhase(phase)
- #else
- #define DEBUG_COIN_DECLARE_ONLY_PARAMS()
- #define DEBUG_COIN_DECLARE_PARAMS()
- #define DEBUG_COIN_ONLY_PARAMS()
- #define DEBUG_COIN_PARAMS()
- #define DEBUG_ITER_ONLY_PARAMS(iteration)
- #define DEBUG_ITER_PARAMS(iteration)
- #define DEBUG_PHASE_ONLY_PARAMS(phase)
- #define DEBUG_PHASE_PARAMS(phase)
- #define DEBUG_SET_PHASE()
- #define DEBUG_STATIC_SET_PHASE(obj)
- #endif
- #define CUBIC_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
- #define CONIC_DEBUG_STR "{{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}, %1.9g}"
- #define QUAD_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
- #define LINE_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
- #define PT_DEBUG_STR "{{%1.9g,%1.9g}}"
- #define T_DEBUG_STR(t, n) #t "[" #n "]=%1.9g"
- #define TX_DEBUG_STR(t) #t "[%d]=%1.9g"
- #define CUBIC_DEBUG_DATA(c) c[0].fX, c[0].fY, c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY
- #define CONIC_DEBUG_DATA(c, w) c[0].fX, c[0].fY, c[1].fX, c[1].fY, c[2].fX, c[2].fY, w
- #define QUAD_DEBUG_DATA(q) q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY
- #define LINE_DEBUG_DATA(l) l[0].fX, l[0].fY, l[1].fX, l[1].fY
- #define PT_DEBUG_DATA(i, n) i.pt(n).asSkPoint().fX, i.pt(n).asSkPoint().fY
- #ifndef DEBUG_TEST
- #define DEBUG_TEST 0
- #endif
- #if DEBUG_SHOW_TEST_NAME
- #include "src/core/SkTLS.h"
- #endif
- // Tests with extreme numbers may fail, but all other tests should never fail.
- #define FAIL_IF(cond) \
- do { bool fail = (cond); SkOPASSERT(!fail); if (fail) return false; } while (false)
- #define FAIL_WITH_NULL_IF(cond) \
- do { bool fail = (cond); SkOPASSERT(!fail); if (fail) return nullptr; } while (false)
- // Some functions serve two masters: one allows the function to fail, the other expects success
- // always. If abort is true, tests with normal numbers may not fail and assert if they do so.
- // If abort is false, both normal and extreme numbers may return false without asserting.
- #define RETURN_FALSE_IF(abort, cond) \
- do { bool fail = (cond); SkOPASSERT(!(abort) || !fail); if (fail) return false; \
- } while (false)
- class SkPathOpsDebug {
- public:
- #if DEBUG_COIN
- struct GlitchLog;
- enum GlitchType {
- kUninitialized_Glitch,
- kAddCorruptCoin_Glitch,
- kAddExpandedCoin_Glitch,
- kAddExpandedFail_Glitch,
- kAddIfCollapsed_Glitch,
- kAddIfMissingCoin_Glitch,
- kAddMissingCoin_Glitch,
- kAddMissingExtend_Glitch,
- kAddOrOverlap_Glitch,
- kCollapsedCoin_Glitch,
- kCollapsedDone_Glitch,
- kCollapsedOppValue_Glitch,
- kCollapsedSpan_Glitch,
- kCollapsedWindValue_Glitch,
- kCorrectEnd_Glitch,
- kDeletedCoin_Glitch,
- kExpandCoin_Glitch,
- kFail_Glitch,
- kMarkCoinEnd_Glitch,
- kMarkCoinInsert_Glitch,
- kMarkCoinMissing_Glitch,
- kMarkCoinStart_Glitch,
- kMergeMatches_Glitch,
- kMissingCoin_Glitch,
- kMissingDone_Glitch,
- kMissingIntersection_Glitch,
- kMoveMultiple_Glitch,
- kMoveNearbyClearAll_Glitch,
- kMoveNearbyClearAll2_Glitch,
- kMoveNearbyMerge_Glitch,
- kMoveNearbyMergeFinal_Glitch,
- kMoveNearbyRelease_Glitch,
- kMoveNearbyReleaseFinal_Glitch,
- kReleasedSpan_Glitch,
- kReturnFalse_Glitch,
- kUnaligned_Glitch,
- kUnalignedHead_Glitch,
- kUnalignedTail_Glitch,
- };
- struct CoinDictEntry {
- int fIteration;
- int fLineNumber;
- GlitchType fGlitchType;
- const char* fFunctionName;
- };
- struct CoinDict {
- void add(const CoinDictEntry& key);
- void add(const CoinDict& dict);
- void dump(const char* str, bool visitCheck) const;
- SkTDArray<CoinDictEntry> fDict;
- };
- static CoinDict gCoinSumChangedDict;
- static CoinDict gCoinSumVisitedDict;
- static CoinDict gCoinVistedDict;
- #endif
- #if defined(SK_DEBUG) || !FORCE_RELEASE
- static int gContourID;
- static int gSegmentID;
- #endif
- #if DEBUG_SORT
- static int gSortCountDefault;
- static int gSortCount;
- #endif
- #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);
- #if DEBUG_SHOW_TEST_NAME
- static void* CreateNameStr();
- static void DeleteNameStr(void* v);
- #define DEBUG_FILENAME_STRING_LENGTH 64
- #define DEBUG_FILENAME_STRING (reinterpret_cast<char* >(SkTLS::Get(SkPathOpsDebug::CreateNameStr, \
- SkPathOpsDebug::DeleteNameStr)))
- static void BumpTestName(char* );
- #endif
- 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<SkOpSpanBase*>& , const SkOpSpanBase* );
- static void CheckHealth(class SkOpContourHead* contourList);
- #if DEBUG_COIN
- static void DumpCoinDict();
- static void DumpGlitchType(GlitchType );
- #endif
- };
- // Visual Studio 2017 does not permit calling member functions from the Immediate Window.
- // Global functions work fine, however. Use globals rather than static members inside a class.
- 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);
- #if DEBUG_DUMP_VERIFY
- void DumpOp(const SkPath& one, const SkPath& two, SkPathOp op,
- const char* testName);
- void DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op,
- const char* testName);
- 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);
- void VerifySimplify(const SkPath& path, const SkPath& result);
- #endif
- // 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& );
- void Dump(const SkOpAngle& );
- // 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
|