43 const SkOpPtT* origPtT = (this->*getEnd)();
48 if (origPtT != testPtT) {
49 (this->*setEnd)(testPtT);
67 bool expanded =
false;
74 if (!
prev || !(oppPtT =
prev->contains(oppSegment))) {
77 double midT = (
prev->t() +
start->t()) / 2;
78 if (!segment->
isClose(midT, oppSegment)) {
94 double midT = (
end->t() +
next->t()) / 2;
95 if (!segment->
isClose(midT, oppSegment)) {
136 if (
s->segment() == fCoinPtTStart->
segment()) {
137 return fCoinPtTStart->
fT <=
s->fT &&
e->fT <= fCoinPtTEnd->
fT;
140 double oppTs = fOppPtTStart->
fT;
141 double oppTe = fOppPtTEnd->
fT;
146 return oppTs <=
s->fT &&
e->fT <= oppTe;
173 double oppLastT = fOppPtTStart->
fT;
188 if (!
next->upCastable()) {
207 if (!
Ordered(coinPtTStart, oppPtTStart)) {
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);
217 double oppMinT =
std::min(oppPtTStart->
fT, oppPtTEnd->
fT);
220 if (coinSeg !=
test->coinPtTStart()->segment()) {
223 if (oppSeg !=
test->oppPtTStart()->segment()) {
226 double oTestMinT =
std::min(
test->oppPtTStart()->fT,
test->oppPtTEnd()->fT);
227 double oTestMaxT =
std::max(
test->oppPtTStart()->fT,
test->oppPtTEnd()->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);
248 ||
check->oppPtTStart() != oppPtTStart ||
check->oppPtTEnd() != oppPtTEnd);
250 ||
check->oppPtTStart() != coinPtTStart ||
check->oppPtTEnd() != coinPtTEnd);
260 if (!
Ordered(coinPtTStart, oppPtTStart)) {
261 if (oppPtTStart->
fT < oppPtTEnd->
fT) {
262 this->
add(oppPtTStart, oppPtTEnd, coinPtTStart, coinPtTEnd);
264 this->
add(oppPtTEnd, oppPtTStart, coinPtTEnd, coinPtTStart);
270 coinPtTStart = coinPtTStart->
span()->
ptT();
271 coinPtTEnd = coinPtTEnd->
span()->
ptT();
272 oppPtTStart = oppPtTStart->
span()->
ptT();
273 oppPtTEnd = oppPtTEnd->
span()->
ptT();
280 DebugCheckAdd(fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
281 DebugCheckAdd(fTop, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
284 coinRec->
set(this->fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd);
291 const SkOpPtT* stopPtT = testPtT;
293 int escapeHatch = 100000;
294 while ((testPtT = testPtT->
next()) != stopPtT) {
295 if (--escapeHatch <= 0) {
302 if (testSeg == baseSeg) {
305 if (testPtT->
span()->
ptT() != testPtT) {
308 if (this->
contains(baseSeg, testSeg, testPtT->
fT)) {
317 for (
int index = 0; index <
i.used(); ++index) {
318 double t =
i[0][index];
328 if (oppStart == testPtT) {
338 double coinTs, coinTe, oppTs, oppTe;
339 if (
Ordered(coinSeg, oppSeg)) {
341 coinTe = testSpan->
t();
342 oppTs = oppStart->
fT;
346 swap(coinSeg, oppSeg);
347 coinTs = oppStart->
fT;
348 coinTe = testPtT->
fT;
350 oppTe = testSpan->
t();
352 if (coinTs > coinTe) {
354 swap(coinTs, coinTe);
358 FAIL_IF(!this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added));
370 if (!
prev->isCanceled()) {
375 if (!
base->isCanceled()) {
432 }
while ((span = span->
next()));
449 double priorT = startPtT->
fT;
450 double oPriorT = oStartPtT->
fT;
465 while (
test !=
end || oTest != oEnd) {
466 const SkOpPtT* containedOpp =
test->ptT()->contains(oSeg);
468 if (!containedOpp || !containedThis) {
470 double nextT, oNextT;
473 oNextT = containedOpp->
fT;
474 }
else if (containedThis) {
475 nextT = containedThis->
fT;
488 oNextT = walkOpp->
fT;
491 double startRange = nextT - priorT;
493 double startPart = (
test->t() - priorT) / startRange;
494 double oStartRange = oNextT - oPriorT;
496 double oStartPart = (oTest->
t() - oPriorT) / oStartRange;
497 FAIL_IF(startPart == oStartPart);
498 bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart
500 bool startOver =
false;
502 oPriorT + oStartRange * startPart,
test, &startOver)
504 priorT + startRange * oStartPart, oTest, &startOver);
519 oPriorT = oTest->
t();
521 oTest = oTest->
prev();
530 }
while ((coin = coin->
next()));
540double SkOpCoincidence::TRange(
const SkOpPtT* overS,
double t,
543 const SkOpPtT* foundStart =
nullptr;
544 const SkOpPtT* foundEnd =
nullptr;
545 const SkOpPtT* coinStart =
nullptr;
546 const SkOpPtT* coinEnd =
nullptr;
555 if (work->
t() <= t) {
556 coinStart = contained;
557 foundStart = work->
ptT();
559 if (work->
t() >= t) {
561 foundEnd = work->
ptT();
566 if (!coinStart || !coinEnd) {
570 double denom = foundEnd->
fT - foundStart->
fT;
571 double sRatio = denom ? (t - foundStart->
fT) / denom : 1;
572 return coinStart->
fT + (coinEnd->
fT - coinStart->
fT) * sRatio;
578 double coinTs,
double coinTe,
double oppTs,
double oppTe,
580 if (!
Ordered(coinSeg, oppSeg)) {
582 return this->checkOverlap(
check, oppSeg, coinSeg, oppTs, oppTe, coinTs, coinTe,
585 return this->checkOverlap(
check, oppSeg, coinSeg, oppTe, oppTs, coinTe, coinTs, overlaps);
587 bool swapOpp = oppTs > oppTe;
593 if (
check->coinPtTStart()->segment() != coinSeg) {
596 if (
check->oppPtTStart()->segment() != oppSeg) {
599 double checkTs =
check->coinPtTStart()->fT;
600 double checkTe =
check->coinPtTEnd()->fT;
601 bool coinOutside = coinTe < checkTs || coinTs > checkTe;
602 double oCheckTs =
check->oppPtTStart()->fT;
603 double oCheckTe =
check->oppPtTEnd()->fT;
605 if (oCheckTs <= oCheckTe) {
609 swap(oCheckTs, oCheckTe);
611 bool oppOutside = oppTe < oCheckTs || oppTs > oCheckTe;
612 if (coinOutside && oppOutside) {
615 bool coinInside = coinTe <= checkTe && coinTs >= checkTs;
616 bool oppInside = oppTe <= oCheckTe && oppTs >= oCheckTs;
617 if (coinInside && oppInside) {
627bool SkOpCoincidence::addIfMissing(
const SkOpPtT* over1s,
const SkOpPtT* over2s,
643 double coinTs, coinTe, oppTs, oppTe;
656 if (coinTs > coinTe) {
658 swap(coinTs, coinTe);
661 (void) this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added);
669 double coinTs,
double coinTe,
double oppTs,
double oppTe,
bool* added) {
672 if (!this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) {
675 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs,
676 coinTe, oppTs, oppTe, &overlaps)) {
680 for (
int index = 1; index < overlaps.
size(); ++index) {
704 if (overlap && cs && ce && overlap->
contains(cs, ce)) {
710 if (overlap && os && oe && overlap->
contains(os, oe)) {
717 const SkOpPtT* csExisting = !cs ? coinSeg->
existing(coinTs,
nullptr) :
nullptr;
718 const SkOpPtT* ceExisting = !ce ? coinSeg->
existing(coinTe,
nullptr) :
nullptr;
719 FAIL_IF(csExisting && csExisting == ceExisting);
722 FAIL_IF(ceExisting && (ceExisting == cs ||
723 ceExisting->
contains(csExisting ? csExisting : cs)));
724 const SkOpPtT* osExisting = !os ? oppSeg->
existing(oppTs,
nullptr) :
nullptr;
725 const SkOpPtT* oeExisting = !oe ? oppSeg->
existing(oppTe,
nullptr) :
nullptr;
726 FAIL_IF(osExisting && osExisting == oeExisting);
727 FAIL_IF(osExisting && (osExisting == oe ||
728 osExisting->
contains(oeExisting ? oeExisting : oe)));
729 FAIL_IF(oeExisting && (oeExisting == os ||
730 oeExisting->
contains(osExisting ? osExisting : os)));
735 : coinSeg->
addT(coinTs);
736 if (csWritable == ce) {
740 : oppSeg->
addT(oppTs);
741 FAIL_IF(!csWritable || !osWritable);
744 os = osWritable->
active();
750 : coinSeg->
addT(coinTe);
752 : oppSeg->
addT(oppTe);
768 if (os->
fT > oe->
fT) {
775#if DEBUG_COINCIDENCE_VERBOSE
777 overlaps[0]->debugShow();
781 this->
add(cs, ce, os, oe);
782#if DEBUG_COINCIDENCE_VERBOSE
822#ifdef SK_BUILD_FOR_FUZZER
823 int safetyNet = 1000;
825 while ((inner = inner->
next())) {
826#ifdef SK_BUILD_FOR_FUZZER
843 if (outerCoin == innerCoin) {
850 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) {
852 overS, overE, outerOppWritable, innerOppWritable, added
856 }
else if (outerCoin == innerOpp) {
861 if (outerOpp != innerCoin && this->overlap(ocs, oce,
ios, ioe, &overS, &overE)) {
863 overS, overE, outerOppWritable, innerCoinWritable, added
867 }
else if (outerOpp == innerCoin) {
873 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) {
875 overS, overE, outerCoinWritable, innerOppWritable, added
879 }
else if (outerOpp == innerOpp) {
887 if (this->overlap(oos, ooe,
ios, ioe, &overS, &overE)) {
889 overS, overE, outerCoinWritable, innerCoinWritable, added
896 }
while ((outer = outer->
next()));
909 s1 = overS->
find(seg1o);
922 s2 = overS->
find(seg2o);
923 e2 = overE->
find(seg2o);
933 if (s1->
fT >
e1->fT) {
938 this->
add(s1,
e1, s2, e2);
943 if (this->
contains(fHead, seg, opp, oppT)) {
946 if (this->
contains(fTop, seg, opp, oppT)) {
966 }
while ((coin = coin->
next()));
978 if (!
Ordered(coinPtTStart, oppPtTStart)) {
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);
988 double oppMinT =
std::min(oppPtTStart->
fT, oppPtTEnd->
fT);
989 double oppMaxT =
std::max(oppPtTStart->
fT, oppPtTEnd->
fT);
991 if (coinSeg !=
test->coinPtTStart()->segment()) {
994 if (coinPtTStart->
fT <
test->coinPtTStart()->fT) {
997 if (coinPtTEnd->
fT >
test->coinPtTEnd()->fT) {
1000 if (oppSeg !=
test->oppPtTStart()->segment()) {
1022 }
while ((coin = coin->
next()));
1036 if (
start->deleted()) {
1041 bool flipped = coin->
flipped();
1060 if (oNext == oEnd) {
1064 oStart = oNext->
upCast();
1068 int windValue =
start->windValue();
1069 int oppValue =
start->oppValue();
1071 int oOppValue = oStart->
oppValue();
1074 int windDiff = operandSwap ? oOppValue : oWindValue;
1075 int oWindDiff = operandSwap ? oppValue : windValue;
1077 windDiff = -windDiff;
1078 oWindDiff = -oWindDiff;
1080 bool addToStart = windValue && (windValue > windDiff || (windValue == windDiff
1081 && oWindValue <= oWindDiff));
1082 if (addToStart ?
start->done() : oStart->
done()) {
1088 swap(oWindValue, oOppValue);
1091 windValue -= oWindValue;
1092 oppValue -= oOppValue;
1094 windValue += oWindValue;
1095 oppValue += oOppValue;
1097 if (segment->
isXor()) {
1103 oWindValue = oOppValue = 0;
1107 swap(windValue, oppValue);
1110 oWindValue -= windValue;
1111 oOppValue -= oppValue;
1113 oWindValue += windValue;
1114 oOppValue += oppValue;
1116 if (oSegment->
isXor()) {
1119 if (oSegment->
oppXor()) {
1122 windValue = oppValue = 0;
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);
1131 start->setWindValue(windValue);
1132 start->setOppValue(oppValue);
1136 if (!windValue && !oppValue) {
1139 if (!oWindValue && !oOppValue) {
1153 oStart = oNext->
upCast();
1155 }
while ((coin = coin->
next()));
1169 }
else if (
head == fHead) {
1177 }
while ((coin =
next));
1178 return coin !=
nullptr;
1195 }
else if (
head == fHead) {
1205 }
while ((coin =
next));
1213void SkOpCoincidence::restoreHead() {
1216 headPtr = (*headPtr)->
nextPtr();
1224 if (
test->coinPtTStart()->segment()->done() ||
test->oppPtTStart()->segment()->done()) {
1225 *headPtr =
test->next();
1228 headPtr = (*headPtr)->
nextPtr();
1240 bool expanded =
false;
1257 }
while ((coin = coin->
next()));
1263 overlaps->fHead = overlaps->fTop =
nullptr;
1269 while ((inner = inner->
next())) {
1271 if (outerCoin == innerCoin) {
1282 &overlapS, &overlapE))
1285 &overlapS, &overlapE))) {
1286 if (!overlaps->addOverlap(outerCoin, outerOpp, innerCoin, innerOpp,
1287 overlapS, overlapE)) {
1292 outer = outer->
next();
1300 this->
fixUp(fHead, deleted, kept);
1303 this->
fixUp(fTop, deleted, kept);
1338 }
while ((coin = coin->
next()));
1360 bool flipped = coin->
flipped();
1369 end->insertCoinEnd(oEnd);
1378 FAIL_IF(!
next->upCast()->insertCoincidence(oSegment, flipped, ordered));
1380 while ((oNext = oNext->
upCast()->
next()) != oEnd) {
1384 }
while ((coin = coin->
next()));
1401 coin = coin->
next();
1412 if (coinSeg->
verb() < oppSeg->
verb()) {
1415 if (coinSeg->
verb() > oppSeg->
verb()) {
1421 for (
int index = 0; index <
count; ++index) {
1434bool SkOpCoincidence::overlap(
const SkOpPtT* coin1s,
const SkOpPtT* coin1e,
1435 const SkOpPtT* coin2s,
const SkOpPtT* coin2e,
double* overS,
double* overE)
const {
1439 return *overS < *overE;
1455 }
while ((coin = coin->
next()));
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static float next(float f)
static float prev(float f)
#define check(reporter, ref, unref, make, kill)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static void DebugCheckAdd(const SkCoincidentSpans *check, const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
static void(*const CurveIntersectRay[])(const SkPoint[], SkScalar, const SkDLine &, SkIntersections *)
#define DEBUG_COIN_DECLARE_PARAMS()
#define DEBUG_COIN_DECLARE_ONLY_PARAMS()
#define SkDEBUGPARAMS(...)
#define DEBUG_SET_PHASE()
bool between(double a, double b, double c)
bool zero_or_one(double x)
int SkPathOpsVerbToPoints(SkPath::Verb verb)
void swap(sk_sp< T > &a, sk_sp< T > &b)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
const SkOpPtT * oppPtTEnd() const
void setOppPtTEnd(const SkOpPtT *ptT)
bool contains(const SkOpPtT *s, const SkOpPtT *e) const
SkCoincidentSpans * next()
SkOpPtT * oppPtTStartWritable() const
void setCoinPtTStart(const SkOpPtT *ptT)
SkOpPtT * coinPtTStartWritable() const
void setStarts(const SkOpPtT *coinPtTStart, const SkOpPtT *oppPtTStart)
void setEnds(const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTEnd)
const SkOpPtT * coinPtTEnd() const
SkOpPtT * coinPtTEndWritable() const
SkOpPtT * oppPtTEndWritable() const
const SkOpPtT * coinPtTStart() const
void correctOneEnd(const SkOpPtT *(SkCoincidentSpans::*getEnd)() const, void(SkCoincidentSpans::*setEnd)(const SkOpPtT *ptT))
SkCoincidentSpans ** nextPtr()
bool ordered(bool *result) const
void setCoinPtTEnd(const SkOpPtT *ptT)
void setOppPtTStart(const SkOpPtT *ptT)
bool collapsed(const SkOpPtT *) const
const SkOpPtT * oppPtTStart() const
bool extend(const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
void set(SkCoincidentSpans *next, const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
bool addExpanded(DEBUG_COIN_DECLARE_ONLY_PARAMS())
void add(SkOpPtT *coinPtTStart, SkOpPtT *coinPtTEnd, SkOpPtT *oppPtTStart, SkOpPtT *oppPtTEnd)
bool addEndMovedSpans(DEBUG_COIN_DECLARE_ONLY_PARAMS())
bool apply(DEBUG_COIN_DECLARE_ONLY_PARAMS())
void markCollapsed(SkOpPtT *)
bool contains(const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd) const
SkOpGlobalState * globalState()
bool extend(const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
void fixUp(SkOpPtT *deleted, const SkOpPtT *kept)
bool addMissing(bool *added DEBUG_COIN_DECLARE_PARAMS())
static bool Ordered(const SkOpPtT *coinPtTStart, const SkOpPtT *oppPtTStart)
void release(const SkOpSegment *)
void correctEnds(DEBUG_COIN_DECLARE_ONLY_PARAMS())
bool findOverlaps(SkOpCoincidence *DEBUG_COIN_DECLARE_PARAMS()) const
bool expand(DEBUG_COIN_DECLARE_ONLY_PARAMS())
bool mark(DEBUG_COIN_DECLARE_ONLY_PARAMS())
void debugValidate() const
SkArenaAlloc * allocator()
const SkOpSpanBase * span() const
static bool Overlaps(const SkOpPtT *s1, const SkOpPtT *e1, const SkOpPtT *s2, const SkOpPtT *e2, const SkOpPtT **sOut, const SkOpPtT **eOut)
const SkOpPtT * next() const
const SkOpSegment * segment() const
const SkOpPtT * active() const
const SkOpPtT * debugEnder(const SkOpPtT *end) const
const SkOpPtT * find(const SkOpSegment *) const
bool contains(const SkOpPtT *) const
const SkOpPtT * starter(const SkOpPtT *end) const
SkDVector dSlopeAtT(double mid) const
SkOpSpanBase::Collapsed collapsed(double startT, double endT) const
SkPath::Verb verb() const
bool isClose(double t, const SkOpSegment *opp) const
const SkOpPtT * existing(double t, const SkOpSegment *opp) const
const SkPoint * pts() const
void markDone(SkOpSpan *)
bool addExpanded(double newT, const SkOpSpanBase *test, bool *startOver)
const SkOpSpan * prev() const
bool addOpp(SkOpSpanBase *opp)
bool contains(const SkOpSpanBase *) const
const SkOpSpan * starter(const SkOpSpanBase *end) const
SkOpSegment * segment() const
const SkOpPtT * ptT() const
void setWindValue(int windValue)
bool insertCoincidence(const SkOpSegment *, bool flipped, bool ordered)
SkOpSpanBase * next() const
void setOppValue(int oppValue)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
SK_API sk_sp< SkSurface > ios(9.0)
bool approximatelyEqual(const SkDPoint &a) const