Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
SkOpCoincidence Class Reference

#include <SkOpCoincidence.h>

Public Member Functions

 SkOpCoincidence (SkOpGlobalState *globalState)
 
void add (SkOpPtT *coinPtTStart, SkOpPtT *coinPtTEnd, SkOpPtT *oppPtTStart, SkOpPtT *oppPtTEnd)
 
bool addEndMovedSpans (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
bool addExpanded (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
bool addMissing (bool *added DEBUG_COIN_DECLARE_PARAMS())
 
bool apply (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
bool contains (const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd) const
 
void correctEnds (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
const SkOpAngledebugAngle (int id) const
 
void debugCheckBetween () const
 
SkOpContourdebugContour (int id) const
 
const SkOpPtTdebugPtT (int id) const
 
const SkOpSegmentdebugSegment (int id) const
 
void debugShowCoincidence () const
 
const SkOpSpanBasedebugSpan (int id) const
 
void debugValidate () const
 
void dump () const
 
bool expand (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
bool extend (const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
 
bool findOverlaps (SkOpCoincidence *DEBUG_COIN_DECLARE_PARAMS()) const
 
void fixUp (SkOpPtT *deleted, const SkOpPtT *kept)
 
SkOpGlobalStateglobalState ()
 
const SkOpGlobalStateglobalState () const
 
bool isEmpty () const
 
bool mark (DEBUG_COIN_DECLARE_ONLY_PARAMS())
 
void markCollapsed (SkOpPtT *)
 
void release (const SkOpSegment *)
 
void releaseDeleted ()
 

Static Public Member Functions

static bool Ordered (const SkOpPtT *coinPtTStart, const SkOpPtT *oppPtTStart)
 
static bool Ordered (const SkOpSegment *coin, const SkOpSegment *opp)
 

Detailed Description

Definition at line 138 of file SkOpCoincidence.h.

Constructor & Destructor Documentation

◆ SkOpCoincidence()

SkOpCoincidence::SkOpCoincidence ( SkOpGlobalState globalState)
inline

Definition at line 140 of file SkOpCoincidence.h.

141 : fHead(nullptr)
142 , fTop(nullptr)
143 , fGlobalState(globalState)
144 , fContinue(false)
145 , fSpanDeleted(false)
146 , fPtAllocated(false)
147 , fCoinExtended(false)
148 , fSpanMerged(false) {
150 }
SkOpGlobalState * globalState()
void setCoincidence(SkOpCoincidence *coincidence)

Member Function Documentation

◆ add()

void SkOpCoincidence::add ( SkOpPtT coinPtTStart,
SkOpPtT coinPtTEnd,
SkOpPtT oppPtTStart,
SkOpPtT oppPtTEnd 
)

Definition at line 257 of file SkOpCoincidence.cpp.

258 {
259 // OPTIMIZE: caller should have already sorted
260 if (!Ordered(coinPtTStart, oppPtTStart)) {
261 if (oppPtTStart->fT < oppPtTEnd->fT) {
262 this->add(oppPtTStart, oppPtTEnd, coinPtTStart, coinPtTEnd);
263 } else {
264 this->add(oppPtTEnd, oppPtTStart, coinPtTEnd, coinPtTStart);
265 }
266 return;
267 }
268 SkASSERT(Ordered(coinPtTStart, oppPtTStart));
269 // choose the ptT at the front of the list to track
270 coinPtTStart = coinPtTStart->span()->ptT();
271 coinPtTEnd = coinPtTEnd->span()->ptT();
272 oppPtTStart = oppPtTStart->span()->ptT();
273 oppPtTEnd = oppPtTEnd->span()->ptT();
274 SkOPASSERT(coinPtTStart->fT < coinPtTEnd->fT);
275 SkOPASSERT(oppPtTStart->fT != oppPtTEnd->fT);
276 SkOPASSERT(!coinPtTStart->deleted());
277 SkOPASSERT(!coinPtTEnd->deleted());
278 SkOPASSERT(!oppPtTStart->deleted());
279 SkOPASSERT(!oppPtTEnd->deleted());
280 DebugCheckAdd(fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
281 DebugCheckAdd(fTop, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
283 coinRec->init(SkDEBUGCODE(fGlobalState));
284 coinRec->set(this->fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
285 fHead = coinRec;
286}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static void DebugCheckAdd(const SkCoincidentSpans *check, const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
#define SkOPASSERT(cond)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
void set(SkCoincidentSpans *next, const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
void add(SkOpPtT *coinPtTStart, SkOpPtT *coinPtTEnd, SkOpPtT *oppPtTStart, SkOpPtT *oppPtTEnd)
static bool Ordered(const SkOpPtT *coinPtTStart, const SkOpPtT *oppPtTStart)
SkArenaAlloc * allocator()
const SkOpSpanBase * span() const
Definition: SkOpSpan.h:154
double fT
Definition: SkOpSpan.h:166
bool deleted() const
Definition: SkOpSpan.h:71
const SkOpPtT * ptT() const
Definition: SkOpSpan.h:310

◆ addEndMovedSpans()

bool SkOpCoincidence::addEndMovedSpans ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 392 of file SkOpCoincidence.cpp.

392 {
394 SkCoincidentSpans* span = fHead;
395 if (!span) {
396 return true;
397 }
398 fTop = span;
399 fHead = nullptr;
400 do {
401 if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) {
402 FAIL_IF(1 == span->coinPtTStart()->fT);
403 bool onEnd = span->coinPtTStart()->fT == 0;
404 bool oOnEnd = zero_or_one(span->oppPtTStart()->fT);
405 if (onEnd) {
406 if (!oOnEnd) { // if both are on end, any nearby intersect was already found
407 if (!this->addEndMovedSpans(span->oppPtTStart())) {
408 return false;
409 }
410 }
411 } else if (oOnEnd) {
412 if (!this->addEndMovedSpans(span->coinPtTStart())) {
413 return false;
414 }
415 }
416 }
417 if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) {
418 bool onEnd = span->coinPtTEnd()->fT == 1;
419 bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT);
420 if (onEnd) {
421 if (!oOnEnd) {
422 if (!this->addEndMovedSpans(span->oppPtTEnd())) {
423 return false;
424 }
425 }
426 } else if (oOnEnd) {
427 if (!this->addEndMovedSpans(span->coinPtTEnd())) {
428 return false;
429 }
430 }
431 }
432 } while ((span = span->next()));
433 this->restoreHead();
434 return true;
435}
#define FAIL_IF(cond)
#define DEBUG_SET_PHASE()
bool zero_or_one(double x)
const SkOpPtT * oppPtTEnd() const
SkCoincidentSpans * next()
const SkOpPtT * coinPtTEnd() const
const SkOpPtT * coinPtTStart() const
const SkOpPtT * oppPtTStart() const
bool addEndMovedSpans(DEBUG_COIN_DECLARE_ONLY_PARAMS())
SkPoint fPt
Definition: SkOpSpan.h:167

◆ addExpanded()

bool SkOpCoincidence::addExpanded ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 440 of file SkOpCoincidence.cpp.

440 {
442 SkCoincidentSpans* coin = this->fHead;
443 if (!coin) {
444 return true;
445 }
446 do {
447 const SkOpPtT* startPtT = coin->coinPtTStart();
448 const SkOpPtT* oStartPtT = coin->oppPtTStart();
449 double priorT = startPtT->fT;
450 double oPriorT = oStartPtT->fT;
451 FAIL_IF(!startPtT->contains(oStartPtT));
452 SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd()));
453 const SkOpSpanBase* start = startPtT->span();
454 const SkOpSpanBase* oStart = oStartPtT->span();
455 const SkOpSpanBase* end = coin->coinPtTEnd()->span();
456 const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span();
457 FAIL_IF(oEnd->deleted());
458 FAIL_IF(!start->upCastable());
459 const SkOpSpanBase* test = start->upCast()->next();
460 FAIL_IF(!coin->flipped() && !oStart->upCastable());
461 const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next();
462 FAIL_IF(!oTest);
463 SkOpSegment* seg = start->segment();
464 SkOpSegment* oSeg = oStart->segment();
465 while (test != end || oTest != oEnd) {
466 const SkOpPtT* containedOpp = test->ptT()->contains(oSeg);
467 const SkOpPtT* containedThis = oTest->ptT()->contains(seg);
468 if (!containedOpp || !containedThis) {
469 // choose the ends, or the first common pt-t list shared by both
470 double nextT, oNextT;
471 if (containedOpp) {
472 nextT = test->t();
473 oNextT = containedOpp->fT;
474 } else if (containedThis) {
475 nextT = containedThis->fT;
476 oNextT = oTest->t();
477 } else {
478 // iterate through until a pt-t list found that contains the other
479 const SkOpSpanBase* walk = test;
480 const SkOpPtT* walkOpp;
481 do {
482 FAIL_IF(!walk->upCastable());
483 walk = walk->upCast()->next();
484 } while (!(walkOpp = walk->ptT()->contains(oSeg))
485 && walk != coin->coinPtTEnd()->span());
486 FAIL_IF(!walkOpp);
487 nextT = walk->t();
488 oNextT = walkOpp->fT;
489 }
490 // use t ranges to guess which one is missing
491 double startRange = nextT - priorT;
492 FAIL_IF(!startRange);
493 double startPart = (test->t() - priorT) / startRange;
494 double oStartRange = oNextT - oPriorT;
495 FAIL_IF(!oStartRange);
496 double oStartPart = (oTest->t() - oPriorT) / oStartRange;
497 FAIL_IF(startPart == oStartPart);
498 bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart
499 : !!containedThis;
500 bool startOver = false;
501 bool success = addToOpp ? oSeg->addExpanded(
502 oPriorT + oStartRange * startPart, test, &startOver)
503 : seg->addExpanded(
504 priorT + startRange * oStartPart, oTest, &startOver);
505 FAIL_IF(!success);
506 if (startOver) {
507 test = start;
508 oTest = oStart;
509 }
510 end = coin->coinPtTEnd()->span();
511 oEnd = coin->oppPtTEnd()->span();
512 }
513 if (test != end) {
514 FAIL_IF(!test->upCastable());
515 priorT = test->t();
516 test = test->upCast()->next();
517 }
518 if (oTest != oEnd) {
519 oPriorT = oTest->t();
520 if (coin->flipped()) {
521 oTest = oTest->prev();
522 } else {
523 FAIL_IF(!oTest->upCastable());
524 oTest = oTest->upCast()->next();
525 }
526 FAIL_IF(!oTest);
527 }
528
529 }
530 } while ((coin = coin->next()));
531 return true;
532}
#define test(name)
bool flipped() const
bool contains(const SkOpPtT *) const
Definition: SkOpSpan.cpp:36
bool addExpanded(double newT, const SkOpSpanBase *test, bool *startOver)
const SkOpSpan * prev() const
Definition: SkOpSpan.h:298
bool deleted() const
Definition: SkOpSpan.h:261
double t() const
Definition: SkOpSpan.h:375
SkOpSpan * upCastable()
Definition: SkOpSpan.h:393
SkOpSpan * upCast()
Definition: SkOpSpan.h:383
SkOpSegment * segment() const
Definition: SkOpSpan.h:318
SkOpSpanBase * next() const
Definition: SkOpSpan.h:495
glong glong end

◆ addMissing()

bool SkOpCoincidence::addMissing ( bool *added   DEBUG_COIN_DECLARE_PARAMS())

Definition at line 797 of file SkOpCoincidence.cpp.

797 {
798 SkCoincidentSpans* outer = fHead;
799 *added = false;
800 if (!outer) {
801 return true;
802 }
803 fTop = outer;
804 fHead = nullptr;
805 do {
806 // addifmissing can modify the list that this is walking
807 // save head so that walker can iterate over old data unperturbed
808 // addifmissing adds to head freely then add saved head in the end
809 const SkOpPtT* ocs = outer->coinPtTStart();
810 FAIL_IF(ocs->deleted());
811 const SkOpSegment* outerCoin = ocs->segment();
812 FAIL_IF(outerCoin->done());
813 const SkOpPtT* oos = outer->oppPtTStart();
814 if (oos->deleted()) {
815 return true;
816 }
817 const SkOpSegment* outerOpp = oos->segment();
818 SkOPASSERT(!outerOpp->done());
819 SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin);
820 SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp);
821 SkCoincidentSpans* inner = outer;
822#ifdef SK_BUILD_FOR_FUZZER
823 int safetyNet = 1000;
824#endif
825 while ((inner = inner->next())) {
826#ifdef SK_BUILD_FOR_FUZZER
827 if (!--safetyNet) {
828 return false;
829 }
830#endif
831 this->debugValidate();
832 double overS, overE;
833 const SkOpPtT* ics = inner->coinPtTStart();
834 FAIL_IF(ics->deleted());
835 const SkOpSegment* innerCoin = ics->segment();
836 FAIL_IF(innerCoin->done());
837 const SkOpPtT* ios = inner->oppPtTStart();
838 FAIL_IF(ios->deleted());
839 const SkOpSegment* innerOpp = ios->segment();
840 SkOPASSERT(!innerOpp->done());
841 SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin);
842 SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp);
843 if (outerCoin == innerCoin) {
844 const SkOpPtT* oce = outer->coinPtTEnd();
845 if (oce->deleted()) {
846 return true;
847 }
848 const SkOpPtT* ice = inner->coinPtTEnd();
849 FAIL_IF(ice->deleted());
850 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) {
851 FAIL_IF(!this->addIfMissing(ocs->starter(oce), ics->starter(ice),
852 overS, overE, outerOppWritable, innerOppWritable, added
853 SkDEBUGPARAMS(ocs->debugEnder(oce))
854 SkDEBUGPARAMS(ics->debugEnder(ice))));
855 }
856 } else if (outerCoin == innerOpp) {
857 const SkOpPtT* oce = outer->coinPtTEnd();
858 FAIL_IF(oce->deleted());
859 const SkOpPtT* ioe = inner->oppPtTEnd();
860 FAIL_IF(ioe->deleted());
861 if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) {
862 FAIL_IF(!this->addIfMissing(ocs->starter(oce), ios->starter(ioe),
863 overS, overE, outerOppWritable, innerCoinWritable, added
864 SkDEBUGPARAMS(ocs->debugEnder(oce))
865 SkDEBUGPARAMS(ios->debugEnder(ioe))));
866 }
867 } else if (outerOpp == innerCoin) {
868 const SkOpPtT* ooe = outer->oppPtTEnd();
869 FAIL_IF(ooe->deleted());
870 const SkOpPtT* ice = inner->coinPtTEnd();
871 FAIL_IF(ice->deleted());
872 SkASSERT(outerCoin != innerOpp);
873 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) {
874 FAIL_IF(!this->addIfMissing(oos->starter(ooe), ics->starter(ice),
875 overS, overE, outerCoinWritable, innerOppWritable, added
876 SkDEBUGPARAMS(oos->debugEnder(ooe))
877 SkDEBUGPARAMS(ics->debugEnder(ice))));
878 }
879 } else if (outerOpp == innerOpp) {
880 const SkOpPtT* ooe = outer->oppPtTEnd();
881 FAIL_IF(ooe->deleted());
882 const SkOpPtT* ioe = inner->oppPtTEnd();
883 if (ioe->deleted()) {
884 return true;
885 }
886 SkASSERT(outerCoin != innerCoin);
887 if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) {
888 FAIL_IF(!this->addIfMissing(oos->starter(ooe), ios->starter(ioe),
889 overS, overE, outerCoinWritable, innerCoinWritable, added
890 SkDEBUGPARAMS(oos->debugEnder(ooe))
891 SkDEBUGPARAMS(ios->debugEnder(ioe))));
892 }
893 }
894 this->debugValidate();
895 }
896 } while ((outer = outer->next()));
897 this->restoreHead();
898 return true;
899}
#define SkDEBUGPARAMS(...)
void debugValidate() const
const SkOpSegment * segment() const
Definition: SkOpSpan.cpp:144
const SkOpPtT * debugEnder(const SkOpPtT *end) const
const SkOpPtT * starter(const SkOpPtT *end) const
Definition: SkOpSpan.h:162
bool done() const
Definition: SkOpSegment.h:200
SK_API sk_sp< SkSurface > ios(9.0)

