Allow interpolating between gradients with different opacity stops (#2160)
Fixes #2104
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 027c6c6..963b7ff 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
@@ -5,13 +5,49 @@
import com.airbnb.lottie.model.content.GradientColor;
import com.airbnb.lottie.value.Keyframe;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class AnimatableGradientColorValue extends BaseAnimatableValue<GradientColor,
GradientColor> {
- public AnimatableGradientColorValue(
- List<Keyframe<GradientColor>> keyframes) {
- super(keyframes);
+ public AnimatableGradientColorValue(List<Keyframe<GradientColor>> keyframes) {
+ super(ensureInterpolatableKeyframes(keyframes));
+ }
+
+ private static List<Keyframe<GradientColor>> ensureInterpolatableKeyframes(List<Keyframe<GradientColor>> keyframes) {
+ for (int i = 0; i < keyframes.size(); i++) {
+ keyframes.set(i, ensureInterpolatableKeyframe(keyframes.get(i)));
+ }
+ return keyframes;
+ }
+
+ private static Keyframe<GradientColor> ensureInterpolatableKeyframe(Keyframe<GradientColor> keyframe) {
+ GradientColor startValue = keyframe.startValue;
+ GradientColor endValue = keyframe.endValue;
+ if (startValue == null || endValue == null || startValue.getPositions().length == endValue.getPositions().length) {
+ return keyframe;
+ }
+ float[] mergedPositions = mergePositions(startValue.getPositions(), endValue.getPositions());
+ // The start/end has opacity stops which required adding extra positions in between the existing colors.
+ return keyframe.copyWith(startValue.copyWithPositions(mergedPositions), endValue.copyWithPositions(mergedPositions));
+ }
+
+ static float[] mergePositions(float[] startPositions, float[] endPositions) {
+ float[] mergedArray = new float[startPositions.length + endPositions.length];
+ System.arraycopy(startPositions, 0, mergedArray, 0, startPositions.length);
+ System.arraycopy(endPositions, 0, mergedArray, startPositions.length, endPositions.length);
+ Arrays.sort(mergedArray);
+ int uniqueValues = 0;
+ float lastValue = Float.NaN;
+ for (int i = 0; i < mergedArray.length; i++) {
+ if (mergedArray[i] != lastValue) {
+ mergedArray[uniqueValues] = mergedArray[i];
+ uniqueValues++;
+ lastValue = mergedArray[i];
+ }
+ }
+ return Arrays.copyOfRange(mergedArray, 0, uniqueValues);
}
@Override public BaseKeyframeAnimation<GradientColor, GradientColor> createAnimation() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientColor.java b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientColor.java
index 8385c15..aa69e04 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientColor.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientColor.java
@@ -3,6 +3,8 @@
import com.airbnb.lottie.utils.GammaEvaluator;
import com.airbnb.lottie.utils.MiscUtils;
+import java.util.Arrays;
+
public class GradientColor {
private final float[] positions;
@@ -36,4 +38,33 @@
colors[i] = GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]);
}
}
+
+ public GradientColor copyWithPositions(float[] positions) {
+ int[] colors = new int[positions.length];
+ for (int i = 0; i < positions.length; i++) {
+ colors[i] = getColorForPosition(positions[i]);
+ }
+ return new GradientColor(positions, colors);
+ }
+
+ private int getColorForPosition(float position) {
+ int existingIndex = Arrays.binarySearch(positions, position);
+ if (existingIndex >= 0) {
+ return colors[existingIndex];
+ }
+ // binarySearch returns -insertionPoint - 1 if it is not found.
+ int insertionPoint = -(existingIndex + 1);
+ if (insertionPoint == 0) {
+ return colors[0];
+ } else if (insertionPoint == colors.length - 1) {
+ return colors[colors.length - 1];
+ }
+ float startPosition = positions[insertionPoint - 1];
+ float endPosition = positions[insertionPoint];
+ int startColor = colors[insertionPoint - 1];
+ int endColor = colors[insertionPoint];
+
+ float fraction = (position - startPosition) / (endPosition - startPosition);
+ return GammaEvaluator.evaluate(fraction, startColor, endColor);
+ }
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableValueParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableValueParser.java
index 01ea02c..99ff81d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableValueParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableValueParser.java
@@ -65,8 +65,9 @@
static AnimatableGradientColorValue parseGradientColor(
JsonReader reader, LottieComposition composition, int points) throws IOException {
- return new AnimatableGradientColorValue(
+ AnimatableGradientColorValue animatableGradientColorValue = new AnimatableGradientColorValue(
parse(reader, composition, new GradientColorParser(points)));
+ return animatableGradientColorValue;
}
/**
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/GradientColorParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/GradientColorParser.java
index 50a52e3..f1c5641 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/GradientColorParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/GradientColorParser.java
@@ -4,6 +4,7 @@
import com.airbnb.lottie.model.content.GradientColor;
import com.airbnb.lottie.parser.moshi.JsonReader;
+import com.airbnb.lottie.utils.GammaEvaluator;
import com.airbnb.lottie.utils.MiscUtils;
import java.io.IOException;
@@ -167,7 +168,7 @@
return new GradientColor(newPositions, newColors);
}
- private int getColorInBetweenColorStops(float position, float opacity, float[] colorStopPositions, int[] colorStopColors) {
+ int getColorInBetweenColorStops(float position, float opacity, float[] colorStopPositions, int[] colorStopColors) {
if (colorStopColors.length < 2 || position == colorStopPositions[0]) {
return colorStopColors[0];
}
@@ -183,9 +184,9 @@
int upperColor = colorStopColors[i];
int lowerColor = colorStopColors[i - 1];
int a = (int) (opacity * 255);
- int r = MiscUtils.lerp(Color.red(lowerColor), Color.red(upperColor), percentage);
- int g = MiscUtils.lerp(Color.green(lowerColor), Color.green(upperColor), percentage);
- int b = MiscUtils.lerp(Color.blue(lowerColor), Color.blue(upperColor), percentage);
+ int r = GammaEvaluator.evaluate(percentage, Color.red(lowerColor), Color.red(upperColor));
+ int g = GammaEvaluator.evaluate(percentage, Color.green(lowerColor), Color.green(upperColor));
+ int b = GammaEvaluator.evaluate(percentage, Color.blue(lowerColor), Color.blue(upperColor));
return Color.argb(a, r, g, b);
}
throw new IllegalArgumentException("Unreachable code.");
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/Keyframe.java b/lottie/src/main/java/com/airbnb/lottie/value/Keyframe.java
index 78f74db..6d110b7 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/Keyframe.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/Keyframe.java
@@ -90,6 +90,21 @@
endFrame = Float.MAX_VALUE;
}
+ private Keyframe(T startValue, T endValue) {
+ composition = null;
+ this.startValue = startValue;
+ this.endValue = endValue;
+ interpolator = null;
+ xInterpolator = null;
+ yInterpolator = null;
+ startFrame = Float.MIN_VALUE;
+ endFrame = Float.MAX_VALUE;
+ }
+
+ public Keyframe<T> copyWith(T startValue, T endValue) {
+ return new Keyframe<T>(startValue, endValue);
+ }
+
public float getStartProgress() {
if (composition == null) {
return 0f;
diff --git a/lottie/src/test/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValueTest.java b/lottie/src/test/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValueTest.java
new file mode 100644
index 0000000..0b5004c
--- /dev/null
+++ b/lottie/src/test/java/com/airbnb/lottie/model/animatable/AnimatableGradientColorValueTest.java
@@ -0,0 +1,22 @@
+package com.airbnb.lottie.model.animatable;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class AnimatableGradientColorValueTest {
+ @Test
+ public void testMergeTheSame() {
+ assertArrayEquals(new float[]{1, 2}, AnimatableGradientColorValue.mergePositions(new float[]{1, 2}, new float[]{1, 2}), 0f);
+ }
+
+ @Test
+ public void testMergeDifferent() {
+ assertArrayEquals(new float[]{1, 2, 3, 4}, AnimatableGradientColorValue.mergePositions(new float[]{1, 2}, new float[]{3, 4}), 0f);
+ }
+
+ @Test
+ public void testMergeOneOverlap() {
+ assertArrayEquals(new float[]{1, 2, 3}, AnimatableGradientColorValue.mergePositions(new float[]{1, 2}, new float[]{2, 3}), 0f);
+ }
+}
\ No newline at end of file
diff --git a/snapshot-tests/src/main/assets/Tests/InterpolateBetweenOpacityStops.json b/snapshot-tests/src/main/assets/Tests/InterpolateBetweenOpacityStops.json
new file mode 100755
index 0000000..a049e73
--- /dev/null
+++ b/snapshot-tests/src/main/assets/Tests/InterpolateBetweenOpacityStops.json
@@ -0,0 +1,1038 @@
+{
+ "v": "5.7.4",
+ "fr": 60,
+ "ip": 0,
+ "op": 540,
+ "w": 750,
+ "h": 672,
+ "nm": "app_morning_background",
+ "ddd": 0,
+ "assets": [],
+ "layers": [
+ {
+ "ddd": 0,
+ "ind": 1,
+ "ty": 4,
+ "nm": "City state 2",
+ "td": 1,
+ "sr": 1,
+ "ks": {
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 11
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 10
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 375,
+ 336,
+ 0
+ ],
+ "ix": 2,
+ "l": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0,
+ 0
+ ],
+ "ix": 1,
+ "l": 2
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 100,
+ 100,
+ 100
+ ],
+ "ix": 6,
+ "l": 2
+ }
+ },
+ "ao": 0,
+ "shapes": [
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "ty": "rc",
+ "d": 1,
+ "s": {
+ "a": 0,
+ "k": [
+ 375,
+ 336
+ ],
+ "ix": 2
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 3
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 4
+ },
+ "nm": "Rectangle Path 1",
+ "mn": "ADBE Vector Shape - Rect",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 1
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 200,
+ 200
+ ],
+ "ix": 3
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 6
+ },
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 7
+ },
+ "sk": {
+ "a": 0,
+ "k": 0,
+ "ix": 4
+ },
+ "sa": {
+ "a": 0,
+ "k": 0,
+ "ix": 5
+ },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "City state",
+ "np": 3,
+ "cix": 2,
+ "bm": 0,
+ "ix": 1,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ }
+ ],
+ "ip": 0,
+ "op": 540,
+ "st": 0,
+ "bm": 0
+ },
+ {
+ "ddd": 0,
+ "ind": 2,
+ "ty": 4,
+ "nm": "Ellipse 3",
+ "tt": 2,
+ "sr": 1,
+ "ks": {
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 11
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 10
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 375,
+ 699,
+ 0
+ ],
+ "ix": 2,
+ "l": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0,
+ 0
+ ],
+ "ix": 1,
+ "l": 2
+ },
+ "s": {
+ "a": 1,
+ "k": [
+ {
+ "i": {
+ "x": [
+ 0.52,
+ 0.52,
+ 0.52
+ ],
+ "y": [
+ 0.979,
+ 0.984,
+ 1
+ ]
+ },
+ "o": {
+ "x": [
+ 0.48,
+ 0.48,
+ 0.48
+ ],
+ "y": [
+ 0.021,
+ 0.016,
+ 0
+ ]
+ },
+ "t": 0,
+ "s": [
+ 100,
+ 66,
+ 100
+ ],
+ "e": [
+ 173,
+ 147,
+ 100
+ ]
+ },
+ {
+ "i": {
+ "x": [
+ 0.52,
+ 0.52,
+ 0.52
+ ],
+ "y": [
+ 1,
+ 1,
+ 1
+ ]
+ },
+ "o": {
+ "x": [
+ 0.48,
+ 0.48,
+ 0.48
+ ],
+ "y": [
+ 0,
+ 0,
+ 0
+ ]
+ },
+ "t": 289,
+ "s": [
+ 173,
+ 147,
+ 100
+ ],
+ "e": [
+ 199,
+ 169.092,
+ 100
+ ]
+ },
+ {
+ "i": {
+ "x": [
+ 0.52,
+ 0.52,
+ 0.52
+ ],
+ "y": [
+ 1,
+ 1,
+ 1
+ ]
+ },
+ "o": {
+ "x": [
+ 0.48,
+ 0.48,
+ 0.48
+ ],
+ "y": [
+ 0,
+ 0,
+ 0
+ ]
+ },
+ "t": 300,
+ "s": [
+ 199,
+ 169.092,
+ 100
+ ],
+ "e": [
+ 100,
+ 66,
+ 100
+ ]
+ },
+ {
+ "t": 540
+ }
+ ],
+ "ix": 6,
+ "l": 2
+ }
+ },
+ "ao": 0,
+ "shapes": [
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "d": 1,
+ "ty": "el",
+ "s": {
+ "a": 0,
+ "k": [
+ 363,
+ 363
+ ],
+ "ix": 2
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 3
+ },
+ "nm": "Ellipse Path 1",
+ "mn": "ADBE Vector Shape - Ellipse",
+ "hd": false
+ },
+ {
+ "ty": "gf",
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 10
+ },
+ "r": 1,
+ "bm": 0,
+ "g": {
+ "p": 5,
+ "k": {
+ "a": 1,
+ "k": [
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 0,
+ "s": [
+ 0,
+ 0.956,
+ 0.474,
+ 0.442,
+ 0.265,
+ 0.89,
+ 0.468,
+ 0.367,
+ 0.529,
+ 0.824,
+ 0.461,
+ 0.292,
+ 0.765,
+ 0.878,
+ 0.614,
+ 0.397,
+ 1,
+ 0.931,
+ 0.766,
+ 0.502,
+ 0,
+ 1,
+ 0.256,
+ 0.665,
+ 0.513,
+ 0.33,
+ 0.756,
+ 0.165,
+ 1,
+ 0
+ ],
+ "e": [
+ 0.001,
+ 1,
+ 0.798,
+ 0.325,
+ 0.293,
+ 0.988,
+ 0.775,
+ 0.278,
+ 0.584,
+ 0.975,
+ 0.752,
+ 0.23,
+ 0.79,
+ 0.988,
+ 0.844,
+ 0.437,
+ 0.996,
+ 1,
+ 0.936,
+ 0.643,
+ 0,
+ 1,
+ 0.302,
+ 0.635,
+ 0.604,
+ 0.27,
+ 0.802,
+ 0.135,
+ 1,
+ 0
+ ]
+ },
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 247,
+ "s": [
+ 0.001,
+ 1,
+ 0.798,
+ 0.325,
+ 0.293,
+ 0.988,
+ 0.775,
+ 0.278,
+ 0.584,
+ 0.975,
+ 0.752,
+ 0.23,
+ 0.79,
+ 0.988,
+ 0.844,
+ 0.437,
+ 0.996,
+ 1,
+ 0.936,
+ 0.643,
+ 0,
+ 1,
+ 0.302,
+ 0.635,
+ 0.604,
+ 0.27,
+ 0.802,
+ 0.135,
+ 1,
+ 0
+ ],
+ "e": [
+ 0,
+ 0.902,
+ 0.669,
+ 0.18,
+ 0.265,
+ 0.94,
+ 0.643,
+ 0.283,
+ 0.529,
+ 0.979,
+ 0.616,
+ 0.387,
+ 0.765,
+ 0.949,
+ 0.577,
+ 0.331,
+ 1,
+ 0.919,
+ 0.537,
+ 0.275,
+ 0,
+ 1,
+ 0.264,
+ 0.665,
+ 0.527,
+ 0.33,
+ 0.764,
+ 0.165,
+ 1,
+ 0
+ ]
+ },
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 301,
+ "s": [
+ 0,
+ 0.902,
+ 0.669,
+ 0.18,
+ 0.265,
+ 0.94,
+ 0.643,
+ 0.283,
+ 0.529,
+ 0.979,
+ 0.616,
+ 0.387,
+ 0.765,
+ 0.949,
+ 0.577,
+ 0.331,
+ 1,
+ 0.919,
+ 0.537,
+ 0.275,
+ 0,
+ 1,
+ 0.264,
+ 0.665,
+ 0.527,
+ 0.33,
+ 0.764,
+ 0.165,
+ 1,
+ 0
+ ],
+ "e": [
+ 0,
+ 0.956,
+ 0.474,
+ 0.442,
+ 0.265,
+ 0.89,
+ 0.468,
+ 0.367,
+ 0.529,
+ 0.824,
+ 0.461,
+ 0.292,
+ 0.765,
+ 0.878,
+ 0.614,
+ 0.397,
+ 1,
+ 0.931,
+ 0.766,
+ 0.502,
+ 0,
+ 1,
+ 0.256,
+ 0.665,
+ 0.513,
+ 0.33,
+ 0.756,
+ 0.165,
+ 1,
+ 0
+ ]
+ },
+ {
+ "t": 540
+ }
+ ],
+ "ix": 9
+ }
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 5
+ },
+ "e": {
+ "a": 0,
+ "k": [
+ 181.5,
+ 0
+ ],
+ "ix": 6
+ },
+ "t": 2,
+ "h": {
+ "a": 0,
+ "k": 0,
+ "ix": 7
+ },
+ "a": {
+ "a": 0,
+ "k": 0,
+ "ix": 8
+ },
+ "nm": "Gradient Fill 1",
+ "mn": "ADBE Vector Graphic - G-Fill",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 1
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 200,
+ 200
+ ],
+ "ix": 3
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 6
+ },
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 7
+ },
+ "sk": {
+ "a": 0,
+ "k": 0,
+ "ix": 4
+ },
+ "sa": {
+ "a": 0,
+ "k": 0,
+ "ix": 5
+ },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Ellipse 3",
+ "np": 2,
+ "cix": 2,
+ "bm": 0,
+ "ix": 1,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ }
+ ],
+ "ip": 0,
+ "op": 540,
+ "st": 0,
+ "bm": 0
+ },
+ {
+ "ddd": 0,
+ "ind": 3,
+ "ty": 4,
+ "nm": "Shape Layer 1",
+ "sr": 1,
+ "ks": {
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 11
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 10
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 375,
+ 336,
+ 0
+ ],
+ "ix": 2,
+ "l": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0,
+ 0
+ ],
+ "ix": 1,
+ "l": 2
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 100,
+ 100,
+ 100
+ ],
+ "ix": 6,
+ "l": 2
+ }
+ },
+ "ao": 0,
+ "shapes": [
+ {
+ "ty": "gr",
+ "it": [
+ {
+ "ty": "rc",
+ "d": 1,
+ "s": {
+ "a": 0,
+ "k": [
+ 750,
+ 672
+ ],
+ "ix": 2
+ },
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 3
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 4
+ },
+ "nm": "Rectangle Path 1",
+ "mn": "ADBE Vector Shape - Rect",
+ "hd": false
+ },
+ {
+ "ty": "gf",
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 10
+ },
+ "r": 1,
+ "bm": 0,
+ "g": {
+ "p": 5,
+ "k": {
+ "a": 1,
+ "k": [
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 0,
+ "s": [
+ 0,
+ 0.971,
+ 0.408,
+ 0,
+ 0.377,
+ 0.956,
+ 0.515,
+ 0,
+ 0.755,
+ 0.942,
+ 0.621,
+ 0,
+ 0.877,
+ 0.971,
+ 0.671,
+ 0,
+ 1,
+ 1,
+ 0.72,
+ 0
+ ],
+ "e": [
+ 0,
+ 0.966,
+ 0.445,
+ 0,
+ 0.362,
+ 0.951,
+ 0.51,
+ 0,
+ 0.725,
+ 0.936,
+ 0.576,
+ 0,
+ 0.862,
+ 0.967,
+ 0.628,
+ 0,
+ 1,
+ 0.998,
+ 0.68,
+ 0
+ ]
+ },
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 49,
+ "s": [
+ 0,
+ 0.966,
+ 0.445,
+ 0,
+ 0.362,
+ 0.951,
+ 0.51,
+ 0,
+ 0.725,
+ 0.936,
+ 0.576,
+ 0,
+ 0.862,
+ 0.967,
+ 0.628,
+ 0,
+ 1,
+ 0.998,
+ 0.68,
+ 0
+ ],
+ "e": [
+ 0,
+ 0.946,
+ 0.606,
+ 0,
+ 0.275,
+ 0.928,
+ 0.492,
+ 0,
+ 0.55,
+ 0.91,
+ 0.378,
+ 0,
+ 0.775,
+ 0.948,
+ 0.442,
+ 0,
+ 1,
+ 0.987,
+ 0.507,
+ 0
+ ]
+ },
+ {
+ "i": {
+ "x": 0.833,
+ "y": 0.833
+ },
+ "o": {
+ "x": 0.167,
+ "y": 0.167
+ },
+ "t": 260.375,
+ "s": [
+ 0,
+ 0.946,
+ 0.606,
+ 0,
+ 0.275,
+ 0.928,
+ 0.492,
+ 0,
+ 0.55,
+ 0.91,
+ 0.378,
+ 0,
+ 0.775,
+ 0.948,
+ 0.442,
+ 0,
+ 1,
+ 0.987,
+ 0.507,
+ 0
+ ],
+ "e": [
+ 0,
+ 0.971,
+ 0.408,
+ 0,
+ 0.383,
+ 0.956,
+ 0.515,
+ 0,
+ 0.766,
+ 0.942,
+ 0.621,
+ 0,
+ 0.883,
+ 0.971,
+ 0.671,
+ 0,
+ 1,
+ 1,
+ 0.72,
+ 0
+ ]
+ },
+ {
+ "t": 540
+ }
+ ],
+ "ix": 9
+ }
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ -2.047,
+ 331.848
+ ],
+ "ix": 5
+ },
+ "e": {
+ "a": 0,
+ "k": [
+ 3.137,
+ -336.078
+ ],
+ "ix": 6
+ },
+ "t": 1,
+ "nm": "Gradient Fill 1",
+ "mn": "ADBE Vector Graphic - G-Fill",
+ "hd": false
+ },
+ {
+ "ty": "tr",
+ "p": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 2
+ },
+ "a": {
+ "a": 0,
+ "k": [
+ 0,
+ 0
+ ],
+ "ix": 1
+ },
+ "s": {
+ "a": 0,
+ "k": [
+ 100,
+ 100
+ ],
+ "ix": 3
+ },
+ "r": {
+ "a": 0,
+ "k": 0,
+ "ix": 6
+ },
+ "o": {
+ "a": 0,
+ "k": 100,
+ "ix": 7
+ },
+ "sk": {
+ "a": 0,
+ "k": 0,
+ "ix": 4
+ },
+ "sa": {
+ "a": 0,
+ "k": 0,
+ "ix": 5
+ },
+ "nm": "Transform"
+ }
+ ],
+ "nm": "Rectangle 1",
+ "np": 2,
+ "cix": 2,
+ "bm": 0,
+ "ix": 1,
+ "mn": "ADBE Vector Group",
+ "hd": false
+ }
+ ],
+ "ip": 0,
+ "op": 540,
+ "st": 0,
+ "bm": 0
+ }
+ ],
+ "markers": []
+}
\ No newline at end of file