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,179 @@
1
+ //
2
+ // Transform.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/7/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ /// The animatable transform for a layer. Controls position, rotation, scale, and opacity.
11
+ final class Transform: Codable, DictionaryInitializable {
12
+
13
+ // MARK: Lifecycle
14
+
15
+ required init(from decoder: Decoder) throws {
16
+ /// This manual override of decode is required because we want to throw an error
17
+ /// in the case that there is not position data.
18
+ let container = try decoder.container(keyedBy: Transform.CodingKeys.self)
19
+
20
+ // AnchorPoint
21
+ anchorPoint = try container
22
+ .decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .anchorPoint) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
23
+
24
+ // Position
25
+ if container.contains(.positionX), container.contains(.positionY) {
26
+ // Position dimensions are split into two keyframe groups
27
+ positionX = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .positionX)
28
+ positionY = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .positionY)
29
+ position = nil
30
+ } else if let positionKeyframes = try? container.decode(KeyframeGroup<Vector3D>.self, forKey: .position) {
31
+ // Position dimensions are a single keyframe group.
32
+ position = positionKeyframes
33
+ positionX = nil
34
+ positionY = nil
35
+ } else if
36
+ let positionContainer = try? container.nestedContainer(keyedBy: PositionCodingKeys.self, forKey: .position),
37
+ let positionX = try? positionContainer.decode(KeyframeGroup<Vector1D>.self, forKey: .positionX),
38
+ let positionY = try? positionContainer.decode(KeyframeGroup<Vector1D>.self, forKey: .positionY)
39
+ {
40
+ /// Position keyframes are split and nested.
41
+ self.positionX = positionX
42
+ self.positionY = positionY
43
+ position = nil
44
+ } else {
45
+ /// Default value.
46
+ position = KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
47
+ positionX = nil
48
+ positionY = nil
49
+ }
50
+
51
+ // Scale
52
+ scale = try container
53
+ .decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
54
+
55
+ // Rotation
56
+ if let rotationZ = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotationZ) {
57
+ rotation = rotationZ
58
+ } else {
59
+ rotation = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
60
+ }
61
+ rotationZ = nil
62
+
63
+ // Opacity
64
+ opacity = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
65
+ }
66
+
67
+ init(dictionary: [String: Any]) throws {
68
+ if
69
+ let anchorPointDictionary = dictionary[CodingKeys.anchorPoint.rawValue] as? [String: Any],
70
+ let anchorPoint = try? KeyframeGroup<Vector3D>(dictionary: anchorPointDictionary)
71
+ {
72
+ self.anchorPoint = anchorPoint
73
+ } else {
74
+ anchorPoint = KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
75
+ }
76
+
77
+ if
78
+ let xDictionary = dictionary[CodingKeys.positionX.rawValue] as? [String: Any],
79
+ let yDictionary = dictionary[CodingKeys.positionY.rawValue] as? [String: Any]
80
+ {
81
+ positionX = try KeyframeGroup<Vector1D>(dictionary: xDictionary)
82
+ positionY = try KeyframeGroup<Vector1D>(dictionary: yDictionary)
83
+ position = nil
84
+ } else if
85
+ let positionDictionary = dictionary[CodingKeys.position.rawValue] as? [String: Any],
86
+ positionDictionary[KeyframeGroup<Vector3D>.KeyframeWrapperKey.keyframeData.rawValue] != nil
87
+ {
88
+ position = try KeyframeGroup<Vector3D>(dictionary: positionDictionary)
89
+ positionX = nil
90
+ positionY = nil
91
+ } else if
92
+ let positionDictionary = dictionary[CodingKeys.position.rawValue] as? [String: Any],
93
+ let xDictionary = positionDictionary[PositionCodingKeys.positionX.rawValue] as? [String: Any],
94
+ let yDictionary = positionDictionary[PositionCodingKeys.positionY.rawValue] as? [String: Any]
95
+ {
96
+ positionX = try KeyframeGroup<Vector1D>(dictionary: xDictionary)
97
+ positionY = try KeyframeGroup<Vector1D>(dictionary: yDictionary)
98
+ position = nil
99
+ } else {
100
+ position = KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
101
+ positionX = nil
102
+ positionY = nil
103
+ }
104
+
105
+ if
106
+ let scaleDictionary = dictionary[CodingKeys.scale.rawValue] as? [String: Any],
107
+ let scale = try? KeyframeGroup<Vector3D>(dictionary: scaleDictionary)
108
+ {
109
+ self.scale = scale
110
+ } else {
111
+ scale = KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
112
+ }
113
+ if
114
+ let rotationDictionary = dictionary[CodingKeys.rotationZ.rawValue] as? [String: Any],
115
+ let rotation = try? KeyframeGroup<Vector1D>(dictionary: rotationDictionary)
116
+ {
117
+ self.rotation = rotation
118
+ } else if
119
+ let rotationDictionary = dictionary[CodingKeys.rotation.rawValue] as? [String: Any],
120
+ let rotation = try? KeyframeGroup<Vector1D>(dictionary: rotationDictionary)
121
+ {
122
+ self.rotation = rotation
123
+ } else {
124
+ rotation = KeyframeGroup(Vector1D(0))
125
+ }
126
+ rotationZ = nil
127
+ if
128
+ let opacityDictionary = dictionary[CodingKeys.opacity.rawValue] as? [String: Any],
129
+ let opacity = try? KeyframeGroup<Vector1D>(dictionary: opacityDictionary)
130
+ {
131
+ self.opacity = opacity
132
+ } else {
133
+ opacity = KeyframeGroup(Vector1D(100))
134
+ }
135
+ }
136
+
137
+ // MARK: Internal
138
+
139
+ enum CodingKeys: String, CodingKey {
140
+ case anchorPoint = "a"
141
+ case position = "p"
142
+ case positionX = "px"
143
+ case positionY = "py"
144
+ case scale = "s"
145
+ case rotation = "r"
146
+ case rotationZ = "rz"
147
+ case opacity = "o"
148
+ }
149
+
150
+ enum PositionCodingKeys: String, CodingKey {
151
+ case split = "s"
152
+ case positionX = "x"
153
+ case positionY = "y"
154
+ }
155
+
156
+ /// The anchor point of the transform.
157
+ let anchorPoint: KeyframeGroup<Vector3D>
158
+
159
+ /// The position of the transform. This is nil if the position data was split.
160
+ let position: KeyframeGroup<Vector3D>?
161
+
162
+ /// The positionX of the transform. This is nil if the position property is set.
163
+ let positionX: KeyframeGroup<Vector1D>?
164
+
165
+ /// The positionY of the transform. This is nil if the position property is set.
166
+ let positionY: KeyframeGroup<Vector1D>?
167
+
168
+ /// The scale of the transform
169
+ let scale: KeyframeGroup<Vector3D>
170
+
171
+ /// The rotation of the transform. Note: This is single dimensional rotation.
172
+ let rotation: KeyframeGroup<Vector1D>
173
+
174
+ /// The opacity of the transform.
175
+ let opacity: KeyframeGroup<Vector1D>
176
+
177
+ /// Should always be nil.
178
+ let rotationZ: KeyframeGroup<Vector1D>?
179
+ }
@@ -0,0 +1,74 @@
1
+ //
2
+ // EllipseItem.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/8/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ // MARK: - PathDirection
11
+
12
+ enum PathDirection: Int, Codable {
13
+ case clockwise = 1
14
+ case userSetClockwise = 2
15
+ case counterClockwise = 3
16
+ }
17
+
18
+ // MARK: - Ellipse
19
+
20
+ final class Ellipse: ShapeItem {
21
+
22
+ // MARK: Lifecycle
23
+
24
+ required init(from decoder: Decoder) throws {
25
+ let container = try decoder.container(keyedBy: Ellipse.CodingKeys.self)
26
+ direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
27
+ position = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .position)
28
+ size = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .size)
29
+ try super.init(from: decoder)
30
+ }
31
+
32
+ required init(dictionary: [String: Any]) throws {
33
+ if
34
+ let directionRawType = dictionary[CodingKeys.direction.rawValue] as? Int,
35
+ let direction = PathDirection(rawValue: directionRawType)
36
+ {
37
+ self.direction = direction
38
+ } else {
39
+ direction = .clockwise
40
+ }
41
+ let positionDictionary: [String: Any] = try dictionary.value(for: CodingKeys.position)
42
+ position = try KeyframeGroup<Vector3D>(dictionary: positionDictionary)
43
+ let sizeDictionary: [String: Any] = try dictionary.value(for: CodingKeys.size)
44
+ size = try KeyframeGroup<Vector3D>(dictionary: sizeDictionary)
45
+ try super.init(dictionary: dictionary)
46
+ }
47
+
48
+ // MARK: Internal
49
+
50
+ /// The direction of the ellipse.
51
+ let direction: PathDirection
52
+
53
+ /// The position of the ellipse
54
+ let position: KeyframeGroup<Vector3D>
55
+
56
+ /// The size of the ellipse
57
+ let size: KeyframeGroup<Vector3D>
58
+
59
+ override func encode(to encoder: Encoder) throws {
60
+ try super.encode(to: encoder)
61
+ var container = encoder.container(keyedBy: CodingKeys.self)
62
+ try container.encode(direction, forKey: .direction)
63
+ try container.encode(position, forKey: .position)
64
+ try container.encode(size, forKey: .size)
65
+ }
66
+
67
+ // MARK: Private
68
+
69
+ private enum CodingKeys: String, CodingKey {
70
+ case direction = "d"
71
+ case position = "p"
72
+ case size = "s"
73
+ }
74
+ }
@@ -0,0 +1,74 @@
1
+ //
2
+ // FillShape.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/8/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ // MARK: - FillRule
11
+
12
+ enum FillRule: Int, Codable {
13
+ case none
14
+ case nonZeroWinding
15
+ case evenOdd
16
+ }
17
+
18
+ // MARK: - Fill
19
+
20
+ final class Fill: ShapeItem {
21
+
22
+ // MARK: Lifecycle
23
+
24
+ required init(from decoder: Decoder) throws {
25
+ let container = try decoder.container(keyedBy: Fill.CodingKeys.self)
26
+ opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
27
+ color = try container.decode(KeyframeGroup<Color>.self, forKey: .color)
28
+ fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding
29
+ try super.init(from: decoder)
30
+ }
31
+
32
+ required init(dictionary: [String: Any]) throws {
33
+ let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity)
34
+ opacity = try KeyframeGroup<Vector1D>(dictionary: opacityDictionary)
35
+ let colorDictionary: [String: Any] = try dictionary.value(for: CodingKeys.color)
36
+ color = try KeyframeGroup<Color>(dictionary: colorDictionary)
37
+ if
38
+ let fillRuleRawValue = dictionary[CodingKeys.fillRule.rawValue] as? Int,
39
+ let fillRule = FillRule(rawValue: fillRuleRawValue)
40
+ {
41
+ self.fillRule = fillRule
42
+ } else {
43
+ fillRule = .nonZeroWinding
44
+ }
45
+ try super.init(dictionary: dictionary)
46
+ }
47
+
48
+ // MARK: Internal
49
+
50
+ /// The opacity of the fill
51
+ let opacity: KeyframeGroup<Vector1D>
52
+
53
+ /// The color keyframes for the fill
54
+ let color: KeyframeGroup<Color>
55
+
56
+ /// The fill rule to use when filling a path
57
+ let fillRule: FillRule
58
+
59
+ override func encode(to encoder: Encoder) throws {
60
+ try super.encode(to: encoder)
61
+ var container = encoder.container(keyedBy: CodingKeys.self)
62
+ try container.encode(opacity, forKey: .opacity)
63
+ try container.encode(color, forKey: .color)
64
+ try container.encode(fillRule, forKey: .fillRule)
65
+ }
66
+
67
+ // MARK: Private
68
+
69
+ private enum CodingKeys: String, CodingKey {
70
+ case opacity = "o"
71
+ case color = "c"
72
+ case fillRule = "r"
73
+ }
74
+ }
@@ -0,0 +1,137 @@
1
+ //
2
+ // GradientFill.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/8/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ // MARK: - GradientType
11
+
12
+ enum GradientType: Int, Codable {
13
+ case none
14
+ case linear
15
+ case radial
16
+ }
17
+
18
+ // MARK: - GradientFill
19
+
20
+ final class GradientFill: ShapeItem {
21
+
22
+ // MARK: Lifecycle
23
+
24
+ required init(from decoder: Decoder) throws {
25
+ let container = try decoder.container(keyedBy: GradientFill.CodingKeys.self)
26
+ opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
27
+ startPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .startPoint)
28
+ endPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .endPoint)
29
+ gradientType = try container.decode(GradientType.self, forKey: .gradientType)
30
+ highlightLength = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightLength)
31
+ highlightAngle = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightAngle)
32
+ fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding
33
+ let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
34
+ colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors)
35
+ numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors)
36
+ try super.init(from: decoder)
37
+ }
38
+
39
+ required init(dictionary: [String: Any]) throws {
40
+ let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity)
41
+ opacity = try KeyframeGroup<Vector1D>(dictionary: opacityDictionary)
42
+ let startPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.startPoint)
43
+ startPoint = try KeyframeGroup<Vector3D>(dictionary: startPointDictionary)
44
+ let endPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.endPoint)
45
+ endPoint = try KeyframeGroup<Vector3D>(dictionary: endPointDictionary)
46
+ let gradientRawType: Int = try dictionary.value(for: CodingKeys.gradientType)
47
+ guard let gradient = GradientType(rawValue: gradientRawType) else {
48
+ throw InitializableError.invalidInput
49
+ }
50
+ gradientType = gradient
51
+ if let highlightLengthDictionary = dictionary[CodingKeys.highlightLength.rawValue] as? [String: Any] {
52
+ highlightLength = try? KeyframeGroup<Vector1D>(dictionary: highlightLengthDictionary)
53
+ } else {
54
+ highlightLength = nil
55
+ }
56
+ if let highlightAngleDictionary = dictionary[CodingKeys.highlightAngle.rawValue] as? [String: Any] {
57
+ highlightAngle = try? KeyframeGroup<Vector1D>(dictionary: highlightAngleDictionary)
58
+ } else {
59
+ highlightAngle = nil
60
+ }
61
+ let colorsDictionary: [String: Any] = try dictionary.value(for: CodingKeys.colors)
62
+ let nestedColorsDictionary: [String: Any] = try colorsDictionary.value(for: GradientDataKeys.colors)
63
+ colors = try KeyframeGroup<[Double]>(dictionary: nestedColorsDictionary)
64
+ numberOfColors = try colorsDictionary.value(for: GradientDataKeys.numberOfColors)
65
+ if
66
+ let fillRuleRawValue = dictionary[CodingKeys.fillRule.rawValue] as? Int,
67
+ let fillRule = FillRule(rawValue: fillRuleRawValue)
68
+ {
69
+ self.fillRule = fillRule
70
+ } else {
71
+ fillRule = .nonZeroWinding
72
+ }
73
+ try super.init(dictionary: dictionary)
74
+ }
75
+
76
+ // MARK: Internal
77
+
78
+ /// The opacity of the fill
79
+ let opacity: KeyframeGroup<Vector1D>
80
+
81
+ /// The start of the gradient
82
+ let startPoint: KeyframeGroup<Vector3D>
83
+
84
+ /// The end of the gradient
85
+ let endPoint: KeyframeGroup<Vector3D>
86
+
87
+ /// The type of gradient
88
+ let gradientType: GradientType
89
+
90
+ /// Gradient Highlight Length. Only if type is Radial
91
+ let highlightLength: KeyframeGroup<Vector1D>?
92
+
93
+ /// Highlight Angle. Only if type is Radial
94
+ let highlightAngle: KeyframeGroup<Vector1D>?
95
+
96
+ /// The number of color points in the gradient
97
+ let numberOfColors: Int
98
+
99
+ /// The Colors of the gradient.
100
+ let colors: KeyframeGroup<[Double]>
101
+
102
+ /// The fill rule to use when filling a path
103
+ let fillRule: FillRule
104
+
105
+ override func encode(to encoder: Encoder) throws {
106
+ try super.encode(to: encoder)
107
+ var container = encoder.container(keyedBy: CodingKeys.self)
108
+ try container.encode(opacity, forKey: .opacity)
109
+ try container.encode(startPoint, forKey: .startPoint)
110
+ try container.encode(endPoint, forKey: .endPoint)
111
+ try container.encode(gradientType, forKey: .gradientType)
112
+ try container.encodeIfPresent(highlightLength, forKey: .highlightLength)
113
+ try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle)
114
+ try container.encodeIfPresent(fillRule, forKey: .fillRule)
115
+ var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
116
+ try colorsContainer.encode(numberOfColors, forKey: .numberOfColors)
117
+ try colorsContainer.encode(colors, forKey: .colors)
118
+ }
119
+
120
+ // MARK: Private
121
+
122
+ private enum CodingKeys: String, CodingKey {
123
+ case opacity = "o"
124
+ case startPoint = "s"
125
+ case endPoint = "e"
126
+ case gradientType = "t"
127
+ case highlightLength = "h"
128
+ case highlightAngle = "a"
129
+ case colors = "g"
130
+ case fillRule = "r"
131
+ }
132
+
133
+ private enum GradientDataKeys: String, CodingKey {
134
+ case numberOfColors = "p"
135
+ case colors = "k"
136
+ }
137
+ }
@@ -0,0 +1,185 @@
1
+ //
2
+ // GradientStroke.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/8/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ // MARK: - LineCap
11
+
12
+ enum LineCap: Int, Codable {
13
+ case none
14
+ case butt
15
+ case round
16
+ case square
17
+ }
18
+
19
+ // MARK: - LineJoin
20
+
21
+ enum LineJoin: Int, Codable {
22
+ case none
23
+ case miter
24
+ case round
25
+ case bevel
26
+ }
27
+
28
+ // MARK: - GradientStroke
29
+
30
+ final class GradientStroke: ShapeItem {
31
+
32
+ // MARK: Lifecycle
33
+
34
+ required init(from decoder: Decoder) throws {
35
+ let container = try decoder.container(keyedBy: GradientStroke.CodingKeys.self)
36
+ opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
37
+ startPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .startPoint)
38
+ endPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .endPoint)
39
+ gradientType = try container.decode(GradientType.self, forKey: .gradientType)
40
+ highlightLength = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightLength)
41
+ highlightAngle = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightAngle)
42
+ width = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .width)
43
+ lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round
44
+ lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round
45
+ miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4
46
+ // TODO Decode Color Objects instead of array.
47
+ let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
48
+ colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors)
49
+ numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors)
50
+ dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern)
51
+ try super.init(from: decoder)
52
+ }
53
+
54
+ required init(dictionary: [String: Any]) throws {
55
+ let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity)
56
+ opacity = try KeyframeGroup<Vector1D>(dictionary: opacityDictionary)
57
+ let startPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.startPoint)
58
+ startPoint = try KeyframeGroup<Vector3D>(dictionary: startPointDictionary)
59
+ let endPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.endPoint)
60
+ endPoint = try KeyframeGroup<Vector3D>(dictionary: endPointDictionary)
61
+ let gradientRawType: Int = try dictionary.value(for: CodingKeys.gradientType)
62
+ guard let gradient = GradientType(rawValue: gradientRawType) else {
63
+ throw InitializableError.invalidInput
64
+ }
65
+ gradientType = gradient
66
+ if let highlightLengthDictionary = dictionary[CodingKeys.highlightLength.rawValue] as? [String: Any] {
67
+ highlightLength = try? KeyframeGroup<Vector1D>(dictionary: highlightLengthDictionary)
68
+ } else {
69
+ highlightLength = nil
70
+ }
71
+ if let highlightAngleDictionary = dictionary[CodingKeys.highlightAngle.rawValue] as? [String: Any] {
72
+ highlightAngle = try? KeyframeGroup<Vector1D>(dictionary: highlightAngleDictionary)
73
+ } else {
74
+ highlightAngle = nil
75
+ }
76
+ let widthDictionary: [String: Any] = try dictionary.value(for: CodingKeys.width)
77
+ width = try KeyframeGroup<Vector1D>(dictionary: widthDictionary)
78
+ if
79
+ let lineCapRawValue = dictionary[CodingKeys.lineCap.rawValue] as? Int,
80
+ let lineCap = LineCap(rawValue: lineCapRawValue)
81
+ {
82
+ self.lineCap = lineCap
83
+ } else {
84
+ lineCap = .round
85
+ }
86
+ if
87
+ let lineJoinRawValue = dictionary[CodingKeys.lineJoin.rawValue] as? Int,
88
+ let lineJoin = LineJoin(rawValue: lineJoinRawValue)
89
+ {
90
+ self.lineJoin = lineJoin
91
+ } else {
92
+ lineJoin = .round
93
+ }
94
+ miterLimit = (try? dictionary.value(for: CodingKeys.miterLimit)) ?? 4
95
+ let colorsDictionary: [String: Any] = try dictionary.value(for: CodingKeys.colors)
96
+ let nestedColorsDictionary: [String: Any] = try colorsDictionary.value(for: GradientDataKeys.colors)
97
+ colors = try KeyframeGroup<[Double]>(dictionary: nestedColorsDictionary)
98
+ numberOfColors = try colorsDictionary.value(for: GradientDataKeys.numberOfColors)
99
+ let dashPatternDictionaries = dictionary[CodingKeys.dashPattern.rawValue] as? [[String: Any]]
100
+ dashPattern = try? dashPatternDictionaries?.map({ try DashElement(dictionary: $0) })
101
+ try super.init(dictionary: dictionary)
102
+ }
103
+
104
+ // MARK: Internal
105
+
106
+ /// The opacity of the fill
107
+ let opacity: KeyframeGroup<Vector1D>
108
+
109
+ /// The start of the gradient
110
+ let startPoint: KeyframeGroup<Vector3D>
111
+
112
+ /// The end of the gradient
113
+ let endPoint: KeyframeGroup<Vector3D>
114
+
115
+ /// The type of gradient
116
+ let gradientType: GradientType
117
+
118
+ /// Gradient Highlight Length. Only if type is Radial
119
+ let highlightLength: KeyframeGroup<Vector1D>?
120
+
121
+ /// Highlight Angle. Only if type is Radial
122
+ let highlightAngle: KeyframeGroup<Vector1D>?
123
+
124
+ /// The number of color points in the gradient
125
+ let numberOfColors: Int
126
+
127
+ /// The Colors of the gradient.
128
+ let colors: KeyframeGroup<[Double]>
129
+
130
+ /// The width of the stroke
131
+ let width: KeyframeGroup<Vector1D>
132
+
133
+ /// Line Cap
134
+ let lineCap: LineCap
135
+
136
+ /// Line Join
137
+ let lineJoin: LineJoin
138
+
139
+ /// Miter Limit
140
+ let miterLimit: Double
141
+
142
+ /// The dash pattern of the stroke
143
+ let dashPattern: [DashElement]?
144
+
145
+ override func encode(to encoder: Encoder) throws {
146
+ try super.encode(to: encoder)
147
+ var container = encoder.container(keyedBy: CodingKeys.self)
148
+ try container.encode(opacity, forKey: .opacity)
149
+ try container.encode(startPoint, forKey: .startPoint)
150
+ try container.encode(endPoint, forKey: .endPoint)
151
+ try container.encode(gradientType, forKey: .gradientType)
152
+ try container.encodeIfPresent(highlightLength, forKey: .highlightLength)
153
+ try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle)
154
+ try container.encode(width, forKey: .width)
155
+ try container.encode(lineCap, forKey: .lineCap)
156
+ try container.encode(lineJoin, forKey: .lineJoin)
157
+ try container.encode(miterLimit, forKey: .miterLimit)
158
+ var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
159
+ try colorsContainer.encode(numberOfColors, forKey: .numberOfColors)
160
+ try colorsContainer.encode(colors, forKey: .colors)
161
+ try container.encodeIfPresent(dashPattern, forKey: .dashPattern)
162
+ }
163
+
164
+ // MARK: Private
165
+
166
+ private enum CodingKeys: String, CodingKey {
167
+ case opacity = "o"
168
+ case startPoint = "s"
169
+ case endPoint = "e"
170
+ case gradientType = "t"
171
+ case highlightLength = "h"
172
+ case highlightAngle = "a"
173
+ case colors = "g"
174
+ case width = "w"
175
+ case lineCap = "lc"
176
+ case lineJoin = "lj"
177
+ case miterLimit = "ml"
178
+ case dashPattern = "d"
179
+ }
180
+
181
+ private enum GradientDataKeys: String, CodingKey {
182
+ case numberOfColors = "p"
183
+ case colors = "k"
184
+ }
185
+ }
@@ -0,0 +1,48 @@
1
+ //
2
+ // GroupItem.swift
3
+ // lottie-swift
4
+ //
5
+ // Created by Brandon Withrow on 1/8/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ /// An item that define a a group of shape items
11
+ final class Group: ShapeItem {
12
+
13
+ // MARK: Lifecycle
14
+
15
+ required init(from decoder: Decoder) throws {
16
+ let container = try decoder.container(keyedBy: Group.CodingKeys.self)
17
+ items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items)
18
+ try super.init(from: decoder)
19
+ }
20
+
21
+ required init(dictionary: [String: Any]) throws {
22
+ let itemDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.items)
23
+ items = try [ShapeItem].fromDictionaries(itemDictionaries)
24
+ try super.init(dictionary: dictionary)
25
+ }
26
+
27
+ init(items: [ShapeItem], name: String) {
28
+ self.items = items
29
+ super.init(name: name, type: .group, hidden: false)
30
+ }
31
+
32
+ // MARK: Internal
33
+
34
+ /// A list of shape items.
35
+ let items: [ShapeItem]
36
+
37
+ override func encode(to encoder: Encoder) throws {
38
+ try super.encode(to: encoder)
39
+ var container = encoder.container(keyedBy: CodingKeys.self)
40
+ try container.encode(items, forKey: .items)
41
+ }
42
+
43
+ // MARK: Private
44
+
45
+ private enum CodingKeys: String, CodingKey {
46
+ case items = "it"
47
+ }
48
+ }