Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkPathOpsDebug.h
Go to the documentation of this file.
1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#ifndef SkPathOpsDebug_DEFINED
8#define SkPathOpsDebug_DEFINED
9
13
14#include <cstddef>
15
16class SkOpAngle;
17class SkOpCoincidence;
18class SkOpContour;
19class SkOpContourHead;
20class SkOpPtT;
21class SkOpSegment;
22class SkOpSpan;
23class SkOpSpanBase;
24class SkPath;
25struct SkDConic;
26struct SkDCubic;
27struct SkDLine;
28struct SkDPoint;
29struct SkDQuad;
30
31// define this when running fuzz
32// #define SK_BUILD_FOR_FUZZER
33
34#ifdef SK_RELEASE
35#define FORCE_RELEASE 1
36#else
37#define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging
38#endif
39
40#define DEBUG_UNDER_DEVELOPMENT 0
41
42#define ONE_OFF_DEBUG 0
43#define ONE_OFF_DEBUG_MATHEMATICA 0
44
45#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_ANDROID)
46 #define SK_RAND(seed) rand()
47#else
48 #define SK_RAND(seed) rand_r(&seed)
49#endif
50
51#define WIND_AS_STRING(x) char x##Str[12]; \
52 if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
53 else snprintf(x##Str, sizeof(x##Str), "%d", x)
54
55#if FORCE_RELEASE
56
57#define DEBUG_ACTIVE_OP 0
58#define DEBUG_ACTIVE_SPANS 0
59#define DEBUG_ADD_INTERSECTING_TS 0
60#define DEBUG_ADD_T 0
61#define DEBUG_ALIGNMENT 0
62#define DEBUG_ANGLE 0
63#define DEBUG_ASSEMBLE 0
64#define DEBUG_COINCIDENCE 0
65#define DEBUG_COINCIDENCE_DUMP 0 // accumulate and dump which algorithms fired
66#define DEBUG_COINCIDENCE_ORDER 0 // for well behaved curves, check if pairs match up in t-order
67#define DEBUG_COINCIDENCE_VERBOSE 0 // usually whether the next function generates coincidence
68#define DEBUG_CUBIC_BINARY_SEARCH 0
69#define DEBUG_CUBIC_SPLIT 0
70#define DEBUG_DUMP_SEGMENTS 0
71#define DEBUG_DUMP_VERIFY 0
72#define DEBUG_FLOW 0
73#define DEBUG_LIMIT_WIND_SUM 0
74#define DEBUG_MARK_DONE 0
75#define DEBUG_PATH_CONSTRUCTION 0
76#define DEBUG_PERP 0
77#define DEBUG_SORT 0
78#define DEBUG_T_SECT 0
79#define DEBUG_T_SECT_DUMP 0
80#define DEBUG_T_SECT_LOOP_COUNT 0
81#define DEBUG_VALIDATE 0
82#define DEBUG_WINDING 0
83#define DEBUG_WINDING_AT_T 0
84
85#else
86
87#define DEBUG_ACTIVE_OP 1
88#define DEBUG_ACTIVE_SPANS 1
89#define DEBUG_ADD_INTERSECTING_TS 1
90#define DEBUG_ADD_T 1
91#define DEBUG_ALIGNMENT 0
92#define DEBUG_ANGLE 1
93#define DEBUG_ASSEMBLE 1
94#define DEBUG_COINCIDENCE 1
95#define DEBUG_COINCIDENCE_DUMP 1
96#define DEBUG_COINCIDENCE_ORDER 1 // tight arc quads may generate out-of-order coincidence spans
97#define DEBUG_COINCIDENCE_VERBOSE 1
98#define DEBUG_CUBIC_BINARY_SEARCH 0
99#define DEBUG_CUBIC_SPLIT 1
100#define DEBUG_DUMP_VERIFY 1
101#define DEBUG_DUMP_SEGMENTS 1
102#define DEBUG_FLOW 1
103#define DEBUG_LIMIT_WIND_SUM 15
104#define DEBUG_MARK_DONE 1
105#define DEBUG_PATH_CONSTRUCTION 1
106#define DEBUG_PERP 1
107#define DEBUG_SORT 1
108#define DEBUG_T_SECT 0 // enabling may trigger validate asserts even though op does not fail
109#define DEBUG_T_SECT_DUMP 0 // Use 1 normally. Use 2 to number segments, 3 for script output
110#define DEBUG_T_SECT_LOOP_COUNT 0
111#define DEBUG_VALIDATE 1
112#define DEBUG_WINDING 1
113#define DEBUG_WINDING_AT_T 1
114
115#endif
116
117#ifdef SK_RELEASE
118 #define SkDEBUGRELEASE(a, b) b
119 #define SkDEBUGPARAMS(...)
120#else
121 #define SkDEBUGRELEASE(a, b) a
122 #define SkDEBUGPARAMS(...) , __VA_ARGS__
123#endif
124
125#if DEBUG_VALIDATE == 0
126 #define PATH_OPS_DEBUG_VALIDATE_PARAMS(...)
127#else
128 #define PATH_OPS_DEBUG_VALIDATE_PARAMS(...) , __VA_ARGS__
129#endif
130
131#if DEBUG_T_SECT == 0
132 #define PATH_OPS_DEBUG_T_SECT_RELEASE(a, b) b
133 #define PATH_OPS_DEBUG_T_SECT_PARAMS(...)
134 #define PATH_OPS_DEBUG_T_SECT_CODE(...)
135#else
136 #define PATH_OPS_DEBUG_T_SECT_RELEASE(a, b) a
137 #define PATH_OPS_DEBUG_T_SECT_PARAMS(...) , __VA_ARGS__
138 #define PATH_OPS_DEBUG_T_SECT_CODE(...) __VA_ARGS__
139#endif
140
141#if DEBUG_T_SECT_DUMP > 1
142 extern int gDumpTSectNum;
143#endif
144
145#if DEBUG_COINCIDENCE || DEBUG_COINCIDENCE_DUMP
146 #define DEBUG_COIN 1
147#else
148 #define DEBUG_COIN 0
149#endif
150
151#if DEBUG_COIN
152enum class SkOpPhase : char;
153
154 #define DEBUG_COIN_DECLARE_ONLY_PARAMS() \
155 int lineNo, SkOpPhase phase, int iteration
156 #define DEBUG_COIN_DECLARE_PARAMS() \
157 , DEBUG_COIN_DECLARE_ONLY_PARAMS()
158 #define DEBUG_COIN_ONLY_PARAMS() \
159 __LINE__, SkOpPhase::kNoChange, 0
160 #define DEBUG_COIN_PARAMS() \
161 , DEBUG_COIN_ONLY_PARAMS()
162 #define DEBUG_ITER_ONLY_PARAMS(iteration) \
163 __LINE__, SkOpPhase::kNoChange, iteration
164 #define DEBUG_ITER_PARAMS(iteration) \
165 , DEBUG_ITER_ONLY_PARAMS(iteration)
166 #define DEBUG_PHASE_ONLY_PARAMS(phase) \
167 __LINE__, SkOpPhase::phase, 0
168 #define DEBUG_PHASE_PARAMS(phase) \
169 , DEBUG_PHASE_ONLY_PARAMS(phase)
170 #define DEBUG_SET_PHASE() \
171 this->globalState()->debugSetPhase(__func__, lineNo, phase, iteration)
172 #define DEBUG_STATIC_SET_PHASE(obj) \
173 obj->globalState()->debugSetPhase(__func__, lineNo, phase, iteration)
174#elif DEBUG_VALIDATE
175 #define DEBUG_COIN_DECLARE_ONLY_PARAMS() \
176 SkOpPhase phase
177 #define DEBUG_COIN_DECLARE_PARAMS() \
178 , DEBUG_COIN_DECLARE_ONLY_PARAMS()
179 #define DEBUG_COIN_ONLY_PARAMS() \
180 SkOpPhase::kNoChange
181 #define DEBUG_COIN_PARAMS() \
182 , DEBUG_COIN_ONLY_PARAMS()
183 #define DEBUG_ITER_ONLY_PARAMS(iteration) \
184 SkOpPhase::kNoChange
185 #define DEBUG_ITER_PARAMS(iteration) \
186 , DEBUG_ITER_ONLY_PARAMS(iteration)
187 #define DEBUG_PHASE_ONLY_PARAMS(phase) \
188 SkOpPhase::phase
189 #define DEBUG_PHASE_PARAMS(phase) \
190 , DEBUG_PHASE_ONLY_PARAMS(phase)
191 #define DEBUG_SET_PHASE() \
192 this->globalState()->debugSetPhase(phase)
193 #define DEBUG_STATIC_SET_PHASE(obj) \
194 obj->globalState()->debugSetPhase(phase)
195#else
196 #define DEBUG_COIN_DECLARE_ONLY_PARAMS()
197 #define DEBUG_COIN_DECLARE_PARAMS()
198 #define DEBUG_COIN_ONLY_PARAMS()
199 #define DEBUG_COIN_PARAMS()
200 #define DEBUG_ITER_ONLY_PARAMS(iteration)
201 #define DEBUG_ITER_PARAMS(iteration)
202 #define DEBUG_PHASE_ONLY_PARAMS(phase)
203 #define DEBUG_PHASE_PARAMS(phase)
204 #define DEBUG_SET_PHASE()
205 #define DEBUG_STATIC_SET_PHASE(obj)
206#endif
207
208#define CUBIC_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
209#define CONIC_DEBUG_STR "{{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}, %1.9g}"
210#define QUAD_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
211#define LINE_DEBUG_STR "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
212#define PT_DEBUG_STR "{{%1.9g,%1.9g}}"
213
214#define T_DEBUG_STR(t, n) #t "[" #n "]=%1.9g"
215#define TX_DEBUG_STR(t) #t "[%d]=%1.9g"
216#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
217#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
218#define QUAD_DEBUG_DATA(q) q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY
219#define LINE_DEBUG_DATA(l) l[0].fX, l[0].fY, l[1].fX, l[1].fY
220#define PT_DEBUG_DATA(i, n) i.pt(n).asSkPoint().fX, i.pt(n).asSkPoint().fY
221
222#ifndef DEBUG_TEST
223#define DEBUG_TEST 0
224#endif
225
226// Tests with extreme numbers may fail, but all other tests should never fail.
227#define FAIL_IF(cond) \
228 do { bool fail = (cond); SkOPASSERT(!fail); if (fail) return false; } while (false)
229
230#define FAIL_WITH_NULL_IF(cond) \
231 do { bool fail = (cond); SkOPASSERT(!fail); if (fail) return nullptr; } while (false)
232
234public:
235#if DEBUG_COIN
236 struct GlitchLog;
237
238 enum GlitchType {
239 kUninitialized_Glitch,
240 kAddCorruptCoin_Glitch,
241 kAddExpandedCoin_Glitch,
242 kAddExpandedFail_Glitch,
243 kAddIfCollapsed_Glitch,
244 kAddIfMissingCoin_Glitch,
245 kAddMissingCoin_Glitch,
246 kAddMissingExtend_Glitch,
247 kAddOrOverlap_Glitch,
248 kCollapsedCoin_Glitch,
249 kCollapsedDone_Glitch,
250 kCollapsedOppValue_Glitch,
251 kCollapsedSpan_Glitch,
252 kCollapsedWindValue_Glitch,
253 kCorrectEnd_Glitch,
254 kDeletedCoin_Glitch,
255 kExpandCoin_Glitch,
256 kFail_Glitch,
257 kMarkCoinEnd_Glitch,
258 kMarkCoinInsert_Glitch,
259 kMarkCoinMissing_Glitch,
260 kMarkCoinStart_Glitch,
261 kMergeMatches_Glitch,
262 kMissingCoin_Glitch,
263 kMissingDone_Glitch,
264 kMissingIntersection_Glitch,
265 kMoveMultiple_Glitch,
266 kMoveNearbyClearAll_Glitch,
267 kMoveNearbyClearAll2_Glitch,
268 kMoveNearbyMerge_Glitch,
269 kMoveNearbyMergeFinal_Glitch,
270 kMoveNearbyRelease_Glitch,
271 kMoveNearbyReleaseFinal_Glitch,
272 kReleasedSpan_Glitch,
273 kReturnFalse_Glitch,
274 kUnaligned_Glitch,
275 kUnalignedHead_Glitch,
276 kUnalignedTail_Glitch,
277 };
278
279 struct CoinDictEntry {
280 int fIteration;
281 int fLineNumber;
282 GlitchType fGlitchType;
283 const char* fFunctionName;
284 };
285
286 struct CoinDict {
287 void add(const CoinDictEntry& key);
288 void add(const CoinDict& dict);
289 void dump(const char* str, bool visitCheck) const;
291 };
292
293 static CoinDict gCoinSumChangedDict;
294 static CoinDict gCoinSumVisitedDict;
295 static CoinDict gCoinVistedDict;
296#endif
297
298#if defined(SK_DEBUG) || !FORCE_RELEASE
299 static int gContourID;
300 static int gSegmentID;
301#endif
302
303#if DEBUG_SORT
304 static int gSortCountDefault;
305 static int gSortCount;
306#endif
307
308#if DEBUG_ACTIVE_OP
309 static const char* kPathOpStr[];
310#endif
311 static bool gRunFail;
312 static bool gVeryVerbose;
313
314#if DEBUG_ACTIVE_SPANS
315 static SkString gActiveSpans;
316#endif
317#if DEBUG_DUMP_VERIFY
318 static bool gDumpOp;
319 static bool gVerifyOp;
320#endif
321
322 static const char* OpStr(SkPathOp );
323 static void MathematicaIze(char* str, size_t bufferSize);
324 static bool ValidWind(int winding);
325 static void WindingPrintf(int winding);
326
327 static void ShowActiveSpans(SkOpContourHead* contourList);
328 static void ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration);
329 static void ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name);
330
331 static bool ChaseContains(const SkTDArray<SkOpSpanBase*>& , const SkOpSpanBase* );
332
333 static void CheckHealth(class SkOpContourHead* contourList);
334
335#if DEBUG_COIN
336 static void DumpCoinDict();
337 static void DumpGlitchType(GlitchType );
338#endif
339
340};
341
342// Visual Studio 2017 does not permit calling member functions from the Immediate Window.
343// Global functions work fine, however. Use globals rather than static members inside a class.
344const SkOpAngle* AngleAngle(const SkOpAngle*, int id);
346const SkOpPtT* AnglePtT(const SkOpAngle*, int id);
347const SkOpSegment* AngleSegment(const SkOpAngle*, int id);
348const SkOpSpanBase* AngleSpan(const SkOpAngle*, int id);
349
350const SkOpAngle* ContourAngle(SkOpContour*, int id);
352const SkOpPtT* ContourPtT(SkOpContour*, int id);
353const SkOpSegment* ContourSegment(SkOpContour*, int id);
354const SkOpSpanBase* ContourSpan(SkOpContour*, int id);
355
358const SkOpPtT* CoincidencePtT(SkOpCoincidence*, int id);
361
362const SkOpAngle* PtTAngle(const SkOpPtT*, int id);
364const SkOpPtT* PtTPtT(const SkOpPtT*, int id);
365const SkOpSegment* PtTSegment(const SkOpPtT*, int id);
366const SkOpSpanBase* PtTSpan(const SkOpPtT*, int id);
367
368const SkOpAngle* SegmentAngle(const SkOpSegment*, int id);
370const SkOpPtT* SegmentPtT(const SkOpSegment*, int id);
371const SkOpSegment* SegmentSegment(const SkOpSegment*, int id);
372const SkOpSpanBase* SegmentSpan(const SkOpSegment*, int id);
373
374const SkOpAngle* SpanAngle(const SkOpSpanBase*, int id);
376const SkOpPtT* SpanPtT(const SkOpSpanBase*, int id);
377const SkOpSegment* SpanSegment(const SkOpSpanBase*, int id);
378const SkOpSpanBase* SpanSpan(const SkOpSpanBase*, int id);
379
380#if DEBUG_DUMP_VERIFY
381void DumpOp(const SkPath& one, const SkPath& two, SkPathOp op,
382 const char* testName);
383void DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op,
384 const char* testName);
385void DumpSimplify(const SkPath& path, const char* testName);
386void DumpSimplify(FILE* file, const SkPath& path, const char* testName);
387void ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op);
388void ReportSimplifyFail(const SkPath& path);
389void VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op,
390 const SkPath& result);
391void VerifySimplify(const SkPath& path, const SkPath& result);
392#endif
393
394// global path dumps for msvs Visual Studio 17 to use from Immediate Window
395void Dump(const SkOpContour& );
396void DumpAll(const SkOpContour& );
397void DumpAngles(const SkOpContour& );
398void DumpContours(const SkOpContour& );
399void DumpContoursAll(const SkOpContour& );
400void DumpContoursAngles(const SkOpContour& );
401void DumpContoursPts(const SkOpContour& );
402void DumpContoursPt(const SkOpContour& , int segmentID);
403void DumpContoursSegment(const SkOpContour& , int segmentID);
404void DumpContoursSpan(const SkOpContour& , int segmentID);
405void DumpContoursSpans(const SkOpContour& );
406void DumpPt(const SkOpContour& , int );
407void DumpPts(const SkOpContour& , const char* prefix = "seg");
408void DumpSegment(const SkOpContour& , int );
409void DumpSegments(const SkOpContour& , const char* prefix = "seg", SkPathOp op = (SkPathOp) -1);
410void DumpSpan(const SkOpContour& , int );
411void DumpSpans(const SkOpContour& );
412
413void Dump(const SkOpSegment& );
414void DumpAll(const SkOpSegment& );
415void DumpAngles(const SkOpSegment& );
416void DumpCoin(const SkOpSegment& );
417void DumpPts(const SkOpSegment& , const char* prefix = "seg");
418
419void Dump(const SkOpPtT& );
420void DumpAll(const SkOpPtT& );
421
422void Dump(const SkOpSpanBase& );
423void DumpCoin(const SkOpSpanBase& );
424void DumpAll(const SkOpSpanBase& );
425
426void DumpCoin(const SkOpSpan& );
427bool DumpSpan(const SkOpSpan& );
428
429void Dump(const SkDConic& );
430void DumpID(const SkDConic& , int id);
431
432void Dump(const SkDCubic& );
433void DumpID(const SkDCubic& , int id);
434
435void Dump(const SkDLine& );
436void DumpID(const SkDLine& , int id);
437
438void Dump(const SkDQuad& );
439void DumpID(const SkDQuad& , int id);
440
441void Dump(const SkDPoint& );
442
443void Dump(const SkOpAngle& );
444
445// generates tools/path_sorter.htm and path_visualizer.htm compatible data
446void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo);
447void DumpT(const SkDQuad& quad, double t);
448
449// global path dumps for msvs Visual Studio 17 to use from Immediate Window
450void Dump(const SkPath& path);
451void DumpHex(const SkPath& path);
452
453#endif
int gDumpTSectNum
void DumpID(const SkDConic &, int id)
const SkOpSegment * CoincidenceSegment(SkOpCoincidence *, int id)
void DumpQ(const SkDQuad &quad1, const SkDQuad &quad2, int testNo)
void DumpContoursAngles(const SkOpContour &)
const SkOpAngle * SpanAngle(const SkOpSpanBase *, int id)
SkOpContour * PtTContour(SkOpPtT *, int id)
const SkOpSpanBase * SpanSpan(const SkOpSpanBase *, int id)
void DumpContoursPts(const SkOpContour &)
SkOpContour * ContourContour(SkOpContour *, int id)
const SkOpPtT * ContourPtT(SkOpContour *, int id)
const SkOpSegment * AngleSegment(const SkOpAngle *, int id)
void DumpSegment(const SkOpContour &, int)
void DumpT(const SkDQuad &quad, double t)
const SkOpAngle * AngleAngle(const SkOpAngle *, int id)
void DumpContours(const SkOpContour &)
const SkOpPtT * AnglePtT(const SkOpAngle *, int id)
void DumpContoursSpans(const SkOpContour &)
void DumpSpan(const SkOpContour &, int)
const SkOpPtT * SegmentPtT(const SkOpSegment *, int id)
const SkOpSpanBase * AngleSpan(const SkOpAngle *, int id)
void DumpPt(const SkOpContour &, int)
void DumpHex(const SkPath &path)
void DumpSpans(const SkOpContour &)
void DumpContoursAll(const SkOpContour &)
void DumpAngles(const SkOpContour &)
const SkOpAngle * SegmentAngle(const SkOpSegment *, int id)
const SkOpSpanBase * SegmentSpan(const SkOpSegment *, int id)
const SkOpAngle * ContourAngle(SkOpContour *, int id)
const SkOpSegment * SegmentSegment(const SkOpSegment *, int id)
void DumpCoin(const SkOpSegment &)
void Dump(const SkOpContour &)
void DumpContoursSpan(const SkOpContour &, int segmentID)
const SkOpPtT * CoincidencePtT(SkOpCoincidence *, int id)
const SkOpAngle * CoincidenceAngle(SkOpCoincidence *, int id)
void DumpAll(const SkOpContour &)
const SkOpSegment * ContourSegment(SkOpContour *, int id)
const SkOpSpanBase * CoincidenceSpan(SkOpCoincidence *, int id)
void DumpPts(const SkOpContour &, const char *prefix="seg")
const SkOpPtT * PtTPtT(const SkOpPtT *, int id)
SkOpContour * SpanContour(SkOpSpanBase *, int id)
const SkOpAngle * PtTAngle(const SkOpPtT *, int id)
SkOpContour * SegmentContour(SkOpSegment *, int id)
const SkOpPtT * SpanPtT(const SkOpSpanBase *, int id)
void DumpContoursSegment(const SkOpContour &, int segmentID)
const SkOpSegment * SpanSegment(const SkOpSpanBase *, int id)
SkOpContour * AngleContour(SkOpAngle *, int id)
const SkOpSpanBase * PtTSpan(const SkOpPtT *, int id)
void DumpContoursPt(const SkOpContour &, int segmentID)
const SkOpSpanBase * ContourSpan(SkOpContour *, int id)
SkOpContour * CoincidenceContour(SkOpCoincidence *, int id)
void DumpSegments(const SkOpContour &, const char *prefix="seg", SkPathOp op=(SkPathOp) -1)
const SkOpSegment * PtTSegment(const SkOpPtT *, int id)
SkOpPhase
SkPathOp
Definition SkPathOps.h:22
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
static void ShowPath(const SkPath &one, const SkPath &two, SkPathOp op, const char *name)
static bool gRunFail
static const char * OpStr(SkPathOp)
static void ShowActiveSpans(SkOpContourHead *contourList)
static bool gVeryVerbose
static void MathematicaIze(char *str, size_t bufferSize)
static void ShowOnePath(const SkPath &path, const char *name, bool includeDeclaration)
static bool ValidWind(int winding)
static void CheckHealth(class SkOpContourHead *contourList)
static bool ChaseContains(const SkTDArray< SkOpSpanBase * > &, const SkOpSpanBase *)
static void WindingPrintf(int winding)
GAsyncResult * result
const char * name
Definition fuchsia.cc:50