forked from airbnb/lottie-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial support for linear gradients (airbnb#199)
- Loading branch information
Showing
7 changed files
with
336 additions
and
0 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
lottie/src/main/java/com/airbnb/lottie/AnimatableGradientColorValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package com.airbnb.lottie; | ||
|
||
import android.graphics.Color; | ||
|
||
import org.json.JSONArray; | ||
import org.json.JSONObject; | ||
|
||
import java.util.List; | ||
|
||
class AnimatableGradientColorValue extends BaseAnimatableValue<GradientColor, GradientColor> { | ||
private AnimatableGradientColorValue( | ||
List<Keyframe<GradientColor>> keyframes, GradientColor initialValue) { | ||
super(keyframes, initialValue); | ||
} | ||
|
||
@Override public KeyframeAnimation<GradientColor> createAnimation() { | ||
if (!hasAnimation()) { | ||
return new StaticKeyframeAnimation<>(initialValue); | ||
} | ||
return new GradientColorKeyframeAnimation(keyframes); | ||
} | ||
|
||
static final class Factory { | ||
private Factory() { | ||
} | ||
|
||
static AnimatableGradientColorValue newInstance( | ||
JSONObject json, LottieComposition composition) { | ||
AnimatableValueParser.Result<GradientColor> result = AnimatableValueParser | ||
.newInstance(json, 1, composition, ValueFactory.INSTANCE) | ||
.parseJson(); | ||
GradientColor initialValue = result.initialValue; | ||
return new AnimatableGradientColorValue(result.keyframes, initialValue); | ||
} | ||
} | ||
|
||
private static class ValueFactory implements AnimatableValue.Factory<GradientColor> { | ||
private static final ValueFactory INSTANCE = new ValueFactory(); | ||
|
||
private ValueFactory() { | ||
} | ||
|
||
@Override public GradientColor valueFromObject(Object object, float scale) { | ||
JSONArray array = (JSONArray) object; | ||
int size = array.length() / 4; | ||
float[] positions = new float[size]; | ||
int[] colors = new int[size]; | ||
GradientColor gradientColor = new GradientColor(positions, colors); | ||
int r = 0; | ||
int g = 0; | ||
for (int i = 0; i < array.length(); i++) { | ||
int colorIndex = i / 4; | ||
double value = array.optDouble(i); | ||
switch (i % 4) { | ||
case 0: | ||
// position | ||
positions[colorIndex] = (float) value; | ||
break; | ||
case 1: | ||
r = (int) (value * 255); | ||
break; | ||
case 2: | ||
g = (int) (value * 255); | ||
break; | ||
case 3: | ||
int b = (int) (value * 255); | ||
colors[colorIndex] = Color.argb(255, r, g, b); | ||
break; | ||
} | ||
} | ||
return gradientColor; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.airbnb.lottie; | ||
|
||
class GradientColor { | ||
private final float[] positions; | ||
private final int[] colors; | ||
|
||
GradientColor(float[] positions, int[] colors) { | ||
this.positions = positions; | ||
this.colors = colors; | ||
} | ||
|
||
float[] getPositions() { | ||
return positions; | ||
} | ||
|
||
int[] getColors() { | ||
return colors; | ||
} | ||
|
||
int getSize() { | ||
return colors.length; | ||
} | ||
|
||
void lerp(GradientColor gc1, GradientColor gc2, float progress) { | ||
if (gc1.colors.length != gc2.colors.length) { | ||
throw new IllegalArgumentException("Cannot interpolate between gradients. Lengths vary (" + | ||
gc1.colors.length + " vs " + gc2.colors.length + ")"); | ||
} | ||
|
||
for (int i = 0; i < gc1.colors.length; i++) { | ||
positions[i] = MiscUtils.lerp(gc1.positions[i], gc2.positions[i], progress); | ||
colors[i] = GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]); | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
lottie/src/main/java/com/airbnb/lottie/GradientColorKeyframeAnimation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.airbnb.lottie; | ||
|
||
import java.util.List; | ||
|
||
class GradientColorKeyframeAnimation extends KeyframeAnimation<GradientColor> { | ||
private final GradientColor gradientColor; | ||
|
||
GradientColorKeyframeAnimation(List<? extends Keyframe<GradientColor>> keyframes) { | ||
super(keyframes); | ||
GradientColor startValue = keyframes.get(0).startValue; | ||
int size = startValue == null ? 0 : startValue.getSize(); | ||
gradientColor = new GradientColor(new float[size], new int[size]); | ||
} | ||
|
||
@Override GradientColor getValue(Keyframe<GradientColor> keyframe, float keyframeProgress) { | ||
gradientColor.lerp(keyframe.startValue, keyframe.endValue, keyframeProgress); | ||
return gradientColor; | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
lottie/src/main/java/com/airbnb/lottie/GradientFill.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package com.airbnb.lottie; | ||
|
||
import android.graphics.Path; | ||
import android.support.annotation.Nullable; | ||
|
||
import org.json.JSONObject; | ||
|
||
class GradientFill { | ||
|
||
enum GradientType { | ||
Linear, | ||
Radial | ||
} | ||
|
||
private final GradientType gradientType; | ||
private final Path.FillType fillType; | ||
private final AnimatableGradientColorValue gradientColor; | ||
private final AnimatableIntegerValue opacity; | ||
private final AnimatablePointValue startPoint; | ||
private final AnimatablePointValue endPoint; | ||
@Nullable private final AnimatableFloatValue highlightLength; | ||
@Nullable private final AnimatableFloatValue highlightAngle; | ||
|
||
private GradientFill(GradientType gradientType, Path.FillType fillType, | ||
AnimatableGradientColorValue gradientColor, | ||
AnimatableIntegerValue opacity, AnimatablePointValue startPoint, | ||
AnimatablePointValue endPoint, AnimatableFloatValue highlightLength, | ||
AnimatableFloatValue highlightAngle) { | ||
this.gradientType = gradientType; | ||
this.fillType = fillType; | ||
this.gradientColor = gradientColor; | ||
this.opacity = opacity; | ||
this.startPoint = startPoint; | ||
this.endPoint = endPoint; | ||
this.highlightLength = highlightLength; | ||
this.highlightAngle = highlightAngle; | ||
} | ||
|
||
GradientType getGradientType() { | ||
return gradientType; | ||
} | ||
|
||
Path.FillType getFillType() { | ||
return fillType; | ||
} | ||
|
||
AnimatableGradientColorValue getGradientColor() { | ||
return gradientColor; | ||
} | ||
|
||
AnimatableIntegerValue getOpacity() { | ||
return opacity; | ||
} | ||
|
||
AnimatablePointValue getStartPoint() { | ||
return startPoint; | ||
} | ||
|
||
AnimatablePointValue getEndPoint() { | ||
return endPoint; | ||
} | ||
|
||
@Nullable AnimatableFloatValue getHighlightLength() { | ||
return highlightLength; | ||
} | ||
|
||
@Nullable AnimatableFloatValue getHighlightAngle() { | ||
return highlightAngle; | ||
} | ||
|
||
static class Factory { | ||
private Factory() { | ||
} | ||
|
||
static GradientFill newInstance(JSONObject json, LottieComposition composition) { | ||
JSONObject jsonColor = json.optJSONObject("g"); | ||
if (jsonColor != null && jsonColor.has("k")) { | ||
jsonColor = jsonColor.optJSONObject("k"); | ||
} | ||
AnimatableGradientColorValue color = null; | ||
if (jsonColor != null) { | ||
color = AnimatableGradientColorValue.Factory.newInstance(jsonColor, composition); | ||
} | ||
|
||
JSONObject jsonOpacity = json.optJSONObject("o"); | ||
AnimatableIntegerValue opacity = null; | ||
if (jsonOpacity != null) { | ||
opacity = AnimatableIntegerValue.Factory.newInstance(jsonOpacity, composition); | ||
} | ||
|
||
int fillTypeInt = json.optInt("r", 1); | ||
Path.FillType fillType = fillTypeInt == 1 ? Path.FillType.WINDING : Path.FillType.EVEN_ODD; | ||
|
||
int gradientTypeInt = json.optInt("r", 1); | ||
GradientType gradientType = gradientTypeInt == 1 ? GradientType.Linear : GradientType.Radial; | ||
|
||
JSONObject jsonStartPoint = json.optJSONObject("s"); | ||
AnimatablePointValue startPoint = null; | ||
if (jsonStartPoint != null) { | ||
startPoint = AnimatablePointValue.Factory.newInstance(jsonStartPoint, composition); | ||
} | ||
|
||
JSONObject jsonEndPoint = json.optJSONObject("e"); | ||
AnimatablePointValue endPoint = null; | ||
if (jsonEndPoint != null) { | ||
endPoint = AnimatablePointValue.Factory.newInstance(jsonEndPoint, composition); | ||
} | ||
|
||
// TODO: radial gradients. | ||
|
||
return new GradientFill( | ||
gradientType, fillType, color, opacity, startPoint, endPoint, null, null); | ||
|
||
} | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
lottie/src/main/java/com/airbnb/lottie/GradientFillContent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.airbnb.lottie; | ||
|
||
import android.graphics.Canvas; | ||
import android.graphics.LinearGradient; | ||
import android.graphics.Matrix; | ||
import android.graphics.Paint; | ||
import android.graphics.Path; | ||
import android.graphics.PointF; | ||
import android.graphics.RectF; | ||
import android.graphics.Shader; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
class GradientFillContent implements DrawingContent, BaseKeyframeAnimation.AnimationListener { | ||
private final Path path = new Path(); | ||
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); | ||
private final RectF boundsRect = new RectF(); | ||
private final List<PathContent> paths = new ArrayList<>(); | ||
private final KeyframeAnimation<GradientColor> colorAnimation; | ||
private final KeyframeAnimation<Integer> opacityAnimation; | ||
private final KeyframeAnimation<PointF> startPointAnimation; | ||
private final KeyframeAnimation<PointF> endPointAnimation; | ||
private final LottieDrawable lottieDrawable; | ||
|
||
GradientFillContent(final LottieDrawable lottieDrawable, BaseLayer layer, GradientFill fill) { | ||
this.lottieDrawable = lottieDrawable; | ||
path.setFillType(fill.getFillType()); | ||
|
||
colorAnimation = fill.getGradientColor().createAnimation(); | ||
colorAnimation.addUpdateListener(this); | ||
layer.addAnimation(colorAnimation); | ||
|
||
opacityAnimation = fill.getOpacity().createAnimation(); | ||
opacityAnimation.addUpdateListener(this); | ||
layer.addAnimation(opacityAnimation); | ||
|
||
startPointAnimation = fill.getStartPoint().createAnimation(); | ||
startPointAnimation.addUpdateListener(this); | ||
layer.addAnimation(startPointAnimation); | ||
|
||
endPointAnimation = fill.getEndPoint().createAnimation(); | ||
endPointAnimation.addUpdateListener(this); | ||
layer.addAnimation(endPointAnimation); | ||
} | ||
|
||
@Override public void onValueChanged() { | ||
lottieDrawable.invalidateSelf(); | ||
} | ||
|
||
@Override public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) { | ||
for (int i = 0; i < contentsAfter.size(); i++) { | ||
Content content = contentsAfter.get(i); | ||
if (content instanceof PathContent) { | ||
paths.add((PathContent) content); | ||
} | ||
} | ||
} | ||
|
||
@Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) { | ||
path.reset(); | ||
for (int i = 0; i < paths.size(); i++) { | ||
path.addPath(paths.get(i).getPath(), parentMatrix); | ||
} | ||
|
||
path.computeBounds(boundsRect, false); | ||
|
||
paint.setShader(getShader()); | ||
int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255); | ||
paint.setAlpha(alpha); | ||
|
||
canvas.drawPath(path, paint); | ||
} | ||
|
||
private LinearGradient getShader() { | ||
// TODO: cache these | ||
PointF startPoint = startPointAnimation.getValue(); | ||
PointF endPoint = endPointAnimation.getValue(); | ||
GradientColor gradientColor = colorAnimation.getValue(); | ||
int[] colors = gradientColor.getColors(); | ||
float[] positions = gradientColor.getPositions(); | ||
int x0 = (int) (boundsRect.left + boundsRect.width() / 2 + startPoint.x); | ||
int y0 = (int) (boundsRect.top + boundsRect.height() / 2 + startPoint.y); | ||
int x1 = (int) (boundsRect.left + boundsRect.width() / 2 + endPoint.x); | ||
int y1 = (int) (boundsRect.top + boundsRect.height() / 2 + endPoint.y); | ||
return new LinearGradient(x0 , y0, x1, y1, colors, positions, Shader.TileMode.CLAMP); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters