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 "SkMutex.h" | 8 #include "SkMutex.h" |
9 #include "SkOpCoincidence.h" | 9 #include "SkOpCoincidence.h" |
10 #include "SkOpContour.h" | 10 #include "SkOpContour.h" |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 575 |
576 void SkDRect::debugInit() { | 576 void SkDRect::debugInit() { |
577 fLeft = fTop = fRight = fBottom = SK_ScalarNaN; | 577 fLeft = fTop = fRight = fBottom = SK_ScalarNaN; |
578 } | 578 } |
579 | 579 |
580 #include "SkOpAngle.h" | 580 #include "SkOpAngle.h" |
581 #include "SkOpSegment.h" | 581 #include "SkOpSegment.h" |
582 | 582 |
583 #if DEBUG_COINCIDENCE | 583 #if DEBUG_COINCIDENCE |
584 // commented-out lines keep this in sync with addT() | 584 // commented-out lines keep this in sync with addT() |
585 const SkOpPtT* SkOpSegment::debugAddT(double t, bool* allocated) const { | 585 const SkOpPtT* SkOpSegment::debugAddT(double t) const { |
586 debugValidate(); | 586 debugValidate(); |
587 SkPoint pt = this->ptAtT(t); | 587 SkPoint pt = this->ptAtT(t); |
588 const SkOpSpanBase* span = &fHead; | 588 const SkOpSpanBase* span = &fHead; |
589 do { | 589 do { |
590 const SkOpPtT* result = span->ptT(); | 590 const SkOpPtT* result = span->ptT(); |
591 const SkOpPtT* loop; | 591 if (t == result->fT || this->match(result, this, t, pt)) { |
592 bool duplicatePt; | |
593 if (t == result->fT) { | |
594 goto bumpSpan; | |
595 } | |
596 if (this->match(result, this, t, pt)) { | |
597 // see if any existing alias matches segment, pt, and t | |
598 loop = result->next(); | |
599 duplicatePt = false; | |
600 while (loop != result) { | |
601 bool ptMatch = loop->fPt == pt; | |
602 if (loop->segment() == this && loop->fT == t && ptMatch) { | |
603 goto bumpSpan; | |
604 } | |
605 duplicatePt |= ptMatch; | |
606 loop = loop->next(); | |
607 } | |
608 bumpSpan: | |
609 // span->bumpSpanAdds(); | 592 // span->bumpSpanAdds(); |
610 return result; | 593 return result; |
611 } | 594 } |
612 if (t < result->fT) { | 595 if (t < result->fT) { |
613 const SkOpSpan* prev = result->span()->prev(); | 596 const SkOpSpan* prev = result->span()->prev(); |
614 if (!prev) { | 597 FAIL_WITH_NULL_IF(!prev); |
615 return nullptr; // FIXME: this is a fail case; nullptr return e
lsewhere means result was allocated in non-const version | 598 // marks in global state that new op span has been allocated |
616 } | 599 this->globalState()->setAllocatedOpSpan(); |
617 // SkOpSpan* span = insert(prev, allocator); | |
618 // span->init(this, prev, t, pt); | 600 // span->init(this, prev, t, pt); |
619 this->debugValidate(); | 601 this->debugValidate(); |
620 // #if DEBUG_ADD_T | 602 // #if DEBUG_ADD_T |
621 // SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__,
t, | 603 // SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__,
t, |
622 // span->segment()->debugID(), span->debugID()); | 604 // span->segment()->debugID(), span->debugID()); |
623 // #endif | 605 // #endif |
624 // span->bumpSpanAdds(); | 606 // span->bumpSpanAdds(); |
625 if (allocated) { | |
626 *allocated = true; | |
627 } | |
628 return nullptr; | 607 return nullptr; |
629 } | 608 } |
630 SkASSERT(span != &fTail); | 609 FAIL_WITH_NULL_IF(span != &fTail); |
631 } while ((span = span->upCast()->next())); | 610 } while ((span = span->upCast()->next())); |
632 SkASSERT(0); | 611 SkASSERT(0); |
633 return nullptr; | 612 return nullptr; // we never get here, but need this to satisfy compiler |
634 } | 613 } |
635 #endif | 614 #endif |
636 | 615 |
637 #if DEBUG_ANGLE | 616 #if DEBUG_ANGLE |
638 void SkOpSegment::debugCheckAngleCoin() const { | 617 void SkOpSegment::debugCheckAngleCoin() const { |
639 const SkOpSpanBase* base = &fHead; | 618 const SkOpSpanBase* base = &fHead; |
640 const SkOpSpan* span; | 619 const SkOpSpan* span; |
641 do { | 620 do { |
642 const SkOpAngle* angle = base->fromAngle(); | 621 const SkOpAngle* angle = base->fromAngle(); |
643 if (angle && angle->debugCheckCoincidence()) { | 622 if (angle && angle->debugCheckCoincidence()) { |
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeE
xisting : oe))) { | 1465 if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeE
xisting : oe))) { |
1487 return; | 1466 return; |
1488 } | 1467 } |
1489 if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osE
xisting : os))) { | 1468 if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osE
xisting : os))) { |
1490 return; | 1469 return; |
1491 } | 1470 } |
1492 bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = f
alse; | 1471 bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = f
alse; |
1493 this->debugValidate(); | 1472 this->debugValidate(); |
1494 if (!cs || !os) { | 1473 if (!cs || !os) { |
1495 if (!cs) | 1474 if (!cs) |
1496 cs = coinSeg->debugAddT(coinTs, nullptr); | 1475 cs = coinSeg->debugAddT(coinTs); |
1497 if (!os) | 1476 if (!os) |
1498 os = oppSeg->debugAddT(oppTs, nullptr); | 1477 os = oppSeg->debugAddT(oppTs); |
1499 if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDe
leted, &osDeleted); | 1478 if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDe
leted, &osDeleted); |
1500 // cs = csWritable; | 1479 // cs = csWritable; |
1501 // os = osWritable; | 1480 // os = osWritable; |
1502 if ((ce && ce->deleted()) || (oe && oe->deleted())) { | 1481 if ((ce && ce->deleted()) || (oe && oe->deleted())) { |
1503 return; | 1482 return; |
1504 } | 1483 } |
1505 } | 1484 } |
1506 if (!ce || !oe) { | 1485 if (!ce || !oe) { |
1507 if (!ce) | 1486 if (!ce) |
1508 ce = coinSeg->debugAddT(coinTe, nullptr); | 1487 ce = coinSeg->debugAddT(coinTe); |
1509 if (!oe) | 1488 if (!oe) |
1510 oe = oppSeg->debugAddT(oppTe, nullptr); | 1489 oe = oppSeg->debugAddT(oppTe); |
1511 if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDe
leted, &oeDeleted); | 1490 if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDe
leted, &oeDeleted); |
1512 // ce = ceWritable; | 1491 // ce = ceWritable; |
1513 // oe = oeWritable; | 1492 // oe = oeWritable; |
1514 } | 1493 } |
1515 this->debugValidate(); | 1494 this->debugValidate(); |
1516 if (csDeleted || osDeleted || ceDeleted || oeDeleted) { | 1495 if (csDeleted || osDeleted || ceDeleted || oeDeleted) { |
1517 return; | 1496 return; |
1518 } | 1497 } |
1519 if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) { | 1498 if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) { |
1520 return; | 1499 return; |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 SkASSERT(count >= fDoneCount); | 2031 SkASSERT(count >= fDoneCount); |
2053 SkASSERT(span->final()); | 2032 SkASSERT(span->final()); |
2054 span->debugValidate(); | 2033 span->debugValidate(); |
2055 #endif | 2034 #endif |
2056 } | 2035 } |
2057 | 2036 |
2058 #if DEBUG_COINCIDENCE_VERBOSE | 2037 #if DEBUG_COINCIDENCE_VERBOSE |
2059 // Commented-out lines keep this in sync with addOppAndMerge() | 2038 // Commented-out lines keep this in sync with addOppAndMerge() |
2060 // If the added points envelop adjacent spans, merge them in. | 2039 // If the added points envelop adjacent spans, merge them in. |
2061 void SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog
* log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const { | 2040 void SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog
* log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const { |
2062 if (this->ptT()->debugAddOpp(opp->ptT())) { | 2041 const SkOpPtT* oppPrev = this->ptT()->debugOppPrev(opp->ptT()); |
| 2042 if (oppPrev) { |
| 2043 this->ptT()->debugAddOpp(opp->ptT(), oppPrev); |
2063 this->debugCheckForCollapsedCoincidence(id, log); | 2044 this->debugCheckForCollapsedCoincidence(id, log); |
2064 } | 2045 } |
2065 // compute bounds of points in span | 2046 // compute bounds of points in span |
2066 SkPathOpsBounds bounds; | 2047 SkPathOpsBounds bounds; |
2067 bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin); | 2048 bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin); |
2068 const SkOpPtT* head = this->ptT(); | 2049 const SkOpPtT* head = this->ptT(); |
2069 const SkOpPtT* nextPt = head; | 2050 const SkOpPtT* nextPt = head; |
2070 do { | 2051 do { |
2071 bounds.add(nextPt->fPt); | 2052 bounds.add(nextPt->fPt); |
2072 } while ((nextPt = nextPt->next()) != head); | 2053 } while ((nextPt = nextPt->next()) != head); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 } | 2289 } |
2309 #endif | 2290 #endif |
2310 } | 2291 } |
2311 SkASSERT(count == count2); | 2292 SkASSERT(count == count2); |
2312 return count; | 2293 return count; |
2313 } | 2294 } |
2314 | 2295 |
2315 #include "SkOpContour.h" | 2296 #include "SkOpContour.h" |
2316 | 2297 |
2317 // Commented-out lines keep this in sync with addOpp() | 2298 // Commented-out lines keep this in sync with addOpp() |
2318 bool SkOpPtT::debugAddOpp(const SkOpPtT* opp) const { | 2299 void SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { |
2319 // find the fOpp ptr to opp | 2300 SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); |
2320 const SkOpPtT* oppPrev = opp->fNext; | |
2321 if (oppPrev == this) { | |
2322 return false; | |
2323 } | |
2324 while (oppPrev->fNext != opp) { | |
2325 oppPrev = oppPrev->fNext; | |
2326 if (oppPrev == this) { | |
2327 return false; | |
2328 } | |
2329 } | |
2330 // const SkOpPtT* oldNext = this->fNext; | |
2331 SkASSERT(this != opp); | 2301 SkASSERT(this != opp); |
2332 // this->fNext = opp; | 2302 // this->fNext = opp; |
2333 // SkASSERT(oppPrev != oldNext); | 2303 SkASSERT(oppPrev != oldNext); |
2334 // oppPrev->fNext = oldNext; | 2304 // oppPrev->fNext = oldNext; |
2335 return true; | |
2336 } | 2305 } |
2337 | 2306 |
2338 bool SkOpPtT::debugContains(const SkOpPtT* check) const { | 2307 bool SkOpPtT::debugContains(const SkOpPtT* check) const { |
2339 SkASSERT(this != check); | 2308 SkASSERT(this != check); |
2340 const SkOpPtT* ptT = this; | 2309 const SkOpPtT* ptT = this; |
2341 int links = 0; | 2310 int links = 0; |
2342 do { | 2311 do { |
2343 ptT = ptT->next(); | 2312 ptT = ptT->next(); |
2344 if (ptT == check) { | 2313 if (ptT == check) { |
2345 return true; | 2314 return true; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2396 // by taking a very long time to figure out that no loop entry is a dupl
icate | 2365 // by taking a very long time to figure out that no loop entry is a dupl
icate |
2397 // -- and it's likely that a large loop count is indicative of a bug som
ewhere | 2366 // -- and it's likely that a large loop count is indicative of a bug som
ewhere |
2398 if (++loop > 1000) { | 2367 if (++loop > 1000) { |
2399 SkDebugf("*** loop count exceeds 1000 ***\n"); | 2368 SkDebugf("*** loop count exceeds 1000 ***\n"); |
2400 return 1000; | 2369 return 1000; |
2401 } | 2370 } |
2402 } while ((next = next->fNext) && next != this); | 2371 } while ((next = next->fNext) && next != this); |
2403 return 0; | 2372 return 0; |
2404 } | 2373 } |
2405 | 2374 |
| 2375 const SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { |
| 2376 return this->oppPrev(const_cast<SkOpPtT*>(opp)); |
| 2377 } |
| 2378 |
2406 void SkOpPtT::debugResetCoinT() const { | 2379 void SkOpPtT::debugResetCoinT() const { |
2407 #if DEBUG_COINCIDENCE_ORDER | 2380 #if DEBUG_COINCIDENCE_ORDER |
2408 this->segment()->debugResetCoinT(); | 2381 this->segment()->debugResetCoinT(); |
2409 #endif | 2382 #endif |
2410 } | 2383 } |
2411 | 2384 |
2412 void SkOpPtT::debugSetCoinT(int index) const { | 2385 void SkOpPtT::debugSetCoinT(int index) const { |
2413 #if DEBUG_COINCIDENCE_ORDER | 2386 #if DEBUG_COINCIDENCE_ORDER |
2414 this->segment()->debugSetCoinT(index, fT); | 2387 this->segment()->debugSetCoinT(index, fT); |
2415 #endif | 2388 #endif |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2530 #endif | 2503 #endif |
2531 SkPath::FillType fillType = path.getFillType(); | 2504 SkPath::FillType fillType = path.getFillType(); |
2532 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); | 2505 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); |
2533 if (includeDeclaration) { | 2506 if (includeDeclaration) { |
2534 SkDebugf(" SkPath %s;\n", name); | 2507 SkDebugf(" SkPath %s;\n", name); |
2535 } | 2508 } |
2536 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); | 2509 SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); |
2537 iter.setPath(path); | 2510 iter.setPath(path); |
2538 showPathContours(iter, name); | 2511 showPathContours(iter, name); |
2539 } | 2512 } |
OLD | NEW |