blob: 04dd07d07fe20fb581423273a41265445ff36652 [file] [log] [blame]
package com.airbnb.lottie.parser;
import android.graphics.PointF;
import com.airbnb.lottie.model.CubicCurveData;
import com.airbnb.lottie.model.content.ShapeData;
import com.airbnb.lottie.parser.moshi.JsonReader;
import com.airbnb.lottie.utils.MiscUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ShapeDataParser implements ValueParser<ShapeData> {
public static final ShapeDataParser INSTANCE = new ShapeDataParser();
private static final JsonReader.Options NAMES = JsonReader.Options.of(
"c",
"v",
"i",
"o"
);
private ShapeDataParser() {
}
@Override
public ShapeData parse(JsonReader reader, float scale) throws IOException {
// Sometimes the points data is in a array of length 1. Sometimes the data is at the top
// level.
if (reader.peek() == JsonReader.Token.BEGIN_ARRAY) {
reader.beginArray();
}
boolean closed = false;
List<PointF> pointsArray = null;
List<PointF> inTangents = null;
List<PointF> outTangents = null;
reader.beginObject();
while (reader.hasNext()) {
switch (reader.selectName(NAMES)) {
case 0:
closed = reader.nextBoolean();
break;
case 1:
pointsArray = JsonUtils.jsonToPoints(reader, scale);
break;
case 2:
inTangents = JsonUtils.jsonToPoints(reader, scale);
break;
case 3:
outTangents = JsonUtils.jsonToPoints(reader, scale);
break;
default:
reader.skipName();
reader.skipValue();
}
}
reader.endObject();
if (reader.peek() == JsonReader.Token.END_ARRAY) {
reader.endArray();
}
if (pointsArray == null || inTangents == null || outTangents == null) {
throw new IllegalArgumentException("Shape data was missing information.");
}
if (pointsArray.isEmpty()) {
return new ShapeData(new PointF(), false, Collections.<CubicCurveData>emptyList());
}
int length = pointsArray.size();
PointF vertex = pointsArray.get(0);
PointF initialPoint = vertex;
List<CubicCurveData> curves = new ArrayList<>(length);
for (int i = 1; i < length; i++) {
vertex = pointsArray.get(i);
PointF previousVertex = pointsArray.get(i - 1);
PointF cp1 = outTangents.get(i - 1);
PointF cp2 = inTangents.get(i);
PointF shapeCp1 = MiscUtils.addPoints(previousVertex, cp1);
PointF shapeCp2 = MiscUtils.addPoints(vertex, cp2);
curves.add(new CubicCurveData(shapeCp1, shapeCp2, vertex));
}
if (closed) {
vertex = pointsArray.get(0);
PointF previousVertex = pointsArray.get(length - 1);
PointF cp1 = outTangents.get(length - 1);
PointF cp2 = inTangents.get(0);
PointF shapeCp1 = MiscUtils.addPoints(previousVertex, cp1);
PointF shapeCp2 = MiscUtils.addPoints(vertex, cp2);
curves.add(new CubicCurveData(shapeCp1, shapeCp2, vertex));
}
return new ShapeData(initialPoint, closed, curves);
}
}