caryclark@google.com | 07393ca | 2013-04-08 11:47:37 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2013 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "SkPathOpsDebug.h" |
caryclark@google.com | a5e5592 | 2013-05-07 18:51:31 +0000 | [diff] [blame] | 9 | #include "SkPath.h" |
caryclark@google.com | 07393ca | 2013-04-08 11:47:37 +0000 | [diff] [blame] | 10 | |
| 11 | #if defined SK_DEBUG || !FORCE_RELEASE |
| 12 | |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 13 | const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; |
commit-bot@chromium.org | 8cb1daa | 2014-04-25 12:59:11 +0000 | [diff] [blame] | 14 | |
| 15 | #if defined(SK_DEBUG) || !FORCE_RELEASE |
commit-bot@chromium.org | fe41b8f | 2014-04-25 14:03:52 +0000 | [diff] [blame] | 16 | int SkPathOpsDebug::gContourID = 0; |
| 17 | int SkPathOpsDebug::gSegmentID = 0; |
commit-bot@chromium.org | 8cb1daa | 2014-04-25 12:59:11 +0000 | [diff] [blame] | 18 | #endif |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 19 | |
| 20 | #if DEBUG_SORT || DEBUG_SWAP_TOP |
| 21 | int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; |
| 22 | int SkPathOpsDebug::gSortCount; |
| 23 | #endif |
| 24 | |
| 25 | #if DEBUG_ACTIVE_OP |
| 26 | const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; |
| 27 | #endif |
| 28 | |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 29 | bool 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.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 40 | void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { |
caryclark@google.com | 07393ca | 2013-04-08 11:47:37 +0000 | [diff] [blame] | 41 | 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.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 57 | bool SkPathOpsDebug::ValidWind(int wind) { |
caryclark@google.com | 07393ca | 2013-04-08 11:47:37 +0000 | [diff] [blame] | 58 | return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; |
| 59 | } |
| 60 | |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 61 | void SkPathOpsDebug::WindingPrintf(int wind) { |
caryclark@google.com | 07393ca | 2013-04-08 11:47:37 +0000 | [diff] [blame] | 62 | if (wind == SK_MinS32) { |
| 63 | SkDebugf("?"); |
| 64 | } else { |
| 65 | SkDebugf("%d", wind); |
| 66 | } |
| 67 | } |
caryclark@google.com | a5e5592 | 2013-05-07 18:51:31 +0000 | [diff] [blame] | 68 | |
caryclark@google.com | 07e97fc | 2013-07-08 17:17:02 +0000 | [diff] [blame] | 69 | #if DEBUG_SHOW_TEST_NAME |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 70 | void* SkPathOpsDebug::CreateNameStr() { |
caryclark@google.com | 07e97fc | 2013-07-08 17:17:02 +0000 | [diff] [blame] | 71 | return SkNEW_ARRAY(char, DEBUG_FILENAME_STRING_LENGTH); |
| 72 | } |
| 73 | |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 74 | void SkPathOpsDebug::DeleteNameStr(void* v) { |
caryclark@google.com | 07e97fc | 2013-07-08 17:17:02 +0000 | [diff] [blame] | 75 | SkDELETE_ARRAY(reinterpret_cast<char* >(v)); |
| 76 | } |
| 77 | |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 78 | void SkPathOpsDebug::BumpTestName(char* test) { |
caryclark@google.com | 07e97fc | 2013-07-08 17:17:02 +0000 | [diff] [blame] | 79 | char* num = test + strlen(test); |
| 80 | while (num[-1] >= '0' && num[-1] <= '9') { |
| 81 | --num; |
caryclark@google.com | a5e5592 | 2013-05-07 18:51:31 +0000 | [diff] [blame] | 82 | } |
caryclark@google.com | 07e97fc | 2013-07-08 17:17:02 +0000 | [diff] [blame] | 83 | 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.com | a5e5592 | 2013-05-07 18:51:31 +0000 | [diff] [blame] | 92 | } |
| 93 | #endif |
caryclark@google.com | 570863f | 2013-09-16 15:55:01 +0000 | [diff] [blame] | 94 | |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 95 | #if !DEBUG_SHOW_TEST_NAME // enable when building without extended test |
caryclark@google.com | a2bbc6e | 2013-11-01 17:36:03 +0000 | [diff] [blame] | 96 | void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) { |
| 97 | } |
| 98 | #endif |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 99 | |
| 100 | #endif // defined SK_DEBUG || !FORCE_RELEASE |
| 101 | |
| 102 | #include "SkOpAngle.h" |
| 103 | #include "SkOpSegment.h" |
| 104 | |
| 105 | #if DEBUG_SORT |
| 106 | void SkOpAngle::debugLoop() const { |
caryclark | e4097e3 | 2014-06-18 07:24:19 -0700 | [diff] [blame] | 107 | const SkOpAngle* first = this; |
| 108 | const SkOpAngle* next = this; |
| 109 | do { |
| 110 | next->dumpOne(true); |
caryclark | 19eb3b2 | 2014-07-18 05:08:14 -0700 | [diff] [blame] | 111 | SkDebugf("\n"); |
caryclark | e4097e3 | 2014-06-18 07:24:19 -0700 | [diff] [blame] | 112 | next = next->fNext; |
| 113 | } while (next && next != first); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 114 | } |
| 115 | #endif |
| 116 | |
| 117 | #if DEBUG_ANGLE |
| 118 | void SkOpAngle::debugSameAs(const SkOpAngle* compare) const { |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 119 | SK_ALWAYSBREAK(fSegment == compare->fSegment); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 120 | const SkOpSpan& startSpan = fSegment->span(fStart); |
| 121 | const SkOpSpan& oStartSpan = fSegment->span(compare->fStart); |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 122 | SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle); |
| 123 | SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 124 | const SkOpSpan& endSpan = fSegment->span(fEnd); |
| 125 | const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd); |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 126 | SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle); |
| 127 | SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 128 | } |
| 129 | #endif |
| 130 | |
| 131 | #if DEBUG_VALIDATE |
| 132 | void SkOpAngle::debugValidateNext() const { |
| 133 | const SkOpAngle* first = this; |
| 134 | const SkOpAngle* next = first; |
| 135 | SkTDArray<const SkOpAngle*>(angles); |
| 136 | do { |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 137 | // SK_ALWAYSBREAK(next->fSegment->debugContains(next)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 138 | angles.push(next); |
| 139 | next = next->next(); |
| 140 | if (next == first) { |
| 141 | break; |
| 142 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 143 | SK_ALWAYSBREAK(!angles.contains(next)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 144 | if (!next) { |
| 145 | return; |
| 146 | } |
| 147 | } while (true); |
| 148 | } |
| 149 | |
| 150 | void SkOpAngle::debugValidateLoop() const { |
| 151 | const SkOpAngle* first = this; |
| 152 | const SkOpAngle* next = first; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 153 | SK_ALWAYSBREAK(first->next() != first); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 154 | 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 166 | // SK_ALWAYSBREAK(span.fWindValue == 1); |
| 167 | // SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 168 | } |
| 169 | if (segment->oppXor()) { |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 170 | 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.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 172 | } |
| 173 | next = next->next(); |
| 174 | if (!next) { |
| 175 | return; |
| 176 | } |
| 177 | } while (next != first); |
| 178 | if (unorderable) { |
| 179 | return; |
| 180 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 181 | SK_ALWAYSBREAK(!signSum || fSegment->_xor()); |
| 182 | SK_ALWAYSBREAK(!oppSum || fSegment->oppXor()); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 183 | 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 192 | // SK_ALWAYSBREAK(winding != 0); |
| 193 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 194 | lastWinding = winding; |
| 195 | int diffWinding = segment->spanSign(next); |
| 196 | if (!segment->_xor()) { |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 197 | SK_ALWAYSBREAK(diffWinding != 0); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 198 | bool sameSign = (winding > 0) == (diffWinding > 0); |
| 199 | winding -= sameSign ? diffWinding : -diffWinding; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 200 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); |
| 201 | SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 202 | 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 209 | // SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor()); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 210 | if (oppDiffWinding) { |
| 211 | bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0); |
| 212 | oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 213 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
| 214 | SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 215 | if (!oppSameSign) { |
| 216 | SkTSwap(oppWinding, lastOppWinding); |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | firstOperand = segment->operand(); |
| 221 | break; |
| 222 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 223 | SK_ALWAYSBREAK(span.fOppSum == SK_MinS32); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 224 | next = next->next(); |
| 225 | } while (next != first); |
| 226 | if (winding == SK_MinS32) { |
| 227 | return; |
| 228 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 229 | SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 230 | 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 240 | SK_ALWAYSBREAK(winding != lastWinding); |
| 241 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 242 | } |
| 243 | if (!segment->oppXor()) { |
| 244 | int oppDiffWinding = segment->oppSign(next); |
| 245 | if (oppWinding != SK_MinS32) { |
| 246 | oppWinding -= oppDiffWinding; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 247 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 248 | } else { |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 249 | SK_ALWAYSBREAK(oppDiffWinding == 0); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 250 | } |
| 251 | } |
| 252 | } else { |
| 253 | if (!segment->oppXor()) { |
| 254 | winding -= segment->oppSign(next); |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 255 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 256 | } |
| 257 | if (!segment->_xor()) { |
| 258 | oppWinding -= segment->spanSign(next); |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 259 | SK_ALWAYSBREAK(oppWinding != lastOppWinding); |
| 260 | SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 261 | } |
| 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 281 | SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor()); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 282 | } |
| 283 | } else { |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 284 | SK_ALWAYSBREAK(!firstOperand); |
| 285 | SK_ALWAYSBREAK(!segment->operand()); |
| 286 | SK_ALWAYSBREAK(!span.fOppValue); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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 |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 304 | // SK_ALWAYSBREAK if pair has not already been added |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 305 | void 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.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 311 | SK_ALWAYSBREAK(0); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 320 | SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt)); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 321 | } |
| 322 | } |
| 323 | #endif |
| 324 | |
commit-bot@chromium.org | 8cb1daa | 2014-04-25 12:59:11 +0000 | [diff] [blame] | 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 | |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 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 | |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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; |
| 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 |
| 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 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 406 | SK_ALWAYSBREAK(i < fTs.count() - 1); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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].fOppValue); |
| 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 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 447 | SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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.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 | |
| 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 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 468 | SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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.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 | } |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 484 | SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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.begin(), 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(); |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 514 | SK_ALWAYSBREAK(count >= 2); |
| 515 | SK_ALWAYSBREAK(fTs[0].fT == 0); |
| 516 | SK_ALWAYSBREAK(fTs[count - 1].fT == 1); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 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]; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 524 | SK_ALWAYSBREAK(t <= span.fT); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 525 | t = span.fT; |
| 526 | int otherIndex = span.fOtherIndex; |
| 527 | const SkOpSegment* other = span.fOther; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 528 | SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 529 | const SkOpSpan& otherSpan = other->fTs[otherIndex]; |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 530 | 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.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 533 | done += span.fDone; |
| 534 | if (last) { |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 535 | SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 536 | bool tsEqual = last->fT == span.fT; |
| 537 | bool tsPreciselyEqual = precisely_equal(last->fT, span.fT); |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 538 | SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 539 | bool pointsEqual = last->fPt == span.fPt; |
| 540 | bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt); |
| 541 | #if 0 // bufferOverflow test triggers this |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 542 | SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual); |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 543 | #endif |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 544 | // 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.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 552 | if (last->fTiny) { |
| 553 | tinyTFound |= !tsPreciselyEqual; |
| 554 | } else { |
| 555 | tinyTFound = false; |
| 556 | } |
| 557 | } |
| 558 | last = &span; |
| 559 | hasLoop |= last->fLoop; |
| 560 | } |
commit-bot@chromium.org | 45d1d1d | 2014-04-30 18:24:16 +0000 | [diff] [blame] | 561 | SK_ALWAYSBREAK(done == fDoneSpans); |
caryclark | dac1d17 | 2014-06-17 05:15:38 -0700 | [diff] [blame] | 562 | // if (fAngles.count() ) { |
| 563 | // fAngles.begin()->debugValidateLoop(); |
| 564 | // } |
commit-bot@chromium.org | 4431e77 | 2014-04-14 17:08:59 +0000 | [diff] [blame] | 565 | #endif |
| 566 | } |