◆ apply()

bool SkOpCoincidence::apply ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 1026 of file SkOpCoincidence.cpp.

1026 {
1028 SkCoincidentSpans* coin = fHead;
1029 if (!coin) {
1030 return true;
1031 }
1032 do {
1033 SkOpSpanBase* startSpan = coin->coinPtTStartWritable()->span();
1034 FAIL_IF(!startSpan->upCastable());
1035 SkOpSpan* start = startSpan->upCast();
1036 if (start->deleted()) {
1037 continue;
1038 }
1039 const SkOpSpanBase* end = coin->coinPtTEnd()->span();
1040 FAIL_IF(start != start->starter(end));
1041 bool flipped = coin->flipped();
1042 SkOpSpanBase* oStartBase = (flipped ? coin->oppPtTEndWritable()
1043 : coin->oppPtTStartWritable())->span();
1044 FAIL_IF(!oStartBase->upCastable());
1045 SkOpSpan* oStart = oStartBase->upCast();
1046 if (oStart->deleted()) {
1047 continue;
1048 }
1049 const SkOpSpanBase* oEnd = (flipped ? coin->oppPtTStart() : coin->oppPtTEnd())->span();
1050 SkASSERT(oStart == oStart->starter(oEnd));
1051 SkOpSegment* segment = start->segment();
1052 SkOpSegment* oSegment = oStart->segment();
1053 bool operandSwap = segment->operand() != oSegment->operand();
1054 if (flipped) {
1055 if (oEnd->deleted()) {
1056 continue;
1057 }
1058 do {
1059 SkOpSpanBase* oNext = oStart->next();
1060 if (oNext == oEnd) {
1061 break;
1062 }
1063 FAIL_IF(!oNext->upCastable());
1064 oStart = oNext->upCast();
1065 } while (true);
1066 }
1067 do {
1068 int windValue = start->windValue();
1069 int oppValue = start->oppValue();
1070 int oWindValue = oStart->windValue();
1071 int oOppValue = oStart->oppValue();
1072 // winding values are added or subtracted depending on direction and wind type
1073 // same or opposite values are summed depending on the operand value
1074 int windDiff = operandSwap ? oOppValue : oWindValue;
1075 int oWindDiff = operandSwap ? oppValue : windValue;
1076 if (!flipped) {
1077 windDiff = -windDiff;
1078 oWindDiff = -oWindDiff;
1079 }
1080 bool addToStart = windValue && (windValue > windDiff || (windValue == windDiff
1081 && oWindValue <= oWindDiff));
1082 if (addToStart ? start->done() : oStart->done()) {
1083 addToStart ^= true;
1084 }
1085 if (addToStart) {
1086 if (operandSwap) {
1087 using std::swap;
1088 swap(oWindValue, oOppValue);
1089 }
1090 if (flipped) {
1091 windValue -= oWindValue;
1092 oppValue -= oOppValue;
1093 } else {
1094 windValue += oWindValue;
1095 oppValue += oOppValue;
1096 }
1097 if (segment->isXor()) {
1098 windValue &= 1;
1099 }
1100 if (segment->oppXor()) {
1101 oppValue &= 1;
1102 }
1103 oWindValue = oOppValue = 0;
1104 } else {
1105 if (operandSwap) {
1106 using std::swap;
1107 swap(windValue, oppValue);
1108 }
1109 if (flipped) {
1110 oWindValue -= windValue;
1111 oOppValue -= oppValue;
1112 } else {
1113 oWindValue += windValue;
1114 oOppValue += oppValue;
1115 }
1116 if (oSegment->isXor()) {
1117 oWindValue &= 1;
1118 }
1119 if (oSegment->oppXor()) {
1120 oOppValue &= 1;
1121 }
1122 windValue = oppValue = 0;
1123 }
1124#if 0 && DEBUG_COINCIDENCE
1125 SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", segment->debugID(),
1126 start->debugID(), windValue, oppValue);
1127 SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", oSegment->debugID(),
1128 oStart->debugID(), oWindValue, oOppValue);
1129#endif
1130 FAIL_IF(windValue <= -1);
1131 start->setWindValue(windValue);
1132 start->setOppValue(oppValue);
1133 FAIL_IF(oWindValue <= -1);
1134 oStart->setWindValue(oWindValue);
1135 oStart->setOppValue(oOppValue);
1136 if (!windValue && !oppValue) {
1137 segment->markDone(start);
1138 }
1139 if (!oWindValue && !oOppValue) {
1140 oSegment->markDone(oStart);
1141 }
1142 SkOpSpanBase* next = start->next();
1143 SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next();
1144 if (next == end) {
1145 break;
1146 }
1147 FAIL_IF(!next->upCastable());
1148 start = next->upCast();
1149 // if the opposite ran out too soon, just reuse the last span
1150 if (!oNext || !oNext->upCastable()) {
1151 oNext = oStart;
1152 }
1153 oStart = oNext->upCast();
1154 } while (true);
1155 } while ((coin = coin->next()));
1156 return true;
1157}
static float next(float f)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
SkOpPtT * oppPtTStartWritable() const
SkOpPtT * coinPtTStartWritable() const
SkOpPtT * oppPtTEndWritable() const
bool operand() const
int debugID() const
Definition: SkOpSegment.h:154
bool oppXor() const
bool isXor() const
void markDone(SkOpSpan *)
int debugID() const
Definition: SkOpSpan.h:224
const SkOpSpan * starter(const SkOpSpanBase *end) const
Definition: SkOpSpan.h:347
void setWindValue(int windValue)
Definition: SkOpSpan.h:540
void setOppValue(int oppValue)
Definition: SkOpSpan.h:526
int oppValue() const
Definition: SkOpSpan.h:505
bool done() const
Definition: SkOpSpan.h:459
int windValue() const
Definition: SkOpSpan.h:560

