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

Unified Diff: src/pathops/SkOpEdgeBuilder.cpp

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 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 | « src/pathops/SkOpEdgeBuilder.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpEdgeBuilder.cpp
diff --git a/src/pathops/SkOpEdgeBuilder.cpp b/src/pathops/SkOpEdgeBuilder.cpp
index 803a5f4739e238a5426cc7c4fec513cca1faf879..e3dc1398655273d6236da70e086433c5d82d0bc8 100644
--- a/src/pathops/SkOpEdgeBuilder.cpp
+++ b/src/pathops/SkOpEdgeBuilder.cpp
@@ -9,7 +9,7 @@
#include "SkReduceOrder.h"
void SkOpEdgeBuilder::init() {
- fCurrentContour = NULL;
+ fCurrentContour = fContoursHead;
fOperand = false;
fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
: kWinding_PathOpsMask;
@@ -19,32 +19,43 @@ void SkOpEdgeBuilder::init() {
void SkOpEdgeBuilder::addOperand(const SkPath& path) {
SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
- fPathVerbs.pop_back();
+ fPathVerbs.pop();
fPath = &path;
fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
: kWinding_PathOpsMask;
preFetch();
}
-bool SkOpEdgeBuilder::finish() {
- if (fUnparseable || !walk()) {
+int SkOpEdgeBuilder::count() const {
+ SkOpContour* contour = fContoursHead;
+ int count = 0;
+ while (contour) {
+ count += contour->count() > 0;
+ contour = contour->next();
+ }
+ return count;
+}
+
+bool SkOpEdgeBuilder::finish(SkChunkAlloc* allocator) {
+ fOperand = false;
+ if (fUnparseable || !walk(allocator)) {
return false;
}
complete();
- if (fCurrentContour && !fCurrentContour->segments().count()) {
- fContours.pop_back();
+ if (fCurrentContour && !fCurrentContour->count()) {
+ fContoursHead->remove(fCurrentContour);
}
return true;
}
void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curveStart) {
if (!SkDPoint::ApproximatelyEqual(curveEnd, curveStart)) {
- fPathVerbs.push_back(SkPath::kLine_Verb);
- fPathPts.push_back_n(1, &curveStart);
+ *fPathVerbs.append() = SkPath::kLine_Verb;
+ *fPathPts.append() = curveStart;
} else {
fPathPts[fPathPts.count() - 1] = curveStart;
}
- fPathVerbs.push_back(SkPath::kClose_Verb);
+ *fPathVerbs.append() = SkPath::kClose_Verb;
}
// very tiny points cause numerical instability : don't allow them
@@ -57,7 +68,6 @@ static void force_small_to_zero(SkPoint* pt) {
}
}
-
int SkOpEdgeBuilder::preFetch() {
if (!fPath->isFinite()) {
fUnparseable = true;
@@ -78,18 +88,18 @@ int SkOpEdgeBuilder::preFetch() {
if (!fAllowOpenContours && lastCurve) {
closeContour(curve[0], curveStart);
}
- fPathVerbs.push_back(verb);
+ *fPathVerbs.append() = verb;
force_small_to_zero(&pts[0]);
- fPathPts.push_back(pts[0]);
+ *fPathPts.append() = pts[0];
curveStart = curve[0] = pts[0];
lastCurve = false;
continue;
case SkPath::kLine_Verb:
force_small_to_zero(&pts[1]);
if (SkDPoint::ApproximatelyEqual(curve[0], pts[1])) {
- uint8_t lastVerb = fPathVerbs.back();
+ uint8_t lastVerb = fPathVerbs.top();
if (lastVerb != SkPath::kLine_Verb && lastVerb != SkPath::kMove_Verb) {
- fPathPts.back() = pts[1];
+ fPathPts.top() = pts[1];
}
continue; // skip degenerate points
}
@@ -109,9 +119,9 @@ int SkOpEdgeBuilder::preFetch() {
quadderTol);
const int nQuads = quadder.countQuads();
for (int i = 0; i < nQuads; ++i) {
- fPathVerbs.push_back(SkPath::kQuad_Verb);
+ *fPathVerbs.append() = SkPath::kQuad_Verb;
}
- fPathPts.push_back_n(nQuads * 2, &quadPts[1]);
+ fPathPts.append(nQuads * 2, &quadPts[1]);
curve[0] = pts[2];
lastCurve = true;
}
@@ -135,16 +145,16 @@ int SkOpEdgeBuilder::preFetch() {
case SkPath::kDone_Verb:
continue;
}
- fPathVerbs.push_back(verb);
+ *fPathVerbs.append() = verb;
int ptCount = SkPathOpsVerbToPoints(verb);
- fPathPts.push_back_n(ptCount, &pts[1]);
+ fPathPts.append(ptCount, &pts[1]);
curve[0] = pts[ptCount];
lastCurve = true;
} while (verb != SkPath::kDone_Verb);
if (!fAllowOpenContours && lastCurve) {
closeContour(curve[0], curveStart);
}
- fPathVerbs.push_back(SkPath::kDone_Verb);
+ *fPathVerbs.append() = SkPath::kDone_Verb;
return fPathVerbs.count() - 1;
}
@@ -153,10 +163,10 @@ bool SkOpEdgeBuilder::close() {
return true;
}
-bool SkOpEdgeBuilder::walk() {
+bool SkOpEdgeBuilder::walk(SkChunkAlloc* allocator) {
uint8_t* verbPtr = fPathVerbs.begin();
uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
- const SkPoint* pointsPtr = fPathPts.begin() - 1;
+ SkPoint* pointsPtr = fPathPts.begin() - 1;
SkPath::Verb verb;
while ((verb = (SkPath::Verb) *verbPtr) != SkPath::kDone_Verb) {
if (verbPtr == endOfFirstHalf) {
@@ -165,7 +175,7 @@ bool SkOpEdgeBuilder::walk() {
verbPtr++;
switch (verb) {
case SkPath::kMove_Verb:
- if (fCurrentContour) {
+ if (fCurrentContour && fCurrentContour->count()) {
if (fAllowOpenContours) {
complete();
} else if (!close()) {
@@ -173,21 +183,46 @@ bool SkOpEdgeBuilder::walk() {
}
}
if (!fCurrentContour) {
- fCurrentContour = fContours.push_back_n(1);
- fCurrentContour->setOperand(fOperand);
- fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_PathOpsMask);
+ fCurrentContour = fContoursHead->appendContour(allocator);
}
+ fCurrentContour->init(fGlobalState, fOperand,
+ fXorMask[fOperand] == kEvenOdd_PathOpsMask);
pointsPtr += 1;
continue;
case SkPath::kLine_Verb:
- fCurrentContour->addLine(pointsPtr);
+ fCurrentContour->addLine(pointsPtr, fAllocator);
break;
case SkPath::kQuad_Verb:
- fCurrentContour->addQuad(pointsPtr);
- break;
- case SkPath::kCubic_Verb:
- fCurrentContour->addCubic(pointsPtr);
+ fCurrentContour->addQuad(pointsPtr, fAllocator);
break;
+ case SkPath::kCubic_Verb: {
+ // split self-intersecting cubics in two before proceeding
+ // if the cubic is convex, it doesn't self intersect.
+ SkScalar loopT;
+ if (SkDCubic::ComplexBreak(pointsPtr, &loopT)) {
+ SkPoint cubicPair[7];
+ SkChopCubicAt(pointsPtr, cubicPair, loopT);
+ SkPoint cStorage[2][4];
+ SkPath::Verb v1 = SkReduceOrder::Cubic(&cubicPair[0], cStorage[0]);
+ SkPath::Verb v2 = SkReduceOrder::Cubic(&cubicPair[3], cStorage[1]);
+ if (v1 != SkPath::kMove_Verb && v2 != SkPath::kMove_Verb) {
+ SkPoint* curve1 = v1 == SkPath::kCubic_Verb ? &cubicPair[0] : cStorage[0];
+ SkPoint* curve2 = v2 == SkPath::kCubic_Verb ? &cubicPair[3] : cStorage[1];
+ for (int index = 0; index < SkPathOpsVerbToPoints(v1); ++index) {
+ force_small_to_zero(&curve1[index]);
+ }
+ for (int index = 0; index < SkPathOpsVerbToPoints(v2); ++index) {
+ force_small_to_zero(&curve2[index]);
+ }
+ fCurrentContour->addCurve(v1, curve1, fAllocator);
+ fCurrentContour->addCurve(v2, curve2, fAllocator);
+ } else {
+ fCurrentContour->addCubic(pointsPtr, fAllocator);
+ }
+ } else {
+ fCurrentContour->addCubic(pointsPtr, fAllocator);
+ }
+ } break;
case SkPath::kClose_Verb:
SkASSERT(fCurrentContour);
if (!close()) {
@@ -198,10 +233,11 @@ bool SkOpEdgeBuilder::walk() {
SkDEBUGFAIL("bad verb");
return false;
}
- pointsPtr += SkPathOpsVerbToPoints(verb);
SkASSERT(fCurrentContour);
+ fCurrentContour->debugValidate();
+ pointsPtr += SkPathOpsVerbToPoints(verb);
}
- if (fCurrentContour && !fAllowOpenContours && !close()) {
+ if (fCurrentContour && fCurrentContour->count() &&!fAllowOpenContours && !close()) {
return false;
}
return true;
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698