lottie-ios 3.2.3 → 3.4.2

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 (434) hide show
  1. package/.github/actions/setup/action.yml +32 -0
  2. package/.github/issue_template.md +6 -23
  3. package/.github/workflows/main.yml +98 -0
  4. package/.github/workflows/stale_issues.yml +17 -0
  5. package/.spi.yml +6 -0
  6. package/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +7 -0
  7. package/.swiftpm/xcode/package.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  8. package/.swiftpm/xcode/package.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  9. package/.swiftpm/xcode/xcuserdata/{brandonwithrow.xcuserdatad → cal.xcuserdatad}/xcschemes/xcschememanagement.plist +25 -15
  10. package/.swiftpm/xcode/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  11. package/Gemfile +4 -0
  12. package/Gemfile.lock +102 -0
  13. package/Lottie.xcodeproj/project.pbxproj +2011 -1972
  14. package/Lottie.xcodeproj/project.xcworkspace/contents.xcworkspacedata +1 -1
  15. package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  16. package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_iOS.xcscheme → Lottie (iOS).xcscheme } +15 -18
  17. package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_tvOS.xcscheme → Lottie (macOS).xcscheme } +5 -18
  18. package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_macOS.xcscheme → Lottie (tvOS).xcscheme } +5 -18
  19. package/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +37 -0
  20. package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +24 -0
  21. package/Lottie.xcworkspace/contents.xcworkspacedata +10 -0
  22. package/Lottie.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  23. package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +34 -0
  24. package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  25. package/{Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad → Lottie.xcworkspace/xcuserdata/cal.xcuserdatad}/xcdebugger/Breakpoints_v2.xcbkptlist +2 -2
  26. package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Expressions.xcexplist +153 -0
  27. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  28. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +22 -0
  29. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +138 -0
  30. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +30 -0
  31. package/Package.swift +5 -15
  32. package/README.md +40 -60
  33. package/Rakefile +160 -0
  34. package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +81 -0
  35. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +447 -0
  36. package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +81 -0
  37. package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +41 -0
  38. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +55 -0
  39. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +210 -0
  40. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +229 -0
  41. package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +52 -0
  42. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +58 -0
  43. package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +257 -0
  44. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +124 -0
  45. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +73 -0
  46. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +205 -0
  47. package/Sources/Private/CoreAnimation/Animations/VisibilityAnimation.swift +37 -0
  48. package/Sources/Private/CoreAnimation/CompatibilityTracker.swift +130 -0
  49. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +497 -0
  50. package/Sources/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +35 -0
  51. package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +37 -0
  52. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +154 -0
  53. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +83 -0
  54. package/Sources/Private/CoreAnimation/Layers/BaseAnimationLayer.swift +33 -0
  55. package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +88 -0
  56. package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +167 -0
  57. package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +94 -0
  58. package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +79 -0
  59. package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +64 -0
  60. package/Sources/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +138 -0
  61. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +140 -0
  62. package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +85 -0
  63. package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +315 -0
  64. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +390 -0
  65. package/Sources/Private/CoreAnimation/Layers/SolidLayer.swift +47 -0
  66. package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +91 -0
  67. package/Sources/Private/CoreAnimation/Layers/TransformLayer.swift +11 -0
  68. package/Sources/Private/CoreAnimation/ValueProviderStore.swift +139 -0
  69. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/CompositionLayer.swift +94 -86
  70. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/ImageCompositionLayer.swift +24 -21
  71. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/MaskContainerLayer.swift +75 -54
  72. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/NullCompositionLayer.swift +5 -5
  73. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/PreCompositionLayer.swift +59 -43
  74. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/ShapeCompositionLayer.swift +22 -20
  75. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/SolidCompositionLayer.swift +26 -17
  76. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/TextCompositionLayer.swift +42 -36
  77. package/{lottie-swift/src/Private/LayerContainers/AnimationContainer.swift → Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift} +200 -140
  78. package/Sources/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +47 -0
  79. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/CompositionLayersInitializer.swift +33 -24
  80. package/{lottie-swift/src/Private/LayerContainers/Utility/TextLayer.swift → Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift} +149 -106
  81. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/InvertedMatteLayer.swift +26 -24
  82. package/Sources/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +41 -0
  83. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/LayerImageProvider.swift +20 -16
  84. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +40 -0
  85. package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/LayerTransformNode.swift +82 -67
  86. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Extensions/ItemsExtension.swift +9 -4
  87. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/NodeProperty.swift +29 -21
  88. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift +16 -10
  89. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift +6 -6
  90. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +5 -5
  91. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +10 -8
  92. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueContainer.swift +25 -21
  93. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +23 -17
  94. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift +22 -17
  95. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +110 -79
  96. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +22 -16
  97. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +19 -15
  98. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +22 -20
  99. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +22 -23
  100. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +247 -0
  101. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +30 -24
  102. package/{lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift → Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift} +93 -66
  103. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +23 -19
  104. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +139 -0
  105. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +170 -0
  106. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +95 -58
  107. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift +42 -29
  108. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +108 -69
  109. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +155 -0
  110. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +51 -37
  111. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +57 -42
  112. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +66 -58
  113. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +169 -0
  114. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +138 -119
  115. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/AnimatorNode.swift +80 -79
  116. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/PathNode.swift +5 -3
  117. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/RenderNode.swift +22 -17
  118. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +27 -24
  119. package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +34 -25
  120. package/Sources/Private/Model/Animation.swift +160 -0
  121. package/Sources/Private/Model/Assets/Asset.swift +43 -0
  122. package/{lottie-swift/src → Sources}/Private/Model/Assets/AssetLibrary.swift +40 -13
  123. package/Sources/Private/Model/Assets/ImageAsset.swift +112 -0
  124. package/{lottie-swift/src → Sources}/Private/Model/Assets/PrecompAsset.swift +20 -10
  125. package/Sources/Private/Model/DictionaryInitializable.swift +67 -0
  126. package/Sources/Private/Model/Extensions/Bundle.swift +34 -0
  127. package/{lottie-swift/src → Sources}/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +8 -4
  128. package/Sources/Private/Model/Keyframes/KeyframeData.swift +113 -0
  129. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +222 -0
  130. package/{lottie-swift/src → Sources}/Private/Model/Layers/ImageLayerModel.swift +21 -11
  131. package/Sources/Private/Model/Layers/LayerModel.swift +228 -0
  132. package/{lottie-swift/src → Sources}/Private/Model/Layers/PreCompLayerModel.swift +39 -22
  133. package/{lottie-swift/src → Sources}/Private/Model/Layers/ShapeLayerModel.swift +23 -12
  134. package/{lottie-swift/src → Sources}/Private/Model/Layers/SolidLayerModel.swift +31 -19
  135. package/{lottie-swift/src → Sources}/Private/Model/Layers/TextLayerModel.swift +33 -19
  136. package/Sources/Private/Model/Objects/DashPattern.swift +44 -0
  137. package/Sources/Private/Model/Objects/Marker.swift +33 -0
  138. package/Sources/Private/Model/Objects/Mask.swift +80 -0
  139. package/Sources/Private/Model/Objects/Transform.swift +179 -0
  140. package/Sources/Private/Model/ShapeItems/Ellipse.swift +74 -0
  141. package/Sources/Private/Model/ShapeItems/Fill.swift +74 -0
  142. package/Sources/Private/Model/ShapeItems/GradientFill.swift +137 -0
  143. package/Sources/Private/Model/ShapeItems/GradientStroke.swift +185 -0
  144. package/Sources/Private/Model/ShapeItems/Group.swift +48 -0
  145. package/{lottie-swift/src → Sources}/Private/Model/ShapeItems/Merge.swift +29 -12
  146. package/Sources/Private/Model/ShapeItems/Rectangle.swift +72 -0
  147. package/Sources/Private/Model/ShapeItems/Repeater.swift +135 -0
  148. package/Sources/Private/Model/ShapeItems/Shape.swift +56 -0
  149. package/Sources/Private/Model/ShapeItems/ShapeItem.swift +163 -0
  150. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +135 -0
  151. package/Sources/Private/Model/ShapeItems/Star.swift +131 -0
  152. package/Sources/Private/Model/ShapeItems/Stroke.swift +101 -0
  153. package/Sources/Private/Model/ShapeItems/Trim.swift +77 -0
  154. package/Sources/Private/Model/Text/Font.swift +61 -0
  155. package/{lottie-swift/src → Sources}/Private/Model/Text/Glyph.swift +63 -39
  156. package/Sources/Private/Model/Text/TextAnimator.swift +164 -0
  157. package/Sources/Private/Model/Text/TextDocument.swift +123 -0
  158. package/Sources/Private/RootAnimationLayer.swift +51 -0
  159. package/{lottie-swift/src → Sources}/Private/Utility/Debugging/AnimatorNodeDebugging.swift +7 -7
  160. package/{lottie-swift/src → Sources}/Private/Utility/Debugging/LayerDebugging.swift +72 -48
  161. package/Sources/Private/Utility/Debugging/TestHelpers.swift +10 -0
  162. package/{lottie-swift/src → Sources}/Private/Utility/Extensions/AnimationKeypathExtension.swift +69 -59
  163. package/Sources/Private/Utility/Extensions/BlendMode+Filter.swift +31 -0
  164. package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +22 -0
  165. package/{lottie-swift/src → Sources}/Private/Utility/Extensions/CGFloatExtensions.swift +70 -67
  166. package/Sources/Private/Utility/Extensions/DataExtension.swift +27 -0
  167. package/Sources/Private/Utility/Extensions/MathKit.swift +450 -0
  168. package/Sources/Private/Utility/Extensions/StringExtensions.swift +38 -0
  169. package/{lottie-swift/src → Sources}/Private/Utility/Helpers/AnimationContext.swift +42 -16
  170. package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +134 -0
  171. package/{lottie-swift/src → Sources}/Private/Utility/Interpolatable/KeyframeExtensions.swift +13 -10
  172. package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +59 -0
  173. package/{lottie-swift/src/Private/NodeRenderSystem/NodeProperties/ValueProviders → Sources/Private/Utility/Interpolatable}/KeyframeInterpolator.swift +125 -108
  174. package/{lottie-swift/src → Sources}/Private/Utility/Primitives/BezierPath.swift +229 -143
  175. package/Sources/Private/Utility/Primitives/CGPointExtension.swift +35 -0
  176. package/{lottie-swift/src → Sources}/Private/Utility/Primitives/ColorExtension.swift +46 -14
  177. package/{lottie-swift/src → Sources}/Private/Utility/Primitives/CompoundBezierPath.swift +58 -49
  178. package/Sources/Private/Utility/Primitives/CurveVertex.swift +184 -0
  179. package/Sources/Private/Utility/Primitives/PathElement.swift +75 -0
  180. package/Sources/Private/Utility/Primitives/UnitBezier.swift +115 -0
  181. package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +341 -0
  182. package/Sources/Public/Animation/AnimationPublic.swift +266 -0
  183. package/Sources/Public/Animation/AnimationView.swift +1335 -0
  184. package/Sources/Public/Animation/AnimationViewInitializers.swift +109 -0
  185. package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +22 -0
  186. package/{lottie-swift/src → Sources}/Public/AnimationCache/LRUAnimationCache.swift +22 -18
  187. package/Sources/Public/DynamicProperties/AnimationKeypath.swift +49 -0
  188. package/Sources/Public/DynamicProperties/AnyValueProvider.swift +132 -0
  189. package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +54 -36
  190. package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +40 -36
  191. package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +123 -0
  192. package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +40 -35
  193. package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +40 -35
  194. package/{lottie-swift/src → Sources}/Public/FontProvider/AnimationFontProvider.swift +15 -8
  195. package/Sources/Public/ImageProvider/AnimationImageProvider.swift +21 -0
  196. package/Sources/Public/Keyframes/Interpolatable.swift +253 -0
  197. package/Sources/Public/Keyframes/Keyframe.swift +92 -0
  198. package/Sources/Public/Logging/LottieLogger.swift +137 -0
  199. package/Sources/Public/LottieConfiguration.swift +143 -0
  200. package/{lottie-swift/src → Sources}/Public/Primitives/AnimationTime.swift +1 -1
  201. package/{lottie-swift/src → Sources}/Public/Primitives/Color.swift +10 -6
  202. package/{lottie-swift/src → Sources}/Public/Primitives/Vectors.swift +13 -12
  203. package/Sources/Public/TextProvider/AnimationTextProvider.swift +53 -0
  204. package/{lottie-swift/src → Sources}/Public/iOS/AnimatedButton.swift +42 -26
  205. package/{lottie-swift/src → Sources}/Public/iOS/AnimatedControl.swift +100 -91
  206. package/{lottie-swift/src → Sources}/Public/iOS/AnimatedSwitch.swift +128 -94
  207. package/{lottie-swift/src → Sources}/Public/iOS/AnimationSubview.swift +3 -3
  208. package/Sources/Public/iOS/AnimationViewBase.swift +78 -0
  209. package/{lottie-swift/src → Sources}/Public/iOS/BundleImageProvider.swift +36 -34
  210. package/{lottie-swift/src → Sources}/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift +4 -0
  211. package/{lottie-swift/src → Sources}/Public/iOS/Compatibility/CompatibleAnimationView.swift +38 -29
  212. package/{lottie-swift/src → Sources}/Public/iOS/FilepathImageProvider.swift +24 -21
  213. package/{lottie-swift/src → Sources}/Public/iOS/UIColorExtension.swift +4 -4
  214. package/{lottie-swift/src/Public/MacOS/AnimationSubview.swift → Sources/Public/macOS/AnimationSubview.macOS.swift} +4 -5
  215. package/{lottie-swift/src/Public/MacOS/LottieView.swift → Sources/Public/macOS/AnimationViewBase.macOS.swift} +58 -50
  216. package/{lottie-swift/src/Public/MacOS/BundleImageProvider.swift → Sources/Public/macOS/BundleImageProvider.macOS.swift} +31 -32
  217. package/Sources/Public/macOS/FilepathImageProvider.macOS.swift +67 -0
  218. package/Tests/AnimationKeypathTests.swift +103 -0
  219. package/Tests/AutomaticEngineTests.swift +57 -0
  220. package/Tests/BundleTests.swift +25 -0
  221. package/Tests/DataURLTests.swift +64 -0
  222. package/Tests/ParsingTests.swift +43 -0
  223. package/Tests/PerformanceTests.swift +214 -0
  224. package/Tests/Samples/9squares_AlBoardman.json +1 -0
  225. package/Tests/Samples/Boat_Loader.json +1 -0
  226. package/Tests/Samples/HamburgerArrow.json +1 -0
  227. package/Tests/Samples/IconTransitions.json +1 -0
  228. package/Tests/Samples/Images/dog.png +0 -0
  229. package/Tests/Samples/Issues/issue_1125.json +1 -0
  230. package/Tests/Samples/Issues/issue_1260.json +1 -0
  231. package/Tests/Samples/Issues/issue_1403.json +1 -0
  232. package/Tests/Samples/Issues/issue_1407.json +1 -0
  233. package/Tests/Samples/Issues/issue_1460.json +1 -0
  234. package/Tests/Samples/Issues/issue_1488.json +1 -0
  235. package/Tests/Samples/Issues/issue_1505.json +1 -0
  236. package/Tests/Samples/Issues/issue_1541.json +1 -0
  237. package/Tests/Samples/Issues/issue_1557.json +1 -0
  238. package/Tests/Samples/Issues/issue_1603.json +1 -0
  239. package/Tests/Samples/Issues/issue_1628.json +1 -0
  240. package/Tests/Samples/Issues/issue_1636.json +1 -0
  241. package/Tests/Samples/Issues/issue_1643.json +1 -0
  242. package/Tests/Samples/Issues/issue_1655.json +1 -0
  243. package/Tests/Samples/Issues/issue_1664.json +1 -0
  244. package/Tests/Samples/Issues/issue_1683.json +1 -0
  245. package/Tests/Samples/Issues/issue_1687.json +1 -0
  246. package/Tests/Samples/Issues/issue_1711.json +1 -0
  247. package/Tests/Samples/Issues/issue_1717.json +1 -0
  248. package/Tests/Samples/Issues/issue_769.json +1 -0
  249. package/Tests/Samples/Issues/issue_885.json +1 -0
  250. package/Tests/Samples/Issues/issue_965.json +1 -0
  251. package/Tests/Samples/Issues/pr_1536.json +1 -0
  252. package/Tests/Samples/Issues/pr_1563.json +8439 -0
  253. package/Tests/Samples/Issues/pr_1592.json +5527 -0
  254. package/Tests/Samples/Issues/pr_1599.json +738 -0
  255. package/Tests/Samples/Issues/pr_1604_1.json +1 -0
  256. package/Tests/Samples/Issues/pr_1604_2.json +1 -0
  257. package/Tests/Samples/Issues/pr_1632_1.json +1 -0
  258. package/Tests/Samples/Issues/pr_1632_2.json +1 -0
  259. package/Tests/Samples/Issues/pr_1686.json +513 -0
  260. package/Tests/Samples/Issues/pr_1698.json +1 -0
  261. package/Tests/Samples/Issues/pr_1699.json +1 -0
  262. package/Tests/Samples/LottieFiles/LICENSE.md +14 -0
  263. package/Tests/Samples/LottieFiles/bounce_strokes.json +1 -0
  264. package/Tests/Samples/LottieFiles/cactus.json +1 -0
  265. package/Tests/Samples/LottieFiles/dog_car_ride.json +1 -0
  266. package/Tests/Samples/LottieFiles/draft_icon.json +1 -0
  267. package/Tests/Samples/LottieFiles/fireworks.json +1 -0
  268. package/Tests/Samples/LottieFiles/gradient_1.json +1 -0
  269. package/Tests/Samples/LottieFiles/gradient_2.json +1 -0
  270. package/Tests/Samples/LottieFiles/gradient_pill.json +1 -0
  271. package/Tests/Samples/LottieFiles/gradient_shapes.json +1 -0
  272. package/Tests/Samples/LottieFiles/gradient_square.json +1 -0
  273. package/Tests/Samples/LottieFiles/growth.json +1 -0
  274. package/Tests/Samples/LottieFiles/infinity_loader.json +1 -0
  275. package/Tests/Samples/LottieFiles/loading_dots_1.json +1 -0
  276. package/Tests/Samples/LottieFiles/loading_dots_2.json +1 -0
  277. package/Tests/Samples/LottieFiles/loading_dots_3.json +1 -0
  278. package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +1 -0
  279. package/Tests/Samples/LottieFiles/settings_slider.json +1 -0
  280. package/Tests/Samples/LottieFiles/shop.json +1 -0
  281. package/Tests/Samples/LottieFiles/step_loader.json +1 -0
  282. package/Tests/Samples/LottieLogo1.json +1 -0
  283. package/Tests/Samples/LottieLogo1_masked.json +1 -0
  284. package/Tests/Samples/LottieLogo2.json +1 -0
  285. package/Tests/Samples/MotionCorpse_Jrcanest.json +1 -0
  286. package/Tests/Samples/Nonanimating/BasicLayers.json +1 -0
  287. package/Tests/Samples/Nonanimating/DisableNodesTest.json +1 -0
  288. package/Tests/Samples/Nonanimating/FirstText.json +1 -0
  289. package/Tests/Samples/Nonanimating/GeometryTransformTest.json +1 -0
  290. package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +1 -0
  291. package/Tests/Samples/Nonanimating/Text_Glyph.json +1 -0
  292. package/Tests/Samples/Nonanimating/Text_NoAnimation.json +1 -0
  293. package/Tests/Samples/Nonanimating/Text_NoGlyph.json +1 -0
  294. package/Tests/Samples/Nonanimating/Zoom.json +1 -0
  295. package/Tests/Samples/Nonanimating/_dog.json +1 -0
  296. package/Tests/Samples/Nonanimating/base64Test.json +1 -0
  297. package/Tests/Samples/Nonanimating/blend_mode_test.json +1 -0
  298. package/Tests/Samples/Nonanimating/keypathTest.json +1 -0
  299. package/Tests/Samples/Nonanimating/verifyLineHeight.json +1 -0
  300. package/Tests/Samples/PinJump.json +1 -0
  301. package/Tests/Samples/Switch.json +1 -0
  302. package/Tests/Samples/Switch_States.json +1 -0
  303. package/Tests/Samples/TwitterHeart.json +1 -0
  304. package/Tests/Samples/TwitterHeartButton.json +1 -0
  305. package/Tests/Samples/TypeFace/A.json +1 -0
  306. package/Tests/Samples/TypeFace/Apostrophe.json +1 -0
  307. package/Tests/Samples/TypeFace/B.json +1 -0
  308. package/Tests/Samples/TypeFace/BlinkingCursor.json +1 -0
  309. package/Tests/Samples/TypeFace/C.json +1 -0
  310. package/Tests/Samples/TypeFace/Colon.json +1 -0
  311. package/Tests/Samples/TypeFace/Comma.json +1 -0
  312. package/Tests/Samples/TypeFace/D.json +1 -0
  313. package/Tests/Samples/TypeFace/E.json +1 -0
  314. package/Tests/Samples/TypeFace/F.json +1 -0
  315. package/Tests/Samples/TypeFace/G.json +1 -0
  316. package/Tests/Samples/TypeFace/H.json +1 -0
  317. package/Tests/Samples/TypeFace/I.json +1 -0
  318. package/Tests/Samples/TypeFace/J.json +1 -0
  319. package/Tests/Samples/TypeFace/K.json +1 -0
  320. package/Tests/Samples/TypeFace/L.json +1 -0
  321. package/Tests/Samples/TypeFace/M.json +1 -0
  322. package/Tests/Samples/TypeFace/N.json +1 -0
  323. package/Tests/Samples/TypeFace/O.json +1 -0
  324. package/Tests/Samples/TypeFace/P.json +1 -0
  325. package/Tests/Samples/TypeFace/Q.json +1 -0
  326. package/Tests/Samples/TypeFace/R.json +1 -0
  327. package/Tests/Samples/TypeFace/S.json +1 -0
  328. package/Tests/Samples/TypeFace/T.json +1 -0
  329. package/Tests/Samples/TypeFace/U.json +1 -0
  330. package/Tests/Samples/TypeFace/V.json +1 -0
  331. package/Tests/Samples/TypeFace/W.json +1 -0
  332. package/Tests/Samples/TypeFace/X.json +1 -0
  333. package/Tests/Samples/TypeFace/Y.json +1 -0
  334. package/Tests/Samples/TypeFace/Z.json +1 -0
  335. package/Tests/Samples/Watermelon.json +1 -0
  336. package/Tests/Samples/setValueTest.json +1 -0
  337. package/Tests/Samples/timeremap.json +1 -0
  338. package/Tests/Samples/vcTransition1.json +1 -0
  339. package/Tests/Samples/vcTransition2.json +1 -0
  340. package/Tests/SnapshotConfiguration.swift +158 -0
  341. package/Tests/SnapshotTests.swift +265 -0
  342. package/Tests/Utils/Bundle+Module.swift +30 -0
  343. package/Tests/Utils/HardcodedFontProvider.swift +19 -0
  344. package/Tests/Utils/HardcodedImageProvider.swift +23 -0
  345. package/Tests/Utils/Snapshotting+presentationLayer.swift +47 -0
  346. package/Tests/ValueProvidersTests.swift +27 -0
  347. package/lottie-ios.podspec +12 -12
  348. package/package.json +1 -1
  349. package/script/test-carthage/Cartfile +1 -0
  350. package/script/test-carthage/Cartfile.resolved +1 -0
  351. package/script/test-carthage/CarthageTest/AppDelegate.swift +26 -0
  352. package/script/test-carthage/CarthageTest/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  353. package/script/test-carthage/CarthageTest/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
  354. package/script/test-carthage/CarthageTest/Assets.xcassets/Contents.json +6 -0
  355. package/script/test-carthage/CarthageTest/Base.lproj/LaunchScreen.storyboard +25 -0
  356. package/script/test-carthage/CarthageTest/Base.lproj/Main.storyboard +24 -0
  357. package/script/test-carthage/CarthageTest/Info.plist +66 -0
  358. package/script/test-carthage/CarthageTest/SceneDelegate.swift +10 -0
  359. package/script/test-carthage/CarthageTest/ViewController.swift +15 -0
  360. package/script/test-carthage/CarthageTest-macOS/AppDelegate.swift +7 -0
  361. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  362. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
  363. package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/Contents.json +6 -0
  364. package/script/test-carthage/CarthageTest-macOS/Base.lproj/Main.storyboard +717 -0
  365. package/script/test-carthage/CarthageTest-macOS/CarthageTest_macOS.entitlements +10 -0
  366. package/script/test-carthage/CarthageTest-macOS/ViewController.swift +15 -0
  367. package/script/test-carthage/CarthageTest.xcodeproj/project.pbxproj +532 -0
  368. package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  369. package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  370. package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  371. package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  372. package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  373. package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  374. package/script/test-carthage/Mintfile +1 -0
  375. package/script/test-spm/LottieSPM.xcworkspace/contents.xcworkspacedata +7 -0
  376. package/script/test-spm/LottieSPM.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  377. package/script/test-spm/Mintfile +1 -0
  378. package/.swiftpm/xcode/package.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  379. package/Lottie/Info.plist +0 -22
  380. package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  381. package/Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad/xcschemes/LottieLibraryMacOS.xcscheme +0 -80
  382. package/Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad/xcschemes/xcschememanagement.plist +0 -57
  383. package/lottie-swift/Assets/.gitkeep +0 -0
  384. package/lottie-swift/src/Private/LayerContainers/Utility/LayerFontProvider.swift +0 -37
  385. package/lottie-swift/src/Private/LayerContainers/Utility/LayerTextProvider.swift +0 -36
  386. package/lottie-swift/src/Private/Model/Animation.swift +0 -107
  387. package/lottie-swift/src/Private/Model/Assets/Asset.swift +0 -27
  388. package/lottie-swift/src/Private/Model/Assets/ImageAsset.swift +0 -48
  389. package/lottie-swift/src/Private/Model/Keyframes/Keyframe.swift +0 -128
  390. package/lottie-swift/src/Private/Model/Keyframes/KeyframeGroup.swift +0 -108
  391. package/lottie-swift/src/Private/Model/Layers/LayerModel.swift +0 -150
  392. package/lottie-swift/src/Private/Model/Objects/DashPattern.swift +0 -24
  393. package/lottie-swift/src/Private/Model/Objects/Marker.swift +0 -23
  394. package/lottie-swift/src/Private/Model/Objects/Mask.swift +0 -48
  395. package/lottie-swift/src/Private/Model/Objects/Transform.swift +0 -105
  396. package/lottie-swift/src/Private/Model/ShapeItems/Ellipse.swift +0 -50
  397. package/lottie-swift/src/Private/Model/ShapeItems/FillI.swift +0 -49
  398. package/lottie-swift/src/Private/Model/ShapeItems/GradientFill.swift +0 -86
  399. package/lottie-swift/src/Private/Model/ShapeItems/GradientStroke.swift +0 -125
  400. package/lottie-swift/src/Private/Model/ShapeItems/Group.swift +0 -32
  401. package/lottie-swift/src/Private/Model/ShapeItems/Rectangle.swift +0 -50
  402. package/lottie-swift/src/Private/Model/ShapeItems/Repeater.swift +0 -80
  403. package/lottie-swift/src/Private/Model/ShapeItems/Shape.swift +0 -37
  404. package/lottie-swift/src/Private/Model/ShapeItems/ShapeItem.swift +0 -95
  405. package/lottie-swift/src/Private/Model/ShapeItems/ShapeTransform.swift +0 -68
  406. package/lottie-swift/src/Private/Model/ShapeItems/Star.swift +0 -86
  407. package/lottie-swift/src/Private/Model/ShapeItems/Stroke.swift +0 -67
  408. package/lottie-swift/src/Private/Model/ShapeItems/Trim.swift +0 -53
  409. package/lottie-swift/src/Private/Model/Text/Font.swift +0 -35
  410. package/lottie-swift/src/Private/Model/Text/TextAnimator.swift +0 -99
  411. package/lottie-swift/src/Private/Model/Text/TextDocument.swift +0 -70
  412. package/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +0 -109
  413. package/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +0 -132
  414. package/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +0 -141
  415. package/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +0 -127
  416. package/lottie-swift/src/Private/Utility/Extensions/MathKit.swift +0 -539
  417. package/lottie-swift/src/Private/Utility/Extensions/StringExtensions.swift +0 -32
  418. package/lottie-swift/src/Private/Utility/Interpolatable/Interpolatable.swift +0 -18
  419. package/lottie-swift/src/Private/Utility/Interpolatable/InterpolatableExtensions.swift +0 -170
  420. package/lottie-swift/src/Private/Utility/Primitives/CurveVertex.swift +0 -177
  421. package/lottie-swift/src/Private/Utility/Primitives/PathElement.swift +0 -68
  422. package/lottie-swift/src/Private/Utility/Primitives/VectorsExtensions.swift +0 -218
  423. package/lottie-swift/src/Public/Animation/AnimationPublic.swift +0 -196
  424. package/lottie-swift/src/Public/Animation/AnimationView.swift +0 -1006
  425. package/lottie-swift/src/Public/Animation/AnimationViewInitializers.swift +0 -83
  426. package/lottie-swift/src/Public/AnimationCache/AnimationCacheProvider.swift +0 -24
  427. package/lottie-swift/src/Public/DynamicProperties/AnimationKeypath.swift +0 -46
  428. package/lottie-swift/src/Public/DynamicProperties/AnyValueProvider.swift +0 -29
  429. package/lottie-swift/src/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +0 -114
  430. package/lottie-swift/src/Public/ImageProvider/AnimationImageProvider.swift +0 -23
  431. package/lottie-swift/src/Public/MacOS/FilepathImageProvider.swift +0 -67
  432. package/lottie-swift/src/Public/TextProvider/AnimationTextProvider.swift +0 -39
  433. package/lottie-swift/src/Public/iOS/LottieView.swift +0 -62
  434. package/lottie-swift-testing.podspec +0 -32
