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