@octane-xplat/lottie 0.0.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -2
- package/dist/native/cx.mobile.js +11 -0
- package/dist/native/escape-props.js +39 -0
- package/dist/native/index.js +183 -0
- package/dist/native/layout-child.js +38 -0
- package/dist/native/octane-client-build.json +8 -0
- package/dist/native/vendor/ui-lottie/index.android.js +286 -0
- package/dist/native/vendor/ui-lottie/index.ios.js +214 -0
- package/dist/native/vendor/ui-lottie/src/lottie/index.common.js +50 -0
- package/dist/native/vendor/ui-lottie/src/lottie/utils.js +6 -0
- package/dist/web/escape-props.web.js +17 -0
- package/dist/web/index.js +346 -0
- package/dist/web/layout-child.web.js +47 -0
- package/dist/web/octane-client-build.json +8 -0
- package/package.json +104 -11
- package/platforms/android/include.gradle +7 -0
- package/platforms/android/java/com/nativescript/lottie/LottieAnimationView.java +92 -0
- package/platforms/android/lottie.aar +0 -0
- package/platforms/android/native-api-usage.json +16 -0
- package/platforms/ios/Podfile +5 -0
- package/platforms/macos/LICENSE-EpoxyCore-Apache-2.0.txt +201 -0
- package/platforms/macos/LICENSE-LRUCache-MIT.txt +22 -0
- package/platforms/macos/LICENSE-Lottie-Apache-2.0.txt +201 -0
- package/platforms/macos/LICENSE-ZIPFoundation-MIT.txt +21 -0
- package/platforms/macos/UPSTREAM.md +13 -0
- package/platforms/macos/resources/PrivacyInfo.xcprivacy +23 -0
- package/platforms/macos/resources/THIRD-PARTY-NOTICES.txt +10 -0
- package/platforms/macos/src/XplatAppKitLottie.swift +246 -0
- package/platforms/macos/src/vendor/Lottie/PrivacyInfo.xcprivacy +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +476 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +92 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CustomPathAnimation.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/DropShadowAnimation.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/EllipseAnimation.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/GradientAnimations.swift +287 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/LayerProperty.swift +440 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/OpacityAnimation.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/RectangleAnimation.swift +59 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/ShapeAnimation.swift +246 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/StarAnimation.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/StrokeAnimation.swift +96 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/TransformAnimations.swift +380 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/VisibilityAnimation.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/CompatibilityTracker.swift +129 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/CoreAnimationLayer.swift +645 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/Keyframes+combined.swift +345 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift +46 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/AnimationLayer.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/BaseAnimationLayer.swift +46 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +120 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/GradientRenderLayer.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ImageLayer.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +59 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +139 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/PreCompLayer.swift +107 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/RepeaterLayer.swift +113 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ShapeItemLayer.swift +346 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ShapeLayer.swift +569 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/SolidLayer.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/TextLayer.swift +157 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/TransformLayer.swift +13 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/ValueProviderStore.swift +157 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/Collection+Diff.swift +267 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/Diffable.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/DiffableSection.swift +16 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/IndexChangeset.swift +187 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/SectionedChangeset.swift +22 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Logging/EpoxyLogger.swift +102 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/CallbackContextEpoxyModeled.swift +8 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift +48 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift +158 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelStorage.swift +88 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModeled.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/AnyEpoxyModelProperty.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/ClassReference.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/AnimatedProviding.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DataIDProviding.swift +58 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidDisplayProviding.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidEndDisplayingProviding.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidSelectProviding.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ErasedContentProviding.swift +49 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/MakeViewProviding.swift +61 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetBehaviorsProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetContentProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/StyleIDProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/TraitCollectionProviding.swift +14 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewDifferentiatorProviding.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewProviding.swift +13 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/WillDisplayProviding.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/ViewEpoxyModeled.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/README.md +30 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift +165 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift +127 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +468 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/BehaviorsConfigurableView.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/ContentConfigurableView.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/EpoxyableView.swift +5 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/StyledView.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +257 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/LRUCache/README.md +24 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/README.md +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Deprecated.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +361 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift +205 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift +160 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+ReadingDeprecated.swift +50 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift +403 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+WritingDeprecated.swift +95 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+ZIP64.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive.swift +404 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +632 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+CompressionDeprecated.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+Serialization.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Date+ZIP.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry+Serialization.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift +170 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry.swift +669 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +405 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIPDeprecated.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/README.md +24 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/URL+ZIP.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +177 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/NullCompositionLayer.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +137 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.swift +60 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +247 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +321 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +56 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +424 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +55 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift +52 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift +62 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift +26 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueContainer.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/DropShadowNode.swift +102 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/LayerEffectNode.swift +25 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +281 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +74 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +69 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +253 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +64 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +158 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +165 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +143 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +173 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +238 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift +73 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +224 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +162 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +88 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +345 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift +197 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift +20 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift +60 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/Asset.swift +51 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/AssetLibrary.swift +75 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/ImageAsset.swift +141 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/PrecompAsset.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DictionaryInitializable.swift +73 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieAnimation.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieImageProvider.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieManifest.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieUtils.swift +71 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Extensions/Bundle.swift +58 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +71 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Keyframes/KeyframeData.swift +111 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Keyframes/KeyframeGroup.swift +265 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/DropShadowEffect.swift +52 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/EffectValue.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/LayerEffect.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerStyles/DropShadowStyle.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerStyles/LayerStyle.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/ImageLayerModel.swift +49 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/LayerModel.swift +266 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/PreCompLayerModel.swift +74 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/ShapeLayerModel.swift +50 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/SolidLayerModel.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/TextLayerModel.swift +65 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/DashPattern.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Marker.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Mask.swift +80 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Transform.swift +261 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Ellipse.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Fill.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/GradientFill.swift +142 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/GradientStroke.swift +244 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Group.swift +55 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Merge.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Rectangle.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Repeater.swift +181 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/RoundedCorners.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Shape.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/ShapeItem.swift +171 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/ShapeTransform.swift +202 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Star.swift +136 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Stroke.swift +144 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Trim.swift +90 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/Font.swift +67 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/Glyph.swift +94 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/TextAnimator.swift +240 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/TextDocument.swift +142 -0
- package/platforms/macos/src/vendor/Lottie/Private/RootAnimationLayer.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/AnimatorNodeDebugging.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/LayerDebugging.swift +231 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/TestHelpers.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/AnimationKeypathExtension.swift +303 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/BlendMode+Filter.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/CGColor+RGB.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/CGFloatExtensions.swift +152 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/DataExtension.swift +33 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/MathKit.swift +454 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/StringExtensions.swift +44 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/AnimationContext.swift +95 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/AnyEquatable.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/Binding+Map.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/View+ValueChanged.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/InterpolatableExtensions.swift +143 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/KeyframeExtensions.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/KeyframeInterpolator.swift +250 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/LottieAnimationSource.swift +51 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/BezierPath.swift +509 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/BezierPathRoundExtension.swift +163 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CGPointExtension.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/ColorExtension.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CompoundBezierPath.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CurveVertex.swift +190 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/PathElement.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/UnitBezier.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/VectorsExtensions.swift +368 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimation.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationHelpers.swift +317 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationLayer.swift +1582 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationView.swift +1090 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationViewInitializers.swift +226 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottiePlaybackMode.swift +266 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieView.swift +643 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/AnimationCacheProvider.swift +21 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/DefaultAnimationCache.swift +67 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/LRUAnimationCache.swift +11 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/LottieAnimationCache.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/DecodingStrategy.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/LottieConfiguration.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/LottieURLSession.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/ReducedMotionOption.swift +128 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/RenderingEngineOption.swift +117 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedButton.swift +128 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedControl.swift +248 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedSwitch.swift +271 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieButton.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieSwitch.swift +144 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieViewType.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/Cache/DotLottieCache.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/Cache/DotLottieCacheProvider.swift +21 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieConfiguration.swift +72 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieFile.swift +186 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieFileHelpers.swift +386 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/AnimationKeypath.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/AnyValueProvider.swift +132 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +96 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +138 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/FontProvider/AnimationFontProvider.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Public/ImageProvider/AnimationImageProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/Keyframes/Interpolatable.swift +285 -0
- package/platforms/macos/src/vendor/Lottie/Public/Keyframes/Keyframe.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Public/Logging/LottieLogger.swift +138 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/AnimationTime.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/LottieColor.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/Vectors.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Public/TextProvider/AnimationTextProvider.swift +135 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/AnimationSubview.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/BundleImageProvider.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift +33 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleAnimationView.swift +567 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleFontProvider.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleImageProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/FilepathImageProvider.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/LottieAnimationViewBase.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/UIColorExtension.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/AnimationSubview.macOS.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/BundleImageProvider.macOS.swift +90 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/FilepathImageProvider.macOS.swift +86 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/LottieAnimationViewBase.macOS.swift +102 -0
- package/src/Lottie.macos.tsrx +129 -0
- package/src/Lottie.tsrx +162 -0
- package/src/Lottie.web.tsrx +152 -0
- package/src/cx.mobile.ts +8 -0
- package/src/escape-props.ts +65 -0
- package/src/escape-props.web.ts +25 -0
- package/src/index.macos.ts +2 -0
- package/src/index.ts +2 -0
- package/src/index.web.ts +2 -0
- package/src/layout-child.ts +57 -0
- package/src/layout-child.web.ts +108 -0
- package/src/native-elements.d.ts +8 -0
- package/src/props.ts +133 -0
- package/src/references.d.ts +3 -0
- package/src/vendor/ui-lottie/LICENSE.md +21 -0
- package/src/vendor/ui-lottie/src/lottie/index.android.ts +447 -0
- package/src/vendor/ui-lottie/src/lottie/index.common.ts +84 -0
- package/src/vendor/ui-lottie/src/lottie/index.d.ts +133 -0
- package/src/vendor/ui-lottie/src/lottie/index.ios.ts +345 -0
- package/src/vendor/ui-lottie/src/lottie/typings/android.d.ts +4149 -0
- package/src/vendor/ui-lottie/src/lottie/typings/android.nativescript.d.ts +12 -0
- package/src/vendor/ui-lottie/src/lottie/typings/dotlottie.ios.d.ts +14 -0
- package/src/vendor/ui-lottie/src/lottie/typings/ios.d.ts +384 -0
- package/src/vendor/ui-lottie/src/lottie/utils.ts +9 -0
- package/types/generated/.tsrx-typegen-manifest.json +18 -0
- package/types/generated/Lottie.d.ts +7 -0
- package/types/generated/Lottie.web.d.ts +7 -0
- package/types/generated/cx.mobile.d.ts +6 -0
- package/types/generated/escape-props.d.ts +15 -0
- package/types/generated/escape-props.web.d.ts +5 -0
- package/types/generated/index.d.ts +2 -0
- package/types/generated/index.web.d.ts +2 -0
- package/types/generated/layout-child.d.ts +6 -0
- package/types/generated/layout-child.web.d.ts +15 -0
- package/types/generated/props.d.ts +110 -0
- package/types/generated/vendor/ui-lottie/src/lottie/index.common.d.ts +30 -0
- package/types/generated/vendor/ui-lottie/src/lottie/index.ios.d.ts +35 -0
- package/types/generated/vendor/ui-lottie/src/lottie/utils.d.ts +1 -0
- package/index.d.ts +0 -1
- package/index.js +0 -2
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
// Created by Cal Stephens on 12/14/21.
|
|
2
|
+
// Copyright © 2021 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - ShapeLayer
|
|
7
|
+
|
|
8
|
+
/// The CALayer type responsible for rendering `ShapeLayerModel`s
|
|
9
|
+
final class ShapeLayer: BaseCompositionLayer {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(shapeLayer: ShapeLayerModel, context: LayerContext) throws {
|
|
14
|
+
self.shapeLayer = shapeLayer
|
|
15
|
+
super.init(layerModel: shapeLayer)
|
|
16
|
+
try setUpGroups(context: context)
|
|
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
|
+
shapeLayer = typedLayer.shapeLayer
|
|
31
|
+
super.init(layer: typedLayer)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// MARK: Private
|
|
35
|
+
|
|
36
|
+
private let shapeLayer: ShapeLayerModel
|
|
37
|
+
|
|
38
|
+
private func setUpGroups(context: LayerContext) throws {
|
|
39
|
+
let shapeItems = shapeLayer.items.map { ShapeItemLayer.Item(item: $0, groupPath: []) }
|
|
40
|
+
try setupGroups(from: shapeItems, parentGroup: nil, parentGroupPath: [], context: context)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// MARK: - GroupLayer
|
|
46
|
+
|
|
47
|
+
/// The CALayer type responsible for rendering `Group`s
|
|
48
|
+
final class GroupLayer: BaseAnimationLayer {
|
|
49
|
+
|
|
50
|
+
// MARK: Lifecycle
|
|
51
|
+
|
|
52
|
+
init(group: Group, items: [ShapeItemLayer.Item], groupPath: [String], context: LayerContext) throws {
|
|
53
|
+
self.group = group
|
|
54
|
+
self.items = items
|
|
55
|
+
self.groupPath = groupPath
|
|
56
|
+
super.init()
|
|
57
|
+
try setupLayerHierarchy(context: context)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
required init?(coder _: NSCoder) {
|
|
61
|
+
fatalError("init(coder:) has not been implemented")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Called by CoreAnimation to create a shadow copy of this layer
|
|
65
|
+
/// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
|
|
66
|
+
override init(layer: Any) {
|
|
67
|
+
guard let typedLayer = layer as? Self else {
|
|
68
|
+
fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
group = typedLayer.group
|
|
72
|
+
items = typedLayer.items
|
|
73
|
+
groupPath = typedLayer.groupPath
|
|
74
|
+
super.init(layer: typedLayer)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: Internal
|
|
78
|
+
|
|
79
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
80
|
+
try super.setupAnimations(context: context)
|
|
81
|
+
|
|
82
|
+
if let (shapeTransform, context) = nonGroupItems.first(ShapeTransform.self, context: context) {
|
|
83
|
+
try addTransformAnimations(for: shapeTransform, context: context)
|
|
84
|
+
try addOpacityAnimation(for: shapeTransform, context: context)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// MARK: Private
|
|
89
|
+
|
|
90
|
+
private let group: Group
|
|
91
|
+
|
|
92
|
+
/// `ShapeItemLayer.Item`s rendered by this `Group`
|
|
93
|
+
/// - In the original `ShapeLayer` data model, these items could have originated from a different group
|
|
94
|
+
private let items: [ShapeItemLayer.Item]
|
|
95
|
+
|
|
96
|
+
/// The keypath that represents this group, with respect to the parent `ShapeLayer`
|
|
97
|
+
/// - Due to the way `GroupLayer`s are setup, the original `ShapeItem`
|
|
98
|
+
/// hierarchy from the `ShapeLayer` data model may no longer exactly
|
|
99
|
+
/// match the hierarchy of `GroupLayer` / `ShapeItemLayer`s constructed
|
|
100
|
+
/// at runtime. Since animation keypaths need to match the original
|
|
101
|
+
/// structure of the `ShapeLayer` data model, we track that info here.
|
|
102
|
+
private let groupPath: [String]
|
|
103
|
+
|
|
104
|
+
/// Child group items contained in this group. Correspond to a child `GroupLayer`
|
|
105
|
+
private lazy var childGroups = items.filter { $0.item is Group }
|
|
106
|
+
|
|
107
|
+
/// `ShapeItem`s (other than nested `Group`s) that are rendered by this layer
|
|
108
|
+
private lazy var nonGroupItems = items.filter { !($0.item is Group) }
|
|
109
|
+
|
|
110
|
+
private func setupLayerHierarchy(context: LayerContext) throws {
|
|
111
|
+
// Groups can contain other groups, so we may have to continue
|
|
112
|
+
// recursively creating more `GroupLayer`s
|
|
113
|
+
try setupGroups(from: items, parentGroup: group, parentGroupPath: groupPath, context: context)
|
|
114
|
+
|
|
115
|
+
// Create `ShapeItemLayer`s for each subgroup of shapes that should be rendered as a single unit
|
|
116
|
+
// - These groups are listed from front-to-back, so we have to add the sublayers in reverse order
|
|
117
|
+
let renderGroups = items.shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: !childGroups.isEmpty)
|
|
118
|
+
for shapeRenderGroup in renderGroups.validGroups.reversed() {
|
|
119
|
+
// When there are multiple path-drawing items, they're supposed to be rendered
|
|
120
|
+
// in a single `CAShapeLayer` (instead of rendering them in separate layers) so
|
|
121
|
+
// `CAShapeLayerFillRule.evenOdd` can be applied correctly if the paths overlap.
|
|
122
|
+
// Since a `CAShapeLayer` only supports animating a single `CGPath` from a single `KeyframeGroup<BezierPath>`,
|
|
123
|
+
// this requires combining all of the path-drawing items into a single set of keyframes.
|
|
124
|
+
if
|
|
125
|
+
shapeRenderGroup.pathItems.count > 1,
|
|
126
|
+
// We currently only support this codepath for `Shape` items that directly contain bezier path keyframes.
|
|
127
|
+
// We could also support this for other path types like rectangles, ellipses, and polygons with more work.
|
|
128
|
+
shapeRenderGroup.pathItems.allSatisfy({ $0.item is Shape }),
|
|
129
|
+
// `Trim`s are currently only applied correctly using individual `ShapeItemLayer`s,
|
|
130
|
+
// because each path has to be trimmed separately.
|
|
131
|
+
!shapeRenderGroup.otherItems.contains(where: { $0.item is Trim })
|
|
132
|
+
{
|
|
133
|
+
let allPathKeyframes = shapeRenderGroup.pathItems.compactMap { ($0.item as? Shape)?.path }
|
|
134
|
+
let combinedShape = CombinedShapeItem(
|
|
135
|
+
shapes: Keyframes.combined(allPathKeyframes),
|
|
136
|
+
name: group.name
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
let sublayer = try ShapeItemLayer(
|
|
140
|
+
shape: ShapeItemLayer.Item(item: combinedShape, groupPath: shapeRenderGroup.pathItems[0].groupPath),
|
|
141
|
+
otherItems: shapeRenderGroup.otherItems,
|
|
142
|
+
context: context
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
addSublayer(sublayer)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Otherwise, if each `ShapeItem` that draws a `GGPath` animates independently,
|
|
149
|
+
// we have to create a separate `ShapeItemLayer` for each one. This may render
|
|
150
|
+
// incorrectly if there are multiple paths that overlap with each other.
|
|
151
|
+
else {
|
|
152
|
+
for pathDrawingItem in shapeRenderGroup.pathItems {
|
|
153
|
+
let sublayer = try ShapeItemLayer(
|
|
154
|
+
shape: pathDrawingItem,
|
|
155
|
+
otherItems: shapeRenderGroup.otherItems,
|
|
156
|
+
context: context
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
addSublayer(sublayer)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
extension CALayer {
|
|
168
|
+
|
|
169
|
+
// MARK: Fileprivate
|
|
170
|
+
|
|
171
|
+
/// Sets up `GroupLayer`s for each `Group` in the given list of `ShapeItem`s
|
|
172
|
+
/// - Each `Group` item becomes its own `GroupLayer` sublayer.
|
|
173
|
+
/// - Other `ShapeItem` are applied to all sublayers
|
|
174
|
+
fileprivate func setupGroups(
|
|
175
|
+
from items: [ShapeItemLayer.Item],
|
|
176
|
+
parentGroup: Group?,
|
|
177
|
+
parentGroupPath: [String],
|
|
178
|
+
context: LayerContext
|
|
179
|
+
) throws {
|
|
180
|
+
// If the layer has any `Repeater`s, set up each repeater
|
|
181
|
+
// and then handle any remaining groups like normal.
|
|
182
|
+
if items.contains(where: { $0.item is Repeater }) {
|
|
183
|
+
let repeaterGroupings = items.split(whereSeparator: { $0.item is Repeater })
|
|
184
|
+
|
|
185
|
+
// Iterate through the groupings backwards to preserve the expected rendering order
|
|
186
|
+
for repeaterGrouping in repeaterGroupings.reversed() {
|
|
187
|
+
// Each repeater applies to the previous items in the list
|
|
188
|
+
if let repeater = repeaterGrouping.trailingSeparator?.item as? Repeater {
|
|
189
|
+
try setUpRepeater(
|
|
190
|
+
repeater,
|
|
191
|
+
items: repeaterGrouping.grouping,
|
|
192
|
+
parentGroupPath: parentGroupPath,
|
|
193
|
+
context: context
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Any remaining items after the last repeater are handled like normal
|
|
198
|
+
else {
|
|
199
|
+
try setupGroups(
|
|
200
|
+
from: repeaterGrouping.grouping,
|
|
201
|
+
parentGroup: parentGroup,
|
|
202
|
+
parentGroupPath: parentGroupPath,
|
|
203
|
+
context: context
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
else {
|
|
210
|
+
let groupLayers = try makeGroupLayers(
|
|
211
|
+
from: items,
|
|
212
|
+
parentGroup: parentGroup,
|
|
213
|
+
parentGroupPath: parentGroupPath,
|
|
214
|
+
context: context
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
for groupLayer in groupLayers {
|
|
218
|
+
addSublayer(groupLayer)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// MARK: Private
|
|
224
|
+
|
|
225
|
+
/// Sets up this layer using the given `Repeater`
|
|
226
|
+
private func setUpRepeater(
|
|
227
|
+
_ repeater: Repeater,
|
|
228
|
+
items allItems: [ShapeItemLayer.Item],
|
|
229
|
+
parentGroupPath: [String],
|
|
230
|
+
context: LayerContext
|
|
231
|
+
) throws {
|
|
232
|
+
let items = allItems.filter { !($0.item is Repeater) }
|
|
233
|
+
let copyCount = Int(try repeater.copies.exactlyOneKeyframe(context: context, description: "repeater copies").value)
|
|
234
|
+
|
|
235
|
+
for index in 0..<copyCount {
|
|
236
|
+
let groupLayers = try makeGroupLayers(
|
|
237
|
+
from: items,
|
|
238
|
+
parentGroup: nil, // The repeater layer acts as the parent of its sublayers
|
|
239
|
+
parentGroupPath: parentGroupPath,
|
|
240
|
+
context: context
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
for groupLayer in groupLayers {
|
|
244
|
+
let repeatedLayer = RepeaterLayer(repeater: repeater, childLayer: groupLayer, index: index)
|
|
245
|
+
addSublayer(repeatedLayer)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/// Creates a `GroupLayer` for each `Group` in the given list of `ShapeItem`s
|
|
251
|
+
/// - Each `Group` item becomes its own `GroupLayer` sublayer.
|
|
252
|
+
/// - Other `ShapeItem` are applied to all sublayers
|
|
253
|
+
private func makeGroupLayers(
|
|
254
|
+
from items: [ShapeItemLayer.Item],
|
|
255
|
+
parentGroup: Group?,
|
|
256
|
+
parentGroupPath: [String],
|
|
257
|
+
context: LayerContext
|
|
258
|
+
) throws -> [GroupLayer] {
|
|
259
|
+
var groupItems = items.compactMap { $0.item as? Group }.filter { !$0.hidden }
|
|
260
|
+
var otherItems = items.filter { !($0.item is Group) && !$0.item.hidden }
|
|
261
|
+
|
|
262
|
+
// Handle the top-level `shapeLayer.items` array. This is typically just a single `Group`,
|
|
263
|
+
// but in practice can be any combination of items. The implementation expects all path-drawing
|
|
264
|
+
// shape items to be managed by a `GroupLayer`, so if there's a top-level path item we
|
|
265
|
+
// have to create a placeholder group.
|
|
266
|
+
if parentGroup == nil, otherItems.contains(where: { $0.item.drawsCGPath }) {
|
|
267
|
+
groupItems = [Group(items: items.map { $0.item }, name: "")]
|
|
268
|
+
otherItems = []
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Any child items that wouldn't be included in a valid shape render group
|
|
272
|
+
// need to be applied to child groups (otherwise they'd be silently ignored).
|
|
273
|
+
let inheritedItemsForChildGroups = otherItems
|
|
274
|
+
.shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: !groupItems.isEmpty)
|
|
275
|
+
.unusedItems
|
|
276
|
+
|
|
277
|
+
// Groups are listed from front to back,
|
|
278
|
+
// but `CALayer.sublayers` are listed from back to front.
|
|
279
|
+
let groupsInZAxisOrder = groupItems.reversed()
|
|
280
|
+
|
|
281
|
+
return try groupsInZAxisOrder.compactMap { group in
|
|
282
|
+
var pathForChildren = parentGroupPath
|
|
283
|
+
if !group.name.isEmpty {
|
|
284
|
+
pathForChildren.append(group.name)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let childItems = group.items
|
|
288
|
+
.filter { !$0.hidden }
|
|
289
|
+
.map { ShapeItemLayer.Item(item: $0, groupPath: pathForChildren) }
|
|
290
|
+
|
|
291
|
+
// Some shape item properties are affected by scaling (e.g. stroke width).
|
|
292
|
+
// The child group may have a `ShapeTransform` that affects the scale of its items,
|
|
293
|
+
// but shouldn't affect the scale of any inherited items. To prevent this scale
|
|
294
|
+
// from affecting inherited items, we have to apply an inverse scale to them.
|
|
295
|
+
let inheritedItems = try inheritedItemsForChildGroups.map { item in
|
|
296
|
+
ShapeItemLayer.Item(
|
|
297
|
+
item: try item.item.scaledCopyForChildGroup(group, context: context),
|
|
298
|
+
groupPath: item.groupPath
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return try GroupLayer(
|
|
303
|
+
group: group,
|
|
304
|
+
items: childItems + inheritedItems,
|
|
305
|
+
groupPath: pathForChildren,
|
|
306
|
+
context: context
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
extension ShapeItem {
|
|
313
|
+
/// Whether or not this `ShapeItem` is responsible for rendering a `CGPath`
|
|
314
|
+
var drawsCGPath: Bool {
|
|
315
|
+
switch type {
|
|
316
|
+
case .ellipse, .rectangle, .shape, .star:
|
|
317
|
+
true
|
|
318
|
+
|
|
319
|
+
case .fill, .gradientFill, .group, .gradientStroke, .merge,
|
|
320
|
+
.repeater, .round, .stroke, .trim, .transform, .unknown:
|
|
321
|
+
false
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/// Whether or not this `ShapeItem` provides a fill for a set of shapes
|
|
326
|
+
var isFill: Bool {
|
|
327
|
+
switch type {
|
|
328
|
+
case .fill, .gradientFill:
|
|
329
|
+
true
|
|
330
|
+
|
|
331
|
+
case .ellipse, .rectangle, .shape, .star, .group, .gradientStroke,
|
|
332
|
+
.merge, .repeater, .round, .stroke, .trim, .transform, .unknown:
|
|
333
|
+
false
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/// Whether or not this `ShapeItem` provides a stroke for a set of shapes
|
|
338
|
+
var isStroke: Bool {
|
|
339
|
+
switch type {
|
|
340
|
+
case .stroke, .gradientStroke:
|
|
341
|
+
true
|
|
342
|
+
|
|
343
|
+
case .ellipse, .rectangle, .shape, .star, .group, .gradientFill,
|
|
344
|
+
.merge, .repeater, .round, .fill, .trim, .transform, .unknown:
|
|
345
|
+
false
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/// For any inherited shape items that are affected by scaling (e.g. strokes but not fills),
|
|
350
|
+
/// any `ShapeTransform` in the given child group isn't supposed to be applied to the item.
|
|
351
|
+
/// To cancel out the effect of the transform, we can apply an inverse transform to the
|
|
352
|
+
/// shape item.
|
|
353
|
+
func scaledCopyForChildGroup(_ childGroup: Group, context: LayerContext) throws -> ShapeItem {
|
|
354
|
+
guard
|
|
355
|
+
// Path-drawing items aren't inherited by child groups in this way
|
|
356
|
+
!drawsCGPath,
|
|
357
|
+
// Stroke widths are affected by scaling, but fill colors aren't.
|
|
358
|
+
// We can expand this to other types of items in the future if necessary.
|
|
359
|
+
let stroke = self as? StrokeShapeItem,
|
|
360
|
+
// We only need to handle scaling if there's a `ShapeTransform` present
|
|
361
|
+
let transform = childGroup.items.first(where: { $0 is ShapeTransform }) as? ShapeTransform
|
|
362
|
+
else { return self }
|
|
363
|
+
|
|
364
|
+
let newWidth = try Keyframes.combined(stroke.width, transform.scale) { strokeWidth, scale -> LottieVector1D in
|
|
365
|
+
// Since we're applying this scale to a scalar value rather than to a layer,
|
|
366
|
+
// we can only handle cases where the scale is also a scalar (e.g. the same for both x and y)
|
|
367
|
+
try context.compatibilityAssert(scale.x == scale.y, """
|
|
368
|
+
The Core Animation rendering engine doesn't support applying separate x/y scale values \
|
|
369
|
+
(x: \(scale.x), y: \(scale.y)) to this stroke item (\(self.name)).
|
|
370
|
+
""")
|
|
371
|
+
|
|
372
|
+
return LottieVector1D(strokeWidth.value * (100 / scale.x))
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return stroke.copy(width: newWidth)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
extension Collection {
|
|
380
|
+
/// Splits this collection into two groups, based on the given predicate
|
|
381
|
+
func grouped(by predicate: (Element) -> Bool) -> (trueElements: [Element], falseElements: [Element]) {
|
|
382
|
+
var trueElements = [Element]()
|
|
383
|
+
var falseElements = [Element]()
|
|
384
|
+
|
|
385
|
+
for element in self {
|
|
386
|
+
if predicate(element) {
|
|
387
|
+
trueElements.append(element)
|
|
388
|
+
} else {
|
|
389
|
+
falseElements.append(element)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return (trueElements, falseElements)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/// Splits this collection into an array of grouping separated by the given separator.
|
|
397
|
+
/// For example, `[A, B, C]` split by `B` returns an array with two elements:
|
|
398
|
+
/// 1. `(grouping: [A], trailingSeparator: B)`
|
|
399
|
+
/// 2. `(grouping: [C], trailingSeparator: nil)`
|
|
400
|
+
func split(whereSeparator separatorPredicate: (Element) -> Bool)
|
|
401
|
+
-> [(grouping: [Element], trailingSeparator: Element?)]
|
|
402
|
+
{
|
|
403
|
+
guard !isEmpty else { return [] }
|
|
404
|
+
|
|
405
|
+
var groupings = [(grouping: [Element], trailingSeparator: Element?)]()
|
|
406
|
+
|
|
407
|
+
for element in self {
|
|
408
|
+
if groupings.isEmpty || groupings.last?.trailingSeparator != nil {
|
|
409
|
+
groupings.append((grouping: [], trailingSeparator: nil))
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if separatorPredicate(element) {
|
|
413
|
+
groupings[groupings.indices.last!].trailingSeparator = element
|
|
414
|
+
} else {
|
|
415
|
+
groupings[groupings.indices.last!].grouping.append(element)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return groupings
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// MARK: - ShapeRenderGroup
|
|
424
|
+
|
|
425
|
+
/// A group of `ShapeItem`s that should be rendered together as a single unit
|
|
426
|
+
struct ShapeRenderGroup {
|
|
427
|
+
/// The items in this group that render `CGPath`s.
|
|
428
|
+
/// Valid shape render groups must have at least one path-drawing item.
|
|
429
|
+
var pathItems = [ShapeItemLayer.Item]()
|
|
430
|
+
/// Shape items that modify the appearance of the shapes rendered by this group
|
|
431
|
+
var otherItems = [ShapeItemLayer.Item]()
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
extension [ShapeItemLayer.Item] {
|
|
435
|
+
/// Splits this list of `ShapeItem`s into groups that should be rendered together as individual units,
|
|
436
|
+
/// plus the remaining items that were not included in any group.
|
|
437
|
+
/// - groupHasChildGroupsToInheritUnusedItems: whether or not this group has child groups
|
|
438
|
+
/// that will inherit any items that aren't used as part of a valid render group
|
|
439
|
+
func shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: Bool)
|
|
440
|
+
-> (validGroups: [ShapeRenderGroup], unusedItems: [ShapeItemLayer.Item])
|
|
441
|
+
{
|
|
442
|
+
var renderGroups = [ShapeRenderGroup()]
|
|
443
|
+
|
|
444
|
+
for item in self {
|
|
445
|
+
// `renderGroups` is non-empty, so is guaranteed to have a valid end index
|
|
446
|
+
var lastIndex: Int {
|
|
447
|
+
renderGroups.indices.last!
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if item.item.drawsCGPath {
|
|
451
|
+
// Trims should only affect paths that precede them in the group,
|
|
452
|
+
// so if the existing group already has a trim we create a new group for this path item.
|
|
453
|
+
if renderGroups[lastIndex].otherItems.contains(where: { $0.item is Trim }) {
|
|
454
|
+
renderGroups.append(ShapeRenderGroup())
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
renderGroups[lastIndex].pathItems.append(item)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// `Fill` items are unique, because they specifically only apply to _previous_ shapes in a `Group`
|
|
461
|
+
// - For example, with [Rectangle, Fill(Red), Circle, Fill(Blue)], the Rectangle should be Red
|
|
462
|
+
// but the Circle should be Blue.
|
|
463
|
+
// - To handle this, we create a new `ShapeRenderGroup` when we encounter a `Fill` item
|
|
464
|
+
else if item.item.isFill {
|
|
465
|
+
renderGroups[lastIndex].otherItems.append(item)
|
|
466
|
+
|
|
467
|
+
// There are cases where the current render group doesn't have a path-drawing
|
|
468
|
+
// shape item yet, and could just contain this fill. Some examples:
|
|
469
|
+
// - `[Circle, Fill(Red), Fill(Green)]`: In this case, the second fill would
|
|
470
|
+
// be unused and silently ignored. To avoid this we render the fill using
|
|
471
|
+
// the shape items from the previous group.
|
|
472
|
+
// - `[Circle, Fill(Red), Group, Fill(Green)]`: In this case, the second fill
|
|
473
|
+
// is inherited and rendered by the child group.
|
|
474
|
+
if
|
|
475
|
+
renderGroups[lastIndex].pathItems.isEmpty,
|
|
476
|
+
!groupHasChildGroupsToInheritUnusedItems,
|
|
477
|
+
lastIndex != renderGroups.indices.first
|
|
478
|
+
{
|
|
479
|
+
renderGroups[lastIndex].pathItems = renderGroups[lastIndex - 1].pathItems
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Finalize the group so the fill item doesn't affect following shape items
|
|
483
|
+
renderGroups.append(ShapeRenderGroup())
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Other items in the list are applied to all subgroups
|
|
487
|
+
else {
|
|
488
|
+
for index in renderGroups.indices {
|
|
489
|
+
renderGroups[index].otherItems.append(item)
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/// The main thread rendering engine draws each Stroke and Fill as a separate `CAShapeLayer`.
|
|
495
|
+
/// As an optimization, we can combine them into a single shape layer when a few conditions are met:
|
|
496
|
+
/// 1. There is at most one stroke and one fill (a `CAShapeLayer` can only render one of each)
|
|
497
|
+
/// 2. The stroke is drawn on top of the fill (the behavior of a `CAShapeLayer`)
|
|
498
|
+
/// 3. The fill and stroke have the same `opacity` animations (since a `CAShapeLayer` can only render
|
|
499
|
+
/// a single set of `opacity` animations).
|
|
500
|
+
/// Otherwise, each stroke / fill needs to be split into a separate layer.
|
|
501
|
+
renderGroups = renderGroups.flatMap { group -> [ShapeRenderGroup] in
|
|
502
|
+
let (strokesAndFills, otherItems) = group.otherItems.grouped(by: { $0.item.isFill || $0.item.isStroke })
|
|
503
|
+
let (strokes, fills) = strokesAndFills.grouped(by: { $0.item.isStroke })
|
|
504
|
+
|
|
505
|
+
// A `CAShapeLayer` can only draw a single fill and a single stroke
|
|
506
|
+
let hasAtMostOneFill = fills.count <= 1
|
|
507
|
+
let hasAtMostOneStroke = strokes.count <= 1
|
|
508
|
+
|
|
509
|
+
// A `CAShapeLayer` can only draw a stroke on top of a fill -- if the fill is supposed to be
|
|
510
|
+
// drawn on top of the stroke, then they have to be rendered as separate layers.
|
|
511
|
+
let strokeDrawnOnTopOfFill: Bool =
|
|
512
|
+
if
|
|
513
|
+
let strokeIndex = strokesAndFills.firstIndex(where: { $0.item.isStroke }),
|
|
514
|
+
let fillIndex = strokesAndFills.firstIndex(where: { $0.item.isFill })
|
|
515
|
+
{
|
|
516
|
+
strokeIndex < fillIndex
|
|
517
|
+
} else {
|
|
518
|
+
false
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// `Fill` and `Stroke` items have an `alpha` property that can be animated separately,
|
|
522
|
+
// but each layer only has a single `opacity` property. We can only use a single `CAShapeLayer`
|
|
523
|
+
// when the items have the same `alpha` animations.
|
|
524
|
+
let allAlphaAnimationsAreIdentical = {
|
|
525
|
+
strokesAndFills.allSatisfy { item in
|
|
526
|
+
(item.item as? OpacityAnimationModel)?.opacity
|
|
527
|
+
== (strokesAndFills.first?.item as? OpacityAnimationModel)?.opacity
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// If all the required conditions are met, this group can be rendered using a single `ShapeItemLayer`
|
|
532
|
+
if
|
|
533
|
+
hasAtMostOneFill,
|
|
534
|
+
hasAtMostOneStroke,
|
|
535
|
+
strokeDrawnOnTopOfFill,
|
|
536
|
+
allAlphaAnimationsAreIdentical()
|
|
537
|
+
{
|
|
538
|
+
return [group]
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Otherwise each stroke / fill needs to be rendered as a separate `ShapeItemLayer`
|
|
542
|
+
return strokesAndFills.map { strokeOrFill in
|
|
543
|
+
ShapeRenderGroup(
|
|
544
|
+
pathItems: group.pathItems,
|
|
545
|
+
otherItems: [strokeOrFill] + otherItems
|
|
546
|
+
)
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// All valid render groups must have a path, otherwise the items wouldn't be rendered
|
|
551
|
+
renderGroups = renderGroups.filter { renderGroup in
|
|
552
|
+
!renderGroup.pathItems.isEmpty
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
let itemsInValidRenderGroups = Set(
|
|
556
|
+
renderGroups.lazy
|
|
557
|
+
.flatMap { $0.pathItems + $0.otherItems }
|
|
558
|
+
.map { ObjectIdentifier($0.item) }
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
// `unusedItems` should only include each original item a single time,
|
|
562
|
+
// and should preserve the existing order
|
|
563
|
+
let itemsNotInValidRenderGroups = filter { item in
|
|
564
|
+
!itemsInValidRenderGroups.contains(ObjectIdentifier(item.item))
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return (validGroups: renderGroups, unusedItems: itemsNotInValidRenderGroups)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Created by Cal Stephens on 12/13/21.
|
|
2
|
+
// Copyright © 2021 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import QuartzCore
|
|
5
|
+
|
|
6
|
+
// MARK: - SolidLayer
|
|
7
|
+
|
|
8
|
+
final class SolidLayer: BaseCompositionLayer {
|
|
9
|
+
|
|
10
|
+
// MARK: Lifecycle
|
|
11
|
+
|
|
12
|
+
init(_ solidLayer: SolidLayerModel) {
|
|
13
|
+
self.solidLayer = solidLayer
|
|
14
|
+
super.init(layerModel: solidLayer)
|
|
15
|
+
setupContentLayer()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
required init?(coder _: NSCoder) {
|
|
19
|
+
fatalError("init(coder:) has not been implemented")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// Called by CoreAnimation to create a shadow copy of this layer
|
|
23
|
+
/// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
|
|
24
|
+
override init(layer: Any) {
|
|
25
|
+
guard let typedLayer = layer as? Self else {
|
|
26
|
+
fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
solidLayer = typedLayer.solidLayer
|
|
30
|
+
super.init(layer: typedLayer)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// MARK: Internal
|
|
34
|
+
|
|
35
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
36
|
+
try super.setupAnimations(context: context)
|
|
37
|
+
|
|
38
|
+
var context = context
|
|
39
|
+
context = context.addingKeypathComponent(solidLayer.name)
|
|
40
|
+
|
|
41
|
+
// Even though the Lottie json schema provides a fixed `solidLayer.colorHex` value,
|
|
42
|
+
// we still need to create a set of keyframes and go through the standard `CAAnimation`
|
|
43
|
+
// codepath so that this value can be customized using the custom `ValueProvider`s API.
|
|
44
|
+
try shapeLayer.addAnimation(
|
|
45
|
+
for: .fillColor,
|
|
46
|
+
keyframes: KeyframeGroup(solidLayer.colorHex.lottieColor),
|
|
47
|
+
value: { $0.cgColorValue },
|
|
48
|
+
context: context
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// MARK: Private
|
|
53
|
+
|
|
54
|
+
private let solidLayer: SolidLayerModel
|
|
55
|
+
|
|
56
|
+
/// Render the fill color in a child `CAShapeLayer`
|
|
57
|
+
/// - Using a `CAShapeLayer` specifically, instead of a `CALayer` with a `backgroundColor`,
|
|
58
|
+
/// allows the size of the fill shape to be different from `contentsLayer.size`.
|
|
59
|
+
private let shapeLayer = CAShapeLayer()
|
|
60
|
+
|
|
61
|
+
private func setupContentLayer() {
|
|
62
|
+
shapeLayer.path = CGPath(rect: .init(x: 0, y: 0, width: solidLayer.width, height: solidLayer.height), transform: nil)
|
|
63
|
+
addSublayer(shapeLayer)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|