@@ -0,0 +1,47 @@
1
+ // Created by Cal Stephens on 12/13/21.
2
+ // Copyright © 2021 Airbnb Inc. All rights reserved.
3
+
4
+ import QuartzCore
5
+
6
+ // MARK: - SolidLayer
7
+
8
+ final class SolidLayer: BaseCompositionLayer {
9
+
10
+ // MARK: Lifecycle
11
+
12
+ init(_ solidLayer: SolidLayerModel) {
13
+ self.solidLayer = solidLayer
14
+ super.init(layerModel: solidLayer)
15
+ setupContentLayer()
16
+ }
17
+
18
+ required init?(coder _: NSCoder) {
19
+ fatalError("init(coder:) has not been implemented")
20
+ }
21
+
22
+ /// Called by CoreAnimation to create a shadow copy of this layer
23
+ /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
24
+ override init(layer: Any) {
25
+ guard let typedLayer = layer as? Self else {
26
+ fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
27
+ }
28
+
29
+ solidLayer = typedLayer.solidLayer
30
+ super.init(layer: typedLayer)
31
+ }
32
+
33
+ // MARK: Private
34
+
35
+ private let solidLayer: SolidLayerModel
36
+
37
+ private func setupContentLayer() {
38
+ // Render the fill color in a child `CAShapeLayer`
39
+ // - Using a `CAShapeLayer` specifically, instead of a `CALayer` with a `backgroundColor`,
40
+ // allows the size of the fill shape to be different from `contentsLayer.size`.
41
+ let shapeLayer = CAShapeLayer()
42
+ shapeLayer.fillColor = solidLayer.colorHex.cgColor
43
+ shapeLayer.path = CGPath(rect: .init(x: 0, y: 0, width: solidLayer.width, height: solidLayer.height), transform: nil)
44
+ addSublayer(shapeLayer)
45
+ }
46
+
47
+ }
@@ -0,0 +1,91 @@
1
+ // Created by Cal Stephens on 2/9/22.
2
+ // Copyright © 2022 Airbnb Inc. All rights reserved.
3
+
4
+ import QuartzCore
5
+
6
+ /// The `CALayer` type responsible for rendering `TextLayer`s
7
+ final class TextLayer: BaseCompositionLayer {
8
+
9
+ // MARK: Lifecycle
10
+
11
+ init(
12
+ textLayerModel: TextLayerModel,
13
+ context: LayerContext)
14
+ throws
15
+ {
16
+ self.textLayerModel = textLayerModel
17
+ super.init(layerModel: textLayerModel)
18
+ setupSublayers()
19
+ try configureRenderLayer(with: context)
20
+ }
21
+
22
+ required init?(coder _: NSCoder) {
23
+ fatalError("init(coder:) has not been implemented")
24
+ }
25
+
26
+ /// Called by CoreAnimation to create a shadow copy of this layer
27
+ /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
28
+ override init(layer: Any) {
29
+ guard let typedLayer = layer as? Self else {
30
+ fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
31
+ }
32
+
33
+ textLayerModel = typedLayer.textLayerModel
34
+ super.init(layer: typedLayer)
35
+ }
36
+
37
+ // MARK: Internal
38
+
39
+ func configureRenderLayer(with context: LayerContext) throws {
40
+ // We can't use `CATextLayer`, because it doesn't support enough features we use.
41
+ // Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation)
42
+ // used by the Main Thread rendering engine. This means the Core Animation engine can't
43
+ // _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")
45
+
46
+ // The Core Animation engine doesn't currently support `TextAnimator`s.
47
+ // - We could add support for animating the transform-related properties without much trouble.
48
+ // - We may be able to support animating `fillColor` by getting clever with layer blend modes
49
+ // or masks (e.g. use `CoreTextRenderLayer` to draw black glyphs, and then fill them in
50
+ // using a `CAShapeLayer`).
51
+ if !textLayerModel.animators.isEmpty {
52
+ try context.logCompatibilityIssue("""
53
+ The Core Animation rendering engine currently doesn't support text animators.
54
+ """)
55
+ }
56
+
57
+ renderLayer.text = text.text
58
+ renderLayer.font = context.fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
59
+
60
+ renderLayer.alignment = text.justification.textAlignment
61
+ renderLayer.lineHeight = CGFloat(text.lineHeight)
62
+ renderLayer.tracking = (CGFloat(text.fontSize) * CGFloat(text.tracking)) / 1000
63
+
64
+ renderLayer.fillColor = text.fillColorData?.cgColorValue
65
+ renderLayer.strokeColor = text.strokeColorData?.cgColorValue
66
+ renderLayer.strokeWidth = CGFloat(text.strokeWidth ?? 0)
67
+ renderLayer.strokeOnTop = text.strokeOverFill ?? false
68
+
69
+ renderLayer.preferredSize = text.textFrameSize?.sizeValue
70
+ renderLayer.sizeToFit()
71
+
72
+ renderLayer.transform = CATransform3DIdentity
73
+ renderLayer.position = text.textFramePosition?.pointValue ?? .zero
74
+ }
75
+
76
+ // MARK: Private
77
+
78
+ private let textLayerModel: TextLayerModel
79
+ private let renderLayer = CoreTextRenderLayer()
80
+
81
+ private func setupSublayers() {
82
+ // Place the text render layer in an additional container
83
+ // - Direct sublayers of a `BaseCompositionLayer` always fill the bounds
84
+ // of their superlayer -- so this container will be the bounds of self,
85
+ // and the text render layer can be positioned anywhere.
86
+ let textContainerLayer = CALayer()
87
+ textContainerLayer.addSublayer(renderLayer)
88
+ addSublayer(textContainerLayer)
89
+ }
90
+
91
+ }
@@ -0,0 +1,11 @@
1
+ // Created by Cal Stephens on 12/21/21.
2
+ // Copyright © 2021 Airbnb Inc. All rights reserved.
3
+
4
+ /// The CALayer type responsible for only rendering the `transform` of a `LayerModel`
5
+ final class TransformLayer: BaseCompositionLayer {
6
+
7
+ /// `TransformLayer`s don't render any visible content,
8
+ /// they just `transform` their sublayers
9
+ override var renderLayerContents: Bool { false }
10
+
11
+ }
@@ -0,0 +1,139 @@
1
+ // Created by Cal Stephens on 1/13/22.
2
+ // Copyright © 2022 Airbnb Inc. All rights reserved.
3
+
4
+ import QuartzCore
5
+
6
+ // MARK: - ValueProviderStore
7
+
8
+ /// Registration and storage for `AnyValueProvider`s that can dynamically
9
+ /// provide custom values for `AnimationKeypath`s within an `Animation`.
10
+ final class ValueProviderStore {
11
+
12
+ // MARK: Lifecycle
13
+
14
+ init(logger: LottieLogger) {
15
+ self.logger = logger
16
+ }
17
+
18
+ // MARK: Internal
19
+
20
+ /// Registers an `AnyValueProvider` for the given `AnimationKeypath`
21
+ func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) {
22
+ logger.assert(
23
+ valueProvider.typeErasedStorage.isSupportedByCoreAnimationRenderingEngine,
24
+ """
25
+ The Core Animation rendering engine doesn't support Value Providers that vend a closure,
26
+ because that would require calling the closure on the main thread once per frame.
27
+ """)
28
+
29
+ // TODO: Support more value types
30
+ logger.assert(
31
+ keypath.keys.last == PropertyName.color.rawValue,
32
+ "The Core Animation rendering engine currently only supports customizing color values")
33
+
34
+ valueProviders.append((keypath: keypath, valueProvider: valueProvider))
35
+ }
36
+
37
+ // Retrieves the custom value keyframes for the given property,
38
+ // if an `AnyValueProvider` was registered for the given keypath.
39
+ func customKeyframes<Value>(
40
+ of customizableProperty: CustomizableProperty<Value>,
41
+ for keypath: AnimationKeypath,
42
+ context: LayerAnimationContext)
43
+ throws
44
+ -> KeyframeGroup<Value>?
45
+ {
46
+ if context.logHierarchyKeypaths {
47
+ context.logger.info(keypath.fullPath)
48
+ }
49
+
50
+ guard let anyValueProvider = valueProvider(for: keypath) else {
51
+ return nil
52
+ }
53
+
54
+ // Retrieve the type-erased keyframes from the custom `ValueProvider`
55
+ let typeErasedKeyframes: [Keyframe<Any>]
56
+ switch anyValueProvider.typeErasedStorage {
57
+ case .singleValue(let typeErasedValue):
58
+ typeErasedKeyframes = [Keyframe(typeErasedValue)]
59
+
60
+ case .keyframes(let keyframes, _):
61
+ typeErasedKeyframes = keyframes
62
+
63
+ case .closure:
64
+ try context.logCompatibilityIssue("""
65
+ The Core Animation rendering engine doesn't support Value Providers that vend a closure,
66
+ because that would require calling the closure on the main thread once per frame.
67
+ """)
68
+ return nil
69
+ }
70
+
71
+ // Convert the type-erased keyframe values using this `CustomizableProperty`'s conversion closure
72
+ let typedKeyframes = typeErasedKeyframes.compactMap { typeErasedKeyframe -> Keyframe<Value>? in
73
+ guard let convertedValue = customizableProperty.conversion(typeErasedKeyframe.value) else {
74
+ logger.assertionFailure("""
75
+ Could not convert value of type \(type(of: typeErasedKeyframe.value)) to expected type \(Value.self)
76
+ """)
77
+ return nil
78
+ }
79
+
80
+ return typeErasedKeyframe.withValue(convertedValue)
81
+ }
82
+
83
+ // Verify that all of the keyframes were successfully converted to the expected type
84
+ guard typedKeyframes.count == typeErasedKeyframes.count else {
85
+ return nil
86
+ }
87
+
88
+ return KeyframeGroup(keyframes: ContiguousArray(typedKeyframes))
89
+ }
90
+
91
+ // MARK: Private
92
+
93
+ private let logger: LottieLogger
94
+
95
+ private var valueProviders = [(keypath: AnimationKeypath, valueProvider: AnyValueProvider)]()
96
+
97
+ /// Retrieves the most-recently-registered Value Provider that matches the given keypat
98
+ private func valueProvider(for keypath: AnimationKeypath) -> AnyValueProvider? {
99
+ // Find the last keypath matching the given keypath,
100
+ // so we return the value provider that was registered most-recently
101
+ valueProviders.last(where: { registeredKeypath, _ in
102
+ keypath.matches(registeredKeypath)
103
+ })?.valueProvider
104
+ }
105
+
106
+ }
107
+
108
+ extension AnyValueProviderStorage {
109
+ /// Whether or not this type of value provider is supported
110
+ /// by the new Core Animation rendering engine
111
+ var isSupportedByCoreAnimationRenderingEngine: Bool {
112
+ switch self {
113
+ case .singleValue, .keyframes:
114
+ return true
115
+ case .closure:
116
+ return false
117
+ }
118
+ }
119
+ }
120
+
121
+ extension AnimationKeypath {
122
+ /// Whether or not this keypath from the animation hierarchy
123
+ /// matches the given keypath (which may contain wildcards)
124
+ func matches(_ keypath: AnimationKeypath) -> Bool {
125
+ var regex = "^" // match the start of the string
126
+ + keypath.keys.joined(separator: "\\.") // match this keypath, escaping "." characters
127
+ + "$" // match the end of the string
128
+
129
+ // ** wildcards match anything
130
+ // - "**.Color" matches both "Layer 1.Color" and "Layer 1.Layer 2.Color"
131
+ regex = regex.replacingOccurrences(of: "**", with: ".+")
132
+
133
+ // * wildcards match any individual path component
134
+ // - "*.Color" matches "Layer 1.Color" but not "Layer 1.Layer 2.Color"
135
+ regex = regex.replacingOccurrences(of: "*", with: "[^.]+")
136
+
137
+ return fullPath.range(of: regex, options: .regularExpression) != nil
138
+ }
139
+ }
@@ -8,70 +8,37 @@
8
8
  import Foundation