◆ contains()

bool SkOpCoincidence::contains ( const SkOpPtT coinPtTStart,
const SkOpPtT coinPtTEnd,
const SkOpPtT oppPtTStart,
const SkOpPtT oppPtTEnd 
) const

Definition at line 970 of file SkOpCoincidence.cpp.

971 {
972 const SkCoincidentSpans* test = fHead;
973 if (!test) {
974 return false;
975 }
976 const SkOpSegment* coinSeg = coinPtTStart->segment();
977 const SkOpSegment* oppSeg = oppPtTStart->segment();
978 if (!Ordered(coinPtTStart, oppPtTStart)) {
979 using std::swap;
980 swap(coinSeg, oppSeg);
981 swap(coinPtTStart, oppPtTStart);
982 swap(coinPtTEnd, oppPtTEnd);
983 if (coinPtTStart->fT > coinPtTEnd->fT) {
984 swap(coinPtTStart, coinPtTEnd);
985 swap(oppPtTStart, oppPtTEnd);
986 }
987 }
988 double oppMinT = std::min(oppPtTStart->fT, oppPtTEnd->fT);
989 double oppMaxT = std::max(oppPtTStart->fT, oppPtTEnd->fT);
990 do {
991 if (coinSeg != test->coinPtTStart()->segment()) {
992 continue;
993 }
994 if (coinPtTStart->fT < test->coinPtTStart()->fT) {
995 continue;
996 }
997 if (coinPtTEnd->fT > test->coinPtTEnd()->fT) {
998 continue;
999 }
1000 if (oppSeg != test->oppPtTStart()->segment()) {
1001 continue;
1002 }
1003 if (oppMinT < std::min(test->oppPtTStart()->fT, test->oppPtTEnd()->fT)) {
1004 continue;
1005 }
1006 if (oppMaxT > std::max(test->oppPtTStart()->fT, test->oppPtTEnd()->fT)) {
1007 continue;
1008 }
1009 return true;
1010 } while ((test = test->next()));
1011 return false;
1012}
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48

