1 /* 2 * Copyright 2012 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 #include "SkOpCoincidence.h" 8 #include "SkOpContour.h" 9 #include "SkOpSegment.h" 10 #include "SkPathWriter.h" 11 12 /* 13 After computing raw intersections, post process all segments to: 14 - find small collections of points that can be collapsed to a single point 15 - find missing intersections to resolve differences caused by different algorithms 16 17 Consider segments containing tiny or small intervals. Consider coincident segments 18 because coincidence finds intersections through distance measurement that non-coincident 19 intersection tests cannot. 20 */ 21 22 #define F (false) // discard the edge 23 #define T (true) // keep the edge 24 25 static const bool gUnaryActiveEdge[2][2] = { 26 // from=0 from=1 27 // to=0,1 to=0,1 28 {F, T}, {T, F}, 29 }; 30 31 static const bool gActiveEdge[kXOR_SkPathOp + 1][2][2][2][2] = { 32 // miFrom=0 miFrom=1 33 // miTo=0 miTo=1 miTo=0 miTo=1 34 // suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1 35 // suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 36 {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su 37 {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su 38 {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su 39 {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su 40 }; 41 42 #undef F 43 #undef T 44 45 SkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr, 46 SkOpSpanBase** endPtr, bool* done) { 47 if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) { 48 return result; 49 } 50 if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) { 51 return result; 52 } 53 return nullptr; 54 } 55 56 SkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr, 57 SkOpSpanBase** endPtr, bool* done) { 58 SkOpSpan* upSpan = start->upCastable(); 59 if (upSpan) { 60 if (upSpan->windValue() || upSpan->oppValue()) { 61 SkOpSpanBase* next = upSpan->next(); 62 if (!*endPtr) { 63 *startPtr = start; 64 *endPtr = next; 65 } 66 if (!upSpan->done()) { 67 if (upSpan->windSum() != SK_MinS32) { 68 return spanToAngle(start, next); 69 } 70 *done = false; 71 } 72 } else { 73 SkASSERT(upSpan->done()); 74 } 75 } 76 SkOpSpan* downSpan = start->prev(); 77 // edge leading into junction 78 if (downSpan) { 79 if (downSpan->windValue() || downSpan->oppValue()) { 80 if (!*endPtr) { 81 *startPtr = start; 82 *endPtr = downSpan; 83 } 84 if (!downSpan->done()) { 85 if (downSpan->windSum() != SK_MinS32) { 86 return spanToAngle(start, downSpan); 87 } 88 *done = false; 89 } 90 } else { 91 SkASSERT(downSpan->done()); 92 } 93 } 94 return nullptr; 95 } 96 97 SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr, 98 SkOpSpanBase** endPtr, bool* done) { 99 SkOpPtT* oPtT = start->ptT()->next(); 100 SkOpSegment* other = oPtT->segment(); 101 SkOpSpanBase* oSpan = oPtT->span(); 102 return other->activeAngleInner(oSpan, startPtr, endPtr, done); 103 } 104 105 bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask, 106 SkPathOp op) { 107 int sumMiWinding = this->updateWinding(end, start); 108 int sumSuWinding = this->updateOppWinding(end, start); 109 #if DEBUG_LIMIT_WIND_SUM 110 SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); 111 SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); 112 #endif 113 if (this->operand()) { 114 SkTSwap<int>(sumMiWinding, sumSuWinding); 115 } 116 return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding); 117 } 118 119 bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, 120 SkPathOp op, int* sumMiWinding, int* sumSuWinding) { 121 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 122 this->setUpWindings(start, end, sumMiWinding, sumSuWinding, 123 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 124 bool miFrom; 125 bool miTo; 126 bool suFrom; 127 bool suTo; 128 if (operand()) { 129 miFrom = (oppMaxWinding & xorMiMask) != 0; 130 miTo = (oppSumWinding & xorMiMask) != 0; 131 suFrom = (maxWinding & xorSuMask) != 0; 132 suTo = (sumWinding & xorSuMask) != 0; 133 } else { 134 miFrom = (maxWinding & xorMiMask) != 0; 135 miTo = (sumWinding & xorMiMask) != 0; 136 suFrom = (oppMaxWinding & xorSuMask) != 0; 137 suTo = (oppSumWinding & xorSuMask) != 0; 138 } 139 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 140 #if DEBUG_ACTIVE_OP 141 SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", 142 __FUNCTION__, debugID(), start->t(), end->t(), 143 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 144 #endif 145 return result; 146 } 147 148 bool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end) { 149 int sumWinding = updateWinding(end, start); 150 return activeWinding(start, end, &sumWinding); 151 } 152 153 bool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding) { 154 int maxWinding; 155 setUpWinding(start, end, &maxWinding, sumWinding); 156 bool from = maxWinding != 0; 157 bool to = *sumWinding != 0; 158 bool result = gUnaryActiveEdge[from][to]; 159 return result; 160 } 161 162 bool SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, 163 SkPathWriter* path) const { 164 FAIL_IF(start->starter(end)->alreadyAdded()); 165 SkDCurveSweep curvePart; 166 start->segment()->subDivide(start, end, &curvePart.fCurve); 167 curvePart.setCurveHullSweep(fVerb); 168 SkPath::Verb verb = curvePart.isCurve() ? fVerb : SkPath::kLine_Verb; 169 path->deferredMove(start->ptT()); 170 switch (verb) { 171 case SkPath::kLine_Verb: 172 FAIL_IF(!path->deferredLine(end->ptT())); 173 break; 174 case SkPath::kQuad_Verb: 175 path->quadTo(curvePart.fCurve.fQuad[1].asSkPoint(), end->ptT()); 176 break; 177 case SkPath::kConic_Verb: 178 path->conicTo(curvePart.fCurve.fConic[1].asSkPoint(), end->ptT(), 179 curvePart.fCurve.fConic.fWeight); 180 break; 181 case SkPath::kCubic_Verb: 182 path->cubicTo(curvePart.fCurve.fCubic[1].asSkPoint(), 183 curvePart.fCurve.fCubic[2].asSkPoint(), end->ptT()); 184 break; 185 default: 186 SkASSERT(0); 187 } 188 return true; 189 } 190 191 const SkOpPtT* SkOpSegment::existing(double t, const SkOpSegment* opp) const { 192 const SkOpSpanBase* test = &fHead; 193 const SkOpPtT* testPtT; 194 SkPoint pt = this->ptAtT(t); 195 do { 196 testPtT = test->ptT(); 197 if (testPtT->fT == t) { 198 break; 199 } 200 if (!this->match(testPtT, this, t, pt)) { 201 if (t < testPtT->fT) { 202 return nullptr; 203 } 204 continue; 205 } 206 if (!opp) { 207 return testPtT; 208 } 209 const SkOpPtT* loop = testPtT->next(); 210 while (loop != testPtT) { 211 if (loop->segment() == this && loop->fT == t && loop->fPt == pt) { 212 goto foundMatch; 213 } 214 loop = loop->next(); 215 } 216 return nullptr; 217 } while ((test = test->upCast()->next())); 218 foundMatch: 219 return opp && !test->contains(opp) ? nullptr : testPtT; 220 } 221 222 // break the span so that the coincident part does not change the angle of the remainder 223 bool SkOpSegment::addExpanded(double newT, const SkOpSpanBase* test, bool* startOver) { 224 if (this->contains(newT)) { 225 return true; 226 } 227 this->globalState()->resetAllocatedOpSpan(); 228 FAIL_IF(!between(0, newT, 1)); 229 SkOpPtT* newPtT = this->addT(newT); 230 *startOver |= this->globalState()->allocatedOpSpan(); 231 if (!newPtT) { 232 return false; 233 } 234 newPtT->fPt = this->ptAtT(newT); 235 SkOpPtT* oppPrev = test->ptT()->oppPrev(newPtT); 236 if (oppPrev) { 237 // const cast away to change linked list; pt/t values stays unchanged 238 SkOpSpanBase* writableTest = const_cast<SkOpSpanBase*>(test); 239 writableTest->mergeMatches(newPtT->span()); 240 writableTest->ptT()->addOpp(newPtT, oppPrev); 241 writableTest->checkForCollapsedCoincidence(); 242 } 243 return true; 244 } 245 246 // Please keep this in sync with debugAddT() 247 SkOpPtT* SkOpSegment::addT(double t, const SkPoint& pt) { 248 debugValidate(); 249 SkOpSpanBase* spanBase = &fHead; 250 do { 251 SkOpPtT* result = spanBase->ptT(); 252 if (t == result->fT || (!zero_or_one(t) && this->match(result, this, t, pt))) { 253 spanBase->bumpSpanAdds(); 254 return result; 255 } 256 if (t < result->fT) { 257 SkOpSpan* prev = result->span()->prev(); 258 FAIL_WITH_NULL_IF(!prev); 259 // marks in global state that new op span has been allocated 260 SkOpSpan* span = this->insert(prev); 261 span->init(this, prev, t, pt); 262 this->debugValidate(); 263 #if DEBUG_ADD_T 264 SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 265 span->segment()->debugID(), span->debugID()); 266 #endif 267 span->bumpSpanAdds(); 268 return span->ptT(); 269 } 270 FAIL_WITH_NULL_IF(spanBase == &fTail); 271 } while ((spanBase = spanBase->upCast()->next())); 272 SkASSERT(0); 273 return nullptr; // we never get here, but need this to satisfy compiler 274 } 275 276 SkOpPtT* SkOpSegment::addT(double t) { 277 return addT(t, this->ptAtT(t)); 278 } 279 280 void SkOpSegment::calcAngles() { 281 bool activePrior = !fHead.isCanceled(); 282 if (activePrior && !fHead.simple()) { 283 addStartSpan(); 284 } 285 SkOpSpan* prior = &fHead; 286 SkOpSpanBase* spanBase = fHead.next(); 287 while (spanBase != &fTail) { 288 if (activePrior) { 289 SkOpAngle* priorAngle = SkOpTAllocator<SkOpAngle>::Allocate( 290 this->globalState()->allocator()); 291 priorAngle->set(spanBase, prior); 292 spanBase->setFromAngle(priorAngle); 293 } 294 SkOpSpan* span = spanBase->upCast(); 295 bool active = !span->isCanceled(); 296 SkOpSpanBase* next = span->next(); 297 if (active) { 298 SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate( 299 this->globalState()->allocator()); 300 angle->set(span, next); 301 span->setToAngle(angle); 302 } 303 activePrior = active; 304 prior = span; 305 spanBase = next; 306 } 307 if (activePrior && !fTail.simple()) { 308 addEndSpan(); 309 } 310 } 311 312 // Please keep this in sync with debugClearAll() 313 void SkOpSegment::clearAll() { 314 SkOpSpan* span = &fHead; 315 do { 316 this->clearOne(span); 317 } while ((span = span->next()->upCastable())); 318 this->globalState()->coincidence()->release(this); 319 } 320 321 // Please keep this in sync with debugClearOne() 322 void SkOpSegment::clearOne(SkOpSpan* span) { 323 span->setWindValue(0); 324 span->setOppValue(0); 325 this->markDone(span); 326 } 327 328 bool SkOpSegment::collapsed(double s, double e) const { 329 const SkOpSpanBase* span = &fHead; 330 do { 331 if (span->collapsed(s, e)) { 332 return true; 333 } 334 } while (span->upCastable() && (span = span->upCast()->next())); 335 return false; 336 } 337 338 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 339 SkOpAngle::IncludeType includeType) { 340 SkOpSegment* baseSegment = baseAngle->segment(); 341 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 342 int sumSuWinding; 343 bool binary = includeType >= SkOpAngle::kBinarySingle; 344 if (binary) { 345 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); 346 if (baseSegment->operand()) { 347 SkTSwap<int>(sumMiWinding, sumSuWinding); 348 } 349 } 350 SkOpSegment* nextSegment = nextAngle->segment(); 351 int maxWinding, sumWinding; 352 SkOpSpanBase* last; 353 if (binary) { 354 int oppMaxWinding, oppSumWinding; 355 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 356 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 357 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 358 nextAngle); 359 } else { 360 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 361 &maxWinding, &sumWinding); 362 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 363 } 364 nextAngle->setLastMarked(last); 365 } 366 367 void SkOpSegment::ComputeOneSumReverse(SkOpAngle* baseAngle, SkOpAngle* nextAngle, 368 SkOpAngle::IncludeType includeType) { 369 SkOpSegment* baseSegment = baseAngle->segment(); 370 int sumMiWinding = baseSegment->updateWinding(baseAngle); 371 int sumSuWinding; 372 bool binary = includeType >= SkOpAngle::kBinarySingle; 373 if (binary) { 374 sumSuWinding = baseSegment->updateOppWinding(baseAngle); 375 if (baseSegment->operand()) { 376 SkTSwap<int>(sumMiWinding, sumSuWinding); 377 } 378 } 379 SkOpSegment* nextSegment = nextAngle->segment(); 380 int maxWinding, sumWinding; 381 SkOpSpanBase* last; 382 if (binary) { 383 int oppMaxWinding, oppSumWinding; 384 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 385 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 386 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 387 nextAngle); 388 } else { 389 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 390 &maxWinding, &sumWinding); 391 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 392 } 393 nextAngle->setLastMarked(last); 394 } 395 396 // at this point, the span is already ordered, or unorderable 397 int SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end, 398 SkOpAngle::IncludeType includeType) { 399 SkASSERT(includeType != SkOpAngle::kUnaryXor); 400 SkOpAngle* firstAngle = this->spanToAngle(end, start); 401 if (nullptr == firstAngle || nullptr == firstAngle->next()) { 402 return SK_NaN32; 403 } 404 // if all angles have a computed winding, 405 // or if no adjacent angles are orderable, 406 // or if adjacent orderable angles have no computed winding, 407 // there's nothing to do 408 // if two orderable angles are adjacent, and both are next to orderable angles, 409 // and one has winding computed, transfer to the other 410 SkOpAngle* baseAngle = nullptr; 411 bool tryReverse = false; 412 // look for counterclockwise transfers 413 SkOpAngle* angle = firstAngle->previous(); 414 SkOpAngle* next = angle->next(); 415 firstAngle = next; 416 do { 417 SkOpAngle* prior = angle; 418 angle = next; 419 next = angle->next(); 420 SkASSERT(prior->next() == angle); 421 SkASSERT(angle->next() == next); 422 if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 423 baseAngle = nullptr; 424 continue; 425 } 426 int testWinding = angle->starter()->windSum(); 427 if (SK_MinS32 != testWinding) { 428 baseAngle = angle; 429 tryReverse = true; 430 continue; 431 } 432 if (baseAngle) { 433 ComputeOneSum(baseAngle, angle, includeType); 434 baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr; 435 } 436 } while (next != firstAngle); 437 if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) { 438 firstAngle = baseAngle; 439 tryReverse = true; 440 } 441 if (tryReverse) { 442 baseAngle = nullptr; 443 SkOpAngle* prior = firstAngle; 444 do { 445 angle = prior; 446 prior = angle->previous(); 447 SkASSERT(prior->next() == angle); 448 next = angle->next(); 449 if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 450 baseAngle = nullptr; 451 continue; 452 } 453 int testWinding = angle->starter()->windSum(); 454 if (SK_MinS32 != testWinding) { 455 baseAngle = angle; 456 continue; 457 } 458 if (baseAngle) { 459 ComputeOneSumReverse(baseAngle, angle, includeType); 460 baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr; 461 } 462 } while (prior != firstAngle); 463 } 464 return start->starter(end)->windSum(); 465 } 466 467 bool SkOpSegment::contains(double newT) const { 468 const SkOpSpanBase* spanBase = &fHead; 469 do { 470 if (spanBase->ptT()->contains(this, newT)) { 471 return true; 472 } 473 if (spanBase == &fTail) { 474 break; 475 } 476 spanBase = spanBase->upCast()->next(); 477 } while (true); 478 return false; 479 } 480 481 void SkOpSegment::release(const SkOpSpan* span) { 482 if (span->done()) { 483 --fDoneCount; 484 } 485 --fCount; 486 SkOPASSERT(fCount >= fDoneCount); 487 } 488 489 #if DEBUG_ANGLE 490 // called only by debugCheckNearCoincidence 491 double SkOpSegment::distSq(double t, const SkOpAngle* oppAngle) const { 492 SkDPoint testPt = this->dPtAtT(t); 493 SkDLine testPerp = {{ testPt, testPt }}; 494 SkDVector slope = this->dSlopeAtT(t); 495 testPerp[1].fX += slope.fY; 496 testPerp[1].fY -= slope.fX; 497 SkIntersections i; 498 const SkOpSegment* oppSegment = oppAngle->segment(); 499 (*CurveIntersectRay[oppSegment->verb()])(oppSegment->pts(), oppSegment->weight(), testPerp, &i); 500 double closestDistSq = SK_ScalarInfinity; 501 for (int index = 0; index < i.used(); ++index) { 502 if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) { 503 continue; 504 } 505 double testDistSq = testPt.distanceSquared(i.pt(index)); 506 if (closestDistSq > testDistSq) { 507 closestDistSq = testDistSq; 508 } 509 } 510 return closestDistSq; 511 } 512 #endif 513 514 /* 515 The M and S variable name parts stand for the operators. 516 Mi stands for Minuend (see wiki subtraction, analogous to difference) 517 Su stands for Subtrahend 518 The Opp variable name part designates that the value is for the Opposite operator. 519 Opposite values result from combining coincident spans. 520 */ 521 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, 522 SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) { 523 SkOpSpanBase* start = *nextStart; 524 SkOpSpanBase* end = *nextEnd; 525 SkASSERT(start != end); 526 int step = start->step(end); 527 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 528 if (other) { 529 // mark the smaller of startIndex, endIndex done, and all adjacent 530 // spans with the same T value (but not 'other' spans) 531 #if DEBUG_WINDING 532 SkDebugf("%s simple\n", __FUNCTION__); 533 #endif 534 SkOpSpan* startSpan = start->starter(end); 535 if (startSpan->done()) { 536 return nullptr; 537 } 538 markDone(startSpan); 539 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 540 return other; 541 } 542 SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 543 SkASSERT(endNear == end); // is this ever not end? 544 SkASSERT(endNear); 545 SkASSERT(start != endNear); 546 SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 547 // more than one viable candidate -- measure angles to find best 548 int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp); 549 bool sortable = calcWinding != SK_NaN32; 550 if (!sortable) { 551 *unsortable = true; 552 markDone(start->starter(end)); 553 return nullptr; 554 } 555 SkOpAngle* angle = this->spanToAngle(end, start); 556 if (angle->unorderable()) { 557 *unsortable = true; 558 markDone(start->starter(end)); 559 return nullptr; 560 } 561 #if DEBUG_SORT 562 SkDebugf("%s\n", __FUNCTION__); 563 angle->debugLoop(); 564 #endif 565 int sumMiWinding = updateWinding(end, start); 566 if (sumMiWinding == SK_MinS32) { 567 *unsortable = true; 568 markDone(start->starter(end)); 569 return nullptr; 570 } 571 int sumSuWinding = updateOppWinding(end, start); 572 if (operand()) { 573 SkTSwap<int>(sumMiWinding, sumSuWinding); 574 } 575 SkOpAngle* nextAngle = angle->next(); 576 const SkOpAngle* foundAngle = nullptr; 577 bool foundDone = false; 578 // iterate through the angle, and compute everyone's winding 579 SkOpSegment* nextSegment; 580 int activeCount = 0; 581 do { 582 nextSegment = nextAngle->segment(); 583 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(), 584 nextAngle->end(), op, &sumMiWinding, &sumSuWinding); 585 if (activeAngle) { 586 ++activeCount; 587 if (!foundAngle || (foundDone && activeCount & 1)) { 588 foundAngle = nextAngle; 589 foundDone = nextSegment->done(nextAngle); 590 } 591 } 592 if (nextSegment->done()) { 593 continue; 594 } 595 if (!activeAngle) { 596 (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 597 } 598 SkOpSpanBase* last = nextAngle->lastMarked(); 599 if (last) { 600 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 601 *chase->append() = last; 602 #if DEBUG_WINDING 603 SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 604 last->segment()->debugID(), last->debugID()); 605 if (!last->final()) { 606 SkDebugf(" windSum=%d", last->upCast()->windSum()); 607 } 608 SkDebugf("\n"); 609 #endif 610 } 611 } while ((nextAngle = nextAngle->next()) != angle); 612 start->segment()->markDone(start->starter(end)); 613 if (!foundAngle) { 614 return nullptr; 615 } 616 *nextStart = foundAngle->start(); 617 *nextEnd = foundAngle->end(); 618 nextSegment = foundAngle->segment(); 619 #if DEBUG_WINDING 620 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 621 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 622 #endif 623 return nextSegment; 624 } 625 626 SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpanBase*>* chase, 627 SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable) { 628 SkOpSpanBase* start = *nextStart; 629 SkOpSpanBase* end = *nextEnd; 630 SkASSERT(start != end); 631 int step = start->step(end); 632 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 633 if (other) { 634 // mark the smaller of startIndex, endIndex done, and all adjacent 635 // spans with the same T value (but not 'other' spans) 636 #if DEBUG_WINDING 637 SkDebugf("%s simple\n", __FUNCTION__); 638 #endif 639 SkOpSpan* startSpan = start->starter(end); 640 if (startSpan->done()) { 641 return nullptr; 642 } 643 markDone(startSpan); 644 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 645 return other; 646 } 647 SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 648 SkASSERT(endNear == end); // is this ever not end? 649 SkASSERT(endNear); 650 SkASSERT(start != endNear); 651 SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 652 // more than one viable candidate -- measure angles to find best 653 int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding); 654 bool sortable = calcWinding != SK_NaN32; 655 if (!sortable) { 656 *unsortable = true; 657 markDone(start->starter(end)); 658 return nullptr; 659 } 660 SkOpAngle* angle = this->spanToAngle(end, start); 661 if (angle->unorderable()) { 662 *unsortable = true; 663 markDone(start->starter(end)); 664 return nullptr; 665 } 666 #if DEBUG_SORT 667 SkDebugf("%s\n", __FUNCTION__); 668 angle->debugLoop(); 669 #endif 670 int sumWinding = updateWinding(end, start); 671 SkOpAngle* nextAngle = angle->next(); 672 const SkOpAngle* foundAngle = nullptr; 673 bool foundDone = false; 674 // iterate through the angle, and compute everyone's winding 675 SkOpSegment* nextSegment; 676 int activeCount = 0; 677 do { 678 nextSegment = nextAngle->segment(); 679 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(), 680 &sumWinding); 681 if (activeAngle) { 682 ++activeCount; 683 if (!foundAngle || (foundDone && activeCount & 1)) { 684 foundAngle = nextAngle; 685 foundDone = nextSegment->done(nextAngle); 686 } 687 } 688 if (nextSegment->done()) { 689 continue; 690 } 691 if (!activeAngle) { 692 (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 693 } 694 SkOpSpanBase* last = nextAngle->lastMarked(); 695 if (last) { 696 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 697 *chase->append() = last; 698 #if DEBUG_WINDING 699 SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 700 last->segment()->debugID(), last->debugID()); 701 if (!last->final()) { 702 SkDebugf(" windSum=%d", last->upCast()->windSum()); 703 } 704 SkDebugf("\n"); 705 #endif 706 } 707 } while ((nextAngle = nextAngle->next()) != angle); 708 start->segment()->markDone(start->starter(end)); 709 if (!foundAngle) { 710 return nullptr; 711 } 712 *nextStart = foundAngle->start(); 713 *nextEnd = foundAngle->end(); 714 nextSegment = foundAngle->segment(); 715 #if DEBUG_WINDING 716 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 717 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 718 #endif 719 return nextSegment; 720 } 721 722 SkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, 723 bool* unsortable) { 724 SkOpSpanBase* start = *nextStart; 725 SkOpSpanBase* end = *nextEnd; 726 SkASSERT(start != end); 727 int step = start->step(end); 728 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 729 if (other) { 730 // mark the smaller of startIndex, endIndex done, and all adjacent 731 // spans with the same T value (but not 'other' spans) 732 #if DEBUG_WINDING 733 SkDebugf("%s simple\n", __FUNCTION__); 734 #endif 735 SkOpSpan* startSpan = start->starter(end); 736 if (startSpan->done()) { 737 return nullptr; 738 } 739 markDone(startSpan); 740 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 741 return other; 742 } 743 SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \ 744 : (*nextStart)->prev()); 745 SkASSERT(endNear == end); // is this ever not end? 746 SkASSERT(endNear); 747 SkASSERT(start != endNear); 748 SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 749 SkOpAngle* angle = this->spanToAngle(end, start); 750 if (!angle || angle->unorderable()) { 751 *unsortable = true; 752 markDone(start->starter(end)); 753 return nullptr; 754 } 755 #if DEBUG_SORT 756 SkDebugf("%s\n", __FUNCTION__); 757 angle->debugLoop(); 758 #endif 759 SkOpAngle* nextAngle = angle->next(); 760 const SkOpAngle* foundAngle = nullptr; 761 bool foundDone = false; 762 // iterate through the angle, and compute everyone's winding 763 SkOpSegment* nextSegment; 764 int activeCount = 0; 765 do { 766 nextSegment = nextAngle->segment(); 767 ++activeCount; 768 if (!foundAngle || (foundDone && activeCount & 1)) { 769 foundAngle = nextAngle; 770 if (!(foundDone = nextSegment->done(nextAngle))) { 771 break; 772 } 773 } 774 nextAngle = nextAngle->next(); 775 } while (nextAngle != angle); 776 start->segment()->markDone(start->starter(end)); 777 if (!foundAngle) { 778 return nullptr; 779 } 780 *nextStart = foundAngle->start(); 781 *nextEnd = foundAngle->end(); 782 nextSegment = foundAngle->segment(); 783 #if DEBUG_WINDING 784 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 785 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 786 #endif 787 return nextSegment; 788 } 789 790 SkOpGlobalState* SkOpSegment::globalState() const { 791 return contour()->globalState(); 792 } 793 794 void SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkPath::Verb verb) { 795 fContour = contour; 796 fNext = nullptr; 797 fPts = pts; 798 fWeight = weight; 799 fVerb = verb; 800 fCount = 0; 801 fDoneCount = 0; 802 fVisited = false; 803 SkOpSpan* zeroSpan = &fHead; 804 zeroSpan->init(this, nullptr, 0, fPts[0]); 805 SkOpSpanBase* oneSpan = &fTail; 806 zeroSpan->setNext(oneSpan); 807 oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]); 808 SkDEBUGCODE(fID = globalState()->nextSegmentID()); 809 } 810 811 bool SkOpSegment::isClose(double t, const SkOpSegment* opp) const { 812 SkDPoint cPt = this->dPtAtT(t); 813 SkDVector dxdy = (*CurveDSlopeAtT[this->verb()])(this->pts(), this->weight(), t); 814 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; 815 SkIntersections i; 816 (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), perp, &i); 817 int used = i.used(); 818 for (int index = 0; index < used; ++index) { 819 if (cPt.roughlyEqual(i.pt(index))) { 820 return true; 821 } 822 } 823 return false; 824 } 825 826 bool SkOpSegment::isXor() const { 827 return fContour->isXor(); 828 } 829 830 void SkOpSegment::markAllDone() { 831 SkOpSpan* span = this->head(); 832 do { 833 this->markDone(span); 834 } while ((span = span->next()->upCastable())); 835 } 836 837 SkOpSpanBase* SkOpSegment::markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end) { 838 int step = start->step(end); 839 SkOpSpan* minSpan = start->starter(end); 840 markDone(minSpan); 841 SkOpSpanBase* last = nullptr; 842 SkOpSegment* other = this; 843 SkOpSpan* priorDone = nullptr; 844 SkOpSpan* lastDone = nullptr; 845 while ((other = other->nextChase(&start, &step, &minSpan, &last))) { 846 if (other->done()) { 847 SkASSERT(!last); 848 break; 849 } 850 if (lastDone == minSpan || priorDone == minSpan) { 851 return nullptr; 852 } 853 other->markDone(minSpan); 854 priorDone = lastDone; 855 lastDone = minSpan; 856 } 857 return last; 858 } 859 860 bool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding, 861 SkOpSpanBase** lastPtr) { 862 SkOpSpan* spanStart = start->starter(end); 863 int step = start->step(end); 864 bool success = markWinding(spanStart, winding); 865 SkOpSpanBase* last = nullptr; 866 SkOpSegment* other = this; 867 while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 868 if (spanStart->windSum() != SK_MinS32) { 869 // SkASSERT(spanStart->windSum() == winding); // FIXME: is this assert too aggressive? 870 SkASSERT(!last); 871 break; 872 } 873 (void) other->markWinding(spanStart, winding); 874 } 875 if (lastPtr) { 876 *lastPtr = last; 877 } 878 return success; 879 } 880 881 bool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, 882 int winding, int oppWinding, SkOpSpanBase** lastPtr) { 883 SkOpSpan* spanStart = start->starter(end); 884 int step = start->step(end); 885 bool success = markWinding(spanStart, winding, oppWinding); 886 SkOpSpanBase* last = nullptr; 887 SkOpSegment* other = this; 888 while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 889 if (spanStart->windSum() != SK_MinS32) { 890 if (this->operand() == other->operand()) { 891 if (spanStart->windSum() != winding || spanStart->oppSum() != oppWinding) { 892 this->globalState()->setWindingFailed(); 893 return false; 894 } 895 } else { 896 SkASSERT(spanStart->windSum() == oppWinding); 897 SkASSERT(spanStart->oppSum() == winding); 898 } 899 SkASSERT(!last); 900 break; 901 } 902 if (this->operand() == other->operand()) { 903 (void) other->markWinding(spanStart, winding, oppWinding); 904 } else { 905 (void) other->markWinding(spanStart, oppWinding, winding); 906 } 907 } 908 if (lastPtr) { 909 *lastPtr = last; 910 } 911 return success; 912 } 913 914 SkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { 915 SkASSERT(angle->segment() == this); 916 if (UseInnerWinding(maxWinding, sumWinding)) { 917 maxWinding = sumWinding; 918 } 919 SkOpSpanBase* last; 920 (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, &last); 921 #if DEBUG_WINDING 922 if (last) { 923 SkDebugf("%s last seg=%d span=%d", __FUNCTION__, 924 last->segment()->debugID(), last->debugID()); 925 if (!last->final()) { 926 SkDebugf(" windSum="); 927 SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 928 } 929 SkDebugf("\n"); 930 } 931 #endif 932 return last; 933 } 934 935 SkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding, 936 int oppSumWinding, const SkOpAngle* angle) { 937 SkASSERT(angle->segment() == this); 938 if (UseInnerWinding(maxWinding, sumWinding)) { 939 maxWinding = sumWinding; 940 } 941 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { 942 oppMaxWinding = oppSumWinding; 943 } 944 SkOpSpanBase* last = nullptr; 945 // caller doesn't require that this marks anything 946 (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, &last); 947 #if DEBUG_WINDING 948 if (last) { 949 SkDebugf("%s last segment=%d span=%d", __FUNCTION__, 950 last->segment()->debugID(), last->debugID()); 951 if (!last->final()) { 952 SkDebugf(" windSum="); 953 SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 954 } 955 SkDebugf(" \n"); 956 } 957 #endif 958 return last; 959 } 960 961 void SkOpSegment::markDone(SkOpSpan* span) { 962 SkASSERT(this == span->segment()); 963 if (span->done()) { 964 return; 965 } 966 #if DEBUG_MARK_DONE 967 debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum()); 968 #endif 969 span->setDone(true); 970 ++fDoneCount; 971 debugValidate(); 972 } 973 974 bool SkOpSegment::markWinding(SkOpSpan* span, int winding) { 975 SkASSERT(this == span->segment()); 976 SkASSERT(winding); 977 if (span->done()) { 978 return false; 979 } 980 #if DEBUG_MARK_DONE 981 debugShowNewWinding(__FUNCTION__, span, winding); 982 #endif 983 span->setWindSum(winding); 984 debugValidate(); 985 return true; 986 } 987 988 bool SkOpSegment::markWinding(SkOpSpan* span, int winding, int oppWinding) { 989 SkASSERT(this == span->segment()); 990 SkASSERT(winding || oppWinding); 991 if (span->done()) { 992 return false; 993 } 994 #if DEBUG_MARK_DONE 995 debugShowNewWinding(__FUNCTION__, span, winding, oppWinding); 996 #endif 997 span->setWindSum(winding); 998 span->setOppSum(oppWinding); 999 debugValidate(); 1000 return true; 1001 } 1002 1003 bool SkOpSegment::match(const SkOpPtT* base, const SkOpSegment* testParent, double testT, 1004 const SkPoint& testPt) const { 1005 SkASSERT(this == base->segment()); 1006 if (this == testParent) { 1007 if (precisely_equal(base->fT, testT)) { 1008 return true; 1009 } 1010 } 1011 if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) { 1012 return false; 1013 } 1014 return this != testParent || !this->ptsDisjoint(base->fT, base->fPt, testT, testPt); 1015 } 1016 1017 static SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) { 1018 if (last) { 1019 *last = endSpan; 1020 } 1021 return nullptr; 1022 } 1023 1024 SkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr, 1025 SkOpSpanBase** last) const { 1026 SkOpSpanBase* origStart = *startPtr; 1027 int step = *stepPtr; 1028 SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev(); 1029 SkASSERT(endSpan); 1030 SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle(); 1031 SkOpSpanBase* foundSpan; 1032 SkOpSpanBase* otherEnd; 1033 SkOpSegment* other; 1034 if (angle == nullptr) { 1035 if (endSpan->t() != 0 && endSpan->t() != 1) { 1036 return nullptr; 1037 } 1038 SkOpPtT* otherPtT = endSpan->ptT()->next(); 1039 other = otherPtT->segment(); 1040 foundSpan = otherPtT->span(); 1041 otherEnd = step > 0 1042 ? foundSpan->upCastable() ? foundSpan->upCast()->next() : nullptr 1043 : foundSpan->prev(); 1044 } else { 1045 int loopCount = angle->loopCount(); 1046 if (loopCount > 2) { 1047 return set_last(last, endSpan); 1048 } 1049 const SkOpAngle* next = angle->next(); 1050 if (nullptr == next) { 1051 return nullptr; 1052 } 1053 #if DEBUG_WINDING 1054 if (angle->debugSign() != next->debugSign() && !angle->segment()->contour()->isXor() 1055 && !next->segment()->contour()->isXor()) { 1056 SkDebugf("%s mismatched signs\n", __FUNCTION__); 1057 } 1058 #endif 1059 other = next->segment(); 1060 foundSpan = endSpan = next->start(); 1061 otherEnd = next->end(); 1062 } 1063 if (!otherEnd) { 1064 return nullptr; 1065 } 1066 int foundStep = foundSpan->step(otherEnd); 1067 if (*stepPtr != foundStep) { 1068 return set_last(last, endSpan); 1069 } 1070 SkASSERT(*startPtr); 1071 // SkASSERT(otherEnd >= 0); 1072 SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast(); 1073 SkOpSpan* foundMin = foundSpan->starter(otherEnd); 1074 if (foundMin->windValue() != origMin->windValue() 1075 || foundMin->oppValue() != origMin->oppValue()) { 1076 return set_last(last, endSpan); 1077 } 1078 *startPtr = foundSpan; 1079 *stepPtr = foundStep; 1080 if (minPtr) { 1081 *minPtr = foundMin; 1082 } 1083 return other; 1084 } 1085 1086 // Please keep this in sync with DebugClearVisited() 1087 void SkOpSegment::ClearVisited(SkOpSpanBase* span) { 1088 // reset visited flag back to false 1089 do { 1090 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 1091 while ((ptT = ptT->next()) != stopPtT) { 1092 SkOpSegment* opp = ptT->segment(); 1093 opp->resetVisited(); 1094 } 1095 } while (!span->final() && (span = span->upCast()->next())); 1096 } 1097 1098 // Please keep this in sync with debugMissingCoincidence() 1099 // look for pairs of undetected coincident curves 1100 // assumes that segments going in have visited flag clear 1101 // Even though pairs of curves correct detect coincident runs, a run may be missed 1102 // if the coincidence is a product of multiple intersections. For instance, given 1103 // curves A, B, and C: 1104 // A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 1105 // the end of C that the intersection is replaced with the end of C. 1106 // Even though A-B correctly do not detect an intersection at point 2, 1107 // the resulting run from point 1 to point 2 is coincident on A and B. 1108 bool SkOpSegment::missingCoincidence() { 1109 if (this->done()) { 1110 return false; 1111 } 1112 SkOpSpan* prior = nullptr; 1113 SkOpSpanBase* spanBase = &fHead; 1114 bool result = false; 1115 do { 1116 SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 1117 SkOPASSERT(ptT->span() == spanBase); 1118 while ((ptT = ptT->next()) != spanStopPtT) { 1119 if (ptT->deleted()) { 1120 continue; 1121 } 1122 SkOpSegment* opp = ptT->span()->segment(); 1123 if (opp->done()) { 1124 continue; 1125 } 1126 // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 1127 if (!opp->visited()) { 1128 continue; 1129 } 1130 if (spanBase == &fHead) { 1131 continue; 1132 } 1133 if (ptT->segment() == this) { 1134 continue; 1135 } 1136 SkOpSpan* span = spanBase->upCastable(); 1137 // FIXME?: this assumes that if the opposite segment is coincident then no more 1138 // coincidence needs to be detected. This may not be true. 1139 if (span && span->containsCoincidence(opp)) { 1140 continue; 1141 } 1142 if (spanBase->containsCoinEnd(opp)) { 1143 continue; 1144 } 1145 SkOpPtT* priorPtT = nullptr, * priorStopPtT; 1146 // find prior span containing opp segment 1147 SkOpSegment* priorOpp = nullptr; 1148 SkOpSpan* priorTest = spanBase->prev(); 1149 while (!priorOpp && priorTest) { 1150 priorStopPtT = priorPtT = priorTest->ptT(); 1151 while ((priorPtT = priorPtT->next()) != priorStopPtT) { 1152 if (priorPtT->deleted()) { 1153 continue; 1154 } 1155 SkOpSegment* segment = priorPtT->span()->segment(); 1156 if (segment == opp) { 1157 prior = priorTest; 1158 priorOpp = opp; 1159 break; 1160 } 1161 } 1162 priorTest = priorTest->prev(); 1163 } 1164 if (!priorOpp) { 1165 continue; 1166 } 1167 if (priorPtT == ptT) { 1168 continue; 1169 } 1170 SkOpPtT* oppStart = prior->ptT(); 1171 SkOpPtT* oppEnd = spanBase->ptT(); 1172 bool swapped = priorPtT->fT > ptT->fT; 1173 if (swapped) { 1174 SkTSwap(priorPtT, ptT); 1175 SkTSwap(oppStart, oppEnd); 1176 } 1177 SkOpCoincidence* coincidences = this->globalState()->coincidence(); 1178 SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 1179 SkOpPtT* rootPtT = ptT->span()->ptT(); 1180 SkOpPtT* rootOppStart = oppStart->span()->ptT(); 1181 SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 1182 if (coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 1183 goto swapBack; 1184 } 1185 if (this->testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 1186 // mark coincidence 1187 #if DEBUG_COINCIDENCE_VERBOSE 1188 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 1189 rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 1190 rootOppEnd->debugID()); 1191 #endif 1192 if (!coincidences->extend(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 1193 coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 1194 } 1195 #if DEBUG_COINCIDENCE 1196 SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)); 1197 #endif 1198 result = true; 1199 } 1200 swapBack: 1201 if (swapped) { 1202 SkTSwap(priorPtT, ptT); 1203 } 1204 } 1205 } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 1206 ClearVisited(&fHead); 1207 return result; 1208 } 1209 1210 // please keep this in sync with debugMoveMultiples() 1211 // if a span has more than one intersection, merge the other segments' span as needed 1212 bool SkOpSegment::moveMultiples() { 1213 debugValidate(); 1214 SkOpSpanBase* test = &fHead; 1215 do { 1216 int addCount = test->spanAddsCount(); 1217 // FAIL_IF(addCount < 1); 1218 if (addCount <= 1) { 1219 continue; 1220 } 1221 SkOpPtT* startPtT = test->ptT(); 1222 SkOpPtT* testPtT = startPtT; 1223 do { // iterate through all spans associated with start 1224 SkOpSpanBase* oppSpan = testPtT->span(); 1225 if (oppSpan->spanAddsCount() == addCount) { 1226 continue; 1227 } 1228 if (oppSpan->deleted()) { 1229 continue; 1230 } 1231 SkOpSegment* oppSegment = oppSpan->segment(); 1232 if (oppSegment == this) { 1233 continue; 1234 } 1235 // find range of spans to consider merging 1236 SkOpSpanBase* oppPrev = oppSpan; 1237 SkOpSpanBase* oppFirst = oppSpan; 1238 while ((oppPrev = oppPrev->prev())) { 1239 if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 1240 break; 1241 } 1242 if (oppPrev->spanAddsCount() == addCount) { 1243 continue; 1244 } 1245 if (oppPrev->deleted()) { 1246 continue; 1247 } 1248 oppFirst = oppPrev; 1249 } 1250 SkOpSpanBase* oppNext = oppSpan; 1251 SkOpSpanBase* oppLast = oppSpan; 1252 while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 1253 if (!roughly_equal(oppNext->t(), oppSpan->t())) { 1254 break; 1255 } 1256 if (oppNext->spanAddsCount() == addCount) { 1257 continue; 1258 } 1259 if (oppNext->deleted()) { 1260 continue; 1261 } 1262 oppLast = oppNext; 1263 } 1264 if (oppFirst == oppLast) { 1265 continue; 1266 } 1267 SkOpSpanBase* oppTest = oppFirst; 1268 do { 1269 if (oppTest == oppSpan) { 1270 continue; 1271 } 1272 // check to see if the candidate meets specific criteria: 1273 // it contains spans of segments in test's loop but not including 'this' 1274 SkOpPtT* oppStartPtT = oppTest->ptT(); 1275 SkOpPtT* oppPtT = oppStartPtT; 1276 while ((oppPtT = oppPtT->next()) != oppStartPtT) { 1277 SkOpSegment* oppPtTSegment = oppPtT->segment(); 1278 if (oppPtTSegment == this) { 1279 goto tryNextSpan; 1280 } 1281 SkOpPtT* matchPtT = startPtT; 1282 do { 1283 if (matchPtT->segment() == oppPtTSegment) { 1284 goto foundMatch; 1285 } 1286 } while ((matchPtT = matchPtT->next()) != startPtT); 1287 goto tryNextSpan; 1288 foundMatch: // merge oppTest and oppSpan 1289 oppSegment->debugValidate(); 1290 oppTest->mergeMatches(oppSpan); 1291 oppTest->addOpp(oppSpan); 1292 oppSegment->debugValidate(); 1293 goto checkNextSpan; 1294 } 1295 tryNextSpan: 1296 ; 1297 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 1298 } while ((testPtT = testPtT->next()) != startPtT); 1299 checkNextSpan: 1300 ; 1301 } while ((test = test->final() ? nullptr : test->upCast()->next())); 1302 debugValidate(); 1303 return true; 1304 } 1305 1306 // adjacent spans may have points close by 1307 bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* checkSpan, 1308 bool* found) const { 1309 const SkOpPtT* refHead = refSpan->ptT(); 1310 const SkOpPtT* checkHead = checkSpan->ptT(); 1311 // if the first pt pair from adjacent spans are far apart, assume that all are far enough apart 1312 if (!SkDPoint::WayRoughlyEqual(refHead->fPt, checkHead->fPt)) { 1313 #if DEBUG_COINCIDENCE 1314 // verify that no combination of points are close 1315 const SkOpPtT* dBugRef = refHead; 1316 do { 1317 const SkOpPtT* dBugCheck = checkHead; 1318 do { 1319 SkOPASSERT(!SkDPoint::ApproximatelyEqual(dBugRef->fPt, dBugCheck->fPt)); 1320 dBugCheck = dBugCheck->next(); 1321 } while (dBugCheck != checkHead); 1322 dBugRef = dBugRef->next(); 1323 } while (dBugRef != refHead); 1324 #endif 1325 *found = false; 1326 return true; 1327 } 1328 // check only unique points 1329 SkScalar distSqBest = SK_ScalarMax; 1330 const SkOpPtT* refBest = nullptr; 1331 const SkOpPtT* checkBest = nullptr; 1332 const SkOpPtT* ref = refHead; 1333 do { 1334 if (ref->deleted()) { 1335 continue; 1336 } 1337 while (ref->ptAlreadySeen(refHead)) { 1338 ref = ref->next(); 1339 if (ref == refHead) { 1340 goto doneCheckingDistance; 1341 } 1342 } 1343 const SkOpPtT* check = checkHead; 1344 const SkOpSegment* refSeg = ref->segment(); 1345 int escapeHatch = 100000; // defend against infinite loops 1346 do { 1347 if (check->deleted()) { 1348 continue; 1349 } 1350 while (check->ptAlreadySeen(checkHead)) { 1351 check = check->next(); 1352 if (check == checkHead) { 1353 goto nextRef; 1354 } 1355 } 1356 SkScalar distSq = ref->fPt.distanceToSqd(check->fPt); 1357 if (distSqBest > distSq && (refSeg != check->segment() 1358 || !refSeg->ptsDisjoint(*ref, *check))) { 1359 distSqBest = distSq; 1360 refBest = ref; 1361 checkBest = check; 1362 } 1363 if (--escapeHatch <= 0) { 1364 return false; 1365 } 1366 } while ((check = check->next()) != checkHead); 1367 nextRef: 1368 ; 1369 } while ((ref = ref->next()) != refHead); 1370 doneCheckingDistance: 1371 *found = checkBest && refBest->segment()->match(refBest, checkBest->segment(), checkBest->fT, 1372 checkBest->fPt); 1373 return true; 1374 } 1375 1376 // Please keep this function in sync with debugMoveNearby() 1377 // Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1378 bool SkOpSegment::moveNearby() { 1379 debugValidate(); 1380 // release undeleted spans pointing to this seg that are linked to the primary span 1381 SkOpSpanBase* spanBase = &fHead; 1382 do { 1383 SkOpPtT* ptT = spanBase->ptT(); 1384 const SkOpPtT* headPtT = ptT; 1385 while ((ptT = ptT->next()) != headPtT) { 1386 SkOpSpanBase* test = ptT->span(); 1387 if (ptT->segment() == this && !ptT->deleted() && test != spanBase 1388 && test->ptT() == ptT) { 1389 if (test->final()) { 1390 if (spanBase == &fHead) { 1391 this->clearAll(); 1392 return true; 1393 } 1394 spanBase->upCast()->release(ptT); 1395 } else if (test->prev()) { 1396 test->upCast()->release(headPtT); 1397 } 1398 break; 1399 } 1400 } 1401 spanBase = spanBase->upCast()->next(); 1402 } while (!spanBase->final()); 1403 1404 // This loop looks for adjacent spans which are near by 1405 spanBase = &fHead; 1406 do { // iterate through all spans associated with start 1407 SkOpSpanBase* test = spanBase->upCast()->next(); 1408 bool found; 1409 if (!this->spansNearby(spanBase, test, &found)) { 1410 return false; 1411 } 1412 if (found) { 1413 if (test->final()) { 1414 if (spanBase->prev()) { 1415 test->merge(spanBase->upCast()); 1416 } else { 1417 this->clearAll(); 1418 return true; 1419 } 1420 } else { 1421 spanBase->merge(test->upCast()); 1422 } 1423 } 1424 spanBase = test; 1425 } while (!spanBase->final()); 1426 debugValidate(); 1427 return true; 1428 } 1429 1430 bool SkOpSegment::operand() const { 1431 return fContour->operand(); 1432 } 1433 1434 bool SkOpSegment::oppXor() const { 1435 return fContour->oppXor(); 1436 } 1437 1438 bool SkOpSegment::ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const { 1439 if (fVerb == SkPath::kLine_Verb) { 1440 return false; 1441 } 1442 // quads (and cubics) can loop back to nearly a line so that an opposite curve 1443 // hits in two places with very different t values. 1444 // OPTIMIZATION: curves could be preflighted so that, for example, something like 1445 // 'controls contained by ends' could avoid this check for common curves 1446 // 'ends are extremes in x or y' is cheaper to compute and real-world common 1447 // on the other hand, the below check is relatively inexpensive 1448 double midT = (t1 + t2) / 2; 1449 SkPoint midPt = this->ptAtT(midT); 1450 double seDistSq = SkTMax(pt1.distanceToSqd(pt2) * 2, FLT_EPSILON * 2); 1451 return midPt.distanceToSqd(pt1) > seDistSq || midPt.distanceToSqd(pt2) > seDistSq; 1452 } 1453 1454 void SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 1455 int* maxWinding, int* sumWinding) { 1456 int deltaSum = SpanSign(start, end); 1457 *maxWinding = *sumMiWinding; 1458 *sumWinding = *sumMiWinding -= deltaSum; 1459 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 1460 } 1461 1462 void SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 1463 int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding, 1464 int* oppSumWinding) { 1465 int deltaSum = SpanSign(start, end); 1466 int oppDeltaSum = OppSign(start, end); 1467 if (operand()) { 1468 *maxWinding = *sumSuWinding; 1469 *sumWinding = *sumSuWinding -= deltaSum; 1470 *oppMaxWinding = *sumMiWinding; 1471 *oppSumWinding = *sumMiWinding -= oppDeltaSum; 1472 } else { 1473 *maxWinding = *sumMiWinding; 1474 *sumWinding = *sumMiWinding -= deltaSum; 1475 *oppMaxWinding = *sumSuWinding; 1476 *oppSumWinding = *sumSuWinding -= oppDeltaSum; 1477 } 1478 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 1479 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM); 1480 } 1481 1482 bool SkOpSegment::sortAngles() { 1483 SkOpSpanBase* span = &this->fHead; 1484 do { 1485 SkOpAngle* fromAngle = span->fromAngle(); 1486 SkOpAngle* toAngle = span->final() ? nullptr : span->upCast()->toAngle(); 1487 if (!fromAngle && !toAngle) { 1488 continue; 1489 } 1490 #if DEBUG_ANGLE 1491 bool wroteAfterHeader = false; 1492 #endif 1493 SkOpAngle* baseAngle = fromAngle; 1494 if (fromAngle && toAngle) { 1495 #if DEBUG_ANGLE 1496 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(), 1497 span->debugID()); 1498 wroteAfterHeader = true; 1499 #endif 1500 FAIL_IF(!fromAngle->insert(toAngle)); 1501 } else if (!fromAngle) { 1502 baseAngle = toAngle; 1503 } 1504 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 1505 do { 1506 SkOpSpanBase* oSpan = ptT->span(); 1507 if (oSpan == span) { 1508 continue; 1509 } 1510 SkOpAngle* oAngle = oSpan->fromAngle(); 1511 if (oAngle) { 1512 #if DEBUG_ANGLE 1513 if (!wroteAfterHeader) { 1514 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 1515 span->t(), span->debugID()); 1516 wroteAfterHeader = true; 1517 } 1518 #endif 1519 if (!oAngle->loopContains(baseAngle)) { 1520 baseAngle->insert(oAngle); 1521 } 1522 } 1523 if (!oSpan->final()) { 1524 oAngle = oSpan->upCast()->toAngle(); 1525 if (oAngle) { 1526 #if DEBUG_ANGLE 1527 if (!wroteAfterHeader) { 1528 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 1529 span->t(), span->debugID()); 1530 wroteAfterHeader = true; 1531 } 1532 #endif 1533 if (!oAngle->loopContains(baseAngle)) { 1534 baseAngle->insert(oAngle); 1535 } 1536 } 1537 } 1538 } while ((ptT = ptT->next()) != stopPtT); 1539 if (baseAngle->loopCount() == 1) { 1540 span->setFromAngle(nullptr); 1541 if (toAngle) { 1542 span->upCast()->setToAngle(nullptr); 1543 } 1544 baseAngle = nullptr; 1545 } 1546 #if DEBUG_SORT 1547 SkASSERT(!baseAngle || baseAngle->loopCount() > 1); 1548 #endif 1549 } while (!span->final() && (span = span->upCast()->next())); 1550 return true; 1551 } 1552 1553 bool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, 1554 SkDCurve* edge) const { 1555 SkASSERT(start != end); 1556 const SkOpPtT& startPtT = *start->ptT(); 1557 const SkOpPtT& endPtT = *end->ptT(); 1558 SkDEBUGCODE(edge->fVerb = fVerb); 1559 edge->fCubic[0].set(startPtT.fPt); 1560 int points = SkPathOpsVerbToPoints(fVerb); 1561 edge->fCubic[points].set(endPtT.fPt); 1562 if (fVerb == SkPath::kLine_Verb) { 1563 return false; 1564 } 1565 double startT = startPtT.fT; 1566 double endT = endPtT.fT; 1567 if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 1568 // don't compute midpoints if we already have them 1569 if (fVerb == SkPath::kQuad_Verb) { 1570 edge->fLine[1].set(fPts[1]); 1571 return false; 1572 } 1573 if (fVerb == SkPath::kConic_Verb) { 1574 edge->fConic[1].set(fPts[1]); 1575 edge->fConic.fWeight = fWeight; 1576 return false; 1577 } 1578 SkASSERT(fVerb == SkPath::kCubic_Verb); 1579 if (startT == 0) { 1580 edge->fCubic[1].set(fPts[1]); 1581 edge->fCubic[2].set(fPts[2]); 1582 return false; 1583 } 1584 edge->fCubic[1].set(fPts[2]); 1585 edge->fCubic[2].set(fPts[1]); 1586 return false; 1587 } 1588 if (fVerb == SkPath::kQuad_Verb) { 1589 edge->fQuad[1] = SkDQuad::SubDivide(fPts, edge->fQuad[0], edge->fQuad[2], startT, endT); 1590 } else if (fVerb == SkPath::kConic_Verb) { 1591 edge->fConic[1] = SkDConic::SubDivide(fPts, fWeight, edge->fQuad[0], edge->fQuad[2], 1592 startT, endT, &edge->fConic.fWeight); 1593 } else { 1594 SkASSERT(fVerb == SkPath::kCubic_Verb); 1595 SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT, &edge->fCubic[1]); 1596 } 1597 return true; 1598 } 1599 1600 bool SkOpSegment::testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT, 1601 const SkOpSpanBase* prior, const SkOpSpanBase* spanBase, const SkOpSegment* opp) const { 1602 // average t, find mid pt 1603 double midT = (prior->t() + spanBase->t()) / 2; 1604 SkPoint midPt = this->ptAtT(midT); 1605 bool coincident = true; 1606 // if the mid pt is not near either end pt, project perpendicular through opp seg 1607 if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt) 1608 && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) { 1609 if (priorPtT->span() == ptT->span()) { 1610 return false; 1611 } 1612 coincident = false; 1613 SkIntersections i; 1614 SkDCurve curvePart; 1615 this->subDivide(prior, spanBase, &curvePart); 1616 SkDVector dxdy = (*CurveDDSlopeAtT[fVerb])(curvePart, 0.5f); 1617 SkDPoint partMidPt = (*CurveDDPointAtT[fVerb])(curvePart, 0.5f); 1618 SkDLine ray = {{{midPt.fX, midPt.fY}, {partMidPt.fX + dxdy.fY, partMidPt.fY - dxdy.fX}}}; 1619 SkDCurve oppPart; 1620 opp->subDivide(priorPtT->span(), ptT->span(), &oppPart); 1621 (*CurveDIntersectRay[opp->verb()])(oppPart, ray, &i); 1622 // measure distance and see if it's small enough to denote coincidence 1623 for (int index = 0; index < i.used(); ++index) { 1624 if (!between(0, i[0][index], 1)) { 1625 continue; 1626 } 1627 SkDPoint oppPt = i.pt(index); 1628 if (oppPt.approximatelyDEqual(midPt)) { 1629 // the coincidence can occur at almost any angle 1630 coincident = true; 1631 } 1632 } 1633 } 1634 return coincident; 1635 } 1636 1637 SkOpSpan* SkOpSegment::undoneSpan() { 1638 SkOpSpan* span = &fHead; 1639 SkOpSpanBase* next; 1640 do { 1641 next = span->next(); 1642 if (!span->done()) { 1643 return span; 1644 } 1645 } while (!next->final() && (span = next->upCast())); 1646 return nullptr; 1647 } 1648 1649 int SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { 1650 const SkOpSpan* lesser = start->starter(end); 1651 int oppWinding = lesser->oppSum(); 1652 int oppSpanWinding = SkOpSegment::OppSign(start, end); 1653 if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding) 1654 && oppWinding != SK_MaxS32) { 1655 oppWinding -= oppSpanWinding; 1656 } 1657 return oppWinding; 1658 } 1659 1660 int SkOpSegment::updateOppWinding(const SkOpAngle* angle) const { 1661 const SkOpSpanBase* startSpan = angle->start(); 1662 const SkOpSpanBase* endSpan = angle->end(); 1663 return updateOppWinding(endSpan, startSpan); 1664 } 1665 1666 int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { 1667 const SkOpSpanBase* startSpan = angle->start(); 1668 const SkOpSpanBase* endSpan = angle->end(); 1669 return updateOppWinding(startSpan, endSpan); 1670 } 1671 1672 int SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) { 1673 SkOpSpan* lesser = start->starter(end); 1674 int winding = lesser->windSum(); 1675 if (winding == SK_MinS32) { 1676 winding = lesser->computeWindSum(); 1677 } 1678 if (winding == SK_MinS32) { 1679 return winding; 1680 } 1681 int spanWinding = SkOpSegment::SpanSign(start, end); 1682 if (winding && UseInnerWinding(winding - spanWinding, winding) 1683 && winding != SK_MaxS32) { 1684 winding -= spanWinding; 1685 } 1686 return winding; 1687 } 1688 1689 int SkOpSegment::updateWinding(SkOpAngle* angle) { 1690 SkOpSpanBase* startSpan = angle->start(); 1691 SkOpSpanBase* endSpan = angle->end(); 1692 return updateWinding(endSpan, startSpan); 1693 } 1694 1695 int SkOpSegment::updateWindingReverse(const SkOpAngle* angle) { 1696 SkOpSpanBase* startSpan = angle->start(); 1697 SkOpSpanBase* endSpan = angle->end(); 1698 return updateWinding(startSpan, endSpan); 1699 } 1700 1701 // OPTIMIZATION: does the following also work, and is it any faster? 1702 // return outerWinding * innerWinding > 0 1703 // || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0))) 1704 bool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) { 1705 SkASSERT(outerWinding != SK_MaxS32); 1706 SkASSERT(innerWinding != SK_MaxS32); 1707 int absOut = SkTAbs(outerWinding); 1708 int absIn = SkTAbs(innerWinding); 1709 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; 1710 return result; 1711 } 1712 1713 int SkOpSegment::windSum(const SkOpAngle* angle) const { 1714 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); 1715 return minSpan->windSum(); 1716 } 1717