| Index: experimental/Intersection/ShapeOps.cpp
|
| diff --git a/experimental/Intersection/ShapeOps.cpp b/experimental/Intersection/ShapeOps.cpp
|
| deleted file mode 100644
|
| index e58a9e69f268fec30b756886cb4948ec25c28a5b..0000000000000000000000000000000000000000
|
| --- a/experimental/Intersection/ShapeOps.cpp
|
| +++ /dev/null
|
| @@ -1,279 +0,0 @@
|
| -/*
|
| - * 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 "Simplify.h"
|
| -
|
| -namespace Op {
|
| -
|
| -#define INCLUDED_BY_SHAPE_OPS 1
|
| -
|
| -#include "Simplify.cpp"
|
| -
|
| -// FIXME: this and find chase should be merge together, along with
|
| -// other code that walks winding in angles
|
| -// OPTIMIZATION: Probably, the walked winding should be rolled into the angle structure
|
| -// so it isn't duplicated by walkers like this one
|
| -static Segment* findChaseOp(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd) {
|
| - while (chase.count()) {
|
| - Span* span;
|
| - chase.pop(&span);
|
| - const Span& backPtr = span->fOther->span(span->fOtherIndex);
|
| - Segment* segment = backPtr.fOther;
|
| - nextStart = backPtr.fOtherIndex;
|
| - SkTDArray<Angle> angles;
|
| - int done = 0;
|
| - if (segment->activeAngle(nextStart, done, angles)) {
|
| - Angle* last = angles.end() - 1;
|
| - nextStart = last->start();
|
| - nextEnd = last->end();
|
| - #if TRY_ROTATE
|
| - *chase.insert(0) = span;
|
| - #else
|
| - *chase.append() = span;
|
| - #endif
|
| - return last->segment();
|
| - }
|
| - if (done == angles.count()) {
|
| - continue;
|
| - }
|
| - SkTDArray<Angle*> sorted;
|
| - bool sortable = Segment::SortAngles(angles, sorted);
|
| - int angleCount = sorted.count();
|
| -#if DEBUG_SORT
|
| - sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0);
|
| -#endif
|
| - if (!sortable) {
|
| - continue;
|
| - }
|
| - // find first angle, initialize winding to computed fWindSum
|
| - int firstIndex = -1;
|
| - const Angle* angle;
|
| - do {
|
| - angle = sorted[++firstIndex];
|
| - segment = angle->segment();
|
| - } while (segment->windSum(angle) == SK_MinS32);
|
| - #if DEBUG_SORT
|
| - segment->debugShowSort(__FUNCTION__, sorted, firstIndex);
|
| - #endif
|
| - int sumMiWinding = segment->updateWindingReverse(angle);
|
| - int sumSuWinding = segment->updateOppWindingReverse(angle);
|
| - if (segment->operand()) {
|
| - SkTSwap<int>(sumMiWinding, sumSuWinding);
|
| - }
|
| - int nextIndex = firstIndex + 1;
|
| - int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
|
| - Segment* first = NULL;
|
| - do {
|
| - SkASSERT(nextIndex != firstIndex);
|
| - if (nextIndex == angleCount) {
|
| - nextIndex = 0;
|
| - }
|
| - angle = sorted[nextIndex];
|
| - segment = angle->segment();
|
| - int start = angle->start();
|
| - int end = angle->end();
|
| - int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
|
| - segment->setUpWindings(start, end, sumMiWinding, sumSuWinding,
|
| - maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
|
| - if (!segment->done(angle)) {
|
| - if (!first) {
|
| - first = segment;
|
| - nextStart = start;
|
| - nextEnd = end;
|
| - }
|
| - (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding,
|
| - oppSumWinding, true, angle);
|
| - }
|
| - } while (++nextIndex != lastIndex);
|
| - if (first) {
|
| - #if TRY_ROTATE
|
| - *chase.insert(0) = span;
|
| - #else
|
| - *chase.append() = span;
|
| - #endif
|
| - return first;
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -/*
|
| -static bool windingIsActive(int winding, int oppWinding, int spanWinding, int oppSpanWinding,
|
| - bool windingIsOp, ShapeOp op) {
|
| - bool active = windingIsActive(winding, spanWinding);
|
| - if (!active) {
|
| - return false;
|
| - }
|
| - if (oppSpanWinding && windingIsActive(oppWinding, oppSpanWinding)) {
|
| - switch (op) {
|
| - case kIntersect_Op:
|
| - case kUnion_Op:
|
| - return true;
|
| - case kDifference_Op: {
|
| - int absSpan = abs(spanWinding);
|
| - int absOpp = abs(oppSpanWinding);
|
| - return windingIsOp ? absSpan < absOpp : absSpan > absOpp;
|
| - }
|
| - case kXor_Op:
|
| - return spanWinding != oppSpanWinding;
|
| - default:
|
| - SkASSERT(0);
|
| - }
|
| - }
|
| - bool opActive = oppWinding != 0;
|
| - return gOpLookup[op][opActive][windingIsOp];
|
| -}
|
| -*/
|
| -
|
| -static bool bridgeOp(SkTDArray<Contour*>& contourList, const ShapeOp op,
|
| - const int xorMask, const int xorOpMask, PathWrapper& simple) {
|
| - bool firstContour = true;
|
| - bool unsortable = false;
|
| - bool topUnsortable = false;
|
| - SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
|
| - do {
|
| - int index, endIndex;
|
| - bool done;
|
| - Segment* current = findSortableTop(contourList, firstContour, index, endIndex, topLeft,
|
| - topUnsortable, done, true);
|
| - if (!current) {
|
| - if (topUnsortable || !done) {
|
| - topUnsortable = false;
|
| - SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
|
| - topLeft.fX = topLeft.fY = SK_ScalarMin;
|
| - continue;
|
| - }
|
| - break;
|
| - }
|
| - SkTDArray<Span*> chaseArray;
|
| - do {
|
| - if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) {
|
| - do {
|
| - #if DEBUG_ACTIVE_SPANS
|
| - if (!unsortable && current->done()) {
|
| - debugShowActiveSpans(contourList);
|
| - }
|
| - #endif
|
| - SkASSERT(unsortable || !current->done());
|
| - int nextStart = index;
|
| - int nextEnd = endIndex;
|
| - Segment* next = current->findNextOp(chaseArray, nextStart, nextEnd,
|
| - unsortable, op, xorMask, xorOpMask);
|
| - 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->markDoneBinary(min);
|
| - }
|
| - }
|
| - simple.close();
|
| - } else {
|
| - Span* last = current->markAndChaseDoneBinary(index, endIndex);
|
| - if (last && !last->fLoop) {
|
| - *chaseArray.append() = last;
|
| - }
|
| - }
|
| - current = findChaseOp(chaseArray, index, endIndex);
|
| - #if DEBUG_ACTIVE_SPANS
|
| - debugShowActiveSpans(contourList);
|
| - #endif
|
| - if (!current) {
|
| - break;
|
| - }
|
| - } while (true);
|
| - } while (true);
|
| - return simple.someAssemblyRequired();
|
| -}
|
| -
|
| -} // end of Op namespace
|
| -
|
| -
|
| -void operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result) {
|
| -#if DEBUG_SORT || DEBUG_SWAP_TOP
|
| - Op::gDebugSortCount = Op::gDebugSortCountDefault;
|
| -#endif
|
| - result.reset();
|
| - result.setFillType(SkPath::kEvenOdd_FillType);
|
| - // turn path into list of segments
|
| - SkTArray<Op::Contour> contours;
|
| - // FIXME: add self-intersecting cubics' T values to segment
|
| - Op::EdgeBuilder builder(one, contours);
|
| - const int xorMask = builder.xorMask();
|
| - builder.addOperand(two);
|
| - builder.finish();
|
| - const int xorOpMask = builder.xorMask();
|
| - SkTDArray<Op::Contour*> contourList;
|
| - makeContourList(contours, contourList, xorMask == kEvenOdd_Mask,
|
| - xorOpMask == kEvenOdd_Mask);
|
| - Op::Contour** currentPtr = contourList.begin();
|
| - if (!currentPtr) {
|
| - return;
|
| - }
|
| - Op::Contour** listEnd = contourList.end();
|
| - // find all intersections between segments
|
| - do {
|
| - Op::Contour** nextPtr = currentPtr;
|
| - Op::Contour* current = *currentPtr++;
|
| - if (current->containsCubics()) {
|
| - addSelfIntersectTs(current);
|
| - }
|
| - Op::Contour* next;
|
| - do {
|
| - next = *nextPtr++;
|
| - } while (addIntersectTs(current, next) && nextPtr != listEnd);
|
| - } while (currentPtr != listEnd);
|
| - // eat through coincident edges
|
| -
|
| - int total = 0;
|
| - int index;
|
| - for (index = 0; index < contourList.count(); ++index) {
|
| - total += contourList[index]->segments().count();
|
| - }
|
| -#if DEBUG_SHOW_WINDING
|
| - Op::Contour::debugShowWindingValues(contourList);
|
| -#endif
|
| - coincidenceCheck(contourList, total);
|
| -#if DEBUG_SHOW_WINDING
|
| - Op::Contour::debugShowWindingValues(contourList);
|
| -#endif
|
| - fixOtherTIndex(contourList);
|
| - sortSegments(contourList);
|
| -#if DEBUG_ACTIVE_SPANS
|
| - debugShowActiveSpans(contourList);
|
| -#endif
|
| - // construct closed contours
|
| - Op::PathWrapper wrapper(result);
|
| - bridgeOp(contourList, op, xorMask, xorOpMask, wrapper);
|
| - { // if some edges could not be resolved, assemble remaining fragments
|
| - SkPath temp;
|
| - temp.setFillType(SkPath::kEvenOdd_FillType);
|
| - Op::PathWrapper assembled(temp);
|
| - assemble(wrapper, assembled);
|
| - result = *assembled.nativePath();
|
| - }
|
| -}
|
|
|