New SkCurve type with multiple curve segments

- Converted all linear force stuff into a single affector,
  used at either spawn or update time appropriately.
  The new affector can either set or adjust velocity.
- Converted lifetime to a curve.
- Removed SkRangedFloat, initial velocity params, etc.

Looks like a large addition, but that's mostly down to the
JSON getting bigger. There's a net reduction in LoC.

Bug: skia:
Change-Id: Iac7417f15f96d0313efd08c4b26dc3250b80fa77
Reviewed-on: https://skia-review.googlesource.com/c/192102
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/modules/particles/include/SkCurve.h b/modules/particles/include/SkCurve.h
index 3b9bfc4..cca41a1 100644
--- a/modules/particles/include/SkCurve.h
+++ b/modules/particles/include/SkCurve.h
@@ -9,36 +9,39 @@
 #define SkCurve_DEFINED
 
 #include "SkScalar.h"
+#include "SkTArray.h"
 
 class SkFieldVisitor;
 class SkRandom;
 
-// TODO: Generalize this to a keyframed list of cubics
+struct SkCurveSegment {
+    SkScalar eval(SkScalar x, SkRandom& random) const;
+    void visitFields(SkFieldVisitor* v);
+
+    void setConstant(SkScalar c) {
+        fConstant = true;
+        fRanged   = false;
+        fMin[0] = c;
+    }
+
+    SkScalar fMin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+    SkScalar fMax[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+    bool fConstant      = true;
+    bool fRanged        = false;
+    bool fBidirectional = false;
+};
 
 struct SkCurve {
     SkCurve(SkScalar c = 0.0f) {
-        fRanged = false;
-        fMin[0] = fMin[1] = fMin[2] = fMin[3] = c;
-        fMax[0] = fMax[1] = fMax[2] = fMax[3] = c;
+        fSegments.push_back().setConstant(c);
     }
 
-    SkScalar eval(float x, SkRandom& random) const;
+    SkScalar eval(SkScalar x, SkRandom& random) const;
     void visitFields(SkFieldVisitor* v);
 
-    bool fRanged;
-    SkScalar fMin[4];
-    SkScalar fMax[4]; // used if ranged
-};
-
-// Ranged constant. Keeping this here temporarily. Phase this out in favor of SkCurve everywhere.
-struct SkRangedFloat {
-    float eval(SkRandom& random) const;
-    float* vec() { return &fMin; }
-
-    float fMin = 0.0f;
-    float fMax = 0.0f;
-
-    void visitFields(SkFieldVisitor* v);
+    SkTArray<SkScalar, true>       fXValues;
+    SkTArray<SkCurveSegment, true> fSegments;
 };
 
 #endif // SkCurve_DEFINED
diff --git a/modules/particles/include/SkParticleAffector.h b/modules/particles/include/SkParticleAffector.h
index 1200821..82570db 100644
--- a/modules/particles/include/SkParticleAffector.h
+++ b/modules/particles/include/SkParticleAffector.h
@@ -12,6 +12,7 @@
 
 #include "SkPoint.h"
 
+struct SkCurve;
 struct SkParticlePoseAndVelocity;
 struct SkParticleUpdateParams;
 
@@ -23,12 +24,14 @@
 
     static void RegisterAffectorTypes();
 
-    static sk_sp<SkParticleAffector> MakeDirectionalForce(SkVector force);
-    static sk_sp<SkParticleAffector> MakeRangedForce(const SkCurve& angle, const SkCurve& strength,
-                                                     bool bidirectional);
+    static sk_sp<SkParticleAffector> MakeLinearVelocity(const SkCurve& angle,
+                                                        const SkCurve& strength,
+                                                        bool force);
     static sk_sp<SkParticleAffector> MakePointForce(SkPoint point, SkScalar constant,
                                                     SkScalar invSquare);
     static sk_sp<SkParticleAffector> MakeOrientAlongVelocity();
+
+    static sk_sp<SkParticleAffector> MakeSizeAffector(const SkCurve& curve);
 };
 
 #endif // SkParticleAffector_DEFINED
