}
void SkOpSegment::addEndSpan(int endIndex) {
+ SkASSERT(span(endIndex).fT == 1 || (span(endIndex).fTiny
+ && approximately_greater_than_one(span(endIndex).fT)));
int spanCount = fTs.count();
int startIndex = endIndex - 1;
while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) {
- ++startIndex;
- SkASSERT(startIndex < spanCount - 1);
- ++endIndex;
+ --startIndex;
+ SkASSERT(startIndex > 0);
+ --endIndex;
}
SkOpAngle& angle = fAngles.push_back();
angle.set(this, spanCount - 1, startIndex);
// FIXME? assert that only one other span has a valid windValue or oppValue
void SkOpSegment::addSimpleAngle(int index) {
SkOpSpan* span = &fTs[index];
- if (index == 0) {
+ int idx;
+ int start, end;
+ if (span->fT == 0) {
+ idx = 0;
+ span = &fTs[0];
do {
if (span->fToAngle) {
SkASSERT(span->fToAngle->loopCount() == 2);
span->fFromAngle = span->fToAngle->next();
return;
}
- span = &fTs[++index];
+ span = &fTs[++idx];
} while (span->fT == 0);
- SkASSERT(index == 1);
- index = 0;
- SkASSERT(!fTs[0].fTiny && fTs[1].fT > 0);
- addStartSpan(1);
+ SkASSERT(!fTs[0].fTiny && fTs[idx].fT > 0);
+ addStartSpan(idx);
+ start = 0;
+ end = idx;
} else {
+ idx = count() - 1;
+ span = &fTs[idx];
do {
if (span->fFromAngle) {
SkASSERT(span->fFromAngle->loopCount() == 2);
span->fToAngle = span->fFromAngle->next();
return;
}
- span = &fTs[--index];
+ span = &fTs[--idx];
} while (span->fT == 1);
- SkASSERT(index == count() - 2);
- index = count() - 1;
- SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1);
- addEndSpan(index);
+ SkASSERT(!fTs[idx].fTiny && fTs[idx].fT < 1);
+ addEndSpan(++idx);
+ start = idx;
+ end = count();
}
- span = &fTs[index];
- SkOpSegment* other = span->fOther;
- SkOpSpan& oSpan = other->fTs[span->fOtherIndex];
+ SkOpSegment* other;
+ SkOpSpan* oSpan;
+ index = start;
+ do {
+ span = &fTs[index];
+ other = span->fOther;
+ int oFrom = span->fOtherIndex;
+ oSpan = &other->fTs[oFrom];
+ if (oSpan->fT < 1 && oSpan->fWindValue) {
+ break;
+ }
+ if (oSpan->fT == 0) {
+ continue;
+ }
+ oFrom = other->nextExactSpan(oFrom, -1);
+ SkOpSpan* oFromSpan = &other->fTs[oFrom];
+ SkASSERT(oFromSpan->fT < 1);
+ if (oFromSpan->fWindValue) {
+ break;
+ }
+ } while (++index < end);
SkOpAngle* angle, * oAngle;
- if (index == 0) {
+ if (span->fT == 0) {
SkASSERT(span->fOtherIndex - 1 >= 0);
SkASSERT(span->fOtherT == 1);
- SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span->fOtherIndex - 1]);
+ SkDEBUGCODE(int oPriorIndex = other->nextExactSpan(span->fOtherIndex, -1));
+ SkDEBUGCODE(const SkOpSpan& oPrior = other->span(oPriorIndex));
SkASSERT(!oPrior.fTiny && oPrior.fT < 1);
other->addEndSpan(span->fOtherIndex);
angle = span->fToAngle;
- oAngle = oSpan.fFromAngle;
+ oAngle = oSpan->fFromAngle;
} else {
SkASSERT(span->fOtherIndex + 1 < other->count());
SkASSERT(span->fOtherT == 0);
- SkASSERT(!oSpan.fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0
+ SkASSERT(!oSpan->fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0
|| (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL
&& other->fTs[span->fOtherIndex + 1].fToAngle == NULL)));
int oIndex = 1;
} while (true);
other->addStartSpan(oIndex);
angle = span->fFromAngle;
- oAngle = oSpan.fToAngle;
+ oAngle = oSpan->fToAngle;
}
angle->insert(oAngle);
}
success = true;
break;
}
- oPeek = &other->fTs[++oPeekIndex];
+ if (++oPeekIndex == oCount) {
+ break;
+ }
+ oPeek = &other->fTs[oPeekIndex];
} while (endPt == oPeek->fPt);
}
if (success) {
}
const SkOpSpan& firstSpan = this->firstSpan(*thisSpan);
const SkOpSpan& lastSpan = this->lastSpan(*thisSpan);
+ const SkOpSpan* nextSpan = &firstSpan + 1;
ptrdiff_t smallCount = &lastSpan - &firstSpan + 1;
SkASSERT(1 <= smallCount && smallCount < count());
- if (smallCount <= 1) {
+ if (smallCount <= 1 && !nextSpan->fSmall) {
SkASSERT(1 == smallCount);
checkSmallCoincidence(firstSpan, NULL);
continue;
int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) const {
int count = this->count();
+ // prefer exact matches over approximate matches
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (span.fT == t && span.fOther == match) {
+ return index;
+ }
+ }
for (int index = 0; index < count; ++index) {
const SkOpSpan& span = fTs[index];
if (approximately_equal_orderable(span.fT, t) && span.fOther == match) {
SkOpSegment* other = this;
while ((other = other->nextChase(&index, &step, &min, &last))) {
if (other->fTs[min].fWindSum != SK_MinS32) {
- SkASSERT(other->fTs[min].fWindSum == winding);
+// SkASSERT(other->fTs[min].fWindSum == winding);
SkASSERT(!last);
break;
}
}
}
+bool SkOpSegment::reversePoints(const SkPoint& p1, const SkPoint& p2) const {
+ SkASSERT(p1 != p2);
+ int spanCount = count();
+ int p1IndexMin = -1;
+ int p2IndexMax = spanCount;
+ for (int index = 0; index < spanCount; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (span.fPt == p1) {
+ if (p1IndexMin < 0) {
+ p1IndexMin = index;
+ }
+ } else if (span.fPt == p2) {
+ p2IndexMax = index;
+ }
+ }
+ return p1IndexMin > p2IndexMax;
+}
+
void SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt,
SkOpSegment* other) {
int count = this->count();