OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPathOpsDebug.h" | 8 #include "SkPathOpsDebug.h" |
9 #include "SkPath.h" | 9 #include "SkPath.h" |
10 | 10 |
11 #if defined SK_DEBUG || !FORCE_RELEASE | 11 #if defined SK_DEBUG || !FORCE_RELEASE |
12 | 12 |
13 int SkPathOpsDebug::gMaxWindSum = SK_MaxS32; | 13 int SkPathOpsDebug::gMaxWindSum = SK_MaxS32; |
14 int SkPathOpsDebug::gMaxWindValue = SK_MaxS32; | 14 int SkPathOpsDebug::gMaxWindValue = SK_MaxS32; |
15 | 15 |
16 const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; | 16 const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; |
17 int SkPathOpsDebug::gContourID; | 17 int SkPathOpsDebug::gContourID; |
18 int SkPathOpsDebug::gSegmentID; | 18 int SkPathOpsDebug::gSegmentID; |
19 | 19 |
20 #if DEBUG_SORT || DEBUG_SWAP_TOP | 20 #if DEBUG_SORT || DEBUG_SWAP_TOP |
21 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; | 21 int SkPathOpsDebug::gSortCountDefault = SK_MaxS32; |
22 int SkPathOpsDebug::gSortCount; | 22 int SkPathOpsDebug::gSortCount; |
23 #endif | 23 #endif |
24 | 24 |
25 #if DEBUG_ACTIVE_OP | 25 #if DEBUG_ACTIVE_OP |
26 const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; | 26 const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; |
27 #endif | 27 #endif |
28 | 28 |
| 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 |
29 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { | 40 void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { |
30 size_t len = strlen(str); | 41 size_t len = strlen(str); |
31 bool num = false; | 42 bool num = false; |
32 for (size_t idx = 0; idx < len; ++idx) { | 43 for (size_t idx = 0; idx < len; ++idx) { |
33 if (num && str[idx] == 'e') { | 44 if (num && str[idx] == 'e') { |
34 if (len + 2 >= bufferLen) { | 45 if (len + 2 >= bufferLen) { |
35 return; | 46 return; |
36 } | 47 } |
37 memmove(&str[idx + 2], &str[idx + 1], len - idx); | 48 memmove(&str[idx + 2], &str[idx + 1], len - idx); |
38 str[idx] = '*'; | 49 str[idx] = '*'; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 } | 85 } |
75 int dec = atoi(num); | 86 int dec = atoi(num); |
76 if (dec == 0) { | 87 if (dec == 0) { |
77 return; | 88 return; |
78 } | 89 } |
79 ++dec; | 90 ++dec; |
80 SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); | 91 SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); |
81 } | 92 } |
82 #endif | 93 #endif |
83 | 94 |
| 95 #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) { |
| 97 } |
| 98 #endif |
| 99 |
| 100 #endif // defined SK_DEBUG || !FORCE_RELEASE |
| 101 |
| 102 #include "SkOpAngle.h" |
84 #include "SkOpSegment.h" | 103 #include "SkOpSegment.h" |
85 | 104 |
86 void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) { | 105 #if DEBUG_SORT |
87 int count = angles.count(); | 106 void SkOpAngle::debugLoop() const { |
88 for (int index = 0; index < count; ++index) { | 107 const SkOpAngle* first = this; |
89 angles[index].dump(); | 108 const SkOpAngle* next = this; |
90 } | 109 do { |
91 } | 110 next->debugOne(true); |
92 | 111 SkDebugf("\n"); |
93 void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) { | 112 next = next->fNext; |
94 int count = angles.count(); | 113 } while (next && next != first); |
95 for (int index = 0; index < count; ++index) { | 114 } |
96 angles[index]->dump(); | 115 |
97 } | 116 void SkOpAngle::debugOne(bool functionHeader) const { |
98 } | 117 // fSegment->debugValidate(); |
99 #endif // SK_DEBUG || !FORCE_RELEASE | 118 const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd)); |
100 | 119 if (functionHeader) { |
101 #ifdef SK_DEBUG | 120 SkDebugf("%s ", __FUNCTION__); |
102 void SkOpSpan::dump() const { | 121 } |
103 SkDebugf("t="); | 122 SkDebugf("[%d", fSegment->debugID()); |
104 DebugDumpDouble(fT); | 123 #if DEBUG_ANGLE |
105 SkDebugf(" pt="); | 124 SkDebugf("/%d", fID); |
106 SkDPoint::dump(fPt); | 125 #endif |
107 SkDebugf(" other.fID=%d", fOther->debugID()); | 126 SkDebugf("] next="); |
108 SkDebugf(" [%d] otherT=", fOtherIndex); | 127 if (fNext) { |
109 DebugDumpDouble(fOtherT); | 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 |
110 SkDebugf(" windSum="); | 141 SkDebugf(" windSum="); |
111 SkPathOpsDebug::WindingPrintf(fWindSum); | 142 SkPathOpsDebug::WindingPrintf(mSpan.fWindSum); |
112 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { | 143 #endif |
| 144 if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) { |
| 145 SkDebugf(" oppVal=%d", mSpan.fOppValue); |
| 146 #if DEBUG_WINDING |
113 SkDebugf(" oppSum="); | 147 SkDebugf(" oppSum="); |
114 SkPathOpsDebug::WindingPrintf(fOppSum); | 148 SkPathOpsDebug::WindingPrintf(mSpan.fOppSum); |
115 } | 149 #endif |
116 SkDebugf(" windValue=%d", fWindValue); | 150 } |
117 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) { | 151 if (mSpan.fDone) { |
118 SkDebugf(" oppValue=%d", fOppValue); | |
119 } | |
120 if (fDone) { | |
121 SkDebugf(" done"); | 152 SkDebugf(" done"); |
122 } | 153 } |
123 if (fUnsortableStart) { | 154 if (unorderable()) { |
124 SkDebugf(" unsortable-start"); | 155 SkDebugf(" unorderable"); |
125 } | 156 } |
126 if (fUnsortableEnd) { | 157 if (small()) { |
127 SkDebugf(" unsortable-end"); | 158 SkDebugf(" small"); |
128 } | 159 } |
129 if (fTiny) { | 160 if (mSpan.fTiny) { |
130 SkDebugf(" tiny"); | 161 SkDebugf(" tiny"); |
131 } else if (fSmall) { | 162 } |
132 SkDebugf(" small"); | 163 if (fSegment->operand()) { |
133 } | 164 SkDebugf(" operand"); |
134 if (fLoop) { | 165 } |
135 SkDebugf(" loop"); | 166 if (fStop) { |
| 167 SkDebugf(" stop"); |
| 168 } |
| 169 } |
| 170 #endif |
| 171 |
| 172 #if DEBUG_ANGLE |
| 173 void SkOpAngle::debugSameAs(const SkOpAngle* compare) const { |
| 174 SK_DEBUGBREAK(fSegment == compare->fSegment); |
| 175 const SkOpSpan& startSpan = fSegment->span(fStart); |
| 176 const SkOpSpan& oStartSpan = fSegment->span(compare->fStart); |
| 177 SK_DEBUGBREAK(startSpan.fToAngleIndex == oStartSpan.fToAngleIndex); |
| 178 SK_DEBUGBREAK(startSpan.fFromAngleIndex == oStartSpan.fFromAngleIndex); |
| 179 const SkOpSpan& endSpan = fSegment->span(fEnd); |
| 180 const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd); |
| 181 SK_DEBUGBREAK(endSpan.fToAngleIndex == oEndSpan.fToAngleIndex); |
| 182 SK_DEBUGBREAK(endSpan.fFromAngleIndex == oEndSpan.fFromAngleIndex); |
| 183 } |
| 184 #endif |
| 185 |
| 186 #if DEBUG_VALIDATE |
| 187 void SkOpAngle::debugValidateNext() const { |
| 188 const SkOpAngle* first = this; |
| 189 const SkOpAngle* next = first; |
| 190 SkTDArray<const SkOpAngle*>(angles); |
| 191 do { |
| 192 SK_DEBUGBREAK(next->fSegment->debugContains(next)); |
| 193 angles.push(next); |
| 194 next = next->next(); |
| 195 if (next == first) { |
| 196 break; |
| 197 } |
| 198 SK_DEBUGBREAK(!angles.contains(next)); |
| 199 if (!next) { |
| 200 return; |
| 201 } |
| 202 } while (true); |
| 203 } |
| 204 |
| 205 void SkOpAngle::debugValidateLoop() const { |
| 206 const SkOpAngle* first = this; |
| 207 const SkOpAngle* next = first; |
| 208 SK_DEBUGBREAK(first->next() != first); |
| 209 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(ne
xt); |
| 218 oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(nex
t); |
| 219 const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd)); |
| 220 if (segment->_xor()) { |
| 221 // SK_DEBUGBREAK(span.fWindValue == 1); |
| 222 // SK_DEBUGBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1); |
| 223 } |
| 224 if (segment->oppXor()) { |
| 225 SK_DEBUGBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1); |
| 226 // SK_DEBUGBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || ab
s(span.fOppSum) == 1); |
| 227 } |
| 228 next = next->next(); |
| 229 if (!next) { |
| 230 return; |
| 231 } |
| 232 } while (next != first); |
| 233 if (unorderable) { |
| 234 return; |
| 235 } |
| 236 SK_DEBUGBREAK(!signSum || fSegment->_xor()); |
| 237 SK_DEBUGBREAK(!oppSum || fSegment->oppXor()); |
| 238 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) { |
| 247 // SK_DEBUGBREAK(winding != 0); |
| 248 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
| 249 lastWinding = winding; |
| 250 int diffWinding = segment->spanSign(next); |
| 251 if (!segment->_xor()) { |
| 252 SK_DEBUGBREAK(diffWinding != 0); |
| 253 bool sameSign = (winding > 0) == (diffWinding > 0); |
| 254 winding -= sameSign ? diffWinding : -diffWinding; |
| 255 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
| 256 SK_DEBUGBREAK(abs(winding) <= abs(lastWinding)); |
| 257 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); |
| 264 // SK_DEBUGBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segme
nt->_xor()); |
| 265 if (oppDiffWinding) { |
| 266 bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0); |
| 267 oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding
; |
| 268 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
| 269 SK_DEBUGBREAK(abs(oppWinding) <= abs(lastOppWinding)); |
| 270 if (!oppSameSign) { |
| 271 SkTSwap(oppWinding, lastOppWinding); |
| 272 } |
| 273 } |
| 274 } |
| 275 firstOperand = segment->operand(); |
| 276 break; |
| 277 } |
| 278 SK_DEBUGBREAK(span.fOppSum == SK_MinS32); |
| 279 next = next->next(); |
| 280 } while (next != first); |
| 281 if (winding == SK_MinS32) { |
| 282 return; |
| 283 } |
| 284 SK_DEBUGBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWindin
g)); |
| 285 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); |
| 295 SK_DEBUGBREAK(winding != lastWinding); |
| 296 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
| 297 } |
| 298 if (!segment->oppXor()) { |
| 299 int oppDiffWinding = segment->oppSign(next); |
| 300 if (oppWinding != SK_MinS32) { |
| 301 oppWinding -= oppDiffWinding; |
| 302 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
| 303 } else { |
| 304 SK_DEBUGBREAK(oppDiffWinding == 0); |
| 305 } |
| 306 } |
| 307 } else { |
| 308 if (!segment->oppXor()) { |
| 309 winding -= segment->oppSign(next); |
| 310 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(winding)); |
| 311 } |
| 312 if (!segment->_xor()) { |
| 313 oppWinding -= segment->spanSign(next); |
| 314 SK_DEBUGBREAK(oppWinding != lastOppWinding); |
| 315 SK_DEBUGBREAK(SkPathOpsDebug::ValidWind(oppWinding)); |
| 316 } |
| 317 } |
| 318 bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding); |
| 319 int sumWinding = useInner ? winding : lastWinding; |
| 320 bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWindi
ng); |
| 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 w
indSum=%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) { |
| 336 SK_DEBUGBREAK(span.fOppSum == oppSumWinding || segment->oppXor()
|| segment->_xor()); |
| 337 } |
| 338 } else { |
| 339 SK_DEBUGBREAK(!firstOperand); |
| 340 SK_DEBUGBREAK(!segment->operand()); |
| 341 SK_DEBUGBREAK(!span.fOppValue); |
| 342 } |
| 343 next = next->next(); |
| 344 } while (next != first); |
| 345 } |
| 346 #endif |
| 347 |
| 348 #if DEBUG_SWAP_TOP |
| 349 bool 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 |
| 359 // SK_DEBUGBREAK if pair has not already been added |
| 360 void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double other
T) const { |
| 361 for (int i = 0; i < fTs.count(); ++i) { |
| 362 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == other
T) { |
| 363 return; |
| 364 } |
| 365 } |
| 366 SK_DEBUGBREAK(0); |
| 367 } |
| 368 #endif |
| 369 |
| 370 #if DEBUG_ANGLE |
| 371 void 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; |
| 375 SK_DEBUGBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt)); |
| 376 } |
| 377 } |
| 378 #endif |
| 379 |
| 380 #if DEBUG_VALIDATE |
| 381 bool 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 |
| 396 void SkOpSegment::debugReset() { |
| 397 fTs.reset(); |
| 398 fAngles.reset(); |
| 399 } |
| 400 |
| 401 #if DEBUG_CONCIDENT |
| 402 void SkOpSegment::debugShowTs(const char* prefix) const { |
| 403 SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID); |
| 404 int lastWind = -1; |
| 405 int lastOpp = -1; |
| 406 double lastT = -1; |
| 407 int i; |
| 408 for (i = 0; i < fTs.count(); ++i) { |
| 409 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue |
| 410 || lastOpp != fTs[i].fOppValue; |
| 411 if (change && lastWind >= 0) { |
| 412 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]", |
| 413 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp); |
| 414 } |
| 415 if (change) { |
| 416 SkDebugf(" [o=%d", fTs[i].fOther->fID); |
| 417 lastWind = fTs[i].fWindValue; |
| 418 lastOpp = fTs[i].fOppValue; |
| 419 lastT = fTs[i].fT; |
| 420 } else { |
| 421 SkDebugf(",%d", fTs[i].fOther->fID); |
| 422 } |
| 423 } |
| 424 if (i <= 0) { |
| 425 return; |
| 426 } |
| 427 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]", |
| 428 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp); |
| 429 if (fOperand) { |
| 430 SkDebugf(" operand"); |
| 431 } |
| 432 if (done()) { |
| 433 SkDebugf(" done"); |
136 } | 434 } |
137 SkDebugf("\n"); | 435 SkDebugf("\n"); |
138 } | 436 } |
139 | 437 #endif |
140 void Dump(const SkTArray<class SkOpAngle, true>& angles) { | 438 |
141 SkPathOpsDebug::DumpAngles(angles); | 439 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
142 } | 440 void SkOpSegment::debugShowActiveSpans() const { |
143 | 441 debugValidate(); |
144 void Dump(const SkTArray<class SkOpAngle* , true>& angles) { | 442 if (done()) { |
145 SkPathOpsDebug::DumpAngles(angles); | 443 return; |
146 } | 444 } |
147 | 445 #if DEBUG_ACTIVE_SPANS_SHORT_FORM |
148 void Dump(const SkTArray<class SkOpAngle, true>* angles) { | 446 int lastId = -1; |
149 SkPathOpsDebug::DumpAngles(*angles); | 447 double lastT = -1; |
150 } | 448 #endif |
151 | 449 for (int i = 0; i < fTs.count(); ++i) { |
152 void Dump(const SkTArray<class SkOpAngle* , true>* angles) { | 450 if (fTs[i].fDone) { |
153 SkPathOpsDebug::DumpAngles(*angles); | 451 continue; |
154 } | 452 } |
155 | 453 SK_DEBUGBREAK(i < fTs.count() - 1); |
156 #endif | 454 #if DEBUG_ACTIVE_SPANS_SHORT_FORM |
157 | 455 if (lastId == fID && lastT == fTs[i].fT) { |
158 #if !FORCE_RELEASE && 0 // enable when building without extended test | 456 continue; |
159 void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op,
const char* name) { | 457 } |
160 } | 458 lastId = fID; |
161 #endif | 459 lastT = fTs[i].fT; |
| 460 #endif |
| 461 SkDebugf("%s id=%d", __FUNCTION__, fID); |
| 462 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 463 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 464 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 465 } |
| 466 const SkOpSpan* span = &fTs[i]; |
| 467 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span)); |
| 468 int iEnd = i + 1; |
| 469 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT))
{ |
| 470 ++iEnd; |
| 471 } |
| 472 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT); |
| 473 const SkOpSegment* other = fTs[i].fOther; |
| 474 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=", |
| 475 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex); |
| 476 if (fTs[i].fWindSum == SK_MinS32) { |
| 477 SkDebugf("?"); |
| 478 } else { |
| 479 SkDebugf("%d", fTs[i].fWindSum); |
| 480 } |
| 481 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppVa
lue); |
| 482 } |
| 483 } |
| 484 #endif |
| 485 |
| 486 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE |
| 487 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding) { |
| 488 const SkPoint& pt = xyAtT(&span); |
| 489 SkDebugf("%s id=%d", fun, fID); |
| 490 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 491 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 492 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 493 } |
| 494 SK_DEBUGBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
| 495 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); |
| 496 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=", |
| 497 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, |
| 498 (&span)[1].fT, winding); |
| 499 if (span.fWindSum == SK_MinS32) { |
| 500 SkDebugf("?"); |
| 501 } else { |
| 502 SkDebugf("%d", span.fWindSum); |
| 503 } |
| 504 SkDebugf(" windValue=%d\n", span.fWindValue); |
| 505 } |
| 506 |
| 507 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding, |
| 508 int oppWinding) { |
| 509 const SkPoint& pt = xyAtT(&span); |
| 510 SkDebugf("%s id=%d", fun, fID); |
| 511 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 512 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 513 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 514 } |
| 515 SK_DEBUGBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
| 516 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); |
| 517 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d
oppSum=", |
| 518 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, |
| 519 (&span)[1].fT, winding, oppWinding); |
| 520 if (span.fOppSum == SK_MinS32) { |
| 521 SkDebugf("?"); |
| 522 } else { |
| 523 SkDebugf("%d", span.fOppSum); |
| 524 } |
| 525 SkDebugf(" windSum="); |
| 526 if (span.fWindSum == SK_MinS32) { |
| 527 SkDebugf("?"); |
| 528 } else { |
| 529 SkDebugf("%d", span.fWindSum); |
| 530 } |
| 531 SkDebugf(" windValue=%d\n", span.fWindValue); |
| 532 } |
| 533 #endif |
| 534 |
| 535 #if DEBUG_SHOW_WINDING |
| 536 int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const { |
| 537 if (!(1 << fID & ofInterest)) { |
| 538 return 0; |
| 539 } |
| 540 int sum = 0; |
| 541 SkTArray<char, true> slots(slotCount * 2); |
| 542 memset(slots.begin(), ' ', slotCount * 2); |
| 543 for (int i = 0; i < fTs.count(); ++i) { |
| 544 // if (!(1 << fTs[i].fOther->fID & ofInterest)) { |
| 545 // continue; |
| 546 // } |
| 547 sum += fTs[i].fWindValue; |
| 548 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); |
| 549 sum += fTs[i].fOppValue; |
| 550 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); |
| 551 } |
| 552 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, |
| 553 slots.begin() + slotCount); |
| 554 return sum; |
| 555 } |
| 556 #endif |
| 557 |
| 558 void SkOpSegment::debugValidate() const { |
| 559 #if DEBUG_VALIDATE |
| 560 int count = fTs.count(); |
| 561 SK_DEBUGBREAK(count >= 2); |
| 562 SK_DEBUGBREAK(fTs[0].fT == 0); |
| 563 SK_DEBUGBREAK(fTs[count - 1].fT == 1); |
| 564 int done = 0; |
| 565 double t = -1; |
| 566 const SkOpSpan* last = NULL; |
| 567 bool tinyTFound = false; |
| 568 bool hasLoop = false; |
| 569 for (int i = 0; i < count; ++i) { |
| 570 const SkOpSpan& span = fTs[i]; |
| 571 SK_DEBUGBREAK(t <= span.fT); |
| 572 t = span.fT; |
| 573 int otherIndex = span.fOtherIndex; |
| 574 const SkOpSegment* other = span.fOther; |
| 575 SK_DEBUGBREAK(other != this || fVerb == SkPath::kCubic_Verb); |
| 576 const SkOpSpan& otherSpan = other->fTs[otherIndex]; |
| 577 SK_DEBUGBREAK(otherSpan.fPt == span.fPt); |
| 578 SK_DEBUGBREAK(otherSpan.fOtherT == t); |
| 579 SK_DEBUGBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]); |
| 580 done += span.fDone; |
| 581 if (last) { |
| 582 bool tsEqual = last->fT == span.fT; |
| 583 bool tsPreciselyEqual = precisely_equal(last->fT, span.fT); |
| 584 SK_DEBUGBREAK(!tsEqual || tsPreciselyEqual); |
| 585 bool pointsEqual = last->fPt == span.fPt; |
| 586 bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt); |
| 587 #if 0 // bufferOverflow test triggers this |
| 588 SK_DEBUGBREAK(!tsPreciselyEqual || pointsNearlyEqual); |
| 589 #endif |
| 590 // SK_DEBUGBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || t
inyTFound); |
| 591 SK_DEBUGBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || has
Loop); |
| 592 SK_DEBUGBREAK(!last->fTiny || pointsEqual); |
| 593 SK_DEBUGBREAK(!last->fTiny || last->fDone); |
| 594 SK_DEBUGBREAK(!last->fSmall || pointsNearlyEqual); |
| 595 SK_DEBUGBREAK(!last->fSmall || last->fDone); |
| 596 // SK_DEBUGBREAK(!last->fSmall || last->fTiny); |
| 597 // SK_DEBUGBREAK(last->fTiny || !pointsEqual || last->fDone == span.f
Done); |
| 598 if (last->fTiny) { |
| 599 tinyTFound |= !tsPreciselyEqual; |
| 600 } else { |
| 601 tinyTFound = false; |
| 602 } |
| 603 } |
| 604 last = &span; |
| 605 hasLoop |= last->fLoop; |
| 606 } |
| 607 SK_DEBUGBREAK(done == fDoneSpans); |
| 608 if (fAngles.count() ) { |
| 609 fAngles.begin()->debugValidateLoop(); |
| 610 } |
| 611 #endif |
| 612 } |
OLD | NEW |