Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Unified Diff: src/pathops/SkOpBuilder.cpp

Issue 1129193006: fix winding for path ops builder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix compile bug Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/pathops/SkOpContour.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpBuilder.cpp
diff --git a/src/pathops/SkOpBuilder.cpp b/src/pathops/SkOpBuilder.cpp
index 1a446f15b61c2f16217b88bf6ae1f26bc4895691..39da2efbcee7a727b70b08b192de52112323b30f 100644
--- a/src/pathops/SkOpBuilder.cpp
+++ b/src/pathops/SkOpBuilder.cpp
@@ -6,8 +6,80 @@
*/
#include "SkMatrix.h"
+#include "SkOpEdgeBuilder.h"
#include "SkPath.h"
#include "SkPathOps.h"
+#include "SkPathOpsCommon.h"
+
+static bool one_contour(const SkPath& path) {
+ SkChunkAlloc allocator(256);
+ int verbCount = path.countVerbs();
+ uint8_t* verbs = (uint8_t*) allocator.alloc(sizeof(uint8_t) * verbCount,
+ SkChunkAlloc::kThrow_AllocFailType);
+ (void) path.getVerbs(verbs, verbCount);
+ for (int index = 1; index < verbCount; ++index) {
+ if (verbs[index] == SkPath::kMove_Verb) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void FixWinding(SkPath* path) {
+ SkPath::FillType fillType = path->getFillType();
+ if (fillType == SkPath::kInverseEvenOdd_FillType) {
+ fillType = SkPath::kInverseWinding_FillType;
+ } else if (fillType == SkPath::kEvenOdd_FillType) {
+ fillType = SkPath::kWinding_FillType;
+ }
+ SkPath::Direction dir;
+ if (one_contour(*path) && path->cheapComputeDirection(&dir)) {
+ if (dir != SkPath::kCCW_Direction) {
+ SkPath temp;
+ temp.reverseAddPath(*path);
+ *path = temp;
+ }
+ path->setFillType(fillType);
+ return;
+ }
+ SkChunkAlloc allocator(4096);
+ SkOpContourHead contourHead;
+ SkOpGlobalState globalState(NULL, &contourHead);
+ SkOpEdgeBuilder builder(*path, &contourHead, &allocator, &globalState);
+ builder.finish(&allocator);
+ SkASSERT(contourHead.next());
+ contourHead.resetReverse();
+ bool writePath = false;
+ SkOpSpan* topSpan;
+ globalState.setPhase(SkOpGlobalState::kFixWinding);
+ while ((topSpan = FindSortableTop(&contourHead))) {
+ SkOpSegment* topSegment = topSpan->segment();
+ SkOpContour* topContour = topSegment->contour();
+ bool active = topSegment->activeWinding(topSpan, topSpan->next());
+ SkASSERT(topContour->isCcw() >= 0);
+ if (active != SkToBool(topContour->isCcw())) {
+ topContour->setReverse();
+ writePath = true;
+ }
+ topContour->markDone();
+ }
+ if (!writePath) {
+ path->setFillType(fillType);
+ return;
+ }
+ SkPath empty;
+ SkPathWriter woundPath(empty);
+ SkOpContour* test = &contourHead;
+ do {
+ if (test->reversed()) {
+ test->toReversePath(&woundPath);
+ } else {
+ test->toPath(&woundPath);
+ }
+ } while ((test = test->next()));
+ *path = *woundPath.nativePath();
+ path->setFillType(fillType);
+}
void SkOpBuilder::add(const SkPath& path, SkPathOp op) {
if (0 == fOps.count() && op != kUnion_SkPathOp) {
@@ -82,10 +154,11 @@ bool SkOpBuilder::resolve(SkPath* result) {
*result = original;
return false;
}
+ // convert the even odd result back to winding form before accumulating it
+ FixWinding(&fPathRefs[index]);
sum.addPath(fPathRefs[index]);
}
reset();
- sum.setFillType(SkPath::kEvenOdd_FillType);
bool success = Simplify(sum, result);
if (!success) {
*result = original;
« no previous file with comments | « no previous file | src/pathops/SkOpContour.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698