Add asADash entry point into SkPathEffect to allow extracting Dash info from PathEffects
BUG=skia: R=bsalomon@google.com, reed@google.com Author: egdaniel@google.com Review URL: https://codereview.chromium.org/212103010 git-svn-id: http://skia.googlecode.com/svn/trunk@14297 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
fd4ee4dea1
commit
aec143824c
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
57
tests/AsADashTest.cpp
Normal file
57
tests/AsADashTest.cpp
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user