• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.airbnb.lottie.model.content;
2 
3 import com.airbnb.lottie.utils.GammaEvaluator;
4 import com.airbnb.lottie.utils.MiscUtils;
5 
6 import java.util.Arrays;
7 
8 
9 public class GradientColor {
10   private final float[] positions;
11   private final int[] colors;
12 
GradientColor(float[] positions, int[] colors)13   public GradientColor(float[] positions, int[] colors) {
14     this.positions = positions;
15     this.colors = colors;
16   }
17 
getPositions()18   public float[] getPositions() {
19     return positions;
20   }
21 
getColors()22   public int[] getColors() {
23     return colors;
24   }
25 
getSize()26   public int getSize() {
27     return colors.length;
28   }
29 
lerp(GradientColor gc1, GradientColor gc2, float progress)30   public void lerp(GradientColor gc1, GradientColor gc2, float progress) {
31     // Fast return in case start and end is the same
32     // or if progress is at start/end or out of [0,1] bounds
33     if (gc1.equals(gc2)) {
34       copyFrom(gc1);
35       return;
36     } else if (progress <= 0f) {
37       copyFrom(gc1);
38       return;
39     } else if (progress >= 1f) {
40       copyFrom(gc2);
41       return;
42     }
43 
44     if (gc1.colors.length != gc2.colors.length) {
45       throw new IllegalArgumentException("Cannot interpolate between gradients. Lengths vary (" +
46           gc1.colors.length + " vs " + gc2.colors.length + ")");
47     }
48 
49     for (int i = 0; i < gc1.colors.length; i++) {
50       positions[i] = MiscUtils.lerp(gc1.positions[i], gc2.positions[i], progress);
51       colors[i] = GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]);
52     }
53 
54     // Not all keyframes that this GradientColor are used for will have the same length.
55     // AnimatableGradientColorValue.ensureInterpolatableKeyframes may add extra positions
56     // for some keyframes but not others to ensure that it is interpolatable.
57     // If there are extra positions here, just duplicate the last value in the gradient.
58     for (int i = gc1.colors.length; i < positions.length; i++) {
59       positions[i] = positions[gc1.colors.length - 1];
60       colors[i] = colors[gc1.colors.length - 1];
61     }
62   }
63 
copyWithPositions(float[] positions)64   public GradientColor copyWithPositions(float[] positions) {
65     int[] colors = new int[positions.length];
66     for (int i = 0; i < positions.length; i++) {
67       colors[i] = getColorForPosition(positions[i]);
68     }
69     return new GradientColor(positions, colors);
70   }
71 
72   @Override
equals(Object o)73   public boolean equals(Object o) {
74     if (this == o) {
75       return true;
76     }
77     if (o == null || getClass() != o.getClass()) {
78       return false;
79     }
80     GradientColor that = (GradientColor) o;
81     return Arrays.equals(positions, that.positions) && Arrays.equals(colors, that.colors);
82   }
83 
84   @Override
hashCode()85   public int hashCode() {
86     int result = Arrays.hashCode(positions);
87     result = 31 * result + Arrays.hashCode(colors);
88     return result;
89   }
90 
getColorForPosition(float position)91   private int getColorForPosition(float position) {
92     int existingIndex = Arrays.binarySearch(positions, position);
93     if (existingIndex >= 0) {
94       return colors[existingIndex];
95     }
96     // binarySearch returns -insertionPoint - 1 if it is not found.
97     int insertionPoint = -(existingIndex + 1);
98     if (insertionPoint == 0) {
99       return colors[0];
100     } else if (insertionPoint == colors.length - 1) {
101       return colors[colors.length - 1];
102     }
103     float startPosition = positions[insertionPoint - 1];
104     float endPosition = positions[insertionPoint];
105     int startColor = colors[insertionPoint - 1];
106     int endColor = colors[insertionPoint];
107 
108     float fraction = (position - startPosition) / (endPosition - startPosition);
109     return GammaEvaluator.evaluate(fraction, startColor, endColor);
110   }
111 
copyFrom(GradientColor other)112   private void copyFrom(GradientColor other) {
113     for (int i = 0; i < other.colors.length; i++) {
114       positions[i] = other.positions[i];
115       colors[i] = other.colors[i];
116     }
117   }
118 }
119