aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkPathOpsCommon.cpp
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-05-13 08:23:48 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-05-13 08:23:48 -0700
commitbca19f77479adfd8ba2171753382bc8bf4c2b4ca (patch)
tree767104fcb63f7fab8901f7f7597a12bb78bf2e1e /src/pathops/SkPathOpsCommon.cpp
parent04d24a3f86b6f2382e5c6ffaf161ffc734a4d02a (diff)
deal more consistently with unsortable edges
Improve line/curve coincident detection and resolution. This fixed the remaining simple failures. When an edge is unsortable, use the ray intersection to determine the angles' winding. Deal with degenerate segments. TBR=reed@google.com BUG=skia:3588,skia:3762 Review URL: https://codereview.chromium.org/1140813002
Diffstat (limited to 'src/pathops/SkPathOpsCommon.cpp')
-rw-r--r--src/pathops/SkPathOpsCommon.cpp94
1 files changed, 65 insertions, 29 deletions
diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
index 734b5f0819..98cce15fb2 100644
--- a/src/pathops/SkPathOpsCommon.cpp
+++ b/src/pathops/SkPathOpsCommon.cpp
@@ -11,6 +11,55 @@
#include "SkPathWriter.h"
#include "SkTSort.h"
+const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windingPtr,
+ bool* sortablePtr) {
+ // find first angle, initialize winding to computed fWindSum
+ SkOpSegment* segment = start->segment();
+ const SkOpAngle* angle = segment->spanToAngle(start, end);
+ if (!angle) {
+ *windingPtr = SK_MinS32;
+ return NULL;
+ }
+ bool computeWinding = false;
+ const SkOpAngle* firstAngle = angle;
+ bool loop = false;
+ bool unorderable = false;
+ int winding = SK_MinS32;
+ do {
+ angle = angle->next();
+ unorderable |= angle->unorderable();
+ if ((computeWinding = unorderable || (angle == firstAngle && loop))) {
+ break; // if we get here, there's no winding, loop is unorderable
+ }
+ loop |= angle == firstAngle;
+ segment = angle->segment();
+ winding = segment->windSum(angle);
+ } while (winding == SK_MinS32);
+ // if the angle loop contains an unorderable span, the angle order may be useless
+ // directly compute the winding in this case for each span
+ if (computeWinding) {
+ firstAngle = angle;
+ winding = SK_MinS32;
+ do {
+ SkOpSpanBase* startSpan = angle->start();
+ SkOpSpanBase* endSpan = angle->end();
+ SkOpSpan* lesser = startSpan->starter(endSpan);
+ int testWinding = lesser->windSum();
+ if (testWinding == SK_MinS32) {
+ testWinding = lesser->computeWindSum();
+ }
+ if (testWinding != SK_MinS32) {
+ segment = angle->segment();
+ winding = testWinding;
+ }
+ angle = angle->next();
+ } while (angle != firstAngle);
+ }
+ *sortablePtr = !unorderable;
+ *windingPtr = winding;
+ return angle;
+}
+
SkOpSegment* FindUndone(SkOpContourHead* contourList, SkOpSpanBase** startPtr,
SkOpSpanBase** endPtr) {
SkOpSegment* result;
@@ -31,14 +80,9 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
chase->pop(&span);
SkOpSegment* segment = span->segment();
*startPtr = span->ptT()->next()->span();
- bool sortable = true;
bool done = true;
*endPtr = NULL;
- if (SkOpAngle* last = segment->activeAngle(*startPtr, startPtr, endPtr, &done,
- &sortable)) {
- if (last->unorderable()) {
- continue;
- }
+ if (SkOpAngle* last = segment->activeAngle(*startPtr, startPtr, endPtr, &done)) {
*startPtr = last->start();
*endPtr = last->end();
#if TRY_ROTATE
@@ -51,46 +95,38 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
if (done) {
continue;
}
- if (!sortable) {
- continue;
- }
// find first angle, initialize winding to computed wind sum
- const SkOpAngle* angle = segment->spanToAngle(*startPtr, *endPtr);
- if (!angle) {
+ int winding;
+ bool sortable;
+ const SkOpAngle* angle = AngleWinding(*startPtr, *endPtr, &winding, &sortable);
+ if (winding == SK_MinS32) {
continue;
}
- const SkOpAngle* firstAngle = angle;
- bool loop = false;
- int winding = SK_MinS32;
- do {
- angle = angle->next();
- if (angle == firstAngle && loop) {
- break; // if we get here, there's no winding, loop is unorderable
- }
- loop |= angle == firstAngle;
+ int sumWinding SK_INIT_TO_AVOID_WARNING;
+ if (sortable) {
segment = angle->segment();
- winding = segment->windSum(angle);
- } while (winding == SK_MinS32);
- if (winding == SK_MinS32) {
- continue;
+ sumWinding = segment->updateWindingReverse(angle);
}
- int sumWinding = segment->updateWindingReverse(angle);
SkOpSegment* first = NULL;
- firstAngle = angle;
+ const SkOpAngle* firstAngle = angle;
while ((angle = angle->next()) != firstAngle) {
segment = angle->segment();
SkOpSpanBase* start = angle->start();
SkOpSpanBase* end = angle->end();
int maxWinding;
- segment->setUpWinding(start, end, &maxWinding, &sumWinding);
+ if (sortable) {
+ segment->setUpWinding(start, end, &maxWinding, &sumWinding);
+ }
if (!segment->done(angle)) {
- if (!first) {
+ if (!first && (sortable || start->starter(end)->windSum() != SK_MinS32)) {
first = segment;
*startPtr = start;
*endPtr = end;
}
// OPTIMIZATION: should this also add to the chase?
- (void) segment->markAngle(maxWinding, sumWinding, angle);
+ if (sortable) {
+ (void) segment->markAngle(maxWinding, sumWinding, angle);
+ }
}
}
if (first) {