◆ correctEnds()

void SkOpCoincidence::correctEnds ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 1014 of file SkOpCoincidence.cpp.

1014 {
1016 SkCoincidentSpans* coin = fHead;
1017 if (!coin) {
1018 return;
1019 }
1020 do {
1021 coin->correctEnds();
1022 } while ((coin = coin->next()));
1023}

◆ debugAngle()

const SkOpAngle * SkOpCoincidence::debugAngle ( int  id) const
inline

Definition at line 172 of file SkOpCoincidence.h.

172 {
173 return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr);
174 }
#define SkDEBUGRELEASE(a, b)

◆ debugCheckBetween()

void SkOpCoincidence::debugCheckBetween ( ) const

Definition at line 2257 of file SkPathOpsDebug.cpp.

2257 {
2258#if DEBUG_COINCIDENCE
2259 if (fGlobalState->debugCheckHealth()) {
2260 return;
2261 }
2262 DebugCheckBetween(fHead, fTop, nullptr);
2263 DebugCheckBetween(fTop, nullptr, nullptr);
2264#endif
2265}

◆ debugContour()

SkOpContour * SkOpCoincidence::debugContour ( int  id) const
inline

Definition at line 182 of file SkOpCoincidence.h.

182 {
183 return SkDEBUGRELEASE(fGlobalState->debugContour(id), nullptr);
184 }

