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.
- package/.github/actions/setup/action.yml +32 -0
- package/.github/issue_template.md +6 -23
- package/.github/workflows/main.yml +98 -0
- package/.github/workflows/stale_issues.yml +17 -0
- package/.spi.yml +6 -0
- package/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +7 -0
- package/.swiftpm/xcode/package.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/.swiftpm/xcode/package.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/.swiftpm/xcode/xcuserdata/{brandonwithrow.xcuserdatad → cal.xcuserdatad}/xcschemes/xcschememanagement.plist +25 -15
- package/.swiftpm/xcode/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/Gemfile +4 -0
- package/Gemfile.lock +102 -0
- package/Lottie.xcodeproj/project.pbxproj +2011 -1972
- package/Lottie.xcodeproj/project.xcworkspace/contents.xcworkspacedata +1 -1
- package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_iOS.xcscheme → Lottie (iOS).xcscheme } +15 -18
- package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_tvOS.xcscheme → Lottie (macOS).xcscheme } +5 -18
- package/Lottie.xcodeproj/xcshareddata/xcschemes/{Lottie_macOS.xcscheme → Lottie (tvOS).xcscheme } +5 -18
- package/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +37 -0
- package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +24 -0
- package/Lottie.xcworkspace/contents.xcworkspacedata +10 -0
- package/Lottie.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +34 -0
- package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/{Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad → Lottie.xcworkspace/xcuserdata/cal.xcuserdatad}/xcdebugger/Breakpoints_v2.xcbkptlist +2 -2
- package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Expressions.xcexplist +153 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +22 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +138 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +30 -0
- package/Package.swift +5 -15
- package/README.md +40 -60
- package/Rakefile +160 -0
- package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +81 -0
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +447 -0
- package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +81 -0
- package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +41 -0
- package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +55 -0
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +210 -0
- package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +229 -0
- package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +52 -0
- package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +58 -0
- package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +257 -0
- package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +124 -0
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +73 -0
- package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +205 -0
- package/Sources/Private/CoreAnimation/Animations/VisibilityAnimation.swift +37 -0
- package/Sources/Private/CoreAnimation/CompatibilityTracker.swift +130 -0
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +497 -0
- package/Sources/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +35 -0
- package/Sources/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +37 -0
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combinedIfPossible.swift +154 -0
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +83 -0
- package/Sources/Private/CoreAnimation/Layers/BaseAnimationLayer.swift +33 -0
- package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +88 -0
- package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +167 -0
- package/Sources/Private/CoreAnimation/Layers/GradientRenderLayer.swift +94 -0
- package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +79 -0
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +64 -0
- package/Sources/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +138 -0
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +140 -0
- package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +85 -0
- package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +315 -0
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +390 -0
- package/Sources/Private/CoreAnimation/Layers/SolidLayer.swift +47 -0
- package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +91 -0
- package/Sources/Private/CoreAnimation/Layers/TransformLayer.swift +11 -0
- package/Sources/Private/CoreAnimation/ValueProviderStore.swift +139 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/CompositionLayer.swift +94 -86
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/ImageCompositionLayer.swift +24 -21
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/MaskContainerLayer.swift +75 -54
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/NullCompositionLayer.swift +5 -5
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/PreCompositionLayer.swift +59 -43
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/ShapeCompositionLayer.swift +22 -20
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/SolidCompositionLayer.swift +26 -17
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/CompLayers/TextCompositionLayer.swift +42 -36
- package/{lottie-swift/src/Private/LayerContainers/AnimationContainer.swift → Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift} +200 -140
- package/Sources/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +47 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/CompositionLayersInitializer.swift +33 -24
- package/{lottie-swift/src/Private/LayerContainers/Utility/TextLayer.swift → Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift} +149 -106
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/InvertedMatteLayer.swift +26 -24
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +41 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/LayerImageProvider.swift +20 -16
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +40 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/LayerContainers/Utility/LayerTransformNode.swift +82 -67
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Extensions/ItemsExtension.swift +9 -4
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/NodeProperty.swift +29 -21
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift +16 -10
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift +6 -6
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +5 -5
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +10 -8
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueContainer.swift +25 -21
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +23 -17
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift +22 -17
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +110 -79
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +22 -16
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +19 -15
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +22 -20
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +22 -23
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +247 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +30 -24
- package/{lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift → Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift} +93 -66
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +23 -19
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +139 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +170 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +95 -58
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift +42 -29
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +108 -69
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +155 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +51 -37
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +57 -42
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +66 -58
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +169 -0
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +138 -119
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/AnimatorNode.swift +80 -79
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/PathNode.swift +5 -3
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/Protocols/RenderNode.swift +22 -17
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +27 -24
- package/{lottie-swift/src/Private → Sources/Private/MainThread}/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +34 -25
- package/Sources/Private/Model/Animation.swift +160 -0
- package/Sources/Private/Model/Assets/Asset.swift +43 -0
- package/{lottie-swift/src → Sources}/Private/Model/Assets/AssetLibrary.swift +40 -13
- package/Sources/Private/Model/Assets/ImageAsset.swift +112 -0
- package/{lottie-swift/src → Sources}/Private/Model/Assets/PrecompAsset.swift +20 -10
- package/Sources/Private/Model/DictionaryInitializable.swift +67 -0
- package/Sources/Private/Model/Extensions/Bundle.swift +34 -0
- package/{lottie-swift/src → Sources}/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +8 -4
- package/Sources/Private/Model/Keyframes/KeyframeData.swift +113 -0
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +222 -0
- package/{lottie-swift/src → Sources}/Private/Model/Layers/ImageLayerModel.swift +21 -11
- package/Sources/Private/Model/Layers/LayerModel.swift +228 -0
- package/{lottie-swift/src → Sources}/Private/Model/Layers/PreCompLayerModel.swift +39 -22
- package/{lottie-swift/src → Sources}/Private/Model/Layers/ShapeLayerModel.swift +23 -12
- package/{lottie-swift/src → Sources}/Private/Model/Layers/SolidLayerModel.swift +31 -19
- package/{lottie-swift/src → Sources}/Private/Model/Layers/TextLayerModel.swift +33 -19
- package/Sources/Private/Model/Objects/DashPattern.swift +44 -0
- package/Sources/Private/Model/Objects/Marker.swift +33 -0
- package/Sources/Private/Model/Objects/Mask.swift +80 -0
- package/Sources/Private/Model/Objects/Transform.swift +179 -0
- package/Sources/Private/Model/ShapeItems/Ellipse.swift +74 -0
- package/Sources/Private/Model/ShapeItems/Fill.swift +74 -0
- package/Sources/Private/Model/ShapeItems/GradientFill.swift +137 -0
- package/Sources/Private/Model/ShapeItems/GradientStroke.swift +185 -0
- package/Sources/Private/Model/ShapeItems/Group.swift +48 -0
- package/{lottie-swift/src → Sources}/Private/Model/ShapeItems/Merge.swift +29 -12
- package/Sources/Private/Model/ShapeItems/Rectangle.swift +72 -0
- package/Sources/Private/Model/ShapeItems/Repeater.swift +135 -0
- package/Sources/Private/Model/ShapeItems/Shape.swift +56 -0
- package/Sources/Private/Model/ShapeItems/ShapeItem.swift +163 -0
- package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +135 -0
- package/Sources/Private/Model/ShapeItems/Star.swift +131 -0
- package/Sources/Private/Model/ShapeItems/Stroke.swift +101 -0
- package/Sources/Private/Model/ShapeItems/Trim.swift +77 -0
- package/Sources/Private/Model/Text/Font.swift +61 -0
- package/{lottie-swift/src → Sources}/Private/Model/Text/Glyph.swift +63 -39
- package/Sources/Private/Model/Text/TextAnimator.swift +164 -0
- package/Sources/Private/Model/Text/TextDocument.swift +123 -0
- package/Sources/Private/RootAnimationLayer.swift +51 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Debugging/AnimatorNodeDebugging.swift +7 -7
- package/{lottie-swift/src → Sources}/Private/Utility/Debugging/LayerDebugging.swift +72 -48
- package/Sources/Private/Utility/Debugging/TestHelpers.swift +10 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Extensions/AnimationKeypathExtension.swift +69 -59
- package/Sources/Private/Utility/Extensions/BlendMode+Filter.swift +31 -0
- package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +22 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Extensions/CGFloatExtensions.swift +70 -67
- package/Sources/Private/Utility/Extensions/DataExtension.swift +27 -0
- package/Sources/Private/Utility/Extensions/MathKit.swift +450 -0
- package/Sources/Private/Utility/Extensions/StringExtensions.swift +38 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Helpers/AnimationContext.swift +42 -16
- package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +134 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Interpolatable/KeyframeExtensions.swift +13 -10
- package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +59 -0
- package/{lottie-swift/src/Private/NodeRenderSystem/NodeProperties/ValueProviders → Sources/Private/Utility/Interpolatable}/KeyframeInterpolator.swift +125 -108
- package/{lottie-swift/src → Sources}/Private/Utility/Primitives/BezierPath.swift +229 -143
- package/Sources/Private/Utility/Primitives/CGPointExtension.swift +35 -0
- package/{lottie-swift/src → Sources}/Private/Utility/Primitives/ColorExtension.swift +46 -14
- package/{lottie-swift/src → Sources}/Private/Utility/Primitives/CompoundBezierPath.swift +58 -49
- package/Sources/Private/Utility/Primitives/CurveVertex.swift +184 -0
- package/Sources/Private/Utility/Primitives/PathElement.swift +75 -0
- package/Sources/Private/Utility/Primitives/UnitBezier.swift +115 -0
- package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +341 -0
- package/Sources/Public/Animation/AnimationPublic.swift +266 -0
- package/Sources/Public/Animation/AnimationView.swift +1335 -0
- package/Sources/Public/Animation/AnimationViewInitializers.swift +109 -0
- package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +22 -0
- package/{lottie-swift/src → Sources}/Public/AnimationCache/LRUAnimationCache.swift +22 -18
- package/Sources/Public/DynamicProperties/AnimationKeypath.swift +49 -0
- package/Sources/Public/DynamicProperties/AnyValueProvider.swift +132 -0
- package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +54 -36
- package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +40 -36
- package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +123 -0
- package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +40 -35
- package/{lottie-swift/src → Sources}/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +40 -35
- package/{lottie-swift/src → Sources}/Public/FontProvider/AnimationFontProvider.swift +15 -8
- package/Sources/Public/ImageProvider/AnimationImageProvider.swift +21 -0
- package/Sources/Public/Keyframes/Interpolatable.swift +253 -0
- package/Sources/Public/Keyframes/Keyframe.swift +92 -0
- package/Sources/Public/Logging/LottieLogger.swift +137 -0
- package/Sources/Public/LottieConfiguration.swift +143 -0
- package/{lottie-swift/src → Sources}/Public/Primitives/AnimationTime.swift +1 -1
- package/{lottie-swift/src → Sources}/Public/Primitives/Color.swift +10 -6
- package/{lottie-swift/src → Sources}/Public/Primitives/Vectors.swift +13 -12
- package/Sources/Public/TextProvider/AnimationTextProvider.swift +53 -0
- package/{lottie-swift/src → Sources}/Public/iOS/AnimatedButton.swift +42 -26
- package/{lottie-swift/src → Sources}/Public/iOS/AnimatedControl.swift +100 -91
- package/{lottie-swift/src → Sources}/Public/iOS/AnimatedSwitch.swift +128 -94
- package/{lottie-swift/src → Sources}/Public/iOS/AnimationSubview.swift +3 -3
- package/Sources/Public/iOS/AnimationViewBase.swift +78 -0
- package/{lottie-swift/src → Sources}/Public/iOS/BundleImageProvider.swift +36 -34
- package/{lottie-swift/src → Sources}/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift +4 -0
- package/{lottie-swift/src → Sources}/Public/iOS/Compatibility/CompatibleAnimationView.swift +38 -29
- package/{lottie-swift/src → Sources}/Public/iOS/FilepathImageProvider.swift +24 -21
- package/{lottie-swift/src → Sources}/Public/iOS/UIColorExtension.swift +4 -4
- package/{lottie-swift/src/Public/MacOS/AnimationSubview.swift → Sources/Public/macOS/AnimationSubview.macOS.swift} +4 -5
- package/{lottie-swift/src/Public/MacOS/LottieView.swift → Sources/Public/macOS/AnimationViewBase.macOS.swift} +58 -50
- package/{lottie-swift/src/Public/MacOS/BundleImageProvider.swift → Sources/Public/macOS/BundleImageProvider.macOS.swift} +31 -32
- package/Sources/Public/macOS/FilepathImageProvider.macOS.swift +67 -0
- package/Tests/AnimationKeypathTests.swift +103 -0
- package/Tests/AutomaticEngineTests.swift +57 -0
- package/Tests/BundleTests.swift +25 -0
- package/Tests/DataURLTests.swift +64 -0
- package/Tests/ParsingTests.swift +43 -0
- package/Tests/PerformanceTests.swift +214 -0
- package/Tests/Samples/9squares_AlBoardman.json +1 -0
- package/Tests/Samples/Boat_Loader.json +1 -0
- package/Tests/Samples/HamburgerArrow.json +1 -0
- package/Tests/Samples/IconTransitions.json +1 -0
- package/Tests/Samples/Images/dog.png +0 -0
- package/Tests/Samples/Issues/issue_1125.json +1 -0
- package/Tests/Samples/Issues/issue_1260.json +1 -0
- package/Tests/Samples/Issues/issue_1403.json +1 -0
- package/Tests/Samples/Issues/issue_1407.json +1 -0
- package/Tests/Samples/Issues/issue_1460.json +1 -0
- package/Tests/Samples/Issues/issue_1488.json +1 -0
- package/Tests/Samples/Issues/issue_1505.json +1 -0
- package/Tests/Samples/Issues/issue_1541.json +1 -0
- package/Tests/Samples/Issues/issue_1557.json +1 -0
- package/Tests/Samples/Issues/issue_1603.json +1 -0
- package/Tests/Samples/Issues/issue_1628.json +1 -0
- package/Tests/Samples/Issues/issue_1636.json +1 -0
- package/Tests/Samples/Issues/issue_1643.json +1 -0
- package/Tests/Samples/Issues/issue_1655.json +1 -0
- package/Tests/Samples/Issues/issue_1664.json +1 -0
- package/Tests/Samples/Issues/issue_1683.json +1 -0
- package/Tests/Samples/Issues/issue_1687.json +1 -0
- package/Tests/Samples/Issues/issue_1711.json +1 -0
- package/Tests/Samples/Issues/issue_1717.json +1 -0
- package/Tests/Samples/Issues/issue_769.json +1 -0
- package/Tests/Samples/Issues/issue_885.json +1 -0
- package/Tests/Samples/Issues/issue_965.json +1 -0
- package/Tests/Samples/Issues/pr_1536.json +1 -0
- package/Tests/Samples/Issues/pr_1563.json +8439 -0
- package/Tests/Samples/Issues/pr_1592.json +5527 -0
- package/Tests/Samples/Issues/pr_1599.json +738 -0
- package/Tests/Samples/Issues/pr_1604_1.json +1 -0
- package/Tests/Samples/Issues/pr_1604_2.json +1 -0
- package/Tests/Samples/Issues/pr_1632_1.json +1 -0
- package/Tests/Samples/Issues/pr_1632_2.json +1 -0
- package/Tests/Samples/Issues/pr_1686.json +513 -0
- package/Tests/Samples/Issues/pr_1698.json +1 -0
- package/Tests/Samples/Issues/pr_1699.json +1 -0
- package/Tests/Samples/LottieFiles/LICENSE.md +14 -0
- package/Tests/Samples/LottieFiles/bounce_strokes.json +1 -0
- package/Tests/Samples/LottieFiles/cactus.json +1 -0
- package/Tests/Samples/LottieFiles/dog_car_ride.json +1 -0
- package/Tests/Samples/LottieFiles/draft_icon.json +1 -0
- package/Tests/Samples/LottieFiles/fireworks.json +1 -0
- package/Tests/Samples/LottieFiles/gradient_1.json +1 -0
- package/Tests/Samples/LottieFiles/gradient_2.json +1 -0
- package/Tests/Samples/LottieFiles/gradient_pill.json +1 -0
- package/Tests/Samples/LottieFiles/gradient_shapes.json +1 -0
- package/Tests/Samples/LottieFiles/gradient_square.json +1 -0
- package/Tests/Samples/LottieFiles/growth.json +1 -0
- package/Tests/Samples/LottieFiles/infinity_loader.json +1 -0
- package/Tests/Samples/LottieFiles/loading_dots_1.json +1 -0
- package/Tests/Samples/LottieFiles/loading_dots_2.json +1 -0
- package/Tests/Samples/LottieFiles/loading_dots_3.json +1 -0
- package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +1 -0
- package/Tests/Samples/LottieFiles/settings_slider.json +1 -0
- package/Tests/Samples/LottieFiles/shop.json +1 -0
- package/Tests/Samples/LottieFiles/step_loader.json +1 -0
- package/Tests/Samples/LottieLogo1.json +1 -0
- package/Tests/Samples/LottieLogo1_masked.json +1 -0
- package/Tests/Samples/LottieLogo2.json +1 -0
- package/Tests/Samples/MotionCorpse_Jrcanest.json +1 -0
- package/Tests/Samples/Nonanimating/BasicLayers.json +1 -0
- package/Tests/Samples/Nonanimating/DisableNodesTest.json +1 -0
- package/Tests/Samples/Nonanimating/FirstText.json +1 -0
- package/Tests/Samples/Nonanimating/GeometryTransformTest.json +1 -0
- package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +1 -0
- package/Tests/Samples/Nonanimating/Text_Glyph.json +1 -0
- package/Tests/Samples/Nonanimating/Text_NoAnimation.json +1 -0
- package/Tests/Samples/Nonanimating/Text_NoGlyph.json +1 -0
- package/Tests/Samples/Nonanimating/Zoom.json +1 -0
- package/Tests/Samples/Nonanimating/_dog.json +1 -0
- package/Tests/Samples/Nonanimating/base64Test.json +1 -0
- package/Tests/Samples/Nonanimating/blend_mode_test.json +1 -0
- package/Tests/Samples/Nonanimating/keypathTest.json +1 -0
- package/Tests/Samples/Nonanimating/verifyLineHeight.json +1 -0
- package/Tests/Samples/PinJump.json +1 -0
- package/Tests/Samples/Switch.json +1 -0
- package/Tests/Samples/Switch_States.json +1 -0
- package/Tests/Samples/TwitterHeart.json +1 -0
- package/Tests/Samples/TwitterHeartButton.json +1 -0
- package/Tests/Samples/TypeFace/A.json +1 -0
- package/Tests/Samples/TypeFace/Apostrophe.json +1 -0
- package/Tests/Samples/TypeFace/B.json +1 -0
- package/Tests/Samples/TypeFace/BlinkingCursor.json +1 -0
- package/Tests/Samples/TypeFace/C.json +1 -0
- package/Tests/Samples/TypeFace/Colon.json +1 -0
- package/Tests/Samples/TypeFace/Comma.json +1 -0
- package/Tests/Samples/TypeFace/D.json +1 -0
- package/Tests/Samples/TypeFace/E.json +1 -0
- package/Tests/Samples/TypeFace/F.json +1 -0
- package/Tests/Samples/TypeFace/G.json +1 -0
- package/Tests/Samples/TypeFace/H.json +1 -0
- package/Tests/Samples/TypeFace/I.json +1 -0
- package/Tests/Samples/TypeFace/J.json +1 -0
- package/Tests/Samples/TypeFace/K.json +1 -0
- package/Tests/Samples/TypeFace/L.json +1 -0
- package/Tests/Samples/TypeFace/M.json +1 -0
- package/Tests/Samples/TypeFace/N.json +1 -0
- package/Tests/Samples/TypeFace/O.json +1 -0
- package/Tests/Samples/TypeFace/P.json +1 -0
- package/Tests/Samples/TypeFace/Q.json +1 -0
- package/Tests/Samples/TypeFace/R.json +1 -0
- package/Tests/Samples/TypeFace/S.json +1 -0
- package/Tests/Samples/TypeFace/T.json +1 -0
- package/Tests/Samples/TypeFace/U.json +1 -0
- package/Tests/Samples/TypeFace/V.json +1 -0
- package/Tests/Samples/TypeFace/W.json +1 -0
- package/Tests/Samples/TypeFace/X.json +1 -0
- package/Tests/Samples/TypeFace/Y.json +1 -0
- package/Tests/Samples/TypeFace/Z.json +1 -0
- package/Tests/Samples/Watermelon.json +1 -0
- package/Tests/Samples/setValueTest.json +1 -0
- package/Tests/Samples/timeremap.json +1 -0
- package/Tests/Samples/vcTransition1.json +1 -0
- package/Tests/Samples/vcTransition2.json +1 -0
- package/Tests/SnapshotConfiguration.swift +158 -0
- package/Tests/SnapshotTests.swift +265 -0
- package/Tests/Utils/Bundle+Module.swift +30 -0
- package/Tests/Utils/HardcodedFontProvider.swift +19 -0
- package/Tests/Utils/HardcodedImageProvider.swift +23 -0
- package/Tests/Utils/Snapshotting+presentationLayer.swift +47 -0
- package/Tests/ValueProvidersTests.swift +27 -0
- package/lottie-ios.podspec +12 -12
- package/package.json +1 -1
- package/script/test-carthage/Cartfile +1 -0
- package/script/test-carthage/Cartfile.resolved +1 -0
- package/script/test-carthage/CarthageTest/AppDelegate.swift +26 -0
- package/script/test-carthage/CarthageTest/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/script/test-carthage/CarthageTest/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
- package/script/test-carthage/CarthageTest/Assets.xcassets/Contents.json +6 -0
- package/script/test-carthage/CarthageTest/Base.lproj/LaunchScreen.storyboard +25 -0
- package/script/test-carthage/CarthageTest/Base.lproj/Main.storyboard +24 -0
- package/script/test-carthage/CarthageTest/Info.plist +66 -0
- package/script/test-carthage/CarthageTest/SceneDelegate.swift +10 -0
- package/script/test-carthage/CarthageTest/ViewController.swift +15 -0
- package/script/test-carthage/CarthageTest-macOS/AppDelegate.swift +7 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
- package/script/test-carthage/CarthageTest-macOS/Assets.xcassets/Contents.json +6 -0
- package/script/test-carthage/CarthageTest-macOS/Base.lproj/Main.storyboard +717 -0
- package/script/test-carthage/CarthageTest-macOS/CarthageTest_macOS.entitlements +10 -0
- package/script/test-carthage/CarthageTest-macOS/ViewController.swift +15 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.pbxproj +532 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/script/test-carthage/CarthageTest.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/script/test-carthage/CarthageTest.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
- package/script/test-carthage/Mintfile +1 -0
- package/script/test-spm/LottieSPM.xcworkspace/contents.xcworkspacedata +7 -0
- package/script/test-spm/LottieSPM.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/script/test-spm/Mintfile +1 -0
- package/.swiftpm/xcode/package.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie/Info.plist +0 -22
- package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad/xcschemes/LottieLibraryMacOS.xcscheme +0 -80
- package/Lottie.xcodeproj/xcuserdata/brandonwithrow.xcuserdatad/xcschemes/xcschememanagement.plist +0 -57
- package/lottie-swift/Assets/.gitkeep +0 -0
- package/lottie-swift/src/Private/LayerContainers/Utility/LayerFontProvider.swift +0 -37
- package/lottie-swift/src/Private/LayerContainers/Utility/LayerTextProvider.swift +0 -36
- package/lottie-swift/src/Private/Model/Animation.swift +0 -107
- package/lottie-swift/src/Private/Model/Assets/Asset.swift +0 -27
- package/lottie-swift/src/Private/Model/Assets/ImageAsset.swift +0 -48
- package/lottie-swift/src/Private/Model/Keyframes/Keyframe.swift +0 -128
- package/lottie-swift/src/Private/Model/Keyframes/KeyframeGroup.swift +0 -108
- package/lottie-swift/src/Private/Model/Layers/LayerModel.swift +0 -150
- package/lottie-swift/src/Private/Model/Objects/DashPattern.swift +0 -24
- package/lottie-swift/src/Private/Model/Objects/Marker.swift +0 -23
- package/lottie-swift/src/Private/Model/Objects/Mask.swift +0 -48
- package/lottie-swift/src/Private/Model/Objects/Transform.swift +0 -105
- package/lottie-swift/src/Private/Model/ShapeItems/Ellipse.swift +0 -50
- package/lottie-swift/src/Private/Model/ShapeItems/FillI.swift +0 -49
- package/lottie-swift/src/Private/Model/ShapeItems/GradientFill.swift +0 -86
- package/lottie-swift/src/Private/Model/ShapeItems/GradientStroke.swift +0 -125
- package/lottie-swift/src/Private/Model/ShapeItems/Group.swift +0 -32
- package/lottie-swift/src/Private/Model/ShapeItems/Rectangle.swift +0 -50
- package/lottie-swift/src/Private/Model/ShapeItems/Repeater.swift +0 -80
- package/lottie-swift/src/Private/Model/ShapeItems/Shape.swift +0 -37
- package/lottie-swift/src/Private/Model/ShapeItems/ShapeItem.swift +0 -95
- package/lottie-swift/src/Private/Model/ShapeItems/ShapeTransform.swift +0 -68
- package/lottie-swift/src/Private/Model/ShapeItems/Star.swift +0 -86
- package/lottie-swift/src/Private/Model/ShapeItems/Stroke.swift +0 -67
- package/lottie-swift/src/Private/Model/ShapeItems/Trim.swift +0 -53
- package/lottie-swift/src/Private/Model/Text/Font.swift +0 -35
- package/lottie-swift/src/Private/Model/Text/TextAnimator.swift +0 -99
- package/lottie-swift/src/Private/Model/Text/TextDocument.swift +0 -70
- package/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +0 -109
- package/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +0 -132
- package/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +0 -141
- package/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +0 -127
- package/lottie-swift/src/Private/Utility/Extensions/MathKit.swift +0 -539
- package/lottie-swift/src/Private/Utility/Extensions/StringExtensions.swift +0 -32
- package/lottie-swift/src/Private/Utility/Interpolatable/Interpolatable.swift +0 -18
- package/lottie-swift/src/Private/Utility/Interpolatable/InterpolatableExtensions.swift +0 -170
- package/lottie-swift/src/Private/Utility/Primitives/CurveVertex.swift +0 -177
- package/lottie-swift/src/Private/Utility/Primitives/PathElement.swift +0 -68
- package/lottie-swift/src/Private/Utility/Primitives/VectorsExtensions.swift +0 -218
- package/lottie-swift/src/Public/Animation/AnimationPublic.swift +0 -196
- package/lottie-swift/src/Public/Animation/AnimationView.swift +0 -1006
- package/lottie-swift/src/Public/Animation/AnimationViewInitializers.swift +0 -83
- package/lottie-swift/src/Public/AnimationCache/AnimationCacheProvider.swift +0 -24
- package/lottie-swift/src/Public/DynamicProperties/AnimationKeypath.swift +0 -46
- package/lottie-swift/src/Public/DynamicProperties/AnyValueProvider.swift +0 -29
- package/lottie-swift/src/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +0 -114
- package/lottie-swift/src/Public/ImageProvider/AnimationImageProvider.swift +0 -23
- package/lottie-swift/src/Public/MacOS/FilepathImageProvider.swift +0 -67
- package/lottie-swift/src/Public/TextProvider/AnimationTextProvider.swift +0 -39
- package/lottie-swift/src/Public/iOS/LottieView.swift +0 -62
- package/lottie-swift-testing.podspec +0 -32
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Created by Cal Stephens on 1/10/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - ImageLayer
|
|
7
|
+
|
|
8
|
+
/// The `CALayer` type responsible for rendering `ImageLayerModel`s
|
|
9
|
+
final class ImageLayer: BaseCompositionLayer {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(
|
|
14
|
+
imageLayer: ImageLayerModel,
|
|
15
|
+
context: LayerContext)
|
|
16
|
+
{
|
|
17
|
+
self.imageLayer = imageLayer
|
|
18
|
+
super.init(layerModel: imageLayer)
|
|
19
|
+
setupImage(context: 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
|
+
imageLayer = typedLayer.imageLayer
|
|
34
|
+
super.init(layer: typedLayer)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// MARK: Internal
|
|
38
|
+
|
|
39
|
+
func setupImage(context: LayerContext) {
|
|
40
|
+
guard
|
|
41
|
+
let imageAsset = context.animation.assetLibrary?.imageAssets[imageLayer.referenceID],
|
|
42
|
+
let image = context.imageProvider.imageForAsset(asset: imageAsset)
|
|
43
|
+
else {
|
|
44
|
+
self.imageAsset = nil
|
|
45
|
+
contents = nil
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
self.imageAsset = imageAsset
|
|
50
|
+
contents = image
|
|
51
|
+
setNeedsLayout()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// MARK: Private
|
|
55
|
+
|
|
56
|
+
private let imageLayer: ImageLayerModel
|
|
57
|
+
private var imageAsset: ImageAsset?
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// MARK: CustomLayoutLayer
|
|
62
|
+
|
|
63
|
+
extension ImageLayer: CustomLayoutLayer {
|
|
64
|
+
func layout(superlayerBounds: CGRect) {
|
|
65
|
+
anchorPoint = .zero
|
|
66
|
+
|
|
67
|
+
guard let imageAsset = imageAsset else {
|
|
68
|
+
bounds = superlayerBounds
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Image layers specifically need to use the size of the image itself
|
|
73
|
+
bounds = CGRect(
|
|
74
|
+
x: superlayerBounds.origin.x,
|
|
75
|
+
y: superlayerBounds.origin.y,
|
|
76
|
+
width: CGFloat(imageAsset.width),
|
|
77
|
+
height: CGFloat(imageAsset.height))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Created by Cal Stephens on 12/20/21.
|
|
2
|
+
// Copyright © 2021 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - LayerContext
|
|
7
|
+
|
|
8
|
+
/// Context available when constructing an `AnimationLayer`
|
|
9
|
+
struct LayerContext {
|
|
10
|
+
let animation: Animation
|
|
11
|
+
let imageProvider: AnimationImageProvider
|
|
12
|
+
let fontProvider: AnimationFontProvider
|
|
13
|
+
let compatibilityTracker: CompatibilityTracker
|
|
14
|
+
var layerName: String
|
|
15
|
+
|
|
16
|
+
func forLayer(_ layer: LayerModel) -> LayerContext {
|
|
17
|
+
var context = self
|
|
18
|
+
context.layerName = layer.name
|
|
19
|
+
return context
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: - LayerModel + makeAnimationLayer
|
|
24
|
+
|
|
25
|
+
extension LayerModel {
|
|
26
|
+
/// Constructs an `AnimationLayer` / `CALayer` that represents this `LayerModel`
|
|
27
|
+
func makeAnimationLayer(context: LayerContext) throws -> BaseCompositionLayer? {
|
|
28
|
+
let context = context.forLayer(self)
|
|
29
|
+
|
|
30
|
+
if hidden {
|
|
31
|
+
return TransformLayer(layerModel: self)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
switch (type, self) {
|
|
35
|
+
case (.precomp, let preCompLayerModel as PreCompLayerModel):
|
|
36
|
+
let preCompLayer = PreCompLayer(preCompLayer: preCompLayerModel)
|
|
37
|
+
try preCompLayer.setup(context: context)
|
|
38
|
+
return preCompLayer
|
|
39
|
+
|
|
40
|
+
case (.solid, let solidLayerModel as SolidLayerModel):
|
|
41
|
+
return SolidLayer(solidLayerModel)
|
|
42
|
+
|
|
43
|
+
case (.shape, let shapeLayerModel as ShapeLayerModel):
|
|
44
|
+
return try ShapeLayer(shapeLayer: shapeLayerModel, context: context)
|
|
45
|
+
|
|
46
|
+
case (.image, let imageLayerModel as ImageLayerModel):
|
|
47
|
+
return ImageLayer(imageLayer: imageLayerModel, context: context)
|
|
48
|
+
|
|
49
|
+
case (.text, let textLayerModel as TextLayerModel):
|
|
50
|
+
return try TextLayer(textLayerModel: textLayerModel, context: context)
|
|
51
|
+
|
|
52
|
+
case (.null, _):
|
|
53
|
+
return TransformLayer(layerModel: self)
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
try context.logCompatibilityIssue("""
|
|
57
|
+
Unexpected layer type combination ("\(type)" and "\(Swift.type(of: self))")
|
|
58
|
+
""")
|
|
59
|
+
|
|
60
|
+
return nil
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Created by Cal Stephens on 1/6/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - MaskCompositionLayer
|
|
7
|
+
|
|
8
|
+
/// The CALayer type responsible for rendering the `Mask` of a `BaseCompositionLayer`
|
|
9
|
+
final class MaskCompositionLayer: CALayer {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(masks: [Mask]) {
|
|
14
|
+
maskLayers = masks.map(MaskLayer.init(mask:))
|
|
15
|
+
super.init()
|
|
16
|
+
|
|
17
|
+
var containerLayer = BaseAnimationLayer()
|
|
18
|
+
var firstObject = true
|
|
19
|
+
for maskLayer in maskLayers {
|
|
20
|
+
if maskLayer.maskModel.mode.usableMode == .none {
|
|
21
|
+
continue
|
|
22
|
+
} else if maskLayer.maskModel.mode.usableMode == .add || firstObject {
|
|
23
|
+
firstObject = false
|
|
24
|
+
containerLayer.addSublayer(maskLayer)
|
|
25
|
+
} else {
|
|
26
|
+
containerLayer.mask = maskLayer
|
|
27
|
+
let newContainer = BaseAnimationLayer()
|
|
28
|
+
newContainer.addSublayer(containerLayer)
|
|
29
|
+
containerLayer = newContainer
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addSublayer(containerLayer)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
required init?(coder _: NSCoder) {
|
|
37
|
+
fatalError("init(coder:) has not been implemented")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Called by CoreAnimation to create a shadow copy of this layer
|
|
41
|
+
/// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
|
|
42
|
+
override init(layer: Any) {
|
|
43
|
+
guard let typedLayer = layer as? Self else {
|
|
44
|
+
fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
maskLayers = typedLayer.maskLayers
|
|
48
|
+
super.init(layer: typedLayer)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// MARK: Internal
|
|
52
|
+
|
|
53
|
+
override func layoutSublayers() {
|
|
54
|
+
super.layoutSublayers()
|
|
55
|
+
|
|
56
|
+
for sublayer in sublayers ?? [] {
|
|
57
|
+
sublayer.fillBoundsOfSuperlayer()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// MARK: Private
|
|
62
|
+
|
|
63
|
+
private let maskLayers: [MaskLayer]
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// MARK: AnimationLayer
|
|
68
|
+
|
|
69
|
+
extension MaskCompositionLayer: AnimationLayer {
|
|
70
|
+
func setupAnimations(context: LayerAnimationContext) throws {
|
|
71
|
+
for maskLayer in maskLayers {
|
|
72
|
+
try maskLayer.setupAnimations(context: context)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: MaskCompositionLayer.MaskLayer
|
|
78
|
+
|
|
79
|
+
extension MaskCompositionLayer {
|
|
80
|
+
final class MaskLayer: CAShapeLayer {
|
|
81
|
+
|
|
82
|
+
// MARK: Lifecycle
|
|
83
|
+
|
|
84
|
+
init(mask: Mask) {
|
|
85
|
+
maskModel = mask
|
|
86
|
+
super.init()
|
|
87
|
+
|
|
88
|
+
fillRule = .evenOdd
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
required init?(coder _: NSCoder) {
|
|
92
|
+
fatalError("init(coder:) has not been implemented")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Called by CoreAnimation to create a shadow copy of this layer
|
|
96
|
+
/// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
|
|
97
|
+
override init(layer: Any) {
|
|
98
|
+
guard let typedLayer = layer as? Self else {
|
|
99
|
+
fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
maskModel = typedLayer.maskModel
|
|
103
|
+
super.init(layer: typedLayer)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// MARK: Internal
|
|
107
|
+
|
|
108
|
+
let maskModel: Mask
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// MARK: - MaskCompositionLayer.MaskLayer + AnimationLayer
|
|
114
|
+
|
|
115
|
+
extension MaskCompositionLayer.MaskLayer: AnimationLayer {
|
|
116
|
+
func setupAnimations(context: LayerAnimationContext) throws {
|
|
117
|
+
let shouldInvertMask = (maskModel.mode.usableMode == .subtract && !maskModel.inverted)
|
|
118
|
+
|| (maskModel.mode.usableMode == .add && maskModel.inverted)
|
|
119
|
+
|
|
120
|
+
try addAnimations(
|
|
121
|
+
for: maskModel.shape,
|
|
122
|
+
context: context,
|
|
123
|
+
transformPath: { maskPath in
|
|
124
|
+
// If the mask is using `MaskMode.subtract` or has `inverted: true`,
|
|
125
|
+
// we have to invert the area filled by the path. We can do that by
|
|
126
|
+
// drawing a rectangle, and then adding a path (which is subtracted
|
|
127
|
+
// from the rectangle based on the .evenOdd fill mode).
|
|
128
|
+
if shouldInvertMask {
|
|
129
|
+
let path = CGMutablePath()
|
|
130
|
+
path.addRect(.veryLargeRect)
|
|
131
|
+
path.addPath(maskPath)
|
|
132
|
+
return path
|
|
133
|
+
} else {
|
|
134
|
+
return maskPath
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Created by Cal Stephens on 12/14/21.
|
|
2
|
+
// Copyright © 2021 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - PreCompLayer
|
|
7
|
+
|
|
8
|
+
/// The `CALayer` type responsible for rendering `PreCompLayerModel`s
|
|
9
|
+
final class PreCompLayer: BaseCompositionLayer {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(preCompLayer: PreCompLayerModel) {
|
|
14
|
+
self.preCompLayer = preCompLayer
|
|
15
|
+
super.init(layerModel: preCompLayer)
|
|
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
|
+
preCompLayer = typedLayer.preCompLayer
|
|
30
|
+
timeRemappingInterpolator = typedLayer.timeRemappingInterpolator
|
|
31
|
+
super.init(layer: typedLayer)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// MARK: Internal
|
|
35
|
+
|
|
36
|
+
/// Post-init setup for `PreCompLayer`s.
|
|
37
|
+
/// Should always be called after `PreCompLayer.init(preCompLayer:)`.
|
|
38
|
+
///
|
|
39
|
+
/// This is a workaround for a hard-to-reproduce crash that was
|
|
40
|
+
/// triggered when `PreCompLayer.init` was called reentantly. We didn't
|
|
41
|
+
/// have any consistent repro steps for this crash (it happened 100% of
|
|
42
|
+
/// the time for some testers, and 0% of the time for other testers),
|
|
43
|
+
/// but moving this code out of `PreCompLayer.init` does seem to fix it.
|
|
44
|
+
///
|
|
45
|
+
/// The stack trace looked like:
|
|
46
|
+
/// - `_os_unfair_lock_recursive_abort`
|
|
47
|
+
/// - `-[CALayerAccessibility__UIKit__QuartzCore dealloc]`
|
|
48
|
+
/// - `PreCompLayer.__allocating_init(preCompLayer:context:)` <- reentrant init call
|
|
49
|
+
/// - ...
|
|
50
|
+
/// - `CALayer.setupLayerHierarchy(for:context:)`
|
|
51
|
+
/// - `PreCompLayer.init(preCompLayer:context:)`
|
|
52
|
+
///
|
|
53
|
+
func setup(context: LayerContext) throws {
|
|
54
|
+
if let timeRemappingKeyframes = preCompLayer.timeRemapping {
|
|
55
|
+
timeRemappingInterpolator = try .timeRemapping(keyframes: timeRemappingKeyframes, context: context)
|
|
56
|
+
} else {
|
|
57
|
+
timeRemappingInterpolator = nil
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try setupLayerHierarchy(
|
|
61
|
+
for: context.animation.assetLibrary?.precompAssets[preCompLayer.referenceID]?.layers ?? [],
|
|
62
|
+
context: context)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
66
|
+
var context = context
|
|
67
|
+
context = context.addingKeypathComponent(preCompLayer.name)
|
|
68
|
+
try setupLayerAnimations(context: context)
|
|
69
|
+
|
|
70
|
+
// Precomp layers can adjust the local time of their child layers (relative to the
|
|
71
|
+
// animation's global time) via `timeRemapping` or a custom `startTime`
|
|
72
|
+
let contextForChildren = context.withTimeRemapping { [preCompLayer, timeRemappingInterpolator] layerLocalFrame in
|
|
73
|
+
if let timeRemappingInterpolator = timeRemappingInterpolator {
|
|
74
|
+
return timeRemappingInterpolator.value(frame: layerLocalFrame) as? AnimationFrameTime ?? layerLocalFrame
|
|
75
|
+
} else {
|
|
76
|
+
return layerLocalFrame + AnimationFrameTime(preCompLayer.startTime)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try setupChildAnimations(context: contextForChildren)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// MARK: Private
|
|
84
|
+
|
|
85
|
+
private let preCompLayer: PreCompLayerModel
|
|
86
|
+
private var timeRemappingInterpolator: KeyframeInterpolator<AnimationFrameTime>?
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// MARK: CustomLayoutLayer
|
|
91
|
+
|
|
92
|
+
extension PreCompLayer: CustomLayoutLayer {
|
|
93
|
+
func layout(superlayerBounds: CGRect) {
|
|
94
|
+
anchorPoint = .zero
|
|
95
|
+
|
|
96
|
+
// Pre-comp layers use a size specified in the layer model,
|
|
97
|
+
// and clip the composition to that bounds
|
|
98
|
+
bounds = CGRect(
|
|
99
|
+
x: superlayerBounds.origin.x,
|
|
100
|
+
y: superlayerBounds.origin.y,
|
|
101
|
+
width: CGFloat(preCompLayer.width),
|
|
102
|
+
height: CGFloat(preCompLayer.height))
|
|
103
|
+
|
|
104
|
+
masksToBounds = true
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
extension KeyframeInterpolator where ValueType == AnimationFrameTime {
|
|
109
|
+
/// A `KeyframeInterpolator` for the given `timeRemapping` keyframes
|
|
110
|
+
static func timeRemapping(
|
|
111
|
+
keyframes timeRemappingKeyframes: KeyframeGroup<Vector1D>,
|
|
112
|
+
context: LayerContext)
|
|
113
|
+
throws
|
|
114
|
+
-> KeyframeInterpolator<AnimationFrameTime>
|
|
115
|
+
{
|
|
116
|
+
try context.logCompatibilityIssue("""
|
|
117
|
+
The Core Animation rendering engine partially supports time remapping keyframes,
|
|
118
|
+
but this is somewhat experimental and has some known issues. Since it doesn't work
|
|
119
|
+
in all cases, we have to fall back to using the main thread engine when using
|
|
120
|
+
`RenderingEngineOption.automatic`.
|
|
121
|
+
""")
|
|
122
|
+
|
|
123
|
+
// `timeRemapping` is a mapping from the animation's global time to the layer's local time.
|
|
124
|
+
// In the Core Animation engine, we need to perform the opposite calculation -- convert
|
|
125
|
+
// the layer's local time into the animation's global time. We can get this by inverting
|
|
126
|
+
// the time remapping, swapping the x axis (global time) and the y axis (local time).
|
|
127
|
+
let localTimeToGlobalTimeMapping = timeRemappingKeyframes.keyframes.map { keyframe in
|
|
128
|
+
Keyframe(
|
|
129
|
+
value: keyframe.time,
|
|
130
|
+
time: keyframe.value.cgFloatValue * CGFloat(context.animation.framerate),
|
|
131
|
+
isHold: keyframe.isHold,
|
|
132
|
+
inTangent: keyframe.inTangent,
|
|
133
|
+
outTangent: keyframe.outTangent,
|
|
134
|
+
spatialInTangent: keyframe.spatialInTangent,
|
|
135
|
+
spatialOutTangent: keyframe.spatialOutTangent)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return KeyframeInterpolator(keyframes: .init(localTimeToGlobalTimeMapping))
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Created by Cal Stephens on 8/1/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - RepeaterLayer
|
|
7
|
+
|
|
8
|
+
/// A layer that renders a child layer at some offset using a `Repeater`
|
|
9
|
+
final class RepeaterLayer: BaseAnimationLayer {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(repeater: Repeater, childLayer: CALayer, index: Int) {
|
|
14
|
+
repeaterTransform = RepeaterTransform(repeater: repeater, index: index)
|
|
15
|
+
super.init()
|
|
16
|
+
addSublayer(childLayer)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
required init?(coder _: NSCoder) {
|
|
20
|
+
fatalError("init(coder:) has not been implemented")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Called by CoreAnimation to create a shadow copy of this layer
|
|
24
|
+
/// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
|
|
25
|
+
override init(layer: Any) {
|
|
26
|
+
guard let typedLayer = layer as? Self else {
|
|
27
|
+
fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
repeaterTransform = typedLayer.repeaterTransform
|
|
31
|
+
super.init(layer: typedLayer)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// MARK: Internal
|
|
35
|
+
|
|
36
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
37
|
+
try super.setupAnimations(context: context)
|
|
38
|
+
try addTransformAnimations(for: repeaterTransform, context: context)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// MARK: Private
|
|
42
|
+
|
|
43
|
+
private let repeaterTransform: RepeaterTransform
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// MARK: - RepeaterTransform
|
|
48
|
+
|
|
49
|
+
/// A transform model created from a `Repeater`
|
|
50
|
+
private struct RepeaterTransform {
|
|
51
|
+
|
|
52
|
+
// MARK: Lifecycle
|
|
53
|
+
|
|
54
|
+
init(repeater: Repeater, index: Int) {
|
|
55
|
+
anchorPoint = repeater.anchorPoint
|
|
56
|
+
scale = repeater.scale
|
|
57
|
+
|
|
58
|
+
rotation = repeater.rotation.map { rotation in
|
|
59
|
+
Vector1D(rotation.value * Double(index))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
position = repeater.position.map { position in
|
|
63
|
+
Vector3D(
|
|
64
|
+
x: position.x * Double(index),
|
|
65
|
+
y: position.y * Double(index),
|
|
66
|
+
z: position.z * Double(index))
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// MARK: Internal
|
|
71
|
+
|
|
72
|
+
let anchorPoint: KeyframeGroup<Vector3D>
|
|
73
|
+
let position: KeyframeGroup<Vector3D>
|
|
74
|
+
let rotation: KeyframeGroup<Vector1D>
|
|
75
|
+
let scale: KeyframeGroup<Vector3D>
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// MARK: TransformModel
|
|
80
|
+
|
|
81
|
+
extension RepeaterTransform: TransformModel {
|
|
82
|
+
var _position: KeyframeGroup<Vector3D>? { position }
|
|
83
|
+
var _positionX: KeyframeGroup<Vector1D>? { nil }
|
|
84
|
+
var _positionY: KeyframeGroup<Vector1D>? { nil }
|
|
85
|
+
}
|