[go: nahoru, domu]

blob: 56813b8b1f207171e05c2ad0a2e25ff3323e0f1b [file] [log] [blame]
caryclark@google.com21c29242013-04-08 11:47:37 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkPathOpsDebug.h"
caryclark@google.com2274f122013-05-07 18:51:31 +00009#include "SkPath.h"
caryclark@google.com21c29242013-04-08 11:47:37 +000010
11#if defined SK_DEBUG || !FORCE_RELEASE
12
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000013const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
commit-bot@chromium.orgf3d75312014-04-25 12:59:11 +000014
15#if defined(SK_DEBUG) || !FORCE_RELEASE
commit-bot@chromium.org60512372014-04-25 14:03:52 +000016int SkPathOpsDebug::gContourID = 0;
17int SkPathOpsDebug::gSegmentID = 0;
commit-bot@chromium.orgf3d75312014-04-25 12:59:11 +000018#endif
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000019
20#if DEBUG_SORT || DEBUG_SWAP_TOP
21int SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
22int SkPathOpsDebug::gSortCount;
23#endif
24
25#if DEBUG_ACTIVE_OP
26const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
27#endif
28
commit-bot@chromium.org017596e2014-04-14 17:08:59 +000029bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpan *>& chaseArray,
30 const SkOpSpan* span) {
31 for (int index = 0; index < chaseArray.count(); ++index) {
32 const SkOpSpan* entry = chaseArray[index];
33 if (entry == span) {
34 return true;
35 }
36 }
37 return false;
38}
39
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000040void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
caryclark@google.com21c29242013-04-08 11:47:37 +000041 size_t len = strlen(str);
42 bool num = false;
43 for (size_t idx = 0; idx < len; ++idx) {
44 if (num && str[idx] == 'e') {
45 if (len + 2 >= bufferLen) {
46 return;
47 }
48 memmove(&str[idx + 2], &str[idx + 1], len - idx);
49 str[idx] = '*';
50 str[idx + 1] = '^';
51 ++len;
52 }
53 num = str[idx] >= '0' && str[idx] <= '9';
54 }
55}
56
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000057bool SkPathOpsDebug::ValidWind(int wind) {
caryclark@google.com21c29242013-04-08 11:47:37 +000058 return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
59}
60
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000061void SkPathOpsDebug::WindingPrintf(int wind) {
caryclark@google.com21c29242013-04-08 11:47:37 +000062 if (wind == SK_MinS32) {
63 SkDebugf("?");
64 } else {
65 SkDebugf("%d", wind);
66 }
67}
caryclark@google.com2274f122013-05-07 18:51:31 +000068
caryclark@google.com46e30862013-07-08 17:17:02 +000069#if DEBUG_SHOW_TEST_NAME
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000070void* SkPathOpsDebug::CreateNameStr() {
caryclark@google.com46e30862013-07-08 17:17:02 +000071 return SkNEW_ARRAY(char, DEBUG_FILENAME_STRING_LENGTH);
72}
73
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000074void SkPathOpsDebug::DeleteNameStr(void* v) {
caryclark@google.com46e30862013-07-08 17:17:02 +000075 SkDELETE_ARRAY(reinterpret_cast<char* >(v));
76}
77
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000078void SkPathOpsDebug::BumpTestName(char* test) {
caryclark@google.com46e30862013-07-08 17:17:02 +000079 char* num = test + strlen(test);
80 while (num[-1] >= '0' && num[-1] <= '9') {
81 --num;
caryclark@google.com2274f122013-05-07 18:51:31 +000082 }
caryclark@google.com46e30862013-07-08 17:17:02 +000083 if (num[0] == '\0') {
84 return;
85 }
86 int dec = atoi(num);
87 if (dec == 0) {
88 return;
89 }
90 ++dec;
91 SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec);
caryclark@google.com2274f122013-05-07 18:51:31 +000092}
93#endif
caryclark@google.com6f2c7c32013-09-16 15:55:01 +000094
commit-bot@chromium.org017596e2014-04-14 17:08:59 +000095#if !DEBUG_SHOW_TEST_NAME // enable when building without extended test
caryclark@google.com9b5b31c2013-11-01 17:36:03 +000096void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) {
97}
98#endif
commit-bot@chromium.org017596e2014-04-14 17:08:59 +000099
100#endif // defined SK_DEBUG || !FORCE_RELEASE
101
102#include "SkOpAngle.h"
103#include "SkOpSegment.h"
104
105#if DEBUG_SORT
106void SkOpAngle::debugLoop() const {
107 const SkOpAngle* first = this;
108 const SkOpAngle* next = this;
109 do {
110 next->debugOne(true);
111 SkDebugf("\n");
112 next = next->fNext;
113 } while (next && next != first);
114}
115
116void SkOpAngle::debugOne(bool functionHeader) const {
117// fSegment->debugValidate();
118 const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd));
119 if (functionHeader) {
120 SkDebugf("%s ", __FUNCTION__);
121 }
122 SkDebugf("[%d", fSegment->debugID());
123#if DEBUG_ANGLE
124 SkDebugf("/%d", fID);
125#endif
126 SkDebugf("] next=");
127 if (fNext) {
128 SkDebugf("%d", fNext->fSegment->debugID());
129#if DEBUG_ANGLE
130 SkDebugf("/%d", fNext->fID);
131#endif
132 } else {
133 SkDebugf("?");
134 }
135 SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
136 SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fSegment->span(fStart).fT, fStart,
137 fSegment->span(fEnd).fT, fEnd);
138 SkDebugf(" sgn=%d windVal=%d", sign(), mSpan.fWindValue);
139
140#if DEBUG_WINDING
141 SkDebugf(" windSum=");
142 SkPathOpsDebug::WindingPrintf(mSpan.fWindSum);
143#endif
144 if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) {
145 SkDebugf(" oppVal=%d", mSpan.fOppValue);
146#if DEBUG_WINDING
147 SkDebugf(" oppSum=");
148 SkPathOpsDebug::WindingPrintf(mSpan.fOppSum);
149#endif
150 }
151 if (mSpan.fDone) {
152 SkDebugf(" done");
153 }
154 if (unorderable()) {
155 SkDebugf(" unorderable");
156 }
157 if (small()) {
158 SkDebugf(" small");
159 }
160 if (mSpan.fTiny) {
161 SkDebugf(" tiny");
162 }
163 if (fSegment->operand()) {
164 SkDebugf(" operand");
165 }
166 if (fStop) {
167 SkDebugf(" stop");
168 }
169}
170#endif
171
172#if DEBUG_ANGLE
173void SkOpAngle::debugSameAs(const SkOpAngle* compare) const {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000174 SK_ALWAYSBREAK(fSegment == compare->fSegment);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000175 const SkOpSpan& startSpan = fSegment->span(fStart);
176 const SkOpSpan& oStartSpan = fSegment->span(compare->fStart);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000177 SK_ALWAYSBREAK(startSpan.fToAngleIndex == oStartSpan.fToAngleIndex);
178 SK_ALWAYSBREAK(startSpan.fFromAngleIndex == oStartSpan.fFromAngleIndex);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000179 const SkOpSpan& endSpan = fSegment->span(fEnd);
180 const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000181 SK_ALWAYSBREAK(endSpan.fToAngleIndex == oEndSpan.fToAngleIndex);
182 SK_ALWAYSBREAK(endSpan.fFromAngleIndex == oEndSpan.fFromAngleIndex);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000183}
184#endif
185
186#if DEBUG_VALIDATE
187void SkOpAngle::debugValidateNext() const {
188 const SkOpAngle* first = this;
189 const SkOpAngle* next = first;
190 SkTDArray<const SkOpAngle*>(angles);
191 do {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000192 SK_ALWAYSBREAK(next->fSegment->debugContains(next));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000193 angles.push(next);
194 next = next->next();
195 if (next == first) {
196 break;
197 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000198 SK_ALWAYSBREAK(!angles.contains(next));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000199 if (!next) {
200 return;
201 }
202 } while (true);
203}
204
205void SkOpAngle::debugValidateLoop() const {
206 const SkOpAngle* first = this;
207 const SkOpAngle* next = first;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000208 SK_ALWAYSBREAK(first->next() != first);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000209 int signSum = 0;
210 int oppSum = 0;
211 bool firstOperand = fSegment->operand();
212 bool unorderable = false;
213 do {
214 unorderable |= next->fUnorderable;
215 const SkOpSegment* segment = next->fSegment;
216 bool operandsMatch = firstOperand == segment->operand();
217 signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(next);
218 oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(next);
219 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
220 if (segment->_xor()) {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000221// SK_ALWAYSBREAK(span.fWindValue == 1);
222// SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000223 }
224 if (segment->oppXor()) {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000225 SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1);
226// SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000227 }
228 next = next->next();
229 if (!next) {
230 return;
231 }
232 } while (next != first);
233 if (unorderable) {
234 return;
235 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000236 SK_ALWAYSBREAK(!signSum || fSegment->_xor());
237 SK_ALWAYSBREAK(!oppSum || fSegment->oppXor());
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000238 int lastWinding;
239 int lastOppWinding;
240 int winding;
241 int oppWinding;
242 do {
243 const SkOpSegment* segment = next->fSegment;
244 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
245 winding = span.fWindSum;
246 if (winding != SK_MinS32) {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000247// SK_ALWAYSBREAK(winding != 0);
248 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000249 lastWinding = winding;
250 int diffWinding = segment->spanSign(next);
251 if (!segment->_xor()) {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000252 SK_ALWAYSBREAK(diffWinding != 0);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000253 bool sameSign = (winding > 0) == (diffWinding > 0);
254 winding -= sameSign ? diffWinding : -diffWinding;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000255 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
256 SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000257 if (!sameSign) {
258 SkTSwap(winding, lastWinding);
259 }
260 }
261 lastOppWinding = oppWinding = span.fOppSum;
262 if (oppWinding != SK_MinS32 && !segment->oppXor()) {
263 int oppDiffWinding = segment->oppSign(next);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000264// SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor());
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000265 if (oppDiffWinding) {
266 bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0);
267 oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000268 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
269 SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000270 if (!oppSameSign) {
271 SkTSwap(oppWinding, lastOppWinding);
272 }
273 }
274 }
275 firstOperand = segment->operand();
276 break;
277 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000278 SK_ALWAYSBREAK(span.fOppSum == SK_MinS32);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000279 next = next->next();
280 } while (next != first);
281 if (winding == SK_MinS32) {
282 return;
283 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000284 SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000285 first = next;
286 next = next->next();
287 do {
288 const SkOpSegment* segment = next->fSegment;
289 lastWinding = winding;
290 lastOppWinding = oppWinding;
291 bool operandsMatch = firstOperand == segment->operand();
292 if (operandsMatch) {
293 if (!segment->_xor()) {
294 winding -= segment->spanSign(next);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000295 SK_ALWAYSBREAK(winding != lastWinding);
296 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000297 }
298 if (!segment->oppXor()) {
299 int oppDiffWinding = segment->oppSign(next);
300 if (oppWinding != SK_MinS32) {
301 oppWinding -= oppDiffWinding;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000302 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000303 } else {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000304 SK_ALWAYSBREAK(oppDiffWinding == 0);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000305 }
306 }
307 } else {
308 if (!segment->oppXor()) {
309 winding -= segment->oppSign(next);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000310 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000311 }
312 if (!segment->_xor()) {
313 oppWinding -= segment->spanSign(next);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000314 SK_ALWAYSBREAK(oppWinding != lastOppWinding);
315 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000316 }
317 }
318 bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
319 int sumWinding = useInner ? winding : lastWinding;
320 bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWinding);
321 int oppSumWinding = oppUseInner ? oppWinding : lastOppWinding;
322 if (!operandsMatch) {
323 SkTSwap(useInner, oppUseInner);
324 SkTSwap(sumWinding, oppSumWinding);
325 }
326 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
327 if (winding == -lastWinding) {
328 if (span.fWindSum != SK_MinS32) {
329 SkDebugf("%s useInner=%d spanSign=%d lastWinding=%d winding=%d windSum=%d\n",
330 __FUNCTION__,
331 useInner, segment->spanSign(next), lastWinding, winding, span.fWindSum);
332 }
333 }
334 if (oppWinding != SK_MinS32) {
335 if (span.fOppSum != SK_MinS32) {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000336 SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor());
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000337 }
338 } else {
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000339 SK_ALWAYSBREAK(!firstOperand);
340 SK_ALWAYSBREAK(!segment->operand());
341 SK_ALWAYSBREAK(!span.fOppValue);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000342 }
343 next = next->next();
344 } while (next != first);
345}
346#endif
347
348#if DEBUG_SWAP_TOP
349bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
350 if (fVerb != SkPath::kCubic_Verb) {
351 return false;
352 }
353 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
354 return dst.controlsContainedByEnds();
355}
356#endif
357
358#if DEBUG_CONCIDENT
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000359// SK_ALWAYSBREAK if pair has not already been added
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000360void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
361 for (int i = 0; i < fTs.count(); ++i) {
362 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
363 return;
364 }
365 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000366 SK_ALWAYSBREAK(0);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000367}
368#endif
369
370#if DEBUG_ANGLE
371void SkOpSegment::debugCheckPointsEqualish(int tStart, int tEnd) const {
372 const SkPoint& basePt = fTs[tStart].fPt;
373 while (++tStart < tEnd) {
374 const SkPoint& cmpPt = fTs[tStart].fPt;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000375 SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000376 }
377}
378#endif
379
380#if DEBUG_VALIDATE
381bool SkOpSegment::debugContains(const SkOpAngle* angle) const {
382 for (int index = 0; index < fAngles.count(); ++index) {
383 if (&fAngles[index] == angle) {
384 return true;
385 }
386 }
387 for (int index = 0; index < fSingletonAngles.count(); ++index) {
388 if (&fSingletonAngles[index] == angle) {
389 return true;
390 }
391 }
392 return false;
393}
394#endif
395
commit-bot@chromium.orgf3d75312014-04-25 12:59:11 +0000396#if DEBUG_SWAP_TOP
397int SkOpSegment::debugInflections(int tStart, int tEnd) const {
398 if (fVerb != SkPath::kCubic_Verb) {
399 return false;
400 }
401 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
402 double inflections[2];
403 return dst.findInflections(inflections);
404}
405#endif
406
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000407void SkOpSegment::debugReset() {
408 fTs.reset();
409 fAngles.reset();
410}
411
412#if DEBUG_CONCIDENT
413void SkOpSegment::debugShowTs(const char* prefix) const {
414 SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
415 int lastWind = -1;
416 int lastOpp = -1;
417 double lastT = -1;
418 int i;
419 for (i = 0; i < fTs.count(); ++i) {
420 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
421 || lastOpp != fTs[i].fOppValue;
422 if (change && lastWind >= 0) {
423 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
424 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
425 }
426 if (change) {
427 SkDebugf(" [o=%d", fTs[i].fOther->fID);
428 lastWind = fTs[i].fWindValue;
429 lastOpp = fTs[i].fOppValue;
430 lastT = fTs[i].fT;
431 } else {
432 SkDebugf(",%d", fTs[i].fOther->fID);
433 }
434 }
435 if (i <= 0) {
436 return;
437 }
438 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
439 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
440 if (fOperand) {
441 SkDebugf(" operand");
442 }
443 if (done()) {
444 SkDebugf(" done");
445 }
446 SkDebugf("\n");
447}
448#endif
449
450#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
451void SkOpSegment::debugShowActiveSpans() const {
452 debugValidate();
453 if (done()) {
454 return;
455 }
456#if DEBUG_ACTIVE_SPANS_SHORT_FORM
457 int lastId = -1;
458 double lastT = -1;
459#endif
460 for (int i = 0; i < fTs.count(); ++i) {
461 if (fTs[i].fDone) {
462 continue;
463 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000464 SK_ALWAYSBREAK(i < fTs.count() - 1);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000465#if DEBUG_ACTIVE_SPANS_SHORT_FORM
466 if (lastId == fID && lastT == fTs[i].fT) {
467 continue;
468 }
469 lastId = fID;
470 lastT = fTs[i].fT;
471#endif
472 SkDebugf("%s id=%d", __FUNCTION__, fID);
473 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
474 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
475 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
476 }
477 const SkOpSpan* span = &fTs[i];
478 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
479 int iEnd = i + 1;
480 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
481 ++iEnd;
482 }
483 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
484 const SkOpSegment* other = fTs[i].fOther;
485 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
486 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
487 if (fTs[i].fWindSum == SK_MinS32) {
488 SkDebugf("?");
489 } else {
490 SkDebugf("%d", fTs[i].fWindSum);
491 }
492 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
493 }
494}
495#endif
496
497#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
498void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
499 const SkPoint& pt = xyAtT(&span);
500 SkDebugf("%s id=%d", fun, fID);
501 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
502 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
503 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
504 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000505 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000506 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
507 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
508 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
509 (&span)[1].fT, winding);
510 if (span.fWindSum == SK_MinS32) {
511 SkDebugf("?");
512 } else {
513 SkDebugf("%d", span.fWindSum);
514 }
515 SkDebugf(" windValue=%d\n", span.fWindValue);
516}
517
518void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
519 int oppWinding) {
520 const SkPoint& pt = xyAtT(&span);
521 SkDebugf("%s id=%d", fun, fID);
522 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
523 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
524 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
525 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000526 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000527 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
528 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
529 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
530 (&span)[1].fT, winding, oppWinding);
531 if (span.fOppSum == SK_MinS32) {
532 SkDebugf("?");
533 } else {
534 SkDebugf("%d", span.fOppSum);
535 }
536 SkDebugf(" windSum=");
537 if (span.fWindSum == SK_MinS32) {
538 SkDebugf("?");
539 } else {
540 SkDebugf("%d", span.fWindSum);
541 }
542 SkDebugf(" windValue=%d\n", span.fWindValue);
543}
544#endif
545
546#if DEBUG_SHOW_WINDING
547int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
548 if (!(1 << fID & ofInterest)) {
549 return 0;
550 }
551 int sum = 0;
552 SkTArray<char, true> slots(slotCount * 2);
553 memset(slots.begin(), ' ', slotCount * 2);
554 for (int i = 0; i < fTs.count(); ++i) {
555 // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
556 // continue;
557 // }
558 sum += fTs[i].fWindValue;
559 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
560 sum += fTs[i].fOppValue;
561 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
562 }
563 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
564 slots.begin() + slotCount);
565 return sum;
566}
567#endif
568
569void SkOpSegment::debugValidate() const {
570#if DEBUG_VALIDATE
571 int count = fTs.count();
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000572 SK_ALWAYSBREAK(count >= 2);
573 SK_ALWAYSBREAK(fTs[0].fT == 0);
574 SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000575 int done = 0;
576 double t = -1;
577 const SkOpSpan* last = NULL;
578 bool tinyTFound = false;
579 bool hasLoop = false;
580 for (int i = 0; i < count; ++i) {
581 const SkOpSpan& span = fTs[i];
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000582 SK_ALWAYSBREAK(t <= span.fT);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000583 t = span.fT;
584 int otherIndex = span.fOtherIndex;
585 const SkOpSegment* other = span.fOther;
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000586 SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000587 const SkOpSpan& otherSpan = other->fTs[otherIndex];
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000588 SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
589 SK_ALWAYSBREAK(otherSpan.fOtherT == t);
590 SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000591 done += span.fDone;
592 if (last) {
593 bool tsEqual = last->fT == span.fT;
594 bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000595 SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000596 bool pointsEqual = last->fPt == span.fPt;
597 bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
598#if 0 // bufferOverflow test triggers this
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000599 SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000600#endif
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000601// SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
602 SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
603 SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
604 SK_ALWAYSBREAK(!last->fTiny || last->fDone);
605 SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
606 SK_ALWAYSBREAK(!last->fSmall || last->fDone);
607// SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
608// SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000609 if (last->fTiny) {
610 tinyTFound |= !tsPreciselyEqual;
611 } else {
612 tinyTFound = false;
613 }
614 }
615 last = &span;
616 hasLoop |= last->fLoop;
617 }
commit-bot@chromium.orgbd57dcd2014-04-30 18:24:16 +0000618 SK_ALWAYSBREAK(done == fDoneSpans);
commit-bot@chromium.org017596e2014-04-14 17:08:59 +0000619 if (fAngles.count() ) {
620 fAngles.begin()->debugValidateLoop();
621 }
622#endif
623}