◆ debugPtT()

const SkOpPtT * SkOpCoincidence::debugPtT ( int  id) const
inline

Definition at line 195 of file SkOpCoincidence.h.

195 {
196 return SkDEBUGRELEASE(fGlobalState->debugPtT(id), nullptr);
197 }

◆ debugSegment()

const SkOpSegment * SkOpCoincidence::debugSegment ( int  id) const
inline

Definition at line 199 of file SkOpCoincidence.h.

199 {
200 return SkDEBUGRELEASE(fGlobalState->debugSegment(id), nullptr);
201 }

◆ debugShowCoincidence()

void SkOpCoincidence::debugShowCoincidence ( ) const

Definition at line 2090 of file SkPathOpsDebug.cpp.

2090 {
2091#if DEBUG_COINCIDENCE
2092 const SkCoincidentSpans* span = fHead;
2093 while (span) {
2094 span->debugShow();
2095 span = span->next();
2096 }
2097#endif // DEBUG_COINCIDENCE
2098}
void debugShow() const

◆ debugSpan()

const SkOpSpanBase * SkOpCoincidence::debugSpan ( int  id) const
inline

Definition at line 210 of file SkOpCoincidence.h.

210 {
211 return SkDEBUGRELEASE(fGlobalState->debugSpan(id), nullptr);
212 }

