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.
Files changed (394) hide show
  1. package/.github/workflows/main.yml +10 -7
  2. package/.github/workflows/stale_issues.yml +17 -0
  3. package/.swiftpm/xcode/package.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  4. package/Lottie.xcodeproj/project.pbxproj +33 -21
  5. package/Lottie.xcodeproj/xcshareddata/xcschemes/Lottie (macOS).xcscheme +2 -2
  6. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  7. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +5 -6
  8. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +114 -1
  9. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +30 -0
  10. package/Package.swift +1 -1
  11. package/README.md +5 -6
  12. package/Rakefile +52 -17
  13. package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +7 -2
  14. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +192 -67
  15. package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +28 -0
  16. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +31 -4
  17. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +98 -43
  18. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +19 -19
  19. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +34 -7
  20. package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +25 -14
  21. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +61 -32
  22. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +6 -2
  23. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +29 -11
  24. package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +2 -2
  25. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +116 -23
  26. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +9 -0
  27. package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +2 -1
  28. package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +48 -12
  29. package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +10 -3
  30. package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +5 -0
  31. package/Sources/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +1 -1
  32. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -2
  33. package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +85 -0
  34. package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +94 -38
  35. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +131 -46
  36. package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +16 -2
  37. package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +1 -1
  38. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +0 -2
  39. package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +2 -2
  40. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +1 -2
  41. package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +30 -1
  42. package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -0
  43. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +0 -1
  44. package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +5 -2
  45. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +4 -7
  46. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +5 -0
  47. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +1 -2
  48. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +1 -1
  49. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +1 -1
  50. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +1 -1
  51. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +3 -3
  52. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +3 -0
  53. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
  54. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +28 -1
  55. package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +1 -1
  56. package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +0 -1
  57. package/Sources/Private/Model/Animation.swift +4 -4
  58. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +25 -0
  59. package/Sources/Private/Model/ShapeItems/Ellipse.swift +0 -1
  60. package/Sources/Private/Model/ShapeItems/Fill.swift +1 -1
  61. package/Sources/Private/Model/ShapeItems/GradientFill.swift +14 -1
  62. package/Sources/Private/Model/ShapeItems/GradientStroke.swift +0 -1
  63. package/Sources/Private/Model/ShapeItems/Group.swift +6 -1
  64. package/Sources/Private/Model/ShapeItems/Merge.swift +0 -1
  65. package/Sources/Private/Model/ShapeItems/Rectangle.swift +0 -1
  66. package/Sources/Private/Model/ShapeItems/Repeater.swift +0 -1
  67. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +0 -1
  68. package/Sources/Private/Model/ShapeItems/Star.swift +0 -1
  69. package/Sources/Private/Model/ShapeItems/Stroke.swift +0 -1
  70. package/Sources/Private/Model/ShapeItems/Trim.swift +0 -1
  71. package/Sources/Private/Model/Text/TextAnimator.swift +0 -1
  72. package/Sources/Private/Utility/Debugging/LayerDebugging.swift +1 -2
  73. package/Sources/Private/Utility/Extensions/MathKit.swift +1 -2
  74. package/Sources/Private/Utility/Extensions/StringExtensions.swift +0 -1
  75. package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +0 -1
  76. package/Sources/Private/{MainThread/NodeRenderSystem/NodeProperties/ValueProviders → Utility/Interpolatable}/KeyframeInterpolator.swift +1 -4
  77. package/Sources/Private/Utility/Primitives/BezierPath.swift +1 -2
  78. package/Sources/Private/Utility/Primitives/CurveVertex.swift +2 -4
  79. package/Sources/Public/Animation/AnimationPublic.swift +2 -4
  80. package/Sources/Public/Animation/AnimationView.swift +29 -7
  81. package/Sources/Public/Animation/AnimationViewInitializers.swift +13 -11
  82. package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +0 -2
  83. package/Sources/Public/FontProvider/AnimationFontProvider.swift +1 -1
  84. package/Sources/Public/Logging/LottieLogger.swift +15 -2
  85. package/Sources/Public/TextProvider/AnimationTextProvider.swift +1 -1
  86. package/Sources/Public/iOS/AnimatedButton.swift +10 -4
  87. package/Sources/Public/iOS/AnimatedControl.swift +3 -5
  88. package/Sources/Public/iOS/AnimatedSwitch.swift +9 -6
  89. package/Sources/Public/iOS/BundleImageProvider.swift +2 -3
  90. package/Sources/Public/iOS/FilepathImageProvider.swift +1 -2
  91. package/Sources/Public/macOS/BundleImageProvider.macOS.swift +1 -2
  92. package/Sources/Public/macOS/FilepathImageProvider.macOS.swift +1 -3
  93. package/Tests/AnimationKeypathTests.swift +10 -1
  94. package/Tests/AutomaticEngineTests.swift +1 -0
  95. package/Tests/ParsingTests.swift +2 -1
  96. package/Tests/PerformanceTests.swift +28 -29
  97. package/Tests/SnapshotConfiguration.swift +19 -0
  98. package/Tests/SnapshotTests.swift +4 -0
  99. package/Tests/Utils/HardcodedTextProvider.swift +27 -0
  100. package/lottie-ios.podspec +2 -2
  101. package/package.json +1 -1
  102. package/script/test-carthage/CarthageTest/AppDelegate.swift +6 -7
  103. package/script/test-carthage/CarthageTest/ViewController.swift +1 -1
  104. package/script/test-carthage/CarthageTest-macOS/AppDelegate.swift +7 -0
  105. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  106. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
  107. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/Contents.json +6 -0
  108. package/script/test-carthage/CarthageTest-macOS/Base.lproj/Main.storyboard +717 -0
  109. package/script/test-carthage/CarthageTest-macOS/CarthageTest_macOS.entitlements +10 -0
  110. package/script/test-carthage/CarthageTest-macOS/ViewController.swift +15 -0
  111. package/script/test-carthage/CarthageTest.xcodeproj/project.pbxproj +159 -5
  112. package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  113. package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  114. package/Lottie.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +0 -23
  115. package/Mintfile +0 -3
  116. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-7Vi1RszY1XYnR2CCkEwIpKG8NwwA9zsZEz_WD7Dv6kKh4RC7N7ob8NIRVHGUJKp7eXxlpeI_gzD87Pcs_2u0g== +0 -0
  117. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-SKV2drO-SFlrlh-wrzECDMkUSr-aF1lV9h-5onOy94zSTsD-oI45s0-KpOK45L-kq3hRY7v9vm-xmh00_eheg== +0 -0
  118. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~-_CU_vuaiFfObSeDFfmp7GuB20ThMSAL-P_RUMowiQLbdu-y0bU9upIm3q8g6XmXUG5hP6J1az0Ma5Hi_rhhRg== +0 -0
  119. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~03aPYP6VHJjZj5DlphGarj0xdw43qu09Onx5SReZoPvg9zh5uL212E-KWfGct9jf6JG0JFV2tdbBi7X_8bH9aw== +0 -0
  120. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~1Z82GPBBPc1VLvn4O7V5glb6lgyXteNlDREUzV_TPymM4ra4UkBMklzV90lEqoYRCDuRVzaQHaDYbmYp3-8CFw== +0 -0
  121. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~1mFDCboXpUu9pSHAiVGr1O_QgqEEtvJp_LUhickxLZo0Z5pj3fvadn1l2MzEOd4bFsVBZifUvcyPa7dzlMWF-A== +0 -0
  122. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~2_L9PUjv2JDKu1n8bDLb4XLB-yex6ZVjDDMwfuKAr7teDw-SKgLgkW6H-m_gjWChIVdB4vW6yvHP7XJxvXtRNA== +0 -0
  123. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -1
  124. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4krT4ZMzDOu34msFUq0Xod142kw4pAeSWX4JSxlsjOI0Wanu3343qeespgFi61MTWq1DdH9XXspVKqGlGm_fyw== +0 -0
  125. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~5_aJsdP-e3dRTAUnH-y1U2plaCuUi1vyHriaZuNK0xFe8wGl9Qft6uLCX2Qt6CRBKJQluEe9o0uRWw1eb42FHQ== +0 -0
  126. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~8b0bSqV7eND54zvHvu1v2Htpm7yn-BOEFw5d3mITJrXWNykJ5BTR9WbrD80JEctNcT-rDqO2xfrQk1tFWeY6Sw== +0 -0
  127. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~9u8KAGpgtSm-mQ12Py8RZUbYbDlBhM3w1I2MQO53K2CSn6IePp7g65DBcdXTYMfG1bgoJ-6x30fjnGe-2UYsDQ== +0 -0
  128. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Bw7uMs4wqB9ahfEqGii2FkQ9pvZmG6HGe2hmbAT2wyM5hpn8Xh5dELysMcEz6hEsqmn6HdRdLOLZhC_fNaXzgA== +0 -0
  129. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~BwUq2xXQYuE8ya6HT6lfNsdtEjz5AKGf8GvLY6VBxQyIY1vgj_Gov-3NeM69OS66BQRDK0PG9H4Oyg0R48E4vg== +0 -0
  130. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~EkDVUR6dcnzxV_lYjkrJ5QGMVTCvb_upAoBF6DBu61sQkGvZN3fSRTsJ1XfJIZO-JUzdNoVA3D_CcvokL0gnQg== +0 -0
  131. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~FUkcLSJ8RAuPenM4HFG1R-sN5-cDBGcTxgR2jaVCna7xV0ZTyBHriB1Nn59mariNlJDiCoBtMUQEmauGxWtfBA== +0 -0
  132. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~FqsuZe4RVLOOVUYLTL-GTIohZ8TdSfxx7m2KJtLYFPGOdE4XorTX7Oc7kXbhghPRppXT3jW-slI37M34YNEvLQ== +0 -0
  133. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~G4F_NtyTj3i46fmKm0NorHAeq8tYWWYf6uv5yC1DwzdpWVoYbOPufmFNvdEbxZt4AMdV0gKx3HI46EAXNOQVFg== +0 -0
  134. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~GxetzGUNDgaBBXcTmLK6p9JBDX3I3QPshshbui1IaEWvJbQko-E36tCKwaJYHbleAWz9FqkAM_Tqx3YOmSVkVg== +0 -0
  135. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~H1Wjd5kKWDW4t3SDodxiHV72V8WT0xwPubw5cJTNLkPRLgaILFPh-dpy8EOUNgy1KzrDujFsm9EcTsbuqtMPLA== +0 -0
  136. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~JpI5MH4zCgebUHFpXVn4zjtsGtMNnO7BQZWfNARAB5UWa9gqz6YXHR3uLCJ_AvJ3lh53BUVkavsx9TY2FMmxbA== +0 -0
  137. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~JujNYkJtcux0Ni4QnR64zu4Wz_zYjyKvYaYZm5ypxTLPSzF3_jNE_NO4sdbDamF8wEqWoky1uf4ZE0JT3L607A== +0 -0
  138. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~KJSEA6DKnb2_FRPSqKZGh41eo-C8x448J9kEBrH012bUrZfOSDvrgmIrU0Vz7Ri3gaS9aKKmSaVMvXsHSlTJVA== +0 -0
  139. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~MStOwu3jBlJtcRnxrseVOuhI4kCj--ggFPG7sqrq5w1hjrI3bVyD-bm1Jwyx0noY3wT1rHDEvaGWnV2qsGjGwg== +0 -0
  140. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~McsJ8kFVf3IjhgXIRdw8Xx-EXgbV071bmlj2BBnk52xrWl3sEeiIyxwUsF7mIWvMRWfcFfu4VGHYyqfk2BeHXw== +0 -0
  141. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~NHt9fVe4kDdbxnglKcEwXaRK-WsYEOaD23Kbl8SJPRMYHr_Z6SJd_HmG3BROHHR_M6TgSmucONpDJdTj5tjuFw== +0 -0
  142. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Nfo2iwCPcfAcOBIVyoUAK0-PIfr5qYxIKZt-uaSaTBdrTNxAuJ1ItmeDPZ3VdJJmxD_c22No7x482bdd3_yYtw== +0 -0
  143. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~S2Qlu11xBhEd5aGSzWsnw1TR8u8PiOF93GO0j5bfNoAFCVzxKOwhRFoIXba2EpQnLQqFdIKyhWN3l70A4GPHmg== +0 -0
  144. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~W7a7M37RO9jgck2zeR0471Pm7e8K0Kqj5tXEouDjvqKZXSrWxMaWD28oqkKKYAiU4608R4S9mM11KyphljdMSw== +0 -0
  145. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~XUo1oyPCrlL7CA74wG-OzQ06VOWJYWvHGFHU7keZN1SKaIXjHX5qi_kBzjG_rBCi89-S8GVmCy7S3PHSjG8SbQ== +0 -0
  146. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Xh0VmDvFNMELHu08-vrs54pegVyUwwDRxx_nXkwyD0NjnYozyqcGAKAr_QWHmw6F8XyuWg51M9KGpJJIFzzGuw== +0 -0
  147. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Xve-wMBp_lxVUgD9qH5GwieGP9cAWtm0xULZvdGjBRUMvaevmpCB5gnbMBuIXAO6a1c9v6WUq0jNVX7ut5HvOw== +0 -0
  148. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ZU1XkZFgnEE22CXEF-pOlcj5f10x-KM1Vw9d4IOLu-NiTZcz7koYPixhdrB1PJr8J-h9NpJmfqEastfxamA1jQ== +0 -0
  149. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~_YkNYEHTsbbtFILJpzH3HenH0t4ShI25dIMdve541CF5bl-jPF3X3F7tq-t5dvP0TEkATsOJdLQdBp1xv4Q-ag== +0 -0
  150. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~boy6mpn2jkwm60jjgQ0TG25UqRdN46LzmgTVCrpy6nBOgkLCGkGHcbceiwjU1itS_vj3-iQX0ZnrWOQrPyfHNA== +0 -0
  151. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~bwzpVZ9hAqGDHhXs2FRA82dfGfLmc7-m0uQhZDDfHHO7hQ17M_Np341BZX4WDLhYYS4cdUgaDodlNpdfpG3nXw== +0 -0
  152. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cBxe-9PpAGFdAsYkmdN3lJVqEliLcRYlyoAov0aPZfJGwUr_cOm3XpjO7nmf_2eLf8UAx-rycjnJzw07xLrNCA== +0 -1
  153. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~dirWk6W4Pav1oyciuflfJlRu0iuxbYOmrpQapOJ0mV9C1SQ-jvDRv_7h753Cy18-SwULARUdWsyUy3yNNvxF7w== +0 -0
  154. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ebwZVjSEHroc9jtIm4jd_h_YAqEBcOkAZ4HPNJT8pLCldjRcTq-obQLakxXOhfuoOBlYBoZLuO-Y0lskeZRYKw== +0 -0
  155. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~gfcRcmRIr0h09d0jiZsA7nUeQv2XtapxuYEXZy1Z9um0tTJQvz-O5ef5f7zhLenLvjnDtDtlY_aY4Hvpce6e1Q== +0 -0
  156. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~hgOgiVCyv2R0W-f0qKw5xYPeUwj8_ccCM9vKH_7vAQcCO9t8BwR1APGRBv20AONmp-PYMXmtgsBlQkNBRBpdQA== +0 -0
  157. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~hrhCl-YRAAr8ByNB_LCgEBsVNHMp92gTIUknetpUHMjcXl4Hpn_uY-h6C45oga0ZALnfGCo6iKTmiPLa4Qvnpg== +0 -0
  158. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~n2yoR7JsyL4DSUwmjnpE4Iq9Qi_eeZrmpPU8cdehDFKfESK7nwxXxfrSMQbk0BQ2lgGPadoRcd1-qr1xVz97jA== +0 -0
  159. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~nMCcZm8WvPogyO_nuJ926Q3Q2dqVMN2LdjEL1Kq2wJ_RG-rH-e_6v41l1xZbCsQTa3XykQdEiXNc0HtAvT6IRA== +0 -0
  160. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~oc3C7xkUt-OWDL6rrsxs-seS4Fu1bqBWAAXCHalgShaGg9MUrOiRbHT2DcAnhyQFKx6x5FRbvjmYoQWrQiXJZA== +0 -0
  161. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~p-ihj7SEgkDXpMu9hvKE_wiX9cvtwyXrdIn964BfedXHKGpC6o7mMPxEyC0kRPVi_EZs_MRV5bAPEpl5h5we0g== +0 -0
  162. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~qlhO_D9oE8uSKH-mZqyRF9pp4Zv1Tv0dIYcqrH4hb1VWlIxcdxmg2j0M8496cQeFXC5bn_JMXdBlD-d6cnFF8w== +0 -0
  163. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~tjpiyIxJR_boTdUNrtFDuKIZoY84fI4lA1oMJbq9e2ZmYKIK5FeRN2O8cV_yMOYJGr4lbv03kTmT70mCjUc2_Q== +0 -0
  164. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~wULeoj18eEKJWAKx1uFQVwS48cUGFcYPRJQj1Ro5XNJsWCwppGSCdIPhwifD6Z2f_j3zfI2SmC2Gg81sBXXW7g== +0 -0
  165. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~zrEihMys4NVV5rx6FmuzEGO2TjloI3OiC7yzIhvqYoRo43ibb2F-Km6Jf4NX-ac62pOLBYZRcjQTvYMpn75_oA== +0 -0
  166. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-7Vi1RszY1XYnR2CCkEwIpKG8NwwA9zsZEz_WD7Dv6kKh4RC7N7ob8NIRVHGUJKp7eXxlpeI_gzD87Pcs_2u0g== +0 -0
  167. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-SKV2drO-SFlrlh-wrzECDMkUSr-aF1lV9h-5onOy94zSTsD-oI45s0-KpOK45L-kq3hRY7v9vm-xmh00_eheg== +0 -0
  168. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~-_CU_vuaiFfObSeDFfmp7GuB20ThMSAL-P_RUMowiQLbdu-y0bU9upIm3q8g6XmXUG5hP6J1az0Ma5Hi_rhhRg== +0 -0
  169. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~03aPYP6VHJjZj5DlphGarj0xdw43qu09Onx5SReZoPvg9zh5uL212E-KWfGct9jf6JG0JFV2tdbBi7X_8bH9aw== +0 -0
  170. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~1Z82GPBBPc1VLvn4O7V5glb6lgyXteNlDREUzV_TPymM4ra4UkBMklzV90lEqoYRCDuRVzaQHaDYbmYp3-8CFw== +0 -0
  171. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~1mFDCboXpUu9pSHAiVGr1O_QgqEEtvJp_LUhickxLZo0Z5pj3fvadn1l2MzEOd4bFsVBZifUvcyPa7dzlMWF-A== +0 -0
  172. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~2_L9PUjv2JDKu1n8bDLb4XLB-yex6ZVjDDMwfuKAr7teDw-SKgLgkW6H-m_gjWChIVdB4vW6yvHP7XJxvXtRNA== +0 -0
  173. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -0
  174. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4krT4ZMzDOu34msFUq0Xod142kw4pAeSWX4JSxlsjOI0Wanu3343qeespgFi61MTWq1DdH9XXspVKqGlGm_fyw== +0 -0
  175. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~5_aJsdP-e3dRTAUnH-y1U2plaCuUi1vyHriaZuNK0xFe8wGl9Qft6uLCX2Qt6CRBKJQluEe9o0uRWw1eb42FHQ== +0 -0
  176. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~8b0bSqV7eND54zvHvu1v2Htpm7yn-BOEFw5d3mITJrXWNykJ5BTR9WbrD80JEctNcT-rDqO2xfrQk1tFWeY6Sw== +0 -0
  177. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~9u8KAGpgtSm-mQ12Py8RZUbYbDlBhM3w1I2MQO53K2CSn6IePp7g65DBcdXTYMfG1bgoJ-6x30fjnGe-2UYsDQ== +0 -0
  178. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Bw7uMs4wqB9ahfEqGii2FkQ9pvZmG6HGe2hmbAT2wyM5hpn8Xh5dELysMcEz6hEsqmn6HdRdLOLZhC_fNaXzgA== +0 -0
  179. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~BwUq2xXQYuE8ya6HT6lfNsdtEjz5AKGf8GvLY6VBxQyIY1vgj_Gov-3NeM69OS66BQRDK0PG9H4Oyg0R48E4vg== +0 -0
  180. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~EkDVUR6dcnzxV_lYjkrJ5QGMVTCvb_upAoBF6DBu61sQkGvZN3fSRTsJ1XfJIZO-JUzdNoVA3D_CcvokL0gnQg== +0 -0
  181. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~FUkcLSJ8RAuPenM4HFG1R-sN5-cDBGcTxgR2jaVCna7xV0ZTyBHriB1Nn59mariNlJDiCoBtMUQEmauGxWtfBA== +0 -0
  182. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~FqsuZe4RVLOOVUYLTL-GTIohZ8TdSfxx7m2KJtLYFPGOdE4XorTX7Oc7kXbhghPRppXT3jW-slI37M34YNEvLQ== +0 -0
  183. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~G4F_NtyTj3i46fmKm0NorHAeq8tYWWYf6uv5yC1DwzdpWVoYbOPufmFNvdEbxZt4AMdV0gKx3HI46EAXNOQVFg== +0 -0
  184. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~GxetzGUNDgaBBXcTmLK6p9JBDX3I3QPshshbui1IaEWvJbQko-E36tCKwaJYHbleAWz9FqkAM_Tqx3YOmSVkVg== +0 -0
  185. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~H1Wjd5kKWDW4t3SDodxiHV72V8WT0xwPubw5cJTNLkPRLgaILFPh-dpy8EOUNgy1KzrDujFsm9EcTsbuqtMPLA== +0 -0
  186. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~JpI5MH4zCgebUHFpXVn4zjtsGtMNnO7BQZWfNARAB5UWa9gqz6YXHR3uLCJ_AvJ3lh53BUVkavsx9TY2FMmxbA== +0 -0
  187. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~JujNYkJtcux0Ni4QnR64zu4Wz_zYjyKvYaYZm5ypxTLPSzF3_jNE_NO4sdbDamF8wEqWoky1uf4ZE0JT3L607A== +0 -0
  188. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~KJSEA6DKnb2_FRPSqKZGh41eo-C8x448J9kEBrH012bUrZfOSDvrgmIrU0Vz7Ri3gaS9aKKmSaVMvXsHSlTJVA== +0 -0
  189. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~MStOwu3jBlJtcRnxrseVOuhI4kCj--ggFPG7sqrq5w1hjrI3bVyD-bm1Jwyx0noY3wT1rHDEvaGWnV2qsGjGwg== +0 -0
  190. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~McsJ8kFVf3IjhgXIRdw8Xx-EXgbV071bmlj2BBnk52xrWl3sEeiIyxwUsF7mIWvMRWfcFfu4VGHYyqfk2BeHXw== +0 -0
  191. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~NHt9fVe4kDdbxnglKcEwXaRK-WsYEOaD23Kbl8SJPRMYHr_Z6SJd_HmG3BROHHR_M6TgSmucONpDJdTj5tjuFw== +0 -0
  192. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Nfo2iwCPcfAcOBIVyoUAK0-PIfr5qYxIKZt-uaSaTBdrTNxAuJ1ItmeDPZ3VdJJmxD_c22No7x482bdd3_yYtw== +0 -0
  193. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~S2Qlu11xBhEd5aGSzWsnw1TR8u8PiOF93GO0j5bfNoAFCVzxKOwhRFoIXba2EpQnLQqFdIKyhWN3l70A4GPHmg== +0 -0
  194. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~W7a7M37RO9jgck2zeR0471Pm7e8K0Kqj5tXEouDjvqKZXSrWxMaWD28oqkKKYAiU4608R4S9mM11KyphljdMSw== +0 -0
  195. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~XUo1oyPCrlL7CA74wG-OzQ06VOWJYWvHGFHU7keZN1SKaIXjHX5qi_kBzjG_rBCi89-S8GVmCy7S3PHSjG8SbQ== +0 -0
  196. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Xh0VmDvFNMELHu08-vrs54pegVyUwwDRxx_nXkwyD0NjnYozyqcGAKAr_QWHmw6F8XyuWg51M9KGpJJIFzzGuw== +0 -0
  197. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Xve-wMBp_lxVUgD9qH5GwieGP9cAWtm0xULZvdGjBRUMvaevmpCB5gnbMBuIXAO6a1c9v6WUq0jNVX7ut5HvOw== +0 -0
  198. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ZU1XkZFgnEE22CXEF-pOlcj5f10x-KM1Vw9d4IOLu-NiTZcz7koYPixhdrB1PJr8J-h9NpJmfqEastfxamA1jQ== +0 -0
  199. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~_YkNYEHTsbbtFILJpzH3HenH0t4ShI25dIMdve541CF5bl-jPF3X3F7tq-t5dvP0TEkATsOJdLQdBp1xv4Q-ag== +0 -0
  200. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~boy6mpn2jkwm60jjgQ0TG25UqRdN46LzmgTVCrpy6nBOgkLCGkGHcbceiwjU1itS_vj3-iQX0ZnrWOQrPyfHNA== +0 -0
  201. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~bwzpVZ9hAqGDHhXs2FRA82dfGfLmc7-m0uQhZDDfHHO7hQ17M_Np341BZX4WDLhYYS4cdUgaDodlNpdfpG3nXw== +0 -0
  202. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cBxe-9PpAGFdAsYkmdN3lJVqEliLcRYlyoAov0aPZfJGwUr_cOm3XpjO7nmf_2eLf8UAx-rycjnJzw07xLrNCA== +0 -0
  203. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~dirWk6W4Pav1oyciuflfJlRu0iuxbYOmrpQapOJ0mV9C1SQ-jvDRv_7h753Cy18-SwULARUdWsyUy3yNNvxF7w== +0 -0
  204. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ebwZVjSEHroc9jtIm4jd_h_YAqEBcOkAZ4HPNJT8pLCldjRcTq-obQLakxXOhfuoOBlYBoZLuO-Y0lskeZRYKw== +0 -0
  205. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~gfcRcmRIr0h09d0jiZsA7nUeQv2XtapxuYEXZy1Z9um0tTJQvz-O5ef5f7zhLenLvjnDtDtlY_aY4Hvpce6e1Q== +0 -0
  206. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~hgOgiVCyv2R0W-f0qKw5xYPeUwj8_ccCM9vKH_7vAQcCO9t8BwR1APGRBv20AONmp-PYMXmtgsBlQkNBRBpdQA== +0 -0
  207. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~hrhCl-YRAAr8ByNB_LCgEBsVNHMp92gTIUknetpUHMjcXl4Hpn_uY-h6C45oga0ZALnfGCo6iKTmiPLa4Qvnpg== +0 -0
  208. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~n2yoR7JsyL4DSUwmjnpE4Iq9Qi_eeZrmpPU8cdehDFKfESK7nwxXxfrSMQbk0BQ2lgGPadoRcd1-qr1xVz97jA== +0 -0
  209. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~nMCcZm8WvPogyO_nuJ926Q3Q2dqVMN2LdjEL1Kq2wJ_RG-rH-e_6v41l1xZbCsQTa3XykQdEiXNc0HtAvT6IRA== +0 -0
  210. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~oc3C7xkUt-OWDL6rrsxs-seS4Fu1bqBWAAXCHalgShaGg9MUrOiRbHT2DcAnhyQFKx6x5FRbvjmYoQWrQiXJZA== +0 -0
  211. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~p-ihj7SEgkDXpMu9hvKE_wiX9cvtwyXrdIn964BfedXHKGpC6o7mMPxEyC0kRPVi_EZs_MRV5bAPEpl5h5we0g== +0 -0
  212. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~qlhO_D9oE8uSKH-mZqyRF9pp4Zv1Tv0dIYcqrH4hb1VWlIxcdxmg2j0M8496cQeFXC5bn_JMXdBlD-d6cnFF8w== +0 -0
  213. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~tjpiyIxJR_boTdUNrtFDuKIZoY84fI4lA1oMJbq9e2ZmYKIK5FeRN2O8cV_yMOYJGr4lbv03kTmT70mCjUc2_Q== +0 -0
  214. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~wULeoj18eEKJWAKx1uFQVwS48cUGFcYPRJQj1Ro5XNJsWCwppGSCdIPhwifD6Z2f_j3zfI2SmC2Gg81sBXXW7g== +0 -0
  215. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~zrEihMys4NVV5rx6FmuzEGO2TjloI3OiC7yzIhvqYoRo43ibb2F-Km6Jf4NX-ac62pOLBYZRcjQTvYMpn75_oA== +0 -0
  216. package/Tests/Artifacts/LottieTests.xcresult/Info.plist +0 -29
  217. package/Tests/Samples/9squares_AlBoardman.json +0 -1
  218. package/Tests/Samples/Boat_Loader.json +0 -1
  219. package/Tests/Samples/HamburgerArrow.json +0 -1
  220. package/Tests/Samples/IconTransitions.json +0 -1
  221. package/Tests/Samples/Images/dog.png +0 -0
  222. package/Tests/Samples/Issues/issue_1403.json +0 -1
  223. package/Tests/Samples/Issues/issue_1407.json +0 -1
  224. package/Tests/Samples/Issues/issue_1488.json +0 -1
  225. package/Tests/Samples/Issues/issue_1505.json +0 -1
  226. package/Tests/Samples/Issues/issue_1628.json +0 -1
  227. package/Tests/Samples/Issues/pr_1536.json +0 -1
  228. package/Tests/Samples/Issues/pr_1563.json +0 -8439
  229. package/Tests/Samples/Issues/pr_1592.json +0 -5527
  230. package/Tests/Samples/Issues/pr_1599.json +0 -738
  231. package/Tests/Samples/Issues/pr_1604_1.json +0 -1
  232. package/Tests/Samples/Issues/pr_1604_2.json +0 -1
  233. package/Tests/Samples/LottieFiles/LICENSE.md +0 -14
  234. package/Tests/Samples/LottieFiles/bounce_strokes.json +0 -1
  235. package/Tests/Samples/LottieFiles/cactus.json +0 -1
  236. package/Tests/Samples/LottieFiles/dog_car_ride.json +0 -1
  237. package/Tests/Samples/LottieFiles/draft_icon.json +0 -1
  238. package/Tests/Samples/LottieFiles/gradient_1.json +0 -1
  239. package/Tests/Samples/LottieFiles/gradient_2.json +0 -1
  240. package/Tests/Samples/LottieFiles/gradient_pill.json +0 -1
  241. package/Tests/Samples/LottieFiles/gradient_shapes.json +0 -1
  242. package/Tests/Samples/LottieFiles/gradient_square.json +0 -1
  243. package/Tests/Samples/LottieFiles/growth.json +0 -1
  244. package/Tests/Samples/LottieFiles/infinity_loader.json +0 -1
  245. package/Tests/Samples/LottieFiles/loading_dots_1.json +0 -1
  246. package/Tests/Samples/LottieFiles/loading_dots_2.json +0 -1
  247. package/Tests/Samples/LottieFiles/loading_dots_3.json +0 -1
  248. package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +0 -1
  249. package/Tests/Samples/LottieFiles/settings_slider.json +0 -1
  250. package/Tests/Samples/LottieFiles/shop.json +0 -1
  251. package/Tests/Samples/LottieFiles/step_loader.json +0 -1
  252. package/Tests/Samples/LottieLogo1.json +0 -1
  253. package/Tests/Samples/LottieLogo1_masked.json +0 -1
  254. package/Tests/Samples/LottieLogo2.json +0 -1
  255. package/Tests/Samples/MotionCorpse_Jrcanest.json +0 -1
  256. package/Tests/Samples/Nonanimating/BasicLayers.json +0 -1
  257. package/Tests/Samples/Nonanimating/DisableNodesTest.json +0 -1
  258. package/Tests/Samples/Nonanimating/FirstText.json +0 -1
  259. package/Tests/Samples/Nonanimating/GeometryTransformTest.json +0 -1
  260. package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +0 -1
  261. package/Tests/Samples/Nonanimating/Text_Glyph.json +0 -1
  262. package/Tests/Samples/Nonanimating/Text_NoAnimation.json +0 -1
  263. package/Tests/Samples/Nonanimating/Text_NoGlyph.json +0 -1
  264. package/Tests/Samples/Nonanimating/Zoom.json +0 -1
  265. package/Tests/Samples/Nonanimating/_dog.json +0 -1
  266. package/Tests/Samples/Nonanimating/base64Test.json +0 -1
  267. package/Tests/Samples/Nonanimating/blend_mode_test.json +0 -1
  268. package/Tests/Samples/Nonanimating/keypathTest.json +0 -1
  269. package/Tests/Samples/Nonanimating/verifyLineHeight.json +0 -1
  270. package/Tests/Samples/PinJump.json +0 -1
  271. package/Tests/Samples/Private/BrokenLottieFiles/growth_man.json +0 -874
  272. package/Tests/Samples/Private/BrokenLottieFiles/rocket.json +0 -1
  273. package/Tests/Samples/Private/China_EmptyState_Itinerary.json +0 -1
  274. package/Tests/Samples/Private/LoaderHourglass.json +0 -12070
  275. package/Tests/Samples/Private/README.md +0 -7
  276. package/Tests/Samples/Private/Urgency/alarm_animated.json +0 -1
  277. package/Tests/Samples/Private/Urgency/diamond_animated.json +0 -1
  278. package/Tests/Samples/Private/Urgency/eye_animated.json +0 -1
  279. package/Tests/Samples/Private/Urgency/light_bulb_animated.json +0 -1
  280. package/Tests/Samples/Private/Urgency/light_bulb_static.json +0 -1
  281. package/Tests/Samples/Private/Urgency/piggy_bank_static.json +0 -1
  282. package/Tests/Samples/Private/Urgency/price_tag_legacy.json +0 -1
  283. package/Tests/Samples/Private/Urgency/rausch_alarm.json +0 -1
  284. package/Tests/Samples/Private/Urgency/rausch_alert.json +0 -1
  285. package/Tests/Samples/Private/Urgency/rausch_clock.json +0 -1
  286. package/Tests/Samples/Private/Urgency/rausch_diamond.json +0 -1
  287. package/Tests/Samples/Private/Urgency/rausch_money.json +0 -1
  288. package/Tests/Samples/Private/Urgency/rausch_piggy_bank.json +0 -1
  289. package/Tests/Samples/Private/Urgency/rausch_tag.json +0 -1
  290. package/Tests/Samples/Private/Urgency/red_envelope_animated.json +0 -1
  291. package/Tests/Samples/Private/Urgency/tag_animated.json +0 -1
  292. package/Tests/Samples/Private/Urgency/trophy_animated.json +0 -1
  293. package/Tests/Samples/Private/Urgency/wings_key_animated.json +0 -1
  294. package/Tests/Samples/Private/_flexible.json +0 -1
  295. package/Tests/Samples/Private/aircover.json +0 -1
  296. package/Tests/Samples/Private/belo_spin_rausch.json +0 -1
  297. package/Tests/Samples/Private/celebration.json +0 -2821
  298. package/Tests/Samples/Private/checkbox.json +0 -1
  299. package/Tests/Samples/Private/checkbox_small.json +0 -1
  300. package/Tests/Samples/Private/getting_your_trip_ready.json +0 -3540
  301. package/Tests/Samples/Private/gradient_afternoon.json +0 -1
  302. package/Tests/Samples/Private/gradient_brand.json +0 -1
  303. package/Tests/Samples/Private/gradient_evening.json +0 -1
  304. package/Tests/Samples/Private/gradient_morning.json +0 -1
  305. package/Tests/Samples/Private/issue_1467.json +0 -1
  306. package/Tests/Samples/Private/loading_dots.json +0 -1
  307. package/Tests/Samples/Private/loading_dots_small.json +0 -1
  308. package/Tests/Samples/Private/payment_loader.json +0 -1
  309. package/Tests/Samples/Private/radio_button.json +0 -1
  310. package/Tests/Samples/Private/selfie_intro.json +0 -1
  311. package/Tests/Samples/Private/stepper_add.json +0 -1
  312. package/Tests/Samples/Private/stepper_subtract.json +0 -1
  313. package/Tests/Samples/Private/switch.json +0 -1
  314. package/Tests/Samples/Private/thumb.json +0 -1
  315. package/Tests/Samples/Private/toggle_no.json +0 -1
  316. package/Tests/Samples/Private/toggle_yes.json +0 -1
  317. package/Tests/Samples/Private/user_error_black_and_white.json +0 -1
  318. package/Tests/Samples/Private/user_error_cut_off.json +0 -1
  319. package/Tests/Samples/Switch.json +0 -1
  320. package/Tests/Samples/Switch_States.json +0 -1
  321. package/Tests/Samples/TwitterHeart.json +0 -1
  322. package/Tests/Samples/TwitterHeartButton.json +0 -1
  323. package/Tests/Samples/TypeFace/A.json +0 -1
  324. package/Tests/Samples/TypeFace/Apostrophe.json +0 -1
  325. package/Tests/Samples/TypeFace/B.json +0 -1
  326. package/Tests/Samples/TypeFace/BlinkingCursor.json +0 -1
  327. package/Tests/Samples/TypeFace/C.json +0 -1
  328. package/Tests/Samples/TypeFace/Colon.json +0 -1
  329. package/Tests/Samples/TypeFace/Comma.json +0 -1
  330. package/Tests/Samples/TypeFace/D.json +0 -1
  331. package/Tests/Samples/TypeFace/E.json +0 -1
  332. package/Tests/Samples/TypeFace/F.json +0 -1
  333. package/Tests/Samples/TypeFace/G.json +0 -1
  334. package/Tests/Samples/TypeFace/H.json +0 -1
  335. package/Tests/Samples/TypeFace/I.json +0 -1
  336. package/Tests/Samples/TypeFace/J.json +0 -1
  337. package/Tests/Samples/TypeFace/K.json +0 -1
  338. package/Tests/Samples/TypeFace/L.json +0 -1
  339. package/Tests/Samples/TypeFace/M.json +0 -1
  340. package/Tests/Samples/TypeFace/N.json +0 -1
  341. package/Tests/Samples/TypeFace/O.json +0 -1
  342. package/Tests/Samples/TypeFace/P.json +0 -1
  343. package/Tests/Samples/TypeFace/Q.json +0 -1
  344. package/Tests/Samples/TypeFace/R.json +0 -1
  345. package/Tests/Samples/TypeFace/S.json +0 -1
  346. package/Tests/Samples/TypeFace/T.json +0 -1
  347. package/Tests/Samples/TypeFace/U.json +0 -1
  348. package/Tests/Samples/TypeFace/V.json +0 -1
  349. package/Tests/Samples/TypeFace/W.json +0 -1
  350. package/Tests/Samples/TypeFace/X.json +0 -1
  351. package/Tests/Samples/TypeFace/Y.json +0 -1
  352. package/Tests/Samples/TypeFace/Z.json +0 -1
  353. package/Tests/Samples/Watermelon.json +0 -1
  354. package/Tests/Samples/setValueTest.json +0 -1
  355. package/Tests/Samples/timeremap.json +0 -1
  356. package/Tests/Samples/vcTransition1.json +0 -1
  357. package/Tests/Samples/vcTransition2.json +0 -1
  358. package/script/lint/airbnb.swiftformat +0 -68
  359. package/script/lint/swiftlint.yml +0 -38
  360. package/script/test-carthage/Carthage/Build/.lottie-ios.version +0 -19
  361. package/script/test-carthage/Carthage/Build/Lottie.xcframework/Info.plist +0 -46
  362. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/BCSymbolMaps/BF971162-BE99-3507-B5B3-11947DC6B176.bcsymbolmap +0 -14778
  363. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Headers/Lottie-Swift.h +0 -673
  364. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Info.plist +0 -0
  365. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Lottie +0 -0
  366. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  367. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
  368. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftdoc +0 -0
  369. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftmodule +0 -0
  370. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/Lottie.framework/Modules/module.modulemap +0 -4
  371. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/dSYMs/Lottie.framework.dSYM/Contents/Info.plist +0 -20
  372. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64/dSYMs/Lottie.framework.dSYM/Contents/Resources/DWARF/Lottie +0 -0
  373. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Headers/Lottie-Swift.h +0 -1352
  374. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Info.plist +0 -0
  375. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Lottie +0 -0
  376. 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
  377. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/arm64.swiftsourceinfo +0 -0
  378. 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
  379. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/Project/x86_64.swiftsourceinfo +0 -0
  380. 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
  381. 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
  382. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftdoc +0 -0
  383. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/arm64.swiftmodule +0 -0
  384. 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
  385. 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
  386. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64.swiftdoc +0 -0
  387. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/Lottie.swiftmodule/x86_64.swiftmodule +0 -0
  388. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/Modules/module.modulemap +0 -4
  389. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/Lottie.framework/_CodeSignature/CodeResources +0 -256
  390. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/dSYMs/Lottie.framework.dSYM/Contents/Info.plist +0 -20
  391. package/script/test-carthage/Carthage/Build/Lottie.xcframework/ios-arm64_x86_64-simulator/dSYMs/Lottie.framework.dSYM/Contents/Resources/DWARF/Lottie +0 -0
  392. package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  393. package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
  394. package/script/test-carthage/Carthage/Checkouts/lottie-ios/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
@@ -55,8 +55,13 @@ final class ShapeItemLayer: BaseAnimationLayer {
55
55
  /// A `ShapeItem` that should be rendered by this layer
56
56
  let item: ShapeItem
57
57
 
58
- /// The group that contains this `ShapeItem`, if applicable
59
- let parentGroup: Group?
58
+ /// The set of groups that this item descends from
59
+ /// - Due to the way `GroupLayer`s are setup, the original `ShapeItem`
60
+ /// hierarchy from the `ShapeLayer` data model may no longer exactly
61
+ /// match the hierarchy of `GroupLayer` / `ShapeItemLayer`s constructed
62
+ /// at runtime. Since animation keypaths need to match the original
63
+ /// structure of the `ShapeLayer` data model, we track that info here.
64
+ let groupPath: [String]
60
65
  }
61
66
 
62
67
  override func setupAnimations(context: LayerAnimationContext) throws {
@@ -69,27 +74,24 @@ final class ShapeItemLayer: BaseAnimationLayer {
69
74
  try setupSolidFillAnimations(shapeLayer: shapeLayer, context: context)
70
75
 
71
76
  case .gradientFill(let gradientLayers):
72
- try setupGradientFillAnimations(
73
- gradientLayer: gradientLayers.gradientLayer,
74
- maskLayer: gradientLayers.maskLayer,
75
- context: context)
77
+ try setupGradientFillAnimations(layers: gradientLayers, context: context)
76
78
  }
77
79
 
78
80
  if let gradientStrokeConfiguration = sublayerConfiguration.gradientStroke {
79
- try setupGradientStrokeAnimations(
80
- gradientLayer: gradientStrokeConfiguration.gradientLayer,
81
- maskLayer: gradientStrokeConfiguration.maskLayer,
82
- context: context)
81
+ try setupGradientStrokeAnimations(layers: gradientStrokeConfiguration, context: context)
83
82
  }
84
83
  }
85
84
 
86
85
  // MARK: Private
87
86
 
88
87
  private struct GradientLayers {
89
- /// The `CALayer` that renders the actual gradient
90
- let gradientLayer: GradientRenderLayer
91
- /// The `CAShapeLayer` that clips the gradient layer to the expected shape
92
- let maskLayer: CAShapeLayer
88
+ /// The `CALayer` that renders the RGB components of the gradient
89
+ let gradientColorLayer: GradientRenderLayer
90
+ /// The `CALayer` that renders the alpha components of the gradient,
91
+ /// masking the `gradientColorLayer`
92
+ let gradientAlphaLayer: GradientRenderLayer?
93
+ /// The `CAShapeLayer` that clips the gradient layers to the expected shape
94
+ let shapeMaskLayer: CAShapeLayer
93
95
  }
94
96
 
95
97
  /// The configuration of this layer's `fill` sublayers
@@ -115,15 +117,15 @@ final class ShapeItemLayer: BaseAnimationLayer {
115
117
  // we're rendering a gradient (a `CAGradientLayer` masked by a `CAShapeLayer`)
116
118
  // or a solid shape (a simple `CAShapeLayer`).
117
119
  let fillLayerConfiguration: FillLayerConfiguration
118
- if otherItems.contains(where: { $0.item is GradientFill }) {
119
- fillLayerConfiguration = setupGradientFillLayerHierarchy()
120
+ if let gradientFill = otherItems.first(GradientFill.self) {
121
+ fillLayerConfiguration = setupGradientFillLayerHierarchy(for: gradientFill)
120
122
  } else {
121
123
  fillLayerConfiguration = setupSolidFillLayerHierarchy()
122
124
  }
123
125
 
124
126
  let gradientStrokeConfiguration: GradientLayers?
125
- if otherItems.contains(where: { $0.item is GradientStroke }) {
126
- gradientStrokeConfiguration = setupGradientStrokeLayerHierarchy()
127
+ if let gradientStroke = otherItems.first(GradientStroke.self) {
128
+ gradientStrokeConfiguration = setupGradientStrokeLayerHierarchy(for: gradientStroke)
127
129
  } else {
128
130
  gradientStrokeConfiguration = nil
129
131
  }
@@ -144,18 +146,35 @@ final class ShapeItemLayer: BaseAnimationLayer {
144
146
  return .solidFill(shapeLayer)
145
147
  }
146
148
 
147
- private func setupGradientFillLayerHierarchy() -> FillLayerConfiguration {
149
+ private func setupGradientFillLayerHierarchy(
150
+ for gradientFill: GradientFill)
151
+ -> FillLayerConfiguration
152
+ {
148
153
  let pathMask = CAShapeLayer()
149
154
  pathMask.fillColor = .rgb(0, 0, 0)
150
155
  mask = pathMask
151
156
 
152
- let gradientLayer = GradientRenderLayer()
153
- addSublayer(gradientLayer)
157
+ let rgbGradientLayer = GradientRenderLayer()
158
+ addSublayer(rgbGradientLayer)
154
159
 
155
- return .gradientFill(.init(gradientLayer: gradientLayer, maskLayer: pathMask))
160
+ let alphaGradientLayer: GradientRenderLayer?
161
+ if gradientFill.hasAlphaComponent {
162
+ alphaGradientLayer = GradientRenderLayer()
163
+ rgbGradientLayer.mask = alphaGradientLayer
164
+ } else {
165
+ alphaGradientLayer = nil
166
+ }
167
+
168
+ return .gradientFill(GradientLayers(
169
+ gradientColorLayer: rgbGradientLayer,
170
+ gradientAlphaLayer: alphaGradientLayer,
171
+ shapeMaskLayer: pathMask))
156
172
  }
157
173
 
158
- private func setupGradientStrokeLayerHierarchy() -> GradientLayers {
174
+ private func setupGradientStrokeLayerHierarchy(
175
+ for gradientStroke: GradientStroke)
176
+ -> GradientLayers
177
+ {
159
178
  let container = BaseAnimationLayer()
160
179
 
161
180
  let pathMask = CAShapeLayer()
@@ -163,11 +182,22 @@ final class ShapeItemLayer: BaseAnimationLayer {
163
182
  pathMask.strokeColor = .rgb(0, 0, 0)
164
183
  container.mask = pathMask
165
184
 
166
- let gradientLayer = GradientRenderLayer()
167
- container.addSublayer(gradientLayer)
185
+ let rgbGradientLayer = GradientRenderLayer()
186
+ container.addSublayer(rgbGradientLayer)
168
187
  addSublayer(container)
169
188
 
170
- return .init(gradientLayer: gradientLayer, maskLayer: pathMask)
189
+ let alphaGradientLayer: GradientRenderLayer?
190
+ if gradientStroke.hasAlphaComponent {
191
+ alphaGradientLayer = GradientRenderLayer()
192
+ rgbGradientLayer.mask = alphaGradientLayer
193
+ } else {
194
+ alphaGradientLayer = nil
195
+ }
196
+
197
+ return GradientLayers(
198
+ gradientColorLayer: rgbGradientLayer,
199
+ gradientAlphaLayer: alphaGradientLayer,
200
+ shapeMaskLayer: pathMask)
171
201
  }
172
202
 
173
203
  private func setupSolidFillAnimations(
@@ -178,6 +208,13 @@ final class ShapeItemLayer: BaseAnimationLayer {
178
208
  var trimPathMultiplier: PathMultiplier? = nil
179
209
  if let (trim, context) = otherItems.first(Trim.self, context: context) {
180
210
  trimPathMultiplier = try shapeLayer.addAnimations(for: trim, context: context)
211
+
212
+ try context.compatibilityAssert(
213
+ otherItems.first(Fill.self) == nil,
214
+ """
215
+ The Core Animation rendering engine doesn't currently support applying
216
+ trims to filled shapes (only stroked shapes).
217
+ """)
181
218
  }
182
219
 
183
220
  try shapeLayer.addAnimations(for: shape.item, context: context.for(shape), pathMultiplier: trimPathMultiplier ?? 1)
@@ -192,34 +229,42 @@ final class ShapeItemLayer: BaseAnimationLayer {
192
229
  }
193
230
 
194
231
  private func setupGradientFillAnimations(
195
- gradientLayer: GradientRenderLayer,
196
- maskLayer: CAShapeLayer,
232
+ layers: GradientLayers,
197
233
  context: LayerAnimationContext)
198
234
  throws
199
235
  {
200
- try maskLayer.addAnimations(for: shape.item, context: context.for(shape), pathMultiplier: 1)
236
+ try layers.shapeMaskLayer.addAnimations(
237
+ for: shape.item,
238
+ context: context.for(shape),
239
+ pathMultiplier: 1)
201
240
 
202
241
  if let (gradientFill, context) = otherItems.first(GradientFill.self, context: context) {
203
- try gradientLayer.addGradientAnimations(for: gradientFill, context: context)
242
+ layers.shapeMaskLayer.fillRule = gradientFill.fillRule.caFillRule
243
+ try layers.gradientColorLayer.addGradientAnimations(for: gradientFill, type: .rgb, context: context)
244
+ try layers.gradientAlphaLayer?.addGradientAnimations(for: gradientFill, type: .alpha, context: context)
204
245
  }
205
246
  }
206
247
 
207
248
  private func setupGradientStrokeAnimations(
208
- gradientLayer: GradientRenderLayer,
209
- maskLayer: CAShapeLayer,
249
+ layers: GradientLayers,
210
250
  context: LayerAnimationContext)
211
251
  throws
212
252
  {
213
253
  var trimPathMultiplier: PathMultiplier? = nil
214
254
  if let (trim, context) = otherItems.first(Trim.self, context: context) {
215
- trimPathMultiplier = try maskLayer.addAnimations(for: trim, context: context)
255
+ trimPathMultiplier = try layers.shapeMaskLayer.addAnimations(for: trim, context: context)
216
256
  }
217
257
 
218
- try maskLayer.addAnimations(for: shape.item, context: context.for(shape), pathMultiplier: trimPathMultiplier ?? 1)
258
+ try layers.shapeMaskLayer.addAnimations(
259
+ for: shape.item,
260
+ context: context.for(shape),
261
+ pathMultiplier: trimPathMultiplier ?? 1)
219
262
 
220
263
  if let (gradientStroke, context) = otherItems.first(GradientStroke.self, context: context) {
221
- try gradientLayer.addGradientAnimations(for: gradientStroke, context: context)
222
- try maskLayer.addStrokeAnimations(for: gradientStroke, context: context)
264
+ try layers.gradientColorLayer.addGradientAnimations(for: gradientStroke, type: .rgb, context: context)
265
+ try layers.gradientAlphaLayer?.addGradientAnimations(for: gradientStroke, type: .alpha, context: context)
266
+
267
+ try layers.shapeMaskLayer.addStrokeAnimations(for: gradientStroke, context: context)
223
268
  }
224
269
  }
225
270
 
@@ -241,6 +286,17 @@ extension Array where Element == ShapeItemLayer.Item {
241
286
 
242
287
  return nil
243
288
  }
289
+
290
+ /// The first `ShapeItem` in this array of the given type
291
+ func first<ItemType: ShapeItem>(_: ItemType.Type) -> ItemType? {
292
+ for item in self {
293
+ if let match = item.item as? ItemType {
294
+ return match
295
+ }
296
+ }
297
+
298
+ return nil
299
+ }
244
300
  }
245
301
 
246
302
  extension LayerAnimationContext {
@@ -249,8 +305,8 @@ extension LayerAnimationContext {
249
305
  func `for`(_ item: ShapeItemLayer.Item) -> LayerAnimationContext {
250
306
  var context = self
251
307
 
252
- if let group = item.parentGroup {
253
- context.currentKeypath.keys.append(group.name)
308
+ for parentGroupName in item.groupPath {
309
+ context.currentKeypath.keys.append(parentGroupName)
254
310
  }
255
311
 
256
312
  context.currentKeypath.keys.append(item.item.name)
@@ -13,7 +13,7 @@ final class ShapeLayer: BaseCompositionLayer {
13
13
  init(shapeLayer: ShapeLayerModel, context: LayerContext) throws {
14
14
  self.shapeLayer = shapeLayer
15
15
  super.init(layerModel: shapeLayer)
16
- try setupGroups(from: shapeLayer.items, parentGroup: nil, context: context)
16
+ try setUpGroups(context: context)
17
17
  }
18
18
 
19
19
  required init?(coder _: NSCoder) {
@@ -35,6 +35,28 @@ final class ShapeLayer: BaseCompositionLayer {
35
35
 
36
36
  private let shapeLayer: ShapeLayerModel
37
37
 
38
+ private func setUpGroups(context: LayerContext) throws {
39
+ // If the layer has a `Repeater`, the `Group`s are duplicated and offset
40
+ // based on the copy count of the repeater.
41
+ if let repeater = shapeLayer.items.first(where: { $0 is Repeater }) as? Repeater {
42
+ try setUpRepeater(repeater, context: context)
43
+ } else {
44
+ try setupGroups(from: shapeLayer.items, parentGroup: nil, parentGroupPath: [], context: context)
45
+ }
46
+ }
47
+
48
+ private func setUpRepeater(_ repeater: Repeater, context: LayerContext) throws {
49
+ let items = shapeLayer.items.filter { !($0 is Repeater) }
50
+ let copyCount = Int(try repeater.copies.exactlyOneKeyframe(context: context, description: "repeater copies").value)
51
+
52
+ for index in 0..<copyCount {
53
+ for groupLayer in try makeGroupLayers(from: items, parentGroup: nil, parentGroupPath: [], context: context) {
54
+ let repeatedLayer = RepeaterLayer(repeater: repeater, childLayer: groupLayer, index: index)
55
+ addSublayer(repeatedLayer)
56
+ }
57
+ }
58
+ }
59
+
38
60
  }
39
61
 
40
62
  // MARK: - GroupLayer
@@ -44,9 +66,10 @@ final class GroupLayer: BaseAnimationLayer {
44
66
 
45
67
  // MARK: Lifecycle
46
68
 
47
- init(group: Group, inheritedItems: [ShapeItemLayer.Item], context: LayerContext) throws {
69
+ init(group: Group, items: [ShapeItemLayer.Item], groupPath: [String], context: LayerContext) throws {
48
70
  self.group = group
49
- self.inheritedItems = inheritedItems
71
+ self.items = items
72
+ self.groupPath = groupPath
50
73
  super.init()
51
74
  try setupLayerHierarchy(context: context)
52
75
  }
@@ -63,7 +86,8 @@ final class GroupLayer: BaseAnimationLayer {
63
86
  }
64
87
 
65
88
  group = typedLayer.group
66
- inheritedItems = typedLayer.inheritedItems
89
+ items = typedLayer.items
90
+ groupPath = typedLayer.groupPath
67
91
  super.init(layer: typedLayer)
68
92
  }
69
93
 
@@ -82,46 +106,62 @@ final class GroupLayer: BaseAnimationLayer {
82
106
 
83
107
  private let group: Group
84
108
 
85
- /// `ShapeItem`s that were listed in the parent's `items: [ShapeItem]` array
86
- /// - This layer's parent is either the root `ShapeLayerModel` or some other `Group`
87
- private let inheritedItems: [ShapeItemLayer.Item]
109
+ /// `ShapeItemLayer.Item`s rendered by this `Group`
110
+ /// - In the original `ShapeLayer` data model, these items could have originated from a different group
111
+ private let items: [ShapeItemLayer.Item]
112
+
113
+ /// The keypath that represents this group, with respect to the parent `ShapeLayer`
114
+ /// - Due to the way `GroupLayer`s are setup, the original `ShapeItem`
115
+ /// hierarchy from the `ShapeLayer` data model may no longer exactly
116
+ /// match the hierarchy of `GroupLayer` / `ShapeItemLayer`s constructed
117
+ /// at runtime. Since animation keypaths need to match the original
118
+ /// structure of the `ShapeLayer` data model, we track that info here.
119
+ private let groupPath: [String]
88
120
 
89
- /// `ShapeItem`s (other than nested `Group`s) that are included in this group
90
- private lazy var nonGroupItems = group.items
91
- .filter { !($0 is Group) }
92
- .map { ShapeItemLayer.Item(item: $0, parentGroup: group) }
93
- + inheritedItems
121
+ /// `ShapeItem`s (other than nested `Group`s) that are rendered by this layer
122
+ private lazy var nonGroupItems = items.filter { !($0.item is Group) }
94
123
 
95
124
  private func setupLayerHierarchy(context: LayerContext) throws {
96
125
  // Groups can contain other groups, so we may have to continue
97
126
  // recursively creating more `GroupLayer`s
98
- try setupGroups(from: group.items, parentGroup: group, context: context)
127
+ try setupGroups(from: group.items, parentGroup: group, parentGroupPath: groupPath, context: context)
99
128
 
100
129
  // Create `ShapeItemLayer`s for each subgroup of shapes that should be rendered as a single unit
101
130
  // - These groups are listed from front-to-back, so we have to add the sublayers in reverse order
102
131
  for shapeRenderGroup in nonGroupItems.shapeRenderGroups.reversed() {
103
- // If all of the path-drawing `ShapeItem`s have keyframes with the same timing information,
104
- // we can combine the `[KeyframeGroup<BezierPath>]` (which have to animate in separate layers)
105
- // into a single `KeyframeGroup<[BezierPath]>`, which can be combined into a single CGPath animation.
106
- //
107
- // This is how Groups with multiple path-drawing items are supposed to be rendered,
108
- // because combining multiple paths into a single `CGPath` (instead of rendering them in separate layers)
109
- // allows `CAShapeLayerFillRule.evenOdd` to be applied if the paths overlap. We just can't do this
110
- // in all cases, due to limitations of Core Animation.
132
+ // When there are multiple path-drawing items, they're supposed to be rendered
133
+ // in a single `CAShapeLayer` (instead of rendering them in separate layers) so
134
+ // `CAShapeLayerFillRule.evenOdd` can be applied correctly if the paths overlap.
135
+ // Since a `CAShapeLayer` only supports animating a single `CGPath` from a single `KeyframeGroup<BezierPath>`,
136
+ // this requires combining all of the path-drawing items into a single set of keyframes.
111
137
  if
112
138
  shapeRenderGroup.pathItems.count > 1,
113
- let combinedShapeKeyframes = Keyframes.combinedIfPossible(
114
- shapeRenderGroup.pathItems.map { ($0.item as? Shape)?.path }),
139
+ // We currently only support this codepath for `Shape` items that directly contain bezier path keyframes.
140
+ // We could also support this for other path types like rectangles, ellipses, and polygons with more work.
141
+ shapeRenderGroup.pathItems.allSatisfy({ $0.item is Shape }),
115
142
  // `Trim`s are currently only applied correctly using individual `ShapeItemLayer`s,
116
143
  // because each path has to be trimmed separately.
117
144
  !shapeRenderGroup.otherItems.contains(where: { $0.item is Trim })
118
145
  {
119
- let combinedShape = CombinedShapeItem(
120
- shapes: combinedShapeKeyframes,
121
- name: group.name)
146
+ let allPathKeyframes = shapeRenderGroup.pathItems.compactMap { ($0.item as? Shape)?.path }
147
+ let combinedShape: CombinedShapeItem
148
+
149
+ // If all of the path-drawing `ShapeItem`s have keyframes with the same timing information,
150
+ // we can combine the `[KeyframeGroup<BezierPath>]` (which have to animate in separate layers)
151
+ // into a single `KeyframeGroup<[BezierPath]>`, which can be combined into a single CGPath animation.
152
+ if let combinedShapeKeyframes = Keyframes.combinedIfPossible(allPathKeyframes) {
153
+ combinedShape = CombinedShapeItem(shapes: combinedShapeKeyframes, name: group.name)
154
+ }
155
+
156
+ // Otherwise, in order for the path fills to be rendered correctly, we have to manually
157
+ // interpolate the path for each shape at each frame ahead of time so we can combine them
158
+ // into a single set of bezier path keyframes.
159
+ else {
160
+ combinedShape = .manuallyInterpolating(shapes: allPathKeyframes, name: group.name, context: context)
161
+ }
122
162
 
123
163
  let sublayer = try ShapeItemLayer(
124
- shape: ShapeItemLayer.Item(item: combinedShape, parentGroup: group),
164
+ shape: ShapeItemLayer.Item(item: combinedShape, groupPath: shapeRenderGroup.pathItems[0].groupPath),
125
165
  otherItems: shapeRenderGroup.otherItems,
126
166
  context: context)
127
167
 
@@ -129,7 +169,8 @@ final class GroupLayer: BaseAnimationLayer {
129
169
  }
130
170
 
131
171
  // Otherwise, if each `ShapeItem` that draws a `GGPath` animates independently,
132
- // we have to create a separate `ShapeItemLayer` for each one.
172
+ // we have to create a separate `ShapeItemLayer` for each one. This may render
173
+ // incorrectly if there are multiple paths that overlap with each other.
133
174
  else {
134
175
  for pathDrawingItem in shapeRenderGroup.pathItems {
135
176
  let sublayer = try ShapeItemLayer(
@@ -149,34 +190,78 @@ extension CALayer {
149
190
  /// Sets up `GroupLayer`s for each `Group` in the given list of `ShapeItem`s
150
191
  /// - Each `Group` item becomes its own `GroupLayer` sublayer.
151
192
  /// - Other `ShapeItem` are applied to all sublayers
152
- fileprivate func setupGroups(from items: [ShapeItem], parentGroup: Group?, context: LayerContext) throws {
153
- let (groupItems, otherItems) = items.grouped(by: { $0 is Group })
193
+ fileprivate func setupGroups(
194
+ from items: [ShapeItem],
195
+ parentGroup: Group?,
196
+ parentGroupPath: [String],
197
+ context: LayerContext) throws
198
+ {
199
+ let groupLayers = try makeGroupLayers(
200
+ from: items,
201
+ parentGroup: parentGroup,
202
+ parentGroupPath: parentGroupPath,
203
+ context: context)
204
+
205
+ for groupLayer in groupLayers {
206
+ addSublayer(groupLayer)
207
+ }
208
+ }
209
+
210
+ /// Creates a `GroupLayer` for each `Group` in the given list of `ShapeItem`s
211
+ /// - Each `Group` item becomes its own `GroupLayer` sublayer.
212
+ /// - Other `ShapeItem` are applied to all sublayers
213
+ fileprivate func makeGroupLayers(
214
+ from items: [ShapeItem],
215
+ parentGroup: Group?,
216
+ parentGroupPath: [String],
217
+ context: LayerContext) throws
218
+ -> [GroupLayer]
219
+ {
220
+ var (groupItems, otherItems) = items
221
+ .filter { !$0.hidden }
222
+ .grouped(by: { $0 is Group })
223
+
224
+ // If this shape doesn't have any groups but just has top-level shape items,
225
+ // we can create a placeholder group with those items. (Otherwise the shape items
226
+ // would be silently ignored, since we expect all shape layers to have a top-level group).
227
+ if groupItems.isEmpty, parentGroup == nil {
228
+ groupItems = [Group(items: otherItems, name: "")]
229
+ otherItems = []
230
+ }
231
+
232
+ // `ShapeItem`s either draw a path, or modify how a path is rendered.
233
+ // - If this group doesn't have any items that draw a path, then its
234
+ // items are applied to all of this group's children.
235
+ let inheritedItemsForChildGroups: [ShapeItemLayer.Item]
236
+ if !otherItems.contains(where: { $0.drawsCGPath }) {
237
+ inheritedItemsForChildGroups = otherItems.map {
238
+ ShapeItemLayer.Item(item: $0, groupPath: parentGroupPath)
239
+ }
240
+ } else {
241
+ inheritedItemsForChildGroups = []
242
+ }
154
243
 
155
244
  // Groups are listed from front to back,
156
245
  // but `CALayer.sublayers` are listed from back to front.
157
246
  let groupsInZAxisOrder = groupItems.reversed()
158
247
 
159
- for group in groupsInZAxisOrder {
160
- guard let group = group as? Group else { continue }
248
+ return try groupsInZAxisOrder.compactMap { group in
249
+ guard let group = group as? Group else { return nil }
161
250
 
162
- // `ShapeItem`s either draw a path, or modify how a path is rendered.
163
- // - If this group doesn't have any items that draw a path, then its
164
- // items are applied to all of this groups children.
165
- let inheritedItems: [ShapeItemLayer.Item]
166
- if !otherItems.contains(where: { $0.drawsCGPath }) {
167
- inheritedItems = otherItems.map {
168
- ShapeItemLayer.Item(item: $0, parentGroup: parentGroup)
169
- }
170
- } else {
171
- inheritedItems = []
251
+ var pathForChildren = parentGroupPath
252
+ if !group.name.isEmpty {
253
+ pathForChildren.append(group.name)
172
254
  }
173
255
 
174
- let groupLayer = try GroupLayer(
256
+ let childItems = group.items
257
+ .filter { !$0.hidden }
258
+ .map { ShapeItemLayer.Item(item: $0, groupPath: pathForChildren) }
259
+
260
+ return try GroupLayer(
175
261
  group: group,
176
- inheritedItems: inheritedItems,
262
+ items: childItems + inheritedItemsForChildGroups,
263
+ groupPath: pathForChildren,
177
264
  context: context)
178
-
179
- addSublayer(groupLayer)
180
265
  }
181
266
  }
182
267
  }
@@ -36,12 +36,27 @@ final class TextLayer: BaseCompositionLayer {
36
36
 
37
37
  // MARK: Internal
38
38
 
39
+ override func setupAnimations(context: LayerAnimationContext) throws {
40
+ try super.setupAnimations(context: context)
41
+ let textAnimationContext = context.addingKeypathComponent(textLayerModel.name)
42
+
43
+ let sourceText = try textLayerModel.text.exactlyOneKeyframe(
44
+ context: textAnimationContext,
45
+ description: "text layer text")
46
+
47
+ renderLayer.text = context.textProvider.textFor(
48
+ keypathName: textAnimationContext.currentKeypath.fullPath,
49
+ sourceText: sourceText.text)
50
+
51
+ renderLayer.sizeToFit()
52
+ }
53
+
39
54
  func configureRenderLayer(with context: LayerContext) throws {
40
55
  // We can't use `CATextLayer`, because it doesn't support enough features we use.
41
56
  // Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation)
42
57
  // used by the Main Thread rendering engine. This means the Core Animation engine can't
43
58
  // _animate_ text properties, but it can display static text without any issues.
44
- let text = try textLayerModel.text.exactlyOneKeyframe(context: context, description: "text layer text").value
59
+ let text = try textLayerModel.text.exactlyOneKeyframe(context: context, description: "text layer text")
45
60
 
46
61
  // The Core Animation engine doesn't currently support `TextAnimator`s.
47
62
  // - We could add support for animating the transform-related properties without much trouble.
@@ -54,7 +69,6 @@ final class TextLayer: BaseCompositionLayer {
54
69
  """)
55
70
  }
56
71
 
57
- renderLayer.text = text.text
58
72
  renderLayer.font = context.fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
59
73
 
60
74
  renderLayer.alignment = text.justification.textAlignment
@@ -17,7 +17,7 @@ class CompositionLayer: CALayer, KeypathSearchable {
17
17
 
18
18
  init(layer: LayerModel, size: CGSize) {
19
19
  transformNode = LayerTransformNode(transform: layer.transform)
20
- if let masks = layer.masks {
20
+ if let masks = layer.masks?.filter({ $0.mode != .none }), !masks.isEmpty {
21
21
  maskLayer = MaskContainerLayer(masks: masks)
22
22
  } else {
23
23
  maskLayer = nil
@@ -109,7 +109,6 @@ private class MaskLayer: CALayer {
109
109
  actions = [
110
110
  "opacity" : NSNull(),
111
111
  ]
112
-
113
112
  }
114
113
 
115
114
  override init(layer: Any) {
@@ -152,7 +151,6 @@ private class MaskLayer: CALayer {
152
151
  }
153
152
  maskLayer.path = path
154
153
  }
155
-
156
154
  }
157
155
  }
158
156
 
@@ -107,12 +107,12 @@ final class PreCompositionLayer: CompositionLayer {
107
107
  } else {
108
108
  localFrame = (frame - startFrame) / timeStretch
109
109
  }
110
- animationLayers.forEach( { $0.displayWithFrame(frame: localFrame, forceUpdates: forceUpdates) })
110
+ animationLayers.forEach({ $0.displayWithFrame(frame: localFrame, forceUpdates: forceUpdates) })
111
111
  }
112
112
 
113
113
  override func updateRenderScale() {
114
114
  super.updateRenderScale()
115
- animationLayers.forEach( { $0.renderScale = renderScale } )
115
+ animationLayers.forEach({ $0.renderScale = renderScale })
116
116
  }
117
117
 
118
118
  // MARK: Fileprivate
@@ -93,7 +93,6 @@ final class MainThreadAnimationLayer: CALayer, RootAnimationLayer {
93
93
  super.init(layer: layer)
94
94
 
95
95
  currentFrame = typedLayer.currentFrame
96
-
97
96
  }
98
97
 
99
98
  required init?(coder _: NSCoder) {
@@ -195,7 +194,7 @@ final class MainThreadAnimationLayer: CALayer, RootAnimationLayer {
195
194
 
196
195
  /// Forces the view to update its drawing.
197
196
  func forceDisplayUpdate() {
198
- animationLayers.forEach( { $0.displayWithFrame(frame: currentFrame, forceUpdates: true) })
197
+ animationLayers.forEach({ $0.displayWithFrame(frame: currentFrame, forceUpdates: true) })
199
198
  }
200
199
 
201
200
  func logHierarchyKeypaths() {
@@ -151,6 +151,16 @@ final class CoreTextRenderLayer: CALayer {
151
151
  strokeFrame = nil
152
152
  }
153
153
 
154
+ // This fixes a vertical padding issue that arises when drawing some fonts.
155
+ // For some reason some fonts, such as Helvetica draw with and ascender that is greater than the one reported by CTFontGetAscender.
156
+ // I suspect this is actually an issue with the Attributed string, but cannot reproduce.
157
+
158
+ if let fillFrame = fillFrame {
159
+ ctx.adjustWithLineOrigins(in: fillFrame, with: font)
160
+ } else if let strokeFrame = strokeFrame {
161
+ ctx.adjustWithLineOrigins(in: strokeFrame, with: font)
162
+ }
163
+
154
164
  if !strokeOnTop, let strokeFrame = strokeFrame {
155
165
  CTFrameDraw(strokeFrame, ctx)
156
166
  }
@@ -311,10 +321,29 @@ final class CoreTextRenderLayer: CALayer {
311
321
  x: textAnchor.x.remap(fromLow: 0, fromHigh: drawingRect.size.width, toLow: 0, toHigh: 1),
312
322
  y: textAnchor.y.remap(fromLow: 0, fromHigh: drawingRect.size.height, toLow: 0, toHigh: 1))
313
323
 
314
- if fillFrameSetter != nil && strokeFrameSetter != nil {
324
+ if fillFrameSetter != nil, strokeFrameSetter != nil {
315
325
  drawingRect.size.width += strokeWidth
316
326
  drawingRect.size.height += strokeWidth
317
327
  }
318
328
  }
319
329
 
320
330
  }
331
+
332
+ extension CGContext {
333
+
334
+ fileprivate func adjustWithLineOrigins(in frame: CTFrame, with font: CTFont?) {
335
+ guard let font = font else { return }
336
+
337
+ let count = CFArrayGetCount(CTFrameGetLines(frame))
338
+
339
+ guard count > 0 else { return }
340
+
341
+ var o = [CGPoint](repeating: .zero, count: 1)
342
+ CTFrameGetLineOrigins(frame, CFRange(location: count - 1, length: 1), &o)
343
+
344
+ let diff = CTFontGetDescent(font) - o[0].y
345
+ if diff > 0 {
346
+ translateBy(x: 0, y: diff)
347
+ }
348
+ }
349
+ }
@@ -42,6 +42,7 @@ final class InvertedMatteLayer: CALayer, CompositionLayerDelegate {
42
42
  let wrapperLayer = CALayer()
43
43
 
44
44
  func frameUpdated(frame _: CGFloat) {
45
+ setNeedsDisplay()
45
46
  displayIfNeeded()
46
47
  }
47
48
 
@@ -16,7 +16,6 @@ final class LayerTransformProperties: NodePropertyMap, KeypathSearchable {
16
16
  // MARK: Lifecycle
17
17
 
18
18
  init(transform: Transform) {
19
-
20
19
  anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.anchorPoint.keyframes))
21
20
  scale = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.scale.keyframes))
22
21
  rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotation.keyframes))