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

Unified Diff: src/pathops/SkOpEdgeBuilder.cpp

Issue 13094010: Add implementation of path ops (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 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
===================================================================
--- src/pathops/SkOpEdgeBuilder.cpp (revision 0)
+++ src/pathops/SkOpEdgeBuilder.cpp (revision 0)
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkOpEdgeBuilder.h"
+#include "SkReduceOrder.h"
+
+void SkOpEdgeBuilder::init() {
+ fCurrentContour = NULL;
+ fOperand = false;
+ fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
+ : kWinding_PathOpsMask;
+#if DEBUG_DUMP
+ gContourID = 0;
+ gSegmentID = 0;
+#endif
+ fSecondHalf = preFetch();
+}
+
+void SkOpEdgeBuilder::addOperand(const SkPath& path) {
+ SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
+ fPathVerbs.pop();
+ fPath = &path;
+ fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
+ : kWinding_PathOpsMask;
+ preFetch();
+}
+
+void SkOpEdgeBuilder::finish() {
+ walk();
+ complete();
+ if (fCurrentContour && !fCurrentContour->segments().count()) {
+ fContours.pop_back();
+ }
+ // correct pointers in contours since fReducePts may have moved as it grew
+ int cIndex = 0;
+ int extraCount = fExtra.count();
+ SkASSERT(extraCount == 0 || fExtra[0] == -1);
+ int eIndex = 0;
+ int rIndex = 0;
+ while (++eIndex < extraCount) {
+ int offset = fExtra[eIndex];
+ if (offset < 0) {
+ ++cIndex;
+ continue;
+ }
+ fCurrentContour = &fContours[cIndex];
+ rIndex += fCurrentContour->updateSegment(offset - 1,
+ &fReducePts[rIndex]);
+ }
+ fExtra.reset(); // we're done with this
+}
+
+// FIXME:remove once we can access path pts directly
+int SkOpEdgeBuilder::preFetch() {
+ SkPath::RawIter iter(*fPath); // FIXME: access path directly when allowed
+ SkPoint pts[4];
+ SkPath::Verb verb;
+ do {
+ verb = iter.next(pts);
+ *fPathVerbs.append() = verb;
+ if (verb == SkPath::kMove_Verb) {
+ *fPathPts.append() = pts[0];
+ } else if (verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
+ fPathPts.append(verb, &pts[1]);
+ }
+ } while (verb != SkPath::kDone_Verb);
+ return fPathVerbs.count() - 1;
+}
+
+void SkOpEdgeBuilder::walk() {
+ SkPath::Verb reducedVerb;
+ uint8_t* verbPtr = fPathVerbs.begin();
+ uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
+ const SkPoint* pointsPtr = fPathPts.begin();
+ const SkPoint* finalCurveStart = NULL;
+ const SkPoint* finalCurveEnd = NULL;
+ SkPath::Verb verb;
+ while ((verb = (SkPath::Verb) *verbPtr++) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ complete();
+ if (!fCurrentContour) {
+ fCurrentContour = fContours.push_back_n(1);
+ fCurrentContour->setOperand(fOperand);
+ fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_PathOpsMask);
+ *fExtra.append() = -1; // start new contour
+ }
+ finalCurveEnd = pointsPtr++;
+ goto nextVerb;
+ case SkPath::kLine_Verb:
+ // skip degenerate points
+ if (pointsPtr[-1].fX != pointsPtr[0].fX || pointsPtr[-1].fY != pointsPtr[0].fY) {
+ fCurrentContour->addLine(&pointsPtr[-1]);
+ }
+ break;
+ case SkPath::kQuad_Verb:
+ reducedVerb = SkReduceOrder::Quad(&pointsPtr[-1], &fReducePts);
+ if (reducedVerb == 0) {
+ break; // skip degenerate points
+ }
+ if (reducedVerb == 1) {
+ *fExtra.append() =
+ fCurrentContour->addLine(fReducePts.end() - 2);
+ break;
+ }
+ fCurrentContour->addQuad(&pointsPtr[-1]);
+ break;
+ case SkPath::kCubic_Verb:
+ reducedVerb = SkReduceOrder::Cubic(&pointsPtr[-1], &fReducePts);
+ if (reducedVerb == 0) {
+ break; // skip degenerate points
+ }
+ if (reducedVerb == 1) {
+ *fExtra.append() = fCurrentContour->addLine(fReducePts.end() - 2);
+ break;
+ }
+ if (reducedVerb == 2) {
+ *fExtra.append() = fCurrentContour->addQuad(fReducePts.end() - 3);
+ break;
+ }
+ fCurrentContour->addCubic(&pointsPtr[-1]);
+ break;
+ case SkPath::kClose_Verb:
+ SkASSERT(fCurrentContour);
+ if (finalCurveStart && finalCurveEnd
+ && *finalCurveStart != *finalCurveEnd) {
+ *fReducePts.append() = *finalCurveStart;
+ *fReducePts.append() = *finalCurveEnd;
+ *fExtra.append() = fCurrentContour->addLine(fReducePts.end() - 2);
+ }
+ complete();
+ goto nextVerb;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ finalCurveStart = &pointsPtr[verb - 1];
+ pointsPtr += verb;
+ SkASSERT(fCurrentContour);
+ nextVerb:
+ if (verbPtr == endOfFirstHalf) {
+ fOperand = 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