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
diff --git a/include/effects/SkDiscretePathEffect.h b/include/effects/SkDiscretePathEffect.h
index 8373b6a..cbee20f 100644
--- a/include/effects/SkDiscretePathEffect.h
+++ b/include/effects/SkDiscretePathEffect.h
@@ -19,9 +19,21 @@
     /** 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 @@
     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;
 };
 
diff --git a/src/effects/SkDiscretePathEffect.cpp b/src/effects/SkDiscretePathEffect.cpp
index de83442..f6f9112 100644
--- a/src/effects/SkDiscretePathEffect.cpp
+++ b/src/effects/SkDiscretePathEffect.cpp
@@ -20,9 +20,10 @@
     *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 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 @@
     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();
 }