Removed InitialValue code (#568)

Internal optimization.
Cleans up code and should make switching to JSONReader easier.
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 67852cd..69d5ee6 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -107,7 +107,7 @@
           <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
           <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
           <option name="ENUM_CONSTANTS_WRAP" value="1" />
-          <option name="WRAP_ON_TYPING" value="1" />
+          <option name="WRAP_ON_TYPING" value="0" />
           <indentOptions>
             <option name="INDENT_SIZE" value="2" />
             <option name="CONTINUATION_INDENT_SIZE" value="4" />
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index bb0eb90..6cdc0ed 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -768,7 +768,7 @@
   }
 
   public long getDuration() {
-    return composition != null ? composition.getDuration() : 0;
+    return composition != null ? (long) composition.getDuration() : 0;
   }
 
   public void setPerformanceTrackingEnabled(boolean enabled) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
index b98528f..97293c1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
@@ -54,8 +54,8 @@
   private final HashSet<String> warnings = new HashSet<>();
   private final PerformanceTracker performanceTracker = new PerformanceTracker();
   private final Rect bounds;
-  private final long startFrame;
-  private final long endFrame;
+  private final float startFrame;
+  private final float endFrame;
   private final float frameRate;
   private final float dpScale;
   /* Bodymovin version */
@@ -105,8 +105,8 @@
     return bounds;
   }
 
-  @SuppressWarnings("WeakerAccess") public long getDuration() {
-    long frameDuration = endFrame - startFrame;
+  @SuppressWarnings("WeakerAccess") public float getDuration() {
+    float frameDuration = endFrame - startFrame;
     return (long) (frameDuration / frameRate * 1000);
   }
 
@@ -126,12 +126,12 @@
   }
 
   @RestrictTo(RestrictTo.Scope.LIBRARY)
-  public long getStartFrame() {
+  public float getStartFrame() {
     return startFrame;
   }
 
   @RestrictTo(RestrictTo.Scope.LIBRARY)
-  public long getEndFrame() {
+  public float getEndFrame() {
     return endFrame;
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/Keyframe.java b/lottie/src/main/java/com/airbnb/lottie/animation/Keyframe.java
index dd178c2..f333d21 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/Keyframe.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/Keyframe.java
@@ -50,8 +50,7 @@
     }
   }
 
-
-  private final LottieComposition composition;
+  @Nullable private final LottieComposition composition;
   @Nullable public final T startValue;
   @Nullable public final T endValue;
   @Nullable public final Interpolator interpolator;
@@ -61,7 +60,9 @@
   private float startProgress = Float.MIN_VALUE;
   private float endProgress = Float.MIN_VALUE;
 
-  public Keyframe(LottieComposition composition, @Nullable T startValue, @Nullable T endValue,
+
+  public Keyframe(@SuppressWarnings("NullableProblems") LottieComposition composition,
+      @Nullable T startValue, @Nullable T endValue,
       @Nullable Interpolator interpolator, float startFrame, @Nullable Float endFrame) {
     this.composition = composition;
     this.startValue = startValue;
@@ -71,7 +72,22 @@
     this.endFrame = endFrame;
   }
 
+  /**
+   * Non-animated value.
+   */
+  public Keyframe(@SuppressWarnings("NullableProblems") T value) {
+    composition = null;
+    startValue = value;
+    endValue = value;
+    interpolator = null;
+    startFrame = Float.MIN_VALUE;
+    endFrame = Float.MAX_VALUE;
+  }
+
   public float getStartProgress() {
+    if (composition == null) {
+      return 0f;
+    }
     if (startProgress == Float.MIN_VALUE) {
       startProgress = (startFrame  - composition.getStartFrame()) / composition.getDurationFrames();
     }
@@ -79,6 +95,9 @@
   }
 
   public float getEndProgress() {
+    if (composition == null) {
+      return 1f;
+    }
     if (endProgress == Float.MIN_VALUE) {
       if (endFrame == null) {
         endProgress = 1f;
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
index f00b6bd..2095927 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
@@ -15,7 +15,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
 import com.airbnb.lottie.model.animatable.AnimatableIntegerValue;
@@ -304,10 +304,12 @@
     } else if (property == LottieProperty.STROKE_WIDTH) {
       widthAnimation.setValueCallback((LottieValueCallback<Float>) callback);
     } else if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
+      if (callback == null) {
+        colorFilterAnimation = null;
+      } else {
+        colorFilterAnimation =
+            new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
       }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
     }
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
index fb39bf8..bff1d68 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
@@ -12,7 +12,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.content.ShapeFill;
 import com.airbnb.lottie.model.layer.BaseLayer;
@@ -87,6 +87,7 @@
     }
 
     canvas.drawPath(path, paint);
+
     L.endSection("FillContent#draw");
   }
 
@@ -118,10 +119,12 @@
     } else if (property == LottieProperty.OPACITY) {
       opacityAnimation.setValueCallback((LottieValueCallback<Integer>) callback);
     } else if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