9
9
  import QuartzCore
10
10
 
11
- /**
12
- The base class for a child layer of CompositionContainer
13
- */
11
+ // MARK: - CompositionLayer
12
+
13
+ /// The base class for a child layer of CompositionContainer
14
14
  class CompositionLayer: CALayer, KeypathSearchable {
15
-
16
- weak var layerDelegate: CompositionLayerDelegate?
17
-
18
- let transformNode: LayerTransformNode
19
-
20
- let contentsLayer: CALayer = CALayer()
21
-
22
- let maskLayer: MaskContainerLayer?
23
-
24
- let matteType: MatteType?
25
-
26
- var renderScale: CGFloat = 1 {
27
- didSet {
28
- self.updateRenderScale()
29
- }
30
- }
31
-
32
- var matteLayer: CompositionLayer? {
33
- didSet {
34
- if let matte = matteLayer {
35
- if let type = matteType, type == .invert {
36
- mask = InvertedMatteLayer(inputMatte: matte)
37
- } else {
38
- mask = matte
39
- }
40
- } else {
41
- mask = nil
42
- }
43
- }
44
- }
45
-
46
- let inFrame: CGFloat
47
- let outFrame: CGFloat
48
- let startFrame: CGFloat
49
- let timeStretch: CGFloat
50
-
15
+
16
+ // MARK: Lifecycle
17
+
51
18
  init(layer: LayerModel, size: CGSize) {
52
- self.transformNode = LayerTransformNode(transform: layer.transform)
53
- if let masks = layer.masks {
19
+ transformNode = LayerTransformNode(transform: layer.transform)
20
+ if let masks = layer.masks?.filter({ $0.mode != .none }), !masks.isEmpty {
54
21
  maskLayer = MaskContainerLayer(masks: masks)
55
22
  } else {
56
23
  maskLayer = nil
57
24
  }
58
- self.matteType = layer.matte
59
- self.inFrame = layer.inFrame.cgFloat
60
- self.outFrame = layer.outFrame.cgFloat
61
- self.timeStretch = layer.timeStretch.cgFloat
62
- self.startFrame = layer.startTime.cgFloat
63
- self.keypathName = layer.name
64
- self.childKeypaths = [transformNode.transformProperties]
25
+ matteType = layer.matte
26
+ inFrame = layer.inFrame.cgFloat
27
+ outFrame = layer.outFrame.cgFloat
28
+ timeStretch = layer.timeStretch.cgFloat
29
+ startFrame = layer.startTime.cgFloat
30
+ keypathName = layer.name
31
+ childKeypaths = [transformNode.transformProperties]
65
32
  super.init()
66
- self.anchorPoint = .zero
67
- self.actions = [
33
+ anchorPoint = .zero
34
+ actions = [
68
35
  "opacity" : NSNull(),
69
36
  "transform" : NSNull(),
70
37
  "bounds" : NSNull(),
71
38
  "anchorPoint" : NSNull(),
72
- "sublayerTransform" : NSNull()
39
+ "sublayerTransform" : NSNull(),
73
40
  ]
74
-
41
+
75
42
  contentsLayer.anchorPoint = .zero
76
43
  contentsLayer.bounds = CGRect(origin: .zero, size: size)
77
44
  contentsLayer.actions = [
@@ -80,36 +47,90 @@ class CompositionLayer: CALayer, KeypathSearchable {
80
47
  "bounds" : NSNull(),
81
48
  "anchorPoint" : NSNull(),
82
49
  "sublayerTransform" : NSNull(),
83
- "hidden" : NSNull()
50
+ "hidden" : NSNull(),
84
51
  ]
52
+ compositingFilter = layer.blendMode.filterName
85
53
  addSublayer(contentsLayer)
86
-
54
+
87
55
  if let maskLayer = maskLayer {
88
56
  contentsLayer.mask = maskLayer
89
57
  }
58
+
59
+ name = layer.name
90
60
  }
91
-
61
+
92
62
  override init(layer: Any) {
93
63
  /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
94
64
  guard let layer = layer as? CompositionLayer else {
95
65
  fatalError("Wrong Layer Class")
96
66
  }
97
- self.transformNode = layer.transformNode
98
- self.matteType = layer.matteType
99
- self.inFrame = layer.inFrame
100
- self.outFrame = layer.outFrame
101
- self.timeStretch = layer.timeStretch
102
- self.startFrame = layer.startFrame
103
- self.keypathName = layer.keypathName
104
- self.childKeypaths = [transformNode.transformProperties]
105
- self.maskLayer = nil
67
+ transformNode = layer.transformNode
68
+ matteType = layer.matteType
69
+ inFrame = layer.inFrame
70
+ outFrame = layer.outFrame
71
+ timeStretch = layer.timeStretch
72
+ startFrame = layer.startFrame
73
+ keypathName = layer.keypathName
74
+ childKeypaths = [transformNode.transformProperties]
75
+ maskLayer = nil
106
76
  super.init(layer: layer)
107
77
  }
108
-
109
- required init?(coder aDecoder: NSCoder) {
78
+
79
+ required init?(coder _: NSCoder) {
110
80
  fatalError("init(coder:) has not been implemented")
111
81
  }
112
-
82
+
83
+ // MARK: Internal
84
+
85
+ weak var layerDelegate: CompositionLayerDelegate?
86
+
87
+ let transformNode: LayerTransformNode
88
+
89
+ let contentsLayer = CALayer()
90
+
91
+ let maskLayer: MaskContainerLayer?
92
+
93
+ let matteType: MatteType?
94
+
95
+ let inFrame: CGFloat
96
+ let outFrame: CGFloat
97
+ let startFrame: CGFloat
98
+ let timeStretch: CGFloat
99
+
100
+ // MARK: Keypath Searchable
101
+
102
+ let keypathName: String
103
+
104
+ final var childKeypaths: [KeypathSearchable]
105
+
106
+ var renderScale: CGFloat = 1 {
107
+ didSet {
108
+ updateRenderScale()
109
+ }
110
+ }
111
+
112
+ var matteLayer: CompositionLayer? {
113
+ didSet {
114
+ if let matte = matteLayer {
115
+ if let type = matteType, type == .invert {
116
+ mask = InvertedMatteLayer(inputMatte: matte)
117
+ } else {
118
+ mask = matte
119
+ }
120
+ } else {
121
+ mask = nil
122
+ }
123
+ }
124
+ }
125
+
126
+ var keypathProperties: [String: AnyNodeProperty] {
127
+ [:]
128
+ }
129
+
130
+ var keypathLayer: CALayer? {
131
+ contentsLayer
132
+ }
133
+
113
134
  final func displayWithFrame(frame: CGFloat, forceUpdates: Bool) {
114
135
  transformNode.updateTree(frame, forceUpdates: forceUpdates)
115
136
  let layerVisible = frame.isInRangeOrEqual(inFrame, outFrame)
@@ -123,31 +144,18 @@ class CompositionLayer: CALayer, KeypathSearchable {
123
144
  contentsLayer.isHidden = !layerVisible
124
145
  layerDelegate?.frameUpdated(frame: frame)
125
146
  }
126
-
127
- func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
147
+
148
+ func displayContentsWithFrame(frame _: CGFloat, forceUpdates _: Bool) {
128
149
  /// To be overridden by subclass
129
150
  }
130
-
131
- // MARK: Keypath Searchable
132
-
133
- let keypathName: String
134
-
135
- var keypathProperties: [String : AnyNodeProperty] {
136
- return [:]
137
- }
138
-
139
- final var childKeypaths: [KeypathSearchable]
140
-
141
- var keypathLayer: CALayer? {
142
- return contentsLayer
143
- }
144
-
151
+
145
152
  func updateRenderScale() {
146
- /// To be overridden by subclass
153
+ contentsScale = renderScale
147
154
  }
148
155
  }
149
156
 
157
+ // MARK: - CompositionLayerDelegate
158
+
150
159
  protocol CompositionLayerDelegate: AnyObject {
151
160
  func frameUpdated(frame: CGFloat)
152
161
  }
153
-
@@ -5,43 +5,46 @@
5
5
  // Created by Brandon Withrow on 1/25/19.
6
6
  //
7
7
 
8
- import Foundation
9
8
  import CoreGraphics
9
+ import Foundation
10
10
  import QuartzCore
11
11
 
12
12
  final class ImageCompositionLayer: CompositionLayer {
13
-
14
- var image: CGImage? = nil {
15
- didSet {
16
- if let image = image {
17
- contentsLayer.contents = image
18
- } else {
19
- contentsLayer.contents = nil
20
- }
21
- }
22
- }
23
-
24
- let imageReferenceID: String
25
-
13
+
14
+ // MARK: Lifecycle
15
+
26
16
  init(imageLayer: ImageLayerModel, size: CGSize) {
27
- self.imageReferenceID = imageLayer.referenceID
17
+ imageReferenceID = imageLayer.referenceID
28
18
  super.init(layer: imageLayer, size: size)
29
19
  contentsLayer.masksToBounds = true
30
20
  contentsLayer.contentsGravity = CALayerContentsGravity.resize
31
21
  }
32
-
22
+
33
23
  override init(layer: Any) {
34
24
  /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
35
25
  guard let layer = layer as? ImageCompositionLayer else {
36
26
  fatalError("init(layer:) Wrong Layer Class")
37
27
  }
38
- self.imageReferenceID = layer.imageReferenceID
39
- self.image = nil
28
+ imageReferenceID = layer.imageReferenceID
29
+ image = nil
40
30
  super.init(layer: layer)
41
31
  }
42
-
43
- required init?(coder aDecoder: NSCoder) {
32
+
33
+ required init?(coder _: NSCoder) {
44
34
  fatalError("init(coder:) has not been implemented")
45
35
  }
46
-
36
+
37
+ // MARK: Internal
38
+
39
+ let imageReferenceID: String
40
+
41
+ var image: CGImage? = nil {
42
+ didSet {
43
+ if let image = image {
44
+ contentsLayer.contents = image
45
+ } else {
46
+ contentsLayer.contents = nil
47
+ }
48
+ }
49
+ }
47
50
  }