OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkMutex.h" | 8 #include "SkMutex.h" |
9 #include "SkOpCoincidence.h" | 9 #include "SkOpCoincidence.h" |
10 #include "SkOpContour.h" | 10 #include "SkOpContour.h" |
11 #include "SkPath.h" | 11 #include "SkPath.h" |
12 #include "SkPathOpsDebug.h" | 12 #include "SkPathOpsDebug.h" |
13 #include "SkString.h" | 13 #include "SkString.h" |
14 | 14 |
15 struct SkCoincidentSpans; | 15 class SkCoincidentSpans; |
16 | 16 |
17 #if DEBUG_VALIDATE | 17 #if DEBUG_VALIDATE |
18 extern bool FLAGS_runFail; | 18 extern bool FLAGS_runFail; |
19 #endif | 19 #endif |
20 | 20 |
21 #if DEBUG_SORT | 21 #if DEBUG_SORT |
22 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; | 22 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; |
23 int SkPathOpsDebug::gSortCount; | 23 int SkPathOpsDebug::gSortCount; |
24 #endif | 24 #endif |
25 | 25 |
(...skipping 13 matching lines...) Expand all Loading... | |
39 for (int index = 0; index < chaseArray.count(); ++index) { | 39 for (int index = 0; index < chaseArray.count(); ++index) { |
40 const SkOpSpanBase* entry = chaseArray[index]; | 40 const SkOpSpanBase* entry = chaseArray[index]; |
41 if (entry == span) { | 41 if (entry == span) { |
42 return true; | 42 return true; |
43 } | 43 } |
44 } | 44 } |
45 return false; | 45 return false; |
46 } | 46 } |
47 #endif | 47 #endif |
48 | 48 |
49 #if DEBUG_COINCIDENCE | 49 #if DEBUG_COINCIDENCE_VERBOSE |
50 enum GlitchType { | 50 enum GlitchType { |
51 kAddCorruptCoin_Glitch, | 51 kAddCorruptCoin_Glitch, |
52 kAddExpandedCoin_Glitch, | 52 kAddExpandedCoin_Glitch, |
53 kAddExpandedFail_Glitch, | |
54 kAddIfMissingCoin_Glitch, | |
53 kAddMissingCoin_Glitch, | 55 kAddMissingCoin_Glitch, |
56 kAddMissingExtend_Glitch, | |
57 kAddOrOverlap_Glitch, | |
54 kCollapsedCoin_Glitch, | 58 kCollapsedCoin_Glitch, |
55 kCollapsedDone_Glitch, | 59 kCollapsedDone_Glitch, |
56 kCollapsedOppValue_Glitch, | 60 kCollapsedOppValue_Glitch, |
57 kCollapsedSpan_Glitch, | 61 kCollapsedSpan_Glitch, |
58 kCollapsedWindValue_Glitch, | 62 kCollapsedWindValue_Glitch, |
59 kDeletedCoin_Glitch, | 63 kDeletedCoin_Glitch, |
60 kExpandCoin_Glitch, | 64 kExpandCoin_Glitch, |
61 kMarkCoinEnd_Glitch, | 65 kMarkCoinEnd_Glitch, |
62 kMarkCoinInsert_Glitch, | 66 kMarkCoinInsert_Glitch, |
67 kMarkCoinMissing_Glitch, | |
68 kMarkCoinStart_Glitch, | |
69 kMergeContained_Glitch, | |
63 kMissingCoin_Glitch, | 70 kMissingCoin_Glitch, |
64 kMissingDone_Glitch, | 71 kMissingDone_Glitch, |
65 kMissingIntersection_Glitch, | 72 kMissingIntersection_Glitch, |
66 kMoveMultiple_Glitch, | 73 kMoveMultiple_Glitch, |
74 kMoveNearbyClearAll_Glitch, | |
75 kMoveNearbyClearAll2_Glitch, | |
76 kMoveNearbyMerge_Glitch, | |
77 kMoveNearbyMergeFinal_Glitch, | |
78 kMoveNearbyRelease_Glitch, | |
79 kMoveNearbyReleaseFinal_Glitch, | |
80 kReleasedSpan_Glitch, | |
67 kUnaligned_Glitch, | 81 kUnaligned_Glitch, |
68 kUnalignedHead_Glitch, | 82 kUnalignedHead_Glitch, |
69 kUnalignedTail_Glitch, | 83 kUnalignedTail_Glitch, |
70 kUndetachedSpan_Glitch, | |
71 kUnmergedSpan_Glitch, | |
72 }; | 84 }; |
73 | 85 |
74 static const int kGlitchType_Count = kUnmergedSpan_Glitch + 1; | 86 static const int kGlitchType_Count = kUnalignedTail_Glitch + 1; |
75 | 87 |
76 struct SpanGlitch { | 88 struct SpanGlitch { |
77 const char* fStage; | 89 const char* fStage; |
78 const SkOpSpanBase* fBase; | 90 const SkOpSpanBase* fBase; |
79 const SkOpSpanBase* fSuspect; | 91 const SkOpSpanBase* fSuspect; |
80 const SkCoincidentSpans* fCoin; | |
81 const SkOpSegment* fSegment; | 92 const SkOpSegment* fSegment; |
93 const SkOpSegment* fOppSegment; | |
82 const SkOpPtT* fCoinSpan; | 94 const SkOpPtT* fCoinSpan; |
83 const SkOpPtT* fEndSpan; | 95 const SkOpPtT* fEndSpan; |
84 const SkOpPtT* fOppSpan; | 96 const SkOpPtT* fOppSpan; |
85 const SkOpPtT* fOppEndSpan; | 97 const SkOpPtT* fOppEndSpan; |
86 double fT; | 98 double fStartT; |
99 double fEndT; | |
100 double fOppStartT; | |
101 double fOppEndT; | |
87 SkPoint fPt; | 102 SkPoint fPt; |
88 GlitchType fType; | 103 GlitchType fType; |
89 }; | 104 }; |
90 | 105 |
91 struct SkPathOpsDebug::GlitchLog { | 106 struct SkPathOpsDebug::GlitchLog { |
92 SpanGlitch* recordCommon(GlitchType type, const char* stage) { | 107 SpanGlitch* recordCommon(GlitchType type, const char* stage) { |
93 SpanGlitch* glitch = fGlitches.push(); | 108 SpanGlitch* glitch = fGlitches.push(); |
94 glitch->fStage = stage; | 109 glitch->fStage = stage; |
95 glitch->fBase = nullptr; | 110 glitch->fBase = nullptr; |
96 glitch->fSuspect = nullptr; | 111 glitch->fSuspect = nullptr; |
97 glitch->fCoin = nullptr; | |
98 glitch->fSegment = nullptr; | 112 glitch->fSegment = nullptr; |
113 glitch->fOppSegment = nullptr; | |
99 glitch->fCoinSpan = nullptr; | 114 glitch->fCoinSpan = nullptr; |
100 glitch->fEndSpan = nullptr; | 115 glitch->fEndSpan = nullptr; |
101 glitch->fOppSpan = nullptr; | 116 glitch->fOppSpan = nullptr; |
102 glitch->fOppEndSpan = nullptr; | 117 glitch->fOppEndSpan = nullptr; |
103 glitch->fT = SK_ScalarNaN; | 118 glitch->fStartT = SK_ScalarNaN; |
119 glitch->fEndT = SK_ScalarNaN; | |
120 glitch->fOppStartT = SK_ScalarNaN; | |
121 glitch->fOppEndT = SK_ScalarNaN; | |
104 glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; | 122 glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; |
105 glitch->fType = type; | 123 glitch->fType = type; |
106 return glitch; | 124 return glitch; |
107 } | 125 } |
108 | 126 |
109 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, | 127 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, |
110 const SkOpSpanBase* suspect = NULL) { | 128 const SkOpSpanBase* suspect = NULL) { |
111 SpanGlitch* glitch = recordCommon(type, stage); | 129 SpanGlitch* glitch = recordCommon(type, stage); |
112 glitch->fBase = base; | 130 glitch->fBase = base; |
113 glitch->fSuspect = suspect; | 131 glitch->fSuspect = suspect; |
114 } | 132 } |
115 | 133 |
134 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, | |
135 const SkOpPtT* ptT) { | |
136 SpanGlitch* glitch = recordCommon(type, stage); | |
137 glitch->fBase = base; | |
138 glitch->fCoinSpan = ptT; | |
139 } | |
140 | |
116 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, | 141 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, |
117 const SkOpPtT* coinSpan) { | 142 const SkCoincidentSpans* opp = NULL) { |
118 SpanGlitch* glitch = recordCommon(type, stage); | 143 SpanGlitch* glitch = recordCommon(type, stage); |
119 glitch->fCoin = coin; | 144 glitch->fCoinSpan = coin->coinPtTStart(); |
120 glitch->fCoinSpan = coinSpan; | 145 glitch->fEndSpan = coin->coinPtTEnd(); |
146 if (opp) { | |
147 glitch->fOppSpan = opp->coinPtTStart(); | |
148 glitch->fOppEndSpan = opp->coinPtTEnd(); | |
149 } | |
121 } | 150 } |
122 | 151 |
123 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, | 152 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, |
124 const SkOpSegment* seg, double t, SkPoint pt) { | 153 const SkOpSegment* seg, double t, SkPoint pt) { |
125 SpanGlitch* glitch = recordCommon(type, stage); | 154 SpanGlitch* glitch = recordCommon(type, stage); |
126 glitch->fBase = base; | 155 glitch->fBase = base; |
127 glitch->fSegment = seg; | 156 glitch->fSegment = seg; |
128 glitch->fT = t; | 157 glitch->fStartT = t; |
129 glitch->fPt = pt; | 158 glitch->fPt = pt; |
130 } | 159 } |
131 | 160 |
132 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, do uble t, | 161 void record(GlitchType type, const char* stage, const SkOpSpanBase* base, do uble t, |
133 SkPoint pt) { | 162 SkPoint pt) { |
134 SpanGlitch* glitch = recordCommon(type, stage); | 163 SpanGlitch* glitch = recordCommon(type, stage); |
135 glitch->fBase = base; | 164 glitch->fBase = base; |
136 glitch->fT = t; | 165 glitch->fStartT = t; |
137 glitch->fPt = pt; | 166 glitch->fPt = pt; |
138 } | 167 } |
139 | 168 |
140 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, | 169 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, |
141 const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { | 170 const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { |
142 SpanGlitch* glitch = recordCommon(type, stage); | 171 SpanGlitch* glitch = recordCommon(type, stage); |
143 glitch->fCoin = coin; | 172 glitch->fCoinSpan = coin->coinPtTStart(); |
144 glitch->fCoinSpan = coinSpan; | 173 glitch->fEndSpan = coin->coinPtTEnd(); |
145 glitch->fEndSpan = endSpan; | 174 glitch->fEndSpan = endSpan; |
175 glitch->fOppSpan = coinSpan; | |
176 glitch->fOppEndSpan = endSpan; | |
146 } | 177 } |
147 | 178 |
148 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, | 179 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, |
149 const SkOpSpanBase* suspect) { | 180 const SkOpSpanBase* base) { |
150 SpanGlitch* glitch = recordCommon(type, stage); | 181 SpanGlitch* glitch = recordCommon(type, stage); |
151 glitch->fSuspect = suspect; | 182 glitch->fBase = base; |
152 glitch->fCoin = coin; | 183 glitch->fCoinSpan = coin->coinPtTStart(); |
184 glitch->fEndSpan = coin->coinPtTEnd(); | |
153 } | 185 } |
154 | 186 |
155 void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const S kOpPtT* ptTE, | 187 void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const S kOpPtT* ptTE, |
156 const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { | 188 const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { |
157 SpanGlitch* glitch = recordCommon(type, stage); | 189 SpanGlitch* glitch = recordCommon(type, stage); |
158 glitch->fCoinSpan = ptTS; | 190 glitch->fCoinSpan = ptTS; |
159 glitch->fEndSpan = ptTE; | 191 glitch->fEndSpan = ptTE; |
160 glitch->fOppSpan = oPtTS; | 192 glitch->fOppSpan = oPtTS; |
161 glitch->fOppEndSpan = oPtTE; | 193 glitch->fOppEndSpan = oPtTE; |
162 } | 194 } |
163 | 195 |
196 void record(GlitchType type, const char* stage, const SkOpSegment* seg, doub le startT, | |
197 double endT, const SkOpSegment* oppSeg, double oppStartT, double opp EndT) { | |
198 SpanGlitch* glitch = recordCommon(type, stage); | |
199 glitch->fSegment = seg; | |
200 glitch->fStartT = startT; | |
201 glitch->fEndT = endT; | |
202 glitch->fOppSegment = oppSeg; | |
203 glitch->fOppStartT = oppStartT; | |
204 glitch->fOppEndT = oppEndT; | |
205 } | |
206 | |
207 void record(GlitchType type, const char* stage, const SkOpSegment* seg, | |
208 const SkOpSpan* span) { | |
209 SpanGlitch* glitch = recordCommon(type, stage); | |
210 glitch->fSegment = seg; | |
211 glitch->fBase = span; | |
212 } | |
213 | |
214 void record(GlitchType type, const char* stage, double t, const SkOpSpanBase * span) { | |
215 SpanGlitch* glitch = recordCommon(type, stage); | |
216 glitch->fStartT = t; | |
217 glitch->fBase = span; | |
218 } | |
219 | |
220 void record(GlitchType type, const char* stage, const SkOpSegment* seg) { | |
221 SpanGlitch* glitch = recordCommon(type, stage); | |
222 glitch->fSegment = seg; | |
223 } | |
224 | |
225 void record(GlitchType type, const char* stage, const SkCoincidentSpans* coi n, | |
226 const SkOpPtT* ptT) { | |
227 SpanGlitch* glitch = recordCommon(type, stage); | |
228 glitch->fCoinSpan = coin->coinPtTStart(); | |
229 glitch->fEndSpan = ptT; | |
230 } | |
231 | |
164 SkTDArray<SpanGlitch> fGlitches; | 232 SkTDArray<SpanGlitch> fGlitches; |
165 }; | 233 }; |
234 #endif | |
166 | 235 |
236 void SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { | |
237 #if DEBUG_ACTIVE_SPANS | |
238 SkOpContour* contour = contourList; | |
239 do { | |
240 contour->debugShowActiveSpans(); | |
241 } while ((contour = contour->next())); | |
242 #endif | |
243 } | |
244 | |
245 #if DEBUG_COINCIDENCE | |
167 void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { | 246 void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { |
247 contourList->globalState()->debugSetCheckHealth(true); | |
248 #if DEBUG_COINCIDENCE_VERBOSE | |
168 GlitchLog glitches; | 249 GlitchLog glitches; |
169 const SkOpContour* contour = contourList; | 250 const SkOpContour* contour = contourList; |
170 const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); | 251 const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); |
252 coincidence->debugCheckValid(id, &glitches); // don't call validate; spans m ay be inconsistent | |
171 do { | 253 do { |
172 contour->debugCheckHealth(id, &glitches); | 254 contour->debugCheckHealth(id, &glitches); |
173 contour->debugMissingCoincidence(id, &glitches, coincidence); | 255 contour->debugMissingCoincidence(id, &glitches); |
174 } while ((contour = contour->next())); | 256 } while ((contour = contour->next())); |
175 coincidence->debugFixAligned(id, &glitches); | 257 coincidence->debugRemoveCollapsed(id, &glitches); |
176 coincidence->debugAddMissing(id, &glitches); | 258 coincidence->debugAddMissing(id, &glitches); |
177 coincidence->debugExpand(id, &glitches); | 259 coincidence->debugExpand(id, &glitches); |
178 coincidence->debugAddExpanded(id, &glitches); | 260 coincidence->debugAddExpanded(id, &glitches); |
179 coincidence->debugMark(id, &glitches); | 261 coincidence->debugMark(id, &glitches); |
262 coincidence->debugReorder(id, &glitches); | |
180 unsigned mask = 0; | 263 unsigned mask = 0; |
181 for (int index = 0; index < glitches.fGlitches.count(); ++index) { | 264 for (int index = 0; index < glitches.fGlitches.count(); ++index) { |
182 const SpanGlitch& glitch = glitches.fGlitches[index]; | 265 const SpanGlitch& glitch = glitches.fGlitches[index]; |
183 mask |= 1 << glitch.fType; | 266 mask |= 1 << glitch.fType; |
184 } | 267 } |
185 for (int index = 0; index < kGlitchType_Count; ++index) { | 268 for (int index = 0; index < kGlitchType_Count; ++index) { |
186 SkDebugf(mask & (1 << index) ? "x" : "-"); | 269 SkDebugf(mask & (1 << index) ? "x" : "-"); |
187 } | 270 } |
188 SkDebugf(" %s\n", id); | 271 SkDebugf(" %s\n", id); |
272 for (int index = 0; index < glitches.fGlitches.count(); ++index) { | |
273 const SpanGlitch& glitch = glitches.fGlitches[index]; | |
274 SkDebugf("%02d: ", index); | |
275 if (glitch.fBase) { | |
276 SkDebugf(" base=%d", glitch.fBase->debugID()); | |
277 } | |
278 if (glitch.fSuspect) { | |
279 SkDebugf(" base=%d", glitch.fSuspect->debugID()); | |
280 } | |
281 if (glitch.fSegment) { | |
282 SkDebugf(" segment=%d", glitch.fSegment->debugID()); | |
283 } | |
284 if (glitch.fCoinSpan) { | |
285 SkDebugf(" coinSpan=%d", glitch.fCoinSpan->debugID()); | |
286 } | |
287 if (glitch.fEndSpan) { | |
288 SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); | |
289 } | |
290 if (glitch.fOppSpan) { | |
291 SkDebugf(" oppSpan=%d", glitch.fOppSpan->debugID()); | |
292 } | |
293 if (glitch.fOppEndSpan) { | |
294 SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); | |
295 } | |
296 if (!SkScalarIsNaN(glitch.fStartT)) { | |
297 SkDebugf(" startT=%g", glitch.fStartT); | |
298 } | |
299 if (!SkScalarIsNaN(glitch.fEndT)) { | |
300 SkDebugf(" endT=%g", glitch.fEndT); | |
301 } | |
302 if (glitch.fOppSegment) { | |
303 SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); | |
304 } | |
305 if (!SkScalarIsNaN(glitch.fOppStartT)) { | |
306 SkDebugf(" oppStartT=%g", glitch.fOppStartT); | |
307 } | |
308 if (!SkScalarIsNaN(glitch.fOppEndT)) { | |
309 SkDebugf(" oppEndT=%g", glitch.fOppEndT); | |
310 } | |
311 if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { | |
312 SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); | |
313 } | |
314 switch (glitch.fType) { | |
315 case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; | |
316 case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; | |
317 case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; | |
318 case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; | |
319 case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; | |
320 case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; | |
321 case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; | |
322 case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; | |
323 case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; | |
324 case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); brea k; | |
325 case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; | |
326 case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); br eak; | |
327 case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; | |
328 case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; | |
329 case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; | |
330 case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; | |
331 case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; | |
332 case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; | |
333 case kMergeContained_Glitch: SkDebugf(" MergeContained"); break; | |
334 case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; | |
335 case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; | |
336 case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; | |
337 case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; | |
338 case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); br eak; | |
339 case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; | |
340 case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; | |
341 case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal") ; break; | |
342 case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); brea k; | |
343 case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFin al"); break; | |
344 case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; | |
345 case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; | |
346 case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; | |
347 case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; | |
348 default: SkASSERT(0); | |
349 } | |
350 SkDebugf("\n"); | |
351 } | |
352 contourList->globalState()->debugSetCheckHealth(false); | |
353 #if DEBUG_ACTIVE_SPANS | |
354 SkDebugf("active after %s:\n", id); | |
355 ShowActiveSpans(contourList); | |
356 #endif | |
357 #endif | |
189 } | 358 } |
190 #endif | 359 #endif |
191 | 360 |
192 #if defined SK_DEBUG || !FORCE_RELEASE | 361 #if defined SK_DEBUG || !FORCE_RELEASE |
193 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { | 362 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { |
194 size_t len = strlen(str); | 363 size_t len = strlen(str); |
195 bool num = false; | 364 bool num = false; |
196 for (size_t idx = 0; idx < len; ++idx) { | 365 for (size_t idx = 0; idx < len; ++idx) { |
197 if (num && str[idx] == 'e') { | 366 if (num && str[idx] == 'e') { |
198 if (len + 2 >= bufferLen) { | 367 if (len + 2 >= bufferLen) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filenam e) {\n", functionName); | 416 SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filenam e) {\n", functionName); |
248 if (strcmp("skphealth_com76", functionName) == 0) { | 417 if (strcmp("skphealth_com76", functionName) == 0) { |
249 SkDebugf("found it\n"); | 418 SkDebugf("found it\n"); |
250 } | 419 } |
251 } | 420 } |
252 | 421 |
253 static const char* gOpStrs[] = { | 422 static const char* gOpStrs[] = { |
254 "kDifference_SkPathOp", | 423 "kDifference_SkPathOp", |
255 "kIntersect_SkPathOp", | 424 "kIntersect_SkPathOp", |
256 "kUnion_SkPathOp", | 425 "kUnion_SkPathOp", |
257 "kXor_PathOp", | 426 "kXOR_PathOp", |
258 "kReverseDifference_SkPathOp", | 427 "kReverseDifference_SkPathOp", |
259 }; | 428 }; |
260 | 429 |
261 const char* SkPathOpsDebug::OpStr(SkPathOp op) { | 430 const char* SkPathOpsDebug::OpStr(SkPathOp op) { |
262 return gOpStrs[op]; | 431 return gOpStrs[op]; |
263 } | 432 } |
264 | 433 |
265 static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { | 434 static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { |
266 SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathT wo, gOpStrs[op]); | 435 SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathT wo, gOpStrs[op]); |
267 SkDebugf("}\n"); | 436 SkDebugf("}\n"); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 } | 574 } |
406 | 575 |
407 void SkDRect::debugInit() { | 576 void SkDRect::debugInit() { |
408 fLeft = fTop = fRight = fBottom = SK_ScalarNaN; | 577 fLeft = fTop = fRight = fBottom = SK_ScalarNaN; |
409 } | 578 } |
410 | 579 |
411 #include "SkOpAngle.h" | 580 #include "SkOpAngle.h" |
412 #include "SkOpSegment.h" | 581 #include "SkOpSegment.h" |
413 | 582 |
414 #if DEBUG_COINCIDENCE | 583 #if DEBUG_COINCIDENCE |
415 void SkOpSegment::debugAddAlignIntersection(const char* id, SkPathOpsDebug::Glit chLog* log, | 584 // commented-out lines keep this in sync with addT() |
416 const SkOpPtT& endPtT, const SkPoint& oldPt, const SkOpContourHead* con tourList) const { | 585 const SkOpPtT* SkOpSegment::debugAddT(double t, AliasMatch allowAlias, bool* al located) const { |
417 const SkPoint& newPt = endPtT.fPt; | 586 debugValidate(); |
418 if (newPt == oldPt) { | 587 SkPoint pt = this->ptAtT(t); |
419 return; | 588 const SkOpSpanBase* span = &fHead; |
420 } | |
421 SkPoint line[2] = { newPt, oldPt }; | |
422 SkPathOpsBounds lineBounds; | |
423 lineBounds.setBounds(line, 2); | |
424 SkDLine aLine; | |
425 aLine.set(line); | |
426 const SkOpContour* current = contourList; | |
427 do { | 589 do { |
428 if (!SkPathOpsBounds::Intersects(current->bounds(), lineBounds)) { | 590 const SkOpPtT* result = span->ptT(); |
429 continue; | 591 const SkOpPtT* loop; |
592 bool duplicatePt; | |
593 if (t == result->fT) { | |
594 goto bumpSpan; | |
430 } | 595 } |
431 const SkOpSegment* segment = current->first(); | 596 if (this->match(result, this, t, pt, allowAlias)) { |
432 do { | 597 // see if any existing alias matches segment, pt, and t |
433 if (!SkPathOpsBounds::Intersects(segment->bounds(), lineBounds)) { | 598 loop = result->next(); |
434 continue; | 599 duplicatePt = false; |
600 while (loop != result) { | |
601 bool ptMatch = loop->fPt == pt; | |
602 if (loop->segment() == this && loop->fT == t && ptMatch) { | |
603 goto bumpSpan; | |
604 } | |
605 duplicatePt |= ptMatch; | |
606 loop = loop->next(); | |
435 } | 607 } |
436 if (newPt == segment->fPts[0]) { | 608 if (kNoAliasMatch == allowAlias) { |
437 continue; | 609 bumpSpan: |
610 // span->bumpSpanAdds(); | |
611 return result; | |
438 } | 612 } |
439 if (newPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { | 613 // SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator); |
440 continue; | 614 // alias->init(result->span(), t, pt, duplicatePt); |
615 // result->insert(alias); | |
616 // result->span()->unaligned(); | |
617 this->debugValidate(); | |
618 // #if DEBUG_ADD_T | |
619 // SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, | |
620 // alias->segment()->debugID(), alias->span()->debugID()); | |
621 // #endif | |
622 // span->bumpSpanAdds(); | |
623 if (allocated) { | |
624 *allocated = true; | |
441 } | 625 } |
442 if (oldPt == segment->fPts[0]) { | 626 return nullptr; |
443 continue; | 627 } |
628 if (t < result->fT) { | |
629 const SkOpSpan* prev = result->span()->prev(); | |
630 if (!prev) { | |
631 return nullptr; // FIXME: this is a fail case; nullptr return e lsewhere means result was allocated in non-const version | |
444 } | 632 } |
445 if (oldPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { | 633 // SkOpSpan* span = insert(prev, allocator); |
446 continue; | 634 // span->init(this, prev, t, pt); |
635 this->debugValidate(); | |
636 // #if DEBUG_ADD_T | |
637 // SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, | |
638 // span->segment()->debugID(), span->debugID()); | |
639 // #endif | |
640 // span->bumpSpanAdds(); | |
641 if (allocated) { | |
642 *allocated = true; | |
447 } | 643 } |
448 if (endPtT.debugContains(segment)) { | 644 return nullptr; |
449 continue; | |
450 } | |
451 SkIntersections i; | |
452 switch (segment->fVerb) { | |
453 case SkPath::kLine_Verb: { | |
454 SkDLine bLine; | |
455 bLine.set(segment->fPts); | |
456 i.intersect(bLine, aLine); | |
457 } break; | |
458 case SkPath::kQuad_Verb: { | |
459 SkDQuad bQuad; | |
460 bQuad.set(segment->fPts); | |
461 i.intersect(bQuad, aLine); | |
462 } break; | |
463 case SkPath::kConic_Verb: { | |
464 SkDConic bConic; | |
465 bConic.set(segment->fPts, segment->fWeight); | |
466 i.intersect(bConic, aLine); | |
467 } break; | |
468 case SkPath::kCubic_Verb: { | |
469 SkDCubic bCubic; | |
470 bCubic.set(segment->fPts); | |
471 i.intersect(bCubic, aLine); | |
472 } break; | |
473 default: | |
474 SkASSERT(0); | |
475 } | |
476 if (i.used()) { | |
477 SkASSERT(i.used() == 1); | |
478 SkASSERT(!zero_or_one(i[0][0])); | |
479 SkOpSpanBase* checkSpan = fHead.next(); | |
480 while (!checkSpan->final()) { | |
481 if (checkSpan->contains(segment)) { | |
482 goto nextSegment; | |
483 } | |
484 checkSpan = checkSpan->upCast()->next(); | |
485 } | |
486 log->record(kMissingIntersection_Glitch, id, checkSpan, segment, i[0][0], newPt); | |
487 } | |
488 nextSegment: | |
489 ; | |
490 } while ((segment = segment->next())); | |
491 } while ((current = current->next())); | |
492 } | |
493 | |
494 bool SkOpSegment::debugAddMissing(double t, const SkOpSegment* opp) const { | |
495 const SkOpSpanBase* existing = nullptr; | |
496 const SkOpSpanBase* test = &fHead; | |
497 double testT; | |
498 do { | |
499 if ((testT = test->ptT()->fT) >= t) { | |
500 if (testT == t) { | |
501 existing = test; | |
502 } | |
503 break; | |
504 } | 645 } |
505 } while ((test = test->upCast()->next())); | 646 SkASSERT(span != &fTail); |
506 return !existing || !existing->debugContains(opp); | 647 } while ((span = span->upCast()->next())); |
507 } | 648 SkASSERT(0); |
508 | 649 return nullptr; |
509 void SkOpSegment::debugAlign(const char* id, SkPathOpsDebug::GlitchLog* glitches ) const { | |
510 const SkOpSpanBase* span = &fHead; | |
511 if (!span->aligned()) { | |
512 if (!span->debugAlignedEnd(0, fPts[0])) { | |
513 glitches->record(kUnalignedHead_Glitch, id, span); | |
514 } | |
515 } | |
516 while ((span = span->upCast()->next())) { | |
517 if (span == &fTail) { | |
518 break; | |
519 } | |
520 if (!span->aligned()) { | |
521 glitches->record(kUnaligned_Glitch, id, span); | |
522 } | |
523 } | |
524 if (!span->aligned()) { | |
525 span->debugAlignedEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); | |
526 } | |
527 if (this->collapsed()) { | |
528 const SkOpSpan* span = &fHead; | |
529 do { | |
530 if (span->windValue()) { | |
531 glitches->record(kCollapsedWindValue_Glitch, id, span); | |
532 } | |
533 if (span->oppValue()) { | |
534 glitches->record(kCollapsedOppValue_Glitch, id, span); | |
535 } | |
536 if (!span->done()) { | |
537 glitches->record(kCollapsedDone_Glitch, id, span); | |
538 } | |
539 } while ((span = span->next()->upCastable())); | |
540 } | |
541 } | 650 } |
542 #endif | 651 #endif |
543 | 652 |
544 #if DEBUG_ANGLE | 653 #if DEBUG_ANGLE |
545 void SkOpSegment::debugCheckAngleCoin() const { | 654 void SkOpSegment::debugCheckAngleCoin() const { |
546 const SkOpSpanBase* base = &fHead; | 655 const SkOpSpanBase* base = &fHead; |
547 const SkOpSpan* span; | 656 const SkOpSpan* span; |
548 do { | 657 do { |
549 const SkOpAngle* angle = base->fromAngle(); | 658 const SkOpAngle* angle = base->fromAngle(); |
550 if (angle && angle->fCheckCoincidence) { | 659 if (angle && angle->debugCheckCoincidence()) { |
551 angle->debugCheckNearCoincidence(); | 660 angle->debugCheckNearCoincidence(); |
552 } | 661 } |
553 if (base->final()) { | 662 if (base->final()) { |
554 break; | 663 break; |
555 } | 664 } |
556 span = base->upCast(); | 665 span = base->upCast(); |
557 angle = span->toAngle(); | 666 angle = span->toAngle(); |
558 if (angle && angle->fCheckCoincidence) { | 667 if (angle && angle->debugCheckCoincidence()) { |
559 angle->debugCheckNearCoincidence(); | 668 angle->debugCheckNearCoincidence(); |
560 } | 669 } |
561 } while ((base = span->next())); | 670 } while ((base = span->next())); |
562 } | 671 } |
563 #endif | 672 #endif |
564 | 673 |
565 #if DEBUG_COINCIDENCE | 674 #if DEBUG_COINCIDENCE_VERBOSE |
566 // this mimics the order of the checks in handle coincidence | 675 // this mimics the order of the checks in handle coincidence |
567 void SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* gl itches) const { | 676 void SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* gl itches) const { |
568 debugMoveMultiples(id, glitches); | 677 debugMoveMultiples(id, glitches); |
569 debugFindCollapsed(id, glitches); | |
570 debugMoveNearby(id, glitches); | 678 debugMoveNearby(id, glitches); |
571 debugAlign(id, glitches); | 679 debugMissingCoincidence(id, glitches); |
572 debugAddAlignIntersections(id, glitches, this->globalState()->contourHead()) ; | |
573 | |
574 } | 680 } |
575 | 681 |
576 void SkOpSegment::debugFindCollapsed(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { | 682 // commented-out lines keep this in sync with clearAll() |
577 if (fHead.contains(&fTail)) { | 683 void SkOpSegment::debugClearAll(const char* id, SkPathOpsDebug::GlitchLog* glitc hes) const { |
578 const SkOpSpan* span = this->head(); | 684 const SkOpSpan* span = &fHead; |
579 bool missingDone = false; | 685 do { |
580 do { | 686 this->debugClearOne(span, id, glitches); |
581 missingDone |= !span->done(); | 687 } while ((span = span->next()->upCastable())); |
582 } while ((span = span->next()->upCastable())); | 688 this->globalState()->coincidence()->debugRelease(id, glitches, this); |
583 if (missingDone) { | 689 } |
584 glitches->record(kMissingDone_Glitch, id, &fHead); | 690 |
585 } | 691 // commented-out lines keep this in sync with clearOne() |
586 if (!fHead.debugAlignedEnd(0, fHead.pt())) { | 692 void SkOpSegment::debugClearOne(const SkOpSpan* span, const char* id, SkPathOpsD ebug::GlitchLog* glitches) const { |
587 glitches->record(kUnalignedHead_Glitch, id, &fHead); | 693 if (span->windValue()) glitches->record(kCollapsedWindValue_Glitch, id, span ); |
588 } | 694 if (span->oppValue()) glitches->record(kCollapsedOppValue_Glitch, id, span); |
589 if (!fTail.aligned()) { | 695 if (!span->done()) glitches->record(kCollapsedDone_Glitch, id, span); |
590 glitches->record(kUnalignedTail_Glitch, id, &fTail); | |
591 } | |
592 } | |
593 } | 696 } |
594 #endif | 697 #endif |
595 | 698 |
596 SkOpAngle* SkOpSegment::debugLastAngle() { | 699 SkOpAngle* SkOpSegment::debugLastAngle() { |
597 SkOpAngle* result = nullptr; | 700 SkOpAngle* result = nullptr; |
598 SkOpSpan* span = this->head(); | 701 SkOpSpan* span = this->head(); |
599 do { | 702 do { |
600 if (span->toAngle()) { | 703 if (span->toAngle()) { |
601 SkASSERT(!result); | 704 SkASSERT(!result); |
602 result = span->toAngle(); | 705 result = span->toAngle(); |
603 } | 706 } |
604 } while ((span = span->next()->upCastable())); | 707 } while ((span = span->next()->upCastable())); |
605 SkASSERT(result); | 708 SkASSERT(result); |
606 return result; | 709 return result; |
607 } | 710 } |
608 | 711 |
609 #if DEBUG_COINCIDENCE | 712 #if DEBUG_COINCIDENCE |
610 void SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch Log* log, | 713 // commented-out lines keep this in sync with ClearVisited |
611 const SkOpCoincidence* coincidences) const { | 714 void SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { |
612 if (this->verb() != SkPath::kLine_Verb) { | 715 // reset visited flag back to false |
613 return; | 716 do { |
614 } | 717 const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; |
718 while ((ptT = ptT->next()) != stopPtT) { | |
719 const SkOpSegment* opp = ptT->segment(); | |
720 opp->resetDebugVisited(); | |
721 } | |
722 } while (!span->final() && (span = span->upCast()->next())); | |
723 } | |
724 #endif | |
725 | |
726 #if DEBUG_COINCIDENCE_VERBOSE | |
727 // commented-out lines keep this in sync with missingCoincidence() | |
728 // look for pairs of undetected coincident curves | |
729 // assumes that segments going in have visited flag clear | |
730 // Even though pairs of curves correct detect coincident runs, a run may be miss ed | |
731 // if the coincidence is a product of multiple intersections. For instance, give n | |
732 // curves A, B, and C: | |
733 // A-B intersect at a point 1; A-C and B-C intersect at point 2, so near | |
734 // the end of C that the intersection is replaced with the end of C. | |
735 // Even though A-B correctly do not detect an intersection at point 2, | |
736 // the resulting run from point 1 to point 2 is coincident on A and B. | |
737 void SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch Log* log) const { | |
615 if (this->done()) { | 738 if (this->done()) { |
616 return; | 739 return; |
617 } | 740 } |
618 const SkOpSpan* prior = nullptr; | 741 const SkOpSpan* prior = nullptr; |
619 const SkOpSpanBase* spanBase = &fHead; | 742 const SkOpSpanBase* spanBase = &fHead; |
743 // bool result = false; | |
620 do { | 744 do { |
621 const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; | 745 const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; |
622 SkASSERT(ptT->span() == spanBase); | 746 SkASSERT(ptT->span() == spanBase); |
623 while ((ptT = ptT->next()) != spanStopPtT) { | 747 while ((ptT = ptT->next()) != spanStopPtT) { |
624 if (ptT->deleted()) { | 748 if (ptT->deleted()) { |
625 continue; | 749 continue; |
626 } | 750 } |
627 SkOpSegment* opp = ptT->span()->segment(); | 751 const SkOpSegment* opp = ptT->span()->segment(); |
628 // if (opp->verb() == SkPath::kLine_Verb) { | |
629 // continue; | |
630 // } | |
631 if (opp->done()) { | 752 if (opp->done()) { |
632 continue; | 753 continue; |
633 } | 754 } |
634 // when opp is encounted the 1st time, continue; on 2nd encounter, l ook for coincidence | 755 // when opp is encounted the 1st time, continue; on 2nd encounter, l ook for coincidence |
635 if (!opp->visited()) { | 756 if (!opp->debugVisited()) { |
636 continue; | 757 continue; |
637 } | 758 } |
638 if (spanBase == &fHead) { | 759 if (spanBase == &fHead) { |
639 continue; | 760 continue; |
640 } | 761 } |
762 if (ptT->segment() == this) { | |
763 continue; | |
764 } | |
641 const SkOpSpan* span = spanBase->upCastable(); | 765 const SkOpSpan* span = spanBase->upCastable(); |
642 // FIXME?: this assumes that if the opposite segment is coincident t hen no more | 766 // FIXME?: this assumes that if the opposite segment is coincident t hen no more |
643 // coincidence needs to be detected. This may not be true. | 767 // coincidence needs to be detected. This may not be true. |
644 if (span && span->segment() != opp && span->containsCoincidence(opp) ) { | 768 if (span && span->segment() != opp && span->containsCoincidence(opp) ) { // debug has additional condition since it may be called before inner dupli cate points have been deleted |
herb_g
2016/07/18 15:13:39
Comments on next line?
caryclark
2016/07/18 15:55:49
The crazy formatting here is so that SkOpSegment::
| |
645 continue; | 769 continue; |
646 } | 770 } |
647 if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { | 771 if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted |
648 continue; | 772 continue; |
649 } | 773 } |
650 const SkOpPtT* priorPtT = nullptr, * priorStopPtT; | 774 const SkOpPtT* priorPtT = nullptr, * priorStopPtT; |
651 // find prior span containing opp segment | 775 // find prior span containing opp segment |
652 const SkOpSegment* priorOpp = nullptr; | 776 const SkOpSegment* priorOpp = nullptr; |
653 const SkOpSpan* priorTest = spanBase->prev(); | 777 const SkOpSpan* priorTest = spanBase->prev(); |
654 while (!priorOpp && priorTest) { | 778 while (!priorOpp && priorTest) { |
655 priorStopPtT = priorPtT = priorTest->ptT(); | 779 priorStopPtT = priorPtT = priorTest->ptT(); |
656 while ((priorPtT = priorPtT->next()) != priorStopPtT) { | 780 while ((priorPtT = priorPtT->next()) != priorStopPtT) { |
657 if (priorPtT->deleted()) { | 781 if (priorPtT->deleted()) { |
658 continue; | 782 continue; |
659 } | 783 } |
660 SkOpSegment* segment = priorPtT->span()->segment(); | 784 SkOpSegment* segment = priorPtT->span()->segment(); |
661 if (segment == opp) { | 785 if (segment == opp) { |
662 prior = priorTest; | 786 prior = priorTest; |
663 priorOpp = opp; | 787 priorOpp = opp; |
664 break; | 788 break; |
665 } | 789 } |
666 } | 790 } |
667 priorTest = priorTest->prev(); | 791 priorTest = priorTest->prev(); |
668 } | 792 } |
669 if (!priorOpp) { | 793 if (!priorOpp) { |
670 continue; | 794 continue; |
671 } | 795 } |
796 if (priorPtT == ptT) { | |
797 continue; | |
798 } | |
672 const SkOpPtT* oppStart = prior->ptT(); | 799 const SkOpPtT* oppStart = prior->ptT(); |
673 const SkOpPtT* oppEnd = spanBase->ptT(); | 800 const SkOpPtT* oppEnd = spanBase->ptT(); |
674 bool swapped = priorPtT->fT > ptT->fT; | 801 bool swapped = priorPtT->fT > ptT->fT; |
675 if (swapped) { | 802 if (swapped) { |
676 SkTSwap(priorPtT, ptT); | 803 SkTSwap(priorPtT, ptT); |
677 SkTSwap(oppStart, oppEnd); | 804 SkTSwap(oppStart, oppEnd); |
678 } | 805 } |
679 bool flipped = oppStart->fT > oppEnd->fT; | 806 const SkOpCoincidence* coincidence = this->globalState()->coincidenc e(); |
680 bool coincident = false; | 807 const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); |
681 if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped) ) { | 808 const SkOpPtT* rootPtT = ptT->span()->ptT(); |
809 const SkOpPtT* rootOppStart = oppStart->span()->ptT(); | |
810 const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); | |
811 if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootO ppEnd)) { | |
682 goto swapBack; | 812 goto swapBack; |
683 } | 813 } |
684 if (opp->verb() == SkPath::kLine_Verb) { | 814 if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { |
685 coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppSta rt->fPt) || | 815 // mark coincidence |
686 SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt) ) && | 816 #if DEBUG_COINCIDENCE |
687 (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) | | | 817 // SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\ n", __FUNCTION__, |
herb_g
2016/07/18 15:13:39
Remove commented out code.
caryclark
2016/07/18 15:55:49
See above
| |
688 SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt)); | 818 // rootPriorPtT->debugID(), rootPtT->debugID(), rootOppS tart->debugID(), |
689 } | 819 // rootOppEnd->debugID()); |
690 if (!coincident) { | 820 #endif |
691 coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000); | |
692 } | |
693 if (coincident) { | |
694 log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, op pEnd); | 821 log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, op pEnd); |
822 // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, root OppEnd); | |
823 // } | |
824 #if DEBUG_COINCIDENCE | |
825 // SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOpp Start, rootOppEnd) | |
826 #endif | |
827 // result = true; | |
695 } | 828 } |
696 swapBack: | 829 swapBack: |
697 if (swapped) { | 830 if (swapped) { |
698 SkTSwap(priorPtT, ptT); | 831 SkTSwap(priorPtT, ptT); |
699 } | 832 } |
700 } | 833 } |
701 } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next( ))); | 834 } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next( ))); |
835 DebugClearVisited(&fHead); | |
836 return; | |
702 } | 837 } |
703 | 838 |
839 // commented-out lines keep this in sync with moveMultiples() | |
840 // if a span has more than one intersection, merge the other segments' span as n eeded | |
704 void SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { | 841 void SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { |
842 debugValidate(); | |
705 const SkOpSpanBase* test = &fHead; | 843 const SkOpSpanBase* test = &fHead; |
706 do { | 844 do { |
707 int addCount = test->spanAddsCount(); | 845 int addCount = test->spanAddsCount(); |
708 SkASSERT(addCount >= 1); | 846 SkASSERT(addCount >= 1); |
709 if (addCount == 1) { | 847 if (addCount == 1) { |
710 continue; | 848 continue; |
711 } | 849 } |
712 const SkOpPtT* startPtT = test->ptT(); | 850 const SkOpPtT* startPtT = test->ptT(); |
713 const SkOpPtT* testPtT = startPtT; | 851 const SkOpPtT* testPtT = startPtT; |
714 do { // iterate through all spans associated with start | 852 do { // iterate through all spans associated with start |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
770 goto tryNextSpan; | 908 goto tryNextSpan; |
771 } | 909 } |
772 const SkOpPtT* matchPtT = startPtT; | 910 const SkOpPtT* matchPtT = startPtT; |
773 do { | 911 do { |
774 if (matchPtT->segment() == oppPtTSegment) { | 912 if (matchPtT->segment() == oppPtTSegment) { |
775 goto foundMatch; | 913 goto foundMatch; |
776 } | 914 } |
777 } while ((matchPtT = matchPtT->next()) != startPtT); | 915 } while ((matchPtT = matchPtT->next()) != startPtT); |
778 goto tryNextSpan; | 916 goto tryNextSpan; |
779 foundMatch: // merge oppTest and oppSpan | 917 foundMatch: // merge oppTest and oppSpan |
918 oppSegment->debugValidate(); | |
780 if (oppTest == &oppSegment->fTail || oppTest == &oppSegment- >fHead) { | 919 if (oppTest == &oppSegment->fTail || oppTest == &oppSegment- >fHead) { |
781 SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse | 920 SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse |
782 SkASSERT(oppSpan != &oppSegment->fTail); | 921 SkASSERT(oppSpan != &oppSegment->fTail); |
783 glitches->record(kMoveMultiple_Glitch, id, oppTest, oppS pan); | 922 glitches->record(kMoveMultiple_Glitch, id, oppTest, oppS pan); |
784 } else { | 923 } else { |
785 glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppT est); | 924 glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppT est); |
786 } | 925 } |
926 oppSegment->debugValidate(); | |
787 goto checkNextSpan; | 927 goto checkNextSpan; |
788 } | 928 } |
789 tryNextSpan: | 929 tryNextSpan: |
790 ; | 930 ; |
791 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()) ); | 931 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()) ); |
792 } while ((testPtT = testPtT->next()) != startPtT); | 932 } while ((testPtT = testPtT->next()) != startPtT); |
793 checkNextSpan: | 933 checkNextSpan: |
794 ; | 934 ; |
795 } while ((test = test->final() ? nullptr : test->upCast()->next())); | 935 } while ((test = test->final() ? nullptr : test->upCast()->next())); |
936 debugValidate(); | |
937 return; | |
796 } | 938 } |
797 | 939 |
940 // commented-out lines keep this in sync with moveNearby() | |
941 // Move nearby t values and pts so they all hang off the same span. Alignment ha ppens later. | |
798 void SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* gli tches) const { | 942 void SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* gli tches) const { |
799 const SkOpSpanBase* spanS = &fHead; | 943 debugValidate(); |
944 // release undeleted spans pointing to this seg that are linked to the prima ry span | |
945 const SkOpSpanBase* spanBase = &fHead; | |
800 do { | 946 do { |
801 const SkOpSpanBase* test = spanS->upCast()->next(); | 947 const SkOpPtT* ptT = spanBase->ptT(); |
802 const SkOpSpanBase* next; | 948 const SkOpPtT* headPtT = ptT; |
803 if (spanS->contains(test)) { | 949 while ((ptT = ptT->next()) != headPtT) { |
804 if (!test->final()) { | 950 const SkOpSpanBase* test = ptT->span(); |
805 glitches->record(kUndetachedSpan_Glitch, id, test, spanS); | 951 if (ptT->segment() == this && !ptT->deleted() && test != spanBase |
806 } else if (spanS != &fHead) { | 952 && test->ptT() == ptT) { |
807 glitches->record(kUndetachedSpan_Glitch, id, spanS, test); | 953 if (test->final()) { |
954 if (spanBase == &fHead) { | |
955 glitches->record(kMoveNearbyClearAll_Glitch, id, this); | |
956 // return; | |
herb_g
2016/07/18 15:13:39
Remove commented out code.
caryclark
2016/07/18 15:55:49
See comment above.
| |
957 } | |
958 glitches->record(kMoveNearbyReleaseFinal_Glitch, id, spanBas e, ptT); | |
959 } else if (test->prev()) { | |
960 glitches->record(kMoveNearbyRelease_Glitch, id, test, headPt T); | |
961 } | |
962 // break; | |
808 } | 963 } |
809 } | 964 } |
810 do { // iterate through all spans associated with start | 965 spanBase = spanBase->upCast()->next(); |
811 const SkOpPtT* startBase = spanS->ptT(); | 966 } while (!spanBase->final()); |
812 next = test->final() ? nullptr : test->upCast()->next(); | 967 |
813 do { | 968 // This loop looks for adjacent spans which are near by |
814 const SkOpPtT* testBase = test->ptT(); | 969 spanBase = &fHead; |
815 do { | 970 do { // iterate through all spans associated with start |
816 if (startBase == testBase) { | 971 const SkOpSpanBase* test = spanBase->upCast()->next(); |
817 goto checkNextSpan; | 972 if (this->spansNearby(spanBase, test)) { |
818 } | 973 if (test->final()) { |
819 if (testBase->duplicate()) { | 974 if (spanBase->prev()) { |
820 continue; | 975 glitches->record(kMoveNearbyMergeFinal_Glitch, id, test); |
821 } | 976 } else { |
822 if (this->match(startBase, testBase->segment(), testBase->fT , testBase->fPt)) { | 977 glitches->record(kMoveNearbyClearAll2_Glitch, id, this); |
823 if (test == &this->fTail) { | 978 // return |
824 if (spanS == &fHead) { | 979 } |
825 glitches->record(kCollapsedSpan_Glitch, id, span S); | 980 } else { |
826 } else { | 981 glitches->record(kMoveNearbyMerge_Glitch, id, spanBase); |
827 glitches->record(kUnmergedSpan_Glitch, id, &this ->fTail, spanS); | 982 } |
828 } | 983 } |
829 } else { | 984 spanBase = test; |
830 glitches->record(kUnmergedSpan_Glitch, id, spanS, te st); | 985 } while (!spanBase->final()); |
831 goto checkNextSpan; | 986 debugValidate(); |
832 } | |
833 } | |
834 } while ((testBase = testBase->next()) != test->ptT()); | |
835 } while ((startBase = startBase->next()) != spanS->ptT()); | |
836 checkNextSpan: | |
837 ; | |
838 } while ((test = next)); | |
839 spanS = spanS->upCast()->next(); | |
840 } while (!spanS->final()); | |
841 } | 987 } |
842 #endif | 988 #endif |
843 | 989 |
844 void SkOpSegment::debugReset() { | 990 void SkOpSegment::debugReset() { |
845 this->init(this->fPts, this->fWeight, this->contour(), this->verb()); | 991 this->init(this->fPts, this->fWeight, this->contour(), this->verb()); |
846 } | 992 } |
847 | 993 |
848 #if DEBUG_ACTIVE_SPANS | 994 #if DEBUG_ACTIVE_SPANS |
849 void SkOpSegment::debugShowActiveSpans() const { | 995 void SkOpSegment::debugShowActiveSpans() const { |
850 debugValidate(); | 996 debugValidate(); |
851 if (done()) { | 997 if (done()) { |
852 return; | 998 return; |
853 } | 999 } |
854 int lastId = -1; | 1000 int lastId = -1; |
855 double lastT = -1; | 1001 double lastT = -1; |
856 const SkOpSpan* span = &fHead; | 1002 const SkOpSpan* span = &fHead; |
857 do { | 1003 do { |
858 if (span->done()) { | 1004 if (span->done()) { |
859 continue; | 1005 continue; |
860 } | 1006 } |
861 if (lastId == this->debugID() && lastT == span->t()) { | 1007 if (lastId == this->debugID() && lastT == span->t()) { |
862 continue; | 1008 continue; |
863 } | 1009 } |
864 lastId = this->debugID(); | 1010 lastId = this->debugID(); |
865 lastT = span->t(); | 1011 lastT = span->t(); |
866 SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); | 1012 SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); |
867 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); | 1013 // since endpoints may have be adjusted, show actual computed curves |
1014 SkDCurve curvePart; | |
1015 this->subDivide(span, span->next(), &curvePart); | |
1016 const SkDPoint* pts = curvePart.fCubic.fPts; | |
1017 SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); | |
868 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { | 1018 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
869 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); | 1019 SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); |
870 } | 1020 } |
871 if (SkPath::kConic_Verb == fVerb) { | 1021 if (SkPath::kConic_Verb == fVerb) { |
872 SkDebugf(" %1.9gf", fWeight); | 1022 SkDebugf(" %1.9gf", curvePart.fConic.fWeight); |
873 } | 1023 } |
874 const SkOpPtT* ptT = span->ptT(); | 1024 SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); |
875 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", ptT->fT, ptT->fPt.fX, ptT->fPt.fY); | |
876 SkDebugf(" tEnd=%1.9g", span->next()->t()); | |
877 if (span->windSum() == SK_MinS32) { | 1025 if (span->windSum() == SK_MinS32) { |
878 SkDebugf(" windSum=?"); | 1026 SkDebugf(" windSum=?"); |
879 } else { | 1027 } else { |
880 SkDebugf(" windSum=%d", span->windSum()); | 1028 SkDebugf(" windSum=%d", span->windSum()); |
881 } | 1029 } |
882 if (span->oppValue() && span->oppSum() == SK_MinS32) { | 1030 if (span->oppValue() && span->oppSum() == SK_MinS32) { |
883 SkDebugf(" oppSum=?"); | 1031 SkDebugf(" oppSum=?"); |
884 } else if (span->oppValue() || span->oppSum() != SK_MinS32) { | 1032 } else if (span->oppValue() || span->oppSum() != SK_MinS32) { |
885 SkDebugf(" oppSum=%d", span->oppSum()); | 1033 SkDebugf(" oppSum=%d", span->oppSum()); |
886 } | 1034 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 SkDebugf("%d", span->windSum()); | 1099 SkDebugf("%d", span->windSum()); |
952 } | 1100 } |
953 SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()) ; | 1101 SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()) ; |
954 } | 1102 } |
955 | 1103 |
956 #endif | 1104 #endif |
957 | 1105 |
958 // loop looking for a pair of angle parts that are too close to be sorted | 1106 // loop looking for a pair of angle parts that are too close to be sorted |
959 /* This is called after other more simple intersection and angle sorting tests h ave been exhausted. | 1107 /* This is called after other more simple intersection and angle sorting tests h ave been exhausted. |
960 This should be rarely called -- the test below is thorough and time consuming . | 1108 This should be rarely called -- the test below is thorough and time consuming . |
961 This checks the distance between start points; the distance between | 1109 This checks the distance between start points; the distance between |
962 */ | 1110 */ |
963 #if DEBUG_ANGLE | 1111 #if DEBUG_ANGLE |
964 void SkOpAngle::debugCheckNearCoincidence() const { | 1112 void SkOpAngle::debugCheckNearCoincidence() const { |
965 const SkOpAngle* test = this; | 1113 const SkOpAngle* test = this; |
966 do { | 1114 do { |
967 const SkOpSegment* testSegment = test->segment(); | 1115 const SkOpSegment* testSegment = test->segment(); |
968 double testStartT = test->start()->t(); | 1116 double testStartT = test->start()->t(); |
969 SkDPoint testStartPt = testSegment->dPtAtT(testStartT); | 1117 SkDPoint testStartPt = testSegment->dPtAtT(testStartT); |
970 double testEndT = test->end()->t(); | 1118 double testEndT = test->end()->t(); |
971 SkDPoint testEndPt = testSegment->dPtAtT(testEndT); | 1119 SkDPoint testEndPt = testSegment->dPtAtT(testEndT); |
(...skipping 17 matching lines...) Expand all Loading... | |
989 SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); | 1137 SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); |
990 SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); | 1138 SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); |
991 SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); | 1139 SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); |
992 SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); | 1140 SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); |
993 SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); | 1141 SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); |
994 double nextLenSq = nextStartPt.distanceSquared(nextEndPt); | 1142 double nextLenSq = nextStartPt.distanceSquared(nextEndPt); |
995 SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); | 1143 SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); |
996 SkDebugf("\n"); | 1144 SkDebugf("\n"); |
997 } | 1145 } |
998 test = test->fNext; | 1146 test = test->fNext; |
999 } while (test->fNext != this); | 1147 } while (test->fNext != this); |
1000 } | 1148 } |
1001 #endif | 1149 #endif |
1002 | 1150 |
1003 #if DEBUG_ANGLE | 1151 #if DEBUG_ANGLE |
1004 SkString SkOpAngle::debugPart() const { | 1152 SkString SkOpAngle::debugPart() const { |
1005 SkString result; | 1153 SkString result; |
1006 switch (this->segment()->verb()) { | 1154 switch (this->segment()->verb()) { |
1007 case SkPath::kLine_Verb: | 1155 case SkPath::kLine_Verb: |
1008 result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart), | 1156 result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart), |
1009 this->segment()->debugID()); | 1157 this->segment()->debugID()); |
(...skipping 29 matching lines...) Expand all Loading... | |
1039 } while (next && next != first); | 1187 } while (next && next != first); |
1040 next = first; | 1188 next = first; |
1041 do { | 1189 do { |
1042 next->debugValidate(); | 1190 next->debugValidate(); |
1043 next = next->fNext; | 1191 next = next->fNext; |
1044 } while (next && next != first); | 1192 } while (next && next != first); |
1045 } | 1193 } |
1046 #endif | 1194 #endif |
1047 | 1195 |
1048 void SkOpAngle::debugValidate() const { | 1196 void SkOpAngle::debugValidate() const { |
1197 #if DEBUG_COINCIDENCE | |
1198 if (this->globalState()->debugCheckHealth()) { | |
1199 return; | |
1200 } | |
1201 #endif | |
1049 #if DEBUG_VALIDATE | 1202 #if DEBUG_VALIDATE |
1050 const SkOpAngle* first = this; | 1203 const SkOpAngle* first = this; |
1051 const SkOpAngle* next = this; | 1204 const SkOpAngle* next = this; |
1052 int wind = 0; | 1205 int wind = 0; |
1053 int opp = 0; | 1206 int opp = 0; |
1054 int lastXor = -1; | 1207 int lastXor = -1; |
1055 int lastOppXor = -1; | 1208 int lastOppXor = -1; |
1056 do { | 1209 do { |
1057 if (next->unorderable()) { | 1210 if (next->unorderable()) { |
1058 return; | 1211 return; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1101 break; | 1254 break; |
1102 } | 1255 } |
1103 SkASSERT_RELEASE(!angles.contains(next)); | 1256 SkASSERT_RELEASE(!angles.contains(next)); |
1104 if (!next) { | 1257 if (!next) { |
1105 return; | 1258 return; |
1106 } | 1259 } |
1107 } while (true); | 1260 } while (true); |
1108 #endif | 1261 #endif |
1109 } | 1262 } |
1110 | 1263 |
1111 | 1264 #ifdef SK_DEBUG |
1112 #if DEBUG_COINCIDENCE | 1265 void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpa nBase* over, |
1266 const SkOpGlobalState* debugState) const { | |
1267 SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); | |
1268 SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); | |
1269 } | |
1270 #endif | |
1271 | |
1272 #if DEBUG_COINCIDENCE_VERBOSE | |
1273 /* Commented-out lines keep this in sync with expand */ | |
1274 bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l og) const { | |
1275 bool expanded = false; | |
1276 const SkOpSegment* segment = coinPtTStart()->segment(); | |
1277 const SkOpSegment* oppSegment = oppPtTStart()->segment(); | |
1278 do { | |
1279 const SkOpSpan* start = coinPtTStart()->span()->upCast(); | |
1280 const SkOpSpan* prev = start->prev(); | |
1281 const SkOpPtT* oppPtT; | |
1282 if (!prev || !(oppPtT = prev->contains(oppSegment))) { | |
1283 break; | |
1284 } | |
1285 double midT = (prev->t() + start->t()) / 2; | |
1286 if (!segment->isClose(midT, oppSegment)) { | |
1287 break; | |
1288 } | |
1289 if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT); | |
1290 expanded = true; | |
1291 } while (false); // actual continues while expansion is possible | |
1292 do { | |
1293 const SkOpSpanBase* end = coinPtTEnd()->span(); | |
1294 SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); | |
1295 const SkOpPtT* oppPtT; | |
1296 if (!next || !(oppPtT = next->contains(oppSegment))) { | |
1297 break; | |
1298 } | |
1299 double midT = (end->t() + next->t()) / 2; | |
1300 if (!segment->isClose(midT, oppSegment)) { | |
1301 break; | |
1302 } | |
1303 if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT); | |
1304 expanded = true; | |
1305 } while (false); // actual continues while expansion is possible | |
1306 return expanded; | |
1307 } | |
1308 | |
1309 #define FAIL_IF(cond) do { if (cond) log->record(kAddExpandedFail_Glitch, id, c oin); } while (false) | |
1310 | |
1311 /* Commented-out lines keep this in sync with addExpanded */ | |
1312 // for each coincident pair, match the spans | |
1313 // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span | |
1113 void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog * log) const { | 1314 void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog * log) const { |
1114 // for each coincident pair, match the spans | |
1115 // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span | |
1116 const SkCoincidentSpans* coin = this->fHead; | 1315 const SkCoincidentSpans* coin = this->fHead; |
1117 if (!coin) { | 1316 if (!coin) { |
1118 coin = this->fTop; | 1317 return; |
1119 } | 1318 } |
1120 if (!coin) { | 1319 do { |
1121 return; | 1320 const SkOpPtT* startPtT = coin->coinPtTStart(); |
1122 } | 1321 const SkOpPtT* oStartPtT = coin->oppPtTStart(); |
1123 do { | |
1124 const SkOpPtT* startPtT = coin->fCoinPtTStart; | |
1125 const SkOpPtT* oStartPtT = coin->fOppPtTStart; | |
1126 SkASSERT(startPtT->contains(oStartPtT)); | 1322 SkASSERT(startPtT->contains(oStartPtT)); |
1127 SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd)); | 1323 SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); |
1128 const SkOpSpanBase* start = startPtT->span(); | 1324 const SkOpSpanBase* start = startPtT->span(); |
1129 const SkOpSpanBase* oStart = oStartPtT->span(); | 1325 const SkOpSpanBase* oStart = oStartPtT->span(); |
1130 const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); | 1326 const SkOpSpanBase* end = coin->coinPtTEnd()->span(); |
1131 const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); | 1327 const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); |
1328 FAIL_IF(oEnd->deleted()); | |
1132 const SkOpSpanBase* test = start->upCast()->next(); | 1329 const SkOpSpanBase* test = start->upCast()->next(); |
1133 const SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->up Cast()->next(); | 1330 const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->u pCast()->next(); |
1331 if (!oTest) { | |
1332 return; | |
1333 } | |
1134 while (test != end || oTest != oEnd) { | 1334 while (test != end || oTest != oEnd) { |
1135 bool bumpTest = true; | 1335 if (!test->ptT()->contains(oTest->segment()) |
1136 bool bumpOTest = true; | 1336 || !oTest->ptT()->contains(start->segment())) { |
1137 if (!test->ptT()->contains(oTest->ptT())) { | |
1138 // use t ranges to guess which one is missing | 1337 // use t ranges to guess which one is missing |
1139 double startRange = coin->fCoinPtTEnd->fT - startPtT->fT; | 1338 double startRange = coin->coinPtTEnd()->fT - startPtT->fT; |
1339 FAIL_IF(!startRange); | |
1140 double startPart = (test->t() - startPtT->fT) / startRange; | 1340 double startPart = (test->t() - startPtT->fT) / startRange; |
1141 double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT; | 1341 double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT; |
1342 FAIL_IF(!oStartRange); | |
1142 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; | 1343 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; |
1143 if (startPart == oStartPart) { | 1344 FAIL_IF(startPart == oStartPart); |
1144 // data is corrupt | 1345 bool startOver = false; |
1145 log->record(kAddCorruptCoin_Glitch, id, start, oStart); | 1346 if (startPart < oStartPart) |
1146 break; | 1347 log->record(kAddExpandedCoin_Glitch, id, // strange deb ug formatting lines up with original |
1147 } | 1348 oStartPtT->fT + oStartRange * startPart, test); |
1148 if (startPart < oStartPart) { | 1349 else log->record(kAddExpandedCoin_Glitch, id, |
1149 double newT = oStartPtT->fT + oStartRange * startPart; | 1350 startPtT->fT + startRange * oStartPart, oTest); |
1150 log->record(kAddExpandedCoin_Glitch, id, oStart, newT, test- >pt()); | 1351 if (false) { |
1151 bumpOTest = false; | 1352 SkASSERT(0); |
1152 } else { | 1353 return; |
1153 double newT = startPtT->fT + startRange * oStartPart; | 1354 } |
1154 log->record(kAddExpandedCoin_Glitch, id, start, newT, oTest- >pt()); | 1355 if (startOver) { |
1155 bumpTest = false; | 1356 test = start; |
1156 } | 1357 oTest = oStart; |
1157 } | 1358 } |
1158 if (bumpTest && test != end) { | 1359 } |
1360 if (test != end) { | |
1159 test = test->upCast()->next(); | 1361 test = test->upCast()->next(); |
1160 } | 1362 } |
1161 if (bumpOTest && oTest != oEnd) { | 1363 if (oTest != oEnd) { |
1162 oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next() ; | 1364 oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next( ); |
1163 } | 1365 if (!oTest) { |
1164 } | 1366 return; |
1165 } while ((coin = coin->fNext)); | 1367 } |
1166 } | 1368 } |
1167 | 1369 } |
1168 static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d ouble tEnd, | 1370 } while ((coin = coin->next())); |
1169 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs, double* coinTe) { | 1371 return; |
1170 double denom = overE->fT - overS->fT; | 1372 } |
1171 double start = 0 < denom ? tStart : tEnd; | 1373 |
1172 double end = 0 < denom ? tEnd : tStart; | 1374 /* Commented-out lines keep this in sync with addIfMissing() */ |
1173 double sRatio = (start - overS->fT) / denom; | 1375 void SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const Sk OpPtT* over1s, |
1174 double eRatio = (end - overS->fT) / denom; | 1376 const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog* lo g) const { |
1175 *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; | 1377 // SkASSERT(fTop); |
1176 *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; | 1378 if (fTop && alreadyAdded(fTop, outer, over1s, over1e)) { // in debug, fTop may be null |
1177 } | 1379 return; |
1178 | 1380 } |
1179 bool SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const Sk OpPtT* over1s, | 1381 if (fHead && alreadyAdded(fHead, outer, over1s, over1e)) { |
1180 const SkOpPtT* over1e) const { | 1382 return; |
1181 const SkCoincidentSpans* check = this->fTop; | 1383 } |
1182 while (check) { | 1384 log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coin PtTEnd(), over1s, over1e); |
1183 if (check->fCoinPtTStart->span() == over1s->span() | 1385 this->debugValidate(); |
1184 && check->fOppPtTStart->span() == outer->fOppPtTStart->span()) { | 1386 return; |
1185 SkASSERT(check->fCoinPtTEnd->span() == over1e->span() | 1387 } |
1186 || !fDebugState->debugRunFail()); | 1388 |
1187 SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span() | 1389 /* Commented-out lines keep this in sync addIfMissing() */ |
1188 || !fDebugState->debugRunFail()); | 1390 void SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* ov er1e, |
1189 return false; | 1391 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd , |
1190 } | 1392 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
1191 if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span() | 1393 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, const char* id, Sk PathOpsDebug::GlitchLog* log) const { |
1192 && check->fOppPtTStart->span() == over1s->span()) { | |
1193 SkASSERT(check->fCoinPtTEnd->span() == outer->fCoinPtTEnd->span() | |
1194 || !fDebugState->debugRunFail()); | |
1195 SkASSERT(check->fOppPtTEnd->span() == over1e->span() | |
1196 || !fDebugState->debugRunFail()); | |
1197 return false; | |
1198 } | |
1199 check = check->fNext; | |
1200 } | |
1201 return true; | |
1202 } | |
1203 | |
1204 bool SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* ov er1e, | |
1205 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStar t, double tEnd, | |
1206 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | |
1207 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const { | |
1208 double coinTs, coinTe, oppTs, oppTe; | 1394 double coinTs, coinTe, oppTs, oppTe; |
1209 t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &co inTe); | 1395 TRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coi nTe); |
1210 t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe ); | 1396 TRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe) ; |
1397 bool swap = coinTs > coinTe; | |
1398 if (swap) { | |
1399 SkTSwap(coinTs, coinTe); | |
1400 } | |
1401 if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { | |
1402 SkTSwap(oppTs, oppTe); | |
1403 } | |
1404 if (swap) { | |
1405 SkTSwap(oppTs, oppTe); | |
1406 } | |
1211 const SkOpSegment* coinSeg = coinPtTStart->segment(); | 1407 const SkOpSegment* coinSeg = coinPtTStart->segment(); |
1212 const SkOpSegment* oppSeg = oppPtTStart->segment(); | 1408 const SkOpSegment* oppSeg = oppPtTStart->segment(); |
1213 SkASSERT(coinSeg != oppSeg); | 1409 if (coinSeg == oppSeg) { |
1214 const SkCoincidentSpans* check = this->fTop; | 1410 return; |
1215 ; | 1411 } |
1216 while (check) { | 1412 return this->debugAddOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe , id, log); |
1217 const SkOpSegment* checkCoinSeg = check->fCoinPtTStart->segment(); | 1413 } |
1218 const SkOpSegment* checkOppSeg; | 1414 |
1219 if (checkCoinSeg != coinSeg && checkCoinSeg != oppSeg) { | 1415 /* Commented-out lines keep this in sync addOrOverlap() */ |
1220 goto next; | 1416 void SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSe gment* oppSeg, |
1221 } | 1417 double coinTs, double coinTe, double oppTs, double oppTe, const char* id , SkPathOpsDebug::GlitchLog* log) const { |
1222 checkOppSeg = check->fOppPtTStart->segment(); | 1418 SkTDArray<SkCoincidentSpans*> overlaps; |
1223 if (checkOppSeg != coinSeg && checkOppSeg != oppSeg) { | 1419 SkASSERT(!fTop); // this is (correctly) reversed in addifMissing() |
1224 goto next; | 1420 if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs , oppTe, &overlaps)) { |
1225 } | 1421 return; |
1226 { | 1422 } |
1227 int cTs = coinTs; | 1423 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, |
1228 int cTe = coinTe; | 1424 coinTe, oppTs, oppTe, &overlaps)) { |
1229 int oTs = oppTs; | 1425 return; |
1230 int oTe = oppTe; | 1426 } |
1231 if (checkCoinSeg != coinSeg) { | 1427 const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; |
1232 SkASSERT(checkOppSeg != oppSeg); | 1428 for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing |
1233 SkTSwap(cTs, oTs); | 1429 const SkCoincidentSpans* test = overlaps[index]; |
1234 SkTSwap(cTe, oTe); | 1430 if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { |
1235 } | 1431 log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart()) ; |
1236 int tweenCount = (int) between(check->fCoinPtTStart->fT, cTs, check- >fCoinPtTEnd->fT) | 1432 } |
1237 + (int) between(check->fCoinPtTStart->fT, cTe, check- >fCoinPtTEnd->fT) | 1433 if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { |
1238 + (int) between(check->fOppPtTStart->fT, oTs, check-> fOppPtTEnd->fT) | 1434 log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd()); |
1239 + (int) between(check->fOppPtTStart->fT, oTe, check-> fOppPtTEnd->fT); | 1435 } |
1240 // SkASSERT(tweenCount == 0 || tweenCount == 4); | 1436 if (overlap->flipped() |
1241 if (tweenCount) { | 1437 ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT |
1242 return true; | 1438 : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { |
1243 } | 1439 log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart()); |
1244 } | 1440 } |
1245 next: | 1441 if (overlap->flipped() |
1246 check = check->fNext; | 1442 ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT |
1247 } | 1443 : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { |
1248 if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { | 1444 log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd()); |
1249 SkTSwap(oppTs, oppTe); | 1445 } |
1250 } | 1446 if (!fHead) { |
1251 if (coinTs > coinTe) { | 1447 SkAssertResult(true); |
1252 SkTSwap(coinTs, coinTe); | 1448 } |
1253 SkTSwap(oppTs, oppTe); | 1449 } |
1254 } | 1450 const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); |
1255 bool cs = coinSeg->debugAddMissing(coinTs, oppSeg); | 1451 const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); |
1256 bool ce = coinSeg->debugAddMissing(coinTe, oppSeg); | 1452 if (overlap && cs && ce && overlap->contains(cs, ce)) { |
1257 if (cs == ce) { | 1453 return; |
1258 return false; | 1454 } |
1259 } | 1455 SkASSERT(cs != ce || !cs); |
1260 return true; | 1456 const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); |
1261 } | 1457 const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); |
1262 | 1458 if (overlap && os && oe && overlap->contains(os, oe)) { |
1459 return; | |
1460 } | |
1461 SkASSERT(true || !cs || !cs->deleted()); | |
1462 SkASSERT(true || !os || !os->deleted()); | |
1463 SkASSERT(true || !ce || !ce->deleted()); | |
1464 SkASSERT(true || !oe || !oe->deleted()); | |
1465 const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullp tr; | |
1466 const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullp tr; | |
1467 if (csExisting && csExisting == ceExisting) { | |
1468 return; | |
1469 } | |
1470 if (csExisting && (csExisting == ce || csExisting->contains(ceExisting ? ceE xisting : ce))) { | |
1471 return; | |
1472 } | |
1473 if (ceExisting && (ceExisting == cs || ceExisting->contains(csExisting ? csE xisting : cs))) { | |
1474 return; | |
1475 } | |
1476 const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr ; | |
1477 const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr ; | |
1478 if (osExisting && osExisting == oeExisting) { | |
1479 return; | |
1480 } | |
1481 if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeE xisting : oe))) { | |
1482 return; | |
1483 } | |
1484 if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osE xisting : os))) { | |
1485 return; | |
1486 } | |
1487 bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = f alse; | |
1488 this->debugValidate(); | |
1489 if (!cs || !os) { | |
1490 if (!cs) | |
1491 cs = coinSeg->debugAddT(coinTs, SkOpSegment::kNoAliasMatch, nullptr) ; | |
1492 if (!os) | |
1493 os = oppSeg->debugAddT(oppTs, SkOpSegment::kNoAliasMatch, nullptr); | |
1494 if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDe leted, &osDeleted); | |
1495 // cs = csWritable; | |
herb_g
2016/07/18 15:13:39
You have a bunch of commented out code in this rou
caryclark
2016/07/18 15:55:49
See reply above.
| |
1496 // os = osWritable; | |
1497 if ((ce && ce->deleted()) || (oe && oe->deleted())) { | |
1498 return; | |
1499 } | |
1500 } | |
1501 if (!ce || !oe) { | |
1502 if (!ce) | |
1503 ce = coinSeg->debugAddT(coinTe, SkOpSegment::kNoAliasMatch, nullptr) ; | |
1504 if (!oe) | |
1505 oe = oppSeg->debugAddT(oppTe, SkOpSegment::kNoAliasMatch, nullptr); | |
1506 if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDe leted, &oeDeleted); | |
1507 // ce = ceWritable; | |
1508 // oe = oeWritable; | |
1509 } | |
1510 this->debugValidate(); | |
1511 if (csDeleted || osDeleted || ceDeleted || oeDeleted) { | |
1512 return; | |
1513 } | |
1514 if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) { | |
1515 return; | |
1516 } | |
1517 // bool result = true; | |
1518 if (overlap) { | |
1519 if (overlap->coinPtTStart()->segment() == coinSeg) { | |
1520 log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinT e, oppSeg, oppTs, oppTe); | |
1521 } else { | |
1522 if (oppTs > oppTe) { | |
1523 SkTSwap(coinTs, coinTe); | |
1524 SkTSwap(oppTs, oppTe); | |
1525 } | |
1526 log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coin Seg, coinTs, coinTe); | |
1527 } | |
1528 #if DEBUG_COINCIDENCE_VERBOSE | |
1529 // if (result) { | |
1530 // overlap->debugShow(); | |
1531 // } | |
1532 #endif | |
1533 } else { | |
1534 log->record(kAddMissingCoin_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); | |
1535 #if DEBUG_COINCIDENCE_VERBOSE | |
1536 // fHead->debugShow(); | |
1537 #endif | |
1538 } | |
1539 this->debugValidate(); | |
1540 return; | |
1541 } | |
1542 | |
1543 // Extra commented-out lines keep this in sync with addMissing() | |
1544 /* detects overlaps of different coincident runs on same segment */ | |
1545 /* does not detect overlaps for pairs without any segments in common */ | |
1546 // returns true if caller should loop again | |
1263 void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const { | 1547 void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const { |
1264 const SkCoincidentSpans* outer = fHead; | 1548 const SkCoincidentSpans* outer = fHead; |
1265 if (!outer) { | 1549 if (!outer) { |
1266 return; | 1550 return; |
1267 } | 1551 } |
1552 // bool added = false; | |
1553 // fTop = outer; | |
1554 // fHead = nullptr; | |
1268 do { | 1555 do { |
1269 // addifmissing can modify the list that this is walking | 1556 // addifmissing can modify the list that this is walking |
1270 // save head so that walker can iterate over old data unperturbed | 1557 // save head so that walker can iterate over old data unperturbed |
1271 // addifmissing adds to head freely then add saved head in the end | 1558 // addifmissing adds to head freely then add saved head in the end |
1272 const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment(); | 1559 const SkOpSegment* outerCoin = outer->coinPtTStart()->segment(); |
1273 SkASSERT(outerCoin == outer->fCoinPtTEnd->segment()); | 1560 const SkOpSegment* outerOpp = outer->oppPtTStart()->segment(); |
1274 const SkOpSegment* outerOpp = outer->fOppPtTStart->segment(); | 1561 if (outerCoin->done() || outerOpp->done()) { |
1275 SkASSERT(outerOpp == outer->fOppPtTEnd->segment()); | 1562 continue; |
1563 } | |
1276 const SkCoincidentSpans* inner = outer; | 1564 const SkCoincidentSpans* inner = outer; |
1277 while ((inner = inner->fNext)) { | 1565 while ((inner = inner->next())) { |
1566 this->debugValidate(); | |
1278 double overS, overE; | 1567 double overS, overE; |
1279 const SkOpSegment* innerCoin = inner->fCoinPtTStart->segment(); | 1568 const SkOpSegment* innerCoin = inner->coinPtTStart()->segment(); |
1280 SkASSERT(innerCoin == inner->fCoinPtTEnd->segment()); | 1569 const SkOpSegment* innerOpp = inner->oppPtTStart()->segment(); |
1281 const SkOpSegment* innerOpp = inner->fOppPtTStart->segment(); | 1570 if (innerCoin->done() || innerOpp->done()) { |
1282 SkASSERT(innerOpp == inner->fOppPtTEnd->segment()); | 1571 continue; |
1283 if (outerCoin == innerCoin | 1572 } |
1284 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 1573 if (outerCoin == innerCoin) { |
1285 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 1574 if (outerOpp != innerOpp |
1286 if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPt TEnd, | 1575 && this->overlap(outer->coinPtTStart(), outer->coinPtTEn d(), |
1287 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 1576 inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &ove rE)) { |
1288 outer->fOppPtTStart, outer->fOppPtTEnd, | 1577 this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPt TEnd(), |
1289 inner->fOppPtTStart, inner->fOppPtTEnd)) { | 1578 inner->coinPtTStart(), inner->coinPtTEnd(), overS, o verE, |
1290 log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinP tTStart); | 1579 outer->oppPtTStart(), outer->oppPtTEnd(), |
1291 } | 1580 inner->oppPtTStart(), inner->oppPtTEnd(), id, log); |
1292 } else if (outerCoin == innerOpp | 1581 } |
1293 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 1582 } else if (outerCoin == innerOpp) { |
1294 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 1583 if (outerOpp != innerCoin |
1295 if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPt TEnd, | 1584 && this->overlap(outer->coinPtTStart(), outer->coinPtTEn d(), |
1296 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 1585 inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE )) { |
1297 outer->fOppPtTStart, outer->fOppPtTEnd, | 1586 this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPt TEnd(), |
1298 inner->fCoinPtTStart, inner->fCoinPtTEnd)) { | 1587 inner->oppPtTStart(), inner->oppPtTEnd(), overS, ove rE, |
1299 log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPt TStart); | 1588 outer->oppPtTStart(), outer->oppPtTEnd(), |
1300 } | 1589 inner->coinPtTStart(), inner->coinPtTEnd(), id, log) ; |
1301 } else if (outerOpp == innerCoin | 1590 } |
1302 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 1591 } else if (outerOpp == innerCoin) { |
1303 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 1592 SkASSERT(outerCoin != innerOpp); |
1304 if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTE nd, | 1593 if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), |
1305 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 1594 inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &ove rE)) { |
1306 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 1595 this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTE nd(), |
1307 inner->fOppPtTStart, inner->fOppPtTEnd)) { | 1596 inner->coinPtTStart(), inner->coinPtTEnd(), overS, o verE, |
1308 log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinP tTStart); | 1597 outer->coinPtTStart(), outer->coinPtTEnd(), |
1309 } | 1598 inner->oppPtTStart(), inner->oppPtTEnd(), id, log); |
1310 } else if (outerOpp == innerOpp | 1599 } |
1311 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 1600 } else if (outerOpp == innerOpp) { |
1312 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 1601 SkASSERT(outerCoin != innerCoin); |
1313 if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTE nd, | 1602 if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), |
1314 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 1603 inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE )) { |
1315 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 1604 this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTE nd(), |
1316 inner->fCoinPtTStart, inner->fCoinPtTEnd)) { | 1605 inner->oppPtTStart(), inner->oppPtTEnd(), overS, ove rE, |
1317 log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPt TStart); | 1606 outer->coinPtTStart(), outer->coinPtTEnd(), |
1318 } | 1607 inner->coinPtTStart(), inner->coinPtTEnd(), id, log) ; |
1319 } else if (outerCoin != innerCoin) { | 1608 } |
1320 // check to see if outer span overlaps the inner span | 1609 } |
1321 // look for inner segment in pt-t list | 1610 this->debugValidate(); |
1322 // if present, and if t values are in coincident range | 1611 } |
1323 // add two pairs of new coincidence | 1612 } while ((outer = outer->next())); |
1324 const SkOpPtT* testS = outer->fCoinPtTStart->debugContains(inner Coin); | 1613 // this->restoreHead(); |
1325 const SkOpPtT* testE = outer->fCoinPtTEnd->debugContains(innerCo in); | 1614 return; |
1326 if (testS && testS->fT >= inner->fCoinPtTStart->fT | 1615 } |
1327 && testE && testE->fT <= inner->fCoinPtTEnd->fT | 1616 |
1328 && this->testForCoincidence(outer, testS, testE)) { | 1617 // Commented-out lines keep this in sync with release() |
1329 if (this->debugAddIfMissing(outer, testS, testE)) { | 1618 void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* lo g, const SkOpSegment* deleted) const { |
1330 log->record(kAddMissingCoin_Glitch, id, outer, testS, te stE); | 1619 const SkCoincidentSpans* coin = fHead; |
1331 } | 1620 if (!coin) { |
1332 } else { | 1621 return; |
1333 testS = inner->fCoinPtTStart->debugContains(outerCoin); | 1622 } |
1334 testE = inner->fCoinPtTEnd->debugContains(outerCoin); | 1623 do { |
1335 if (testS && testS->fT >= outer->fCoinPtTStart->fT | 1624 if (coin->coinPtTStart()->segment() == deleted |
1336 && testE && testE->fT <= outer->fCoinPtTEnd->fT | 1625 || coin->coinPtTEnd()->segment() == deleted |
1337 && this->testForCoincidence(inner, testS, testE)) { | 1626 || coin->oppPtTStart()->segment() == deleted |
1338 if (this->debugAddIfMissing(inner, testS, testE)) { | 1627 || coin->oppPtTEnd()->segment() == deleted) { |
1339 log->record(kAddMissingCoin_Glitch, id, inner, testS , testE); | 1628 log->record(kReleasedSpan_Glitch, id, coin); |
1340 } | 1629 } |
1341 } | 1630 } while ((coin = coin->next())); |
1342 } | 1631 } |
1343 } | 1632 |
1344 } | 1633 // Commented-out lines keep this in sync with reorder() |
1345 } while ((outer = outer->fNext)); | 1634 // iterate through all coincident pairs, looking for ranges greater than 1 |
1346 } | 1635 // if found, see if the opposite pair can match it -- which may require |
1347 | 1636 // reordering the ptT pairs |
1637 void SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* lo g) const { | |
1638 const SkCoincidentSpans* coin = fHead; | |
1639 if (!coin) { | |
1640 return; | |
1641 } | |
1642 do { | |
1643 // most commonly, concidence are one span long; check for that first | |
1644 int intervals = coin->spanCount(); | |
1645 if (intervals = 1) { | |
1646 #if DEBUG_COINCIDENCE_VERBOSE | |
1647 // SkASSERT(!coin->debugExpand(nullptr, nullptr)); | |
1648 #endif | |
1649 continue; | |
1650 } | |
1651 coin->debugExpand(id, log); | |
1652 if (coin->spanCount() <= 0) { | |
1653 return; | |
1654 } | |
1655 // check to see if every span in coin has a mate in opp | |
1656 const SkOpSpan* start = coin->coinPtTStart()->span()->upCast(); | |
1657 bool flipped = coin->flipped(); | |
1658 const SkOpSpanBase* oppStartBase = coin->oppPtTStart()->span(); | |
1659 const SkOpSpan* oppStart = flipped ? oppStartBase->prev() : oppStartBase ->upCast(); | |
1660 SkDebugf("", start, oppStart); | |
1661 } while ((coin = coin->next())); | |
1662 return; | |
1663 } | |
1664 | |
1665 // Commented-out lines keep this in sync with expand() | |
1666 // expand the range by checking adjacent spans for coincidence | |
1348 bool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log ) const { | 1667 bool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log ) const { |
1349 const SkCoincidentSpans* coin = fHead; | 1668 const SkCoincidentSpans* coin = fHead; |
1350 if (!coin) { | 1669 if (!coin) { |
1351 return false; | 1670 return false; |
1352 } | 1671 } |
1353 bool expanded = false; | 1672 bool expanded = false; |
1354 do { | 1673 do { |
1355 const SkOpSpan* start = coin->fCoinPtTStart->span()->upCast(); | 1674 if (coin->debugExpand(id, log)) { |
1356 const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); | 1675 // check to see if multiple spans expanded so they are now identical |
1357 const SkOpSegment* segment = coin->fCoinPtTStart->segment(); | 1676 const SkCoincidentSpans* test = fHead; |
1358 const SkOpSegment* oppSegment = coin->fOppPtTStart->segment(); | 1677 do { |
1359 const SkOpSpan* prev = start->prev(); | 1678 if (coin == test) { |
1360 if (prev && prev->debugContains(oppSegment)) { | 1679 continue; |
1361 double midT = (prev->t() + start->t()) / 2; | 1680 } |
1362 if (segment->isClose(midT, oppSegment)) { | 1681 if (coin->coinPtTStart() == test->coinPtTStart() |
1363 log->record(kExpandCoin_Glitch, id, coin, prev); | 1682 && coin->oppPtTStart() == test->oppPtTStart()) { |
1364 } | 1683 if (log) log->record(kExpandCoin_Glitch, id, fHead, test->co inPtTStart()); |
1365 } | 1684 break; |
1366 SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); | 1685 } |
1367 if (next && next->debugContains(oppSegment)) { | 1686 } while ((test = test->next())); |
1368 double midT = (end->t() + next->t()) / 2; | 1687 expanded = true; |
1369 if (segment->isClose(midT, oppSegment)) { | 1688 } |
1370 log->record(kExpandCoin_Glitch, id, coin, next); | 1689 } while ((coin = coin->next())); |
1371 } | |
1372 } | |
1373 } while ((coin = coin->fNext)); | |
1374 return expanded; | 1690 return expanded; |
1375 } | 1691 } |
1376 | 1692 |
1377 void SkOpCoincidence::debugFixAligned(const char* id, SkPathOpsDebug::GlitchLog* log) const { | 1693 // Commented-out lines keep this in sync with removeCollapsed() |
1694 void SkOpCoincidence::debugRemoveCollapsed(const char* id, SkPathOpsDebug::Glitc hLog* log) const { | |
1378 const SkCoincidentSpans* coin = fHead; | 1695 const SkCoincidentSpans* coin = fHead; |
1379 if (!coin) { | 1696 if (!coin) { |
1380 return; | 1697 return; |
1381 } | 1698 } |
1382 do { | 1699 // SkCoincidentSpans** priorPtr = &fHead; |
1383 if (coin->fCoinPtTStart->deleted()) { | 1700 do { |
1384 log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTStart); | 1701 if (coin->coinPtTStart() == coin->coinPtTEnd()) { |
1385 } | 1702 return; |
1386 if (coin->fCoinPtTEnd->deleted()) { | 1703 } |
1387 log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTEnd); | 1704 if (coin->oppPtTStart() == coin->oppPtTEnd()) { |
1388 } | 1705 return; |
1389 if (coin->fOppPtTStart->deleted()) { | 1706 } |
1390 log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTStart); | 1707 if (coin->coinPtTStart()->collapsed(coin->coinPtTEnd())) { |
1391 } | 1708 log->record(kCollapsedCoin_Glitch, id, coin); |
1392 if (coin->fOppPtTEnd->deleted()) { | 1709 // continue; |
1393 log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTEnd); | 1710 } |
1394 } | 1711 if (coin->oppPtTStart()->collapsed(coin->oppPtTEnd())) { |
1395 } while ((coin = coin->fNext)); | 1712 log->record(kCollapsedCoin_Glitch, id, coin, coin); |
1396 coin = fHead; | 1713 // continue; |
1397 do { | 1714 } |
1398 if (coin->fCoinPtTStart->collapsed(coin->fCoinPtTEnd)) { | 1715 // priorPtr = &coin->nextPtr(); |
1399 log->record(kCollapsedCoin_Glitch, id, coin, coin->fCoinPtTStart); | 1716 } while ((coin = coin->next())); |
1400 } | 1717 return; |
1401 if (coin->fOppPtTStart->collapsed(coin->fOppPtTEnd)) { | 1718 } |
1402 log->record(kCollapsedCoin_Glitch, id, coin, coin->fOppPtTStart); | 1719 |
1403 } | 1720 // Commented-out lines keep this in sync with mark() |
1404 } while ((coin = coin->fNext)); | 1721 /* this sets up the coincidence links in the segments when the coincidence cross es multiple spans */ |
1405 } | |
1406 | |
1407 void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const { | 1722 void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const { |
1408 const SkCoincidentSpans* coin = fHead; | 1723 const SkCoincidentSpans* coin = fHead; |
1409 if (!coin) { | 1724 if (!coin) { |
1410 return; | 1725 return; |
1411 } | 1726 } |
1412 do { | 1727 do { |
1413 const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); | 1728 const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); |
1414 const SkOpSpanBase* oldEnd = end; | 1729 // SkASSERT(start->deleted()); |
1415 const SkOpSpan* start = coin->fCoinPtTStart->span()->debugStarter(&end); | 1730 const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); |
1416 const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); | 1731 // SkASSERT(end->deleted()); |
1417 const SkOpSpanBase* oOldEnd = oEnd; | 1732 const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); |
1418 const SkOpSpanBase* oStart = coin->fOppPtTStart->span()->debugStarter(&o End); | 1733 // SkASSERT(oStart->deleted()); |
1419 bool flipped = (end == oldEnd) != (oEnd == oOldEnd); | 1734 const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); |
1735 // SkASSERT(oEnd->deleted()); | |
1736 bool flipped = coin->flipped(); | |
1420 if (flipped) { | 1737 if (flipped) { |
1421 SkTSwap(oStart, oEnd); | 1738 SkTSwap(oStart, oEnd); |
1422 } | 1739 } |
1740 /* coin and opp spans may not match up. Mark the ends, and then let the interior | |
1741 get marked as many times as the spans allow */ | |
1742 start->debugInsertCoincidence(id, log, oStart->upCast()); | |
1743 end->debugInsertCoinEnd(id, log, oEnd); | |
1744 const SkOpSegment* segment = start->segment(); | |
1745 const SkOpSegment* oSegment = oStart->segment(); | |
1423 const SkOpSpanBase* next = start; | 1746 const SkOpSpanBase* next = start; |
1424 const SkOpSpanBase* oNext = oStart; | 1747 const SkOpSpanBase* oNext = oStart; |
1748 while ((next = next->upCast()->next()) != end) { | |
1749 if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flippe d), false) { | |
1750 return; | |
1751 } | |
1752 } | |
1753 while ((oNext = oNext->upCast()->next()) != oEnd) { | |
1754 if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flippe d), false) { | |
1755 return; | |
1756 } | |
1757 } | |
1758 } while ((coin = coin->next())); | |
1759 return; | |
1760 } | |
1761 #endif | |
1762 | |
1763 #if DEBUG_COINCIDENCE_VERBOSE | |
1764 // Commented-out lines keep this in sync with markCollapsed() | |
1765 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL og* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { | |
1766 while (coin) { | |
1767 if (coin->collapsed(test)) { | |
1768 if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinP tTEnd()->fT)) { | |
1769 log->record(kCollapsedCoin_Glitch, id, coin); | |
1770 } | |
1771 if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtT End()->fT)) { | |
1772 log->record(kCollapsedCoin_Glitch, id, coin); | |
1773 } | |
1774 } | |
1775 coin = coin->next(); | |
1776 } | |
1777 } | |
1778 | |
1779 // Commented-out lines keep this in sync with markCollapsed() | |
1780 void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL og* log, const SkOpPtT* test) const { | |
1781 this->debugMarkCollapsed(id, log, fHead, test); | |
1782 this->debugMarkCollapsed(id, log, fTop, test); | |
1783 } | |
1784 #endif | |
1785 | |
1786 void SkCoincidentSpans::debugShow() const { | |
1787 SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, | |
1788 coinPtTStart()->segment()->debugID(), | |
1789 coinPtTStart()->fT, coinPtTEnd()->fT); | |
1790 SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, | |
1791 oppPtTStart()->segment()->debugID(), | |
1792 oppPtTStart()->fT, oppPtTEnd()->fT); | |
1793 } | |
1794 | |
1795 void SkOpCoincidence::debugShowCoincidence() const { | |
1796 #if DEBUG_COINCIDENCE | |
1797 const SkCoincidentSpans* span = fHead; | |
1798 while (span) { | |
1799 span->debugShow(); | |
1800 span = span->next(); | |
1801 } | |
1802 #endif | |
1803 } | |
1804 | |
1805 #if DEBUG_COINCIDENCE | |
1806 static void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end, | |
1807 double oStart, double oEnd, const SkOpSegment* oSegment, | |
1808 const char* id, SkPathOpsDebug::GlitchLog* log) { | |
1809 SkASSERT(next != end); | |
1810 SkASSERT(!next->contains(end) || log); | |
1811 if (next->t() > end->t()) { | |
1812 SkTSwap(next, end); | |
1813 } | |
1814 do { | |
1815 const SkOpPtT* ptT = next->ptT(); | |
1816 int index = 0; | |
1817 bool somethingBetween; | |
1425 do { | 1818 do { |
1426 next = next->upCast()->next(); | 1819 ++index; |
1427 oNext = flipped ? oNext->prev() : oNext->upCast()->next(); | 1820 ptT = ptT->next(); |
1428 if (next == end || oNext == oEnd) { | 1821 const SkOpPtT* checkPtT = next->ptT(); |
1822 if (ptT == checkPtT) { | |
1429 break; | 1823 break; |
1430 } | 1824 } |
1431 if (!next->containsCoinEnd(oNext)) { | 1825 bool looped = false; |
1432 log->record(kMarkCoinEnd_Glitch, id, next, oNext); | 1826 for (int check = 0; check < index; ++check) { |
1433 } | 1827 if ((looped = checkPtT == ptT)) { |
1434 const SkOpSpan* nextSpan = next->upCast(); | 1828 break; |
1435 const SkOpSpan* oNextSpan = oNext->upCast(); | 1829 } |
1436 if (!nextSpan->containsCoincidence(oNextSpan)) { | 1830 checkPtT = checkPtT->next(); |
1437 log->record(kMarkCoinInsert_Glitch, id, nextSpan, oNextSpan); | 1831 } |
1438 } | 1832 if (looped) { |
1833 SkASSERT(0); | |
1834 break; | |
1835 } | |
1836 if (ptT->deleted()) { | |
1837 continue; | |
1838 } | |
1839 if (ptT->segment() != oSegment) { | |
1840 continue; | |
1841 } | |
1842 somethingBetween |= between(oStart, ptT->fT, oEnd); | |
1439 } while (true); | 1843 } while (true); |
1440 } while ((coin = coin->fNext)); | 1844 SkASSERT(somethingBetween); |
1441 } | 1845 } while (next != end && (next = next->upCast()->next())); |
1442 #endif | 1846 } |
1443 | 1847 |
1444 void SkOpCoincidence::debugShowCoincidence() const { | 1848 static void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentS pans* list, |
1445 SkCoincidentSpans* span = fHead; | 1849 const char* id, SkPathOpsDebug::GlitchLog* log) { |
1446 while (span) { | 1850 if (!list) { |
1447 SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, | 1851 return; |
1448 span->fCoinPtTStart->segment()->debugID(), | 1852 } |
1449 span->fCoinPtTStart->fT, span->fCoinPtTEnd->fT); | 1853 const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); |
1450 SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, | 1854 SkASSERT(coinSeg == test->coinPtTEnd()->segment()); |
1451 span->fOppPtTStart->segment()->debugID(), | 1855 const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); |
1452 span->fOppPtTStart->fT, span->fOppPtTEnd->fT); | 1856 SkASSERT(oppSeg == test->oppPtTEnd()->segment()); |
1453 span = span->fNext; | 1857 SkASSERT(coinSeg != test->oppPtTStart()->segment()); |
1454 } | 1858 SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); |
1455 } | 1859 SkASSERT(between(0, tcs, 1)); |
1456 | 1860 SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); |
1861 SkASSERT(between(0, tce, 1)); | |
1862 SkASSERT(tcs < tce); | |
1863 double tos = test->oppPtTStart()->fT; | |
1864 SkASSERT(between(0, tos, 1)); | |
1865 double toe = test->oppPtTEnd()->fT; | |
1866 SkASSERT(between(0, toe, 1)); | |
1867 SkASSERT(tos != toe); | |
1868 if (tos > toe) { | |
1869 SkTSwap(tos, toe); | |
1870 } | |
1871 do { | |
1872 double lcs, lce, los, loe; | |
1873 if (coinSeg == list->coinPtTStart()->segment()) { | |
1874 if (oppSeg != list->oppPtTStart()->segment()) { | |
1875 continue; | |
1876 } | |
1877 lcs = list->coinPtTStart()->fT; | |
1878 lce = list->coinPtTEnd()->fT; | |
1879 los = list->oppPtTStart()->fT; | |
1880 loe = list->oppPtTEnd()->fT; | |
1881 if (los > loe) { | |
1882 SkTSwap(los, loe); | |
1883 } | |
1884 } else if (coinSeg == list->oppPtTStart()->segment()) { | |
1885 if (oppSeg != list->coinPtTStart()->segment()) { | |
1886 continue; | |
1887 } | |
1888 lcs = list->oppPtTStart()->fT; | |
1889 lce = list->oppPtTEnd()->fT; | |
1890 if (lcs > lce) { | |
1891 SkTSwap(lcs, lce); | |
1892 } | |
1893 los = list->coinPtTStart()->fT; | |
1894 loe = list->coinPtTEnd()->fT; | |
1895 } else { | |
1896 continue; | |
1897 } | |
1898 SkASSERT(tce < lcs || lce < tcs); | |
1899 SkASSERT(toe < los || loe < tos); | |
1900 } while ((list = list->next())); | |
1901 } | |
1902 | |
1903 | |
1904 static void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincide ntSpans* opt, | |
1905 const char* id, SkPathOpsDebug::GlitchLog* log) { | |
1906 // check for overlapping coincident spans | |
1907 const SkCoincidentSpans* test = head; | |
1908 while (test) { | |
1909 const SkCoincidentSpans* next = test->next(); | |
1910 DebugCheckOverlap(test, next, id, log); | |
1911 DebugCheckOverlap(test, opt, id, log); | |
1912 test = next; | |
1913 } | |
1914 } | |
1915 | |
1916 #if DEBUG_COINCIDENCE_VERBOSE | |
1917 void SkOpCoincidence::debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLo g* log) const { | |
1918 DebugCheckOverlapTop(fHead, fTop, id, log); | |
1919 DebugCheckOverlapTop(fTop, nullptr, id, log); | |
1920 } | |
1921 #endif | |
1922 | |
1923 static void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans * opt, | |
1924 const char* id, SkPathOpsDebug::GlitchLog* log) { | |
1925 // look for pts inside coincident spans that are not inside the opposite spa ns | |
1926 const SkCoincidentSpans* coin = head; | |
1927 while (coin) { | |
1928 SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), | |
1929 coin->oppPtTStart()->segment())); | |
1930 SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); | |
1931 SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); | |
1932 SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); | |
1933 SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); | |
1934 DebugValidate(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), | |
1935 coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStar t()->segment(), | |
1936 id, log); | |
1937 DebugValidate(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), | |
1938 coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTS tart()->segment(), | |
1939 id, log); | |
1940 coin = coin->next(); | |
1941 } | |
1942 DebugCheckOverlapTop(head, opt, id, log); | |
1943 } | |
1944 #endif | |
1945 | |
1946 void SkOpCoincidence::debugValidate() const { | |
1457 #if DEBUG_COINCIDENCE | 1947 #if DEBUG_COINCIDENCE |
1948 // if (fGlobalState->debugCheckHealth()) { | |
1949 // return; | |
1950 // } | |
1951 DebugValidate(fHead, fTop, nullptr, nullptr); | |
1952 DebugValidate(fTop, nullptr, nullptr, nullptr); | |
1953 #endif | |
1954 } | |
1955 | |
1956 #if DEBUG_COINCIDENCE_VERBOSE | |
1957 void SkOpCoincidence::debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const { | |
1958 DebugValidate(fHead, fTop, id, log); | |
1959 DebugValidate(fTop, nullptr, id, log); | |
1960 } | |
1961 #endif | |
1962 | |
1963 #if DEBUG_COINCIDENCE_VERBOSE | |
1458 void SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* lo g) const { | 1964 void SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* lo g) const { |
1459 const SkOpSegment* segment = &fHead; | 1965 const SkOpSegment* segment = &fHead; |
1460 do { | 1966 do { |
1461 segment->debugCheckHealth(id, log); | 1967 segment->debugCheckHealth(id, log); |
1462 } while ((segment = segment->next())); | 1968 } while ((segment = segment->next())); |
1463 } | 1969 } |
1464 | 1970 |
1465 void SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch Log* log, | 1971 // commmented-out lines keep this aligned with missingCoincidence() |
1466 const SkOpCoincidence* coincidence) const { | 1972 void SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch Log* log) const { |
1973 // SkASSERT(fCount > 0); | |
1467 const SkOpSegment* segment = &fHead; | 1974 const SkOpSegment* segment = &fHead; |
1975 // bool result = false; | |
1468 do { | 1976 do { |
1469 segment->debugMissingCoincidence(id, log, coincidence); | 1977 if (fState->angleCoincidence()) { |
1470 } while ((segment = segment->next())); | 1978 // #if DEBUG_ANGLE |
1979 // segment->debugCheckAngleCoin(); | |
1980 // #endif | |
1981 } else if (segment->debugMissingCoincidence(id, log), false) { | |
1982 // result = true; | |
1983 // see FIXME in missingCoincidence() | |
1984 // | |
1985 // | |
1986 // | |
1987 // continue; | |
1988 } | |
1989 segment = segment->next(); | |
1990 } while (segment); | |
1991 return; | |
1471 } | 1992 } |
1472 #endif | 1993 #endif |
1473 | 1994 |
1474 void SkOpSegment::debugValidate() const { | 1995 void SkOpSegment::debugValidate() const { |
1996 #if DEBUG_COINCIDENCE | |
1997 if (this->globalState()->debugCheckHealth()) { | |
1998 return; | |
1999 } | |
2000 #endif | |
1475 #if DEBUG_VALIDATE | 2001 #if DEBUG_VALIDATE |
1476 const SkOpSpanBase* span = &fHead; | 2002 const SkOpSpanBase* span = &fHead; |
1477 double lastT = -1; | 2003 double lastT = -1; |
1478 const SkOpSpanBase* prev = nullptr; | 2004 const SkOpSpanBase* prev = nullptr; |
1479 int count = 0; | 2005 int count = 0; |
1480 int done = 0; | 2006 int done = 0; |
1481 do { | 2007 do { |
1482 if (!span->final()) { | 2008 if (!span->final()) { |
1483 ++count; | 2009 ++count; |
1484 done += span->upCast()->done() ? 1 : 0; | 2010 done += span->upCast()->done() ? 1 : 0; |
1485 } | 2011 } |
1486 SkASSERT(span->segment() == this); | 2012 SkASSERT(span->segment() == this); |
1487 SkASSERT(!prev || prev->upCast()->next() == span); | 2013 SkASSERT(!prev || prev->upCast()->next() == span); |
1488 SkASSERT(!prev || prev == span->prev()); | 2014 SkASSERT(!prev || prev == span->prev()); |
1489 prev = span; | 2015 prev = span; |
1490 double t = span->ptT()->fT; | 2016 double t = span->ptT()->fT; |
1491 SkASSERT(lastT < t); | 2017 SkASSERT(lastT < t); |
1492 lastT = t; | 2018 lastT = t; |
1493 span->debugValidate(); | 2019 span->debugValidate(); |
1494 } while (!span->final() && (span = span->upCast()->next())); | 2020 } while (!span->final() && (span = span->upCast()->next())); |
1495 SkASSERT(count == fCount); | 2021 SkASSERT(count == fCount); |
1496 SkASSERT(done == fDoneCount); | 2022 SkASSERT(done == fDoneCount); |
1497 SkASSERT(count >= fDoneCount); | 2023 SkASSERT(count >= fDoneCount); |
1498 SkASSERT(span->final()); | 2024 SkASSERT(span->final()); |
1499 span->debugValidate(); | 2025 span->debugValidate(); |
1500 #endif | 2026 #endif |
1501 } | 2027 } |
1502 | 2028 |
1503 bool SkOpSpanBase::debugAlignedEnd(double t, const SkPoint& pt) const { | 2029 #if DEBUG_COINCIDENCE_VERBOSE |
1504 SkASSERT(zero_or_one(t)); | 2030 // Commented-out lines keep this in sync with addOppAndMerge() |
1505 const SkOpSegment* segment = this->segment(); | 2031 // If the added points envelop adjacent spans, merge them in. |
1506 SkASSERT(t ? segment->lastPt() == pt : segment->pts()[0] == pt); | 2032 void SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog * log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const { |
1507 if (!debugAlignedInner()) { | 2033 if (this->ptT()->debugAddOpp(opp->ptT())) { |
1508 return false; | 2034 this->debugCheckForCollapsedCoincidence(id, log); |
1509 } | 2035 } |
1510 if ((t ? segment->lastPt() : segment->pts()[0]) != pt) { | 2036 // compute bounds of points in span |
1511 return false; | 2037 SkPathOpsBounds bounds; |
2038 bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin); | |
2039 const SkOpPtT* head = this->ptT(); | |
2040 const SkOpPtT* nextPt = head; | |
2041 do { | |
2042 bounds.add(nextPt->fPt); | |
2043 } while ((nextPt = nextPt->next()) != head); | |
2044 if (!bounds.width() && !bounds.height()) { | |
2045 return; | |
1512 } | 2046 } |
1513 const SkOpPtT* ptT = &this->fPtT; | 2047 this->debugMergeContained(id, log, bounds, spanDeleted); |
1514 SkASSERT(t == ptT->fT); | 2048 opp->debugMergeContained(id, log, bounds, oppDeleted); |
1515 SkASSERT(pt == ptT->fPt); | 2049 } |
1516 const SkOpPtT* test = ptT, * stopPtT = ptT; | 2050 |
1517 while ((test = test->next()) != stopPtT) { | 2051 // Commented-out lines keep this in sync with checkForCollapsedCoincidence() |
1518 const SkOpSegment* other = test->segment(); | 2052 void SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDe bug::GlitchLog* log) const { |
1519 if (other == this->segment()) { | 2053 const SkOpCoincidence* coins = this->globalState()->coincidence(); |
2054 if (coins->isEmpty()) { | |
2055 return; | |
2056 } | |
2057 // the insert above may have put both ends of a coincident run in the same span | |
2058 // for each coincident ptT in loop; see if its opposite in is also in the loop | |
2059 // this implementation is the motivation for marking that a ptT is referenced by a coincident span | |
2060 const SkOpPtT* head = this->ptT(); | |
2061 const SkOpPtT* test = head; | |
2062 do { | |
2063 if (!test->coincident()) { | |
1520 continue; | 2064 continue; |
1521 } | 2065 } |
1522 if (!zero_or_one(test->fT)) { | 2066 coins->debugMarkCollapsed(id, log, test); |
1523 continue; | 2067 } while ((test = test->next()) != head); |
1524 } | |
1525 if ((test->fT ? other->lastPt() : other->pts()[0]) != pt) { | |
1526 return false; | |
1527 } | |
1528 } | |
1529 return this->fAligned; | |
1530 } | 2068 } |
1531 | 2069 #endif |
1532 bool SkOpSpanBase::debugAlignedInner() const { | |
1533 // force the spans to share points and t values | |
1534 const SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT; | |
1535 const SkPoint& pt = ptT->fPt; | |
1536 do { | |
1537 if (ptT->fPt != pt) { | |
1538 return false; | |
1539 } | |
1540 const SkOpSpanBase* span = ptT->span(); | |
1541 const SkOpPtT* test = ptT; | |
1542 do { | |
1543 if ((test = test->next()) == stopPtT) { | |
1544 break; | |
1545 } | |
1546 if (span == test->span() && !span->segment()->ptsDisjoint(*ptT, *tes t)) { | |
1547 return false; | |
1548 } | |
1549 } while (true); | |
1550 } while ((ptT = ptT->next()) != stopPtT); | |
1551 return true; | |
1552 } | |
1553 | 2070 |
1554 bool SkOpSpanBase::debugCoinEndLoopCheck() const { | 2071 bool SkOpSpanBase::debugCoinEndLoopCheck() const { |
1555 int loop = 0; | 2072 int loop = 0; |
1556 const SkOpSpanBase* next = this; | 2073 const SkOpSpanBase* next = this; |
1557 SkOpSpanBase* nextCoin; | 2074 SkOpSpanBase* nextCoin; |
1558 do { | 2075 do { |
1559 nextCoin = next->fCoinEnd; | 2076 nextCoin = next->fCoinEnd; |
1560 SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); | 2077 SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); |
1561 for (int check = 1; check < loop - 1; ++check) { | 2078 for (int check = 1; check < loop - 1; ++check) { |
1562 const SkOpSpanBase* checkCoin = this->fCoinEnd; | 2079 const SkOpSpanBase* checkCoin = this->fCoinEnd; |
1563 const SkOpSpanBase* innerCoin = checkCoin; | 2080 const SkOpSpanBase* innerCoin = checkCoin; |
1564 for (int inner = check + 1; inner < loop; ++inner) { | 2081 for (int inner = check + 1; inner < loop; ++inner) { |
1565 innerCoin = innerCoin->fCoinEnd; | 2082 innerCoin = innerCoin->fCoinEnd; |
1566 if (checkCoin == innerCoin) { | 2083 if (checkCoin == innerCoin) { |
1567 SkDebugf("*** bad coincident end loop ***\n"); | 2084 SkDebugf("*** bad coincident end loop ***\n"); |
1568 return false; | 2085 return false; |
1569 } | 2086 } |
1570 } | 2087 } |
1571 } | 2088 } |
1572 ++loop; | 2089 ++loop; |
1573 } while ((next = nextCoin) && next != this); | 2090 } while ((next = nextCoin) && next != this); |
1574 return true; | 2091 return true; |
1575 } | 2092 } |
1576 | 2093 |
1577 bool SkOpSpanBase::debugContains(const SkOpSegment* segment) const { | 2094 #if DEBUG_COINCIDENCE_VERBOSE |
1578 const SkOpPtT* start = &fPtT; | 2095 // Commented-out lines keep this in sync with insertCoinEnd() |
1579 const SkOpPtT* walk = start; | 2096 void SkOpSpanBase::debugInsertCoinEnd(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { |
1580 while ((walk = walk->next()) != start) { | 2097 if (containsCoinEnd(coin)) { |
1581 if (walk->segment() == segment) { | 2098 // SkASSERT(coin->containsCoinEnd(this)); |
1582 return true; | 2099 return; |
2100 } | |
2101 debugValidate(); | |
2102 // SkASSERT(this != coin); | |
2103 log->record(kMarkCoinEnd_Glitch, id, this, coin); | |
2104 // coin->fCoinEnd = this->fCoinEnd; | |
2105 // this->fCoinEnd = coinNext; | |
2106 debugValidate(); | |
2107 } | |
2108 | |
2109 // Commented-out lines keep this in sync with mergeContained() | |
2110 void SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog * log, const SkPathOpsBounds& bounds, bool* deleted) const { | |
2111 // while adjacent spans' points are contained by the bounds, merge them | |
2112 const SkOpSpanBase* prev = this; | |
2113 const SkOpSegment* seg = this->segment(); | |
2114 while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisj oint(prev, this)) { | |
2115 if (prev->prev()) { | |
2116 log->record(kMergeContained_Glitch, id, this, prev); | |
2117 } else if (this->final()) { | |
2118 log->record(kMergeContained_Glitch, id, this, prev); | |
2119 // return; | |
2120 } else { | |
2121 log->record(kMergeContained_Glitch, id, prev, this); | |
1583 } | 2122 } |
1584 } | 2123 } |
1585 return false; | 2124 const SkOpSpanBase* current = this; |
2125 const SkOpSpanBase* next = this; | |
2126 while (next->upCastable() && (next = next->upCast()->next()) | |
2127 && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) { | |
2128 if (!current->prev() && next->final()) { | |
2129 log->record(kMergeContained_Glitch, id, next, current); | |
2130 current = next; | |
2131 } | |
2132 if (current->prev()) { | |
2133 log->record(kMergeContained_Glitch, id, next, current); | |
2134 current = next; | |
2135 } else { | |
2136 log->record(kMergeContained_Glitch, id, next, current); | |
2137 current = next; | |
2138 } | |
2139 } | |
2140 #if DEBUG_COINCIDENCE | |
2141 // this->globalState()->coincidence()->debugValidate(); | |
2142 #endif | |
1586 } | 2143 } |
2144 #endif | |
1587 | 2145 |
1588 const SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { | 2146 const SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { |
1589 const SkOpSpanBase* end = *endPtr; | 2147 const SkOpSpanBase* end = *endPtr; |
1590 SkASSERT(this->segment() == end->segment()); | 2148 SkASSERT(this->segment() == end->segment()); |
1591 const SkOpSpanBase* result; | 2149 const SkOpSpanBase* result; |
1592 if (t() < end->t()) { | 2150 if (t() < end->t()) { |
1593 result = this; | 2151 result = this; |
1594 } else { | 2152 } else { |
1595 result = end; | 2153 result = end; |
1596 *endPtr = this; | 2154 *endPtr = this; |
1597 } | 2155 } |
1598 return result->upCast(); | 2156 return result->upCast(); |
1599 } | 2157 } |
1600 | 2158 |
1601 void SkOpSpanBase::debugValidate() const { | 2159 void SkOpSpanBase::debugValidate() const { |
2160 #if DEBUG_COINCIDENCE | |
2161 if (this->globalState()->debugCheckHealth()) { | |
2162 return; | |
2163 } | |
2164 #endif | |
1602 #if DEBUG_VALIDATE | 2165 #if DEBUG_VALIDATE |
1603 const SkOpPtT* ptT = &fPtT; | 2166 const SkOpPtT* ptT = &fPtT; |
1604 SkASSERT(ptT->span() == this); | 2167 SkASSERT(ptT->span() == this); |
1605 do { | 2168 do { |
1606 // SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); | 2169 // SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); |
1607 ptT->debugValidate(); | 2170 ptT->debugValidate(); |
1608 ptT = ptT->next(); | 2171 ptT = ptT->next(); |
1609 } while (ptT != &fPtT); | 2172 } while (ptT != &fPtT); |
1610 SkASSERT(this->debugCoinEndLoopCheck()); | 2173 SkASSERT(this->debugCoinEndLoopCheck()); |
1611 if (!this->final()) { | 2174 if (!this->final()) { |
(...skipping 24 matching lines...) Expand all Loading... | |
1636 SkDebugf("*** bad coincident loop ***\n"); | 2199 SkDebugf("*** bad coincident loop ***\n"); |
1637 return false; | 2200 return false; |
1638 } | 2201 } |
1639 } | 2202 } |
1640 } | 2203 } |
1641 ++loop; | 2204 ++loop; |
1642 } while ((next = nextCoin) && next != this); | 2205 } while ((next = nextCoin) && next != this); |
1643 return true; | 2206 return true; |
1644 } | 2207 } |
1645 | 2208 |
2209 #if DEBUG_COINCIDENCE_VERBOSE | |
2210 // Commented-out lines keep this in sync with insertCoincidence() in header | |
2211 void SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { | |
2212 if (containsCoincidence(coin)) { | |
2213 // SkASSERT(coin->containsCoincidence(this)); | |
2214 return; | |
2215 } | |
2216 debugValidate(); | |
2217 // SkASSERT(this != coin); | |
2218 log->record(kMarkCoinStart_Glitch, id, this, coin); | |
2219 // coin->fCoincident = this->fCoincident; | |
2220 // this->fCoincident = coinNext; | |
2221 debugValidate(); | |
2222 } | |
2223 | |
2224 // Commented-out lines keep this in sync with insertCoincidence() | |
2225 void SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped) const { | |
2226 if (this->containsCoincidence(segment)) { | |
2227 return; | |
2228 } | |
2229 const SkOpPtT* next = &fPtT; | |
2230 while ((next = next->next()) != &fPtT) { | |
2231 if (next->segment() == segment) { | |
2232 log->record(kMarkCoinInsert_Glitch, id, flipped ? next->span()->prev () : next->span()); | |
2233 return; | |
2234 } | |
2235 } | |
2236 #if DEBUG_COINCIDENCE | |
2237 log->record(kMarkCoinMissing_Glitch, id, segment, this); | |
2238 #endif | |
2239 } | |
2240 #endif | |
2241 | |
1646 // called only by test code | 2242 // called only by test code |
1647 int SkIntersections::debugCoincidentUsed() const { | 2243 int SkIntersections::debugCoincidentUsed() const { |
1648 if (!fIsCoincident[0]) { | 2244 if (!fIsCoincident[0]) { |
1649 SkASSERT(!fIsCoincident[1]); | 2245 SkASSERT(!fIsCoincident[1]); |
1650 return 0; | 2246 return 0; |
1651 } | 2247 } |
1652 int count = 0; | 2248 int count = 0; |
1653 SkDEBUGCODE(int count2 = 0;) | 2249 SkDEBUGCODE(int count2 = 0;) |
1654 for (int index = 0; index < fUsed; ++index) { | 2250 for (int index = 0; index < fUsed; ++index) { |
1655 if (fIsCoincident[0] & (1 << index)) { | 2251 if (fIsCoincident[0] & (1 << index)) { |
1656 ++count; | 2252 ++count; |
1657 } | 2253 } |
1658 #ifdef SK_DEBUG | 2254 #ifdef SK_DEBUG |
1659 if (fIsCoincident[1] & (1 << index)) { | 2255 if (fIsCoincident[1] & (1 << index)) { |
1660 ++count2; | 2256 ++count2; |
1661 } | 2257 } |
1662 #endif | 2258 #endif |
1663 } | 2259 } |
1664 SkASSERT(count == count2); | 2260 SkASSERT(count == count2); |
1665 return count; | 2261 return count; |
1666 } | 2262 } |
1667 | 2263 |
1668 #include "SkOpContour.h" | 2264 #include "SkOpContour.h" |
1669 | 2265 |
2266 // Commented-out lines keep this in sync with addOpp() | |
2267 bool SkOpPtT::debugAddOpp(const SkOpPtT* opp) const { | |
2268 // find the fOpp ptr to opp | |
2269 const SkOpPtT* oppPrev = opp->fNext; | |
2270 if (oppPrev == this) { | |
2271 return false; | |
2272 } | |
2273 while (oppPrev->fNext != opp) { | |
2274 oppPrev = oppPrev->fNext; | |
2275 if (oppPrev == this) { | |
2276 return false; | |
2277 } | |
2278 } | |
2279 // const SkOpPtT* oldNext = this->fNext; | |
2280 SkASSERT(this != opp); | |
2281 // this->fNext = opp; | |
2282 // SkASSERT(oppPrev != oldNext); | |
2283 // oppPrev->fNext = oldNext; | |
2284 return true; | |
2285 } | |
2286 | |
1670 bool SkOpPtT::debugContains(const SkOpPtT* check) const { | 2287 bool SkOpPtT::debugContains(const SkOpPtT* check) const { |
1671 SkASSERT(this != check); | 2288 SkASSERT(this != check); |
1672 const SkOpPtT* ptT = this; | 2289 const SkOpPtT* ptT = this; |
1673 int links = 0; | 2290 int links = 0; |
1674 do { | 2291 do { |
1675 ptT = ptT->next(); | 2292 ptT = ptT->next(); |
1676 if (ptT == check) { | 2293 if (ptT == check) { |
1677 return true; | 2294 return true; |
1678 } | 2295 } |
1679 ++links; | 2296 ++links; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1729 // -- and it's likely that a large loop count is indicative of a bug som ewhere | 2346 // -- and it's likely that a large loop count is indicative of a bug som ewhere |
1730 if (++loop > 1000) { | 2347 if (++loop > 1000) { |
1731 SkDebugf("*** loop count exceeds 1000 ***\n"); | 2348 SkDebugf("*** loop count exceeds 1000 ***\n"); |
1732 return 1000; | 2349 return 1000; |
1733 } | 2350 } |
1734 } while ((next = next->fNext) && next != this); | 2351 } while ((next = next->fNext) && next != this); |
1735 return 0; | 2352 return 0; |
1736 } | 2353 } |
1737 | 2354 |
1738 void SkOpPtT::debugValidate() const { | 2355 void SkOpPtT::debugValidate() const { |
2356 #if DEBUG_COINCIDENCE | |
2357 if (this->globalState()->debugCheckHealth()) { | |
2358 return; | |
2359 } | |
2360 #endif | |
1739 #if DEBUG_VALIDATE | 2361 #if DEBUG_VALIDATE |
1740 SkOpGlobalState::Phase phase = contour()->globalState()->phase(); | 2362 SkOpGlobalState::Phase phase = contour()->globalState()->phase(); |
1741 if (phase == SkOpGlobalState::kIntersecting | 2363 if (phase == SkOpGlobalState::kIntersecting |
1742 || phase == SkOpGlobalState::kFixWinding) { | 2364 || phase == SkOpGlobalState::kFixWinding) { |
1743 return; | 2365 return; |
1744 } | 2366 } |
1745 SkASSERT(fNext); | 2367 SkASSERT(fNext); |
1746 SkASSERT(fNext != this); | 2368 SkASSERT(fNext != this); |
1747 SkASSERT(fNext->fNext); | 2369 SkASSERT(fNext->fNext); |
1748 SkASSERT(debugLoopLimit(false) == 0); | 2370 SkASSERT(debugLoopLimit(false) == 0); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1845 #endif | 2467 #endif |
1846 SkPath::FillType fillType = path.getFillType(); | 2468 SkPath::FillType fillType = path.getFillType(); |
1847 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver seEvenOdd_FillType); | 2469 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver seEvenOdd_FillType); |
1848 if (includeDeclaration) { | 2470 if (includeDeclaration) { |
1849 SkDebugf(" SkPath %s;\n", name); | 2471 SkDebugf(" SkPath %s;\n", name); |
1850 } | 2472 } |
1851 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 2473 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); |
1852 iter.setPath(path); | 2474 iter.setPath(path); |
1853 showPathContours(iter, name); | 2475 showPathContours(iter, name); |
1854 } | 2476 } |
OLD | NEW |