◆ debugValidate()

void SkOpCoincidence::debugValidate ( ) const

Definition at line 2232 of file SkPathOpsDebug.cpp.

2232 {
2233#if DEBUG_COINCIDENCE
2234 DebugValidate(fHead, fTop, nullptr);
2235 DebugValidate(fTop, nullptr, nullptr);
2236#endif
2237}

◆ dump()

void SkOpCoincidence::dump ( ) const

Definition at line 951 of file PathOpsDebug.cpp.

951 {
952 SkCoincidentSpans* span = fHead;
953 while (span) {
954 span->dump();
955 span = span->next();
956 }
957 if (!fTop || fHead == fTop) {
958 return;
959 }
960 SkDebugf("top:\n");
961 span = fTop;
962 int count = 0;
963 while (span) {
964 span->dump();
965 span = span->next();
966 SkCoincidentSpans* check = fTop;
967 ++count;
968 for (int index = 0; index < count; ++index) {
969 if (span == check) {
970 SkDebugf("(loops to #%d)\n", index);
971 return;
972 }
973 check = check->next();
974 }
975 }
976}
int count
Definition: FontMgrTest.cpp:50
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
void dump() const

◆ expand()

bool SkOpCoincidence::expand ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 1234 of file SkOpCoincidence.cpp.

1234 {
1236 SkCoincidentSpans* coin = fHead;
1237 if (!coin) {
1238 return false;
1239 }
1240 bool expanded = false;
1241 do {
1242 if (coin->expand()) {
1243 // check to see if multiple spans expanded so they are now identical
1244 SkCoincidentSpans* test = fHead;
1245 do {
1246 if (coin == test) {
1247 continue;
1248 }
1249 if (coin->coinPtTStart() == test->coinPtTStart()
1250 && coin->oppPtTStart() == test->oppPtTStart()) {
1251 this->release(fHead, test);
1252 break;
1253 }
1254 } while ((test = test->next()));
1255 expanded = true;
1256 }
1257 } while ((coin = coin->next()));
1258 return expanded;
1259}
void release(const SkOpSegment *)

◆ extend()

bool SkOpCoincidence::extend ( const SkOpPtT coinPtTStart,
const SkOpPtT coinPtTEnd,
const SkOpPtT oppPtTStart,
const SkOpPtT oppPtTEnd 
)

Definition at line 199 of file SkOpCoincidence.cpp.

