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

Unified Diff: src/pathops/SkPathOpsSimplify.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/SkPathOpsOp.cpp ('k') | src/pathops/SkPathOpsSpan.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkPathOpsSimplify.cpp
===================================================================
--- src/pathops/SkPathOpsSimplify.cpp (revision 0)
+++ src/pathops/SkPathOpsSimplify.cpp (revision 0)
@@ -0,0 +1,195 @@
+/*
+ * 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 "SkAddIntersections.h"
+#include "SkOpEdgeBuilder.h"
+#include "SkPathOpsCommon.h"
+#include "SkPathWriter.h"
+
+static bool bridgeWinding(SkTDArray<SkOpContour*>& contourList, SkPathWriter& simple) {
+ bool firstContour = true;
+ bool unsortable = false;
+ bool topUnsortable = false;
+ SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
+ do {
+ int index, endIndex;
+ bool topDone;
+ SkOpSegment* current = FindSortableTop(contourList, firstContour, index, endIndex, topLeft,
+ topUnsortable, topDone, false);
+ if (!current) {
+ if (topUnsortable || !topDone) {
+ topUnsortable = false;
+ SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
+ topLeft.fX = topLeft.fY = SK_ScalarMin;
+ continue;
+ }
+ break;
+ }
+ SkTDArray<SkOpSpan*> chaseArray;
+ do {
+ if (current->activeWinding(index, endIndex)) {
+ do {
+ #if DEBUG_ACTIVE_SPANS
+ if (!unsortable && current->done()) {
+ DebugShowActiveSpans(contourList);
+ }
+ #endif
+ SkASSERT(unsortable || !current->done());
+ int nextStart = index;
+ int nextEnd = endIndex;
+ SkOpSegment* next = current->findNextWinding(chaseArray, nextStart, nextEnd,
+ unsortable);
+ if (!next) {
+ if (!unsortable && simple.hasMove()
+ && current->verb() != SkPath::kLine_Verb
+ && !simple.isClosed()) {
+ current->addCurveTo(index, endIndex, simple, true);
+ SkASSERT(simple.isClosed());
+ }
+ break;
+ }
+ #if DEBUG_FLOW
+ SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
+ current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY,
+ current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY);
+ #endif
+ current->addCurveTo(index, endIndex, simple, true);
+ current = next;
+ index = nextStart;
+ endIndex = nextEnd;
+ } while (!simple.isClosed() && (!unsortable
+ || !current->done(SkMin32(index, endIndex))));
+ if (current->activeWinding(index, endIndex) && !simple.isClosed()) {
+ SkASSERT(unsortable);
+ int min = SkMin32(index, endIndex);
+ if (!current->done(min)) {
+ current->addCurveTo(index, endIndex, simple, true);
+ current->markDoneUnary(min);
+ }
+ }
+ simple.close();
+ } else {
+ SkOpSpan* last = current->markAndChaseDoneUnary(index, endIndex);
+ if (last && !last->fLoop) {
+ *chaseArray.append() = last;
+ }
+ }
+ current = FindChase(chaseArray, index, endIndex);
+ #if DEBUG_ACTIVE_SPANS
+ DebugShowActiveSpans(contourList);
+ #endif
+ if (!current) {
+ break;
+ }
+ } while (true);
+ } while (true);
+ return simple.someAssemblyRequired();
+}
+
+// returns true if all edges were processed
+static bool bridgeXor(SkTDArray<SkOpContour*>& contourList, SkPathWriter& simple) {
+ SkOpSegment* current;
+ int start, end;
+ bool unsortable = false;
+ bool closable = true;
+ while ((current = FindUndone(contourList, start, end))) {
+ do {
+ #if DEBUG_ACTIVE_SPANS
+ if (!unsortable && current->done()) {
+ DebugShowActiveSpans(contourList);
+ }
+ #endif
+ SkASSERT(unsortable || !current->done());
+ int nextStart = start;
+ int nextEnd = end;
+ SkOpSegment* next = current->findNextXor(nextStart, nextEnd, unsortable);
+ if (!next) {
+ if (!unsortable && simple.hasMove()
+ && current->verb() != SkPath::kLine_Verb
+ && !simple.isClosed()) {
+ current->addCurveTo(start, end, simple, true);
+ SkASSERT(simple.isClosed());
+ }
+ break;
+ }
+ #if DEBUG_FLOW
+ SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
+ current->debugID(), current->xyAtT(start).fX, current->xyAtT(start).fY,
+ current->xyAtT(end).fX, current->xyAtT(end).fY);
+ #endif
+ current->addCurveTo(start, end, simple, true);
+ current = next;
+ start = nextStart;
+ end = nextEnd;
+ } while (!simple.isClosed() && (!unsortable || !current->done(SkMin32(start, end))));
+ if (!simple.isClosed()) {
+ SkASSERT(unsortable);
+ int min = SkMin32(start, end);
+ if (!current->done(min)) {
+ current->addCurveTo(start, end, simple, true);
+ current->markDone(min, 1);
+ }
+ closable = false;
+ }
+ simple.close();
+ #if DEBUG_ACTIVE_SPANS
+ DebugShowActiveSpans(contourList);
+ #endif
+ }
+ return closable;
+}
+
+// FIXME : add this as a member of SkPath
+void Simplify(const SkPath& path, SkPath* result) {
+#if DEBUG_SORT || DEBUG_SWAP_TOP
+ gDebugSortCount = gDebugSortCountDefault;
+#endif
+ // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
+ result->reset();
+ result->setFillType(SkPath::kEvenOdd_FillType);
+ SkPathWriter simple(*result);
+
+ // turn path into list of segments
+ SkTArray<SkOpContour> contours;
+ SkOpEdgeBuilder builder(path, contours);
+ builder.finish();
+ SkTDArray<SkOpContour*> contourList;
+ MakeContourList(contours, contourList, false, false);
+ SkOpContour** currentPtr = contourList.begin();
+ if (!currentPtr) {
+ return;
+ }
+ SkOpContour** listEnd = contourList.end();
+ // find all intersections between segments
+ do {
+ SkOpContour** nextPtr = currentPtr;
+ SkOpContour* current = *currentPtr++;
+ if (current->containsCubics()) {
+ AddSelfIntersectTs(current);
+ }
+ SkOpContour* next;
+ do {
+ next = *nextPtr++;
+ } while (AddIntersectTs(current, next) && nextPtr != listEnd);
+ } while (currentPtr != listEnd);
+ // eat through coincident edges
+ CoincidenceCheck(contourList, 0);
+ FixOtherTIndex(contourList);
+ SortSegments(contourList);
+#if DEBUG_ACTIVE_SPANS
+ DebugShowActiveSpans(contourList);
+#endif
+ // construct closed contours
+ if (builder.xorMask() == kWinding_PathOpsMask ? bridgeWinding(contourList, simple)
+ : !bridgeXor(contourList, simple))
+ { // if some edges could not be resolved, assemble remaining fragments
+ SkPath temp;
+ temp.setFillType(SkPath::kEvenOdd_FillType);
+ SkPathWriter assembled(temp);
+ Assemble(simple, assembled);
+ *result = *assembled.nativePath();
+ }
+}
« no previous file with comments | « src/pathops/SkPathOpsOp.cpp ('k') | src/pathops/SkPathOpsSpan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698