diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableColorValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableColorValue.java index 9b8b6b1c51..67a0485bbd 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableColorValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableColorValue.java @@ -2,13 +2,12 @@ import org.json.JSONObject; -class AnimatableColorValue extends BaseAnimatableValue { - AnimatableColorValue(JSONObject json, LottieComposition composition) { - super(json, composition, false); - } +import java.util.List; - @Override public Integer valueFromObject(Object object, float scale) { - return ColorFactory.newInstance(object); +class AnimatableColorValue extends BaseAnimatableValue { + private AnimatableColorValue(List> keyframes, LottieComposition composition, + Integer initialValue) { + super(keyframes, composition, initialValue); } @Override public KeyframeAnimation createAnimation() { @@ -21,4 +20,16 @@ class AnimatableColorValue extends BaseAnimatableValue { @Override public String toString() { return "AnimatableColorValue{" + "initialValue=" + initialValue + '}'; } + + static final class Factory { + private Factory() { + } + + static AnimatableColorValue newInstance(JSONObject json, LottieComposition composition) { + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, 1f, composition, ColorFactory.INSTANCE) + .parseJson(); + return new AnimatableColorValue(result.keyframes, composition, result.initialValue); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableFloatValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableFloatValue.java index 473af05297..fda057c682 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableFloatValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableFloatValue.java @@ -2,22 +2,16 @@ import org.json.JSONObject; -class AnimatableFloatValue extends BaseAnimatableValue { - AnimatableFloatValue(LottieComposition composition, Float initialValue) { - super(composition); - this.initialValue = initialValue; - } +import java.util.List; - AnimatableFloatValue(JSONObject json, LottieComposition composition) { - this(json, composition, true); - } - - AnimatableFloatValue(JSONObject json, LottieComposition composition, boolean isDp) { - super(json, composition, isDp); +class AnimatableFloatValue extends BaseAnimatableValue { + private AnimatableFloatValue(LottieComposition composition, Float initialValue) { + super(composition, initialValue); } - @Override public Float valueFromObject(Object object, float scale) { - return JsonUtils.valueFromObject(object) * scale; + private AnimatableFloatValue(List> keyframes, + LottieComposition composition, Float initialValue) { + super(keyframes, composition, initialValue); } @Override public KeyframeAnimation createAnimation() { @@ -31,4 +25,37 @@ class AnimatableFloatValue extends BaseAnimatableValue { public Float getInitialValue() { return initialValue; } + + private static class ValueFactory implements AnimatableValue.Factory { + static final ValueFactory INSTANCE = new ValueFactory(); + + private ValueFactory() { + } + + @Override public Float valueFromObject(Object object, float scale) { + return JsonUtils.valueFromObject(object) * scale; + } + } + + static final class Factory { + private Factory() { + } + + static AnimatableFloatValue newInstance(LottieComposition composition, Float initialValue) { + return new AnimatableFloatValue(composition, initialValue); + } + + static AnimatableFloatValue newInstance(JSONObject json, LottieComposition composition) { + return newInstance(json, composition, true); + } + + static AnimatableFloatValue newInstance(JSONObject json, LottieComposition composition, + boolean isDp) { + float scale = isDp ? composition.getScale() : 1f; + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, scale, composition, ValueFactory.INSTANCE) + .parseJson(); + return new AnimatableFloatValue(result.keyframes, composition, result.initialValue); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableIntegerValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableIntegerValue.java index 382457b89a..2f351038dd 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableIntegerValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableIntegerValue.java @@ -2,27 +2,16 @@ import org.json.JSONObject; -class AnimatableIntegerValue extends BaseAnimatableValue { - AnimatableIntegerValue(LottieComposition composition, Integer initialValue) { - super(composition); - this.initialValue = initialValue; - } +import java.util.List; - AnimatableIntegerValue(JSONObject json, LottieComposition composition, - boolean isDp, boolean remap100To255) { - super(json, composition, isDp); - if (remap100To255) { - initialValue = initialValue * 255 / 100; - for (int i = 0; i < keyframes.size(); i++) { - Keyframe keyframe = keyframes.get(i); - keyframe.startValue = keyframe.startValue * 255 / 100; - keyframe.endValue = keyframe.endValue * 255 / 100; - } - } +class AnimatableIntegerValue extends BaseAnimatableValue { + private AnimatableIntegerValue(LottieComposition composition, Integer initialValue) { + super(composition, initialValue); } - @Override public Integer valueFromObject(Object object, float scale) { - return Math.round(JsonUtils.valueFromObject(object) * scale); + private AnimatableIntegerValue(List> keyframes, LottieComposition composition, + Integer initialValue) { + super(keyframes, composition, initialValue); } @Override public KeyframeAnimation createAnimation() { @@ -36,4 +25,43 @@ class AnimatableIntegerValue extends BaseAnimatableValue { public Integer getInitialValue() { return initialValue; } + + static final class Factory { + private Factory() { + } + + static AnimatableIntegerValue newInstance(LottieComposition composition, Integer initialValue) { + return new AnimatableIntegerValue(composition, initialValue); + } + + static AnimatableIntegerValue newInstance(JSONObject json, LottieComposition composition, + boolean isDp, boolean remap100To255) { + float scale = isDp ? composition.getScale() : 1f; + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, scale, composition, ValueFactory.INSTANCE) + .parseJson(); + Integer initialValue = result.initialValue; + if (remap100To255 && result.initialValue != null) { + initialValue = result.initialValue * 255 / 100; + int size = result.keyframes.size(); + for (int i = 0; i < size; i++) { + Keyframe keyframe = result.keyframes.get(i); + keyframe.startValue = keyframe.startValue * 255 / 100; + keyframe.endValue = keyframe.endValue * 255 / 100; + } + } + return new AnimatableIntegerValue(result.keyframes, composition, initialValue); + } + } + + private static class ValueFactory implements AnimatableValue.Factory { + private static final ValueFactory INSTANCE = new ValueFactory(); + + private ValueFactory() { + } + + @Override public Integer valueFromObject(Object object, float scale) { + return Math.round(JsonUtils.valueFromObject(object) * scale); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatablePathValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatablePathValue.java index 79186d27cd..f1c3fd3444 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatablePathValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatablePathValue.java @@ -15,8 +15,8 @@ static IAnimatablePathValue createAnimatablePathOrSplitDimensionPath( return new AnimatablePathValue(json.opt("k"), composition); } else { return new AnimatableSplitDimensionPathValue( - new AnimatableFloatValue(json.optJSONObject("x"), composition), - new AnimatableFloatValue(json.optJSONObject("y"), composition)); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("x"), composition), + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("y"), composition)); } } @@ -36,7 +36,8 @@ static IAnimatablePathValue createAnimatablePathOrSplitDimensionPath( int length = jsonArray.length(); for (int i = 0; i < length; i++) { JSONObject jsonKeyframe = jsonArray.optJSONObject(i); - PathKeyframe keyframe = PathKeyframe.Factory.newInstance(jsonKeyframe, composition, this); + PathKeyframe keyframe = PathKeyframe.Factory.newInstance(jsonKeyframe, composition, + ValueFactory.INSTANCE); keyframes.add(keyframe); } Keyframe.setEndFrames(keyframes); @@ -54,10 +55,6 @@ private boolean hasKeyframes(Object json) { return firstObject instanceof JSONObject && ((JSONObject) firstObject).has("t"); } - @Override public PointF valueFromObject(Object object, float scale) { - return JsonUtils.pointFromJsonArray((JSONArray) object, scale); - } - @Override public BaseKeyframeAnimation createAnimation() { if (!hasAnimation()) { @@ -81,4 +78,15 @@ public PointF getInitialPoint() { public String toString() { return "initialPoint=" + initialPoint; } + + private static class ValueFactory implements AnimatableValue.Factory { + private static final Factory INSTANCE = new ValueFactory(); + + private ValueFactory() { + } + + @Override public PointF valueFromObject(Object object, float scale) { + return JsonUtils.pointFromJsonArray((JSONArray) object, scale); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatablePointValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatablePointValue.java index 58678a9cf6..1089e7fc76 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatablePointValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatablePointValue.java @@ -4,20 +4,31 @@ import org.json.JSONObject; -class AnimatablePointValue extends BaseAnimatableValue { - AnimatablePointValue(JSONObject pointValues, LottieComposition composition) { - super(pointValues, composition, true); - } +import java.util.List; - @Override public PointF valueFromObject(Object object, float scale) { - return PointFFactory.newInstance(object, scale); +class AnimatablePointValue extends BaseAnimatableValue { + private AnimatablePointValue(List> keyframes, LottieComposition composition, + PointF initialValue) { + super(keyframes, composition, initialValue); } @Override public KeyframeAnimation createAnimation() { if (!hasAnimation()) { return new StaticKeyframeAnimation<>(initialValue); + } else { + return new PointKeyframeAnimation(keyframes); } + } - return new PointKeyframeAnimation(keyframes); + static final class Factory { + private Factory() { + } + + static AnimatablePointValue newInstance(JSONObject json, LottieComposition composition) { + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, composition.getScale(), composition, PointFFactory.INSTANCE) + .parseJson(); + return new AnimatablePointValue(result.keyframes, composition, result.initialValue); + } } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableScaleValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableScaleValue.java index 4ba4b8afcf..d33fcf2aad 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableScaleValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableScaleValue.java @@ -2,18 +2,16 @@ import org.json.JSONObject; -class AnimatableScaleValue extends BaseAnimatableValue { - AnimatableScaleValue(LottieComposition composition) { - super(composition); - initialValue = new ScaleXY(); - } +import java.util.List; - AnimatableScaleValue(JSONObject scaleValues, LottieComposition composition, boolean isDp) { - super(scaleValues, composition, isDp); +class AnimatableScaleValue extends BaseAnimatableValue { + private AnimatableScaleValue(LottieComposition composition) { + super(composition, new ScaleXY()); } - @Override public ScaleXY valueFromObject(Object object, float scale) { - return ScaleXY.Factory.newInstance(object, scale); + private AnimatableScaleValue(List> keyframes, LottieComposition composition, + ScaleXY initialValue) { + super(keyframes, composition, initialValue); } @Override public KeyframeAnimation createAnimation() { @@ -23,4 +21,22 @@ class AnimatableScaleValue extends BaseAnimatableValue { return new ScaleKeyframeAnimation(keyframes); } } + + static final class Factory { + private Factory() { + } + + static AnimatableScaleValue newInstance(JSONObject json, LottieComposition + composition, boolean isDp) { + float scale = isDp ? composition.getScale() : 1f; + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, scale, composition, ScaleXY.Factory.INSTANCE) + .parseJson(); + return new AnimatableScaleValue(result.keyframes, composition, result.initialValue); + } + + static AnimatableScaleValue newInstance(LottieComposition composition) { + return new AnimatableScaleValue(composition); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableShapeValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableShapeValue.java index aea802dbe7..7580410a58 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableShapeValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableShapeValue.java @@ -4,23 +4,22 @@ import org.json.JSONObject; +import java.util.List; + class AnimatableShapeValue extends BaseAnimatableValue { private final Path convertTypePath = new Path(); - AnimatableShapeValue(JSONObject json, LottieComposition composition) { - super(json, composition, true); - } - - @Override public ShapeData valueFromObject(Object object, float scale) { - return ShapeData.Factory.newInstance(object, scale); + private AnimatableShapeValue(List> keyframes, LottieComposition composition, + ShapeData initialValue) { + super(keyframes, composition, initialValue); } @Override public BaseKeyframeAnimation createAnimation() { if (!hasAnimation()) { return new StaticKeyframeAnimation<>(convertType(initialValue)); + } else { + return new ShapeKeyframeAnimation(keyframes); } - - return new ShapeKeyframeAnimation(keyframes); } @Override Path convertType(ShapeData shapeData) { @@ -28,4 +27,16 @@ class AnimatableShapeValue extends BaseAnimatableValue { MiscUtils.getPathFromData(shapeData, convertTypePath); return convertTypePath; } + + static final class Factory { + private Factory() { + } + + static AnimatableShapeValue newInstance(JSONObject json, LottieComposition composition) { + AnimatableValueParser.Result result = AnimatableValueParser + .newInstance(json, composition.getScale(), composition, ShapeData.Factory.INSTANCE) + .parseJson(); + return new AnimatableShapeValue(result.keyframes, composition, result.initialValue); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableSplitDimensionPathValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableSplitDimensionPathValue.java index 151c77a290..7be9980d34 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableSplitDimensionPathValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableSplitDimensionPathValue.java @@ -14,10 +14,6 @@ class AnimatableSplitDimensionPathValue implements IAnimatablePathValue { this.animatableYDimension = animatableYDimension; } - @Override public PointF valueFromObject(Object object, float scale) { - return null; - } - @Override public KeyframeAnimation createAnimation() { return new SplitDimensionPathKeyframeAnimation( animatableXDimension.createAnimation(), animatableYDimension.createAnimation()); diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableTransform.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableTransform.java index 5b7ef407d0..2c18a65b3b 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableTransform.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableTransform.java @@ -25,9 +25,9 @@ private Factory() { static AnimatableTransform newInstance(LottieComposition composition) { AnimatablePathValue anchorPoint = new AnimatablePathValue(); IAnimatablePathValue position = new AnimatablePathValue(); - AnimatableScaleValue scale = new AnimatableScaleValue(composition); - AnimatableFloatValue rotation = new AnimatableFloatValue(composition, 0f); - AnimatableIntegerValue opacity = new AnimatableIntegerValue(composition, 255); + AnimatableScaleValue scale = AnimatableScaleValue.Factory.newInstance(composition); + AnimatableFloatValue rotation = AnimatableFloatValue.Factory.newInstance(composition, 0f); + AnimatableIntegerValue opacity = AnimatableIntegerValue.Factory.newInstance(composition, 255); return new AnimatableTransform(anchorPoint, position, scale, rotation, opacity); } @@ -54,7 +54,7 @@ static AnimatableTransform newInstance(JSONObject json, LottieComposition compos JSONObject scaleJson = json.optJSONObject("s"); if (scaleJson != null) { - scale = new AnimatableScaleValue(scaleJson, composition, false); + scale = AnimatableScaleValue.Factory.newInstance(scaleJson, composition, false); } else { throwMissingTransform("scale"); } @@ -64,14 +64,14 @@ static AnimatableTransform newInstance(JSONObject json, LottieComposition compos rotationJson = json.optJSONObject("rz"); } if (rotationJson != null) { - rotation = new AnimatableFloatValue(rotationJson, composition, false); + rotation = AnimatableFloatValue.Factory.newInstance(rotationJson, composition, false); } else { throwMissingTransform("rotation"); } JSONObject opacityJson = json.optJSONObject("o"); if (opacityJson != null) { - opacity = new AnimatableIntegerValue(opacityJson, composition, false, true); + opacity = AnimatableIntegerValue.Factory.newInstance(opacityJson, composition, false, true); } else { throwMissingTransform("opacity"); } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableValue.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableValue.java index 70105fbd99..72fbb62642 100644 --- a/lottie/src/main/java/com/airbnb/lottie/AnimatableValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableValue.java @@ -1,7 +1,10 @@ package com.airbnb.lottie; interface AnimatableValue { - V valueFromObject(Object object, float scale); BaseKeyframeAnimation createAnimation(); boolean hasAnimation(); + + interface Factory { + V valueFromObject(Object object, float scale); + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/AnimatableValueParser.java b/lottie/src/main/java/com/airbnb/lottie/AnimatableValueParser.java new file mode 100644 index 0000000000..211da7fad0 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/AnimatableValueParser.java @@ -0,0 +1,79 @@ +package com.airbnb.lottie; + +import android.support.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.Collections; +import java.util.List; + +class AnimatableValueParser { + @Nullable private final JSONObject json; + private final float scale; + private final LottieComposition composition; + private final AnimatableValue.Factory valueFactory; + + private AnimatableValueParser(@Nullable JSONObject json, float scale, LottieComposition + composition, AnimatableValue.Factory valueFactory) { + this.json = json; + this.scale = scale; + this.composition = composition; + this.valueFactory = valueFactory; + } + + static AnimatableValueParser newInstance(@Nullable JSONObject json, float scale, + LottieComposition composition, AnimatableValue.Factory valueFactory) { + return new AnimatableValueParser<>(json, scale, composition, valueFactory); + } + + Result parseJson() { + List> keyframes = parseKeyframes(); + T initialValue = parseInitialValue(keyframes); + return new Result<>(keyframes, initialValue); + } + + private List> 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(); + } + } else { + return Collections.emptyList(); + } + } + + @Nullable private T parseInitialValue(List> keyframes) { + if (json != null) { + if (!keyframes.isEmpty()) { + return keyframes.get(0).startValue; + } else { + return valueFactory.valueFromObject(json.opt("k"), scale); + } + } else { + return null; + } + } + + private static boolean hasKeyframes(Object json) { + if (!(json instanceof JSONArray)) { + return false; + } else { + Object firstObject = ((JSONArray) json).opt(0); + return firstObject instanceof JSONObject && ((JSONObject) firstObject).has("t"); + } + } + + static class Result { + final List> keyframes; + final @Nullable T initialValue; + + Result(List> keyframes, @Nullable T initialValue) { + this.keyframes = keyframes; + this.initialValue = initialValue; + } + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/BaseAnimatableValue.java b/lottie/src/main/java/com/airbnb/lottie/BaseAnimatableValue.java index d60cd03830..4e774eb2e0 100644 --- a/lottie/src/main/java/com/airbnb/lottie/BaseAnimatableValue.java +++ b/lottie/src/main/java/com/airbnb/lottie/BaseAnimatableValue.java @@ -1,57 +1,25 @@ package com.airbnb.lottie; -import android.support.annotation.Nullable; - -import org.json.JSONArray; -import org.json.JSONObject; - import java.util.Arrays; import java.util.Collections; import java.util.List; abstract class BaseAnimatableValue implements AnimatableValue { - List> keyframes = Collections.emptyList(); + final List> keyframes; final LottieComposition composition; - private final boolean isDp; + final V initialValue; - V initialValue; - - /** Create a default static animatable path. */ - BaseAnimatableValue(LottieComposition composition) { - this.composition = composition; - isDp = false; + /** + * Create a default static animatable path. + */ + BaseAnimatableValue(LottieComposition composition, V initialValue) { + this(Collections.>emptyList(), composition, initialValue); } - BaseAnimatableValue(@Nullable JSONObject json, LottieComposition composition, boolean isDp) { + BaseAnimatableValue(List> keyframes, LottieComposition composition, V initialValue) { + this.keyframes = keyframes; this.composition = composition; - this.isDp = isDp; - if (json != null) { - Object k = json.opt("k"); - if (hasKeyframes(k)) { - keyframes = Keyframe.Factory.parseKeyframes((JSONArray) k, composition, getScale(), this); - if (!keyframes.isEmpty()) { - initialValue = keyframes.get(0).startValue; - } - } else { - initialValue = valueFromObject(k, getScale()); - } - if (keyframes == null) { - keyframes = Collections.emptyList(); - } - } - } - - private boolean hasKeyframes(Object json) { - if (!(json instanceof JSONArray)) { - return false; - } - - Object firstObject = ((JSONArray) json).opt(0); - return firstObject instanceof JSONObject && ((JSONObject) firstObject).has("t"); - } - - private float getScale() { - return isDp ? composition.getScale() : 1f; + this.initialValue = initialValue; } /** @@ -71,11 +39,9 @@ public O getInitialValue() { return convertType(initialValue); } - public abstract BaseKeyframeAnimation createAnimation(); - @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("initialValue=").append(initialValue); + sb.append("parseInitialValue=").append(initialValue); if (!keyframes.isEmpty()) { sb.append(", values=").append(Arrays.toString(keyframes.toArray())); } diff --git a/lottie/src/main/java/com/airbnb/lottie/CircleShape.java b/lottie/src/main/java/com/airbnb/lottie/CircleShape.java index 5652fc1053..f8c281e5eb 100644 --- a/lottie/src/main/java/com/airbnb/lottie/CircleShape.java +++ b/lottie/src/main/java/com/airbnb/lottie/CircleShape.java @@ -19,7 +19,7 @@ static CircleShape newInstance(JSONObject json, LottieComposition composition) { return new CircleShape( AnimatablePathValue .createAnimatablePathOrSplitDimensionPath(json.optJSONObject("p"), composition), - new AnimatablePointValue(json.optJSONObject("s"), composition)); + AnimatablePointValue.Factory.newInstance(json.optJSONObject("s"), composition)); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/ColorFactory.java b/lottie/src/main/java/com/airbnb/lottie/ColorFactory.java index 62ef771b60..066ea54035 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ColorFactory.java +++ b/lottie/src/main/java/com/airbnb/lottie/ColorFactory.java @@ -4,11 +4,10 @@ import org.json.JSONArray; -class ColorFactory { - private ColorFactory() { - } +class ColorFactory implements AnimatableValue.Factory { + static final ColorFactory INSTANCE = new ColorFactory(); - static Integer newInstance(Object object) { + @Override public Integer valueFromObject(Object object, float scale) { JSONArray colorArray = (JSONArray) object; if (colorArray.length() == 4) { boolean shouldUse255 = true; diff --git a/lottie/src/main/java/com/airbnb/lottie/Keyframe.java b/lottie/src/main/java/com/airbnb/lottie/Keyframe.java index b0ea0e724b..cbf95d5b5f 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Keyframe.java +++ b/lottie/src/main/java/com/airbnb/lottie/Keyframe.java @@ -87,7 +87,7 @@ private Factory() { } static Keyframe newInstance(JSONObject json, LottieComposition composition, float scale, - AnimatableValue animatableValue) { + AnimatableValue.Factory valueFactory) { PointF cp1 = null; PointF cp2 = null; float startFrame = 0; @@ -99,12 +99,12 @@ static Keyframe newInstance(JSONObject json, LottieComposition compositio startFrame = (float) json.optDouble("t", 0); Object startValueJson = json.opt("s"); if (startValueJson != null) { - startValue = animatableValue.valueFromObject(startValueJson, scale); + startValue = valueFactory.valueFromObject(startValueJson, scale); } Object endValueJson = json.opt("e"); if (endValueJson != null) { - endValue = animatableValue.valueFromObject(endValueJson, scale); + endValue = valueFactory.valueFromObject(endValueJson, scale); } JSONObject cp1Json = json.optJSONObject("o"); @@ -127,14 +127,14 @@ static Keyframe newInstance(JSONObject json, LottieComposition compositio interpolator = LINEAR_INTERPOLATOR; } } else { - startValue = animatableValue.valueFromObject(json, scale); + startValue = valueFactory.valueFromObject(json, scale); endValue = startValue; } return new Keyframe<>(composition, startValue, endValue, interpolator, startFrame, null); } static List> parseKeyframes(JSONArray json, LottieComposition composition, - float scale, AnimatableValue animatableValue) { + float scale, AnimatableValue.Factory valueFactory) { int length = json.length(); if (length == 0) { return Collections.emptyList(); @@ -142,7 +142,7 @@ static List> parseKeyframes(JSONArray json, LottieComposition co List> keyframes = new ArrayList<>(); for (int i = 0; i < length; i++) { keyframes.add(Keyframe.Factory.newInstance(json.optJSONObject(i), composition, scale, - animatableValue)); + valueFactory)); } setEndFrames(keyframes); diff --git a/lottie/src/main/java/com/airbnb/lottie/Mask.java b/lottie/src/main/java/com/airbnb/lottie/Mask.java index 77190b60a9..6fcad96ca6 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Mask.java +++ b/lottie/src/main/java/com/airbnb/lottie/Mask.java @@ -38,8 +38,8 @@ static Mask newMask(JSONObject json, LottieComposition composition) { maskMode = MaskMode.MaskModeUnknown; } - AnimatableShapeValue maskPath = new AnimatableShapeValue(json.optJSONObject("pt"), - composition); + AnimatableShapeValue maskPath = AnimatableShapeValue.Factory.newInstance( + json.optJSONObject("pt"), composition); // TODO: use this // JSONObject opacityJson = json.optJSONObject("o"); // if (opacityJson != null) { diff --git a/lottie/src/main/java/com/airbnb/lottie/PathKeyframe.java b/lottie/src/main/java/com/airbnb/lottie/PathKeyframe.java index 075fed5e78..0d7680b2bf 100644 --- a/lottie/src/main/java/com/airbnb/lottie/PathKeyframe.java +++ b/lottie/src/main/java/com/airbnb/lottie/PathKeyframe.java @@ -22,9 +22,9 @@ private Factory() { } static PathKeyframe newInstance(JSONObject json, LottieComposition composition, - AnimatableValue animatableValue) { + AnimatableValue.Factory valueFactory) { Keyframe keyframe = Keyframe.Factory.newInstance(json, composition, - composition.getScale(), animatableValue); + composition.getScale(), valueFactory); PointF cp1 = null; PointF cp2 = null; JSONArray tiJson = json.optJSONArray("ti"); diff --git a/lottie/src/main/java/com/airbnb/lottie/PointFFactory.java b/lottie/src/main/java/com/airbnb/lottie/PointFFactory.java index 372a3c12f8..12c38d08a4 100644 --- a/lottie/src/main/java/com/airbnb/lottie/PointFFactory.java +++ b/lottie/src/main/java/com/airbnb/lottie/PointFFactory.java @@ -5,8 +5,13 @@ import org.json.JSONArray; import org.json.JSONObject; -class PointFFactory { - static PointF newInstance(Object object, float scale) { +class PointFFactory implements AnimatableValue.Factory { + static final PointFFactory INSTANCE = new PointFFactory(); + + private PointFFactory() { + } + + @Override public PointF valueFromObject(Object object, float scale) { if (object instanceof JSONArray) { return JsonUtils.pointFromJsonArray((JSONArray) object, scale); } else if (object instanceof JSONObject) { diff --git a/lottie/src/main/java/com/airbnb/lottie/PolystarShape.java b/lottie/src/main/java/com/airbnb/lottie/PolystarShape.java index 877126c282..818f0520d8 100644 --- a/lottie/src/main/java/com/airbnb/lottie/PolystarShape.java +++ b/lottie/src/main/java/com/airbnb/lottie/PolystarShape.java @@ -53,21 +53,23 @@ private Factory() { static PolystarShape newInstance(JSONObject json, LottieComposition composition) { Type type = Type.forValue(json.optInt("sy")); AnimatableFloatValue points = - new AnimatableFloatValue(json.optJSONObject("pt"), composition, false); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("pt"), composition, false); IAnimatablePathValue position = AnimatablePathValue.createAnimatablePathOrSplitDimensionPath( json.optJSONObject("p"), composition); AnimatableFloatValue rotation = - new AnimatableFloatValue(json.optJSONObject("r"), composition, false); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("r"), composition, false); AnimatableFloatValue outerRadius = - new AnimatableFloatValue(json.optJSONObject("or"), composition); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("or"), composition); AnimatableFloatValue outerRoundedness = - new AnimatableFloatValue(json.optJSONObject("os"), composition, false); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("os"), composition, false); AnimatableFloatValue innerRadius; AnimatableFloatValue innerRoundedness; if (type == Type.Star) { - innerRadius = new AnimatableFloatValue(json.optJSONObject("ir"), composition); - innerRoundedness = new AnimatableFloatValue(json.optJSONObject("is"), composition, false); + innerRadius = + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("ir"), composition); + innerRoundedness = + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("is"), composition, false); } else { innerRadius = null; innerRoundedness = null; diff --git a/lottie/src/main/java/com/airbnb/lottie/RectangleShape.java b/lottie/src/main/java/com/airbnb/lottie/RectangleShape.java index ebeefc04e1..09e46a3ba6 100644 --- a/lottie/src/main/java/com/airbnb/lottie/RectangleShape.java +++ b/lottie/src/main/java/com/airbnb/lottie/RectangleShape.java @@ -22,8 +22,8 @@ static RectangleShape newInstance(JSONObject json, LottieComposition composition return new RectangleShape( AnimatablePathValue.createAnimatablePathOrSplitDimensionPath( json.optJSONObject("p"), composition), - new AnimatablePointValue(json.optJSONObject("s"), composition), - new AnimatableFloatValue(json.optJSONObject("r"), composition)); + AnimatablePointValue.Factory.newInstance(json.optJSONObject("s"), composition), + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("r"), composition)); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/ScaleXY.java b/lottie/src/main/java/com/airbnb/lottie/ScaleXY.java index 6452375dda..4431783354 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ScaleXY.java +++ b/lottie/src/main/java/com/airbnb/lottie/ScaleXY.java @@ -27,11 +27,13 @@ float getScaleY() { return getScaleX() + "x" + getScaleY(); } - static class Factory { + static class Factory implements AnimatableValue.Factory { + static final Factory INSTANCE = new Factory(); + private Factory() { } - static ScaleXY newInstance(Object object, float scale) { + @Override public ScaleXY valueFromObject(Object object, float scale) { JSONArray array = (JSONArray) object; return new ScaleXY( (float) array.optDouble(0, 1) / 100f * scale, diff --git a/lottie/src/main/java/com/airbnb/lottie/ShapeData.java b/lottie/src/main/java/com/airbnb/lottie/ShapeData.java index b6b2969ca6..7e11de260a 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ShapeData.java +++ b/lottie/src/main/java/com/airbnb/lottie/ShapeData.java @@ -97,11 +97,13 @@ void interpolateBetween(ShapeData shapeData1, ShapeData shapeData2, '}'; } - static class Factory { + static class Factory implements AnimatableValue.Factory { + static final ShapeData.Factory INSTANCE = new Factory(); + private Factory() { } - static ShapeData newInstance(Object object, float scale) { + @Override public ShapeData valueFromObject(Object object, float scale) { JSONObject pointsData = null; if (object instanceof JSONArray) { Object firstObject = ((JSONArray) object).opt(0); diff --git a/lottie/src/main/java/com/airbnb/lottie/ShapeFill.java b/lottie/src/main/java/com/airbnb/lottie/ShapeFill.java index 67e6e7630d..e854a1a5fb 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ShapeFill.java +++ b/lottie/src/main/java/com/airbnb/lottie/ShapeFill.java @@ -27,12 +27,12 @@ static ShapeFill newInstance(JSONObject json, LottieComposition composition) { JSONObject jsonColor = json.optJSONObject("c"); if (jsonColor != null) { - color = new AnimatableColorValue(jsonColor, composition); + color = AnimatableColorValue.Factory.newInstance(jsonColor, composition); } JSONObject jsonOpacity = json.optJSONObject("o"); if (jsonOpacity != null) { - opacity = new AnimatableIntegerValue(jsonOpacity, composition, false, true); + opacity = AnimatableIntegerValue.Factory.newInstance(jsonOpacity, composition, false, true); } fillEnabled = json.optBoolean("fillEnabled"); return new ShapeFill(fillEnabled, color, opacity); diff --git a/lottie/src/main/java/com/airbnb/lottie/ShapePath.java b/lottie/src/main/java/com/airbnb/lottie/ShapePath.java index a3b362d255..973c6e1155 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ShapePath.java +++ b/lottie/src/main/java/com/airbnb/lottie/ShapePath.java @@ -18,8 +18,9 @@ private Factory() { } static ShapePath newInstance(JSONObject json, LottieComposition composition) { - return new ShapePath(json.optString("nm"), json.optInt("ind"), - new AnimatableShapeValue(json.optJSONObject("ks"), composition)); + AnimatableShapeValue animatableShapeValue = + AnimatableShapeValue.Factory.newInstance(json.optJSONObject("ks"), composition); + return new ShapePath(json.optString("nm"), json.optInt("ind"), animatableShapeValue); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/ShapeStroke.java b/lottie/src/main/java/com/airbnb/lottie/ShapeStroke.java index 061dcbf286..230c715ab7 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ShapeStroke.java +++ b/lottie/src/main/java/com/airbnb/lottie/ShapeStroke.java @@ -48,10 +48,12 @@ private Factory() { static ShapeStroke newInstance(JSONObject json, LottieComposition composition) { List lineDashPattern = new ArrayList<>(); - AnimatableColorValue color = new AnimatableColorValue(json.optJSONObject("c"), composition); - AnimatableFloatValue width = new AnimatableFloatValue(json.optJSONObject("w"), composition); - AnimatableIntegerValue opacity = new AnimatableIntegerValue(json.optJSONObject("o"), - composition, false, true); + AnimatableColorValue color = AnimatableColorValue.Factory.newInstance(json.optJSONObject("c"), + composition); + AnimatableFloatValue width = AnimatableFloatValue.Factory.newInstance(json.optJSONObject("w"), + composition); + AnimatableIntegerValue opacity = AnimatableIntegerValue.Factory.newInstance( + json.optJSONObject("o"), composition, false, true); LineCapType capType = LineCapType.values()[json.optInt("lc") - 1]; LineJoinType joinType = LineJoinType.values()[json.optInt("lj") - 1]; AnimatableFloatValue offset = null; @@ -63,10 +65,10 @@ static ShapeStroke newInstance(JSONObject json, LottieComposition composition) { String n = dashJson.optString("n"); if (n.equals("o")) { JSONObject value = dashJson.optJSONObject("v"); - offset = new AnimatableFloatValue(value, composition); + offset = AnimatableFloatValue.Factory.newInstance(value, composition); } else if (n.equals("d") || n.equals("g")) { JSONObject value = dashJson.optJSONObject("v"); - lineDashPattern.add(new AnimatableFloatValue(value, composition)); + lineDashPattern.add(AnimatableFloatValue.Factory.newInstance(value, composition)); } } if (lineDashPattern.size() == 1) { diff --git a/lottie/src/main/java/com/airbnb/lottie/ShapeTrimPath.java b/lottie/src/main/java/com/airbnb/lottie/ShapeTrimPath.java index 86e055831d..a9da1e3e6c 100644 --- a/lottie/src/main/java/com/airbnb/lottie/ShapeTrimPath.java +++ b/lottie/src/main/java/com/airbnb/lottie/ShapeTrimPath.java @@ -20,9 +20,9 @@ private Factory() { static ShapeTrimPath newInstance(JSONObject json, LottieComposition composition) { return new ShapeTrimPath( - new AnimatableFloatValue(json.optJSONObject("s"), composition, false), - new AnimatableFloatValue(json.optJSONObject("e"), composition, false), - new AnimatableFloatValue(json.optJSONObject("o"), composition, false)); + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("s"), composition, false), + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("e"), composition, false), + AnimatableFloatValue.Factory.newInstance(json.optJSONObject("o"), composition, false)); } }