Index: tests/SubsetPath.cpp |
diff --git a/tests/SubsetPath.cpp b/tests/SubsetPath.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e67df1210b8797fdb76e511df33eb0de06e9dcb9 |
--- /dev/null |
+++ b/tests/SubsetPath.cpp |
@@ -0,0 +1,240 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SubsetPath.h" |
+ |
+SubsetPath::SubsetPath(const SkPath& path) |
+ : fPath(path) |
+ , fSubset(1) { |
+} |
+ |
+int SubsetPath::range(int* end) const { |
+ int leadingZero = SkCLZ(fSubset); |
+ int parts = 1 << (31 - leadingZero); |
+ int partIndex = fSubset - parts; |
+ SkASSERT(partIndex >= 0); |
+ int count = fSelected.count(); |
+ int start = count * partIndex / parts; |
+ *end = count * (partIndex + 1) / parts; |
+ return start; |
+} |
+ |
+bool SubsetPath::subset(bool testFailed, SkPath* sub) { |
+ int start, end; |
+ if (!testFailed) { |
+ start = range(&end); |
+ for (; start < end; ++start) { |
+ fSelected[start] = true; |
+ } |
+ } |
+ do { |
+ do { |
+ ++fSubset; |
+ start = range(&end); |
+ // SkDebugf("%d s=%d e=%d t=%d\n", fSubset, start, end, fTries); |
+ if (end - start > 1) { |
+ fTries = fSelected.count(); |
+ } else if (end - start == 1) { |
+ if (--fTries <= 0) { |
+ return false; |
+ } |
+ } |
+ } while (start == end); |
+ } while (!fSelected[start]); |
+ for (; start < end; ++start) { |
+ fSelected[start] = false; |
+ } |
+#if 1 |
+ SkDebugf("selected: "); |
+ for (int index = 0; index < fSelected.count(); ++index) { |
+ SkDebugf("%c", fSelected[index] ? 'x' : '-'); |
+ } |
+#endif |
+ *sub = getSubsetPath(); |
+ return true; |
+} |
+ |
+SubsetContours::SubsetContours(const SkPath& path) |
+ : SubsetPath(path) { |
+ SkPath::RawIter iter(fPath); |
+ uint8_t verb; |
+ SkPoint pts[4]; |
+ bool foundCurve = false; |
+ int contourCount = 0; |
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
+ switch (verb) { |
+ case SkPath::kMove_Verb: |
+ break; |
+ case SkPath::kLine_Verb: |
+ case SkPath::kQuad_Verb: |
+ case SkPath::kConic_Verb: |
+ case SkPath::kCubic_Verb: |
+ foundCurve = true; |
+ break; |
+ case SkPath::kClose_Verb: |
+ ++contourCount; |
+ foundCurve = false; |
+ break; |
+ default: |
+ SkDEBUGFAIL("bad verb"); |
+ return; |
+ } |
+ } |
+ contourCount += foundCurve; |
+ for (int index = 0; index < contourCount; ++index) { |
+ *fSelected.append() = true; |
+ } |
+ fTries = contourCount; |
+} |
+ |
+SkPath SubsetContours::getSubsetPath() const { |
+ SkPath result; |
+ result.setFillType(fPath.getFillType()); |
+ if (!fSelected.count()) { |
+ return result; |
+ } |
+ SkPath::RawIter iter(fPath); |
+ uint8_t verb; |
+ SkPoint pts[4]; |
+ int contourCount = 0; |
+ bool enabled = fSelected[0]; |
+ bool addMoveTo = true; |
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
+ if (enabled && addMoveTo) { |
+ result.moveTo(pts[0]); |
+ addMoveTo = false; |
+ } |
+ switch (verb) { |
+ case SkPath::kMove_Verb: |
+ break; |
+ case SkPath::kLine_Verb: |
+ if (enabled) { |
+ result.lineTo(pts[1]); |
+ } |
+ break; |
+ case SkPath::kQuad_Verb: |
+ if (enabled) { |
+ result.quadTo(pts[1], pts[2]); |
+ } |
+ break; |
+ case SkPath::kConic_Verb: |
+ if (enabled) { |
+ result.conicTo(pts[1], pts[2], iter.conicWeight()); |
+ } |
+ break; |
+ case SkPath::kCubic_Verb: |
+ if (enabled) { |
+ result.cubicTo(pts[1], pts[2], pts[3]); |
+ } |
+ break; |
+ case SkPath::kClose_Verb: |
+ if (enabled) { |
+ result.close(); |
+ } |
+ if (++contourCount >= fSelected.count()) { |
+ break; |
+ } |
+ enabled = fSelected[contourCount]; |
+ addMoveTo = true; |
+ continue; |
+ default: |
+ SkDEBUGFAIL("bad verb"); |
+ return result; |
+ } |
+ } |
+ return result; |
+} |
+ |
+SubsetVerbs::SubsetVerbs(const SkPath& path) |
+ : SubsetPath(path) { |
+ SkPath::RawIter iter(fPath); |
+ uint8_t verb; |
+ SkPoint pts[4]; |
+ int verbCount = 0; |
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
+ switch (verb) { |
+ case SkPath::kMove_Verb: |
+ break; |
+ case SkPath::kLine_Verb: |
+ case SkPath::kQuad_Verb: |
+ case SkPath::kConic_Verb: |
+ case SkPath::kCubic_Verb: |
+ ++verbCount; |
+ break; |
+ case SkPath::kClose_Verb: |
+ break; |
+ default: |
+ SkDEBUGFAIL("bad verb"); |
+ return; |
+ } |
+ } |
+ for (int index = 0; index < verbCount; ++index) { |
+ *fSelected.append() = true; |
+ } |
+ fTries = verbCount; |
+} |
+ |
+SkPath SubsetVerbs::getSubsetPath() const { |
+ SkPath result; |
+ result.setFillType(fPath.getFillType()); |
+ if (!fSelected.count()) { |
+ return result; |
+ } |
+ SkPath::RawIter iter(fPath); |
+ uint8_t verb; |
+ SkPoint pts[4]; |
+ int verbIndex = 0; |
+ bool addMoveTo = true; |
+ bool addLineTo = false; |
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
+ bool enabled = SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb |
+ ? fSelected[verbIndex++] : false; |
+ if (enabled) { |
+ if (addMoveTo) { |
+ result.moveTo(pts[0]); |
+ addMoveTo = false; |
+ } else if (addLineTo) { |
+ result.lineTo(pts[0]); |
+ addLineTo = false; |
+ } |
+ } |
+ switch (verb) { |
+ case SkPath::kMove_Verb: |
+ break; |
+ case SkPath::kLine_Verb: |
+ if (enabled) { |
+ result.lineTo(pts[1]); |
+ } |
+ break; |
+ case SkPath::kQuad_Verb: |
+ if (enabled) { |
+ result.quadTo(pts[1], pts[2]); |
+ } |
+ break; |
+ case SkPath::kConic_Verb: |
+ if (enabled) { |
+ result.conicTo(pts[1], pts[2], iter.conicWeight()); |
+ } |
+ break; |
+ case SkPath::kCubic_Verb: |
+ if (enabled) { |
+ result.cubicTo(pts[1], pts[2], pts[3]); |
+ } |
+ break; |
+ case SkPath::kClose_Verb: |
+ result.close(); |
+ addMoveTo = true; |
+ addLineTo = false; |
+ continue; |
+ default: |
+ SkDEBUGFAIL("bad verb"); |
+ return result; |
+ } |
+ addLineTo = !enabled; |
+ } |
+ return result; |
+} |