Updated testing (#1064)
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieTest.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieTest.kt
index 5a0d254..31a4bf9 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieTest.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieTest.kt
@@ -22,6 +22,7 @@
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility
import com.amazonaws.services.s3.AmazonS3Client
+import com.amazonaws.services.s3.model.ListObjectsV2Request
import com.amazonaws.services.s3.model.S3ObjectSummary
import kotlinx.coroutines.*
@@ -78,7 +79,7 @@
@Test
fun testAll() {
runBlocking {
- withTimeout(TimeUnit.MINUTES.toMillis(15)) {
+ withTimeout(TimeUnit.MINUTES.toMillis(45)) {
snapshotProdAnimations()
snapshotAssets()
snapshotFrameBoundaries()
@@ -91,9 +92,25 @@
private suspend fun snapshotProdAnimations() {
Log.d(L.TAG, "Downloading prod animations from S3.")
+ val allObjects = mutableListOf<S3ObjectSummary>()
val s3Client = AmazonS3Client(BasicAWSCredentials(BuildConfig.S3AccessKey, BuildConfig.S3SecretKey))
- val objectListing = s3Client.listObjects("lottie-prod-animations")
- objectListing.objectSummaries.forEach { snapshotProdAnimation(it) }
+ var request = ListObjectsV2Request().apply {
+ bucketName = "lottie-prod-animations"
+ }
+ var result = s3Client.listObjectsV2(request)
+ allObjects.addAll(result.objectSummaries)
+ var startAfter = result.objectSummaries.lastOrNull()?.key
+ while (startAfter != null) {
+ request = ListObjectsV2Request().apply {
+ bucketName = "lottie-prod-animations"
+ this.startAfter = startAfter
+ }
+ result = s3Client.listObjectsV2(request)
+ allObjects.addAll(result.objectSummaries)
+ startAfter = result.objectSummaries.lastOrNull()?.key
+ }
+
+ allObjects.forEach { snapshotProdAnimation(it) }
}
private suspend fun snapshotProdAnimation(objectSummary: S3ObjectSummary) {
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SnapshotTestActivity.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SnapshotTestActivity.kt
index 9903fbd..c044da2 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SnapshotTestActivity.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SnapshotTestActivity.kt
@@ -3,9 +3,11 @@
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
+import android.graphics.Typeface
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
+import com.airbnb.lottie.FontAssetDelegate
import com.airbnb.lottie.ImageAssetDelegate
import com.airbnb.lottie.LottieComposition
import kotlinx.android.synthetic.main.activity_snapshot_tests.*
@@ -24,6 +26,11 @@
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_snapshot_tests)
filmStripView.setImageAssetDelegate(ImageAssetDelegate { dummyBitmap })
+ filmStripView.setFontAssetDelegate(object : FontAssetDelegate() {
+ override fun getFontPath(fontFamily: String?): String {
+ return "fonts/Roboto.ttf"
+ }
+ })
@Suppress("DEPRECATION")
animationView.isDrawingCacheEnabled = false
}
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/FilmStripView.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/FilmStripView.kt
index e7370f3..dd6b356 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/FilmStripView.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/FilmStripView.kt
@@ -6,6 +6,7 @@
import android.widget.FrameLayout
import androidx.annotation.FloatRange
import androidx.core.view.children
+import com.airbnb.lottie.FontAssetDelegate
import com.airbnb.lottie.ImageAssetDelegate
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieComposition
@@ -40,4 +41,8 @@
fun setImageAssetDelegate(delegate: ImageAssetDelegate) {
animationViews.forEach { it.setImageAssetDelegate(delegate) }
}
+
+ fun setFontAssetDelegate(delegate: FontAssetDelegate) {
+ animationViews.forEach { it.setFontAssetDelegate(delegate) }
+ }
}
\ No newline at end of file
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index effa0fe..80e7e81 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -183,6 +183,9 @@
float x1 = endPoint.x;
float y1 = endPoint.y;
float r = (float) Math.hypot(x1 - x0, y1 - y0);
+ if (r <= 0) {
+ r = 0.001f;
+ }
gradient = new RadialGradient(x0, y0, r, colors, positions, Shader.TileMode.CLAMP);
radialGradientCache.put(gradientHash, gradient);
return gradient;
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java b/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
index 18720e9..31a50cf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
@@ -185,7 +185,7 @@
@SuppressWarnings("SimplifiableIfStatement")
@RestrictTo(RestrictTo.Scope.LIBRARY)
public boolean propagateToChildren(String key, int depth) {
- if (key.equals("__container")) {
+ if ("__container".equals(key)) {
return true;
}
return depth < keys.size() - 1 || keys.get(depth).equals("**");
@@ -196,7 +196,7 @@
* and for the contents of a ShapeLayer).
*/
private boolean isContainer(String key) {
- return key.equals("__container");
+ return "__container".equals(key);
}
private boolean endsWithGlobstar() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
index da0ca56..20c0ccf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableTransform.java
@@ -51,7 +51,8 @@
!(position instanceof AnimatableSplitDimensionPathValue) &&
position.isStatic() && position.getKeyframes().get(0).startValue.equals(0f, 0f) &&
scale.isStatic() && scale.getKeyframes().get(0).startValue.equals(1f, 1f) &&
- rotation.isStatic() && rotation.getKeyframes().get(0).startValue == 0f;
+ (rotation.isStatic() && rotation.getKeyframes().get(0).startValue == 0f ||
+ rotation.keyframes.isEmpty());
}
public AnimatablePathValue getAnchorPoint() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java b/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
index 39cfa35..4f930ae 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/animatable/BaseAnimatableValue.java
@@ -28,7 +28,7 @@
@Override
public boolean isStatic() {
- return keyframes.size() == 1 && keyframes.get(0).isStatic();
+ return keyframes.isEmpty() || (keyframes.size() == 1 && keyframes.get(0).isStatic());
}
@Override public String toString() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeData.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeData.java
index 4018fb7..4824a01 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeData.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeData.java
@@ -63,7 +63,7 @@
curves.add(new CubicCurveData());
}
} else if (curves.size() > points) {
- for (int i = points; i < curves.size(); i++) {
+ for (int i = curves.size() - 1; i >= points; i--) {
curves.remove(curves.size() - 1);
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableTransformParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableTransformParser.java
index dc5e234..7a6d750 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableTransformParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/AnimatableTransformParser.java
@@ -13,6 +13,7 @@
import com.airbnb.lottie.model.animatable.AnimatableScaleValue;
import com.airbnb.lottie.model.animatable.AnimatableTransform;
import com.airbnb.lottie.model.animatable.AnimatableValue;
+import com.airbnb.lottie.value.Keyframe;
import com.airbnb.lottie.value.ScaleXY;
import java.io.IOException;
@@ -58,7 +59,20 @@
case "rz":
composition.addWarning("Lottie doesn't support 3D layers.");
case "r":
+ /**
+ * Sometimes split path rotation gets exported like:
+ * "rz": {
+ * "a": 1,
+ * "k": [
+ * {}
+ * ]
+ * },
+ * which doesn't parse to a real keyframe.
+ */
rotation = AnimatableValueParser.parseFloat(reader, composition, false);
+ if (rotation.getKeyframes().isEmpty()) {
+ rotation.getKeyframes().add(new Keyframe(composition, 0f, 0f, null, 0f, composition.getEndFrame()));
+ }
break;
case "o":
opacity = AnimatableValueParser.parseInteger(reader, composition);
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ScaleXYParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ScaleXYParser.java
index b0bdd9d..91d6f87 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ScaleXYParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ScaleXYParser.java
@@ -28,4 +28,5 @@
}
return new ScaleXY(sx / 100f * scale, sy / 100f * scale);
}
+
}