| package com.airbnb.lottie.model.content; |
| |
| import android.graphics.PointF; |
| import androidx.annotation.FloatRange; |
| |
| import com.airbnb.lottie.model.CubicCurveData; |
| import com.airbnb.lottie.utils.Logger; |
| import com.airbnb.lottie.utils.MiscUtils; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class ShapeData { |
| private final List<CubicCurveData> curves; |
| private PointF initialPoint; |
| private boolean closed; |
| |
| public ShapeData(PointF initialPoint, boolean closed, List<CubicCurveData> curves) { |
| this.initialPoint = initialPoint; |
| this.closed = closed; |
| this.curves = new ArrayList<>(curves); |
| } |
| |
| public ShapeData() { |
| curves = new ArrayList<>(); |
| } |
| |
| private void setInitialPoint(float x, float y) { |
| if (initialPoint == null) { |
| initialPoint = new PointF(); |
| } |
| initialPoint.set(x, y); |
| } |
| |
| public PointF getInitialPoint() { |
| return initialPoint; |
| } |
| |
| public boolean isClosed() { |
| return closed; |
| } |
| |
| public List<CubicCurveData> getCurves() { |
| return curves; |
| } |
| |
| public void interpolateBetween(ShapeData shapeData1, ShapeData shapeData2, |
| @FloatRange(from = 0f, to = 1f) float percentage) { |
| if (initialPoint == null) { |
| initialPoint = new PointF(); |
| } |
| closed = shapeData1.isClosed() || shapeData2.isClosed(); |
| |
| |
| if (shapeData1.getCurves().size() != shapeData2.getCurves().size()) { |
| Logger.warning("Curves must have the same number of control points. Shape 1: " + |
| shapeData1.getCurves().size() + "\tShape 2: " + shapeData2.getCurves().size()); |
| } |
| |
| int points = Math.min(shapeData1.getCurves().size(), shapeData2.getCurves().size()); |
| if (curves.size() < points) { |
| for (int i = curves.size(); i < points; i++) { |
| curves.add(new CubicCurveData()); |
| } |
| } else if (curves.size() > points) { |
| for (int i = curves.size() - 1; i >= points; i--) { |
| curves.remove(curves.size() - 1); |
| } |
| } |
| |
| PointF initialPoint1 = shapeData1.getInitialPoint(); |
| PointF initialPoint2 = shapeData2.getInitialPoint(); |
| |
| setInitialPoint(MiscUtils.lerp(initialPoint1.x, initialPoint2.x, percentage), |
| MiscUtils.lerp(initialPoint1.y, initialPoint2.y, percentage)); |
| |
| for (int i = curves.size() - 1; i >= 0; i--) { |
| CubicCurveData curve1 = shapeData1.getCurves().get(i); |
| CubicCurveData curve2 = shapeData2.getCurves().get(i); |
| |
| PointF cp11 = curve1.getControlPoint1(); |
| PointF cp21 = curve1.getControlPoint2(); |
| PointF vertex1 = curve1.getVertex(); |
| |
| PointF cp12 = curve2.getControlPoint1(); |
| PointF cp22 = curve2.getControlPoint2(); |
| PointF vertex2 = curve2.getVertex(); |
| |
| curves.get(i).setControlPoint1( |
| MiscUtils.lerp(cp11.x, cp12.x, percentage), MiscUtils.lerp(cp11.y, cp12.y, |
| percentage)); |
| curves.get(i).setControlPoint2( |
| MiscUtils.lerp(cp21.x, cp22.x, percentage), MiscUtils.lerp(cp21.y, cp22.y, |
| percentage)); |
| curves.get(i).setVertex( |
| MiscUtils.lerp(vertex1.x, vertex2.x, percentage), MiscUtils.lerp(vertex1.y, vertex2.y, |
| percentage)); |
| } |
| } |
| |
| @Override public String toString() { |
| return "ShapeData{" + "numCurves=" + curves.size() + |
| "closed=" + closed + |
| '}'; |
| } |
| } |