blob: 7db93f5e969b5ba53689be47c5f9936f76601e20 [file] [log] [blame]
caryclark@google.com07393ca2013-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.coma5e55922013-05-07 18:51:31 +00009#include "SkPath.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000010
11#if defined SK_DEBUG || !FORCE_RELEASE
12
caryclark@google.com570863f2013-09-16 15:55:01 +000013const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +000014
15#if defined(SK_DEBUG) || !FORCE_RELEASE
commit-bot@chromium.orgfe41b8f2014-04-25 14:03:52 +000016int SkPathOpsDebug::gContourID = 0;
17int SkPathOpsDebug::gSegmentID = 0;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +000018#endif
caryclark@google.com570863f2013-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.org4431e772014-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.com570863f2013-09-16 15:55:01 +000040void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
caryclark@google.com07393ca2013-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.com570863f2013-09-16 15:55:01 +000057bool SkPathOpsDebug::ValidWind(int wind) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000058 return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
59}
60
caryclark@google.com570863f2013-09-16 15:55:01 +000061void SkPathOpsDebug::WindingPrintf(int wind) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000062 if (wind == SK_MinS32) {
63 SkDebugf("?");
64 } else {
65 SkDebugf("%d", wind);
66 }
67}
caryclark@google.coma5e55922013-05-07 18:51:31 +000068
caryclark@google.com07e97fc2013-07-08 17:17:02 +000069#if DEBUG_SHOW_TEST_NAME
caryclark@google.com570863f2013-09-16 15:55:01 +000070void* SkPathOpsDebug::CreateNameStr() {
caryclark@google.com07e97fc2013-07-08 17:17:02 +000071 return SkNEW_ARRAY(char, DEBUG_FILENAME_STRING_LENGTH);
72}
73
caryclark@google.com570863f2013-09-16 15:55:01 +000074void SkPathOpsDebug::DeleteNameStr(void* v) {
caryclark@google.com07e97fc2013-07-08 17:17:02 +000075 SkDELETE_ARRAY(reinterpret_cast<char* >(v));
76}
77
caryclark@google.com570863f2013-09-16 15:55:01 +000078void SkPathOpsDebug::BumpTestName(char* test) {
caryclark@google.com07e97fc2013-07-08 17:17:02 +000079 char* num = test + strlen(test);
80 while (num[-1] >= '0' && num[-1] <= '9') {
81 --num;
caryclark@google.coma5e55922013-05-07 18:51:31 +000082 }
caryclark@google.com07e97fc2013-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.coma5e55922013-05-07 18:51:31 +000092}
93#endif
caryclark@google.com570863f2013-09-16 15:55:01 +000094
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000095#if !DEBUG_SHOW_TEST_NAME // enable when building without extended test
caryclark@google.coma2bbc6e2013-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.org4431e772014-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 {
caryclarke4097e32014-06-18 07:24:19 -0700107 const SkOpAngle* first = this;
108 const SkOpAngle* next = this;
109 do {
110 next->dumpOne(true);
caryclark19eb3b22014-07-18 05:08:14 -0700111 SkDebugf("\n");
caryclarke4097e32014-06-18 07:24:19 -0700112 next = next->fNext;
113 } while (next && next != first);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000114}
115#endif
116
117#if DEBUG_ANGLE
118void SkOpAngle::debugSameAs(const SkOpAngle* compare) const {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000119 SK_ALWAYSBREAK(fSegment == compare->fSegment);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000120 const SkOpSpan& startSpan = fSegment->span(fStart);
121 const SkOpSpan& oStartSpan = fSegment->span(compare->fStart);
caryclarkdac1d172014-06-17 05:15:38 -0700122 SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle);
123 SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000124 const SkOpSpan& endSpan = fSegment->span(fEnd);
125 const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
caryclarkdac1d172014-06-17 05:15:38 -0700126 SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle);
127 SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000128}
129#endif
130
131#if DEBUG_VALIDATE
132void SkOpAngle::debugValidateNext() const {
133 const SkOpAngle* first = this;
134 const SkOpAngle* next = first;
135 SkTDArray<const SkOpAngle*>(angles);
136 do {
caryclarkdac1d172014-06-17 05:15:38 -0700137// SK_ALWAYSBREAK(next->fSegment->debugContains(next));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000138 angles.push(next);
139 next = next->next();
140 if (next == first) {
141 break;
142 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000143 SK_ALWAYSBREAK(!angles.contains(next));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000144 if (!next) {
145 return;
146 }
147 } while (true);
148}
149
150void SkOpAngle::debugValidateLoop() const {
151 const SkOpAngle* first = this;
152 const SkOpAngle* next = first;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000153 SK_ALWAYSBREAK(first->next() != first);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000154 int signSum = 0;
155 int oppSum = 0;
156 bool firstOperand = fSegment->operand();
157 bool unorderable = false;
158 do {
159 unorderable |= next->fUnorderable;
160 const SkOpSegment* segment = next->fSegment;
161 bool operandsMatch = firstOperand == segment->operand();
162 signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(next);
163 oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(next);
164 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
165 if (segment->_xor()) {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000166// SK_ALWAYSBREAK(span.fWindValue == 1);
167// SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000168 }
169 if (segment->oppXor()) {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000170 SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1);
171// SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000172 }
173 next = next->next();
174 if (!next) {
175 return;
176 }
177 } while (next != first);
178 if (unorderable) {
179 return;
180 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000181 SK_ALWAYSBREAK(!signSum || fSegment->_xor());
182 SK_ALWAYSBREAK(!oppSum || fSegment->oppXor());
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000183 int lastWinding;
184 int lastOppWinding;
185 int winding;
186 int oppWinding;
187 do {
188 const SkOpSegment* segment = next->fSegment;
189 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
190 winding = span.fWindSum;
191 if (winding != SK_MinS32) {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000192// SK_ALWAYSBREAK(winding != 0);
193 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000194 lastWinding = winding;
195 int diffWinding = segment->spanSign(next);
196 if (!segment->_xor()) {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000197 SK_ALWAYSBREAK(diffWinding != 0);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000198 bool sameSign = (winding > 0) == (diffWinding > 0);
199 winding -= sameSign ? diffWinding : -diffWinding;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000200 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
201 SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000202 if (!sameSign) {
203 SkTSwap(winding, lastWinding);
204 }
205 }
206 lastOppWinding = oppWinding = span.fOppSum;
207 if (oppWinding != SK_MinS32 && !segment->oppXor()) {
208 int oppDiffWinding = segment->oppSign(next);
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000209// SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor());
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000210 if (oppDiffWinding) {
211 bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0);
212 oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000213 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
214 SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000215 if (!oppSameSign) {
216 SkTSwap(oppWinding, lastOppWinding);
217 }
218 }
219 }
220 firstOperand = segment->operand();
221 break;
222 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000223 SK_ALWAYSBREAK(span.fOppSum == SK_MinS32);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000224 next = next->next();
225 } while (next != first);
226 if (winding == SK_MinS32) {
227 return;
228 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000229 SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000230 first = next;
231 next = next->next();
232 do {
233 const SkOpSegment* segment = next->fSegment;
234 lastWinding = winding;
235 lastOppWinding = oppWinding;
236 bool operandsMatch = firstOperand == segment->operand();
237 if (operandsMatch) {
238 if (!segment->_xor()) {
239 winding -= segment->spanSign(next);
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000240 SK_ALWAYSBREAK(winding != lastWinding);
241 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000242 }
243 if (!segment->oppXor()) {
244 int oppDiffWinding = segment->oppSign(next);
245 if (oppWinding != SK_MinS32) {
246 oppWinding -= oppDiffWinding;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000247 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000248 } else {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000249 SK_ALWAYSBREAK(oppDiffWinding == 0);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000250 }
251 }
252 } else {
253 if (!segment->oppXor()) {
254 winding -= segment->oppSign(next);
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000255 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000256 }
257 if (!segment->_xor()) {
258 oppWinding -= segment->spanSign(next);
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000259 SK_ALWAYSBREAK(oppWinding != lastOppWinding);
260 SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000261 }
262 }
263 bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
264 int sumWinding = useInner ? winding : lastWinding;
265 bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWinding);
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 windSum=%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) {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000281 SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor());
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000282 }
283 } else {
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000284 SK_ALWAYSBREAK(!firstOperand);
285 SK_ALWAYSBREAK(!segment->operand());
286 SK_ALWAYSBREAK(!span.fOppValue);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000287 }
288 next = next->next();
289 } while (next != first);
290}
291#endif
292
293#if DEBUG_SWAP_TOP
294bool 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
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000304// SK_ALWAYSBREAK if pair has not already been added
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000305void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
306 for (int i = 0; i < fTs.count(); ++i) {
307 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
308 return;
309 }
310 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000311 SK_ALWAYSBREAK(0);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000312}
313#endif
314
315#if DEBUG_ANGLE
316void 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;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000320 SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000321 }
322}
323#endif
324
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000325#if DEBUG_SWAP_TOP
326int 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
caryclarkdac1d172014-06-17 05:15:38 -0700336const 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
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000349void SkOpSegment::debugReset() {
350 fTs.reset();
351 fAngles.reset();
352}
353
354#if DEBUG_CONCIDENT
355void 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;
379 }
380 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
381 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
382 if (fOperand) {
383 SkDebugf(" operand");
384 }
385 if (done()) {
386 SkDebugf(" done");
387 }
388 SkDebugf("\n");
389}
390#endif
391
392#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
393void 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 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000406 SK_ALWAYSBREAK(i < fTs.count() - 1);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000407#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].fOppValue);
435 }
436}
437#endif
438
439#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
440void 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 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000447 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000448 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.fY,
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
460void 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 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000468 SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000469 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.fY,
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 }
caryclarkdac1d172014-06-17 05:15:38 -0700484 SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000485}
486#endif
487
488#if DEBUG_SHOW_WINDING
489int 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.begin(), slotCount,
506 slots.begin() + slotCount);
507 return sum;
508}
509#endif
510
511void SkOpSegment::debugValidate() const {
512#if DEBUG_VALIDATE
513 int count = fTs.count();
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000514 SK_ALWAYSBREAK(count >= 2);
515 SK_ALWAYSBREAK(fTs[0].fT == 0);
516 SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000517 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];
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000524 SK_ALWAYSBREAK(t <= span.fT);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000525 t = span.fT;
526 int otherIndex = span.fOtherIndex;
527 const SkOpSegment* other = span.fOther;
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000528 SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000529 const SkOpSpan& otherSpan = other->fTs[otherIndex];
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000530 SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
531 SK_ALWAYSBREAK(otherSpan.fOtherT == t);
532 SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000533 done += span.fDone;
534 if (last) {
caryclarkdac1d172014-06-17 05:15:38 -0700535 SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000536 bool tsEqual = last->fT == span.fT;
537 bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000538 SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000539 bool pointsEqual = last->fPt == span.fPt;
540 bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
541#if 0 // bufferOverflow test triggers this
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000542 SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000543#endif
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000544// SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
545 SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
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);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000552 if (last->fTiny) {
553 tinyTFound |= !tsPreciselyEqual;
554 } else {
555 tinyTFound = false;
556 }
557 }
558 last = &span;
559 hasLoop |= last->fLoop;
560 }
commit-bot@chromium.org45d1d1d2014-04-30 18:24:16 +0000561 SK_ALWAYSBREAK(done == fDoneSpans);
caryclarkdac1d172014-06-17 05:15:38 -0700562// if (fAngles.count() ) {
563// fAngles.begin()->debugValidateLoop();
564// }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000565#endif
566}