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 c4c1a51d4..2ce54d8d0 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 @@ -10,12 +10,22 @@ public class GradientColorKeyframeAnimation extends KeyframeAnimation> keyframes) { super(keyframes); - GradientColor startValue = keyframes.get(0).startValue; - int size = startValue == null ? 0 : startValue.getSize(); + // Not all keyframes that this GradientColor are used for will have the same length. + // AnimatableGradientColorValue.ensureInterpolatableKeyframes may add extra positions + // for some keyframes but not others to ensure that it is interpolatable. + // Ensure that there is enough space for the largest keyframe. + int size = 0; + for (int i = 0; i < keyframes.size(); i++) { + GradientColor startValue = keyframes.get(i).startValue; + if (startValue != null) { + size = Math.max(size, startValue.getSize()); + } + } gradientColor = new GradientColor(new float[size], new int[size]); } @Override GradientColor getValue(Keyframe keyframe, float keyframeProgress) { + //noinspection DataFlowIssue gradientColor.lerp(keyframe.startValue, keyframe.endValue, keyframeProgress); return gradientColor; } 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 aa69e047e..3485d5832 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 @@ -37,6 +37,15 @@ public void lerp(GradientColor gc1, GradientColor gc2, float progress) { positions[i] = MiscUtils.lerp(gc1.positions[i], gc2.positions[i], progress); colors[i] = GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]); } + + // Not all keyframes that this GradientColor are used for will have the same length. + // AnimatableGradientColorValue.ensureInterpolatableKeyframes may add extra positions + // for some keyframes but not others to ensure that it is interpolatable. + // If there are extra positions here, just duplicate the last value in the gradient. + for (int i = gc1.colors.length; i < positions.length; i++) { + positions[i] = positions[gc1.colors.length - 1]; + colors[i] = colors[gc1.colors.length - 1]; + } } public GradientColor copyWithPositions(float[] positions) { diff --git a/snapshot-tests/src/main/assets/Tests/GradientWithVaryingOpacityStops.json b/snapshot-tests/src/main/assets/Tests/GradientWithVaryingOpacityStops.json new file mode 100644 index 000000000..8ad790c13 --- /dev/null +++ b/snapshot-tests/src/main/assets/Tests/GradientWithVaryingOpacityStops.json @@ -0,0 +1,264 @@ +{ + "v": "5.12.1", + "fr": 60, + "ip": 0, + "op": 240, + "w": 430, + "h": 795, + "nm": "gradient", + "ddd": 0, + "assets": [ + { + "id": "comp_0", + "nm": "gradient", + "fr": 60, + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "1", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 0, + "s": [100] + }, + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 30, + "s": [75] + }, + { "t": 59, "s": [100] } + ], + "ix": 11 + }, + "r": { "a": 0, "k": 0, "ix": 10 }, + "p": { "a": 0, "k": [51.5, 58, 0], "ix": 2, "l": 2 }, + "a": { "a": 0, "k": [-4.5, -130.5, 0], "ix": 1, "l": 2 }, + "s": { "a": 0, "k": [100, 100, 100], "ix": 6, "l": 2 } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 1, + "k": [ + { + "i": { "x": [0.833, 0.833], "y": [0.833, 0.833] }, + "o": { "x": [0.167, 0.167], "y": [0.167, 0.167] }, + "t": 0, + "s": [50, 50] + }, + { + "i": { "x": [0.833, 0.833], "y": [0.833, 0.833] }, + "o": { "x": [0.167, 0.167], "y": [0.167, 0.167] }, + "t": 28, + "s": [46, 46] + }, + { + "i": { "x": [0.833, 0.833], "y": [0.833, 0.833] }, + "o": { "x": [0.167, 0.167], "y": [0.167, 0.167] }, + "t": 59, + "s": [50, 50] + }, + { + "i": { "x": [0.833, 0.833], "y": [0.833, 0.833] }, + "o": { "x": [0.167, 0.167], "y": [0.167, 0.167] }, + "t": 120, + "s": [73.252, 73.252] + }, + { "t": 239, "s": [86.252, 86.252] } + ], + "ix": 2 + }, + "p": { "a": 0, "k": [0, 0], "ix": 3 }, + "nm": "1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "gf", + "o": { + "a": 1, + "k": [ + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 0, + "s": [0] + }, + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 15, + "s": [83] + }, + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 44, + "s": [100] + }, + { "t": 59, "s": [0] } + ], + "ix": 10 + }, + "r": 1, + "bm": 0, + "g": { + "p": 3, + "k": { + "a": 1, + "k": [ + { + "i": { "x": 0.833, "y": 0.833 }, + "o": { "x": 0.167, "y": 0.167 }, + "t": 0, + "s": [ + 0, 1, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 1, 0, 0.1, 0.5, + 0.3, 1, 0.5 + ] + }, + { + "i": { "x": 0.833, "y": 0.833 }, + "o": { "x": 0.167, "y": 0.167 }, + "t": 15, + "s": [ + 0, 0.992, 0.995, 1, 0.5, 0.996, 0.998, 1, 1, 1, 1, + 1, 0, 0.2, 0.5, 0.45, 1, 0.7 + ] + }, + { + "i": { "x": 0.833, "y": 0.833 }, + "o": { "x": 0.167, "y": 0.167 }, + "t": 31, + "s": [ + 0, 1, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 1, 0, 0.1, 0.5, + 0.35, 1, 0.6 + ] + }, + { + "i": { "x": 0.833, "y": 0.833 }, + "o": { "x": 0.167, "y": 0.167 }, + "t": 59, + "s": [ + 0, 1, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 1, 0, 0.2, 0.5, + 0.45, 1, 0.7 + ] + }, + { + "i": { "x": 0.833, "y": 0.833 }, + "o": { "x": 0.167, "y": 0.167 }, + "t": 160, + "s": [ + 0, 0.302, 0.391, 0.586, 0.529, 0.17, 0.239, 0.393, + 1, 0.039, 0.086, 0.2, 0, 1, 0.5, 1, 1, 1 + ] + }, + { + "t": 239, + "s": [ + 0, 0.053, 0.362, 0.77, 0.5, 0.046, 0.224, 0.485, 1, + 0.039, 0.086, 0.2, 0, 1, 0.5, 1, 1, 1 + ] + } + ], + "ix": 9 + } + }, + "s": { "a": 0, "k": [0, 0], "ix": 5 }, + "e": { "a": 0, "k": [29.461, 0.027], "ix": 6 }, + "t": 2, + "h": { "a": 0, "k": 0, "ix": 7 }, + "a": { "a": 0, "k": 0, "ix": 8 }, + "nm": "1", + "mn": "ADBE Vector Graphic - G-Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [-3.372, -136.224], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [110.999, 110.999], "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 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 60, + "st": 0, + "ct": 1, + "bm": 0 + } + ] + } + ], + "layers": [ + { + "ddd": 0, + "ind": 36, + "ty": 0, + "nm": "", + "refId": "comp_0", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 11, + "s": [0] + }, + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 130, + "s": [100] + }, + { "t": 213, "s": [0] } + ], + "ix": 11 + }, + "r": { "a": 0, "k": 0, "ix": 10 }, + "p": { "a": 0, "k": [168, 285.5, 0], "ix": 2, "l": 2 }, + "a": { "a": 0, "k": [50, 51, 0], "ix": 1, "l": 2 }, + "s": { "a": 0, "k": [100, 100, 100], "ix": 6, "l": 2 } + }, + "ao": 0, + "w": 100, + "h": 102, + "ip": 0, + "op": 60, + "st": 0, + "bm": 0 + } + ], + "markers": [], + "props": {} +}