Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: src/pathops/SkPathOpsDebug.cpp

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkPathOpsDebug.h ('k') | src/pathops/SkPathOpsLine.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkPathOpsDebug.h" 8 #include "SkPathOpsDebug.h"
9 #include "SkPath.h" 9 #include "SkPath.h"
10 #if DEBUG_ANGLE
11 #include "SkString.h"
12 #endif
13
14 #if DEBUG_VALIDATE
15 extern bool FLAGS_runFail;
16 #endif
10 17
11 #if defined SK_DEBUG || !FORCE_RELEASE 18 #if defined SK_DEBUG || !FORCE_RELEASE
12 19
13 const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 20 const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
14 21
15 #if defined(SK_DEBUG) || !FORCE_RELEASE 22 #if defined(SK_DEBUG) || !FORCE_RELEASE
16 int SkPathOpsDebug::gContourID = 0; 23 int SkPathOpsDebug::gContourID = 0;
17 int SkPathOpsDebug::gSegmentID = 0; 24 int SkPathOpsDebug::gSegmentID = 0;
18 #endif 25 #endif
19 26
20 #if DEBUG_SORT || DEBUG_SWAP_TOP 27 #if DEBUG_SORT || DEBUG_SWAP_TOP
21 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 28 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
22 int SkPathOpsDebug::gSortCount; 29 int SkPathOpsDebug::gSortCount;
23 #endif 30 #endif
24 31
25 #if DEBUG_ACTIVE_OP 32 #if DEBUG_ACTIVE_OP
26 const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 33 const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
27 #endif 34 #endif
28 35
29 bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpan *>& chaseArray, 36 bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray,
30 const SkOpSpan* span) { 37 const SkOpSpanBase* span) {
31 for (int index = 0; index < chaseArray.count(); ++index) { 38 for (int index = 0; index < chaseArray.count(); ++index) {
32 const SkOpSpan* entry = chaseArray[index]; 39 const SkOpSpanBase* entry = chaseArray[index];
33 if (entry == span) { 40 if (entry == span) {
34 return true; 41 return true;
35 } 42 }
36 } 43 }
37 return false; 44 return false;
38 } 45 }
39 46
40 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 47 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
41 size_t len = strlen(str); 48 size_t len = strlen(str);
42 bool num = false; 49 bool num = false;
(...skipping 15 matching lines...) Expand all
58 return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 65 return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
59 } 66 }
60 67
61 void SkPathOpsDebug::WindingPrintf(int wind) { 68 void SkPathOpsDebug::WindingPrintf(int wind) {
62 if (wind == SK_MinS32) { 69 if (wind == SK_MinS32) {
63 SkDebugf("?"); 70 SkDebugf("?");
64 } else { 71 } else {
65 SkDebugf("%d", wind); 72 SkDebugf("%d", wind);
66 } 73 }
67 } 74 }
75 #endif // defined SK_DEBUG || !FORCE_RELEASE
76
68 77
69 #if DEBUG_SHOW_TEST_NAME 78 #if DEBUG_SHOW_TEST_NAME
70 void* SkPathOpsDebug::CreateNameStr() { 79 void* SkPathOpsDebug::CreateNameStr() {
71 return SkNEW_ARRAY(char, DEBUG_FILENAME_STRING_LENGTH); 80 return SkNEW_ARRAY(char, DEBUG_FILENAME_STRING_LENGTH);
72 } 81 }
73 82
74 void SkPathOpsDebug::DeleteNameStr(void* v) { 83 void SkPathOpsDebug::DeleteNameStr(void* v) {
75 SkDELETE_ARRAY(reinterpret_cast<char* >(v)); 84 SkDELETE_ARRAY(reinterpret_cast<char* >(v));
76 } 85 }
77 86
(...skipping 12 matching lines...) Expand all
90 ++dec; 99 ++dec;
91 SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 100 SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec);
92 } 101 }
93 #endif 102 #endif
94 103
95 #if !DEBUG_SHOW_TEST_NAME // enable when building without extended test 104 #if !DEBUG_SHOW_TEST_NAME // enable when building without extended test
96 void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) { 105 void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) {
97 } 106 }
98 #endif 107 #endif
99 108
100 #endif // defined SK_DEBUG || !FORCE_RELEASE
101
102 #include "SkOpAngle.h" 109 #include "SkOpAngle.h"
103 #include "SkOpSegment.h" 110 #include "SkOpSegment.h"
104 111
112 #if DEBUG_SWAP_TOP
113 int SkOpSegment::debugInflections(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
114 if (fVerb != SkPath::kCubic_Verb) {
115 return false;
116 }
117 SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t());
118 double inflections[2];
119 return dst.findInflections(inflections);
120 }
121 #endif
122
123 SkOpAngle* SkOpSegment::debugLastAngle() {
124 SkOpAngle* result = NULL;
125 SkOpSpan* span = this->head();
126 do {
127 if (span->toAngle()) {
128 SkASSERT(!result);
129 result = span->toAngle();
130 }
131 } while ((span = span->next()->upCastable()));
132 SkASSERT(result);
133 return result;
134 }
135
136 void SkOpSegment::debugReset() {
137 this->init(this->fPts, this->contour(), this->verb());
138 }
139
140 #if DEBUG_ACTIVE_SPANS
141 void SkOpSegment::debugShowActiveSpans() const {
142 debugValidate();
143 if (done()) {
144 return;
145 }
146 int lastId = -1;
147 double lastT = -1;
148 const SkOpSpan* span = &fHead;
149 do {
150 if (span->done()) {
151 continue;
152 }
153 if (lastId == fID && lastT == span->t()) {
154 continue;
155 }
156 lastId = fID;
157 lastT = span->t();
158 SkDebugf("%s id=%d", __FUNCTION__, fID);
159 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
160 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
161 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
162 }
163 const SkOpPtT* ptT = span->ptT();
164 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", ptT->fT, ptT->fPt.fX, ptT->fPt.fY);
165 SkDebugf(" tEnd=%1.9g", span->next()->t());
166 SkDebugf(" windSum=");
167 if (span->windSum() == SK_MinS32) {
168 SkDebugf("?");
169 } else {
170 SkDebugf("%d", span->windSum());
171 }
172 SkDebugf(" windValue=%d oppValue=%d", span->windValue(), span->oppValue( ));
173 SkDebugf("\n");
174 } while ((span = span->next()->upCastable()));
175 }
176 #endif
177
178 #if DEBUG_MARK_DONE
179 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) {
180 const SkPoint& pt = span->ptT()->fPt;
181 SkDebugf("%s id=%d", fun, fID);
182 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
183 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
184 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
185 }
186 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
187 span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t());
188 if (winding == SK_MinS32) {
189 SkDebugf("?");
190 } else {
191 SkDebugf("%d", winding);
192 }
193 SkDebugf(" windSum=");
194 if (span->windSum() == SK_MinS32) {
195 SkDebugf("?");
196 } else {
197 SkDebugf("%d", span->windSum());
198 }
199 SkDebugf(" windValue=%d\n", span->windValue());
200 }
201
202 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding,
203 int oppWinding) {
204 const SkPoint& pt = span->ptT()->fPt;
205 SkDebugf("%s id=%d", fun, fID);
206 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
207 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
208 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
209 }
210 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
211 span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding , oppWinding);
212 if (winding == SK_MinS32) {
213 SkDebugf("?");
214 } else {
215 SkDebugf("%d", winding);
216 }
217 SkDebugf(" newOppSum=");
218 if (oppWinding == SK_MinS32) {
219 SkDebugf("?");
220 } else {
221 SkDebugf("%d", oppWinding);
222 }
223 SkDebugf(" oppSum=");
224 if (span->oppSum() == SK_MinS32) {
225 SkDebugf("?");
226 } else {
227 SkDebugf("%d", span->oppSum());
228 }
229 SkDebugf(" windSum=");
230 if (span->windSum() == SK_MinS32) {
231 SkDebugf("?");
232 } else {
233 SkDebugf("%d", span->windSum());
234 }
235 SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()) ;
236 }
237
238 #endif
239
240 #if DEBUG_ANGLE
241 SkString SkOpAngle::debugPart() const {
242 SkString result;
243 switch (this->segment()->verb()) {
244 case SkPath::kLine_Verb:
245 result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart),
246 this->segment()->debugID());
247 break;
248 case SkPath::kQuad_Verb:
249 result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart),
250 this->segment()->debugID());
251 break;
252 case SkPath::kCubic_Verb:
253 result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart) ,
254 this->segment()->debugID());
255 break;
256 default:
257 SkASSERT(0);
258 }
259 return result;
260 }
261 #endif
262
105 #if DEBUG_SORT 263 #if DEBUG_SORT
106 void SkOpAngle::debugLoop() const { 264 void SkOpAngle::debugLoop() const {
107 const SkOpAngle* first = this; 265 const SkOpAngle* first = this;
108 const SkOpAngle* next = this; 266 const SkOpAngle* next = this;
109 do { 267 do {
110 next->dumpOne(true); 268 next->dumpOne(true);
111 SkDebugf("\n"); 269 SkDebugf("\n");
112 next = next->fNext; 270 next = next->fNext;
113 } while (next && next != first); 271 } while (next && next != first);
114 } 272 next = first;
115 #endif 273 do {
116 274 next->debugValidate();
117 #if DEBUG_ANGLE 275 next = next->fNext;
118 void SkOpAngle::debugSameAs(const SkOpAngle* compare) const { 276 } while (next && next != first);
119 SK_ALWAYSBREAK(fSegment == compare->fSegment); 277 }
120 const SkOpSpan& startSpan = fSegment->span(fStart); 278 #endif
121 const SkOpSpan& oStartSpan = fSegment->span(compare->fStart); 279
122 SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle); 280 void SkOpAngle::debugValidate() const {
123 SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle);
124 const SkOpSpan& endSpan = fSegment->span(fEnd);
125 const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
126 SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle);
127 SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle);
128 }
129 #endif
130
131 #if DEBUG_VALIDATE 281 #if DEBUG_VALIDATE
282 const SkOpAngle* first = this;
283 const SkOpAngle* next = this;
284 int wind = 0;
285 int opp = 0;
286 int lastXor = -1;
287 int lastOppXor = -1;
288 do {
289 if (next->unorderable()) {
290 return;
291 }
292 const SkOpSpan* minSpan = next->start()->starter(next->end());
293 if (minSpan->windValue() == SK_MinS32) {
294 return;
295 }
296 bool op = next->segment()->operand();
297 bool isXor = next->segment()->isXor();
298 bool oppXor = next->segment()->oppXor();
299 SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG _LIMIT_WIND_SUM));
300 SkASSERT(!DEBUG_LIMIT_WIND_SUM
301 || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIM IT_WIND_SUM));
302 bool useXor = op ? oppXor : isXor;
303 SkASSERT(lastXor == -1 || lastXor == (int) useXor);
304 lastXor = (int) useXor;
305 wind += next->sign() * (op ? minSpan->oppValue() : minSpan->windValue()) ;
306 if (useXor) {
307 wind &= 1;
308 }
309 useXor = op ? isXor : oppXor;
310 SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor);
311 lastOppXor = (int) useXor;
312 opp += next->sign() * (op ? minSpan->windValue() : minSpan->oppValue());
313 if (useXor) {
314 opp &= 1;
315 }
316 next = next->fNext;
317 } while (next && next != first);
318 SkASSERT(wind == 0);
319 SkASSERT(opp == 0 || !FLAGS_runFail);
320 #endif
321 }
322
132 void SkOpAngle::debugValidateNext() const { 323 void SkOpAngle::debugValidateNext() const {
324 #if !FORCE_RELEASE
133 const SkOpAngle* first = this; 325 const SkOpAngle* first = this;
134 const SkOpAngle* next = first; 326 const SkOpAngle* next = first;
135 SkTDArray<const SkOpAngle*>(angles); 327 SkTDArray<const SkOpAngle*>(angles);
136 do { 328 do {
137 // SK_ALWAYSBREAK(next->fSegment->debugContains(next)); 329 // SK_ALWAYSBREAK(next->fSegment->debugContains(next));
138 angles.push(next); 330 angles.push(next);
139 next = next->next(); 331 next = next->next();
140 if (next == first) { 332 if (next == first) {
141 break; 333 break;
142 } 334 }
143 SK_ALWAYSBREAK(!angles.contains(next)); 335 SK_ALWAYSBREAK(!angles.contains(next));
144 if (!next) { 336 if (!next) {
145 return; 337 return;
146 } 338 }
147 } while (true); 339 } while (true);
148 } 340 #endif
149 341 }
150 void SkOpAngle::debugValidateLoop() const { 342
151 const SkOpAngle* first = this; 343 void SkOpSegment::debugValidate() const {
152 const SkOpAngle* next = first; 344 #if DEBUG_VALIDATE
153 SK_ALWAYSBREAK(first->next() != first); 345 const SkOpSpanBase* span = &fHead;
154 int signSum = 0; 346 double lastT = -1;
155 int oppSum = 0; 347 const SkOpSpanBase* prev = NULL;
156 bool firstOperand = fSegment->operand(); 348 int count = 0;
157 bool unorderable = false; 349 int done = 0;
158 do { 350 do {
159 unorderable |= next->fUnorderable; 351 if (!span->final()) {
160 const SkOpSegment* segment = next->fSegment; 352 ++count;
161 bool operandsMatch = firstOperand == segment->operand(); 353 done += span->upCast()->done() ? 1 : 0;
162 signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(ne xt); 354 }
163 oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(nex t); 355 SkASSERT(span->segment() == this);
164 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd)); 356 SkASSERT(!prev || prev->upCast()->next() == span);
165 if (segment->_xor()) { 357 SkASSERT(!prev || prev == span->prev());
166 // SK_ALWAYSBREAK(span.fWindValue == 1); 358 prev = span;
167 // SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1); 359 double t = span->ptT()->fT;
168 } 360 SkASSERT(lastT < t);
169 if (segment->oppXor()) { 361 lastT = t;
170 SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1); 362 span->debugValidate();
171 // SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || a bs(span.fOppSum) == 1); 363 } while (!span->final() && (span = span->upCast()->next()));
172 } 364 SkASSERT(count == fCount);
173 next = next->next(); 365 SkASSERT(done == fDoneCount);
174 if (!next) { 366 SkASSERT(span->final());
175 return; 367 span->debugValidate();
176 } 368 #endif
177 } while (next != first); 369 }
178 if (unorderable) { 370
179 return; 371 bool SkOpSpanBase::debugCoinEndLoopCheck() const {
180 } 372 int loop = 0;
181 SK_ALWAYSBREAK(!signSum || fSegment->_xor()); 373 const SkOpSpanBase* next = this;
182 SK_ALWAYSBREAK(!oppSum || fSegment->oppXor()); 374 SkOpSpanBase* nextCoin;
183 int lastWinding; 375 do {
184 int lastOppWinding; 376 nextCoin = next->fCoinEnd;
185 int winding; 377 SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin);
186 int oppWinding; 378 for (int check = 1; check < loop - 1; ++check) {
187 do { 379 const SkOpSpanBase* checkCoin = this->fCoinEnd;
188 const SkOpSegment* segment = next->fSegment; 380 const SkOpSpanBase* innerCoin = checkCoin;
189 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd)); 381 for (int inner = check + 1; inner < loop; ++inner) {
190 winding = span.fWindSum; 382 innerCoin = innerCoin->fCoinEnd;
191 if (winding != SK_MinS32) { 383 if (checkCoin == innerCoin) {
192 // SK_ALWAYSBREAK(winding != 0); 384 SkDebugf("*** bad coincident end loop ***\n");
193 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); 385 return false;
194 lastWinding = winding;
195 int diffWinding = segment->spanSign(next);
196 if (!segment->_xor()) {
197 SK_ALWAYSBREAK(diffWinding != 0);
198 bool sameSign = (winding > 0) == (diffWinding > 0);
199 winding -= sameSign ? diffWinding : -diffWinding;
200 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
201 SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
202 if (!sameSign) {
203 SkTSwap(winding, lastWinding);
204 } 386 }
205 } 387 }
206 lastOppWinding = oppWinding = span.fOppSum; 388 }
207 if (oppWinding != SK_MinS32 && !segment->oppXor()) { 389 ++loop;
208 int oppDiffWinding = segment->oppSign(next); 390 } while ((next = nextCoin) && next != this);
209 // SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segm ent->_xor()); 391 return true;
210 if (oppDiffWinding) { 392 }
211 bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0); 393
212 oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding ; 394 void SkOpSpanBase::debugValidate() const {
213 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding)); 395 #if DEBUG_VALIDATE
214 SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding)); 396 const SkOpPtT* ptT = &fPtT;
215 if (!oppSameSign) { 397 SkASSERT(ptT->span() == this);
216 SkTSwap(oppWinding, lastOppWinding); 398 do {
217 } 399 // SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt));
400 ptT->debugValidate();
401 ptT = ptT->next();
402 } while (ptT != &fPtT);
403 SkASSERT(this->debugCoinEndLoopCheck());
404 if (!this->final()) {
405 SkASSERT(this->upCast()->debugCoinLoopCheck());
406 }
407 if (fFromAngle) {
408 fFromAngle->debugValidate();
409 }
410 if (!this->final() && this->upCast()->toAngle()) {
411 this->upCast()->toAngle()->debugValidate();
412 }
413 #endif
414 }
415
416 bool SkOpSpan::debugCoinLoopCheck() const {
417 int loop = 0;
418 const SkOpSpan* next = this;
419 SkOpSpan* nextCoin;
420 do {
421 nextCoin = next->fCoincident;
422 SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin);
423 for (int check = 1; check < loop - 1; ++check) {
424 const SkOpSpan* checkCoin = this->fCoincident;
425 const SkOpSpan* innerCoin = checkCoin;
426 for (int inner = check + 1; inner < loop; ++inner) {
427 innerCoin = innerCoin->fCoincident;
428 if (checkCoin == innerCoin) {
429 SkDebugf("*** bad coincident loop ***\n");
430 return false;
218 } 431 }
219 } 432 }
220 firstOperand = segment->operand(); 433 }
221 break; 434 ++loop;
222 } 435 } while ((next = nextCoin) && next != this);
223 SK_ALWAYSBREAK(span.fOppSum == SK_MinS32); 436 return true;
224 next = next->next(); 437 }
225 } while (next != first); 438
226 if (winding == SK_MinS32) { 439 #include "SkOpContour.h"
227 return; 440
228 } 441 int SkOpPtT::debugLoopLimit(bool report) const {
229 SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWindi ng)); 442 int loop = 0;
230 first = next; 443 const SkOpPtT* next = this;
231 next = next->next(); 444 do {
232 do { 445 for (int check = 1; check < loop - 1; ++check) {
233 const SkOpSegment* segment = next->fSegment; 446 const SkOpPtT* checkPtT = this->fNext;
234 lastWinding = winding; 447 const SkOpPtT* innerPtT = checkPtT;
235 lastOppWinding = oppWinding; 448 for (int inner = check + 1; inner < loop; ++inner) {
236 bool operandsMatch = firstOperand == segment->operand(); 449 innerPtT = innerPtT->fNext;
237 if (operandsMatch) { 450 if (checkPtT == innerPtT) {
238 if (!segment->_xor()) { 451 if (report) {
239 winding -= segment->spanSign(next); 452 SkDebugf("*** bad ptT loop ***\n");
240 SK_ALWAYSBREAK(winding != lastWinding); 453 }
241 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); 454 return loop;
242 }
243 if (!segment->oppXor()) {
244 int oppDiffWinding = segment->oppSign(next);
245 if (oppWinding != SK_MinS32) {
246 oppWinding -= oppDiffWinding;
247 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
248 } else {
249 SK_ALWAYSBREAK(oppDiffWinding == 0);
250 } 455 }
251 } 456 }
252 } else { 457 }
253 if (!segment->oppXor()) { 458 ++loop;
254 winding -= segment->oppSign(next); 459 } while ((next = next->fNext) && next != this);
255 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); 460 return 0;
256 } 461 }
257 if (!segment->_xor()) { 462
258 oppWinding -= segment->spanSign(next); 463 void SkOpPtT::debugValidate() const {
259 SK_ALWAYSBREAK(oppWinding != lastOppWinding); 464 #if DEBUG_VALIDATE
260 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding)); 465 if (contour()->globalState()->phase() == SkOpGlobalState::kIntersecting) {
261 }
262 }
263 bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
264 int sumWinding = useInner ? winding : lastWinding;
265 bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWindi ng);
266 int oppSumWinding = oppUseInner ? oppWinding : lastOppWinding;
267 if (!operandsMatch) {
268 SkTSwap(useInner, oppUseInner);
269 SkTSwap(sumWinding, oppSumWinding);
270 }
271 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
272 if (winding == -lastWinding) {
273 if (span.fWindSum != SK_MinS32) {
274 SkDebugf("%s useInner=%d spanSign=%d lastWinding=%d winding=%d w indSum=%d\n",
275 __FUNCTION__,
276 useInner, segment->spanSign(next), lastWinding, winding, span.fWindSum);
277 }
278 }
279 if (oppWinding != SK_MinS32) {
280 if (span.fOppSum != SK_MinS32) {
281 SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor( ) || segment->_xor());
282 }
283 } else {
284 SK_ALWAYSBREAK(!firstOperand);
285 SK_ALWAYSBREAK(!segment->operand());
286 SK_ALWAYSBREAK(!span.fOppValue);
287 }
288 next = next->next();
289 } while (next != first);
290 }
291 #endif
292
293 #if DEBUG_SWAP_TOP
294 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
295 if (fVerb != SkPath::kCubic_Verb) {
296 return false;
297 }
298 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
299 return dst.controlsContainedByEnds();
300 }
301 #endif
302
303 #if DEBUG_CONCIDENT
304 // SK_ALWAYSBREAK if pair has not already been added
305 void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double other T) const {
306 for (int i = 0; i < fTs.count(); ++i) {
307 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == other T) {
308 return;
309 }
310 }
311 SK_ALWAYSBREAK(0);
312 }
313 #endif
314
315 #if DEBUG_ANGLE
316 void SkOpSegment::debugCheckPointsEqualish(int tStart, int tEnd) const {
317 const SkPoint& basePt = fTs[tStart].fPt;
318 while (++tStart < tEnd) {
319 const SkPoint& cmpPt = fTs[tStart].fPt;
320 SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
321 }
322 }
323 #endif
324
325 #if DEBUG_SWAP_TOP
326 int SkOpSegment::debugInflections(int tStart, int tEnd) const {
327 if (fVerb != SkPath::kCubic_Verb) {
328 return false;
329 }
330 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
331 double inflections[2];
332 return dst.findInflections(inflections);
333 }
334 #endif
335
336 const SkOpAngle* SkOpSegment::debugLastAngle() const {
337 const SkOpAngle* result = NULL;
338 for (int index = 0; index < count(); ++index) {
339 const SkOpSpan& span = this->span(index);
340 if (span.fToAngle) {
341 SkASSERT(!result);
342 result = span.fToAngle;
343 }
344 }
345 SkASSERT(result);
346 return result;
347 }
348
349 void SkOpSegment::debugReset() {
350 fTs.reset();
351 fAngles.reset();
352 }
353
354 #if DEBUG_CONCIDENT
355 void SkOpSegment::debugShowTs(const char* prefix) const {
356 SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
357 int lastWind = -1;
358 int lastOpp = -1;
359 double lastT = -1;
360 int i;
361 for (i = 0; i < fTs.count(); ++i) {
362 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
363 || lastOpp != fTs[i].fOppValue;
364 if (change && lastWind >= 0) {
365 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
366 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
367 }
368 if (change) {
369 SkDebugf(" [o=%d", fTs[i].fOther->fID);
370 lastWind = fTs[i].fWindValue;
371 lastOpp = fTs[i].fOppValue;
372 lastT = fTs[i].fT;
373 } else {
374 SkDebugf(",%d", fTs[i].fOther->fID);
375 }
376 }
377 if (i <= 0) {
378 return; 466 return;
379 } 467 }
380 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]", 468 SkASSERT(fNext);
381 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp); 469 SkASSERT(fNext != this);
382 if (fOperand) { 470 SkASSERT(fNext->fNext);
383 SkDebugf(" operand"); 471 SkASSERT(debugLoopLimit(false) == 0);
384 } 472 #endif
385 if (done()) { 473 }
386 SkDebugf(" done");
387 }
388 SkDebugf("\n");
389 }
390 #endif
391
392 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
393 void SkOpSegment::debugShowActiveSpans() const {
394 debugValidate();
395 if (done()) {
396 return;
397 }
398 #if DEBUG_ACTIVE_SPANS_SHORT_FORM
399 int lastId = -1;
400 double lastT = -1;
401 #endif
402 for (int i = 0; i < fTs.count(); ++i) {
403 if (fTs[i].fDone) {
404 continue;
405 }
406 SK_ALWAYSBREAK(i < fTs.count() - 1);
407 #if DEBUG_ACTIVE_SPANS_SHORT_FORM
408 if (lastId == fID && lastT == fTs[i].fT) {
409 continue;
410 }
411 lastId = fID;
412 lastT = fTs[i].fT;
413 #endif
414 SkDebugf("%s id=%d", __FUNCTION__, fID);
415 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
416 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
417 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
418 }
419 const SkOpSpan* span = &fTs[i];
420 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
421 int iEnd = i + 1;
422 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
423 ++iEnd;
424 }
425 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
426 const SkOpSegment* other = fTs[i].fOther;
427 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
428 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
429 if (fTs[i].fWindSum == SK_MinS32) {
430 SkDebugf("?");
431 } else {
432 SkDebugf("%d", fTs[i].fWindSum);
433 }
434 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppVa lue);
435 }
436 }
437 #endif
438
439 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
440 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
441 const SkPoint& pt = xyAtT(&span);
442 SkDebugf("%s id=%d", fun, fID);
443 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
444 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
445 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
446 }
447 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
448 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
449 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
450 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f Y,
451 (&span)[1].fT, winding);
452 if (span.fWindSum == SK_MinS32) {
453 SkDebugf("?");
454 } else {
455 SkDebugf("%d", span.fWindSum);
456 }
457 SkDebugf(" windValue=%d\n", span.fWindValue);
458 }
459
460 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
461 int oppWinding) {
462 const SkPoint& pt = xyAtT(&span);
463 SkDebugf("%s id=%d", fun, fID);
464 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
465 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
466 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
467 }
468 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
469 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
470 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
471 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f Y,
472 (&span)[1].fT, winding, oppWinding);
473 if (span.fOppSum == SK_MinS32) {
474 SkDebugf("?");
475 } else {
476 SkDebugf("%d", span.fOppSum);
477 }
478 SkDebugf(" windSum=");
479 if (span.fWindSum == SK_MinS32) {
480 SkDebugf("?");
481 } else {
482 SkDebugf("%d", span.fWindSum);
483 }
484 SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue);
485 }
486 #endif
487
488 #if DEBUG_SHOW_WINDING
489 int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
490 if (!(1 << fID & ofInterest)) {
491 return 0;
492 }
493 int sum = 0;
494 SkTArray<char, true> slots(slotCount * 2);
495 memset(slots.begin(), ' ', slotCount * 2);
496 for (int i = 0; i < fTs.count(); ++i) {
497 // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
498 // continue;
499 // }
500 sum += fTs[i].fWindValue;
501 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
502 sum += fTs[i].fOppValue;
503 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
504 }
505 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi n(), slotCount,
506 slots.begin() + slotCount);
507 return sum;
508 }
509 #endif
510
511 void SkOpSegment::debugValidate() const {
512 #if DEBUG_VALIDATE
513 int count = fTs.count();
514 SK_ALWAYSBREAK(count >= 2);
515 SK_ALWAYSBREAK(fTs[0].fT == 0);
516 SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
517 int done = 0;
518 double t = -1;
519 const SkOpSpan* last = NULL;
520 bool tinyTFound = false;
521 bool hasLoop = false;
522 for (int i = 0; i < count; ++i) {
523 const SkOpSpan& span = fTs[i];
524 SK_ALWAYSBREAK(t <= span.fT);
525 t = span.fT;
526 int otherIndex = span.fOtherIndex;
527 const SkOpSegment* other = span.fOther;
528 SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
529 const SkOpSpan& otherSpan = other->fTs[otherIndex];
530 SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
531 SK_ALWAYSBREAK(otherSpan.fOtherT == t);
532 SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]) ;
533 done += span.fDone;
534 if (last) {
535 SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
536 bool tsEqual = last->fT == span.fT;
537 bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
538 SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
539 bool pointsEqual = last->fPt == span.fPt;
540 bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
541 #if 0 // bufferOverflow test triggers this
542 SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
543 #endif
544 // SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
545 SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || ha sLoop);
546 SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
547 SK_ALWAYSBREAK(!last->fTiny || last->fDone);
548 SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
549 SK_ALWAYSBREAK(!last->fSmall || last->fDone);
550 // SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
551 // SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span. fDone);
552 if (last->fTiny) {
553 tinyTFound |= !tsPreciselyEqual;
554 } else {
555 tinyTFound = false;
556 }
557 }
558 last = &span;
559 hasLoop |= last->fLoop;
560 }
561 SK_ALWAYSBREAK(done == fDoneSpans);
562 // if (fAngles.count() ) {
563 // fAngles.begin()->debugValidateLoop();
564 // }
565 #endif
566 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsDebug.h ('k') | src/pathops/SkPathOpsLine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698