diff options
author | Cary Clark <caryclark@skia.org> | 2018-07-11 11:01:43 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-11 15:30:28 +0000 |
commit | 1857ddbe218afd8ef32f672619ab13c0f853436c (patch) | |
tree | e8d562ec9910743e3020098e8e3c9d02e3305567 | |
parent | cd3e13a130e3d99790e80b329ef6d13591615fe0 (diff) |
propogate simple angles in pathops
If an edge is unsortable, its winding value is untrustworthy;
it cannot be added to the output on that alone. If one end
adjoins a trusted edge, and that edge is added to the output,
the untrusted edge can be added as well.
Also add in msvs debugging for angles.
With this change, all extended tests pass.
TBR=reed@google.com
Bug: skia:8125
Change-Id: I049c6efa2fa83edd7b49cdd598ec94c356481b0f
Reviewed-on: https://skia-review.googlesource.com/140562
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 5 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.h | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.h | 2 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 29 | ||||
-rw-r--r-- | src/pathops/SkPathOpsSimplify.cpp | 26 | ||||
-rw-r--r-- | tests/PathOpsDebug.cpp | 4 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 4 |
7 files changed, 42 insertions, 32 deletions
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index 3bd925c0c3..720b34f597 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -524,13 +524,14 @@ double SkOpSegment::distSq(double t, const SkOpAngle* oppAngle) const { Opposite values result from combining coincident spans. */ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, - SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) { + SkOpSpanBase** nextEnd, bool* unsortable, bool* simple, + SkPathOp op, int xorMiMask, int xorSuMask) { SkOpSpanBase* start = *nextStart; SkOpSpanBase* end = *nextEnd; SkASSERT(start != end); int step = start->step(end); SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart - if (other) { + if ((*simple = other)) { // mark the smaller of startIndex, endIndex done, and all adjacent // spans with the same T value (but not 'other' spans) #if DEBUG_WINDING diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index a38d785250..052a220026 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -212,8 +212,8 @@ public: const SkOpPtT* existing(double t, const SkOpSegment* opp) const; SkOpSegment* findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, - SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, - int xorMiMask, int xorSuMask); + SkOpSpanBase** nextEnd, bool* unsortable, bool* simple, + SkPathOp op, int xorMiMask, int xorSuMask); SkOpSegment* findNextWinding(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable); SkOpSegment* findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable); diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index 724713a74a..035ab14a05 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -481,6 +481,8 @@ namespace SkOpDebug { void Dump(const SkDPoint& ); + void Dump(const SkOpAngle& ); + // dummy declarations to fool msvs Visual Studio 2018 Immediate Window #define DummyDeclarations(a, b) \ void Dump(const SkDebugTCoincident##a##b& ); \ diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index f8b8a65eec..0065c7175a 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -99,8 +99,10 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpanBase*>& chase, SkOpSpanBase** } static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op, - const int xorMask, const int xorOpMask, SkPathWriter* simple) { + const int xorMask, const int xorOpMask, SkPathWriter* writer) { bool unsortable = false; + bool lastSimple = false; + bool simple = false; do { SkOpSpan* span = FindSortableTop(contourList); if (!span) { @@ -119,18 +121,23 @@ static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op, SkASSERT(unsortable || !current->done()); SkOpSpanBase* nextStart = start; SkOpSpanBase* nextEnd = end; + lastSimple = simple; SkOpSegment* next = current->findNextOp(&chase, &nextStart, &nextEnd, - &unsortable, op, xorMask, xorOpMask); + &unsortable, &simple, op, xorMask, xorOpMask); if (!next) { - if (!unsortable && simple->hasMove() + if (!unsortable && writer->hasMove() && current->verb() != SkPath::kLine_Verb - && !simple->isClosed()) { - if (!current->addCurveTo(start, end, simple)) { + && !writer->isClosed()) { + if (!current->addCurveTo(start, end, writer)) { return false; } - if (!simple->isClosed()) { + if (!writer->isClosed()) { SkPathOpsDebug::ShowActiveSpans(contourList); } + } else if (lastSimple) { + if (!current->addCurveTo(start, end, writer)) { + return false; + } } break; } @@ -139,23 +146,23 @@ static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op, current->debugID(), start->pt().fX, start->pt().fY, end->pt().fX, end->pt().fY); #endif - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current = next; start = nextStart; end = nextEnd; - } while (!simple->isClosed() && (!unsortable || !start->starter(end)->done())); - if (current->activeWinding(start, end) && !simple->isClosed()) { + } while (!writer->isClosed() && (!unsortable || !start->starter(end)->done())); + if (current->activeWinding(start, end) && !writer->isClosed()) { SkOpSpan* spanStart = start->starter(end); if (!spanStart->done()) { - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current->markDone(spanStart); } } - simple->finishContour(); + writer->finishContour(); } else { SkOpSpanBase* last; if (!current->markAndChaseDone(start, end, &last)) { diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp index 70f730bf21..dba123d41e 100644 --- a/src/pathops/SkPathOpsSimplify.cpp +++ b/src/pathops/SkPathOpsSimplify.cpp @@ -10,7 +10,7 @@ #include "SkPathOpsCommon.h" #include "SkPathWriter.h" -static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple) { +static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* writer) { bool unsortable = false; do { SkOpSpan* span = FindSortableTop(contourList); @@ -25,7 +25,7 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple) { if (current->activeWinding(start, end)) { do { if (!unsortable && current->done()) { - break; + break; } SkASSERT(unsortable || !current->done()); SkOpSpanBase* nextStart = start; @@ -40,23 +40,23 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple) { current->debugID(), start->pt().fX, start->pt().fY, end->pt().fX, end->pt().fY); #endif - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current = next; start = nextStart; end = nextEnd; - } while (!simple->isClosed() && (!unsortable || !start->starter(end)->done())); - if (current->activeWinding(start, end) && !simple->isClosed()) { + } while (!writer->isClosed() && (!unsortable || !start->starter(end)->done())); + if (current->activeWinding(start, end) && !writer->isClosed()) { SkOpSpan* spanStart = start->starter(end); if (!spanStart->done()) { - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current->markDone(spanStart); } } - simple->finishContour(); + writer->finishContour(); } else { SkOpSpanBase* last; if (!current->markAndChaseDone(start, end, &last)) { @@ -86,7 +86,7 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple) { } // returns true if all edges were processed -static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple) { +static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* writer) { bool unsortable = false; int safetyNet = 1000000; do { @@ -117,23 +117,23 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple) { current->debugID(), start->pt().fX, start->pt().fY, end->pt().fX, end->pt().fY); #endif - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current = next; start = nextStart; end = nextEnd; - } while (!simple->isClosed() && (!unsortable || !start->starter(end)->done())); - if (!simple->isClosed()) { + } while (!writer->isClosed() && (!unsortable || !start->starter(end)->done())); + if (!writer->isClosed()) { SkOpSpan* spanStart = start->starter(end); if (!spanStart->done()) { - if (!current->addCurveTo(start, end, simple)) { + if (!current->addCurveTo(start, end, writer)) { return false; } current->markDone(spanStart); } } - simple->finishContour(); + writer->finishContour(); SkPathOpsDebug::ShowActiveSpans(contourList); } while (true); return true; diff --git a/tests/PathOpsDebug.cpp b/tests/PathOpsDebug.cpp index 942f99c7ae..a93c331cb5 100644 --- a/tests/PathOpsDebug.cpp +++ b/tests/PathOpsDebug.cpp @@ -1639,6 +1639,10 @@ namespace SkOpDebug { point.dump(); } + void Dump(const SkOpAngle& angle) { + angle.dump(); + } + // dummy definitions to fool msvs Visual Studio 2018 Immediate Window #define DummyDefinitions(a, b) \ \ diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 950baaf7b3..0420115ce4 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -5751,11 +5751,7 @@ static void testRect1_u(skiatest::Reporter* reporter, const char* filename) { testPathOp(reporter, path, pathB, kUnion_SkPathOp, filename); } -// this test fails for now; it generates partial paths that are incorrectly -// connected to form an area where it should not. The fix is to connect the -// pieces using only contours that are part of the input data set. static void filinmangust14(skiatest::Reporter* reporter, const char* filename) { - return; SkPath path, path1; path.setFillType(SkPath::kWinding_FillType); path.moveTo(SkBits2Float(0x440bc02c), SkBits2Float(0x4409c000)); // 559.003f, 551 |