lottie-ios 3.4.0 → 3.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +10 -7
- package/.github/workflows/stale_issues.yml +17 -0
- package/.swiftpm/xcode/package.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcodeproj/project.pbxproj +33 -21
- package/Lottie.xcodeproj/xcshareddata/xcschemes/Lottie (macOS).xcscheme +2 -2
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +5 -6
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +114 -1
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +30 -0
- package/Package.swift +1 -1
- package/README.md +5 -6
- package/Rakefile +52 -17
- package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +7 -2
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +192 -67
- package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +28 -0
- package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +31 -4
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +98 -43
- package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +19 -19
- package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +34 -7
- package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +25 -14
- package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +61 -32
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +6 -2
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +29 -11
- package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +2 -2
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +116 -23
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +9 -0
- package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +2 -1
- package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +48 -12
- package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +10 -3
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +5 -0
- package/Sources/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +1 -1
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +85 -0
- package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +94 -38
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +131 -46
- package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +16 -2
- package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +1 -1
- package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +0 -2
- package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +2 -2
- package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +1 -2
- package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +30 -1
- package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -0
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +0 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +5 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +4 -7
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +5 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +1 -2
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +3 -3
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +3 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +28 -1
- package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +0 -1
- package/Sources/Private/Model/Animation.swift +4 -4
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +25 -0
- package/Sources/Private/Model/ShapeItems/Ellipse.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Fill.swift +1 -1
- package/Sources/Private/Model/ShapeItems/GradientFill.swift +14 -1
- package/Sources/Private/Model/ShapeItems/GradientStroke.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Group.swift +6 -1
- package/Sources/Private/Model/ShapeItems/Merge.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Rectangle.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Repeater.swift +0 -1
- package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Star.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Stroke.swift +0 -1
- package/Sources/Private/Model/ShapeItems/Trim.swift +0 -1
- package/Sources/Private/Model/Text/TextAnimator.swift +0 -1
- package/Sources/Private/Utility/Debugging/LayerDebugging.swift +1 -2
- package/Sources/Private/Utility/Extensions/MathKit.swift +1 -2
- package/Sources/Private/Utility/Extensions/StringExtensions.swift +0 -1
- package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +0 -1
- package/Sources/Private/{MainThread/NodeRenderSystem/NodeProperties/ValueProviders → Utility/Interpolatable}/KeyframeInterpolator.swift +1 -4
- package/Sources/Private/Utility/Primitives/BezierPath.swift +1 -2
- package/Sources/Private/Utility/Primitives/CurveVertex.swift +2 -4
- package/Sources/Public/Animation/AnimationPublic.swift +2 -4
- package/Sources/Public/Animation/AnimationView.swift +29 -7
- package/Sources/Public/Animation/AnimationViewInitializers.swift +13 -11
- package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +0 -2
- package/Sources/Public/FontProvider/AnimationFontProvider.swift +1 -1
- package/Sources/Public/Logging/LottieLogger.swift +15 -2
- package/Sources/Public/TextProvider/AnimationTextProvider.swift +1 -1
- package/Sources/Public/iOS/AnimatedButton.swift +10 -4
- package/Sources/Public/iOS/AnimatedControl.swift +3 -5
- package/Sources/Public/iOS/AnimatedSwitch.swift +9 -6
- package/Sources/Public/iOS/BundleImageProvider.swift +2 -3
- package/Sources/Public/iOS/FilepathImageProvider.swift +1 -2
- package/Sources/Public/macOS/BundleImageProvider.macOS.swift +1 -2
- package/Sources/Public/macOS/FilepathImageProvider.macOS.swift +1 -3
- package/Tests/AnimationKeypathTests.swift +10 -1
- package/Tests/AutomaticEngineTests.swift +1 -0
- package/Tests/ParsingTests.swift +2 -1
- package/Tests/PerformanceTests.swift +28 -29
- package/Tests/SnapshotConfiguration.swift +19 -0
- package/Tests/SnapshotTests.swift +4 -0
- package/Tests/Utils/HardcodedTextProvider.swift +27 -0
- package/lottie-ios.podspec +2 -2
- package/package.json +1 -1
- package/script/test-carthage/CarthageTest/AppDelegate.swift +6 -7
- package/script/test-carthage/CarthageTest/ViewController.swift +1 -1
- package/script/test-carthage/CarthageTest-macOS/AppDelegate.swift +7 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/Contents.json +6 -0
- package/script/test-carthage/CarthageTest-macOS/Base.lproj/Main.storyboard +717 -0
- package/script/test-carthage/CarthageTest-macOS/CarthageTest_macOS.entitlements +10 -0
- package/script/test-carthage/CarthageTest-macOS/ViewController.swift +15 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.pbxproj +159 -5
- package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
- package/Lottie.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +0 -23
- package/Mintfile +0 -3
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-7Vi1RszY1XYnR2CCkEwIpKG8NwwA9zsZEz_WD7Dv6kKh4RC7N7ob8NIRVHGUJKp7eXxlpeI_gzD87Pcs_2u0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-SKV2drO-SFlrlh-wrzECDMkUSr-aF1lV9h-5onOy94zSTsD-oI45s0-KpOK45L-kq3hRY7v9vm-xmh00_eheg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-_CU_vuaiFfObSeDFfmp7GuB20ThMSAL-P_RUMowiQLbdu-y0bU9upIm3q8g6XmXUG5hP6J1az0Ma5Hi_rhhRg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~03aPYP6VHJjZj5DlphGarj0xdw43qu09Onx5SReZoPvg9zh5uL212E-KWfGct9jf6JG0JFV2tdbBi7X_8bH9aw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~1Z82GPBBPc1VLvn4O7V5glb6lgyXteNlDREUzV_TPymM4ra4UkBMklzV90lEqoYRCDuRVzaQHaDYbmYp3-8CFw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~1mFDCboXpUu9pSHAiVGr1O_QgqEEtvJp_LUhickxLZo0Z5pj3fvadn1l2MzEOd4bFsVBZifUvcyPa7dzlMWF-A== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~2_L9PUjv2JDKu1n8bDLb4XLB-yex6ZVjDDMwfuKAr7teDw-SKgLgkW6H-m_gjWChIVdB4vW6yvHP7XJxvXtRNA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -1
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4krT4ZMzDOu34msFUq0Xod142kw4pAeSWX4JSxlsjOI0Wanu3343qeespgFi61MTWq1DdH9XXspVKqGlGm_fyw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~5_aJsdP-e3dRTAUnH-y1U2plaCuUi1vyHriaZuNK0xFe8wGl9Qft6uLCX2Qt6CRBKJQluEe9o0uRWw1eb42FHQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~8b0bSqV7eND54zvHvu1v2Htpm7yn-BOEFw5d3mITJrXWNykJ5BTR9WbrD80JEctNcT-rDqO2xfrQk1tFWeY6Sw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~9u8KAGpgtSm-mQ12Py8RZUbYbDlBhM3w1I2MQO53K2CSn6IePp7g65DBcdXTYMfG1bgoJ-6x30fjnGe-2UYsDQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Bw7uMs4wqB9ahfEqGii2FkQ9pvZmG6HGe2hmbAT2wyM5hpn8Xh5dELysMcEz6hEsqmn6HdRdLOLZhC_fNaXzgA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~BwUq2xXQYuE8ya6HT6lfNsdtEjz5AKGf8GvLY6VBxQyIY1vgj_Gov-3NeM69OS66BQRDK0PG9H4Oyg0R48E4vg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~EkDVUR6dcnzxV_lYjkrJ5QGMVTCvb_upAoBF6DBu61sQkGvZN3fSRTsJ1XfJIZO-JUzdNoVA3D_CcvokL0gnQg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~FUkcLSJ8RAuPenM4HFG1R-sN5-cDBGcTxgR2jaVCna7xV0ZTyBHriB1Nn59mariNlJDiCoBtMUQEmauGxWtfBA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~FqsuZe4RVLOOVUYLTL-GTIohZ8TdSfxx7m2KJtLYFPGOdE4XorTX7Oc7kXbhghPRppXT3jW-slI37M34YNEvLQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~G4F_NtyTj3i46fmKm0NorHAeq8tYWWYf6uv5yC1DwzdpWVoYbOPufmFNvdEbxZt4AMdV0gKx3HI46EAXNOQVFg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~GxetzGUNDgaBBXcTmLK6p9JBDX3I3QPshshbui1IaEWvJbQko-E36tCKwaJYHbleAWz9FqkAM_Tqx3YOmSVkVg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~H1Wjd5kKWDW4t3SDodxiHV72V8WT0xwPubw5cJTNLkPRLgaILFPh-dpy8EOUNgy1KzrDujFsm9EcTsbuqtMPLA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~JpI5MH4zCgebUHFpXVn4zjtsGtMNnO7BQZWfNARAB5UWa9gqz6YXHR3uLCJ_AvJ3lh53BUVkavsx9TY2FMmxbA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~JujNYkJtcux0Ni4QnR64zu4Wz_zYjyKvYaYZm5ypxTLPSzF3_jNE_NO4sdbDamF8wEqWoky1uf4ZE0JT3L607A== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~KJSEA6DKnb2_FRPSqKZGh41eo-C8x448J9kEBrH012bUrZfOSDvrgmIrU0Vz7Ri3gaS9aKKmSaVMvXsHSlTJVA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~MStOwu3jBlJtcRnxrseVOuhI4kCj--ggFPG7sqrq5w1hjrI3bVyD-bm1Jwyx0noY3wT1rHDEvaGWnV2qsGjGwg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~McsJ8kFVf3IjhgXIRdw8Xx-EXgbV071bmlj2BBnk52xrWl3sEeiIyxwUsF7mIWvMRWfcFfu4VGHYyqfk2BeHXw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~NHt9fVe4kDdbxnglKcEwXaRK-WsYEOaD23Kbl8SJPRMYHr_Z6SJd_HmG3BROHHR_M6TgSmucONpDJdTj5tjuFw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Nfo2iwCPcfAcOBIVyoUAK0-PIfr5qYxIKZt-uaSaTBdrTNxAuJ1ItmeDPZ3VdJJmxD_c22No7x482bdd3_yYtw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~S2Qlu11xBhEd5aGSzWsnw1TR8u8PiOF93GO0j5bfNoAFCVzxKOwhRFoIXba2EpQnLQqFdIKyhWN3l70A4GPHmg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~W7a7M37RO9jgck2zeR0471Pm7e8K0Kqj5tXEouDjvqKZXSrWxMaWD28oqkKKYAiU4608R4S9mM11KyphljdMSw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~XUo1oyPCrlL7CA74wG-OzQ06VOWJYWvHGFHU7keZN1SKaIXjHX5qi_kBzjG_rBCi89-S8GVmCy7S3PHSjG8SbQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Xh0VmDvFNMELHu08-vrs54pegVyUwwDRxx_nXkwyD0NjnYozyqcGAKAr_QWHmw6F8XyuWg51M9KGpJJIFzzGuw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Xve-wMBp_lxVUgD9qH5GwieGP9cAWtm0xULZvdGjBRUMvaevmpCB5gnbMBuIXAO6a1c9v6WUq0jNVX7ut5HvOw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ZU1XkZFgnEE22CXEF-pOlcj5f10x-KM1Vw9d4IOLu-NiTZcz7koYPixhdrB1PJr8J-h9NpJmfqEastfxamA1jQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~_YkNYEHTsbbtFILJpzH3HenH0t4ShI25dIMdve541CF5bl-jPF3X3F7tq-t5dvP0TEkATsOJdLQdBp1xv4Q-ag== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~boy6mpn2jkwm60jjgQ0TG25UqRdN46LzmgTVCrpy6nBOgkLCGkGHcbceiwjU1itS_vj3-iQX0ZnrWOQrPyfHNA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~bwzpVZ9hAqGDHhXs2FRA82dfGfLmc7-m0uQhZDDfHHO7hQ17M_Np341BZX4WDLhYYS4cdUgaDodlNpdfpG3nXw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cBxe-9PpAGFdAsYkmdN3lJVqEliLcRYlyoAov0aPZfJGwUr_cOm3XpjO7nmf_2eLf8UAx-rycjnJzw07xLrNCA== +0 -1
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~dirWk6W4Pav1oyciuflfJlRu0iuxbYOmrpQapOJ0mV9C1SQ-jvDRv_7h753Cy18-SwULARUdWsyUy3yNNvxF7w== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ebwZVjSEHroc9jtIm4jd_h_YAqEBcOkAZ4HPNJT8pLCldjRcTq-obQLakxXOhfuoOBlYBoZLuO-Y0lskeZRYKw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~gfcRcmRIr0h09d0jiZsA7nUeQv2XtapxuYEXZy1Z9um0tTJQvz-O5ef5f7zhLenLvjnDtDtlY_aY4Hvpce6e1Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~hgOgiVCyv2R0W-f0qKw5xYPeUwj8_ccCM9vKH_7vAQcCO9t8BwR1APGRBv20AONmp-PYMXmtgsBlQkNBRBpdQA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~hrhCl-YRAAr8ByNB_LCgEBsVNHMp92gTIUknetpUHMjcXl4Hpn_uY-h6C45oga0ZALnfGCo6iKTmiPLa4Qvnpg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~n2yoR7JsyL4DSUwmjnpE4Iq9Qi_eeZrmpPU8cdehDFKfESK7nwxXxfrSMQbk0BQ2lgGPadoRcd1-qr1xVz97jA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~nMCcZm8WvPogyO_nuJ926Q3Q2dqVMN2LdjEL1Kq2wJ_RG-rH-e_6v41l1xZbCsQTa3XykQdEiXNc0HtAvT6IRA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~oc3C7xkUt-OWDL6rrsxs-seS4Fu1bqBWAAXCHalgShaGg9MUrOiRbHT2DcAnhyQFKx6x5FRbvjmYoQWrQiXJZA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~p-ihj7SEgkDXpMu9hvKE_wiX9cvtwyXrdIn964BfedXHKGpC6o7mMPxEyC0kRPVi_EZs_MRV5bAPEpl5h5we0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~qlhO_D9oE8uSKH-mZqyRF9pp4Zv1Tv0dIYcqrH4hb1VWlIxcdxmg2j0M8496cQeFXC5bn_JMXdBlD-d6cnFF8w== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~tjpiyIxJR_boTdUNrtFDuKIZoY84fI4lA1oMJbq9e2ZmYKIK5FeRN2O8cV_yMOYJGr4lbv03kTmT70mCjUc2_Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~wULeoj18eEKJWAKx1uFQVwS48cUGFcYPRJQj1Ro5XNJsWCwppGSCdIPhwifD6Z2f_j3zfI2SmC2Gg81sBXXW7g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~zrEihMys4NVV5rx6FmuzEGO2TjloI3OiC7yzIhvqYoRo43ibb2F-Km6Jf4NX-ac62pOLBYZRcjQTvYMpn75_oA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-7Vi1RszY1XYnR2CCkEwIpKG8NwwA9zsZEz_WD7Dv6kKh4RC7N7ob8NIRVHGUJKp7eXxlpeI_gzD87Pcs_2u0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-SKV2drO-SFlrlh-wrzECDMkUSr-aF1lV9h-5onOy94zSTsD-oI45s0-KpOK45L-kq3hRY7v9vm-xmh00_eheg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-_CU_vuaiFfObSeDFfmp7GuB20ThMSAL-P_RUMowiQLbdu-y0bU9upIm3q8g6XmXUG5hP6J1az0Ma5Hi_rhhRg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~03aPYP6VHJjZj5DlphGarj0xdw43qu09Onx5SReZoPvg9zh5uL212E-KWfGct9jf6JG0JFV2tdbBi7X_8bH9aw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~1Z82GPBBPc1VLvn4O7V5glb6lgyXteNlDREUzV_TPymM4ra4UkBMklzV90lEqoYRCDuRVzaQHaDYbmYp3-8CFw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~1mFDCboXpUu9pSHAiVGr1O_QgqEEtvJp_LUhickxLZo0Z5pj3fvadn1l2MzEOd4bFsVBZifUvcyPa7dzlMWF-A== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~2_L9PUjv2JDKu1n8bDLb4XLB-yex6ZVjDDMwfuKAr7teDw-SKgLgkW6H-m_gjWChIVdB4vW6yvHP7XJxvXtRNA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4krT4ZMzDOu34msFUq0Xod142kw4pAeSWX4JSxlsjOI0Wanu3343qeespgFi61MTWq1DdH9XXspVKqGlGm_fyw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~5_aJsdP-e3dRTAUnH-y1U2plaCuUi1vyHriaZuNK0xFe8wGl9Qft6uLCX2Qt6CRBKJQluEe9o0uRWw1eb42FHQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~8b0bSqV7eND54zvHvu1v2Htpm7yn-BOEFw5d3mITJrXWNykJ5BTR9WbrD80JEctNcT-rDqO2xfrQk1tFWeY6Sw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~9u8KAGpgtSm-mQ12Py8RZUbYbDlBhM3w1I2MQO53K2CSn6IePp7g65DBcdXTYMfG1bgoJ-6x30fjnGe-2UYsDQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Bw7uMs4wqB9ahfEqGii2FkQ9pvZmG6HGe2hmbAT2wyM5hpn8Xh5dELysMcEz6hEsqmn6HdRdLOLZhC_fNaXzgA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~BwUq2xXQYuE8ya6HT6lfNsdtEjz5AKGf8GvLY6VBxQyIY1vgj_Gov-3NeM69OS66BQRDK0PG9H4Oyg0R48E4vg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~EkDVUR6dcnzxV_lYjkrJ5QGMVTCvb_upAoBF6DBu61sQkGvZN3fSRTsJ1XfJIZO-JUzdNoVA3D_CcvokL0gnQg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~FUkcLSJ8RAuPenM4HFG1R-sN5-cDBGcTxgR2jaVCna7xV0ZTyBHriB1Nn59mariNlJDiCoBtMUQEmauGxWtfBA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~FqsuZe4RVLOOVUYLTL-GTIohZ8TdSfxx7m2KJtLYFPGOdE4XorTX7Oc7kXbhghPRppXT3jW-slI37M34YNEvLQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~G4F_NtyTj3i46fmKm0NorHAeq8tYWWYf6uv5yC1DwzdpWVoYbOPufmFNvdEbxZt4AMdV0gKx3HI46EAXNOQVFg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~GxetzGUNDgaBBXcTmLK6p9JBDX3I3QPshshbui1IaEWvJbQko-E36tCKwaJYHbleAWz9FqkAM_Tqx3YOmSVkVg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~H1Wjd5kKWDW4t3SDodxiHV72V8WT0xwPubw5cJTNLkPRLgaILFPh-dpy8EOUNgy1KzrDujFsm9EcTsbuqtMPLA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~JpI5MH4zCgebUHFpXVn4zjtsGtMNnO7BQZWfNARAB5UWa9gqz6YXHR3uLCJ_AvJ3lh53BUVkavsx9TY2FMmxbA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~JujNYkJtcux0Ni4QnR64zu4Wz_zYjyKvYaYZm5ypxTLPSzF3_jNE_NO4sdbDamF8wEqWoky1uf4ZE0JT3L607A== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~KJSEA6DKnb2_FRPSqKZGh41eo-C8x448J9kEBrH012bUrZfOSDvrgmIrU0Vz7Ri3gaS9aKKmSaVMvXsHSlTJVA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~MStOwu3jBlJtcRnxrseVOuhI4kCj--ggFPG7sqrq5w1hjrI3bVyD-bm1Jwyx0noY3wT1rHDEvaGWnV2qsGjGwg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~McsJ8kFVf3IjhgXIRdw8Xx-EXgbV071bmlj2BBnk52xrWl3sEeiIyxwUsF7mIWvMRWfcFfu4VGHYyqfk2BeHXw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~NHt9fVe4kDdbxnglKcEwXaRK-WsYEOaD23Kbl8SJPRMYHr_Z6SJd_HmG3BROHHR_M6TgSmucONpDJdTj5tjuFw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Nfo2iwCPcfAcOBIVyoUAK0-PIfr5qYxIKZt-uaSaTBdrTNxAuJ1ItmeDPZ3VdJJmxD_c22No7x482bdd3_yYtw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~S2Qlu11xBhEd5aGSzWsnw1TR8u8PiOF93GO0j5bfNoAFCVzxKOwhRFoIXba2EpQnLQqFdIKyhWN3l70A4GPHmg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~W7a7M37RO9jgck2zeR0471Pm7e8K0Kqj5tXEouDjvqKZXSrWxMaWD28oqkKKYAiU4608R4S9mM11KyphljdMSw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~XUo1oyPCrlL7CA74wG-OzQ06VOWJYWvHGFHU7keZN1SKaIXjHX5qi_kBzjG_rBCi89-S8GVmCy7S3PHSjG8SbQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Xh0VmDvFNMELHu08-vrs54pegVyUwwDRxx_nXkwyD0NjnYozyqcGAKAr_QWHmw6F8XyuWg51M9KGpJJIFzzGuw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Xve-wMBp_lxVUgD9qH5GwieGP9cAWtm0xULZvdGjBRUMvaevmpCB5gnbMBuIXAO6a1c9v6WUq0jNVX7ut5HvOw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ZU1XkZFgnEE22CXEF-pOlcj5f10x-KM1Vw9d4IOLu-NiTZcz7koYPixhdrB1PJr8J-h9NpJmfqEastfxamA1jQ== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~_YkNYEHTsbbtFILJpzH3HenH0t4ShI25dIMdve541CF5bl-jPF3X3F7tq-t5dvP0TEkATsOJdLQdBp1xv4Q-ag== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~boy6mpn2jkwm60jjgQ0TG25UqRdN46LzmgTVCrpy6nBOgkLCGkGHcbceiwjU1itS_vj3-iQX0ZnrWOQrPyfHNA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~bwzpVZ9hAqGDHhXs2FRA82dfGfLmc7-m0uQhZDDfHHO7hQ17M_Np341BZX4WDLhYYS4cdUgaDodlNpdfpG3nXw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cBxe-9PpAGFdAsYkmdN3lJVqEliLcRYlyoAov0aPZfJGwUr_cOm3XpjO7nmf_2eLf8UAx-rycjnJzw07xLrNCA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~dirWk6W4Pav1oyciuflfJlRu0iuxbYOmrpQapOJ0mV9C1SQ-jvDRv_7h753Cy18-SwULARUdWsyUy3yNNvxF7w== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ebwZVjSEHroc9jtIm4jd_h_YAqEBcOkAZ4HPNJT8pLCldjRcTq-obQLakxXOhfuoOBlYBoZLuO-Y0lskeZRYKw== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~gfcRcmRIr0h09d0jiZsA7nUeQv2XtapxuYEXZy1Z9um0tTJQvz-O5ef5f7zhLenLvjnDtDtlY_aY4Hvpce6e1Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~hgOgiVCyv2R0W-f0qKw5xYPeUwj8_ccCM9vKH_7vAQcCO9t8BwR1APGRBv20AONmp-PYMXmtgsBlQkNBRBpdQA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~hrhCl-YRAAr8ByNB_LCgEBsVNHMp92gTIUknetpUHMjcXl4Hpn_uY-h6C45oga0ZALnfGCo6iKTmiPLa4Qvnpg== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~n2yoR7JsyL4DSUwmjnpE4Iq9Qi_eeZrmpPU8cdehDFKfESK7nwxXxfrSMQbk0BQ2lgGPadoRcd1-qr1xVz97jA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~nMCcZm8WvPogyO_nuJ926Q3Q2dqVMN2LdjEL1Kq2wJ_RG-rH-e_6v41l1xZbCsQTa3XykQdEiXNc0HtAvT6IRA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~oc3C7xkUt-OWDL6rrsxs-seS4Fu1bqBWAAXCHalgShaGg9MUrOiRbHT2DcAnhyQFKx6x5FRbvjmYoQWrQiXJZA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~p-ihj7SEgkDXpMu9hvKE_wiX9cvtwyXrdIn964BfedXHKGpC6o7mMPxEyC0kRPVi_EZs_MRV5bAPEpl5h5we0g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~qlhO_D9oE8uSKH-mZqyRF9pp4Zv1Tv0dIYcqrH4hb1VWlIxcdxmg2j0M8496cQeFXC5bn_JMXdBlD-d6cnFF8w== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~tjpiyIxJR_boTdUNrtFDuKIZoY84fI4lA1oMJbq9e2ZmYKIK5FeRN2O8cV_yMOYJGr4lbv03kTmT70mCjUc2_Q== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~wULeoj18eEKJWAKx1uFQVwS48cUGFcYPRJQj1Ro5XNJsWCwppGSCdIPhwifD6Z2f_j3zfI2SmC2Gg81sBXXW7g== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~zrEihMys4NVV5rx6FmuzEGO2TjloI3OiC7yzIhvqYoRo43ibb2F-Km6Jf4NX-ac62pOLBYZRcjQTvYMpn75_oA== +0 -0
- package/Tests/Artifacts/LottieTests.xcresult/Info.plist +0 -29
- package/Tests/Samples/9squares_AlBoardman.json +0 -1
- package/Tests/Samples/Boat_Loader.json +0 -1
- package/Tests/Samples/HamburgerArrow.json +0 -1
- package/Tests/Samples/IconTransitions.json +0 -1
- package/Tests/Samples/Images/dog.png +0 -0
- package/Tests/Samples/Issues/issue_1403.json +0 -1
- package/Tests/Samples/Issues/issue_1407.json +0 -1
- package/Tests/Samples/Issues/issue_1488.json +0 -1
- package/Tests/Samples/Issues/issue_1505.json +0 -1
- package/Tests/Samples/Issues/issue_1628.json +0 -1
- package/Tests/Samples/Issues/pr_1536.json +0 -1
- package/Tests/Samples/Issues/pr_1563.json +0 -8439
- package/Tests/Samples/Issues/pr_1592.json +0 -5527
- package/Tests/Samples/Issues/pr_1599.json +0 -738
- package/Tests/Samples/Issues/pr_1604_1.json +0 -1
- package/Tests/Samples/Issues/pr_1604_2.json +0 -1
- package/Tests/Samples/LottieFiles/LICENSE.md +0 -14
- package/Tests/Samples/LottieFiles/bounce_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/cactus.json +0 -1
- package/Tests/Samples/LottieFiles/dog_car_ride.json +0 -1
- package/Tests/Samples/LottieFiles/draft_icon.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_1.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_2.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_pill.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_shapes.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_square.json +0 -1
- package/Tests/Samples/LottieFiles/growth.json +0 -1
- package/Tests/Samples/LottieFiles/infinity_loader.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_1.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_2.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_3.json +0 -1
- package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/settings_slider.json +0 -1
- package/Tests/Samples/LottieFiles/shop.json +0 -1
- package/Tests/Samples/LottieFiles/step_loader.json +0 -1
- package/Tests/Samples/LottieLogo1.json +0 -1
- package/Tests/Samples/LottieLogo1_masked.json +0 -1
- package/Tests/Samples/LottieLogo2.json +0 -1
- package/Tests/Samples/MotionCorpse_Jrcanest.json +0 -1
- package/Tests/Samples/Nonanimating/BasicLayers.json +0 -1
- package/Tests/Samples/Nonanimating/DisableNodesTest.json +0 -1
- package/Tests/Samples/Nonanimating/FirstText.json +0 -1
- package/Tests/Samples/Nonanimating/GeometryTransformTest.json +0 -1
- package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +0 -1
- package/Tests/Samples/Nonanimating/Text_Glyph.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoAnimation.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoGlyph.json +0 -1
- package/Tests/Samples/Nonanimating/Zoom.json +0 -1
- package/Tests/Samples/Nonanimating/_dog.json +0 -1
- package/Tests/Samples/Nonanimating/base64Test.json +0 -1
- package/Tests/Samples/Nonanimating/blend_mode_test.json +0 -1
- package/Tests/Samples/Nonanimating/keypathTest.json +0 -1
- package/Tests/Samples/Nonanimating/verifyLineHeight.json +0 -1
- package/Tests/Samples/PinJump.json +0 -1
- package/Tests/Samples/Private/BrokenLottieFiles/growth_man.json +0 -874
- package/Tests/Samples/Private/BrokenLottieFiles/rocket.json +0 -1
- package/Tests/Samples/Private/China_EmptyState_Itinerary.json +0 -1
- package/Tests/Samples/Private/LoaderHourglass.json +0 -12070
- package/Tests/Samples/Private/README.md +0 -7
- package/Tests/Samples/Private/Urgency/alarm_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/diamond_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/eye_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/light_bulb_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/light_bulb_static.json +0 -1
- package/Tests/Samples/Private/Urgency/piggy_bank_static.json +0 -1
- package/Tests/Samples/Private/Urgency/price_tag_legacy.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_alarm.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_alert.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_clock.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_diamond.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_money.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_piggy_bank.json +0 -1
- package/Tests/Samples/Private/Urgency/rausch_tag.json +0 -1
- package/Tests/Samples/Private/Urgency/red_envelope_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/tag_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/trophy_animated.json +0 -1
- package/Tests/Samples/Private/Urgency/wings_key_animated.json +0 -1
- package/Tests/Samples/Private/_flexible.json +0 -1
- package/Tests/Samples/Private/aircover.json +0 -1
- package/Tests/Samples/Private/belo_spin_rausch.json +0 -1
- package/Tests/Samples/Private/celebration.json +0 -2821
- package/Tests/Samples/Private/checkbox.json +0 -1
- package/Tests/Samples/Private/checkbox_small.json +0 -1
- package/Tests/Samples/Private/getting_your_trip_ready.json +0 -3540
- package/Tests/Samples/Private/gradient_afternoon.json +0 -1
- package/Tests/Samples/Private/gradient_brand.json +0 -1
- package/Tests/Samples/Private/gradient_evening.json +0 -1
- package/Tests/Samples/Private/gradient_morning.json +0 -1
- package/Tests/Samples/Private/issue_1467.json +0 -1
- package/Tests/Samples/Private/loading_dots.json +0 -1
- package/Tests/Samples/Private/loading_dots_small.json +0 -1
- package/Tests/Samples/Private/payment_loader.json +0 -1
- package/Tests/Samples/Private/radio_button.json +0 -1
- package/Tests/Samples/Private/selfie_intro.json +0 -1
- package/Tests/Samples/Private/stepper_add.json +0 -1
- package/Tests/Samples/Private/stepper_subtract.json +0 -1
- package/Tests/Samples/Private/switch.json +0 -1
- package/Tests/Samples/Private/thumb.json +0 -1
- package/Tests/Samples/Private/toggle_no.json +0 -1
- package/Tests/Samples/Private/toggle_yes.json +0 -1
- package/Tests/Samples/Private/user_error_black_and_white.json +0 -1
- package/Tests/Samples/Private/user_error_cut_off.json +0 -1
- package/Tests/Samples/Switch.json +0 -1
- package/Tests/Samples/Switch_States.json +0 -1
- package/Tests/Samples/TwitterHeart.json +0 -1
- package/Tests/Samples/TwitterHeartButton.json +0 -1
- package/Tests/Samples/TypeFace/A.json +0 -1
- package/Tests/Samples/TypeFace/Apostrophe.json +0 -1
- package/Tests/Samples/TypeFace/B.json +0 -1
- package/Tests/Samples/TypeFace/BlinkingCursor.json +0 -1
- package/Tests/Samples/TypeFace/C.json +0 -1
- package/Tests/Samples/TypeFace/Colon.json +0 -1
- package/Tests/Samples/TypeFace/Comma.json +0 -1
- package/Tests/Samples/TypeFace/D.json +0 -1
- package/Tests/Samples/TypeFace/E.json +0 -1
- package/Tests/Samples/TypeFace/F.json +0 -1
- package/Tests/Samples/TypeFace/G.json +0 -1
- package/Tests/Samples/TypeFace/H.json +0 -1
- package/Tests/Samples/TypeFace/I.json +0 -1
- package/Tests/Samples/TypeFace/J.json +0 -1
- package/Tests/Samples/TypeFace/K.json +0 -1
- package/Tests/Samples/TypeFace/L.json +0 -1
- package/Tests/Samples/TypeFace/M.json +0 -1
- package/Tests/Samples/TypeFace/N.json +0 -1
- package/Tests/Samples/TypeFace/O.json +0 -1
- package/Tests/Samples/TypeFace/P.json +0 -1
- package/Tests/Samples/TypeFace/Q.json +0 -1
- package/Tests/Samples/TypeFace/R.json +0 -1
- package/Tests/Samples/TypeFace/S.json +0 -1
- package/Tests/Samples/TypeFace/T.json +0 -1
- package/Tests/Samples/TypeFace/U.json +0 -1
- package/Tests/Samples/TypeFace/V.json +0 -1
- package/Tests/Samples/TypeFace/W.json +0 -1
- package/Tests/Samples/TypeFace/X.json +0 -1
- package/Tests/Samples/TypeFace/Y.json +0 -1
- package/Tests/Samples/TypeFace/Z.json +0 -1
- package/Tests/Samples/Watermelon.json +0 -1
- package/Tests/Samples/setValueTest.json +0 -1
- package/Tests/Samples/timeremap.json +0 -1
- package/Tests/Samples/vcTransition1.json +0 -1
- package/Tests/Samples/vcTransition2.json +0 -1
- package/script/lint/airbnb.swiftformat +0 -68
- package/script/lint/swiftlint.yml +0 -38
- package/script/test-carthage/Carthage/Build/.lottie-ios.version +0 -19
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/Info.plist +0 -46
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/BCSymbolMaps/BF971162-BE99-3507-B5B3-11947DC6B176.bcsymbolmap +0 -14778
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Headers/Lottie-Swift.h +0 -673
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Info.plist +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Lottie +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/module.modulemap +0 -4
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/dSYMs/Lottie.framework.dSYM/Contents/Info.plist +0 -20
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/dSYMs/Lottie.framework.dSYM/Contents/Resources/DWARF/Lottie +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Headers/Lottie-Swift.h +0 -1352
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Info.plist +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Lottie +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/arm64.swiftsourceinfo +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/x86_64.swiftsourceinfo +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios-simulator.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64-apple-ios-simulator.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64.swiftdoc +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64.swiftmodule +0 -0
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/module.modulemap +0 -4
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/_CodeSignature/CodeResources +0 -256
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/dSYMs/Lottie.framework.dSYM/Contents/Info.plist +0 -20
- package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/dSYMs/Lottie.framework.dSYM/Contents/Resources/DWARF/Lottie +0 -0
- package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
- package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
package/Rakefile
CHANGED
|
@@ -75,6 +75,7 @@ namespace :test do
|
|
|
75
75
|
|
|
76
76
|
# Build a test app that imports and uses the LottieCarthage framework
|
|
77
77
|
xcodebuild('build -scheme CarthageTest -destination "platform=iOS Simulator,name=iPhone 8"')
|
|
78
|
+
xcodebuild('build -scheme CarthageTest-macOS')
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
|
|
@@ -91,19 +92,8 @@ end
|
|
|
91
92
|
|
|
92
93
|
namespace :lint do
|
|
93
94
|
desc 'Lints swift files'
|
|
94
|
-
task
|
|
95
|
-
|
|
96
|
-
desc 'Lints swift files'
|
|
97
|
-
namespace :swift do
|
|
98
|
-
desc 'Lints swift files using SwiftLint'
|
|
99
|
-
task :swiftlint do
|
|
100
|
-
sh 'mint run SwiftLint lint Sources Tests Example Package.swift --config script/lint/swiftlint.yml --strict'
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
desc 'Lints swift files using SwiftLint'
|
|
104
|
-
task :swiftformat do
|
|
105
|
-
sh 'mint run SwiftFormat Sources Tests Example Package.swift --config script/lint/airbnb.swiftformat --lint'
|
|
106
|
-
end
|
|
95
|
+
task :swift do
|
|
96
|
+
formatTool('format --lint')
|
|
107
97
|
end
|
|
108
98
|
|
|
109
99
|
desc 'Lints the CocoaPods podspec'
|
|
@@ -113,13 +103,58 @@ namespace :lint do
|
|
|
113
103
|
end
|
|
114
104
|
|
|
115
105
|
namespace :format do
|
|
116
|
-
desc '
|
|
106
|
+
desc 'Formats swift files'
|
|
117
107
|
task :swift do
|
|
118
|
-
|
|
119
|
-
sh 'mint run SwiftFormat Sources Tests Example Package.swift --config script/lint/airbnb.swiftformat'
|
|
108
|
+
formatTool('format')
|
|
120
109
|
end
|
|
121
110
|
end
|
|
122
111
|
|
|
123
112
|
def xcodebuild(command)
|
|
124
|
-
|
|
113
|
+
# Check if the mint tool is installed -- if so, pipe the xcodebuild output through xcbeautify
|
|
114
|
+
`which mint`
|
|
115
|
+
|
|
116
|
+
if $?.success?
|
|
117
|
+
sh "set -o pipefail && xcodebuild #{command} | mint run thii/xcbeautify@0.10.2"
|
|
118
|
+
else
|
|
119
|
+
sh "xcodebuild #{command}"
|
|
120
|
+
end
|
|
125
121
|
end
|
|
122
|
+
|
|
123
|
+
def formatTool(command)
|
|
124
|
+
# As of Xcode 13.4 / Xcode 14 beta 4, including airbnb/swift as a dependency
|
|
125
|
+
# causes Xcode to spin indefinitely at 100% CPU (due to the remote binary dependencies
|
|
126
|
+
# used by that package). As a workaround, we can specifically add that dependency
|
|
127
|
+
# to our Package.swift file when linting / formatting and remove it afterwards.
|
|
128
|
+
packageDefinition = File.read('Package.swift')
|
|
129
|
+
packageDefinitionWithFormatDependency = packageDefinition +
|
|
130
|
+
<<~EOC
|
|
131
|
+
|
|
132
|
+
#if swift(>=5.6)
|
|
133
|
+
// Add the Airbnb Swift formatting plugin if possible
|
|
134
|
+
package.dependencies.append(
|
|
135
|
+
.package(
|
|
136
|
+
url: "https://github.com/airbnb/swift",
|
|
137
|
+
// Since we don't have a Package.resolved for this, we need to reference a specific commit
|
|
138
|
+
// so changes to the style guide don't cause this repo's checks to start failing.
|
|
139
|
+
.revision("cec29280c35dd6eccba415fa3bfc24c819eae887")))
|
|
140
|
+
#endif
|
|
141
|
+
EOC
|
|
142
|
+
|
|
143
|
+
# Add the format tool dependency to our Package.swift
|
|
144
|
+
File.write('Package.swift', packageDefinitionWithFormatDependency)
|
|
145
|
+
|
|
146
|
+
exitCode = 0
|
|
147
|
+
|
|
148
|
+
# Run the given command
|
|
149
|
+
begin
|
|
150
|
+
sh "swift package --allow-writing-to-package-directory #{command}"
|
|
151
|
+
rescue
|
|
152
|
+
exitCode = $?.exitstatus
|
|
153
|
+
ensure
|
|
154
|
+
# Revert the changes to Package.swift
|
|
155
|
+
File.write('Package.swift', packageDefinition)
|
|
156
|
+
File.delete('Package.resolved')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
exit exitCode
|
|
160
|
+
end
|
|
@@ -5,10 +5,12 @@ import QuartzCore
|
|
|
5
5
|
|
|
6
6
|
extension CAAnimation {
|
|
7
7
|
/// Creates a `CAAnimation` that wraps this animation,
|
|
8
|
-
/// applying timing-related configuration from the given `LayerAnimationContext
|
|
8
|
+
/// applying timing-related configuration from the given `LayerAnimationContext`.
|
|
9
|
+
/// - This animation should start at the beginning of the animation and
|
|
10
|
+
/// last the entire duration of the animation. It will be trimmed and retimed
|
|
11
|
+
/// to match the current playback state / looping configuration of the animation view.
|
|
9
12
|
@nonobjc
|
|
10
13
|
func timed(with context: LayerAnimationContext, for layer: CALayer) -> CAAnimation {
|
|
11
|
-
|
|
12
14
|
// The base animation always has the duration of the full animation,
|
|
13
15
|
// since that's the time space where keyframing and interpolating happens.
|
|
14
16
|
// So we start with a simple animation timeline from 0% to 100%:
|
|
@@ -69,6 +71,9 @@ extension CAAnimation {
|
|
|
69
71
|
|
|
70
72
|
extension CALayer {
|
|
71
73
|
/// Adds the given animation to this layer, timed with the given timing configuration
|
|
74
|
+
/// - The given animation should start at the beginning of the animation and
|
|
75
|
+
/// last the entire duration of the animation. It will be trimmed and retimed
|
|
76
|
+
/// to match the current playback state / looping configuration of the animation view.
|
|
72
77
|
@nonobjc
|
|
73
78
|
func add(_ animation: CAPropertyAnimation, timedWith context: LayerAnimationContext) {
|
|
74
79
|
add(animation.timed(with: context, for: self), forKey: animation.keyPath)
|
|
@@ -28,7 +28,8 @@ extension CALayer {
|
|
|
28
28
|
value: keyframeValueMapping,
|
|
29
29
|
context: context)
|
|
30
30
|
{
|
|
31
|
-
|
|
31
|
+
let timedAnimation = defaultAnimation.timed(with: context, for: self)
|
|
32
|
+
add(timedAnimation, forKey: property.caLayerKeypath)
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -44,7 +45,7 @@ extension CALayer {
|
|
|
44
45
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
45
46
|
context: LayerAnimationContext)
|
|
46
47
|
throws
|
|
47
|
-
->
|
|
48
|
+
-> CAAnimation?
|
|
48
49
|
{
|
|
49
50
|
guard !keyframes.isEmpty else { return nil }
|
|
50
51
|
|
|
@@ -52,39 +53,31 @@ extension CALayer {
|
|
|
52
53
|
// by applying that value directly to the layer instead of creating
|
|
53
54
|
// a relatively expensive `CAKeyframeAnimation`.
|
|
54
55
|
if keyframes.count == 1 {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return nil
|
|
61
|
-
}
|
|
56
|
+
return singleKeyframeAnimation(
|
|
57
|
+
for: property,
|
|
58
|
+
keyframeValue: try keyframeValueMapping(keyframes[0].value),
|
|
59
|
+
writeDirectlyToPropertyIfPossible: true)
|
|
60
|
+
}
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if
|
|
67
|
-
let defaultValue = property.defaultValue,
|
|
68
|
-
defaultValue == value(forKey: property.caLayerKeypath) as? ValueRepresentation
|
|
69
|
-
{
|
|
70
|
-
setValue(keyframeValue, forKeyPath: property.caLayerKeypath)
|
|
71
|
-
return nil
|
|
72
|
-
}
|
|
62
|
+
// Split the keyframes into segments with the same `CAAnimationCalculationMode` value
|
|
63
|
+
// - Each of these segments will become their own `CAKeyframeAnimation`
|
|
64
|
+
let animationSegments = keyframes.segmentsSplitByCalculationMode()
|
|
73
65
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
66
|
+
// If we only have a single segment, we can just create a single `CAKeyframeAnimation`
|
|
67
|
+
// instead of wrapping it in a `CAAnimationGroup` -- this reduces allocation overhead a bit.
|
|
68
|
+
if animationSegments.count == 1 {
|
|
69
|
+
return try keyframeAnimation(
|
|
70
|
+
for: property,
|
|
71
|
+
keyframes: animationSegments[0],
|
|
72
|
+
value: keyframeValueMapping,
|
|
73
|
+
context: context)
|
|
74
|
+
} else {
|
|
75
|
+
return try animationGroup(
|
|
76
|
+
for: property,
|
|
77
|
+
animationSegments: animationSegments,
|
|
78
|
+
value: keyframeValueMapping,
|
|
79
|
+
context: context)
|
|
81
80
|
}
|
|
82
|
-
|
|
83
|
-
return try keyframeAnimation(
|
|
84
|
-
for: property,
|
|
85
|
-
keyframes: keyframes,
|
|
86
|
-
value: keyframeValueMapping,
|
|
87
|
-
context: context)
|
|
88
81
|
}
|
|
89
82
|
|
|
90
83
|
/// A `CAAnimation` that applies the custom value from the `AnyValueProvider`
|
|
@@ -106,32 +99,142 @@ extension CALayer {
|
|
|
106
99
|
else { return nil }
|
|
107
100
|
|
|
108
101
|
// Since custom animations are overriding an existing animation,
|
|
109
|
-
// we always have to create a
|
|
110
|
-
//
|
|
102
|
+
// we always have to create a CAAnimation and can't write directly
|
|
103
|
+
// to the layer property
|
|
104
|
+
if
|
|
105
|
+
customKeyframes.keyframes.count == 1,
|
|
106
|
+
let singleKeyframeAnimation = singleKeyframeAnimation(
|
|
107
|
+
for: property,
|
|
108
|
+
keyframeValue: customKeyframes.keyframes[0].value,
|
|
109
|
+
writeDirectlyToPropertyIfPossible: false)
|
|
110
|
+
{
|
|
111
|
+
return singleKeyframeAnimation
|
|
112
|
+
}
|
|
113
|
+
|
|
111
114
|
return try keyframeAnimation(
|
|
112
115
|
for: property,
|
|
113
|
-
keyframes: customKeyframes.keyframes,
|
|
116
|
+
keyframes: Array(customKeyframes.keyframes),
|
|
114
117
|
value: { $0 },
|
|
115
118
|
context: context)
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
/// Creates a
|
|
121
|
+
/// Creates an animation that applies a single keyframe to this layer property
|
|
122
|
+
/// - In many cases this animation can be omitted entirely, and the underlying
|
|
123
|
+
/// property can be set directly. In that case, no animation will be created.
|
|
124
|
+
private func singleKeyframeAnimation<ValueRepresentation>(
|
|
125
|
+
for property: LayerProperty<ValueRepresentation>,
|
|
126
|
+
keyframeValue: ValueRepresentation,
|
|
127
|
+
writeDirectlyToPropertyIfPossible: Bool)
|
|
128
|
+
-> CABasicAnimation?
|
|
129
|
+
{
|
|
130
|
+
if writeDirectlyToPropertyIfPossible {
|
|
131
|
+
// If the keyframe value is the same as the layer's default value for this property,
|
|
132
|
+
// then we can just ignore this set of keyframes.
|
|
133
|
+
if keyframeValue == property.defaultValue {
|
|
134
|
+
return nil
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// If the property on the CALayer being animated hasn't been modified from the default yet,
|
|
138
|
+
// then we can apply the keyframe value directly to the layer using KVC instead
|
|
139
|
+
// of creating a `CAAnimation`.
|
|
140
|
+
if
|
|
141
|
+
let defaultValue = property.defaultValue,
|
|
142
|
+
defaultValue == value(forKey: property.caLayerKeypath) as? ValueRepresentation
|
|
143
|
+
{
|
|
144
|
+
setValue(keyframeValue, forKeyPath: property.caLayerKeypath)
|
|
145
|
+
return nil
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Otherwise, we still need to create a `CAAnimation`, but we can
|
|
150
|
+
// create a simple `CABasicAnimation` that is still less expensive
|
|
151
|
+
// than computing a `CAKeyframeAnimation`.
|
|
152
|
+
let animation = CABasicAnimation(keyPath: property.caLayerKeypath)
|
|
153
|
+
animation.fromValue = keyframeValue
|
|
154
|
+
animation.toValue = keyframeValue
|
|
155
|
+
return animation
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Creates a `CAAnimationGroup` that wraps a `CAKeyframeAnimation` for each
|
|
159
|
+
/// of the given `animationSegments`
|
|
160
|
+
private func animationGroup<KeyframeValue, ValueRepresentation>(
|
|
161
|
+
for property: LayerProperty<ValueRepresentation>,
|
|
162
|
+
animationSegments: [[Keyframe<KeyframeValue>]],
|
|
163
|
+
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
164
|
+
context: LayerAnimationContext)
|
|
165
|
+
throws
|
|
166
|
+
-> CAAnimationGroup
|
|
167
|
+
{
|
|
168
|
+
// Build the `CAKeyframeAnimation` for each segment of keyframes
|
|
169
|
+
// with the same `CAAnimationCalculationMode`.
|
|
170
|
+
// - Here we have a non-zero number of animation segments,
|
|
171
|
+
// all of which have a non-zero number of keyframes.
|
|
172
|
+
let segmentAnimations: [CAKeyframeAnimation] = try animationSegments.indices.map { index in
|
|
173
|
+
let animationSegment = animationSegments[index]
|
|
174
|
+
var segmentStartTime = context.time(for: animationSegment.first!.time)
|
|
175
|
+
var segmentEndTime = context.time(for: animationSegment.last!.time)
|
|
176
|
+
|
|
177
|
+
// Every portion of the animation timeline has to be covered by a `CAKeyframeAnimation`,
|
|
178
|
+
// so if this is the first or last segment then the start/end time should be exactly
|
|
179
|
+
// the start/end time of the animation itself.
|
|
180
|
+
let isFirstSegment = (index == animationSegments.indices.first!)
|
|
181
|
+
let isLastSegment = (index == animationSegments.indices.last!)
|
|
182
|
+
|
|
183
|
+
if isFirstSegment {
|
|
184
|
+
segmentStartTime = context.time(for: context.animation.startFrame)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if isLastSegment {
|
|
188
|
+
segmentEndTime = context.time(for: context.animation.endFrame)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let segmentDuration = segmentEndTime - segmentStartTime
|
|
192
|
+
|
|
193
|
+
// We're building `CAKeyframeAnimation`s, so the `keyTimes` are expressed
|
|
194
|
+
// relative to 0 (`segmentStartTime`) and 1 (`segmentEndTime`). This is different
|
|
195
|
+
// from the default behavior of the `keyframeAnimation` method, where times
|
|
196
|
+
// are expressed relative to the entire animation duration.
|
|
197
|
+
let customKeyTimes = animationSegment.map { keyframeModel -> NSNumber in
|
|
198
|
+
let keyframeTime = context.time(for: keyframeModel.time)
|
|
199
|
+
let segmentProgressTime = ((keyframeTime - segmentStartTime) / segmentDuration)
|
|
200
|
+
return segmentProgressTime as NSNumber
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let animation = try keyframeAnimation(
|
|
204
|
+
for: property,
|
|
205
|
+
keyframes: animationSegment,
|
|
206
|
+
value: keyframeValueMapping,
|
|
207
|
+
customKeyTimes: customKeyTimes,
|
|
208
|
+
context: context)
|
|
209
|
+
|
|
210
|
+
animation.duration = segmentDuration
|
|
211
|
+
animation.beginTime = segmentStartTime
|
|
212
|
+
return animation
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let fullAnimation = CAAnimationGroup()
|
|
216
|
+
fullAnimation.animations = segmentAnimations
|
|
217
|
+
return fullAnimation
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/// Creates and validates a `CAKeyframeAnimation` for the given keyframes
|
|
119
221
|
private func keyframeAnimation<KeyframeValue, ValueRepresentation>(
|
|
120
222
|
for property: LayerProperty<ValueRepresentation>,
|
|
121
|
-
keyframes:
|
|
223
|
+
keyframes: [Keyframe<KeyframeValue>],
|
|
122
224
|
value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation,
|
|
225
|
+
customKeyTimes: [NSNumber]? = nil,
|
|
123
226
|
context: LayerAnimationContext)
|
|
124
227
|
throws
|
|
125
228
|
-> CAKeyframeAnimation
|
|
126
229
|
{
|
|
127
230
|
// Convert the list of `Keyframe<T>` into
|
|
128
231
|
// the representation used by `CAKeyframeAnimation`
|
|
129
|
-
var keyTimes = keyframes.map { keyframeModel -> NSNumber in
|
|
232
|
+
var keyTimes = customKeyTimes ?? keyframes.map { keyframeModel -> NSNumber in
|
|
130
233
|
NSNumber(value: Float(context.progressTime(for: keyframeModel.time)))
|
|
131
234
|
}
|
|
132
235
|
|
|
133
236
|
var timingFunctions = self.timingFunctions(for: keyframes)
|
|
134
|
-
let calculationMode =
|
|
237
|
+
let calculationMode = self.calculationMode(for: keyframes)
|
|
135
238
|
|
|
136
239
|
let animation = CAKeyframeAnimation(keyPath: property.caLayerKeypath)
|
|
137
240
|
|
|
@@ -173,37 +276,22 @@ extension CALayer {
|
|
|
173
276
|
/// The `CAAnimationCalculationMode` that should be used for a `CAKeyframeAnimation`
|
|
174
277
|
/// animating the given keyframes
|
|
175
278
|
private func calculationMode<KeyframeValue>(
|
|
176
|
-
for keyframes:
|
|
177
|
-
context: LayerAnimationContext)
|
|
178
|
-
throws
|
|
279
|
+
for keyframes: [Keyframe<KeyframeValue>])
|
|
179
280
|
-> CAAnimationCalculationMode
|
|
180
281
|
{
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// - We should be able to support this in the future by creating multiple
|
|
189
|
-
// `CAKeyframeAnimation`s with different `calculationMode`s and
|
|
190
|
-
// playing them sequentially.
|
|
191
|
-
//
|
|
192
|
-
let intermediateKeyframes = keyframes.dropFirst().dropLast()
|
|
193
|
-
if intermediateKeyframes.contains(where: \.isHold) {
|
|
194
|
-
if intermediateKeyframes.allSatisfy(\.isHold) {
|
|
195
|
-
return .discrete
|
|
196
|
-
} else {
|
|
197
|
-
try context.logCompatibilityIssue("Mixed `isHold` / `!isHold` keyframes are currently unsupported")
|
|
198
|
-
}
|
|
282
|
+
// At this point we expect all of the animations to have been split in
|
|
283
|
+
// to segments based on the `CAAnimationCalculationMode`, so we can just
|
|
284
|
+
// check the first keyframe.
|
|
285
|
+
if keyframes[0].isHold {
|
|
286
|
+
return .discrete
|
|
287
|
+
} else {
|
|
288
|
+
return .linear
|
|
199
289
|
}
|
|
200
|
-
|
|
201
|
-
return .linear
|
|
202
290
|
}
|
|
203
291
|
|
|
204
292
|
/// `timingFunctions` to apply to a `CAKeyframeAnimation` animating the given keyframes
|
|
205
293
|
private func timingFunctions<KeyframeValue>(
|
|
206
|
-
for keyframes:
|
|
294
|
+
for keyframes: [Keyframe<KeyframeValue>])
|
|
207
295
|
-> [CAMediaTimingFunction]
|
|
208
296
|
{
|
|
209
297
|
// Compute the timing function between each keyframe and the subsequent keyframe
|
|
@@ -231,9 +319,10 @@ extension CALayer {
|
|
|
231
319
|
/// Creates a `CGPath` for the given `position` keyframes,
|
|
232
320
|
/// which accounts for `spatialInTangent`s and `spatialOutTangents`
|
|
233
321
|
private func path<KeyframeValue>(
|
|
234
|
-
keyframes positionKeyframes:
|
|
322
|
+
keyframes positionKeyframes: [Keyframe<KeyframeValue>],
|
|
235
323
|
value keyframeValueMapping: (KeyframeValue) throws -> CGPoint) rethrows
|
|
236
|
-
-> CGPath
|
|
324
|
+
-> CGPath
|
|
325
|
+
{
|
|
237
326
|
let path = CGMutablePath()
|
|
238
327
|
|
|
239
328
|
for (index, keyframe) in positionKeyframes.enumerated() {
|
|
@@ -247,8 +336,7 @@ extension CALayer {
|
|
|
247
336
|
if
|
|
248
337
|
let controlPoint1 = keyframe.spatialOutTangent?.pointValue,
|
|
249
338
|
let controlPoint2 = nextKeyframe.spatialInTangent?.pointValue,
|
|
250
|
-
controlPoint1
|
|
251
|
-
controlPoint2 != .zero
|
|
339
|
+
!(controlPoint1 == .zero && controlPoint2 == .zero)
|
|
252
340
|
{
|
|
253
341
|
path.addCurve(
|
|
254
342
|
to: try keyframeValueMapping(nextKeyframe.value),
|
|
@@ -320,3 +408,40 @@ extension CALayer {
|
|
|
320
408
|
}
|
|
321
409
|
|
|
322
410
|
}
|
|
411
|
+
|
|
412
|
+
extension RandomAccessCollection {
|
|
413
|
+
/// Splits this array of `Keyframe`s into segments with the same `CAAnimationCalculationMode`
|
|
414
|
+
/// - Keyframes with `isHold=true` become `discrete`, and keyframes with `isHold=false`
|
|
415
|
+
/// become linear. Each `CAKeyframeAnimation` can only be one or the other, so each
|
|
416
|
+
/// `calculationModeSegment` becomes its own `CAKeyframeAnimation`.
|
|
417
|
+
func segmentsSplitByCalculationMode<KeyframeValue>() -> [[Element]]
|
|
418
|
+
where Element == Keyframe<KeyframeValue>, Index == Int
|
|
419
|
+
{
|
|
420
|
+
var segments: [[Element]] = []
|
|
421
|
+
var currentSegment: [Element] = []
|
|
422
|
+
|
|
423
|
+
for keyframe in self {
|
|
424
|
+
guard let mostRecentKeyframe = currentSegment.last else {
|
|
425
|
+
currentSegment.append(keyframe)
|
|
426
|
+
continue
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// When `isHold` changes between any two given keyframes, we have to create a new segment
|
|
430
|
+
if keyframe.isHold != mostRecentKeyframe.isHold {
|
|
431
|
+
// Add this keyframe to both the existing segment that is ending,
|
|
432
|
+
// so we know how long that segment is, and the new segment,
|
|
433
|
+
// so we know when that segment starts.
|
|
434
|
+
currentSegment.append(keyframe)
|
|
435
|
+
segments.append(currentSegment)
|
|
436
|
+
currentSegment = [keyframe]
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
else {
|
|
440
|
+
currentSegment.append(keyframe)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
segments.append(currentSegment)
|
|
445
|
+
return segments
|
|
446
|
+
}
|
|
447
|
+
}
|
|
@@ -51,3 +51,31 @@ final class CombinedShapeItem: ShapeItem {
|
|
|
51
51
|
let shapes: KeyframeGroup<[BezierPath]>
|
|
52
52
|
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
extension CombinedShapeItem {
|
|
56
|
+
/// Manually combines the given shape keyframes by manually interpolating at each frame
|
|
57
|
+
static func manuallyInterpolating(
|
|
58
|
+
shapes: [KeyframeGroup<BezierPath>],
|
|
59
|
+
name: String,
|
|
60
|
+
context: LayerContext)
|
|
61
|
+
-> CombinedShapeItem
|
|
62
|
+
{
|
|
63
|
+
let animationTimeRange = Int(context.animation.startFrame)...Int(context.animation.endFrame)
|
|
64
|
+
|
|
65
|
+
let interpolators = shapes.map { shape in
|
|
66
|
+
KeyframeInterpolator(keyframes: shape.keyframes)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let interpolatedKeyframes = animationTimeRange.map { frame in
|
|
70
|
+
Keyframe(
|
|
71
|
+
value: interpolators.compactMap { interpolator in
|
|
72
|
+
interpolator.value(frame: AnimationFrameTime(frame)) as? BezierPath
|
|
73
|
+
},
|
|
74
|
+
time: AnimationFrameTime(frame))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return CombinedShapeItem(
|
|
78
|
+
shapes: KeyframeGroup(keyframes: ContiguousArray(interpolatedKeyframes)),
|
|
79
|
+
name: name)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -14,11 +14,11 @@ extension CAShapeLayer {
|
|
|
14
14
|
{
|
|
15
15
|
try addAnimation(
|
|
16
16
|
for: .path,
|
|
17
|
-
keyframes: ellipse.
|
|
18
|
-
value: {
|
|
17
|
+
keyframes: ellipse.combinedKeyframes(context: context).keyframes,
|
|
18
|
+
value: { keyframe in
|
|
19
19
|
BezierPath.ellipse(
|
|
20
|
-
size:
|
|
21
|
-
center:
|
|
20
|
+
size: keyframe.size.sizeValue,
|
|
21
|
+
center: keyframe.position.pointValue,
|
|
22
22
|
direction: ellipse.direction)
|
|
23
23
|
.cgPath()
|
|
24
24
|
.duplicated(times: pathMultiplier)
|
|
@@ -26,3 +26,30 @@ extension CAShapeLayer {
|
|
|
26
26
|
context: context)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
extension Ellipse {
|
|
31
|
+
/// Data that represents how to render an ellipse at a specific point in time
|
|
32
|
+
struct Keyframe {
|
|
33
|
+
let size: Vector3D
|
|
34
|
+
let position: Vector3D
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Ellipse
|
|
38
|
+
func combinedKeyframes(context: LayerAnimationContext) throws-> KeyframeGroup<Ellipse.Keyframe> {
|
|
39
|
+
let combinedKeyframes = Keyframes.combinedIfPossible(
|
|
40
|
+
size, position,
|
|
41
|
+
makeCombinedResult: Ellipse.Keyframe.init)
|
|
42
|
+
|
|
43
|
+
if let combinedKeyframes = combinedKeyframes {
|
|
44
|
+
return combinedKeyframes
|
|
45
|
+
} else {
|
|
46
|
+
// If we weren't able to combine all of the keyframes, we have to take the timing values
|
|
47
|
+
// from one property and use a fixed value for the other properties.
|
|
48
|
+
return try size.map { sizeValue in
|
|
49
|
+
Keyframe(
|
|
50
|
+
size: sizeValue,
|
|
51
|
+
position: try position.exactlyOneKeyframe(context: context, description: "ellipse position"))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|