diff --git a/modules/particles/include/SkParticleEffect.h b/modules/particles/include/SkParticleEffect.h
index 34d3c51..22fb683 100644
--- a/modules/particles/include/SkParticleEffect.h
+++ b/modules/particles/include/SkParticleEffect.h
@@ -26,35 +26,14 @@
 class SkParticleEmitter;
 struct SkRSXform;
 
-// TODO: Phase this out, once all properties are driven by the two-lists-of-affectors
-struct InitialVelocityParams {
-    float fAngle = 0.0f;
-    float fAngleSpread = 0.0f;
-    SkRangedFloat fStrength = { 0.0f, 0.0f };
-    bool fBidirectional = false;
-
-    SkRangedFloat fSpin = { 0.0f, 0.0f };
-    bool fBidirectionalSpin = false;
-
-    SkParticleVelocity eval(SkRandom& random) const;
-
-    void visitFields(SkFieldVisitor* v);
-};
-
 class SkParticleEffectParams : public SkRefCnt {
 public:
-    int           fMaxCount = 128;
-    float         fEffectDuration = 1.0f;
-    float         fRate = 8.0f;
-    SkRangedFloat fLifetime = { 1.0f, 1.0f };
-    SkColor4f     fStartColor = { 1.0f, 1.0f, 1.0f, 1.0f };
-    SkColor4f     fEndColor = { 1.0f, 1.0f, 1.0f, 1.0f };
-
-    SkCurve       fSize = 1.0f;
-
-    // TODO: Add local vs. world copies of these
-    // Initial velocity controls
-    InitialVelocityParams fVelocity;
+    int       fMaxCount = 128;
+    float     fEffectDuration = 1.0f;
+    float     fRate = 8.0f;
+    SkCurve   fLifetime = 1.0f;
+    SkColor4f fStartColor = { 1.0f, 1.0f, 1.0f, 1.0f };
+    SkColor4f fEndColor = { 1.0f, 1.0f, 1.0f, 1.0f };
 
     // Sprite image parameters
     // TODO: Move sprite stuff in here, out of effect
diff --git a/modules/particles/include/SkParticleSerialization.h b/modules/particles/include/SkParticleSerialization.h
index 946dfd6..a1773fa 100644
--- a/modules/particles/include/SkParticleSerialization.h
+++ b/modules/particles/include/SkParticleSerialization.h
@@ -105,12 +105,6 @@
         }
     }
 
-    void visit(const char* name, SkCurve& c, SkField field) override {
-        if (get(name).is<skjson::ObjectValue>()) {
-            SkFieldVisitor::visit(name, c, field);
-        }
-    }
-
     void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
         const skjson::StringValue* typeString = get("Type");
         const char* type = typeString ? typeString->begin() : "Null";
diff --git a/modules/particles/include/SkReflected.h b/modules/particles/include/SkReflected.h
index ed9d025..93a18a0 100644
--- a/modules/particles/include/SkReflected.h
+++ b/modules/particles/include/SkReflected.h
@@ -9,7 +9,6 @@
 #define SkReflected_DEFINED
 
 #include "SkColor.h"
-#include "SkCurve.h"
 #include "SkRefCnt.h"
 #include "SkString.h"
 #include "SkTArray.h"
@@ -119,12 +118,6 @@
     virtual void visit(const char*, SkPoint&, SkField = SkField()) = 0;
     virtual void visit(const char*, SkColor4f&, SkField = SkField()) = 0;
 
-    virtual void visit(const char* name, SkCurve& curve, SkField = SkField()) {
-        this->enterObject(name);
-        curve.visitFields(this);
-        this->exitObject();
-    }
-
     template <typename T>
     void visit(const char* name, T& value) {
         this->enterObject(name);