+      if (callback == null) {
+        colorFilterAnimation = null;
+      } else {
+        colorFilterAnimation =
+            new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
       }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index 4fd55d9..f5ee559 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -17,7 +17,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.content.GradientColor;
 import com.airbnb.lottie.model.content.GradientFill;
@@ -206,10 +206,12 @@
   @Override
   public <T> void addValueCallback(T property, @Nullable LottieValueCallback<T> callback) {
      if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
-      }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
+       if (callback == null) {
+         colorFilterAnimation = null;
+       } else {
+         colorFilterAnimation =
+             new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
+       }
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
index 9716da1..7ecab54 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
@@ -8,7 +8,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.content.ShapeStroke;
 import com.airbnb.lottie.model.layer.BaseLayer;
 import com.airbnb.lottie.value.LottieValueCallback;
@@ -47,10 +47,12 @@
     if (property == STROKE_COLOR) {
       colorAnimation.setValueCallback((LottieValueCallback<Integer>) callback);
     } else if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
+      if (callback == null) {
+        colorFilterAnimation = null;
+      } else {
+        colorFilterAnimation =
+            new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
       }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/GradientColorKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/GradientColorKeyframeAnimation.java
index a81d995..4ccdc99 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/GradientColorKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/GradientColorKeyframeAnimation.java
@@ -8,7 +8,7 @@
 public class GradientColorKeyframeAnimation extends KeyframeAnimation<GradientColor> {
   private final GradientColor gradientColor;
 
-  public GradientColorKeyframeAnimation(List<? extends Keyframe<GradientColor>> keyframes) {
+  public GradientColorKeyframeAnimation(List<Keyframe<GradientColor>> keyframes) {
     super(keyframes);
     GradientColor startValue = keyframes.get(0).startValue;
     int size = startValue == null ? 0 : startValue.getSize();
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/PointKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/PointKeyframeAnimation.java
index 93a2e96..61a8e75 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/PointKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/PointKeyframeAnimation.java
@@ -21,6 +21,12 @@
     PointF startPoint = keyframe.startValue;
     PointF endPoint = keyframe.endValue;
 
+    if (valueCallback != null) {
+      //noinspection ConstantConditions
+      return valueCallback.getValue(keyframe.startFrame, keyframe.endFrame, startPoint, endPoint,
+          keyframeProgress, getLinearCurrentKeyframeProgress(), getProgress());
+    }
+
     point.set(startPoint.x + keyframeProgress * (endPoint.x - startPoint.x),
         startPoint.y + keyframeProgress * (endPoint.y - startPoint.y));
     return point;
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ScaleKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ScaleKeyframeAnimation.java
index 31cbe84..d0bfaae 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ScaleKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ScaleKeyframeAnimation.java
@@ -17,6 +17,14 @@
     }
     ScaleXY startTransform = keyframe.startValue;
     ScaleXY endTransform = keyframe.endValue;
+
+    if (valueCallback != null) {
+      //noinspection ConstantConditions
+      return valueCallback.getValue(keyframe.startFrame, keyframe.endFrame,
+          startTransform, endTransform,
+          keyframeProgress, getLinearCurrentKeyframeProgress(), getProgress());
+    }
+
     return new ScaleXY(
         MiscUtils.lerp(startTransform.getScaleX(), endTransform.getScaleX(), keyframeProgress),
         MiscUtils.lerp(startTransform.getScaleY(), endTransform.getScaleY(), keyframeProgress));
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/StaticKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/StaticKeyframeAnimation.java
deleted file mode 100644
index 12d3e83..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/StaticKeyframeAnimation.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.airbnb.lottie.animation.keyframe;
-
-import com.airbnb.lottie.animation.Keyframe;
-
-import java.util.Collections;
-
-public class StaticKeyframeAnimation<K, A> extends BaseKeyframeAnimation<K, A> {
-  private final A initialValue;
-
-  public StaticKeyframeAnimation(A initialValue) {
-    super(Collections.<Keyframe<K>>emptyList());
-    this.initialValue = initialValue;
-  }
-
-  @Override public void setProgress(float progress) {
-    super.setProgress(progress);
-  }
-
-  /**
-   * If this doesn't return 1, then {@link #setProgress(float)} will always clamp the progress
-   * to 0.
-   */
-  @Override float getEndProgress() {
-    return 1f;
-  }
-
-  @Override void notifyListeners() {
-    if (this.valueCallback != null) {
-      super.notifyListeners();
-    }
-  }
-
-  @Override public A getValue() {
-    if (valueCallback != null) {
-      return valueCallback.getValue(
-          0f, 0f,
-          initialValue, initialValue,
-          getProgress(), getProgress(), getProgress());
-    }
-    return initialValue;
-  }
-
-  @Override public A getValue(Keyframe<K> keyframe, float keyframeProgress) {
-    return initialValue;
-  }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/TextKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/TextKeyframeAnimation.java
index 6d9eab1..affd4b9 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/TextKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/TextKeyframeAnimation.java
@@ -6,7 +6,7 @@
 import java.util.List;
 
 public class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
-  public TextKeyframeAnimation(List<? extends Keyframe<DocumentData>> keyframes) {
+  public TextKeyframeAnimation(List<Keyframe<DocumentData>> keyframes) {
     super(keyframes);
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ValueCallbackKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ValueCallbackKeyframeAnimation.java
new file mode 100644
index 0000000..920c17f
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ValueCallbackKeyframeAnimation.java
@@ -0,0 +1,42 @@
+package com.airbnb.lottie.animation.keyframe;
+
+import com.airbnb.lottie.animation.Keyframe;
+import com.airbnb.lottie.value.LottieValueCallback;
+
+import java.util.Collections;
+
+public class ValueCallbackKeyframeAnimation<K, A> extends BaseKeyframeAnimation<K, A> {
+
+  public ValueCallbackKeyframeAnimation(LottieValueCallback<A> valueCallback) {
+    super(Collections.<Keyframe<K>>emptyList());
+    setValueCallback(valueCallback);
+  }
+
+  @Override public void setProgress(float progress) {
+    super.setProgress(progress);
+  }
+
+  /**
+   * If this doesn't return 1, then {@link #setProgress(float)} will always clamp the progress
+   * to 0.
+   */
+  @Override float getEndProgress() {
+    return 1f;
+  }
+
+  @Override void notifyListeners() {
+    if (this.valueCallback != null) {
+      super.notifyListeners();
+    }
+  }
+
+  @Override public A getValue() {
+    //noinspection ConstantConditions
+    return valueCallback.getValue(
+        0f, 0f, null, null, getProgress(), getProgress(), getProgress());
+  }
+
+  @Override A getValue(Keyframe<K> keyframe, float keyframeProgress) {
+    return getValue();
+  }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableColorValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableColorValue.java
index 7291b78..f830df3 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableColorValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableColorValue.java
@@ -4,7 +4,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ColorKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.model.ColorFactory;
 
 import org.json.JSONObject;
@@ -12,30 +11,21 @@
 import java.util.List;
 
 public class AnimatableColorValue extends BaseAnimatableValue<Integer, Integer> {
-  private AnimatableColorValue(List<Keyframe<Integer>> keyframes, Integer initialValue) {
-    super(keyframes, initialValue);
+  private AnimatableColorValue(List<Keyframe<Integer>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<Integer, Integer> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    }
     return new ColorKeyframeAnimation(keyframes);
   }
 
-  @Override public String toString() {
-    return "AnimatableColorValue{" + "initialValue=" + initialValue + '}';
-  }
-
   public static final class Factory {
     private Factory() {
     }
 
     public static AnimatableColorValue newInstance(JSONObject json, LottieComposition composition) {
-      AnimatableValueParser.Result<Integer> result = AnimatableValueParser
-          .newInstance(json, 1f, composition, ColorFactory.INSTANCE)
-          .parseJson();
-      return new AnimatableColorValue(result.keyframes, result.initialValue);
+      return new AnimatableColorValue(
+          AnimatableValueParser.newInstance(json, 1f, composition, ColorFactory.INSTANCE));
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableFloatValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableFloatValue.java
index 8123b69..3a8f3bf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableFloatValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableFloatValue.java
@@ -4,7 +4,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.utils.JsonUtils;
 
 import org.json.JSONObject;
@@ -12,27 +11,23 @@
 import java.util.List;
 
 public class AnimatableFloatValue extends BaseAnimatableValue<Float, Float> {
+
   private AnimatableFloatValue() {
-    super(0f);
+    this(0f);
   }
 
-  private AnimatableFloatValue(List<Keyframe<Float>> keyframes, Float initialValue) {
-    super(keyframes, initialValue);
+  private AnimatableFloatValue(Float value) {
+    super(value);
+  }
+
+  private AnimatableFloatValue(List<Keyframe<Float>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<Float, Float> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    }
-
     return new FloatKeyframeAnimation(keyframes);
   }
 
-  @Override
-  public Float getInitialValue() {
-    return initialValue;
-  }
-
   private static class ValueFactory implements AnimatableValue.Factory<Float> {
     static final ValueFactory INSTANCE = new ValueFactory();
 
@@ -56,16 +51,14 @@
       return newInstance(json, composition, true);
     }
 
-    public static AnimatableFloatValue newInstance(JSONObject json, LottieComposition composition,
-        boolean isDp) {
+    public static AnimatableFloatValue newInstance(
+        JSONObject json, LottieComposition composition, boolean isDp) {
       float scale = isDp ? composition.getDpScale() : 1f;
       if (json != null && json.has("x")) {
         composition.addWarning("Lottie doesn't support expressions.");
       }
-      AnimatableValueParser.Result<Float> result = AnimatableValueParser
-          .newInstance(json, scale, composition, ValueFactory.INSTANCE)
-          .parseJson();
-      return new AnimatableFloatValue(result.keyframes, result.initialValue);
+      return new AnimatableFloatValue(
+          AnimatableValueParser.newInstance(json, scale, composition, ValueFactory.INSTANCE));
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValue.java
index e16614a..9af1860 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValue.java
@@ -9,7 +9,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.GradientColorKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.model.content.GradientColor;
 import com.airbnb.lottie.utils.MiscUtils;
 
@@ -21,14 +20,11 @@
 public class AnimatableGradientColorValue extends BaseAnimatableValue<GradientColor,
     GradientColor> {
   private AnimatableGradientColorValue(
-      List<Keyframe<GradientColor>> keyframes, GradientColor initialValue) {
-    super(keyframes, initialValue);
+      List<Keyframe<GradientColor>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<GradientColor, GradientColor> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    }
     return new GradientColorKeyframeAnimation(keyframes);
   }
 
@@ -39,11 +35,9 @@
     public static AnimatableGradientColorValue newInstance(
         JSONObject json, LottieComposition composition) {
       int points = json.optInt("p", json.optJSONArray("k").length() / 4);
-      AnimatableValueParser.Result<GradientColor> result = AnimatableValueParser
-          .newInstance(json, 1, composition, new ValueFactory(points))
-          .parseJson();
-      GradientColor initialValue = result.initialValue;
-      return new AnimatableGradientColorValue(result.keyframes, initialValue);
+      return new AnimatableGradientColorValue(
+          AnimatableValueParser.newInstance(json, 1, composition, new ValueFactory(points))
+      );
     }
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableIntegerValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableIntegerValue.java
index 0a914cb..84a5513 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableIntegerValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableIntegerValue.java
@@ -4,7 +4,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.IntegerKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.utils.JsonUtils;
 
 import org.json.JSONObject;
@@ -12,27 +11,23 @@
 import java.util.List;
 
 public class AnimatableIntegerValue extends BaseAnimatableValue<Integer, Integer> {
+
   private AnimatableIntegerValue() {
-    super(100);
+    this(100);
   }
 
-  AnimatableIntegerValue(List<Keyframe<Integer>> keyframes, Integer initialValue) {
-    super(keyframes, initialValue);
+  private AnimatableIntegerValue(Integer value) {
+    super(value);
+  }
+
+  AnimatableIntegerValue(List<Keyframe<Integer>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<Integer, Integer> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    }
-
     return new IntegerKeyframeAnimation(keyframes);
   }
 
-  @Override
-  public Integer getInitialValue() {
-    return initialValue;
-  }
-
   public static final class Factory {
     private Factory() {
     }
@@ -46,11 +41,9 @@
       if (json != null && json.has("x")) {
         composition.addWarning("Lottie doesn't support expressions.");
       }
-      AnimatableValueParser.Result<Integer> result = AnimatableValueParser
-          .newInstance(json, 1, composition, ValueFactory.INSTANCE)
-          .parseJson();
-      Integer initialValue = result.initialValue;
-      return new AnimatableIntegerValue(result.keyframes, initialValue);
+      return new AnimatableIntegerValue(
+          AnimatableValueParser.newInstance(json, 1, composition, ValueFactory.INSTANCE)
+      );
     }
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePathValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePathValue.java
index 4cb148c..483a762 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePathValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePathValue.java
@@ -7,7 +7,7 @@
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.PathKeyframe;
 import com.airbnb.lottie.animation.keyframe.PathKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.PointKeyframeAnimation;
 import com.airbnb.lottie.utils.JsonUtils;
 
 import org.json.JSONArray;
@@ -28,14 +28,13 @@
     }
   }
 
-  private final List<PathKeyframe> keyframes = new ArrayList<>();
-  private PointF initialPoint;
+  private final List<Keyframe<PointF>> keyframes = new ArrayList<>();
 
   /**
    * Create a default static animatable path.
    */
   AnimatablePathValue() {
-    this.initialPoint = new PointF(0, 0);
+    keyframes.add(new Keyframe<>(new PointF(0, 0)));
   }
 
   AnimatablePathValue(Object json, LottieComposition composition) {
@@ -50,7 +49,8 @@
       }
       Keyframe.setEndFrames(keyframes);
     } else {
-      initialPoint = JsonUtils.pointFromJsonArray((JSONArray) json, composition.getDpScale());
+      keyframes.add(
+          new Keyframe<>(JsonUtils.pointFromJsonArray((JSONArray) json, composition.getDpScale())));
     }
   }
 
@@ -65,23 +65,12 @@
 
   @Override
   public BaseKeyframeAnimation<PointF, PointF> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialPoint);
+    if (keyframes.get(0).isStatic()) {
+      return new PointKeyframeAnimation(keyframes);
     }
-
     return new PathKeyframeAnimation(keyframes);
   }
 
-  @Override
-  public boolean hasAnimation() {
-    return !keyframes.isEmpty();
-  }
-
-  @Override
-  public String toString() {
-    return "initialPoint=" + initialPoint;
-  }
-
   private static class ValueFactory implements AnimatableValue.Factory<PointF> {
     private static final Factory<PointF> INSTANCE = new ValueFactory();
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePointValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePointValue.java
index adcd4ba..f984284 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePointValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatablePointValue.java
@@ -6,7 +6,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.PointKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.model.PointFFactory;
 
 import org.json.JSONObject;
@@ -14,16 +13,12 @@
 import java.util.List;
 
 public class AnimatablePointValue extends BaseAnimatableValue<PointF, PointF> {
-  private AnimatablePointValue(List<Keyframe<PointF>> keyframes, PointF initialValue) {
-    super(keyframes, initialValue);
+  private AnimatablePointValue(List<Keyframe<PointF>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<PointF, PointF> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    } else {
-      return new PointKeyframeAnimation(keyframes);
-    }
+    return new PointKeyframeAnimation(keyframes);
   }
 
   public static final class Factory {
@@ -31,10 +26,10 @@
     }
 
     public static AnimatablePointValue newInstance(JSONObject json, LottieComposition composition) {
-      AnimatableValueParser.Result<PointF> result = AnimatableValueParser
-          .newInstance(json, composition.getDpScale(), composition, PointFFactory.INSTANCE)
-          .parseJson();
-      return new AnimatablePointValue(result.keyframes, result.initialValue);
+      return new AnimatablePointValue(
+          AnimatableValueParser
+              .newInstance(json, composition.getDpScale(), composition, PointFFactory.INSTANCE)
+      );
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableScaleValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableScaleValue.java
index 633fd90..6c1b480 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableScaleValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableScaleValue.java
@@ -4,7 +4,6 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ScaleKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.value.ScaleXY;
 
 import org.json.JSONObject;
@@ -12,32 +11,32 @@
 import java.util.List;
 
 public class AnimatableScaleValue extends BaseAnimatableValue<ScaleXY, ScaleXY> {
+
   private AnimatableScaleValue() {
-    super(new ScaleXY());
+    this(new ScaleXY(1f, 1f));
   }
 
-  AnimatableScaleValue(List<Keyframe<ScaleXY>> keyframes, ScaleXY initialValue) {
-    super(keyframes, initialValue);
+  private AnimatableScaleValue(ScaleXY value) {
+    super(value);
+  }
+
+  AnimatableScaleValue(List<Keyframe<ScaleXY>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<ScaleXY, ScaleXY> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(initialValue);
-    } else {
-      return new ScaleKeyframeAnimation(keyframes);
-    }
+    return new ScaleKeyframeAnimation(keyframes);
   }
 
   static final class Factory {
     private Factory() {
     }
 
-    static AnimatableScaleValue newInstance(JSONObject json, LottieComposition
-        composition) {
-      AnimatableValueParser.Result<ScaleXY> result = AnimatableValueParser
-          .newInstance(json, 1, composition, ScaleXY.Factory.INSTANCE)
-          .parseJson();
-      return new AnimatableScaleValue(result.keyframes, result.initialValue);
+    static AnimatableScaleValue newInstance(
+        JSONObject json, LottieComposition composition) {
+      return new AnimatableScaleValue(
+          AnimatableValueParser.newInstance(json, 1, composition, ScaleXY.Factory.INSTANCE)
+      );
     }
 
     static AnimatableScaleValue newInstance() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableShapeValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableShapeValue.java
index 62f5b01..2bb9057 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableShapeValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableShapeValue.java
@@ -6,33 +6,20 @@
 import com.airbnb.lottie.animation.Keyframe;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ShapeKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
 import com.airbnb.lottie.model.content.ShapeData;
-import com.airbnb.lottie.utils.MiscUtils;
 
 import org.json.JSONObject;
 
 import java.util.List;
 
 public class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
-  private final Path convertTypePath = new Path();
 
-  private AnimatableShapeValue(List<Keyframe<ShapeData>> keyframes, ShapeData initialValue) {
-    super(keyframes, initialValue);
+  private AnimatableShapeValue(List<Keyframe<ShapeData>> keyframes) {
+    super(keyframes);
   }
 
   @Override public BaseKeyframeAnimation<ShapeData, Path> createAnimation() {
-    if (!hasAnimation()) {
-      return new StaticKeyframeAnimation<>(convertType(initialValue));
-    } else {
-      return new ShapeKeyframeAnimation(keyframes);
-    }
-  }
-
-  @Override Path convertType(ShapeData shapeData) {
-    convertTypePath.reset();
-    MiscUtils.getPathFromData(shapeData, convertTypePath);
-    return convertTypePath;
+    return new ShapeKeyframeAnimation(keyframes);
   }
 
   public static final class Factory {
@@ -40,10 +27,10 @@
     }
 
     public static AnimatableShapeValue newInstance(JSONObject json, LottieComposition composition) {
-      AnimatableValueParser.Result<ShapeData> result = AnimatableValueParser
-          .newInstance(json, composition.getDpScale(), composition, ShapeData.Factory.INSTANCE)
-          .parseJson();
-      return new AnimatableShapeValue(result.keyframes, result.initialValue);
+      return new AnimatableShapeValue(
+          AnimatableValueParser
+              .newInstance(json, composition.getDpScale(), composition, ShapeData.Factory.INSTANCE)
+      );
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java
index 9dfd893..442ac03 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java
@@ -21,8 +21,4 @@
         animatableXDimension.createAnimation(), animatableYDimension.createAnimation());
   }
 
-  @Override public boolean hasAnimation() {
-    return animatableXDimension.hasAnimation() || animatableYDimension.hasAnimation();
-  }
-
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTextFrame.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTextFrame.java
index 53bbab8..3922b8a 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTextFrame.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTextFrame.java
@@ -11,8 +11,8 @@
 
 public class AnimatableTextFrame extends BaseAnimatableValue<DocumentData, DocumentData> {
 
-  AnimatableTextFrame(List<Keyframe<DocumentData>> keyframes, DocumentData initialValue) {
-    super(keyframes, initialValue);
+  AnimatableTextFrame(List<Keyframe<DocumentData>> keyframes) {
+    super(keyframes);
   }
 
   @Override public TextKeyframeAnimation createAnimation() {
@@ -27,10 +27,9 @@
       if (json != null && json.has("x")) {
         composition.addWarning("Lottie doesn't support expressions.");
       }
-      AnimatableValueParser.Result<DocumentData> result = AnimatableValueParser
-          .newInstance(json, 1, composition, AnimatableTextFrame.ValueFactory.INSTANCE)
-          .parseJson();
-      return new AnimatableTextFrame(result.keyframes, result.initialValue);
+      return new AnimatableTextFrame(
+          AnimatableValueParser
+              .newInstance(json, 1, composition, AnimatableTextFrame.ValueFactory.INSTANCE));
     }
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
index 8eccd92..ba53002 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
@@ -127,7 +127,7 @@
         scale = AnimatableScaleValue.Factory.newInstance(scaleJson, composition);
       } else {
         // Somehow some community animations don't have scale in the transform.
-        scale = new AnimatableScaleValue(Collections.<Keyframe<ScaleXY>>emptyList(), new ScaleXY());
+        scale = new AnimatableScaleValue(Collections.<Keyframe<ScaleXY>>emptyList());
       }
 
       JSONObject rotationJson = json.optJSONObject("r");
@@ -145,7 +145,7 @@
         opacity = AnimatableIntegerValue.Factory.newInstance(opacityJson, composition);
       } else {
         // Repeaters have start/end opacity instead of opacity
-        opacity = new AnimatableIntegerValue(Collections.<Keyframe<Integer>>emptyList(), 100);
+        opacity = new AnimatableIntegerValue(Collections.<Keyframe<Integer>>emptyList());
       }
 
       JSONObject startOpacityJson = json.optJSONObject("so");
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValue.java
index 0642d41..329b5c3 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValue.java
@@ -4,7 +4,6 @@
 
 public interface AnimatableValue<K, A> {
   BaseKeyframeAnimation<K, A> createAnimation();
-  boolean hasAnimation();
 
   interface Factory<V> {
     V valueFromObject(Object object, float scale);
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValueParser.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValueParser.java
index 276226a..95b296c 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValueParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableValueParser.java
@@ -11,13 +11,13 @@
 import java.util.Collections;
 import java.util.List;
 
-public class AnimatableValueParser<T> {
-  @Nullable private final JSONObject json;
+class AnimatableValueParser<T> {
+  private final JSONObject json;
   private final float scale;
   private final LottieComposition composition;
   private final AnimatableValue.Factory<T> valueFactory;
 
-  private AnimatableValueParser(@Nullable JSONObject json, float scale, LottieComposition
+  private AnimatableValueParser(JSONObject json, float scale, LottieComposition
       composition, AnimatableValue.Factory<T> valueFactory) {
     this.json = json;
     this.scale = scale;
@@ -25,40 +25,25 @@
     this.valueFactory = valueFactory;
   }
 
-  static <T> AnimatableValueParser<T> newInstance(@Nullable JSONObject json, float scale,
+  static <T> List<Keyframe<T>> newInstance(@Nullable JSONObject json, float scale,
       LottieComposition composition, AnimatableValue.Factory<T> valueFactory) {
-    return new AnimatableValueParser<>(json, scale, composition, valueFactory);
-  }
-
-  Result<T> parseJson() {
-    List<Keyframe<T>> keyframes = parseKeyframes();
-    T initialValue = parseInitialValue(keyframes);
-    return new Result<>(keyframes, initialValue);
+    AnimatableValueParser<T> parser =
+        new AnimatableValueParser<>(json, scale, composition, valueFactory);
+    return parser.parseKeyframes();
   }
 
   private List<Keyframe<T>> parseKeyframes() {
-    if (json != null) {
-      Object k = json.opt("k");
-      if (hasKeyframes(k)) {
-        return Keyframe.Factory.parseKeyframes((JSONArray) k, composition, scale, valueFactory);
-      } else {
-        return Collections.emptyList();
-      }
+    Object k = json.opt("k");
+    if (hasKeyframes(k)) {
+      return Keyframe.Factory.parseKeyframes((JSONArray) k, composition, scale, valueFactory);
     } else {
-      return Collections.emptyList();
+      return parseStaticValue();
     }
   }
 
-  @Nullable private T parseInitialValue(List<Keyframe<T>> keyframes) {
-    if (json != null) {
-      if (!keyframes.isEmpty()) {
-        return keyframes.get(0).startValue;
-      } else {
-        return valueFactory.valueFromObject(json.opt("k"), scale);
-      }
-    } else {
-      return null;
-    }
+  private List<Keyframe<T>> parseStaticValue() {
+    T initialValue = valueFactory.valueFromObject(json.opt("k"), scale);
+    return Collections.singletonList(new Keyframe<>(initialValue));
   }
 
   private static boolean hasKeyframes(Object json) {
@@ -69,14 +54,4 @@
       return firstObject instanceof JSONObject && ((JSONObject) firstObject).has("t");
     }
   }
-
-  static class Result<T> {
-    final List<Keyframe<T>> keyframes;
-    final @Nullable T initialValue;
-
-    Result(List<Keyframe<T>> keyframes, @Nullable T initialValue) {
-      this.keyframes = keyframes;
-      this.initialValue = initialValue;
-    }
-  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
index 5be069c..c8eab4f 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
@@ -8,43 +8,22 @@
 
 public abstract class BaseAnimatableValue<V, O> implements AnimatableValue<V, O> {
   final List<Keyframe<V>> keyframes;
-  final V initialValue;
 
   /**
    * Create a default static animatable path.
    */
-  BaseAnimatableValue(V initialValue) {
-    this(Collections.<Keyframe<V>>emptyList(), initialValue);
+  BaseAnimatableValue(V value) {
+    this(Collections.singletonList(new Keyframe<>(value)));
   }
 
-  BaseAnimatableValue(List<Keyframe<V>> keyframes, V initialValue) {
+  BaseAnimatableValue(List<Keyframe<V>> keyframes) {
     this.keyframes = keyframes;
-    this.initialValue = initialValue;
-  }
-
-  /**
-   * Convert the value type of the keyframe to the value type of the animation. Often, these
-   * are the same type.
-   */
-  O convertType(V value) {
-    //noinspection unchecked
-    return (O) value;
-  }
-
-  @Override
-  public boolean hasAnimation() {
-    return !keyframes.isEmpty();
-  }
-
-  public O getInitialValue() {
-    return convertType(initialValue);
   }
 
   @Override public String toString() {
     final StringBuilder sb = new StringBuilder();
-    sb.append("parseInitialValue=").append(initialValue);
     if (!keyframes.isEmpty()) {
-      sb.append(", values=").append(Arrays.toString(keyframes.toArray()));
+      sb.append("values=").append(Arrays.toString(keyframes.toArray()));
     }
     return sb.toString();
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java b/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
index 9992eae..dfe1acf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
@@ -63,8 +63,7 @@
   }
 
   @Override public String toString() {
-    return "RectangleShape{" + "cornerRadius=" + cornerRadius.getInitialValue() +
-        ", position=" + position +
+    return "RectangleShape{position=" + position +
         ", size=" + size +
         '}';
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
index 2c16f99..b13ba97 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
@@ -80,9 +80,7 @@
   @Override
   public String toString() {
     return "ShapeFill{" + "color=" +
-        (color == null ? "null" :  Integer.toHexString(color.getInitialValue())) +
         ", fillEnabled=" + fillEnabled +
-        ", opacity=" + (opacity == null ? "null" : opacity.getInitialValue()) +
         '}';
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
index 7644083..a1ec58d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
@@ -35,7 +35,6 @@
   @Override public String toString() {
     return "ShapePath{" + "name=" + name +
         ", index=" + index +
-        ", hasAnimation=" + shapePath.hasAnimation() +
         '}';
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
index 9ec2414..ed6af1a 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
@@ -12,7 +12,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
 import com.airbnb.lottie.value.LottieValueCallback;
@@ -134,9 +134,9 @@
   @Override public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
     super.setProgress(progress);
     if (timeRemapping != null) {
-      long duration = lottieDrawable.getComposition().getDuration();
+      float duration = lottieDrawable.getComposition().getDuration();
       long remappedTime = (long) (timeRemapping.getValue() * 1000);
-      progress = remappedTime / (float) duration;
+      progress = remappedTime / duration;
     }
     if (layerModel.getTimeStretch() != 0) {
       progress /= layerModel.getTimeStretch();
@@ -199,11 +199,11 @@
     super.addValueCallback(property, callback);
 
     if (property == LottieProperty.TIME_REMAP) {
-      if (timeRemapping == null) {
-        timeRemapping = new StaticKeyframeAnimation<>(1f);
-        addAnimation(timeRemapping);
+      if (callback == null) {
+        timeRemapping = null;
+      } else {
+        timeRemapping = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Float>) callback);
       }
-      timeRemapping.setValueCallback((LottieValueCallback<Float>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
index a9e1861..46e3222 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
@@ -13,7 +13,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.value.LottieValueCallback;
 
 public class ImageLayer extends BaseLayer {
@@ -67,14 +67,17 @@
     return lottieDrawable.getImageAsset(refId);
   }
 
+  @SuppressWarnings("SingleStatementInBlock")
   @Override
   public <T> void addValueCallback(T property, @Nullable LottieValueCallback<T> callback) {
     super.addValueCallback(property, callback);
      if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
-      }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
+       if (callback == null) {
+         colorFilterAnimation = null;
+       } else {
+         colorFilterAnimation =
+             new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
+       }
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
index c0a80ed..4a79a06 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
@@ -11,7 +11,7 @@
 import com.airbnb.lottie.LottieDrawable;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.StaticKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.value.LottieValueCallback;
 
 public class SolidLayer extends BaseLayer {
@@ -58,14 +58,17 @@
     matrix.mapRect(rect);
   }
 
+  @SuppressWarnings("unchecked")
   @Override
   public <T> void addValueCallback(T property, @Nullable LottieValueCallback<T> callback) {
     super.addValueCallback(property, callback);
     if (property == LottieProperty.COLOR_FILTER) {
-      if (colorFilterAnimation == null) {
-        colorFilterAnimation = new StaticKeyframeAnimation<>(null);
+      if (callback == null) {
+        colorFilterAnimation = null;
+      } else {
+        colorFilterAnimation =
+            new ValueCallbackKeyframeAnimation<>((LottieValueCallback<ColorFilter>) callback);
       }
-      colorFilterAnimation.setValueCallback((LottieValueCallback<ColorFilter>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
index 0759459..6e3fb0e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
+++ b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
@@ -9,7 +9,7 @@
  */
 public class LottieValueAnimator extends ValueAnimator {
   private boolean systemAnimationsAreDisabled = false;
-  private long compositionDuration;
+  private float compositionDuration;
   private float speed = 1f;
   @FloatRange(from = 0f, to = 1f) private float value = 0f;
   @FloatRange(from = 0f, to = 1f) private float minValue = 0f;
@@ -33,7 +33,7 @@
     this.systemAnimationsAreDisabled = true;
   }
 
-  public void setCompositionDuration(long compositionDuration) {
+  public void setCompositionDuration(float compositionDuration) {
     this.compositionDuration = compositionDuration;
     updateValues();
   }