diff options
author | caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-22 14:37:05 +0000 |
---|---|---|
committer | caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-22 14:37:05 +0000 |
commit | 7dfbb0720a133c0f63ac7be504f335bbcc62a291 (patch) | |
tree | 819a38446c52c07f941e2bf09ec236823f1032f3 /src | |
parent | c4c9870953037be94da00ac9db887d171f6e479c (diff) |
path ops : add support for inverse fill
add inverse fill, reverse diff, and gm tests
cleaned up some interfaces
Review URL: https://codereview.chromium.org/14371011
git-svn-id: http://skia.googlecode.com/svn/trunk@8798 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 5 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 40 | ||||
-rw-r--r-- | src/pathops/SkPathOpsSimplify.cpp | 6 |
3 files changed, 41 insertions, 10 deletions
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index e221f68945..43afa08555 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -7,7 +7,7 @@ #include "SkIntersections.h" #include "SkOpSegment.h" #include "SkPathWriter.h" -#include "TSearch.h" +#include "SkTSort.h" #define F (false) // discard the edge #define T (true) // keep the edge @@ -18,7 +18,6 @@ static const bool gUnaryActiveEdge[2][2] = { {F, T}, {T, F}, }; -// FIXME: add support for kReverseDifference_Op static const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = { // miFrom=0 miFrom=1 // miTo=0 miTo=1 miTo=0 miTo=1 @@ -2318,7 +2317,7 @@ bool SkOpSegment::SortAngles(const SkTDArray<SkOpAngle>& angles, sortable &= !angle.unsortable(); } if (sortable) { - QSort<SkOpAngle>(angleList->begin(), angleList->end() - 1); + SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1); for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { if (angles[angleIndex].unsortable()) { sortable = false; diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index 5a3576ff6c..07a8babf7f 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -206,18 +206,48 @@ static bool bridgeOp(SkTDArray<SkOpContour*>& contourList, const SkPathOp op, return simple->someAssemblyRequired(); } +// pretty picture: +// https://docs.google.com/a/google.com/drawings/d/1sPV8rPfpEFXymBp3iSbDRWAycp1b-7vD9JP2V-kn9Ss/edit?usp=sharing +static const SkPathOp gOpInverse[kReverseDifference_PathOp + 1][2][2] = { +// inside minuend outside minuend +// inside subtrahend outside subtrahend inside subtrahend outside subtrahend + {{ kDifference_PathOp, kIntersect_PathOp }, { kUnion_PathOp, kReverseDifference_PathOp }}, + {{ kIntersect_PathOp, kDifference_PathOp }, { kReverseDifference_PathOp, kUnion_PathOp }}, + {{ kUnion_PathOp, kReverseDifference_PathOp }, { kDifference_PathOp, kIntersect_PathOp }}, + {{ kXOR_PathOp, kXOR_PathOp }, { kXOR_PathOp, kXOR_PathOp }}, + {{ kReverseDifference_PathOp, kUnion_PathOp }, { kIntersect_PathOp, kDifference_PathOp }}, +}; + +static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { + {{ false, false }, { true, false }}, // diff + {{ false, false }, { false, true }}, // sect + {{ false, true }, { true, true }}, // union + {{ false, true }, { true, false }}, // xor + {{ false, true }, { false, false }}, // rev diff +}; + void Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { + op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; + result->reset(); + SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isInverseFillType()] + ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; + result->setFillType(fillType); + const SkPath* minuend = &one; + const SkPath* subtrahend = &two; + if (op == kReverseDifference_PathOp) { + minuend = &two; + subtrahend = &one; + op = kDifference_PathOp; + } #if DEBUG_SORT || DEBUG_SWAP_TOP gDebugSortCount = gDebugSortCountDefault; #endif - result->reset(); - result->setFillType(SkPath::kEvenOdd_FillType); // turn path into list of segments SkTArray<SkOpContour> contours; // FIXME: add self-intersecting cubics' T values to segment - SkOpEdgeBuilder builder(one, contours); + SkOpEdgeBuilder builder(*minuend, contours); const int xorMask = builder.xorMask(); - builder.addOperand(two); + builder.addOperand(*subtrahend); builder.finish(); const int xorOpMask = builder.xorMask(); SkTDArray<SkOpContour*> contourList; @@ -264,7 +294,7 @@ void Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper); { // if some edges could not be resolved, assemble remaining fragments SkPath temp; - temp.setFillType(SkPath::kEvenOdd_FillType); + temp.setFillType(fillType); SkPathWriter assembled(temp); Assemble(wrapper, &assembled); *result = *assembled.nativePath(); diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp index 2213c68334..5c9d683f51 100644 --- a/src/pathops/SkPathOpsSimplify.cpp +++ b/src/pathops/SkPathOpsSimplify.cpp @@ -149,7 +149,9 @@ void Simplify(const SkPath& path, SkPath* result) { #endif // returns 1 for evenodd, -1 for winding, regardless of inverse-ness result->reset(); - result->setFillType(SkPath::kEvenOdd_FillType); + SkPath::FillType fillType = path.isInverseFillType() ? SkPath::kInverseEvenOdd_FillType + : SkPath::kEvenOdd_FillType; + result->setFillType(fillType); SkPathWriter simple(*result); // turn path into list of segments @@ -187,7 +189,7 @@ void Simplify(const SkPath& path, SkPath* result) { : !bridgeXor(contourList, &simple)) { // if some edges could not be resolved, assemble remaining fragments SkPath temp; - temp.setFillType(SkPath::kEvenOdd_FillType); + temp.setFillType(fillType); SkPathWriter assembled(temp); Assemble(simple, &assembled); *result = *assembled.nativePath(); |