Fix flashing gradient
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
index cfa9523..9c5fc83 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
@@ -1,10 +1,9 @@
package com.airbnb.lottie.animation.content;
import android.graphics.Path;
+import android.graphics.PathMeasure;
import android.graphics.PointF;
-
import androidx.annotation.Nullable;
-
import com.airbnb.lottie.LottieDrawable;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
@@ -28,6 +27,9 @@
private static final float POLYSTAR_MAGIC_NUMBER = .47829f;
private static final float POLYGON_MAGIC_NUMBER = .25f;
private final Path path = new Path();
+ private final Path lastSegmentPath = new Path();
+ private final PathMeasure lastSegmentPathMeasure = new PathMeasure();
+ private final float[] lastSegmentPosition = new float[2];
private final String name;
private final LottieDrawable lottieDrawable;
@@ -291,8 +293,28 @@
float cp1y = radius * roundedness * POLYGON_MAGIC_NUMBER * cp1Dy;
float cp2x = radius * roundedness * POLYGON_MAGIC_NUMBER * cp2Dx;
float cp2y = radius * roundedness * POLYGON_MAGIC_NUMBER * cp2Dy;
- path.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
+
+ if (i == numPoints - 1) {
+ // When there is a huge stroke, it will flash if the path ends where it starts.
+ // We want the final bezier curve to end *slightly* before the start.
+ // The close() call at the end will complete the polystar.
+ // https://github.com/airbnb/lottie-android/issues/2329
+ lastSegmentPath.reset();
+ lastSegmentPath.moveTo(previousX, previousY);
+ lastSegmentPath.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
+ lastSegmentPathMeasure.setPath(lastSegmentPath, false);
+ lastSegmentPathMeasure.getPosTan(lastSegmentPathMeasure.getLength() * 0.9999f, lastSegmentPosition, null);
+ path.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y,lastSegmentPosition[0], lastSegmentPosition[1]);
+ } else {
+ path.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
+ }
} else {
+ if (i == numPoints - 1) {
+ // When there is a huge stroke, it will flash if the path ends where it starts.
+ // The close() call should make the path effectively equivalent.
+ // https://github.com/airbnb/lottie-android/issues/2329
+ continue;
+ }
path.lineTo(x, y);
}
diff --git a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/LottieSnapshotTest.kt b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/LottieSnapshotTest.kt
index 3341722..803f8c0 100644
--- a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/LottieSnapshotTest.kt
+++ b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/LottieSnapshotTest.kt
@@ -31,6 +31,7 @@
import com.airbnb.lottie.snapshots.tests.NightModeTestCase
import com.airbnb.lottie.snapshots.tests.OutlineMasksAndMattesTestCase
import com.airbnb.lottie.snapshots.tests.PartialFrameProgressTestCase
+import com.airbnb.lottie.snapshots.tests.PolygonStrokeTestCase
import com.airbnb.lottie.snapshots.tests.ProdAnimationsTestCase
import com.airbnb.lottie.snapshots.tests.ScaleTypesTestCase
import com.airbnb.lottie.snapshots.tests.SeekBarTestCase
@@ -159,6 +160,7 @@
ClipChildrenTestCase(),
SoftwareRenderingDynamicPropertiesInvalidationTestCase(),
SeekBarTestCase(),
+ PolygonStrokeTestCase(),
CompositionFrameRate(),
)
diff --git a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/PolygonStrokeTestCase.kt b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/PolygonStrokeTestCase.kt
new file mode 100644
index 0000000..470e179
--- /dev/null
+++ b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/PolygonStrokeTestCase.kt
@@ -0,0 +1,13 @@
+package com.airbnb.lottie.snapshots.tests
+
+import com.airbnb.lottie.snapshots.SnapshotTestCase
+import com.airbnb.lottie.snapshots.SnapshotTestCaseContext
+import com.airbnb.lottie.snapshots.withDrawable
+
+class PolygonStrokeTestCase : SnapshotTestCase {
+ override suspend fun SnapshotTestCaseContext.run() {
+ withDrawable("Tests/TriangleLargeStroke.json", "Triangle", "Large Stroke") { drawable ->
+ drawable.progress = 0.40999988f
+ }
+ }
+}
diff --git a/snapshot-tests/src/main/assets/Tests/TriangleLargeStroke.json b/snapshot-tests/src/main/assets/Tests/TriangleLargeStroke.json
new file mode 100644
index 0000000..19c4144
--- /dev/null
+++ b/snapshot-tests/src/main/assets/Tests/TriangleLargeStroke.json
@@ -0,0 +1 @@
+{"v":"5.12.2","fr":29.9700012207031,"ip":0,"op":60.0000024438501,"w":1200,"h":1200,"nm":"Repro 2 - Large","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[600,376,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":301,"ix":7},"os":{"a":0,"k":30,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":100,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-205.188,19.281],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":59.0000024031193,"s":[360]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":301,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 2","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":100,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[225,421],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":59.0000024031193,"s":[360]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}}