diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieDynamicProperties.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieDynamicProperties.kt index 5edd399484..837a6250b0 100644 --- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieDynamicProperties.kt +++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieDynamicProperties.kt @@ -2,6 +2,7 @@ package com.airbnb.lottie.compose import android.graphics.Bitmap import android.graphics.ColorFilter +import android.graphics.Path import android.graphics.PointF import android.graphics.Typeface import androidx.compose.runtime.Composable @@ -102,6 +103,7 @@ class LottieDynamicProperties internal constructor( private val typefaceProperties: List>, private val bitmapProperties: List>, private val charSequenceProperties: List>, + private val pathProperties: List>, ) { @Suppress("UNCHECKED_CAST") constructor(properties: List>) : this( @@ -114,6 +116,7 @@ class LottieDynamicProperties internal constructor( properties.filter { it.property is Typeface } as List>, properties.filter { it.property is Bitmap } as List>, properties.filter { it.property is CharSequence } as List>, + properties.filter { it.property is Path } as List>, ) internal fun addTo(drawable: LottieDrawable) { @@ -144,6 +147,9 @@ class LottieDynamicProperties internal constructor( charSequenceProperties.forEach { p -> drawable.addValueCallback(p.keyPath, p.property, p.callback.toValueCallback()) } + pathProperties.forEach { p -> + drawable.addValueCallback(p.keyPath, p.property, p.callback.toValueCallback()) + } } internal fun removeFrom(drawable: LottieDrawable) { @@ -174,6 +180,9 @@ class LottieDynamicProperties internal constructor( charSequenceProperties.forEach { p -> drawable.addValueCallback(p.keyPath, p.property, null as LottieValueCallback?) } + pathProperties.forEach { p -> + drawable.addValueCallback(p.keyPath, p.property, null as LottieValueCallback?) + } } } @@ -181,4 +190,4 @@ private fun ((frameInfo: LottieFrameInfo) -> T).toValueCallback() = objec override fun getValue(frameInfo: LottieFrameInfo): T { return invoke(frameInfo) } -} \ No newline at end of file +} diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java index 6ab6257c7c..5f75e9e82b 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java @@ -2,6 +2,7 @@ import android.graphics.Bitmap; import android.graphics.ColorFilter; +import android.graphics.Path; import android.graphics.PointF; import android.graphics.Typeface; @@ -220,4 +221,15 @@ public interface LottieProperty { * Replace the text for a text layer. */ CharSequence TEXT = "dynamic_text"; + + /** + * Replace a path. This can only be used on path contents. For other shapes such as rectangles and polystars, + * use LottieProperties corresponding to their specific properties. + *

+ * If you need to do any operations on the path such as morphing, use the Jetpack androidx.graphics.path library. + *

+ * In After Effects, any of those other shapes can be converted to a bezier path by right clicking it and + * selecting "Convert To Bezier Path". + */ + Path PATH = new Path(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java index 1f54ac094d..0386945800 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java @@ -5,16 +5,20 @@ import androidx.annotation.Nullable; import com.airbnb.lottie.LottieDrawable; +import com.airbnb.lottie.LottieProperty; import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation; import com.airbnb.lottie.animation.keyframe.ShapeKeyframeAnimation; +import com.airbnb.lottie.model.KeyPath; import com.airbnb.lottie.model.content.ShapePath; import com.airbnb.lottie.model.content.ShapeTrimPath; import com.airbnb.lottie.model.layer.BaseLayer; +import com.airbnb.lottie.utils.MiscUtils; +import com.airbnb.lottie.value.LottieValueCallback; import java.util.ArrayList; import java.util.List; -public class ShapeContent implements PathContent, BaseKeyframeAnimation.AnimationListener { +public class ShapeContent implements PathContent, BaseKeyframeAnimation.AnimationListener, KeyPathElementContent { private final Path path = new Path(); private final String name; @@ -65,7 +69,7 @@ private void invalidate() { } @Override public Path getPath() { - if (isPathValid) { + if (isPathValid && !shapeAnimation.hasValueCallback()) { return path; } @@ -94,4 +98,17 @@ private void invalidate() { @Override public String getName() { return name; } + + @Override public void resolveKeyPath( + KeyPath keyPath, int depth, List accumulator, KeyPath currentPartialKeyPath) { + MiscUtils.resolveKeyPath(keyPath, depth, accumulator, currentPartialKeyPath, this); + } + + @SuppressWarnings("unchecked") + @Override + public void addValueCallback(T property, @Nullable LottieValueCallback callback) { + if (property == LottieProperty.PATH) { + shapeAnimation.setValueCallback((LottieValueCallback) callback); + } + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java index f66441559b..b61a4e432d 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java @@ -168,6 +168,10 @@ public void setValueCallback(@Nullable LottieValueCallback valueCallback) { } } + public boolean hasValueCallback() { + return valueCallback != null; + } + /** * keyframeProgress will be [0, 1] unless the interpolator has overshoot in which case, this * should be able to handle values outside of that range. diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java index fe7f6a2bc8..43cc1857ee 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java @@ -14,6 +14,8 @@ public class ShapeKeyframeAnimation extends BaseKeyframeAnimation { private final ShapeData tempShapeData = new ShapeData(); private final Path tempPath = new Path(); + private Path valueCallbackStartPath; + private Path valueCallbackEndPath; private List shapeModifiers; @@ -33,6 +35,20 @@ public ShapeKeyframeAnimation(List> keyframes) { } } MiscUtils.getPathFromData(modifiedShapeData, tempPath); + if (valueCallback != null) { + if (valueCallbackStartPath == null) { + valueCallbackStartPath = new Path(); + valueCallbackEndPath = new Path(); + } + MiscUtils.getPathFromData(startShapeData, valueCallbackStartPath); + if (endShapeData != null) { + MiscUtils.getPathFromData(endShapeData, valueCallbackEndPath); + } + + return valueCallback.getValueInternal(keyframe.startFrame, keyframe.endFrame, + valueCallbackStartPath, endShapeData == null ? valueCallbackStartPath : valueCallbackEndPath, + keyframeProgress, getLinearCurrentKeyframeProgress(), getProgress()); + } return tempPath; } diff --git a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/DynamicPropertiesTestCase.kt b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/DynamicPropertiesTestCase.kt index 5a779de683..1094101b84 100644 --- a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/DynamicPropertiesTestCase.kt +++ b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/tests/DynamicPropertiesTestCase.kt @@ -1,7 +1,9 @@ package com.airbnb.lottie.snapshots.tests import android.graphics.Color +import android.graphics.Path import android.graphics.PointF +import android.graphics.RectF import com.airbnb.lottie.LottieProperty import com.airbnb.lottie.SimpleColorFilter import com.airbnb.lottie.model.KeyPath @@ -21,56 +23,56 @@ class DynamicPropertiesTestCase : SnapshotTestCase { "Fill color (Green)", KeyPath("Shape Layer 1", "Rectangle", "Fill 1"), LottieProperty.COLOR, - LottieValueCallback(Color.GREEN) + LottieValueCallback(Color.GREEN), ) testDynamicProperty( "Fill color (Yellow)", KeyPath("Shape Layer 1", "Rectangle", "Fill 1"), LottieProperty.COLOR, - LottieValueCallback(Color.YELLOW) + LottieValueCallback(Color.YELLOW), ) testDynamicProperty( "Fill opacity", KeyPath("Shape Layer 1", "Rectangle", "Fill 1"), LottieProperty.OPACITY, - LottieValueCallback(50) + LottieValueCallback(50), ) testDynamicProperty( "Stroke color", KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"), LottieProperty.STROKE_COLOR, - LottieValueCallback(Color.GREEN) + LottieValueCallback(Color.GREEN), ) testDynamicProperty( "Stroke width", KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"), LottieProperty.STROKE_WIDTH, - LottieRelativeFloatValueCallback(50f) + LottieRelativeFloatValueCallback(50f), ) testDynamicProperty( "Stroke opacity", KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"), LottieProperty.OPACITY, - LottieValueCallback(50) + LottieValueCallback(50), ) testDynamicProperty( "Transform anchor point", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_ANCHOR_POINT, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Transform position", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) @@ -82,7 +84,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { override fun getValue(frameInfo: LottieFrameInfo) = frameInfo.startValue }, progress = 1f, - assetName = "Tests/SplitPathTransform.json" + assetName = "Tests/SplitPathTransform.json", ) testDynamicProperty( @@ -93,224 +95,224 @@ class DynamicPropertiesTestCase : SnapshotTestCase { override fun getValue(frameInfo: LottieFrameInfo) = frameInfo.startValue }, progress = 1f, - assetName = "Tests/SplitPathTransform.json" + assetName = "Tests/SplitPathTransform.json", ) testDynamicProperty( "Transform position (relative)", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Transform opacity", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_OPACITY, - LottieValueCallback(50) + LottieValueCallback(50), ) testDynamicProperty( "Transform rotation", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_ROTATION, - LottieValueCallback(45f) + LottieValueCallback(45f), ) testDynamicProperty( "Transform scale", KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_SCALE, - LottieValueCallback(ScaleXY(0.5f, 0.5f)) + LottieValueCallback(ScaleXY(0.5f, 0.5f)), ) testDynamicProperty( "Rectangle corner roundedness", KeyPath("Shape Layer 1", "Rectangle", "Rectangle Path 1"), LottieProperty.CORNER_RADIUS, - LottieValueCallback(7f) + LottieValueCallback(7f), ) testDynamicProperty( "Rectangle position", KeyPath("Shape Layer 1", "Rectangle", "Rectangle Path 1"), LottieProperty.POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Rectangle size", KeyPath("Shape Layer 1", "Rectangle", "Rectangle Path 1"), LottieProperty.RECTANGLE_SIZE, - LottieRelativePointValueCallback(PointF(30f, 40f)) + LottieRelativePointValueCallback(PointF(30f, 40f)), ) testDynamicProperty( "Ellipse position", KeyPath("Shape Layer 1", "Ellipse", "Ellipse Path 1"), LottieProperty.POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Ellipse size", KeyPath("Shape Layer 1", "Ellipse", "Ellipse Path 1"), LottieProperty.ELLIPSE_SIZE, - LottieRelativePointValueCallback(PointF(40f, 60f)) + LottieRelativePointValueCallback(PointF(40f, 60f)), ) testDynamicProperty( "Star points", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_POINTS, - LottieValueCallback(8f) + LottieValueCallback(8f), ) testDynamicProperty( "Star rotation", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_ROTATION, - LottieValueCallback(10f) + LottieValueCallback(10f), ) testDynamicProperty( "Star position", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Star inner radius", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_INNER_RADIUS, - LottieValueCallback(10f) + LottieValueCallback(10f), ) testDynamicProperty( "Star inner roundedness", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_INNER_ROUNDEDNESS, - LottieValueCallback(100f) + LottieValueCallback(100f), ) testDynamicProperty( "Star outer radius", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_OUTER_RADIUS, - LottieValueCallback(60f) + LottieValueCallback(60f), ) testDynamicProperty( "Star outer roundedness", KeyPath("Shape Layer 1", "Star", "Polystar Path 1"), LottieProperty.POLYSTAR_OUTER_ROUNDEDNESS, - LottieValueCallback(100f) + LottieValueCallback(100f), ) testDynamicProperty( "Polygon points", KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"), LottieProperty.POLYSTAR_POINTS, - LottieValueCallback(8f) + LottieValueCallback(8f), ) testDynamicProperty( "Polygon rotation", KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"), LottieProperty.POLYSTAR_ROTATION, - LottieValueCallback(10f) + LottieValueCallback(10f), ) testDynamicProperty( "Polygon position", KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"), LottieProperty.POSITION, - LottieRelativePointValueCallback(PointF(20f, 20f)) + LottieRelativePointValueCallback(PointF(20f, 20f)), ) testDynamicProperty( "Polygon radius", KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"), LottieProperty.POLYSTAR_OUTER_RADIUS, - LottieRelativeFloatValueCallback(60f) + LottieRelativeFloatValueCallback(60f), ) testDynamicProperty( "Polygon roundedness", KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"), LottieProperty.POLYSTAR_OUTER_ROUNDEDNESS, - LottieValueCallback(100f) + LottieValueCallback(100f), ) testDynamicProperty( "Repeater transform position", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_POSITION, - LottieRelativePointValueCallback(PointF(100f, 100f)) + LottieRelativePointValueCallback(PointF(100f, 100f)), ) testDynamicProperty( "Repeater contents", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_POSITION, - LottieRelativePointValueCallback(PointF(100f, 100f)) + LottieRelativePointValueCallback(PointF(100f, 100f)), ) testDynamicProperty( "Repeater sub-contents", KeyPath("Shape Layer 1", "Repeater Shape", "Fill 1"), LottieProperty.COLOR_FILTER, - LottieValueCallback(SimpleColorFilter(Color.GREEN)) + LottieValueCallback(SimpleColorFilter(Color.GREEN)), ) testDynamicProperty( "Repeater transform start opacity", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_START_OPACITY, - LottieValueCallback(25f) + LottieValueCallback(25f), ) testDynamicProperty( "Repeater transform end opacity", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_END_OPACITY, - LottieValueCallback(25f) + LottieValueCallback(25f), ) testDynamicProperty( "Repeater transform rotation", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_ROTATION, - LottieValueCallback(45f) + LottieValueCallback(45f), ) testDynamicProperty( "Repeater transform scale", KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"), LottieProperty.TRANSFORM_SCALE, - LottieValueCallback(ScaleXY(2f, 2f)) + LottieValueCallback(ScaleXY(2f, 2f)), ) testDynamicProperty( "Time remapping", KeyPath("Circle 1"), LottieProperty.TIME_REMAP, - LottieValueCallback(1f) + LottieValueCallback(1f), ) testDynamicProperty( "Color Filter", KeyPath("**"), LottieProperty.COLOR_FILTER, - LottieValueCallback(SimpleColorFilter(Color.GREEN)) + LottieValueCallback(SimpleColorFilter(Color.GREEN)), ) testDynamicProperty( "Null Color Filter", KeyPath("**"), LottieProperty.COLOR_FILTER, - LottieValueCallback(null) + LottieValueCallback(null), ) testDynamicProperty( @@ -318,7 +320,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_OPACITY, LottieInterpolatedIntegerValue(10, 100), - 0f + 0f, ) testDynamicProperty( @@ -326,7 +328,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_OPACITY, LottieInterpolatedIntegerValue(10, 100), - 0.5f + 0.5f, ) testDynamicProperty( @@ -334,7 +336,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "Rectangle"), LottieProperty.TRANSFORM_OPACITY, LottieInterpolatedIntegerValue(10, 100), - 1f + 1f, ) testDynamicProperty( @@ -342,7 +344,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "**"), LottieProperty.DROP_SHADOW_COLOR, LottieValueCallback(Color.RED), - assetName = "Tests/AnimatedShadow.json" + assetName = "Tests/AnimatedShadow.json", ) testDynamicProperty( @@ -350,7 +352,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "**"), LottieProperty.DROP_SHADOW_DISTANCE, LottieValueCallback(30f), - assetName = "Tests/AnimatedShadow.json" + assetName = "Tests/AnimatedShadow.json", ) testDynamicProperty( @@ -358,7 +360,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "**"), LottieProperty.DROP_SHADOW_DIRECTION, LottieValueCallback(30f), - assetName = "Tests/AnimatedShadow.json" + assetName = "Tests/AnimatedShadow.json", ) testDynamicProperty( @@ -366,7 +368,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "**"), LottieProperty.DROP_SHADOW_RADIUS, LottieValueCallback(40f), - assetName = "Tests/AnimatedShadow.json" + assetName = "Tests/AnimatedShadow.json", ) testDynamicProperty( @@ -374,7 +376,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Shape Layer 1", "**"), LottieProperty.DROP_SHADOW_OPACITY, LottieValueCallback(0.2f), - assetName = "Tests/AnimatedShadow.json" + assetName = "Tests/AnimatedShadow.json", ) testDynamicProperty( @@ -382,7 +384,7 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Cyan Solid 1", "**"), LottieProperty.COLOR, LottieValueCallback(Color.YELLOW), - assetName = "Tests/SolidLayerTransform.json" + assetName = "Tests/SolidLayerTransform.json", ) testDynamicProperty( @@ -390,7 +392,28 @@ class DynamicPropertiesTestCase : SnapshotTestCase { KeyPath("Cyan Solid 1", "**"), LottieProperty.COLOR, LottieValueCallback(null), - assetName = "Tests/SolidLayerTransform.json" + assetName = "Tests/SolidLayerTransform.json", + ) + + testDynamicProperty( + "Shape", + KeyPath("Shape Layer 2", "Polystar 1", "Path 1"), + LottieProperty.PATH, + object : LottieValueCallback() { + override fun getValue(frameInfo: LottieFrameInfo): Path? { + val rect = RectF() + frameInfo.startValue.computeBounds(rect, false) + return Path().apply { + moveTo(rect.left, rect.top) + lineTo(rect.right, rect.top) + lineTo(rect.right, rect.bottom) + lineTo(rect.left, rect.bottom) + lineTo(rect.left, rect.top) + close() + } + } + }, + assetName = "Tests/Polygon.json", ) withDrawable("Tests/DynamicGradient.json", "Gradient Colors", "Linear Gradient Fill") { drawable -> diff --git a/snapshot-tests/src/main/assets/Tests/Polygon.json b/snapshot-tests/src/main/assets/Tests/Polygon.json new file mode 100644 index 0000000000..9173daa558 --- /dev/null +++ b/snapshot-tests/src/main/assets/Tests/Polygon.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":29.9700012207031,"ip":0,"op":900.000036657751,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[394,201,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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,-86.977],[25.562,-35.183],[82.72,-26.877],[41.36,13.439],[51.124,70.365],[0,43.488],[-51.124,70.365],[-41.36,13.439],[-82.72,-26.877],[-25.562,-35.183]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-106.035,-97.711],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"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":[200,200,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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,-86.977],[25.562,-35.183],[82.72,-26.877],[41.36,13.439],[51.124,70.365],[0,43.488],[-51.124,70.365],[-41.36,13.439],[-82.72,-26.877],[-25.562,-35.183]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-106.035,-97.711],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file