aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/tests.gypi1
-rw-r--r--include/core/SkPathEffect.h27
-rw-r--r--include/core/SkPicture.h3
-rw-r--r--include/effects/SkDashPathEffect.h5
-rw-r--r--src/core/SkPathEffect.cpp4
-rw-r--r--src/effects/SkDashPathEffect.cpp76
-rw-r--r--tests/AsADashTest.cpp57
7 files changed, 149 insertions, 24 deletions
diff --git a/gyp/tests.gypi b/gyp/tests.gypi
index e6c6bb0e32..f27b144dea 100644
--- a/gyp/tests.gypi
+++ b/gyp/tests.gypi
@@ -34,6 +34,7 @@
'../tests/ARGBImageEncoderTest.cpp',
'../tests/AndroidPaintTest.cpp',
'../tests/AnnotationTest.cpp',
+ '../tests/AsADashTest.cpp',
'../tests/AtomicTest.cpp',
'../tests/BBoxHierarchyTest.cpp',
'../tests/BitSetTest.cpp',
diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h
index 86ccf86a92..638287d07c 100644
--- a/include/core/SkPathEffect.h
+++ b/include/core/SkPathEffect.h
@@ -104,6 +104,33 @@ public:
const SkStrokeRec&, const SkMatrix&,
const SkRect* cullR) const;
+ /**
+ * If the PathEffect can be represented as a dash pattern, asADash will return kDash_DashType
+ * and None otherwise. If a non NULL info is passed in, the various DashInfo will be filled
+ * in if the PathEffect can be a dash pattern. If passed in info has an fCount equal or
+ * greater to that of the effect, it will memcpy the values of the dash intervals into the
+ * info. Thus the general approach will be call asADash once with default info to get DashType
+ * and fCount. If effect can be represented as a dash pattern, allocate space for the intervals
+ * in info, then call asADash again with the same info and the intervals will get copied in.
+ */
+
+ enum DashType {
+ kNone_DashType, //!< ignores the info parameter
+ kDash_DashType, //!< fills in all of the info parameter
+ };
+
+ struct DashInfo {
+ DashInfo() : fIntervals(NULL), fCount(0), fPhase(0) {}
+
+ SkScalar* fIntervals; //!< Length of on/off intervals for dashed lines
+ // Even values represent ons, and odds offs
+ int32_t fCount; //!< Number of intervals in the dash. Should be even number
+ SkScalar fPhase; //!< Offset into the dashed interval pattern
+ // mod the sum of all intervals
+ };
+
+ virtual DashType asADash(DashInfo* info) const;
+
SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect)
protected:
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index bf9ec4f8bb..996d85716e 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -324,13 +324,14 @@ protected:
// V22: SK_PICT_FACTORY_TAG's size is now the chunk size in bytes
// V23: SkPaint::FilterLevel became a real enum
// V24: SkTwoPointConicalGradient now has fFlipped flag for gradient flipping
+ // V25: SkDashPathEffect now only writes phase and interval array when flattening
// Note: If the picture version needs to be increased then please follow the
// steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
// Only SKPs within the min/current picture version range (inclusive) can be read.
static const uint32_t MIN_PICTURE_VERSION = 19;
- static const uint32_t CURRENT_PICTURE_VERSION = 24;
+ static const uint32_t CURRENT_PICTURE_VERSION = 25;
mutable uint32_t fUniqueID;
diff --git a/include/effects/SkDashPathEffect.h b/include/effects/SkDashPathEffect.h
index 41f8f5a43e..f69e90586a 100644
--- a/include/effects/SkDashPathEffect.h
+++ b/include/effects/SkDashPathEffect.h
@@ -49,6 +49,8 @@ public:
const SkStrokeRec&, const SkMatrix&,
const SkRect*) const SK_OVERRIDE;
+ virtual DashType asADash(DashInfo* info) const SK_OVERRIDE;
+
virtual Factory getFactory() const SK_OVERRIDE;
static SkFlattenable* CreateProc(SkReadBuffer&);
@@ -63,8 +65,11 @@ public:
SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase);
private:
+ void setInternalMembers(SkScalar phase);
+
SkScalar* fIntervals;
int32_t fCount;
+ SkScalar fPhase;
// computed from phase
SkScalar fInitialDashLength;
int32_t fInitialDashIndex;
diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp
index e181320356..01d5d6f961 100644
--- a/src/core/SkPathEffect.cpp
+++ b/src/core/SkPathEffect.cpp
@@ -22,6 +22,10 @@ bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
return false;
}
+SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
+ return kNone_DashType;
+}
+
///////////////////////////////////////////////////////////////////////////////
SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index 15276b684c..6f132e0be5 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -34,19 +34,10 @@ static SkScalar FindFirstInterval(const SkScalar intervals[], SkScalar phase,
return intervals[0];
}
-SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
- SkScalar phase) {
- SkASSERT(intervals);
- SkASSERT(count > 1 && SkAlign2(count) == count);
-
- fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count);
- fCount = count;
-
+void SkDashPathEffect::setInternalMembers(SkScalar phase) {
SkScalar len = 0;
- for (int i = 0; i < count; i++) {
- SkASSERT(intervals[i] >= 0);
- fIntervals[i] = intervals[i];
- len += intervals[i];
+ for (int i = 0; i < fCount; i++) {
+ len += fIntervals[i];
}
fIntervalLength = len;
@@ -74,8 +65,10 @@ SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
}
SkASSERT(phase >= 0 && phase < len);
- fInitialDashLength = FindFirstInterval(intervals, phase,
- &fInitialDashIndex, count);
+ fPhase = phase;
+
+ fInitialDashLength = FindFirstInterval(fIntervals, fPhase,
+ &fInitialDashIndex, fCount);
SkASSERT(fInitialDashLength >= 0);
SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount);
@@ -84,6 +77,21 @@ SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
}
}
+SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
+ SkScalar phase) {
+ SkASSERT(intervals);
+ SkASSERT(count > 1 && SkAlign2(count) == count);
+
+ fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count);
+ fCount = count;
+ for (int i = 0; i < count; i++) {
+ SkASSERT(intervals[i] >= 0);
+ fIntervals[i] = intervals[i];
+ }
+
+ this->setInternalMembers(phase);
+}
+
SkDashPathEffect::~SkDashPathEffect() {
sk_free(fIntervals);
}
@@ -510,17 +518,24 @@ bool SkDashPathEffect::asPoints(PointData* results,
return true;
}
+SkPathEffect::DashType SkDashPathEffect::asADash(DashInfo* info) const {
+ if (info) {
+ if (info->fCount >= fCount && NULL != info->fIntervals) {
+ memcpy(info->fIntervals, fIntervals, fCount * sizeof(SkScalar));
+ }
+ info->fCount = fCount;
+ info->fPhase = fPhase;
+ }
+ return kDash_DashType;
+}
+
SkFlattenable::Factory SkDashPathEffect::getFactory() const {
return CreateProc;
}
void SkDashPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeInt(fInitialDashIndex);
- buffer.writeScalar(fInitialDashLength);
- buffer.writeScalar(fIntervalLength);
- // Dummy write to stay compatible with old skps. Write will be removed in follow up patch.
- buffer.writeBool(false);
+ buffer.writeScalar(fPhase);
buffer.writeScalarArray(fIntervals, fCount);
}
@@ -529,10 +544,15 @@ SkFlattenable* SkDashPathEffect::CreateProc(SkReadBuffer& buffer) {
}
SkDashPathEffect::SkDashPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
- fInitialDashIndex = buffer.readInt();
- fInitialDashLength = buffer.readScalar();
- fIntervalLength = buffer.readScalar();
- buffer.readBool(); // dummy read to stay compatible with old skps
+ bool useOldPic = buffer.pictureVersion() < 25 && 0 != buffer.pictureVersion();
+ if (useOldPic) {
+ fInitialDashIndex = buffer.readInt();
+ fInitialDashLength = buffer.readScalar();
+ fIntervalLength = buffer.readScalar();
+ buffer.readBool(); // Dummy for old ScalarToFit field
+ } else {
+ fPhase = buffer.readScalar();
+ }
fCount = buffer.getArrayCount();
size_t allocSize = sizeof(SkScalar) * fCount;
@@ -542,4 +562,14 @@ SkDashPathEffect::SkDashPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
} else {
fIntervals = NULL;
}
+
+ if (useOldPic) {
+ fPhase = 0;
+ for (int i = 0; i < fInitialDashIndex; ++i) {
+ fPhase += fIntervals[i];
+ }
+ fPhase += fInitialDashLength;
+ } else {
+ this->setInternalMembers(fPhase);
+ }
}
diff --git a/tests/AsADashTest.cpp b/tests/AsADashTest.cpp
new file mode 100644
index 0000000000..47f19717a4
--- /dev/null
+++ b/tests/AsADashTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+
+#include "SkPathEffect.h"
+#include "SkDashPathEffect.h"
+#include "SkCornerPathEffect.h"
+
+DEF_TEST(AsADashTest_noneDash, reporter) {
+ SkAutoTUnref<SkCornerPathEffect> pe(SkCornerPathEffect::Create(1.0));
+ SkPathEffect::DashInfo info;
+
+ SkPathEffect::DashType dashType = pe->asADash(&info);
+ REPORTER_ASSERT(reporter, SkPathEffect::kNone_DashType == dashType);
+}
+
+DEF_TEST(AsADashTest_nullInfo, reporter) {
+ SkScalar inIntervals[] = { 4.0, 2.0, 1.0, 3.0 };
+ const SkScalar phase = 2.0;
+ SkAutoTUnref<SkDashPathEffect> pe(SkDashPathEffect::Create(inIntervals, 4, phase));
+
+ SkPathEffect::DashType dashType = pe->asADash(NULL);
+ REPORTER_ASSERT(reporter, SkPathEffect::kDash_DashType == dashType);
+}
+
+DEF_TEST(AsADashTest_usingDash, reporter) {
+ SkScalar inIntervals[] = { 4.0, 2.0, 1.0, 3.0 };
+ SkScalar totalIntSum = 10.0;
+ const SkScalar phase = 2.0;
+
+ SkAutoTUnref<SkDashPathEffect> pe(SkDashPathEffect::Create(inIntervals, 4, phase));
+
+ SkPathEffect::DashInfo info;
+
+ SkPathEffect::DashType dashType = pe->asADash(&info);
+ REPORTER_ASSERT(reporter, SkPathEffect::kDash_DashType == dashType);
+ REPORTER_ASSERT(reporter, 4 == info.fCount);
+ REPORTER_ASSERT(reporter, SkScalarMod(phase, totalIntSum) == info.fPhase);
+
+ // Since it is a kDash_DashType, allocate space for the intervals and recall asADash
+ SkAutoTArray<SkScalar> intervals(info.fCount);
+ info.fIntervals = intervals.get();
+ pe->asADash(&info);
+ REPORTER_ASSERT(reporter, inIntervals[0] == info.fIntervals[0]);
+ REPORTER_ASSERT(reporter, inIntervals[1] == info.fIntervals[1]);
+ REPORTER_ASSERT(reporter, inIntervals[2] == info.fIntervals[2]);
+ REPORTER_ASSERT(reporter, inIntervals[3] == info.fIntervals[3]);
+
+ // Make sure nothing else has changed on us
+ REPORTER_ASSERT(reporter, 4 == info.fCount);
+ REPORTER_ASSERT(reporter, SkScalarMod(phase, totalIntSum) == info.fPhase);
+}