diff options
author | 2012-06-07 21:43:15 +0000 | |
---|---|---|
committer | 2012-06-07 21:43:15 +0000 | |
commit | df9d656c352928f995abce0a62c4ec3255232a45 (patch) | |
tree | 3cd391af1780d9b161b407178ef591b7d52d3de3 | |
parent | 88f7d0cb09707355bc9079d4b0569537e8048fa9 (diff) |
Add SkPath::getVerbs/countVerbs
Review URL: http://codereview.appspot.com/6306053/
git-svn-id: http://skia.googlecode.com/svn/trunk@4209 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkPath.h | 15 | ||||
-rw-r--r-- | include/core/SkTDArray.h | 19 | ||||
-rw-r--r-- | src/core/SkGlyphCache.cpp | 2 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 16 | ||||
-rw-r--r-- | tests/PathTest.cpp | 120 |
5 files changed, 163 insertions, 9 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 4e987c0a20..e6989f2838 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -259,6 +259,21 @@ public: */ int getPoints(SkPoint points[], int max) const; + /** Return the number of verbs in the path + */ + int countVerbs() const { + return this->getVerbs(NULL, 0); + } + + /** Returns the number of verbs in the path. Up to max verbs are copied. The + verbs are copied as one byte per verb. + + @param verbs If not null, receives up to max verbs + @param max The maximum number of verbs to copy into verbs + @return the actual number of verbs in the path + */ + int getVerbs(uint8_t verbs[], int max) const; + //! Swap contents of this and other. Guaranteed not to throw void swap(SkPath& other); diff --git a/include/core/SkTDArray.h b/include/core/SkTDArray.h index f0f94494f3..426bb6d303 100644 --- a/include/core/SkTDArray.h +++ b/include/core/SkTDArray.h @@ -228,6 +228,25 @@ public: return -1; } + /** + * Copies up to max elements into dst. The number of items copied is + * capped by count - index. The actual number copied is returned. + */ + int copyRange(T* dst, size_t index, int max) const { + SkASSERT(max >= 0); + SkASSERT(!max || dst); + if (index >= fCount) { + return 0; + } + int count = SkMin32(max, fCount - index); + memcpy(dst, fArray + index, sizeof(T) * count); + return count; + } + + void copy(T* dst) const { + this->copyRange(0, fCount, dst); + } + // routines to treat the array like a stack T* push() { return this->append(); } void push(const T& elem) { *this->append() = elem; } diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp index f3363cde70..387b78bc41 100644 --- a/src/core/SkGlyphCache.cpp +++ b/src/core/SkGlyphCache.cpp @@ -313,7 +313,7 @@ const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { const_cast<SkGlyph&>(glyph).fPath = SkNEW(SkPath); fScalerContext->getPath(glyph, glyph.fPath); fMemoryUsed += sizeof(SkPath) + - glyph.fPath->getPoints(NULL, 0x7FFFFFFF) * sizeof(SkPoint); + glyph.fPath->countPoints() * sizeof(SkPoint); } } return glyph.fPath; diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 34b0ac9360..4dab6042a2 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -390,14 +390,13 @@ bool SkPath::isRect(SkRect* rect) const { return result; } -int SkPath::getPoints(SkPoint copy[], int max) const { +int SkPath::getPoints(SkPoint dst[], int max) const { SkDEBUGCODE(this->validate();) SkASSERT(max >= 0); + SkASSERT(!max || dst); int count = fPts.count(); - if (copy && max > 0 && count > 0) { - memcpy(copy, fPts.begin(), sizeof(SkPoint) * SkMin32(max, count)); - } + fPts.copyRange(dst, 0, max); return count; } @@ -408,6 +407,15 @@ SkPoint SkPath::getPoint(int index) const { return SkPoint::Make(0, 0); } +int SkPath::getVerbs(uint8_t dst[], int max) const { + SkDEBUGCODE(this->validate();) + + SkASSERT(max >= 0); + SkASSERT(!max || dst); + fVerbs.copyRange(dst, 0, max); + return fVerbs.count(); +} + bool SkPath::getLastPt(SkPoint* lastPt) const { SkDEBUGCODE(this->validate();) diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index 9d9903fb13..21f78bf2ce 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -756,16 +756,28 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, pt.fY == SK_Scalar1); bounds.set(0, 0, 0, 0); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[1]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + } // MoveTo-MoveTo case p.moveTo(SK_Scalar1*2, SK_Scalar1); REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 2 == p.countPoints()); + REPORTER_ASSERT(reporter, 2 == p.countVerbs()); p.getLastPt(&pt); REPORTER_ASSERT(reporter, pt.fX == SK_Scalar1*2); REPORTER_ASSERT(reporter, pt.fY == SK_Scalar1); bounds.set(SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[2]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[1]); + } // moveTo-close case p.reset(); @@ -774,7 +786,14 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { bounds.set(0, 0, 0, 0); REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 1 == p.countPoints()); + REPORTER_ASSERT(reporter, 2 == p.countVerbs()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[2]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[1]); + } // moveTo-close-moveTo-close case p.moveTo(SK_Scalar1*2, SK_Scalar1); @@ -783,6 +802,14 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 2 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[4]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[1]); + } // moveTo-line case p.reset(); @@ -792,6 +819,12 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 2 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[2]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); + } // moveTo-lineTo-moveTo-lineTo case p.moveTo(SK_Scalar1*2, SK_Scalar1); @@ -800,6 +833,14 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 4 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[4]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[2]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[3]); + } // moveTo-line-close case p.reset(); @@ -810,6 +851,13 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 2 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[3]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[2]); + } // moveTo-line-close-moveTo-line-close case p.moveTo(SK_Scalar1*2, SK_Scalar1); @@ -819,6 +867,16 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 4 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[6]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[2]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[3]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[4]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[5]); + } // moveTo-quadTo case p.reset(); @@ -828,12 +886,26 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 3 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[2]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == verbs[1]); + } // moveTo-quadTo-close case p.close(); REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 3 == p.countPoints()); + REPORTER_ASSERT(reporter, 3 == p.countVerbs()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[3]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[2]); + } // moveTo-quadTo-moveTo-quadTo case p.reset(); @@ -845,6 +917,14 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 6 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[4]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == verbs[1]); + } // moveTo-cubicTo case p.reset(); @@ -856,14 +936,27 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 4 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[2]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == verbs[1]); + } - // moveTo-quadTo-close case + // moveTo-cubicTo-close case p.close(); REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 4 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[3]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[2]); + } - // moveTo-quadTo-moveTo-quadTo case + // moveTo-cubicTo-moveTo-cubicTo case p.reset(); p.moveTo(SK_Scalar1, SK_Scalar1); p.cubicTo(SK_Scalar1, SK_Scalar1, @@ -877,6 +970,14 @@ static void test_zero_length_paths(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !p.isEmpty()); REPORTER_ASSERT(reporter, 8 == p.countPoints()); REPORTER_ASSERT(reporter, bounds == p.getBounds()); + { + uint8_t verbs[4]; + REPORTER_ASSERT(reporter, SK_ARRAY_COUNT(verbs) == p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[2]); + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == verbs[3]); + } } struct SegmentInfo { @@ -1391,6 +1492,7 @@ static void TestPath(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, p.isEmpty()); REPORTER_ASSERT(reporter, 0 == p.countPoints()); + REPORTER_ASSERT(reporter, 0 == p.countVerbs()); REPORTER_ASSERT(reporter, 0 == p.getSegmentMasks()); REPORTER_ASSERT(reporter, p.isConvex()); REPORTER_ASSERT(reporter, p.getFillType() == SkPath::kWinding_FillType); @@ -1426,11 +1528,21 @@ static void TestPath(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, p != p2); REPORTER_ASSERT(reporter, !(p == p2)); - // does getPoints return the right result - REPORTER_ASSERT(reporter, p.getPoints(NULL, 5) == 4); + // do getPoints and getVerbs return the right result + REPORTER_ASSERT(reporter, p.getPoints(NULL, 0) == 4); + REPORTER_ASSERT(reporter, p.getVerbs(NULL, 0) == 5); SkPoint pts[4]; int count = p.getPoints(pts, 4); REPORTER_ASSERT(reporter, count == 4); + uint8_t verbs[6]; + verbs[5] = 0xff; + p.getVerbs(verbs, 5); + REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[2]); + REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[3]); + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[4]); + REPORTER_ASSERT(reporter, 0xff == verbs[5]); bounds2.set(pts, 4); REPORTER_ASSERT(reporter, bounds == bounds2); |