• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.airbnb.lottie.model.content;
2 
3 import android.graphics.PointF;
4 
5 import androidx.annotation.FloatRange;
6 
7 import com.airbnb.lottie.model.CubicCurveData;
8 import com.airbnb.lottie.utils.Logger;
9 import com.airbnb.lottie.utils.MiscUtils;
10 
11 import java.util.ArrayList;
12 import java.util.List;
13 
14 public class ShapeData {
15   private final List<CubicCurveData> curves;
16   private PointF initialPoint;
17   private boolean closed;
18 
ShapeData(PointF initialPoint, boolean closed, List<CubicCurveData> curves)19   public ShapeData(PointF initialPoint, boolean closed, List<CubicCurveData> curves) {
20     this.initialPoint = initialPoint;
21     this.closed = closed;
22     this.curves = new ArrayList<>(curves);
23   }
24 
ShapeData()25   public ShapeData() {
26     curves = new ArrayList<>();
27   }
28 
setInitialPoint(float x, float y)29   public void setInitialPoint(float x, float y) {
30     if (initialPoint == null) {
31       initialPoint = new PointF();
32     }
33     initialPoint.set(x, y);
34   }
35 
getInitialPoint()36   public PointF getInitialPoint() {
37     return initialPoint;
38   }
39 
setClosed(boolean closed)40   public void setClosed(boolean closed) {
41     this.closed = closed;
42   }
43 
isClosed()44   public boolean isClosed() {
45     return closed;
46   }
47 
getCurves()48   public List<CubicCurveData> getCurves() {
49     return curves;
50   }
51 
interpolateBetween(ShapeData shapeData1, ShapeData shapeData2, @FloatRange(from = 0f, to = 1f) float percentage)52   public void interpolateBetween(ShapeData shapeData1, ShapeData shapeData2,
53       @FloatRange(from = 0f, to = 1f) float percentage) {
54     if (initialPoint == null) {
55       initialPoint = new PointF();
56     }
57     closed = shapeData1.isClosed() || shapeData2.isClosed();
58 
59 
60     if (shapeData1.getCurves().size() != shapeData2.getCurves().size()) {
61       Logger.warning("Curves must have the same number of control points. Shape 1: " +
62           shapeData1.getCurves().size() + "\tShape 2: " + shapeData2.getCurves().size());
63     }
64 
65     int points = Math.min(shapeData1.getCurves().size(), shapeData2.getCurves().size());
66     if (curves.size() < points) {
67       for (int i = curves.size(); i < points; i++) {
68         curves.add(new CubicCurveData());
69       }
70     } else if (curves.size() > points) {
71       for (int i = curves.size() - 1; i >= points; i--) {
72         curves.remove(curves.size() - 1);
73       }
74     }
75 
76     PointF initialPoint1 = shapeData1.getInitialPoint();
77     PointF initialPoint2 = shapeData2.getInitialPoint();
78 
79     setInitialPoint(MiscUtils.lerp(initialPoint1.x, initialPoint2.x, percentage),
80         MiscUtils.lerp(initialPoint1.y, initialPoint2.y, percentage));
81 
82     for (int i = curves.size() - 1; i >= 0; i--) {
83       CubicCurveData curve1 = shapeData1.getCurves().get(i);
84       CubicCurveData curve2 = shapeData2.getCurves().get(i);
85 
86       PointF cp11 = curve1.getControlPoint1();
87       PointF cp21 = curve1.getControlPoint2();
88       PointF vertex1 = curve1.getVertex();
89 
90       PointF cp12 = curve2.getControlPoint1();
91       PointF cp22 = curve2.getControlPoint2();
92       PointF vertex2 = curve2.getVertex();
93 
94       curves.get(i).setControlPoint1(
95           MiscUtils.lerp(cp11.x, cp12.x, percentage), MiscUtils.lerp(cp11.y, cp12.y,
96               percentage));
97       curves.get(i).setControlPoint2(
98           MiscUtils.lerp(cp21.x, cp22.x, percentage), MiscUtils.lerp(cp21.y, cp22.y,
99               percentage));
100       curves.get(i).setVertex(
101           MiscUtils.lerp(vertex1.x, vertex2.x, percentage), MiscUtils.lerp(vertex1.y, vertex2.y,
102               percentage));
103     }
104   }
105 
toString()106   @Override public String toString() {
107     return "ShapeData{" + "numCurves=" + curves.size() +
108         "closed=" + closed +
109         '}';
110   }
111 }
112