Randomize seed for SkDiscretePathEffect::filterPath()

Fix for https://code.google.com/p/skia/issues/detail?id=2581. Randomizes
the seed in SkDiscretePathEffect::filterPath(). Prior to this we were
using the path length as a seed.

Now, if we have two different paths with identical contents and we
apply an SkDiscretePathEffect to each, we obtain two different random
paths. Previously, we would obtain two overlapping paths (identical
path contents leading to the same seed).

BUG=skia:
R=reed@google.com, scroggo@google.com

Author: rs.prinja@samsung.com

Review URL: https://codereview.chromium.org/311803002
This commit is contained in:
rs.prinja 2014-06-12 22:55:08 -07:00 committed by Commit bot
parent bfefc7c95f
commit 39e58adb99
2 changed files with 30 additions and 7 deletions

View File

@ -19,9 +19,21 @@ public:
/** Break the path into segments of segLength length, and randomly move the endpoints
away from the original path by a maximum of deviation.
Note: works on filled or framed paths
@param seedAssist This is a caller-supplied seedAssist that modifies
the seed value that is used to randomize the path
segments' endpoints. If not supplied it defaults to 0,
in which case filtering a path multiple times will
result in the same set of segments (this is useful for
testing). If a caller does not want this behaviour
they can pass in a different seedAssist to get a
different set of path segments.
*/
static SkDiscretePathEffect* Create(SkScalar segLength, SkScalar deviation) {
return SkNEW_ARGS(SkDiscretePathEffect, (segLength, deviation));
static SkDiscretePathEffect* Create(SkScalar segLength,
SkScalar deviation,
uint32_t seedAssist=0) {
return SkNEW_ARGS(SkDiscretePathEffect,
(segLength, deviation, seedAssist));
}
virtual bool filterPath(SkPath* dst, const SkPath& src,
@ -30,13 +42,18 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect)
protected:
SkDiscretePathEffect(SkScalar segLength, SkScalar deviation);
SkDiscretePathEffect(SkScalar segLength,
SkScalar deviation,
uint32_t seedAssist);
explicit SkDiscretePathEffect(SkReadBuffer&);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
SkScalar fSegLength, fPerterb;
/* Caller-supplied 32 bit seed assist */
uint32_t fSeedAssist;
typedef SkPathEffect INHERITED;
};

View File

@ -20,9 +20,10 @@ static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
*p += normal;
}
SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
: fSegLength(segLength), fPerterb(deviation)
SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength,
SkScalar deviation,
uint32_t seedAssist)
: fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist)
{
}
@ -31,7 +32,10 @@ bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
bool doFill = rec->isFillStyle();
SkPathMeasure meas(src, doFill);
uint32_t seed = SkScalarRoundToInt(meas.getLength());
/* Caller may supply their own seed assist, which by default is 0 */
uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength());
SkLCGRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
SkScalar scale = fPerterb;
SkPoint p;
@ -75,9 +79,11 @@ void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSegLength);
buffer.writeScalar(fPerterb);
buffer.writeUInt(fSeedAssist);
}
SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) {
fSegLength = buffer.readScalar();
fPerterb = buffer.readScalar();
fSeedAssist = buffer.readUInt();
}