aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-22 14:37:05 +0000
committerGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-22 14:37:05 +0000
commit7dfbb0720a133c0f63ac7be504f335bbcc62a291 (patch)
tree819a38446c52c07f941e2bf09ec236823f1032f3 /src
parentc4c9870953037be94da00ac9db887d171f6e479c (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.cpp5
-rw-r--r--src/pathops/SkPathOpsOp.cpp40
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp6
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();