blob: 7053a0b405453ceea5cdd5355c016a7fd94fdb7f [file] [log] [blame]
package com.airbnb.lottie.parser;
import android.graphics.PointF;
import android.util.JsonToken;
import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
import com.airbnb.lottie.model.animatable.AnimatableIntegerValue;
import com.airbnb.lottie.model.animatable.AnimatablePathValue;
import com.airbnb.lottie.model.animatable.AnimatableScaleValue;
import com.airbnb.lottie.model.animatable.AnimatableSplitDimensionPathValue;
import com.airbnb.lottie.model.animatable.AnimatableTransform;
import com.airbnb.lottie.model.animatable.AnimatableValue;
import com.airbnb.lottie.parser.moshi.JsonReader;
import com.airbnb.lottie.value.Keyframe;
import java.io.IOException;
public class AnimatableTransformParser {
private AnimatableTransformParser() {
}
private static final JsonReader.Options NAMES = JsonReader.Options.of(
"a", // 1
"p", // 2
"s", // 3
"rz", // 4
"r", // 5
"o", // 6
"so", // 7
"eo", // 8
"sk", // 9
"sa" // 10
);
private static final JsonReader.Options ANIMATABLE_NAMES = JsonReader.Options.of("k");
public static AnimatableTransform parse(
JsonReader reader, LottieComposition composition) throws IOException {
AnimatablePathValue anchorPoint = null;
AnimatableValue<PointF, PointF> position = null;
AnimatableScaleValue scale = null;
AnimatableFloatValue rotation = null;
AnimatableIntegerValue opacity = null;
AnimatableFloatValue startOpacity = null;
AnimatableFloatValue endOpacity = null;
AnimatableFloatValue skew = null;
AnimatableFloatValue skewAngle = null;
boolean isObject = reader.peek() == JsonReader.Token.BEGIN_OBJECT;
if (isObject) {
reader.beginObject();
}
while (reader.hasNext()) {
switch (reader.selectName(NAMES)) {
case 0: // a
reader.beginObject();
while (reader.hasNext()) {
switch (reader.selectName(ANIMATABLE_NAMES)) {
case 0:
anchorPoint = AnimatablePathValueParser.parse(reader, composition);
break;
default:
reader.skipName();
reader.skipValue();
}
}
reader.endObject();
break;
case 1: // p
position =
AnimatablePathValueParser.parseSplitPath(reader, composition);
break;
case 2: // s
scale = AnimatableValueParser.parseScale(reader, composition);
break;
case 3: // rz
composition.addWarning("Lottie doesn't support 3D layers.");
case 4: // r
/*
* Sometimes split path rotation gets exported like:
* "rz": {
* "a": 1,
* "k": [
* {}
* ]
* },
* which doesn't parse to a real keyframe.
*/
rotation = AnimatableValueParser.parseFloat(reader, composition, false);
if (rotation.getKeyframes().isEmpty()) {
rotation.getKeyframes().add(new Keyframe<>(composition, 0f, 0f, null, 0f, composition.getEndFrame()));
} else if (rotation.getKeyframes().get(0).startValue == null) {
rotation.getKeyframes().set(0, new Keyframe<>(composition, 0f, 0f, null, 0f, composition.getEndFrame()));
}
break;
case 5: // o
opacity = AnimatableValueParser.parseInteger(reader, composition);
break;
case 6: // so
startOpacity = AnimatableValueParser.parseFloat(reader, composition, false);
break;
case 7: // eo
endOpacity = AnimatableValueParser.parseFloat(reader, composition, false);
break;
case 8: // sk
skew = AnimatableValueParser.parseFloat(reader, composition, false);
break;
case 9: // sa
skewAngle = AnimatableValueParser.parseFloat(reader, composition, false);
break;
default:
reader.skipName();
reader.skipValue();
}
}
if (isObject) {
reader.endObject();
}
if (isAnchorPointIdentity(anchorPoint)) {
anchorPoint = null;
}
if (isPositionIdentity(position)) {
position = null;
}
if (isRotationIdentity(rotation)) {
rotation = null;
}
if (isScaleIdentity(scale)) {
scale = null;
}
if (isSkewIdentity(skew)) {
skew = null;
}
if (isSkewAngleIdentity(skewAngle)) {
skewAngle = null;
}
return new AnimatableTransform(anchorPoint, position, scale, rotation, opacity, startOpacity, endOpacity, skew, skewAngle);
}
private static boolean isAnchorPointIdentity(AnimatablePathValue anchorPoint) {
return anchorPoint == null || (anchorPoint.isStatic() && anchorPoint.getKeyframes().get(0).startValue.equals(0f, 0f));
}
private static boolean isPositionIdentity(AnimatableValue<PointF, PointF> position) {
return position == null || (
!(position instanceof AnimatableSplitDimensionPathValue) &&
position.isStatic() && position.getKeyframes().get(0).startValue.equals(0f, 0f));
}
private static boolean isRotationIdentity(AnimatableFloatValue rotation) {
return rotation == null || (rotation.isStatic() && rotation.getKeyframes().get(0).startValue == 0f);
}
private static boolean isScaleIdentity(AnimatableScaleValue scale) {
return scale == null || (scale.isStatic() && scale.getKeyframes().get(0).startValue.equals(1f, 1f));
}
private static boolean isSkewIdentity(AnimatableFloatValue skew) {
return skew == null || (skew.isStatic() && skew.getKeyframes().get(0).startValue == 0f);
}
private static boolean isSkewAngleIdentity(AnimatableFloatValue skewAngle) {
return skewAngle == null || (skewAngle.isStatic() && skewAngle.getKeyframes().get(0).startValue == 0f);
}
}