200 {
201 SkCoincidentSpans* test = fHead;
202 if (!test) {
203 return false;
204 }
205 const SkOpSegment* coinSeg = coinPtTStart->segment();
206 const SkOpSegment* oppSeg = oppPtTStart->segment();
207 if (!Ordered(coinPtTStart, oppPtTStart)) {
208 using std::swap;
209 swap(coinSeg, oppSeg);
210 swap(coinPtTStart, oppPtTStart);
211 swap(coinPtTEnd, oppPtTEnd);
212 if (coinPtTStart->fT > coinPtTEnd->fT) {
213 swap(coinPtTStart, coinPtTEnd);
214 swap(oppPtTStart, oppPtTEnd);
215 }
216 }
217 double oppMinT = std::min(oppPtTStart->fT, oppPtTEnd->fT);
218 SkDEBUGCODE(double oppMaxT = std::max(oppPtTStart->fT, oppPtTEnd->fT));
219 do {
220 if (coinSeg != test->coinPtTStart()->segment()) {
221 continue;
222 }
223 if (oppSeg != test->oppPtTStart()->segment()) {
224 continue;
225 }
226 double oTestMinT = std::min(test->oppPtTStart()->fT, test->oppPtTEnd()->fT);
227 double oTestMaxT = std::max(test->oppPtTStart()->fT, test->oppPtTEnd()->fT);
228 // if debug check triggers, caller failed to check if extended already exists
229 SkASSERT(test->coinPtTStart()->fT > coinPtTStart->fT
230 || coinPtTEnd->fT > test->coinPtTEnd()->fT
231 || oTestMinT > oppMinT || oppMaxT > oTestMaxT);
232 if ((test->coinPtTStart()->fT <= coinPtTEnd->fT
233 && coinPtTStart->fT <= test->coinPtTEnd()->fT)
234 || (oTestMinT <= oTestMaxT && oppMinT <= oTestMaxT)) {
235 test->extend(coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
236 return true;
237 }
238 } while ((test = test->next()));
239 return false;
240}

◆ findOverlaps()

bool SkOpCoincidence::findOverlaps ( SkOpCoincidence DEBUG_COIN_DECLARE_PARAMS()) const

Definition at line 1261 of file SkOpCoincidence.cpp.

1261 {
1263 overlaps->fHead = overlaps->fTop = nullptr;
1264 SkCoincidentSpans* outer = fHead;
1265 while (outer) {
1266 const SkOpSegment* outerCoin = outer->coinPtTStart()->segment();
1267 const SkOpSegment* outerOpp = outer->oppPtTStart()->segment();
1268 SkCoincidentSpans* inner = outer;
1269 while ((inner = inner->next())) {
1270 const SkOpSegment* innerCoin = inner->coinPtTStart()->segment();
1271 if (outerCoin == innerCoin) {
1272 continue; // both winners are the same segment, so there's no additional overlap
1273 }
1274 const SkOpSegment* innerOpp = inner->oppPtTStart()->segment();
1275 const SkOpPtT* overlapS;
1276 const SkOpPtT* overlapE;
1277 if ((outerOpp == innerCoin && SkOpPtT::Overlaps(outer->oppPtTStart(),
1278 outer->oppPtTEnd(),inner->coinPtTStart(), inner->coinPtTEnd(), &overlapS,
1279 &overlapE))
1280 || (outerCoin == innerOpp && SkOpPtT::Overlaps(outer->coinPtTStart(),
1281 outer->coinPtTEnd(), inner->oppPtTStart(), inner->oppPtTEnd(),
1282 &overlapS, &overlapE))
1283 || (outerOpp == innerOpp && SkOpPtT::Overlaps(outer->oppPtTStart(),
1284 outer->oppPtTEnd(), inner->oppPtTStart(), inner->oppPtTEnd(),
1285 &overlapS, &overlapE))) {
1286 if (!overlaps->addOverlap(outerCoin, outerOpp, innerCoin, innerOpp,
1287 overlapS, overlapE)) {
1288 return false;
1289 }
1290 }
1291 }
1292 outer = outer->next();
1293 }
1294 return true;
1295}
static bool Overlaps(const SkOpPtT *s1, const SkOpPtT *e1, const SkOpPtT *s2, const SkOpPtT *e2, const SkOpPtT **sOut, const SkOpPtT **eOut)
Definition: SkOpSpan.h:119

◆ fixUp()

void SkOpCoincidence::fixUp ( SkOpPtT deleted,
const SkOpPtT kept 
)

Definition at line 1297 of file SkOpCoincidence.cpp.

1297 {
1298 SkOPASSERT(deleted != kept);
1299 if (fHead) {
1300 this->fixUp(fHead, deleted, kept);
1301 }
1302 if (fTop) {
1303 this->fixUp(fTop, deleted, kept);
1304 }
1305}
void fixUp(SkOpPtT *deleted, const SkOpPtT *kept)

◆ globalState() [1/2]

SkOpGlobalState * SkOpCoincidence::globalState ( )
inline

Definition at line 222 of file SkOpCoincidence.h.

222 {
223 return fGlobalState;
224 }

◆ globalState() [2/2]

const SkOpGlobalState * SkOpCoincidence::globalState ( ) const
inline

Definition at line 226 of file SkOpCoincidence.h.

226 {
227 return fGlobalState;
228 }

◆ isEmpty()

bool SkOpCoincidence::isEmpty ( ) const
inline

Definition at line 230 of file SkOpCoincidence.h.

230 {
231 return !fHead && !fTop;
232 }

◆ mark()

bool SkOpCoincidence::mark ( DEBUG_COIN_DECLARE_ONLY_PARAMS()  )

Definition at line 1343 of file SkOpCoincidence.cpp.

1343 {
1345 SkCoincidentSpans* coin = fHead;
1346 if (!coin) {
1347 return true;
1348 }
1349 do {
1350 SkOpSpanBase* startBase = coin->coinPtTStartWritable()->span();
1351 FAIL_IF(!startBase->upCastable());
1352 SkOpSpan* start = startBase->upCast();
1353 FAIL_IF(start->deleted());
1355 SkOPASSERT(!end->deleted());
1356 SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span();
1357 SkOPASSERT(!oStart->deleted());
1358 SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span();
1359 FAIL_IF(oEnd->deleted());
1360 bool flipped = coin->flipped();
1361 if (flipped) {
1362 using std::swap;
1363 swap(oStart, oEnd);
1364 }
1365 /* coin and opp spans may not match up. Mark the ends, and then let the interior
1366 get marked as many times as the spans allow */
1367 FAIL_IF(!oStart->upCastable());
1368 start->insertCoincidence(oStart->upCast());
1369 end->insertCoinEnd(oEnd);
1370 const SkOpSegment* segment = start->segment();
1371 const SkOpSegment* oSegment = oStart->segment();
1373 SkOpSpanBase* oNext = oStart;
1374 bool ordered;
1375 FAIL_IF(!coin->ordered(&ordered));
1376 while ((next = next->upCast()->next()) != end) {
1377 FAIL_IF(!next->upCastable());
1378 FAIL_IF(!next->upCast()->insertCoincidence(oSegment, flipped, ordered));
1379 }
1380 while ((oNext = oNext->upCast()->next()) != oEnd) {
1381 FAIL_IF(!oNext->upCastable());
1382 FAIL_IF(!oNext->upCast()->insertCoincidence(segment, flipped, ordered));
1383 }
1384 } while ((coin = coin->next()));
1385 return true;
1386}
SkOpPtT * coinPtTEndWritable() const
bool ordered(bool *result) const
bool insertCoincidence(const SkOpSegment *, bool flipped, bool ordered)
Definition: SkOpSpan.cpp:413

◆ markCollapsed()

void SkOpCoincidence::markCollapsed ( SkOpPtT test)

Definition at line 1406 of file SkOpCoincidence.cpp.

1406 {
1407 markCollapsed(fHead, test);
1408 markCollapsed(fTop, test);
1409}
void markCollapsed(SkOpPtT *)

◆ Ordered() [1/2]

static bool SkOpCoincidence::Ordered ( const SkOpPtT coinPtTStart,
const SkOpPtT oppPtTStart 
)
inlinestatic

Definition at line 237 of file SkOpCoincidence.h.

237 {
238 return Ordered(coinPtTStart->segment(), oppPtTStart->segment());
239 }

◆ Ordered() [2/2]

bool SkOpCoincidence::Ordered ( const SkOpSegment coin,
const SkOpSegment opp 
)
static

Definition at line 1411 of file SkOpCoincidence.cpp.

1411 {
1412 if (coinSeg->verb() < oppSeg->verb()) {
1413 return true;
1414 }
1415 if (coinSeg->verb() > oppSeg->verb()) {
1416 return false;
1417 }
1418 int count = (SkPathOpsVerbToPoints(coinSeg->verb()) + 1) * 2;
1419 const SkScalar* cPt = &coinSeg->pts()[0].fX;
1420 const SkScalar* oPt = &oppSeg->pts()[0].fX;
1421 for (int index = 0; index < count; ++index) {
1422 if (*cPt < *oPt) {
1423 return true;
1424 }
1425 if (*cPt > *oPt) {
1426 return false;
1427 }
1428 ++cPt;
1429 ++oPt;
1430 }
1431 return true;
1432}
int SkPathOpsVerbToPoints(SkPath::Verb verb)
float SkScalar
Definition: extension.cpp:12

◆ release()

void SkOpCoincidence::release ( const SkOpSegment deleted)

Definition at line 1443 of file SkOpCoincidence.cpp.

1443 {
1444 SkCoincidentSpans* coin = fHead;
1445 if (!coin) {
1446 return;
1447 }
1448 do {
1449 if (coin->coinPtTStart()->segment() == deleted
1450 || coin->coinPtTEnd()->segment() == deleted
1451 || coin->oppPtTStart()->segment() == deleted
1452 || coin->oppPtTEnd()->segment() == deleted) {
1453 this->release(fHead, coin);
1454 }
1455 } while ((coin = coin->next()));
1456}

◆ releaseDeleted()

void SkOpCoincidence::releaseDeleted ( )

Definition at line 1208 of file SkOpCoincidence.cpp.

1208 {
1209 this->releaseDeleted(fHead);
1210 this->releaseDeleted(fTop);
1211}

The documentation for this class was generated from the following files: