lottie-ios 3.4.4 → 4.0.0

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 (183) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/workflows/main.yml +7 -7
  3. package/Gemfile.lock +1 -1
  4. package/Lottie.xcodeproj/project.pbxproj +286 -68
  5. package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +18 -0
  6. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  7. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +3 -24
  8. package/Package.swift +2 -2
  9. package/README.md +10 -3
  10. package/Rakefile +1 -1
  11. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +6 -9
  12. package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +42 -3
  13. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +5 -17
  14. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +25 -17
  15. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +2 -2
  16. package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +1 -1
  17. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +9 -20
  18. package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +39 -25
  19. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +13 -32
  20. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +4 -4
  21. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +13 -13
  22. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +4 -4
  23. package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +4 -12
  24. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +222 -0
  25. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +1 -1
  26. package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +8 -6
  27. package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +13 -10
  28. package/Sources/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift +56 -0
  29. package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -1
  30. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -3
  31. package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +9 -9
  32. package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +9 -3
  33. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +7 -18
  34. package/Sources/Private/CoreAnimation/ValueProviderStore.swift +2 -3
  35. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +5 -5
  36. package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +3 -3
  37. package/Sources/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +2 -2
  38. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +7 -6
  39. package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -3
  40. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +10 -10
  41. package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +7 -0
  42. package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +2 -2
  43. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift +85 -0
  44. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +4 -4
  45. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +11 -12
  46. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +1 -1
  47. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +10 -11
  48. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +1 -1
  49. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +2 -2
  50. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +5 -5
  51. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +3 -3
  52. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +9 -9
  53. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +14 -14
  54. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +2 -2
  55. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +3 -3
  56. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +10 -10
  57. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +14 -14
  58. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +11 -11
  59. package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +1 -1
  60. package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +52 -0
  61. package/Sources/Private/Model/DotLottie/DotLottieConfiguration.swift +15 -0
  62. package/Sources/Private/Model/DotLottie/DotLottieImageProvider.swift +73 -0
  63. package/Sources/Private/Model/DotLottie/DotLottieManifest.swift +53 -0
  64. package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +58 -0
  65. package/Sources/Private/Model/DotLottie/Zip/Data+Compression.swift +134 -0
  66. package/Sources/Private/Model/DotLottie/Zip/Data+Serialization.swift +87 -0
  67. package/Sources/Private/Model/DotLottie/Zip/FileManager+ZIP.swift +130 -0
  68. package/Sources/Private/Model/DotLottie/Zip/ZipArchive.swift +474 -0
  69. package/Sources/Private/Model/DotLottie/Zip/ZipEntry+Serialization.swift +189 -0
  70. package/Sources/Private/Model/DotLottie/Zip/ZipEntry+ZIP64.swift +179 -0
  71. package/Sources/Private/Model/DotLottie/Zip/ZipEntry.swift +227 -0
  72. package/Sources/Private/Model/Extensions/Bundle.swift +26 -0
  73. package/Sources/Private/Model/Keyframes/KeyframeData.swift +12 -12
  74. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +9 -2
  75. package/Sources/Private/Model/Layers/LayerModel.swift +1 -1
  76. package/Sources/Private/Model/Layers/PreCompLayerModel.swift +3 -3
  77. package/Sources/Private/Model/Layers/TextLayerModel.swift +1 -1
  78. package/Sources/Private/Model/Objects/DashPattern.swift +2 -2
  79. package/Sources/Private/Model/Objects/Mask.swift +10 -8
  80. package/Sources/Private/Model/Objects/Transform.swift +39 -35
  81. package/Sources/Private/Model/ShapeItems/Ellipse.swift +6 -6
  82. package/Sources/Private/Model/ShapeItems/Fill.swift +6 -6
  83. package/Sources/Private/Model/ShapeItems/GradientFill.swift +15 -15
  84. package/Sources/Private/Model/ShapeItems/GradientStroke.swift +19 -19
  85. package/Sources/Private/Model/ShapeItems/Rectangle.swift +9 -9
  86. package/Sources/Private/Model/ShapeItems/Repeater.swift +37 -32
  87. package/Sources/Private/Model/ShapeItems/RoundedCorners.swift +47 -0
  88. package/Sources/Private/Model/ShapeItems/ShapeItem.swift +4 -0
  89. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +34 -28
  90. package/Sources/Private/Model/ShapeItems/Star.swift +21 -21
  91. package/Sources/Private/Model/ShapeItems/Stroke.swift +10 -10
  92. package/Sources/Private/Model/ShapeItems/Trim.swift +9 -9
  93. package/Sources/Private/Model/Text/Font.swift +1 -1
  94. package/Sources/Private/Model/Text/TextAnimator.swift +33 -33
  95. package/Sources/Private/Model/Text/TextDocument.swift +8 -8
  96. package/Sources/Private/RootAnimationLayer.swift +4 -4
  97. package/Sources/Private/Utility/Debugging/LayerDebugging.swift +12 -18
  98. package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +2 -2
  99. package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +12 -7
  100. package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +1 -1
  101. package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +4 -4
  102. package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +147 -0
  103. package/Sources/Private/Utility/Primitives/ColorExtension.swift +8 -11
  104. package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +22 -22
  105. package/Sources/{Private/Model/Animation.swift → Public/Animation/LottieAnimation.swift} +8 -8
  106. package/Sources/Public/Animation/{AnimationPublic.swift → LottieAnimationHelpers.swift} +62 -27
  107. package/Sources/Public/Animation/{AnimationView.swift → LottieAnimationView.swift} +122 -26
  108. package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +222 -0
  109. package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +4 -4
  110. package/Sources/Public/AnimationCache/DefaultAnimationCache.swift +54 -0
  111. package/Sources/Public/AnimationCache/LRUAnimationCache.swift +4 -52
  112. package/Sources/Public/AnimationCache/LottieAnimationCache.swift +15 -0
  113. package/Sources/Public/DotLottie/Cache/DotLottieCache.swift +53 -0
  114. package/Sources/Public/DotLottie/Cache/DotLottieCacheProvider.swift +23 -0
  115. package/Sources/Public/DotLottie/DotLottieFile.swift +161 -0
  116. package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +265 -0
  117. package/Sources/Public/DynamicProperties/AnimationKeypath.swift +3 -3
  118. package/Sources/Public/DynamicProperties/AnyValueProvider.swift +2 -2
  119. package/Sources/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +10 -10
  120. package/Sources/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +4 -4
  121. package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +5 -5
  122. package/Sources/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +2 -2
  123. package/Sources/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +2 -2
  124. package/Sources/Public/FontProvider/AnimationFontProvider.swift +1 -1
  125. package/Sources/Public/ImageProvider/AnimationImageProvider.swift +2 -2
  126. package/Sources/Public/Keyframes/Interpolatable.swift +17 -17
  127. package/Sources/Public/Keyframes/Keyframe.swift +10 -10
  128. package/Sources/Public/LottieConfiguration.swift +25 -7
  129. package/Sources/Public/Primitives/{Color.swift → LottieColor.swift} +3 -3
  130. package/Sources/Public/Primitives/Vectors.swift +4 -4
  131. package/Sources/Public/TextProvider/AnimationTextProvider.swift +1 -1
  132. package/Sources/Public/iOS/AnimatedButton.swift +1 -1
  133. package/Sources/Public/iOS/AnimatedControl.swift +6 -6
  134. package/Sources/Public/iOS/AnimatedSwitch.swift +1 -1
  135. package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +8 -8
  136. package/Sources/Public/iOS/{AnimationViewBase.swift → LottieAnimationViewBase.swift} +4 -4
  137. package/Sources/Public/iOS/UIColorExtension.swift +2 -2
  138. package/Sources/Public/macOS/{AnimationViewBase.macOS.swift → LottieAnimationViewBase.macOS.swift} +4 -4
  139. package/Tests/AnimationCacheProviderTests.swift +40 -0
  140. package/Tests/AnimationKeypathTests.swift +20 -13
  141. package/Tests/AnimationViewTests.swift +64 -0
  142. package/Tests/AutomaticEngineTests.swift +11 -2
  143. package/Tests/ParsingTests.swift +4 -2
  144. package/Tests/PerformanceTests.swift +9 -9
  145. package/Tests/SnapshotConfiguration.swift +7 -7
  146. package/Tests/SnapshotTests.swift +57 -27
  147. package/Tests/ValueProvidersTests.swift +9 -6
  148. package/lottie-ios.podspec +4 -4
  149. package/package.json +2 -2
  150. package/script/test-carthage/Cartfile +1 -1
  151. package/script/test-carthage/CarthageTest/ViewController.swift +1 -1
  152. package/script/test-carthage/CarthageTest-macOS/ViewController.swift +1 -1
  153. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +0 -154
  154. package/Sources/Public/Animation/AnimationViewInitializers.swift +0 -109
  155. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -1
  156. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~7IO4FqH8-VUsSfuA0_wMGUgfGdV7MwzpkzjwWbiB50jXZKQRHtU4G0A7ZXTvsR4mDdrWiawpNC_eriOALfZ7Og== +0 -0
  157. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~ClRW5-6rvrgZHHbrPS1VEREaxelpVcKlERPzSa3f2rtFNXdoqATxFCsPge3a_nO4mhhtpmTmbYvyfI-obAu8Qg== +0 -0
  158. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~Jr2dFGcJc1188nMoMha82z9wM99lCLm4MKzhjfVVjIxKeCZVGWGZH3HgJFNkTpozdk5p1u5o91dCiY4-cR1Zhg== +0 -0
  159. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~MBDeCFoahVzzmtSQrVhhy9VMJV6CmcnUkFya_qwe0XsMFscmY2nS8dxrTEYkY16sH68sEH7WVCCzTuW1z1Hocw== +0 -1
  160. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~U4plJajEDM_uSZdglhDyj6gQO63mbeKxYP9X94aIaOtL0yErtfQnGz5SgsqQ0ToSZcJj6Ao9Wx-nesZVwBTRuw== +0 -0
  161. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~UsLY5O-vDMEHEe3bF8XJvkKkYxdsKlIytgJW7zgNuetw53fG3SssfZiiMfbuYnOtvvvYBXTwpbz07V6Czp029Q== +0 -0
  162. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cpg4cb7H0TaehHy4a-xINJMFfBM2_AEHal_0tIX8ymNVJPsjlCysi3-Cad0Ca_SvuGwVM7ONF55OBUuC9YKZvA== +0 -0
  163. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~cuHjdTCuciVumvEpvozxwDj2wAdgWe13bzd1pUAGN45-WOgY0kIid9aUlBX675OnS-xNEc_pyQWo0RO1dKAjcw== +0 -0
  164. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~f_-bfn-KRHHFg39_MtwgBulEAuWH6F05yqGYydXhil6kqZ51eAoRX6tsiqOr0Oa6eL3dK1tcCBD1bWX5orCZhw== +0 -1
  165. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~jdIx7vWS6ej1cqYcbCS4KyZErSMF13ELR95YwClVc98tIXcsglh7KuGvI1gIxEPDtPXQpfC3XijIAGn1quL8Dw== +0 -0
  166. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~lz3e0YeBa8TvMBSSymToh--gc6zznUIdH2jO0AJ4so5OPNdw6wpYmJebhaENGsRoD3beUXvlyD5f7_WeZrzyNQ== +0 -0
  167. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~u_5dWbliYJ__YkyUCDFjdxiFds9M8Epr_RvbU1rIRCbBQdhRJ_TUBXXcL_Qq-wVp4umNLTOzud4OpQItSpO6Rg== +0 -0
  168. package/Tests/Artifacts/LottieTests.xcresult/Data/data.0~v-YGzhC2l_icsAsyp1XAbEWYwxNook-rARAWlVZINioEsgT9LGvhg2oh78nYqoeH78m1fihr5HCcGNfF7SQj0g== +0 -0
  169. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== +0 -0
  170. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~7IO4FqH8-VUsSfuA0_wMGUgfGdV7MwzpkzjwWbiB50jXZKQRHtU4G0A7ZXTvsR4mDdrWiawpNC_eriOALfZ7Og== +0 -0
  171. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~ClRW5-6rvrgZHHbrPS1VEREaxelpVcKlERPzSa3f2rtFNXdoqATxFCsPge3a_nO4mhhtpmTmbYvyfI-obAu8Qg== +0 -0
  172. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~Jr2dFGcJc1188nMoMha82z9wM99lCLm4MKzhjfVVjIxKeCZVGWGZH3HgJFNkTpozdk5p1u5o91dCiY4-cR1Zhg== +0 -0
  173. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~MBDeCFoahVzzmtSQrVhhy9VMJV6CmcnUkFya_qwe0XsMFscmY2nS8dxrTEYkY16sH68sEH7WVCCzTuW1z1Hocw== +0 -0
  174. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~U4plJajEDM_uSZdglhDyj6gQO63mbeKxYP9X94aIaOtL0yErtfQnGz5SgsqQ0ToSZcJj6Ao9Wx-nesZVwBTRuw== +0 -0
  175. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~UsLY5O-vDMEHEe3bF8XJvkKkYxdsKlIytgJW7zgNuetw53fG3SssfZiiMfbuYnOtvvvYBXTwpbz07V6Czp029Q== +0 -0
  176. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cpg4cb7H0TaehHy4a-xINJMFfBM2_AEHal_0tIX8ymNVJPsjlCysi3-Cad0Ca_SvuGwVM7ONF55OBUuC9YKZvA== +0 -0
  177. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~cuHjdTCuciVumvEpvozxwDj2wAdgWe13bzd1pUAGN45-WOgY0kIid9aUlBX675OnS-xNEc_pyQWo0RO1dKAjcw== +0 -0
  178. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~f_-bfn-KRHHFg39_MtwgBulEAuWH6F05yqGYydXhil6kqZ51eAoRX6tsiqOr0Oa6eL3dK1tcCBD1bWX5orCZhw== +0 -0
  179. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~jdIx7vWS6ej1cqYcbCS4KyZErSMF13ELR95YwClVc98tIXcsglh7KuGvI1gIxEPDtPXQpfC3XijIAGn1quL8Dw== +0 -0
  180. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~lz3e0YeBa8TvMBSSymToh--gc6zznUIdH2jO0AJ4so5OPNdw6wpYmJebhaENGsRoD3beUXvlyD5f7_WeZrzyNQ== +0 -0
  181. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~u_5dWbliYJ__YkyUCDFjdxiFds9M8Epr_RvbU1rIRCbBQdhRJ_TUBXXcL_Qq-wVp4umNLTOzud4OpQItSpO6Rg== +0 -0
  182. package/Tests/Artifacts/LottieTests.xcresult/Data/refs.0~v-YGzhC2l_icsAsyp1XAbEWYwxNook-rARAWlVZINioEsgT9LGvhg2oh78nYqoeH78m1fihr5HCcGNfF7SQj0g== +0 -0
  183. package/Tests/Artifacts/LottieTests.xcresult/Info.plist +0 -29
@@ -8,8 +8,8 @@ import QuartzCore
8
8
 
9
9
  /// A `ShapeItem` that represents a stroke
10
10
  protocol StrokeShapeItem: OpacityAnimationModel {
11
- var strokeColor: KeyframeGroup<Color>? { get }
12
- var width: KeyframeGroup<Vector1D> { get }
11
+ var strokeColor: KeyframeGroup<LottieColor>? { get }
12
+ var width: KeyframeGroup<LottieVector1D> { get }
13
13
  var lineCap: LineCap { get }
14
14
  var lineJoin: LineJoin { get }
15
15
  var miterLimit: Double { get }
@@ -19,13 +19,13 @@ protocol StrokeShapeItem: OpacityAnimationModel {
19
19
  // MARK: - Stroke + StrokeShapeItem
20
20
 
21
21
  extension Stroke: StrokeShapeItem {
22
- var strokeColor: KeyframeGroup<Color>? { color }
22
+ var strokeColor: KeyframeGroup<LottieColor>? { color }
23
23
  }
24
24
 
25
25
  // MARK: - GradientStroke + StrokeShapeItem
26
26
 
27
27
  extension GradientStroke: StrokeShapeItem {
28
- var strokeColor: KeyframeGroup<Color>? { nil }
28
+ var strokeColor: KeyframeGroup<LottieColor>? { nil }
29
29
  }
30
30
 
31
31
  // MARK: - CAShapeLayer + StrokeShapeItem
@@ -10,39 +10,39 @@ import QuartzCore
10
10
  /// both transform types to share the same animation implementation.
11
11
  protocol TransformModel {
12
12
  /// The anchor point of the transform.
13
- var anchorPoint: KeyframeGroup<Vector3D> { get }
13
+ var anchorPoint: KeyframeGroup<LottieVector3D> { get }
14
14
 
15
15
  /// The position of the transform. This is nil if the position data was split.
16
- var _position: KeyframeGroup<Vector3D>? { get }
16
+ var _position: KeyframeGroup<LottieVector3D>? { get }
17
17
 
18
18
  /// The positionX of the transform. This is nil if the position property is set.
19
- var _positionX: KeyframeGroup<Vector1D>? { get }
19
+ var _positionX: KeyframeGroup<LottieVector1D>? { get }
20
20
 
21
21
  /// The positionY of the transform. This is nil if the position property is set.
22
- var _positionY: KeyframeGroup<Vector1D>? { get }
22
+ var _positionY: KeyframeGroup<LottieVector1D>? { get }
23
23
 
24
24
  /// The scale of the transform
25
- var scale: KeyframeGroup<Vector3D> { get }
25
+ var scale: KeyframeGroup<LottieVector3D> { get }
26
26
 
27
27
  /// The rotation of the transform. Note: This is single dimensional rotation.
28
- var rotation: KeyframeGroup<Vector1D> { get }
28
+ var rotation: KeyframeGroup<LottieVector1D> { get }
29
29
  }
30
30
 
31
31
  // MARK: - Transform + TransformModel
32
32
 
33
33
  extension Transform: TransformModel {
34
- var _position: KeyframeGroup<Vector3D>? { position }
35
- var _positionX: KeyframeGroup<Vector1D>? { positionX }
36
- var _positionY: KeyframeGroup<Vector1D>? { positionY }
34
+ var _position: KeyframeGroup<LottieVector3D>? { position }
35
+ var _positionX: KeyframeGroup<LottieVector1D>? { positionX }
36
+ var _positionY: KeyframeGroup<LottieVector1D>? { positionY }
37
37
  }
38
38
 
39
39
  // MARK: - ShapeTransform + TransformModel
40
40
 
41
41
  extension ShapeTransform: TransformModel {
42
- var anchorPoint: KeyframeGroup<Vector3D> { anchor }
43
- var _position: KeyframeGroup<Vector3D>? { position }
44
- var _positionX: KeyframeGroup<Vector1D>? { nil }
45
- var _positionY: KeyframeGroup<Vector1D>? { nil }
42
+ var anchorPoint: KeyframeGroup<LottieVector3D> { anchor }
43
+ var _position: KeyframeGroup<LottieVector3D>? { position }
44
+ var _positionX: KeyframeGroup<LottieVector1D>? { nil }
45
+ var _positionY: KeyframeGroup<LottieVector1D>? { nil }
46
46
  }
47
47
 
48
48
  // MARK: - CALayer + TransformModel
@@ -15,7 +15,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
15
15
  /// - This initializer is throwing, but will only throw when using
16
16
  /// `CompatibilityTracker.Mode.abort`.
17
17
  init(
18
- animation: Animation,
18
+ animation: LottieAnimation,
19
19
  imageProvider: AnimationImageProvider,
20
20
  textProvider: AnimationTextProvider,
21
21
  fontProvider: AnimationFontProvider,
@@ -31,7 +31,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
31
31
  compatibilityTracker = CompatibilityTracker(mode: compatibilityTrackerMode, logger: logger)
32
32
  valueProviderStore = ValueProviderStore(logger: logger)
33
33
  super.init()
34
-
34
+ masksToBounds = true
35
35
  setup()
36
36
  try setupChildLayers()
37
37
  }
@@ -156,7 +156,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
156
156
  } catch {
157
157
  if case CompatibilityTracker.Error.encounteredCompatibilityIssue(let compatibilityIssue) = error {
158
158
  // Even though the animation setup failed, we still update the layer's playback state
159
- // so it can be read by the parent `AnimationView` when handling this error
159
+ // so it can be read by the parent `LottieAnimationView` when handling this error
160
160
  currentPlaybackState = pendingAnimationConfiguration.playbackState
161
161
 
162
162
  didSetUpAnimation?([compatibilityIssue])
@@ -187,7 +187,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
187
187
  /// which is also the realtime animation progress of this layer's animation
188
188
  @objc private var animationProgress: CGFloat = 0
189
189
 
190
- private let animation: Animation
190
+ private let animation: LottieAnimation
191
191
  private let valueProviderStore: ValueProviderStore
192
192
  private let compatibilityTracker: CompatibilityTracker
193
193
  private let logger: LottieLogger
@@ -6,17 +6,9 @@
6
6
  extension KeyframeGroup {
7
7
  /// Retrieves the first `Keyframe` from this group,
8
8
  /// and asserts that there are not any extra keyframes that would be ignored
9
- ///
10
- /// - There are several places in Lottie animation definitions where multiple
11
- /// sets of keyframe timings can be provided for properties that have to
12
- /// be applied to a single `CALayer` property (for example, the definition for a
13
- /// `Rectangle` technically lets you animate `size`, `position`, and `cornerRadius`
14
- /// separately, but these all have to be combined into a single `CAKeyframeAnimation`
15
- /// on the `CAShapeLayer.path` property.
16
- ///
17
- /// - In those sorts of cases, we currently choose one one `KeyframeGroup` to provide the
18
- /// timing information, and disallow simultaneous animations on the other properties.
19
- ///
9
+ /// - This should only be used in cases where it's fundamentally not possible to
10
+ /// support animating a given property (e.g. if Core Animation itself doesn't
11
+ /// support the property).
20
12
  func exactlyOneKeyframe(
21
13
  context: CompatibilityTrackerProviding,
22
14
  description: String,
@@ -29,7 +21,7 @@ extension KeyframeGroup {
29
21
  keyframes.count == 1,
30
22
  """
31
23
  The Core Animation rendering engine does not support animating multiple keyframes
32
- for \(description) values (due to limitations of Core Animation `CAKeyframeAnimation`s).
24
+ for \(description) values, due to limitations of Core Animation.
33
25
  """)
34
26
 
35
27
  return keyframes[0].value
@@ -0,0 +1,222 @@
1
+ // Created by Cal Stephens on 1/28/22.
2
+ // Copyright © 2022 Airbnb Inc. All rights reserved.
3
+
4
+ // MARK: - Keyframes
5
+
6
+ enum Keyframes {
7
+
8
+ // MARK: Internal
9
+
10
+ /// Combines the given keyframe groups of `Keyframe<T>`s into a single keyframe group of of `Keyframe<[T]>`s
11
+ /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged
12
+ /// - Otherwise, the keyframes are manually interpolated at each frame in the animation
13
+ static func combined<T>(_ allGroups: [KeyframeGroup<T>]) -> KeyframeGroup<[T]>
14
+ where T: AnyInterpolatable
15
+ {
16
+ Keyframes.combined(allGroups, makeCombinedResult: { untypedValues in
17
+ untypedValues.compactMap { $0 as? T }
18
+ })
19
+ }
20
+
21
+ /// Combines the given keyframe groups of `Keyframe<T>`s into a single keyframe group of of `Keyframe<[T]>`s
22
+ /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged
23
+ /// - Otherwise, the keyframes are manually interpolated at each frame in the animation
24
+ static func combined<T1, T2, CombinedResult>(
25
+ _ k1: KeyframeGroup<T1>,
26
+ _ k2: KeyframeGroup<T2>,
27
+ makeCombinedResult: (T1, T2) -> CombinedResult)
28
+ -> KeyframeGroup<CombinedResult>
29
+ where T1: AnyInterpolatable, T2: AnyInterpolatable
30
+ {
31
+ Keyframes.combined(
32
+ [k1, k2],
33
+ makeCombinedResult: { untypedValues in
34
+ guard
35
+ let t1 = untypedValues[0] as? T1,
36
+ let t2 = untypedValues[1] as? T2
37
+ else { return nil }
38
+
39
+ return makeCombinedResult(t1, t2)
40
+ })
41
+ }
42
+
43
+ /// Combines the given keyframe groups of `Keyframe<T>`s into a single keyframe group of of `Keyframe<[T]>`s
44
+ /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged
45
+ /// - Otherwise, the keyframes are manually interpolated at each frame in the animation
46
+ static func combined<T1, T2, T3, CombinedResult>(
47
+ _ k1: KeyframeGroup<T1>,
48
+ _ k2: KeyframeGroup<T2>,
49
+ _ k3: KeyframeGroup<T3>,
50
+ makeCombinedResult: (T1, T2, T3) -> CombinedResult)
51
+ -> KeyframeGroup<CombinedResult>
52
+ where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable
53
+ {
54
+ Keyframes.combined(
55
+ [k1, k2, k3],
56
+ makeCombinedResult: { untypedValues in
57
+ guard
58
+ let t1 = untypedValues[0] as? T1,
59
+ let t2 = untypedValues[1] as? T2,
60
+ let t3 = untypedValues[2] as? T3
61
+ else { return nil }
62
+
63
+ return makeCombinedResult(t1, t2, t3)
64
+ })
65
+ }
66
+
67
+ /// Combines the given keyframe groups of `Keyframe<T>`s into a single keyframe group of of `Keyframe<[T]>`s
68
+ /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged
69
+ /// - Otherwise, the keyframes are manually interpolated at each frame in the animation
70
+ static func combined<T1, T2, T3, T4, T5, T6, T7, CombinedResult>(
71
+ _ k1: KeyframeGroup<T1>,
72
+ _ k2: KeyframeGroup<T2>,
73
+ _ k3: KeyframeGroup<T3>,
74
+ _ k4: KeyframeGroup<T4>,
75
+ _ k5: KeyframeGroup<T5>,
76
+ _ k6: KeyframeGroup<T6>,
77
+ _ k7: KeyframeGroup<T7>,
78
+ makeCombinedResult: (T1, T2, T3, T4, T5, T6, T7) -> CombinedResult)
79
+ -> KeyframeGroup<CombinedResult>
80
+ where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable, T4: AnyInterpolatable,
81
+ T5: AnyInterpolatable, T6: AnyInterpolatable, T7: AnyInterpolatable
82
+ {
83
+ Keyframes.combined(
84
+ [k1, k2, k3, k4, k5, k6, k7],
85
+ makeCombinedResult: { untypedValues in
86
+ guard
87
+ let t1 = untypedValues[0] as? T1,
88
+ let t2 = untypedValues[1] as? T2,
89
+ let t3 = untypedValues[2] as? T3,
90
+ let t4 = untypedValues[3] as? T4,
91
+ let t5 = untypedValues[4] as? T5,
92
+ let t6 = untypedValues[5] as? T6,
93
+ let t7 = untypedValues[6] as? T7
94
+ else { return nil }
95
+
96
+ return makeCombinedResult(t1, t2, t3, t4, t5, t6, t7)
97
+ })
98
+ }
99
+
100
+ // MARK: Private
101
+
102
+ /// Combines the given `[KeyframeGroup]` of `Keyframe<T>`s into a single `KeyframeGroup` of `Keyframe<CombinedResult>`s
103
+ /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged
104
+ /// - Otherwise, the keyframes are manually interpolated at each frame in the animation
105
+ ///
106
+ /// `makeCombinedResult` is a closure that takes an array of keyframe values (with the exact same length as `AnyKeyframeGroup`),
107
+ /// casts them to the expected type, and combined them into the final resulting keyframe.
108
+ private static func combined<CombinedResult>(
109
+ _ allGroups: [AnyKeyframeGroup],
110
+ makeCombinedResult: ([Any]) -> CombinedResult?)
111
+ -> KeyframeGroup<CombinedResult>
112
+ {
113
+ let untypedGroups = allGroups.map { $0.untyped }
114
+
115
+ // Animations with no timing information (e.g. with just a single keyframe)
116
+ // can be trivially combined with any other set of keyframes, so we don't need
117
+ // to check those.
118
+ let animatingKeyframes = untypedGroups.filter { $0.keyframes.count > 1 }
119
+
120
+ guard
121
+ !allGroups.isEmpty,
122
+ animatingKeyframes.allSatisfy({ $0.hasSameTimingParameters(as: animatingKeyframes[0]) })
123
+ else {
124
+ // If the keyframes don't all share the same timing information,
125
+ // we have to interpolate the value at each individual frame
126
+ return Keyframes.manuallyInterpolated(allGroups, makeCombinedResult: makeCombinedResult)
127
+ }
128
+
129
+ var combinedKeyframes = ContiguousArray<Keyframe<CombinedResult>>()
130
+ let baseKeyframes = (animatingKeyframes.first ?? untypedGroups[0]).keyframes
131
+
132
+ for index in baseKeyframes.indices {
133
+ let baseKeyframe = baseKeyframes[index]
134
+ let untypedValues = untypedGroups.map { $0.valueForCombinedKeyframes(at: index) }
135
+
136
+ if let combinedValue = makeCombinedResult(untypedValues) {
137
+ combinedKeyframes.append(baseKeyframe.withValue(combinedValue))
138
+ } else {
139
+ LottieLogger.shared.assertionFailure("""
140
+ Failed to cast untyped keyframe values to expected type. This is an internal error.
141
+ """)
142
+ }
143
+ }
144
+
145
+ return KeyframeGroup(keyframes: combinedKeyframes)
146
+ }
147
+
148
+ private static func manuallyInterpolated<CombinedResult>(
149
+ _ allGroups: [AnyKeyframeGroup],
150
+ makeCombinedResult: ([Any]) -> CombinedResult?)
151
+ -> KeyframeGroup<CombinedResult>
152
+ {
153
+ let untypedGroups = allGroups.map { $0.untyped }
154
+ let untypedInterpolators = allGroups.map { $0.interpolator }
155
+
156
+ let times = untypedGroups.flatMap { $0.keyframes.map { $0.time } }
157
+
158
+ let minimumTime = times.min() ?? 0
159
+ let maximumTime = times.max() ?? 0
160
+ let animationLocalTimeRange = Int(minimumTime)...Int(maximumTime)
161
+
162
+ let interpolatedKeyframes = animationLocalTimeRange.compactMap { localTime -> Keyframe<CombinedResult>? in
163
+ let interpolatedValues = untypedInterpolators.map { interpolator in
164
+ interpolator.value(frame: AnimationFrameTime(localTime))
165
+ }
166
+
167
+ guard let combinedResult = makeCombinedResult(interpolatedValues) else {
168
+ LottieLogger.shared.assertionFailure("""
169
+ Failed to cast untyped keyframe values to expected type. This is an internal error.
170
+ """)
171
+ return nil
172
+ }
173
+
174
+ return Keyframe(
175
+ value: combinedResult,
176
+ time: AnimationFrameTime(localTime))
177
+ }
178
+
179
+ return KeyframeGroup(keyframes: ContiguousArray(interpolatedKeyframes))
180
+ }
181
+
182
+ }
183
+
184
+ extension KeyframeGroup {
185
+ /// Whether or not all of the keyframes in this `KeyframeGroup` have the same
186
+ /// timing parameters as the corresponding keyframe in the other given `KeyframeGroup`
187
+ func hasSameTimingParameters<T>(as other: KeyframeGroup<T>) -> Bool {
188
+ guard keyframes.count == other.keyframes.count else {
189
+ return false
190
+ }
191
+
192
+ return zip(keyframes, other.keyframes).allSatisfy {
193
+ $0.hasSameTimingParameters(as: $1)
194
+ }
195
+ }
196
+ }
197
+
198
+ extension Keyframe {
199
+ /// Whether or not this keyframe has the same timing parameters as the given keyframe,
200
+ /// excluding `spatialInTangent` and `spatialOutTangent`.
201
+ fileprivate func hasSameTimingParameters<T>(as other: Keyframe<T>) -> Bool {
202
+ time == other.time
203
+ && isHold == other.isHold
204
+ && inTangent == other.inTangent
205
+ && outTangent == other.outTangent
206
+ // We intentionally don't compare spatial in/out tangents,
207
+ // since those values are only used in very specific cases
208
+ // (animating the x/y position of a layer), which aren't ever
209
+ // combined in this way.
210
+ }
211
+ }
212
+
213
+ extension KeyframeGroup {
214
+ /// The value to use for a combined set of keyframes, for the given index
215
+ fileprivate func valueForCombinedKeyframes(at index: Int) -> T {
216
+ if keyframes.count == 1 {
217
+ return keyframes[0].value
218
+ } else {
219
+ return keyframes[index].value
220
+ }
221
+ }
222
+ }
@@ -18,7 +18,7 @@ protocol AnimationLayer: CALayer {
18
18
  // Context describing the timing parameters of the current animation
19
19
  struct LayerAnimationContext {
20
20
  /// The animation being played
21
- let animation: Animation
21
+ let animation: LottieAnimation
22
22
 
23
23
  /// The timing configuration that should be applied to `CAAnimation`s
24
24
  let timingConfiguration: CoreAnimationLayer.CAMediaTimingConfiguration
@@ -15,7 +15,7 @@ extension CALayer {
15
15
  context: LayerContext)
16
16
  throws
17
17
  {
18
- // An `Animation`'s `LayerModel`s are listed from front to back,
18
+ // A `LottieAnimation`'s `LayerModel`s are listed from front to back,
19
19
  // but `CALayer.sublayers` are listed from back to front.
20
20
  // We reverse the layer ordering to match what Core Animation expects.
21
21
  // The final view hierarchy must display the layers in this exact order.
@@ -51,7 +51,7 @@ extension CALayer {
51
51
  }
52
52
 
53
53
  // Create an `AnimationLayer` for each `LayerModel`
54
- for (layerModel, mask) in try layersInZAxisOrder.pairedLayersAndMasks(context: context) {
54
+ for (layerModel, mask) in try layersInZAxisOrder.pairedLayersAndMasks() {
55
55
  guard let layer = try layerModel.makeAnimationLayer(context: context) else {
56
56
  continue
57
57
  }
@@ -106,8 +106,8 @@ extension CALayer {
106
106
  fileprivate func maskLayer(
107
107
  for matteLayerModel: LayerModel,
108
108
  type: MatteType,
109
- context: LayerContext) throws
110
- -> CALayer?
109
+ context: LayerContext)
110
+ throws -> CALayer?
111
111
  {
112
112
  switch type {
113
113
  case .add:
@@ -123,7 +123,9 @@ extension CALayer {
123
123
  // layer being masked, this creates an inverted mask where only areas _outside_
124
124
  // of the mask layer are visible.
125
125
  // https://developer.apple.com/documentation/coregraphics/cgblendmode/xor
126
- let base = BaseAnimationLayer()
126
+ // - The inverted mask is supposed to expand infinitely around the shape,
127
+ // so we use `InfiniteOpaqueAnimationLayer`
128
+ let base = InfiniteOpaqueAnimationLayer()
127
129
  base.backgroundColor = .rgb(0, 0, 0)
128
130
  base.addSublayer(maskLayer)
129
131
  maskLayer.compositingFilter = "xor"
@@ -141,7 +143,7 @@ extension Collection where Element == LayerModel {
141
143
  /// a `LayerModel` to use as its mask, if applicable
142
144
  /// based on the layer's `MatteType` configuration.
143
145
  /// - Assumes the layers are sorted in z-axis order.
144
- fileprivate func pairedLayersAndMasks(context _: LayerContext) throws
146
+ fileprivate func pairedLayersAndMasks() throws
145
147
  -> [(layer: LayerModel, mask: (model: LayerModel, matteType: MatteType)?)]
146
148
  {
147
149
  var layersAndMasks = [(layer: LayerModel, mask: (model: LayerModel, matteType: MatteType)?)]()
@@ -45,8 +45,8 @@ final class GradientRenderLayer: CAGradientLayer {
45
45
  }
46
46
 
47
47
  let pointInBounds = CGPoint(
48
- x: referencePoint.x + gradientPadding,
49
- y: referencePoint.y + gradientPadding)
48
+ x: referencePoint.x + CALayer.veryLargeLayerPadding,
49
+ y: referencePoint.y + CALayer.veryLargeLayerPadding)
50
50
 
51
51
  return CGPoint(
52
52
  x: CGFloat(pointInBounds.x) / bounds.width,
@@ -55,20 +55,14 @@ final class GradientRenderLayer: CAGradientLayer {
55
55
 
56
56
  // MARK: Private
57
57
 
58
- /// Extra padding around the `gradientReferenceBounds` where the gradient is also rendered
59
- /// - This specific value is arbitrary and can be increased if necessary.
60
- /// Theoretically this should be "infinite", to match the behavior of
61
- /// `CGContext.drawLinearGradient` with `[.drawsAfterEndLocation, .drawsBeforeStartLocation]`.
62
- private let gradientPadding: CGFloat = 10_000
63
-
64
58
  private func updateLayout() {
65
59
  anchorPoint = .zero
66
60
 
67
61
  bounds = CGRect(
68
62
  x: gradientReferenceBounds.origin.x,
69
63
  y: gradientReferenceBounds.origin.y,
70
- width: gradientPadding + gradientReferenceBounds.width + gradientPadding,
71
- height: gradientPadding + gradientReferenceBounds.height + gradientPadding)
64
+ width: CALayer.veryLargeLayerPadding + gradientReferenceBounds.width + CALayer.veryLargeLayerPadding,
65
+ height: CALayer.veryLargeLayerPadding + gradientReferenceBounds.height + CALayer.veryLargeLayerPadding)
72
66
 
73
67
  // Align the center of this layer to be at the center point of its parent layer
74
68
  let superlayerSize = superlayer?.frame.size ?? gradientReferenceBounds.size
@@ -92,3 +86,12 @@ extension GradientRenderLayer: CustomLayoutLayer {
92
86
  }
93
87
  }
94
88
  }
89
+
90
+ extension CALayer {
91
+ /// Extra padding to add around layers that should be very large or "infinite" in size.
92
+ /// Examples include `GradientRenderLayer` and `InfiniteOpaqueAnimationLayer`.
93
+ /// - This specific value is arbitrary and can be increased if necessary.
94
+ /// - Theoretically this should be "infinite", to match the behavior of
95
+ /// `CGContext.drawLinearGradient` with `[.drawsAfterEndLocation, .drawsBeforeStartLocation]` etc.
96
+ static let veryLargeLayerPadding: CGFloat = 10_000
97
+ }
@@ -0,0 +1,56 @@
1
+ // Created by Cal Stephens on 10/10/22.
2
+ // Copyright © 2022 Airbnb Inc. All rights reserved.
3
+
4
+ import QuartzCore
5
+
6
+ // MARK: - ExpandedAnimationLayer
7
+
8
+ /// A `BaseAnimationLayer` subclass that renders its background color
9
+ /// as if the layer is infinitely large, without affecting its bounds
10
+ /// or the bounds of its sublayers
11
+ final class InfiniteOpaqueAnimationLayer: BaseAnimationLayer {
12
+
13
+ // MARK: Lifecycle
14
+
15
+ override init() {
16
+ super.init()
17
+ addSublayer(additionalPaddingLayer)
18
+ }
19
+
20
+ required init?(coder _: NSCoder) {
21
+ fatalError("init(coder:) has not been implemented")
22
+ }
23
+
24
+ /// Called by CoreAnimation to create a shadow copy of this layer
25
+ /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
26
+ override init(layer: Any) {
27
+ super.init(layer: layer)
28
+ }
29
+
30
+ // MARK: Internal
31
+
32
+ override func layoutSublayers() {
33
+ super.layoutSublayers()
34
+
35
+ masksToBounds = false
36
+ additionalPaddingLayer.backgroundColor = backgroundColor
37
+
38
+ // Scale `additionalPaddingLayer` to be larger than this layer
39
+ // by `additionalPadding` at each size, and centered at the center
40
+ // of this layer. Since `additionalPadding` is very large, this has
41
+ // the affect of making `additionalPaddingLayer` appear infinite.
42
+ let scaleRatioX = (bounds.width + (CALayer.veryLargeLayerPadding * 2)) / bounds.width
43
+ let scaleRatioY = (bounds.height + (CALayer.veryLargeLayerPadding * 2)) / bounds.height
44
+
45
+ additionalPaddingLayer.transform = CATransform3DScale(
46
+ CATransform3DMakeTranslation(-CALayer.veryLargeLayerPadding, -CALayer.veryLargeLayerPadding, 0),
47
+ scaleRatioX,
48
+ scaleRatioY,
49
+ 1)
50
+ }
51
+
52
+ // MARK: Private
53
+
54
+ private let additionalPaddingLayer = CALayer()
55
+
56
+ }
@@ -7,7 +7,7 @@ import QuartzCore
7
7
 
8
8
  /// Context available when constructing an `AnimationLayer`
9
9
  struct LayerContext {
10
- let animation: Animation
10
+ let animation: LottieAnimation
11
11
  let imageProvider: AnimationImageProvider
12
12
  let textProvider: AnimationTextProvider
13
13
  let fontProvider: AnimationFontProvider
@@ -108,10 +108,9 @@ extension PreCompLayer: CustomLayoutLayer {
108
108
  extension KeyframeInterpolator where ValueType == AnimationFrameTime {
109
109
  /// A `KeyframeInterpolator` for the given `timeRemapping` keyframes
110
110
  static func timeRemapping(
111
- keyframes timeRemappingKeyframes: KeyframeGroup<Vector1D>,
111
+ keyframes timeRemappingKeyframes: KeyframeGroup<LottieVector1D>,
112
112
  context: LayerContext)
113
- throws
114
- -> KeyframeInterpolator<AnimationFrameTime>
113
+ throws -> KeyframeInterpolator<AnimationFrameTime>
115
114
  {
116
115
  try context.logCompatibilityIssue("""
117
116
  The Core Animation rendering engine partially supports time remapping keyframes,
@@ -56,11 +56,11 @@ private struct RepeaterTransform {
56
56
  scale = repeater.scale
57
57
 
58
58
  rotation = repeater.rotation.map { rotation in
59
- Vector1D(rotation.value * Double(index))
59
+ LottieVector1D(rotation.value * Double(index))
60
60
  }
61
61
 
62
62
  position = repeater.position.map { position in
63
- Vector3D(
63
+ LottieVector3D(
64
64
  x: position.x * Double(index),
65
65
  y: position.y * Double(index),
66
66
  z: position.z * Double(index))
@@ -69,17 +69,17 @@ private struct RepeaterTransform {
69
69
 
70
70
  // MARK: Internal
71
71
 
72
- let anchorPoint: KeyframeGroup<Vector3D>
73
- let position: KeyframeGroup<Vector3D>
74
- let rotation: KeyframeGroup<Vector1D>
75
- let scale: KeyframeGroup<Vector3D>
72
+ let anchorPoint: KeyframeGroup<LottieVector3D>
73
+ let position: KeyframeGroup<LottieVector3D>
74
+ let rotation: KeyframeGroup<LottieVector1D>
75
+ let scale: KeyframeGroup<LottieVector3D>
76
76
 
77
77
  }
78
78
 
79
79
  // MARK: TransformModel
80
80
 
81
81
  extension RepeaterTransform: TransformModel {
82
- var _position: KeyframeGroup<Vector3D>? { position }
83
- var _positionX: KeyframeGroup<Vector1D>? { nil }
84
- var _positionY: KeyframeGroup<Vector1D>? { nil }
82
+ var _position: KeyframeGroup<LottieVector3D>? { position }
83
+ var _positionX: KeyframeGroup<LottieVector1D>? { nil }
84
+ var _positionY: KeyframeGroup<LottieVector1D>? { nil }
85
85
  }
@@ -217,7 +217,11 @@ final class ShapeItemLayer: BaseAnimationLayer {
217
217
  """)
218
218
  }
219
219
 
220
- try shapeLayer.addAnimations(for: shape.item, context: context.for(shape), pathMultiplier: trimPathMultiplier ?? 1)
220
+ try shapeLayer.addAnimations(
221
+ for: shape.item,
222
+ context: context.for(shape),
223
+ pathMultiplier: trimPathMultiplier ?? 1,
224
+ roundedCorners: otherItems.first(RoundedCorners.self))
221
225
 
222
226
  if let (fill, context) = otherItems.first(Fill.self, context: context) {
223
227
  try shapeLayer.addAnimations(for: fill, context: context)
@@ -236,7 +240,8 @@ final class ShapeItemLayer: BaseAnimationLayer {
236
240
  try layers.shapeMaskLayer.addAnimations(
237
241
  for: shape.item,
238
242
  context: context.for(shape),
239
- pathMultiplier: 1)
243
+ pathMultiplier: 1,
244
+ roundedCorners: otherItems.first(RoundedCorners.self))
240
245
 
241
246
  if let (gradientFill, context) = otherItems.first(GradientFill.self, context: context) {
242
247
  layers.shapeMaskLayer.fillRule = gradientFill.fillRule.caFillRule
@@ -258,7 +263,8 @@ final class ShapeItemLayer: BaseAnimationLayer {
258
263
  try layers.shapeMaskLayer.addAnimations(
259
264
  for: shape.item,
260
265
  context: context.for(shape),
261
- pathMultiplier: trimPathMultiplier ?? 1)
266
+ pathMultiplier: trimPathMultiplier ?? 1,
267
+ roundedCorners: otherItems.first(RoundedCorners.self))
262
268
 
263
269
  if let (gradientStroke, context) = otherItems.first(GradientStroke.self, context: context) {
264
270
  try layers.gradientColorLayer.addGradientAnimations(for: gradientStroke, type: .rgb, context: context)