├── Podfile
├── Podfile.lock
├── Pods
├── Manifest.lock
├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ │ └── shubham.xcuserdatad
│ │ └── xcschemes
│ │ ├── Pods-UserOnboarding.xcscheme
│ │ ├── lottie-ios.xcscheme
│ │ └── xcschememanagement.plist
├── Target Support Files
│ ├── Pods-UserOnboarding
│ │ ├── Pods-UserOnboarding-Info.plist
│ │ ├── Pods-UserOnboarding-acknowledgements.markdown
│ │ ├── Pods-UserOnboarding-acknowledgements.plist
│ │ ├── Pods-UserOnboarding-dummy.m
│ │ ├── Pods-UserOnboarding-frameworks-Debug-input-files.xcfilelist
│ │ ├── Pods-UserOnboarding-frameworks-Debug-output-files.xcfilelist
│ │ ├── Pods-UserOnboarding-frameworks-Release-input-files.xcfilelist
│ │ ├── Pods-UserOnboarding-frameworks-Release-output-files.xcfilelist
│ │ ├── Pods-UserOnboarding-frameworks.sh
│ │ ├── Pods-UserOnboarding-umbrella.h
│ │ ├── Pods-UserOnboarding.debug.xcconfig
│ │ ├── Pods-UserOnboarding.modulemap
│ │ └── Pods-UserOnboarding.release.xcconfig
│ └── lottie-ios
│ │ ├── lottie-ios-Info.plist
│ │ ├── lottie-ios-dummy.m
│ │ ├── lottie-ios-prefix.pch
│ │ ├── lottie-ios-umbrella.h
│ │ ├── lottie-ios.modulemap
│ │ └── lottie-ios.xcconfig
└── lottie-ios
│ ├── LICENSE
│ ├── README.md
│ └── lottie-swift
│ └── src
│ ├── Private
│ ├── LayerContainers
│ │ ├── AnimationContainer.swift
│ │ ├── CompLayers
│ │ │ ├── CompositionLayer.swift
│ │ │ ├── ImageCompositionLayer.swift
│ │ │ ├── MaskContainerLayer.swift
│ │ │ ├── NullCompositionLayer.swift
│ │ │ ├── PreCompositionLayer.swift
│ │ │ ├── ShapeCompositionLayer.swift
│ │ │ ├── SolidCompositionLayer.swift
│ │ │ └── TextCompositionLayer.swift
│ │ └── Utility
│ │ │ ├── CompositionLayersInitializer.swift
│ │ │ ├── InvertedMatteLayer.swift
│ │ │ ├── LayerImageProvider.swift
│ │ │ ├── LayerTextProvider.swift
│ │ │ └── LayerTransformNode.swift
│ ├── Model
│ │ ├── Animation.swift
│ │ ├── Assets
│ │ │ ├── Asset.swift
│ │ │ ├── AssetLibrary.swift
│ │ │ ├── ImageAsset.swift
│ │ │ └── PrecompAsset.swift
│ │ ├── Extensions
│ │ │ └── KeyedDecodingContainerExtensions.swift
│ │ ├── Keyframes
│ │ │ ├── Keyframe.swift
│ │ │ └── KeyframeGroup.swift
│ │ ├── Layers
│ │ │ ├── ImageLayerModel.swift
│ │ │ ├── LayerModel.swift
│ │ │ ├── PreCompLayerModel.swift
│ │ │ ├── ShapeLayerModel.swift
│ │ │ ├── SolidLayerModel.swift
│ │ │ └── TextLayerModel.swift
│ │ ├── Objects
│ │ │ ├── DashPattern.swift
│ │ │ ├── Marker.swift
│ │ │ ├── Mask.swift
│ │ │ └── Transform.swift
│ │ ├── ShapeItems
│ │ │ ├── Ellipse.swift
│ │ │ ├── FillI.swift
│ │ │ ├── GradientFill.swift
│ │ │ ├── GradientStroke.swift
│ │ │ ├── Group.swift
│ │ │ ├── Merge.swift
│ │ │ ├── Rectangle.swift
│ │ │ ├── Repeater.swift
│ │ │ ├── Shape.swift
│ │ │ ├── ShapeItem.swift
│ │ │ ├── ShapeTransform.swift
│ │ │ ├── Star.swift
│ │ │ ├── Stroke.swift
│ │ │ └── Trim.swift
│ │ └── Text
│ │ │ ├── Font.swift
│ │ │ ├── Glyph.swift
│ │ │ ├── TextAnimator.swift
│ │ │ └── TextDocument.swift
│ ├── NodeRenderSystem
│ │ ├── Extensions
│ │ │ └── ItemsExtension.swift
│ │ ├── NodeProperties
│ │ │ ├── NodeProperty.swift
│ │ │ ├── Protocols
│ │ │ │ ├── AnyNodeProperty.swift
│ │ │ │ ├── AnyValueContainer.swift
│ │ │ │ ├── KeypathSearchable.swift
│ │ │ │ └── NodePropertyMap.swift
│ │ │ ├── ValueContainer.swift
│ │ │ └── ValueProviders
│ │ │ │ ├── GroupInterpolator.swift
│ │ │ │ ├── KeyframeInterpolator.swift
│ │ │ │ └── SingleValueProvider.swift
│ │ ├── Nodes
│ │ │ ├── ModifierNodes
│ │ │ │ └── TrimPathNode.swift
│ │ │ ├── OutputNodes
│ │ │ │ ├── GroupOutputNode.swift
│ │ │ │ ├── PassThroughOutputNode.swift
│ │ │ │ ├── PathOutputNode.swift
│ │ │ │ └── Renderables
│ │ │ │ │ ├── FillRenderer.swift
│ │ │ │ │ ├── GradientFillRenderer.swift
│ │ │ │ │ ├── GradientStrokeRenderer.swift
│ │ │ │ │ └── StrokeRenderer.swift
│ │ │ ├── PathNodes
│ │ │ │ ├── EllipseNode.swift
│ │ │ │ ├── PolygonNode.swift
│ │ │ │ ├── RectNode.swift
│ │ │ │ ├── ShapeNode.swift
│ │ │ │ └── StarNode.swift
│ │ │ ├── RenderContainers
│ │ │ │ └── GroupNode.swift
│ │ │ ├── RenderNodes
│ │ │ │ ├── FillNode.swift
│ │ │ │ ├── GradientFillNode.swift
│ │ │ │ ├── GradientStrokeNode.swift
│ │ │ │ └── StrokeNode.swift
│ │ │ └── Text
│ │ │ │ └── TextAnimatorNode.swift
│ │ ├── Protocols
│ │ │ ├── AnimatorNode.swift
│ │ │ ├── PathNode.swift
│ │ │ └── RenderNode.swift
│ │ └── RenderLayers
│ │ │ ├── ShapeContainerLayer.swift
│ │ │ └── ShapeRenderLayer.swift
│ └── Utility
│ │ ├── Debugging
│ │ ├── AnimatorNodeDebugging.swift
│ │ └── LayerDebugging.swift
│ │ ├── Extensions
│ │ ├── AnimationKeypathExtension.swift
│ │ ├── CGFloatExtensions.swift
│ │ ├── MathKit.swift
│ │ └── StringExtensions.swift
│ │ ├── Helpers
│ │ └── AnimationContext.swift
│ │ ├── Interpolatable
│ │ ├── Interpolatable.swift
│ │ ├── InterpolatableExtensions.swift
│ │ └── KeyframeExtensions.swift
│ │ └── Primitives
│ │ ├── BezierPath.swift
│ │ ├── ColorExtension.swift
│ │ ├── CompoundBezierPath.swift
│ │ ├── CurveVertex.swift
│ │ ├── PathElement.swift
│ │ └── VectorsExtensions.swift
│ └── Public
│ ├── Animation
│ ├── AnimationPublic.swift
│ ├── AnimationView.swift
│ └── AnimationViewInitializers.swift
│ ├── AnimationCache
│ ├── AnimationCacheProvider.swift
│ └── LRUAnimationCache.swift
│ ├── DynamicProperties
│ ├── AnimationKeypath.swift
│ ├── AnyValueProvider.swift
│ └── ValueProviders
│ │ ├── ColorValueProvider.swift
│ │ ├── FloatValueProvider.swift
│ │ ├── GradientValueProvider.swift
│ │ ├── PointValueProvider.swift
│ │ └── SizeValueProvider.swift
│ ├── ImageProvider
│ └── AnimationImageProvider.swift
│ ├── Primitives
│ ├── AnimationTime.swift
│ ├── Color.swift
│ └── Vectors.swift
│ ├── TextProvider
│ └── AnimationTextProvider.swift
│ └── iOS
│ ├── AnimatedButton.swift
│ ├── AnimatedControl.swift
│ ├── AnimatedSwitch.swift
│ ├── AnimationSubview.swift
│ ├── BundleImageProvider.swift
│ ├── Compatibility
│ ├── CompatibleAnimationKeypath.swift
│ └── CompatibleAnimationView.swift
│ ├── FilepathImageProvider.swift
│ ├── LottieView.swift
│ └── UIColorExtension.swift
├── README.md
├── UserOnboarding.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ └── shubham.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── UserOnboarding.xcworkspace
├── contents.xcworkspacedata
├── xcshareddata
│ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ └── shubham.xcuserdatad
│ └── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
└── UserOnboarding
├── AppDelegate.swift
├── Assets.xcassets
├── AppIcon.appiconset
│ └── Contents.json
└── Contents.json
├── Base.lproj
├── LaunchScreen.storyboard
└── Main.storyboard
├── CollectionViewCell.swift
├── Info.plist
├── OnboardingCollectionViewCell.swift
├── OnboardingCollectionViewCell.xib
├── SceneDelegate.swift
└── ViewController.swift
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | target 'UserOnboarding' do
5 | # Comment the next line if you don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for UserOnboarding
9 | pod 'lottie-ios'
10 |
11 |
12 | end
13 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - lottie-ios (3.1.8)
3 |
4 | DEPENDENCIES:
5 | - lottie-ios
6 |
7 | SPEC REPOS:
8 | trunk:
9 | - lottie-ios
10 |
11 | SPEC CHECKSUMS:
12 | lottie-ios: 48fac6be217c76937e36e340e2d09cf7b10b7f5f
13 |
14 | PODFILE CHECKSUM: efe27b7096ba59cdb6862ddf85368f650bc9fa85
15 |
16 | COCOAPODS: 1.8.4
17 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - lottie-ios (3.1.8)
3 |
4 | DEPENDENCIES:
5 | - lottie-ios
6 |
7 | SPEC REPOS:
8 | trunk:
9 | - lottie-ios
10 |
11 | SPEC CHECKSUMS:
12 | lottie-ios: 48fac6be217c76937e36e340e2d09cf7b10b7f5f
13 |
14 | PODFILE CHECKSUM: efe27b7096ba59cdb6862ddf85368f650bc9fa85
15 |
16 | COCOAPODS: 1.8.4
17 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/shubham.xcuserdatad/xcschemes/Pods-UserOnboarding.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/shubham.xcuserdatad/xcschemes/lottie-ios.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/shubham.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Pods-UserOnboarding.xcscheme
8 |
9 | isShown
10 |
11 | orderHint
12 | 1
13 |
14 | lottie-ios.xcscheme
15 |
16 | isShown
17 |
18 | orderHint
19 | 0
20 |
21 |
22 | SuppressBuildableAutocreation
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_UserOnboarding : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_UserOnboarding
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_UserOnboardingVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_UserOnboardingVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "Lottie" -framework "QuartzCore" -framework "UIKit"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_UserOnboarding {
2 | umbrella header "Pods-UserOnboarding-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserOnboarding/Pods-UserOnboarding.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "Lottie" -framework "QuartzCore" -framework "UIKit"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.1.8
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_lottie_ios : NSObject
3 | @end
4 | @implementation PodsDummy_lottie_ios
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double LottieVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char LottieVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios.modulemap:
--------------------------------------------------------------------------------
1 | framework module Lottie {
2 | umbrella header "lottie-ios-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/lottie-ios/lottie-ios.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "QuartzCore" -framework "UIKit"
4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
5 | PODS_BUILD_DIR = ${BUILD_DIR}
6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
12 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/CompLayers/ImageCompositionLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageCompositionLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | import QuartzCore
11 |
12 | final class ImageCompositionLayer: CompositionLayer {
13 |
14 | var image: CGImage? = nil {
15 | didSet {
16 | if let image = image {
17 | contentsLayer.contents = image
18 | } else {
19 | contentsLayer.contents = nil
20 | }
21 | }
22 | }
23 |
24 | let imageReferenceID: String
25 |
26 | init(imageLayer: ImageLayerModel, size: CGSize) {
27 | self.imageReferenceID = imageLayer.referenceID
28 | super.init(layer: imageLayer, size: size)
29 | contentsLayer.masksToBounds = true
30 | contentsLayer.contentsGravity = CALayerContentsGravity.resize
31 | }
32 |
33 | override init(layer: Any) {
34 | /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
35 | guard let layer = layer as? ImageCompositionLayer else {
36 | fatalError("init(layer:) Wrong Layer Class")
37 | }
38 | self.imageReferenceID = layer.imageReferenceID
39 | self.image = nil
40 | super.init(layer: layer)
41 | }
42 |
43 | required init?(coder aDecoder: NSCoder) {
44 | fatalError("init(coder:) has not been implemented")
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/CompLayers/NullCompositionLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NullCompositionLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class NullCompositionLayer: CompositionLayer {
11 |
12 | init(layer: LayerModel) {
13 | super.init(layer: layer, size: .zero)
14 | }
15 |
16 | required init?(coder aDecoder: NSCoder) {
17 | fatalError("init(coder:) has not been implemented")
18 | }
19 |
20 | override init(layer: Any) {
21 | /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
22 | guard let layer = layer as? NullCompositionLayer else {
23 | fatalError("init(layer:) Wrong Layer Class")
24 | }
25 | super.init(layer: layer)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/CompLayers/PreCompositionLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreCompositionLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | final class PreCompositionLayer: CompositionLayer {
12 |
13 | let frameRate: CGFloat
14 | let remappingNode: NodeProperty?
15 | fileprivate var animationLayers: [CompositionLayer]
16 |
17 | init(precomp: PreCompLayerModel,
18 | asset: PrecompAsset,
19 | layerImageProvider: LayerImageProvider,
20 | textProvider: AnimationTextProvider,
21 | assetLibrary: AssetLibrary?,
22 | frameRate: CGFloat) {
23 | self.animationLayers = []
24 | if let keyframes = precomp.timeRemapping?.keyframes {
25 | self.remappingNode = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframes))
26 | } else {
27 | self.remappingNode = nil
28 | }
29 | self.frameRate = frameRate
30 | super.init(layer: precomp, size: CGSize(width: precomp.width, height: precomp.height))
31 | contentsLayer.masksToBounds = true
32 | contentsLayer.bounds = CGRect(origin: .zero, size: CGSize(width: precomp.width, height: precomp.height))
33 |
34 | let layers = asset.layers.initializeCompositionLayers(assetLibrary: assetLibrary, layerImageProvider: layerImageProvider, textProvider: textProvider, frameRate: frameRate)
35 |
36 | var imageLayers = [ImageCompositionLayer]()
37 |
38 | var mattedLayer: CompositionLayer? = nil
39 |
40 | for layer in layers.reversed() {
41 | layer.bounds = bounds
42 | animationLayers.append(layer)
43 | if let imageLayer = layer as? ImageCompositionLayer {
44 | imageLayers.append(imageLayer)
45 | }
46 | if let matte = mattedLayer {
47 | /// The previous layer requires this layer to be its matte
48 | matte.matteLayer = layer
49 | mattedLayer = nil
50 | continue
51 | }
52 | if let matte = layer.matteType,
53 | (matte == .add || matte == .invert) {
54 | /// We have a layer that requires a matte.
55 | mattedLayer = layer
56 | }
57 | contentsLayer.addSublayer(layer)
58 | }
59 |
60 | self.childKeypaths.append(contentsOf: layers)
61 |
62 | layerImageProvider.addImageLayers(imageLayers)
63 | }
64 |
65 | override init(layer: Any) {
66 | /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
67 | guard let layer = layer as? PreCompositionLayer else {
68 | fatalError("init(layer:) Wrong Layer Class")
69 | }
70 | self.frameRate = layer.frameRate
71 | self.remappingNode = nil
72 | self.animationLayers = []
73 |
74 | super.init(layer: layer)
75 | }
76 |
77 | required init?(coder aDecoder: NSCoder) {
78 | fatalError("init(coder:) has not been implemented")
79 | }
80 |
81 | override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
82 | let localFrame: CGFloat
83 | if let remappingNode = remappingNode {
84 | remappingNode.update(frame: frame)
85 | localFrame = remappingNode.value.cgFloatValue * frameRate
86 | } else {
87 | localFrame = (frame - startFrame) / timeStretch
88 | }
89 | animationLayers.forEach( { $0.displayWithFrame(frame: localFrame, forceUpdates: forceUpdates) })
90 | }
91 |
92 | override var keypathProperties: [String : AnyNodeProperty] {
93 | guard let remappingNode = remappingNode else {
94 | return super.keypathProperties
95 | }
96 | return ["Time Remap" : remappingNode]
97 | }
98 |
99 | override func updateRenderScale() {
100 | super.updateRenderScale()
101 | animationLayers.forEach( { $0.renderScale = renderScale } )
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/CompLayers/ShapeCompositionLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeLayerContainer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/22/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /**
12 | A CompositionLayer responsible for initializing and rendering shapes
13 | */
14 | final class ShapeCompositionLayer: CompositionLayer {
15 |
16 | let rootNode: AnimatorNode?
17 | let renderContainer: ShapeContainerLayer?
18 |
19 | init(shapeLayer: ShapeLayerModel) {
20 | let results = shapeLayer.items.initializeNodeTree()
21 | let renderContainer = ShapeContainerLayer()
22 | self.renderContainer = renderContainer
23 | self.rootNode = results.rootNode
24 | super.init(layer: shapeLayer, size: .zero)
25 | contentsLayer.addSublayer(renderContainer)
26 | for container in results.renderContainers {
27 | renderContainer.insertRenderLayer(container)
28 | }
29 | rootNode?.updateTree(0, forceUpdates: true)
30 | self.childKeypaths.append(contentsOf: results.childrenNodes)
31 | }
32 |
33 | override init(layer: Any) {
34 | guard let layer = layer as? ShapeCompositionLayer else {
35 | fatalError("init(layer:) wrong class.")
36 | }
37 | self.rootNode = nil
38 | self.renderContainer = nil
39 | super.init(layer: layer)
40 | }
41 |
42 | override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
43 | rootNode?.updateTree(frame, forceUpdates: forceUpdates)
44 | renderContainer?.markRenderUpdates(forFrame: frame)
45 | }
46 |
47 | required init?(coder aDecoder: NSCoder) {
48 | fatalError("init(coder:) has not been implemented")
49 | }
50 |
51 | override func updateRenderScale() {
52 | super.updateRenderScale()
53 | renderContainer?.renderScale = renderScale
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/CompLayers/SolidCompositionLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolidCompositionLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | final class SolidCompositionLayer: CompositionLayer {
12 |
13 | let colorProperty: NodeProperty?
14 | let solidShape: CAShapeLayer = CAShapeLayer()
15 |
16 | init(solid: SolidLayerModel) {
17 | let components = solid.colorHex.hexColorComponents()
18 | self.colorProperty = NodeProperty(provider: SingleValueProvider(Color(r: Double(components.red), g: Double(components.green), b: Double(components.blue), a: 1)))
19 |
20 | super.init(layer: solid, size: .zero)
21 | solidShape.path = CGPath(rect: CGRect(x: 0, y: 0, width: solid.width, height: solid.height), transform: nil)
22 | contentsLayer.addSublayer(solidShape)
23 | }
24 |
25 | override init(layer: Any) {
26 | /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
27 | guard let layer = layer as? SolidCompositionLayer else {
28 | fatalError("init(layer:) Wrong Layer Class")
29 | }
30 | self.colorProperty = layer.colorProperty
31 | super.init(layer: layer)
32 | }
33 |
34 | required init?(coder aDecoder: NSCoder) {
35 | fatalError("init(coder:) has not been implemented")
36 | }
37 |
38 | override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
39 | guard let colorProperty = colorProperty else { return }
40 | colorProperty.update(frame: frame)
41 | solidShape.fillColor = colorProperty.value.cgColorValue
42 | }
43 |
44 | override var keypathProperties: [String : AnyNodeProperty] {
45 | guard let colorProperty = colorProperty else { return super.keypathProperties }
46 | return ["Color" : colorProperty]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/Utility/CompositionLayersInitializer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CompositionLayersInitializer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | extension Array where Element == LayerModel {
12 |
13 | func initializeCompositionLayers(assetLibrary: AssetLibrary?,
14 | layerImageProvider: LayerImageProvider,
15 | textProvider: AnimationTextProvider,
16 | frameRate: CGFloat) -> [CompositionLayer] {
17 | var compositionLayers = [CompositionLayer]()
18 | var layerMap = [Int : CompositionLayer]()
19 |
20 | /// Organize the assets into a dictionary of [ID : ImageAsset]
21 | var childLayers = [LayerModel]()
22 |
23 | for layer in self {
24 | if layer.hidden == true {
25 | let genericLayer = NullCompositionLayer(layer: layer)
26 | compositionLayers.append(genericLayer)
27 | layerMap[layer.index] = genericLayer
28 | } else if let shapeLayer = layer as? ShapeLayerModel {
29 | let shapeContainer = ShapeCompositionLayer(shapeLayer: shapeLayer)
30 | compositionLayers.append(shapeContainer)
31 | layerMap[layer.index] = shapeContainer
32 | } else if let solidLayer = layer as? SolidLayerModel {
33 | let solidContainer = SolidCompositionLayer(solid: solidLayer)
34 | compositionLayers.append(solidContainer)
35 | layerMap[layer.index] = solidContainer
36 | } else if let precompLayer = layer as? PreCompLayerModel,
37 | let assetLibrary = assetLibrary,
38 | let precompAsset = assetLibrary.precompAssets[precompLayer.referenceID] {
39 | let precompContainer = PreCompositionLayer(precomp: precompLayer,
40 | asset: precompAsset,
41 | layerImageProvider: layerImageProvider,
42 | textProvider: textProvider,
43 | assetLibrary: assetLibrary,
44 | frameRate: frameRate)
45 | compositionLayers.append(precompContainer)
46 | layerMap[layer.index] = precompContainer
47 | } else if let imageLayer = layer as? ImageLayerModel,
48 | let assetLibrary = assetLibrary,
49 | let imageAsset = assetLibrary.imageAssets[imageLayer.referenceID] {
50 | let imageContainer = ImageCompositionLayer(imageLayer: imageLayer, size: CGSize(width: imageAsset.width, height: imageAsset.height))
51 | compositionLayers.append(imageContainer)
52 | layerMap[layer.index] = imageContainer
53 | } else if let textLayer = layer as? TextLayerModel {
54 | let textContainer = TextCompositionLayer(textLayer: textLayer, textProvider: textProvider)
55 | compositionLayers.append(textContainer)
56 | layerMap[layer.index] = textContainer
57 | } else {
58 | let genericLayer = NullCompositionLayer(layer: layer)
59 | compositionLayers.append(genericLayer)
60 | layerMap[layer.index] = genericLayer
61 | }
62 | if layer.parent != nil {
63 | childLayers.append(layer)
64 | }
65 | }
66 |
67 | /// Now link children with their parents
68 | for layerModel in childLayers {
69 | if let parentID = layerModel.parent {
70 | let childLayer = layerMap[layerModel.index]
71 | let parentLayer = layerMap[parentID]
72 | childLayer?.transformNode.parentNode = parentLayer?.transformNode
73 | }
74 | }
75 |
76 | return compositionLayers
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/Utility/InvertedMatteLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InvertedMatteLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/28/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | /**
12 | A layer that inverses the alpha output of its input layer.
13 |
14 | WARNING: This is experimental and probably not very performant.
15 | */
16 | final class InvertedMatteLayer: CALayer, CompositionLayerDelegate {
17 |
18 | let inputMatte: CompositionLayer?
19 | let wrapperLayer = CALayer()
20 |
21 | init(inputMatte: CompositionLayer) {
22 | self.inputMatte = inputMatte
23 | super.init()
24 | inputMatte.layerDelegate = self
25 | self.anchorPoint = .zero
26 | self.bounds = inputMatte.bounds
27 | self.setNeedsDisplay()
28 | }
29 |
30 | override init(layer: Any) {
31 | guard let layer = layer as? InvertedMatteLayer else {
32 | fatalError("init(layer:) wrong class.")
33 | }
34 | self.inputMatte = nil
35 | super.init(layer: layer)
36 | }
37 |
38 | func frameUpdated(frame: CGFloat) {
39 | self.setNeedsDisplay()
40 | self.displayIfNeeded()
41 | }
42 |
43 | required init?(coder aDecoder: NSCoder) {
44 | fatalError("init(coder:) has not been implemented")
45 | }
46 |
47 | override func draw(in ctx: CGContext) {
48 | guard let inputMatte = inputMatte else { return }
49 | guard let fillColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0, 0, 0, 1])
50 | else { return }
51 | ctx.setFillColor(fillColor)
52 | ctx.fill(bounds)
53 | ctx.setBlendMode(.destinationOut)
54 | inputMatte.render(in: ctx)
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/Utility/LayerImageProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LayerImageProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Connects a LottieImageProvider to a group of image layers
11 | final class LayerImageProvider {
12 |
13 | var imageProvider: AnimationImageProvider {
14 | didSet {
15 | reloadImages()
16 | }
17 | }
18 |
19 | fileprivate(set) var imageLayers: [ImageCompositionLayer]
20 | let imageAssets: [String : ImageAsset]
21 |
22 | init(imageProvider: AnimationImageProvider, assets: [String : ImageAsset]?) {
23 | self.imageProvider = imageProvider
24 | self.imageLayers = [ImageCompositionLayer]()
25 | if let assets = assets {
26 | self.imageAssets = assets
27 | } else {
28 | self.imageAssets = [:]
29 | }
30 | reloadImages()
31 | }
32 |
33 | func addImageLayers(_ layers: [ImageCompositionLayer]) {
34 | for layer in layers {
35 | if imageAssets[layer.imageReferenceID] != nil {
36 | /// Found a linking asset in our asset library. Add layer
37 | imageLayers.append(layer)
38 | }
39 | }
40 | }
41 |
42 | func reloadImages() {
43 | for imageLayer in imageLayers {
44 | if let asset = imageAssets[imageLayer.imageReferenceID] {
45 | imageLayer.image = imageProvider.imageForAsset(asset: asset)
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/LayerContainers/Utility/LayerTextProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LayerTextProvider.swift
3 | // lottie-ios-iOS
4 | //
5 | // Created by Alexandr Goncharov on 07/06/2019.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Connects a LottieTextProvider to a group of text layers
11 | final class LayerTextProvider {
12 |
13 | var textProvider: AnimationTextProvider {
14 | didSet {
15 | reloadTexts()
16 | }
17 | }
18 |
19 | fileprivate(set) var textLayers: [TextCompositionLayer]
20 |
21 | init(textProvider: AnimationTextProvider) {
22 | self.textProvider = textProvider
23 | self.textLayers = []
24 | reloadTexts()
25 | }
26 |
27 | func addTextLayers(_ layers: [TextCompositionLayer]) {
28 | textLayers += layers
29 | }
30 |
31 | func reloadTexts() {
32 | textLayers.forEach {
33 | $0.textProvider = textProvider
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Animation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Animation.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/7/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public enum CoordinateSpace: Int, Codable {
11 | case type2d
12 | case type3d
13 | }
14 |
15 | /**
16 | The `Animation` model is the top level model object in Lottie.
17 |
18 | An `Animation` holds all of the animation data backing a Lottie Animation.
19 | Codable, see JSON schema [here](https://github.com/airbnb/lottie-web/tree/master/docs/json).
20 | */
21 | public final class Animation: Codable {
22 |
23 | /// The version of the JSON Schema.
24 | let version: String
25 |
26 | /// The coordinate space of the composition.
27 | let type: CoordinateSpace
28 |
29 | /// The start time of the composition in frameTime.
30 | public let startFrame: AnimationFrameTime
31 |
32 | /// The end time of the composition in frameTime.
33 | public let endFrame: AnimationFrameTime
34 |
35 | /// The frame rate of the composition.
36 | public let framerate: Double
37 |
38 | /// The height of the composition in points.
39 | let width: Int
40 |
41 | /// The width of the composition in points.
42 | let height: Int
43 |
44 | /// The list of animation layers
45 | let layers: [LayerModel]
46 |
47 | /// The list of glyphs used for text rendering
48 | let glyphs: [Glyph]?
49 |
50 | /// The list of fonts used for text rendering
51 | let fonts: FontList?
52 |
53 | /// Asset Library
54 | let assetLibrary: AssetLibrary?
55 |
56 | /// Markers
57 | let markers: [Marker]?
58 | let markerMap: [String : Marker]?
59 |
60 | /// Return all marker names, in order, or an empty list if none are specified
61 | public var markerNames: [String] {
62 | guard let markers = markers else { return [] }
63 | return markers.map { $0.name }
64 | }
65 |
66 | enum CodingKeys : String, CodingKey {
67 | case version = "v"
68 | case type = "ddd"
69 | case startFrame = "ip"
70 | case endFrame = "op"
71 | case framerate = "fr"
72 | case width = "w"
73 | case height = "h"
74 | case layers = "layers"
75 | case glyphs = "chars"
76 | case fonts = "fonts"
77 | case assetLibrary = "assets"
78 | case markers = "markers"
79 | }
80 |
81 | required public init(from decoder: Decoder) throws {
82 | let container = try decoder.container(keyedBy: Animation.CodingKeys.self)
83 | self.version = try container.decode(String.self, forKey: .version)
84 | self.type = try container.decodeIfPresent(CoordinateSpace.self, forKey: .type) ?? .type2d
85 | self.startFrame = try container.decode(AnimationFrameTime.self, forKey: .startFrame)
86 | self.endFrame = try container.decode(AnimationFrameTime.self, forKey: .endFrame)
87 | self.framerate = try container.decode(Double.self, forKey: .framerate)
88 | self.width = try container.decode(Int.self, forKey: .width)
89 | self.height = try container.decode(Int.self, forKey: .height)
90 | self.layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers)
91 | self.glyphs = try container.decodeIfPresent([Glyph].self, forKey: .glyphs)
92 | self.fonts = try container.decodeIfPresent(FontList.self, forKey: .fonts)
93 | self.assetLibrary = try container.decodeIfPresent(AssetLibrary.self, forKey: .assetLibrary)
94 | self.markers = try container.decodeIfPresent([Marker].self, forKey: .markers)
95 |
96 | if let markers = markers {
97 | var markerMap: [String : Marker] = [:]
98 | for marker in markers {
99 | markerMap[marker.name] = marker
100 | }
101 | self.markerMap = markerMap
102 | } else {
103 | self.markerMap = nil
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Assets/Asset.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Asset.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public class Asset: Codable {
11 |
12 | /// The ID of the asset
13 | let id: String
14 |
15 | private enum CodingKeys : String, CodingKey {
16 | case id = "id"
17 | }
18 |
19 | required public init(from decoder: Decoder) throws {
20 | let container = try decoder.container(keyedBy: Asset.CodingKeys.self)
21 | if let id = try? container.decode(String.self, forKey: .id) {
22 | self.id = id
23 | } else {
24 | self.id = String(try container.decode(Int.self, forKey: .id))
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Assets/AssetLibrary.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AssetLibrary.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class AssetLibrary: Codable {
11 |
12 | /// The Assets
13 | let assets: [String : Asset]
14 |
15 | let imageAssets: [String : ImageAsset]
16 | let precompAssets: [String : PrecompAsset]
17 |
18 | required init(from decoder: Decoder) throws {
19 | var container = try decoder.unkeyedContainer()
20 | var containerForKeys = container
21 |
22 | var decodedAssets = [String : Asset]()
23 |
24 | var imageAssets = [String : ImageAsset]()
25 | var precompAssets = [String : PrecompAsset]()
26 |
27 | while !container.isAtEnd {
28 | let keyContainer = try containerForKeys.nestedContainer(keyedBy: PrecompAsset.CodingKeys.self)
29 | if keyContainer.contains(.layers) {
30 | let precompAsset = try container.decode(PrecompAsset.self)
31 | decodedAssets[precompAsset.id] = precompAsset
32 | precompAssets[precompAsset.id] = precompAsset
33 | } else {
34 | let imageAsset = try container.decode(ImageAsset.self)
35 | decodedAssets[imageAsset.id] = imageAsset
36 | imageAssets[imageAsset.id] = imageAsset
37 | }
38 | }
39 | self.assets = decodedAssets
40 | self.precompAssets = precompAssets
41 | self.imageAssets = imageAssets
42 | }
43 |
44 | func encode(to encoder: Encoder) throws {
45 | var container = encoder.unkeyedContainer()
46 | try container.encode(contentsOf: Array(assets.values))
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Assets/ImageAsset.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageAsset.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public final class ImageAsset: Asset {
11 |
12 | /// Image name
13 | public let name: String
14 |
15 | /// Image Directory
16 | public let directory: String
17 |
18 | /// Image Size
19 | public let width: Double
20 |
21 | public let height: Double
22 |
23 | enum CodingKeys : String, CodingKey {
24 | case name = "p"
25 | case directory = "u"
26 | case width = "w"
27 | case height = "h"
28 | }
29 |
30 | required init(from decoder: Decoder) throws {
31 | let container = try decoder.container(keyedBy: ImageAsset.CodingKeys.self)
32 | self.name = try container.decode(String.self, forKey: .name)
33 | self.directory = try container.decode(String.self, forKey: .directory)
34 | self.width = try container.decode(Double.self, forKey: .width)
35 | self.height = try container.decode(Double.self, forKey: .height)
36 | try super.init(from: decoder)
37 | }
38 |
39 | override public func encode(to encoder: Encoder) throws {
40 | try super.encode(to: encoder)
41 | var container = encoder.container(keyedBy: CodingKeys.self)
42 | try container.encode(name, forKey: .name)
43 | try container.encode(directory, forKey: .directory)
44 | try container.encode(width, forKey: .width)
45 | try container.encode(height, forKey: .height)
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Assets/PrecompAsset.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrecompAsset.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class PrecompAsset: Asset {
11 |
12 | /// Layers of the precomp
13 | let layers: [LayerModel]
14 |
15 | enum CodingKeys : String, CodingKey {
16 | case layers = "layers"
17 | }
18 |
19 | required init(from decoder: Decoder) throws {
20 | let container = try decoder.container(keyedBy: PrecompAsset.CodingKeys.self)
21 | self.layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers)
22 | try super.init(from: decoder)
23 | }
24 |
25 | override func encode(to encoder: Encoder) throws {
26 | try super.encode(to: encoder)
27 | var container = encoder.container(keyedBy: CodingKeys.self)
28 | try container.encode(layers, forKey: .layers)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift:
--------------------------------------------------------------------------------
1 | // From: https://medium.com/@kewindannerfjordremeczki/swift-4-0-decodable-heterogeneous-collections-ecc0e6b468cf
2 |
3 | import Foundation
4 |
5 | /// To support a new class family, create an enum that conforms to this protocol and contains the different types.
6 | protocol ClassFamily: Decodable {
7 | /// The discriminator key.
8 | static var discriminator: Discriminator { get }
9 |
10 | /// Returns the class type of the object corresponding to the value.
11 | func getType() -> AnyObject.Type
12 | }
13 |
14 | /// Discriminator key enum used to retrieve discriminator fields in JSON payloads.
15 | enum Discriminator: String, CodingKey {
16 | case type = "ty"
17 | }
18 |
19 | extension KeyedDecodingContainer {
20 |
21 | /// Decode a heterogeneous list of objects for a given family.
22 | /// - Parameters:
23 | /// - heterogeneousType: The decodable type of the list.
24 | /// - family: The ClassFamily enum for the type family.
25 | /// - key: The CodingKey to look up the list in the current container.
26 | /// - Returns: The resulting list of heterogeneousType elements.
27 | func decode(_ heterogeneousType: [T].Type, ofFamily family: U.Type, forKey key: K) throws -> [T] {
28 | var container = try self.nestedUnkeyedContainer(forKey: key)
29 | var list = [T]()
30 | var tmpContainer = container
31 | while !container.isAtEnd {
32 | let typeContainer = try container.nestedContainer(keyedBy: Discriminator.self)
33 | let family: U = try typeContainer.decode(U.self, forKey: U.discriminator)
34 | if let type = family.getType() as? T.Type {
35 | list.append(try tmpContainer.decode(type))
36 | }
37 | }
38 | return list
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Keyframes/Keyframe.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Keyframe.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/7/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /**
12 | Keyframe represents a point in time and is the container for datatypes.
13 | Note: This is a parent class and should not be used directly.
14 | */
15 | final class Keyframe {
16 |
17 | /// The value of the keyframe
18 | let value: T
19 | /// The time in frames of the keyframe.
20 | let time: CGFloat
21 | /// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
22 | let isHold: Bool
23 | /// The in tangent for the time interpolation curve.
24 | let inTangent: Vector2D?
25 | /// The out tangent for the time interpolation curve.
26 | let outTangent: Vector2D?
27 |
28 | /// The spacial in tangent of the vector.
29 | let spatialInTangent: Vector3D?
30 | /// The spacial out tangent of the vector.
31 | let spatialOutTangent: Vector3D?
32 |
33 | /// Initialize a value-only keyframe with no time data.
34 | init(_ value: T,
35 | spatialInTangent: Vector3D? = nil,
36 | spatialOutTangent: Vector3D? = nil) {
37 | self.value = value
38 | self.time = 0
39 | self.isHold = true
40 | self.inTangent = nil
41 | self.outTangent = nil
42 | self.spatialInTangent = spatialInTangent
43 | self.spatialOutTangent = spatialOutTangent
44 | }
45 |
46 | /// Initialize a keyframe
47 | init(value: T,
48 | time: Double,
49 | isHold: Bool,
50 | inTangent: Vector2D?,
51 | outTangent: Vector2D?,
52 | spatialInTangent: Vector3D? = nil,
53 | spatialOutTangent: Vector3D? = nil) {
54 | self.value = value
55 | self.time = CGFloat(time)
56 | self.isHold = isHold
57 | self.outTangent = outTangent
58 | self.inTangent = inTangent
59 | self.spatialInTangent = spatialInTangent
60 | self.spatialOutTangent = spatialOutTangent
61 | }
62 |
63 | }
64 |
65 | /**
66 | A generic class used to parse and remap keyframe json.
67 |
68 | Keyframe json has a couple of different variations and formats depending on the
69 | type of keyframea and also the version of the JSON. By parsing the raw data
70 | we can reconfigure it into a constant format.
71 | */
72 | final class KeyframeData: Codable {
73 |
74 | /// The start value of the keyframe
75 | let startValue: T?
76 | /// The End value of the keyframe. Note: Newer versions animation json do not have this field.
77 | let endValue: T?
78 | /// The time in frames of the keyframe.
79 | let time: Double?
80 | /// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
81 | let hold: Int?
82 |
83 | /// The in tangent for the time interpolation curve.
84 | let inTangent: Vector2D?
85 | /// The out tangent for the time interpolation curve.
86 | let outTangent: Vector2D?
87 |
88 | /// The spacial in tangent of the vector.
89 | let spatialInTangent: Vector3D?
90 | /// The spacial out tangent of the vector.
91 | let spatialOutTangent:Vector3D?
92 |
93 | init(startValue: T?,
94 | endValue: T?,
95 | time: Double?,
96 | hold: Int?,
97 | inTangent: Vector2D?,
98 | outTangent: Vector2D?,
99 | spatialInTangent: Vector3D?,
100 | spatialOutTangent: Vector3D?) {
101 | self.startValue = startValue
102 | self.endValue = endValue
103 | self.time = time
104 | self.hold = hold
105 | self.inTangent = inTangent
106 | self.outTangent = outTangent
107 | self.spatialInTangent = spatialInTangent
108 | self.spatialOutTangent = spatialOutTangent
109 | }
110 |
111 | enum CodingKeys : String, CodingKey {
112 | case startValue = "s"
113 | case endValue = "e"
114 | case time = "t"
115 | case hold = "h"
116 | case inTangent = "i"
117 | case outTangent = "o"
118 | case spatialInTangent = "ti"
119 | case spatialOutTangent = "to"
120 | }
121 |
122 | var isHold: Bool {
123 | if let hold = hold {
124 | return hold > 0
125 | }
126 | return false
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Layers/ImageLayerModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A layer that holds an image.
11 | final class ImageLayerModel: LayerModel {
12 |
13 | /// The reference ID of the image.
14 | let referenceID: String
15 |
16 | private enum CodingKeys : String, CodingKey {
17 | case referenceID = "refId"
18 | }
19 |
20 | required init(from decoder: Decoder) throws {
21 | let container = try decoder.container(keyedBy: ImageLayerModel.CodingKeys.self)
22 | self.referenceID = try container.decode(String.self, forKey: .referenceID)
23 | try super.init(from: decoder)
24 | }
25 |
26 | override func encode(to encoder: Encoder) throws {
27 | try super.encode(to: encoder)
28 | var container = encoder.container(keyedBy: CodingKeys.self)
29 | try container.encode(referenceID, forKey: .referenceID)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Layers/PreCompLayerModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreCompLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A layer that holds another animation composition.
11 | final class PreCompLayerModel: LayerModel {
12 |
13 | /// The reference ID of the precomp.
14 | let referenceID: String
15 |
16 | /// A value that remaps time over time.
17 | let timeRemapping: KeyframeGroup?
18 |
19 | /// Precomp Width
20 | let width: Double
21 |
22 | /// Precomp Height
23 | let height: Double
24 |
25 | private enum CodingKeys : String, CodingKey {
26 | case referenceID = "refId"
27 | case timeRemapping = "tm"
28 | case width = "w"
29 | case height = "h"
30 | }
31 |
32 | required init(from decoder: Decoder) throws {
33 | let container = try decoder.container(keyedBy: PreCompLayerModel.CodingKeys.self)
34 | self.referenceID = try container.decode(String.self, forKey: .referenceID)
35 | self.timeRemapping = try container.decodeIfPresent(KeyframeGroup.self, forKey: .timeRemapping)
36 | self.width = try container.decode(Double.self, forKey: .width)
37 | self.height = try container.decode(Double.self, forKey: .height)
38 | try super.init(from: decoder)
39 | }
40 |
41 | override func encode(to encoder: Encoder) throws {
42 | try super.encode(to: encoder)
43 | var container = encoder.container(keyedBy: CodingKeys.self)
44 | try container.encode(referenceID, forKey: .referenceID)
45 | try container.encode(timeRemapping, forKey: .timeRemapping)
46 | try container.encode(width, forKey: .width)
47 | try container.encode(height, forKey: .height)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Layers/ShapeLayerModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A layer that holds vector shape objects.
11 | final class ShapeLayerModel: LayerModel {
12 |
13 | /// A list of shape items.
14 | let items: [ShapeItem]
15 |
16 | private enum CodingKeys : String, CodingKey {
17 | case items = "shapes"
18 | }
19 |
20 | required init(from decoder: Decoder) throws {
21 | let container = try decoder.container(keyedBy: ShapeLayerModel.CodingKeys.self)
22 | self.items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items)
23 | try super.init(from: decoder)
24 | }
25 |
26 | override func encode(to encoder: Encoder) throws {
27 | try super.encode(to: encoder)
28 | var container = encoder.container(keyedBy: CodingKeys.self)
29 | try container.encode(self.items, forKey: .items)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Layers/SolidLayerModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolidLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A layer that holds a solid color.
11 | final class SolidLayerModel: LayerModel {
12 |
13 | /// The color of the solid in Hex // Change to value provider.
14 | let colorHex: String
15 |
16 | /// The Width of the color layer
17 | let width: Double
18 |
19 | /// The height of the color layer
20 | let height: Double
21 |
22 | private enum CodingKeys : String, CodingKey {
23 | case colorHex = "sc"
24 | case width = "sw"
25 | case height = "sh"
26 | }
27 |
28 | required init(from decoder: Decoder) throws {
29 | let container = try decoder.container(keyedBy: SolidLayerModel.CodingKeys.self)
30 | self.colorHex = try container.decode(String.self, forKey: .colorHex)
31 | self.width = try container.decode(Double.self, forKey: .width)
32 | self.height = try container.decode(Double.self, forKey: .height)
33 | try super.init(from: decoder)
34 | }
35 |
36 | override func encode(to encoder: Encoder) throws {
37 | try super.encode(to: encoder)
38 | var container = encoder.container(keyedBy: CodingKeys.self)
39 | try container.encode(colorHex, forKey: .colorHex)
40 | try container.encode(width, forKey: .width)
41 | try container.encode(height, forKey: .height)
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Layers/TextLayerModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A layer that holds text.
11 | final class TextLayerModel: LayerModel {
12 |
13 | /// The text for the layer
14 | let text: KeyframeGroup
15 |
16 | /// Text animators
17 | let animators: [TextAnimator]
18 |
19 | private enum CodingKeys : String, CodingKey {
20 | case textGroup = "t"
21 | }
22 |
23 | private enum TextCodingKeys : String, CodingKey {
24 | case text = "d"
25 | case animators = "a"
26 | }
27 |
28 | required init(from decoder: Decoder) throws {
29 | let container = try decoder.container(keyedBy: TextLayerModel.CodingKeys.self)
30 | let textContainer = try container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup)
31 | self.text = try textContainer.decode(KeyframeGroup.self, forKey: .text)
32 | self.animators = try textContainer.decode([TextAnimator].self, forKey: .animators)
33 | try super.init(from: decoder)
34 | }
35 |
36 | override func encode(to encoder: Encoder) throws {
37 | try super.encode(to: encoder)
38 | var container = encoder.container(keyedBy: CodingKeys.self)
39 | var textContainer = container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup)
40 | try textContainer.encode(text, forKey: .text)
41 | try textContainer.encode(animators, forKey: .animators)
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Objects/DashPattern.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DashPattern.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/22/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum DashElementType: String, Codable {
11 | case offset = "o"
12 | case dash = "d"
13 | case gap = "g"
14 | }
15 |
16 | final class DashElement: Codable {
17 | let type: DashElementType
18 | let value: KeyframeGroup
19 |
20 | enum CodingKeys : String, CodingKey {
21 | case type = "n"
22 | case value = "v"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Objects/Marker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Marker.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A time marker
11 | final class Marker: Codable {
12 |
13 | /// The Marker Name
14 | let name: String
15 |
16 | /// The Frame time of the marker
17 | let frameTime: AnimationFrameTime
18 |
19 | enum CodingKeys : String, CodingKey {
20 | case name = "cm"
21 | case frameTime = "tm"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Objects/Mask.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mask.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum MaskMode: String, Codable {
11 | case add = "a"
12 | case subtract = "s"
13 | case intersect = "i"
14 | case lighten = "l"
15 | case darken = "d"
16 | case difference = "f"
17 | case none = "n"
18 | }
19 |
20 | final class Mask: Codable {
21 |
22 | let mode: MaskMode
23 |
24 | let opacity: KeyframeGroup
25 |
26 | let shape: KeyframeGroup
27 |
28 | let inverted: Bool
29 |
30 | let expansion: KeyframeGroup
31 |
32 | enum CodingKeys : String, CodingKey {
33 | case mode = "mode"
34 | case opacity = "o"
35 | case inverted = "inv"
36 | case shape = "pt"
37 | case expansion = "x"
38 | }
39 |
40 | required init(from decoder: Decoder) throws {
41 | let container = try decoder.container(keyedBy: Mask.CodingKeys.self)
42 | self.mode = try container.decodeIfPresent(MaskMode.self, forKey: .mode) ?? .add
43 | self.opacity = try container.decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
44 | self.shape = try container.decode(KeyframeGroup.self, forKey: .shape)
45 | self.inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
46 | self.expansion = try container.decodeIfPresent(KeyframeGroup.self, forKey: .expansion) ?? KeyframeGroup(Vector1D(0))
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Objects/Transform.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Transform.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/7/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// The animatable transform for a layer. Controls position, rotation, scale, and opacity.
11 | final class Transform: Codable {
12 |
13 | /// The anchor point of the transform.
14 | let anchorPoint: KeyframeGroup
15 |
16 | /// The position of the transform. This is nil if the position data was split.
17 | let position: KeyframeGroup?
18 |
19 | /// The positionX of the transform. This is nil if the position property is set.
20 | let positionX: KeyframeGroup?
21 |
22 | /// The positionY of the transform. This is nil if the position property is set.
23 | let positionY: KeyframeGroup?
24 |
25 | /// The scale of the transform
26 | let scale: KeyframeGroup
27 |
28 | /// The rotation of the transform. Note: This is single dimensional rotation.
29 | let rotation: KeyframeGroup
30 |
31 | /// The opacity of the transform.
32 | let opacity: KeyframeGroup
33 |
34 | /// Should always be nil.
35 | let rotationZ: KeyframeGroup?
36 |
37 | enum CodingKeys : String, CodingKey {
38 | case anchorPoint = "a"
39 | case position = "p"
40 | case positionX = "px"
41 | case positionY = "py"
42 | case scale = "s"
43 | case rotation = "r"
44 | case rotationZ = "rz"
45 | case opacity = "o"
46 | }
47 |
48 | enum PositionCodingKeys : String, CodingKey {
49 | case split = "s"
50 | case positionX = "x"
51 | case positionY = "y"
52 | }
53 |
54 |
55 | required init(from decoder: Decoder) throws {
56 | /**
57 | This manual override of decode is required because we want to throw an error
58 | in the case that there is not position data.
59 | */
60 | let container = try decoder.container(keyedBy: Transform.CodingKeys.self)
61 |
62 | // AnchorPoint
63 | self.anchorPoint = try container.decodeIfPresent(KeyframeGroup.self, forKey: .anchorPoint) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
64 |
65 | // Position
66 | if container.contains(.positionX), container.contains(.positionY) {
67 | // Position dimensions are split into two keyframe groups
68 | self.positionX = try container.decode(KeyframeGroup.self, forKey: .positionX)
69 | self.positionY = try container.decode(KeyframeGroup.self, forKey: .positionY)
70 | self.position = nil
71 | } else if let positionKeyframes = try? container.decode(KeyframeGroup.self, forKey: .position) {
72 | // Position dimensions are a single keyframe group.
73 | self.position = positionKeyframes
74 | self.positionX = nil
75 | self.positionY = nil
76 | } else if let positionContainer = try? container.nestedContainer(keyedBy: PositionCodingKeys.self, forKey: .position),
77 | let positionX = try? positionContainer.decode(KeyframeGroup.self, forKey: .positionX),
78 | let positionY = try? positionContainer.decode(KeyframeGroup.self, forKey: .positionY) {
79 | /// Position keyframes are split and nested.
80 | self.positionX = positionX
81 | self.positionY = positionY
82 | self.position = nil
83 | } else {
84 | /// Default value.
85 | self.position = KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
86 | self.positionX = nil
87 | self.positionY = nil
88 | }
89 |
90 |
91 | // Scale
92 | self.scale = try container.decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
93 |
94 | // Rotation
95 | if let rotationZ = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotationZ) {
96 | self.rotation = rotationZ
97 | } else {
98 | self.rotation = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
99 | }
100 | self.rotationZ = nil
101 |
102 | // Opacity
103 | self.opacity = try container.decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Ellipse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EllipseItem.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum PathDirection: Int, Codable {
11 | case clockwise = 1
12 | case userSetClockwise = 2
13 | case counterClockwise = 3
14 | }
15 |
16 | /// An item that define an ellipse shape
17 | final class Ellipse: ShapeItem {
18 |
19 | /// The direction of the ellipse.
20 | let direction: PathDirection
21 |
22 | /// The position of the ellipse
23 | let position: KeyframeGroup
24 |
25 | /// The size of the ellipse
26 | let size: KeyframeGroup
27 |
28 | private enum CodingKeys : String, CodingKey {
29 | case direction = "d"
30 | case position = "p"
31 | case size = "s"
32 | }
33 |
34 | required init(from decoder: Decoder) throws {
35 | let container = try decoder.container(keyedBy: Ellipse.CodingKeys.self)
36 | self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
37 | self.position = try container.decode(KeyframeGroup.self, forKey: .position)
38 | self.size = try container.decode(KeyframeGroup.self, forKey: .size)
39 | try super.init(from: decoder)
40 | }
41 |
42 | override func encode(to encoder: Encoder) throws {
43 | try super.encode(to: encoder)
44 | var container = encoder.container(keyedBy: CodingKeys.self)
45 | try container.encode(direction, forKey: .direction)
46 | try container.encode(position, forKey: .position)
47 | try container.encode(size, forKey: .size)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/FillI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FillShape.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum FillRule: Int, Codable {
11 | case none
12 | case nonZeroWinding
13 | case evenOdd
14 | }
15 |
16 | /// An item that defines a fill render
17 | final class Fill: ShapeItem {
18 |
19 | /// The opacity of the fill
20 | let opacity: KeyframeGroup
21 |
22 | /// The color keyframes for the fill
23 | let color: KeyframeGroup
24 |
25 | let fillRule: FillRule
26 |
27 | private enum CodingKeys : String, CodingKey {
28 | case opacity = "o"
29 | case color = "c"
30 | case fillRule = "r"
31 | }
32 |
33 | required init(from decoder: Decoder) throws {
34 | let container = try decoder.container(keyedBy: Fill.CodingKeys.self)
35 | self.opacity = try container.decode(KeyframeGroup.self, forKey: .opacity)
36 | self.color = try container.decode(KeyframeGroup.self, forKey: .color)
37 | self.fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding
38 | try super.init(from: decoder)
39 | }
40 |
41 | override func encode(to encoder: Encoder) throws {
42 | try super.encode(to: encoder)
43 | var container = encoder.container(keyedBy: CodingKeys.self)
44 | try container.encode(opacity, forKey: .opacity)
45 | try container.encode(color, forKey: .color)
46 | try container.encode(fillRule, forKey: .fillRule)
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/GradientFill.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GradientFill.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum GradientType: Int, Codable {
11 | case none
12 | case linear
13 | case radial
14 | }
15 |
16 | /// An item that define a gradient fill
17 | final class GradientFill: ShapeItem {
18 |
19 | /// The opacity of the fill
20 | let opacity: KeyframeGroup
21 |
22 | /// The start of the gradient
23 | let startPoint: KeyframeGroup
24 |
25 | /// The end of the gradient
26 | let endPoint: KeyframeGroup
27 |
28 | /// The type of gradient
29 | let gradientType: GradientType
30 |
31 | /// Gradient Highlight Length. Only if type is Radial
32 | let highlightLength: KeyframeGroup?
33 |
34 | /// Highlight Angle. Only if type is Radial
35 | let highlightAngle: KeyframeGroup?
36 |
37 | /// The number of color points in the gradient
38 | let numberOfColors: Int
39 |
40 | /// The Colors of the gradient.
41 | let colors: KeyframeGroup<[Double]>
42 |
43 | private enum CodingKeys : String, CodingKey {
44 | case opacity = "o"
45 | case startPoint = "s"
46 | case endPoint = "e"
47 | case gradientType = "t"
48 | case highlightLength = "h"
49 | case highlightAngle = "a"
50 | case colors = "g"
51 | }
52 |
53 | private enum GradientDataKeys : String, CodingKey {
54 | case numberOfColors = "p"
55 | case colors = "k"
56 | }
57 |
58 | required init(from decoder: Decoder) throws {
59 | let container = try decoder.container(keyedBy: GradientFill.CodingKeys.self)
60 | self.opacity = try container.decode(KeyframeGroup.self, forKey: .opacity)
61 | self.startPoint = try container.decode(KeyframeGroup.self, forKey: .startPoint)
62 | self.endPoint = try container.decode(KeyframeGroup.self, forKey: .endPoint)
63 | self.gradientType = try container.decode(GradientType.self, forKey: .gradientType)
64 | self.highlightLength = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightLength)
65 | self.highlightAngle = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightAngle)
66 | let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
67 | self.colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors)
68 | self.numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors)
69 | try super.init(from: decoder)
70 | }
71 |
72 | override func encode(to encoder: Encoder) throws {
73 | try super.encode(to: encoder)
74 | var container = encoder.container(keyedBy: CodingKeys.self)
75 | try container.encode(opacity, forKey: .opacity)
76 | try container.encode(startPoint, forKey: .startPoint)
77 | try container.encode(endPoint, forKey: .endPoint)
78 | try container.encode(gradientType, forKey: .gradientType)
79 | try container.encodeIfPresent(highlightLength, forKey: .highlightLength)
80 | try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle)
81 | var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
82 | try colorsContainer.encode(numberOfColors, forKey: .numberOfColors)
83 | try colorsContainer.encode(colors, forKey: .colors)
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Group.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GroupItem.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class Group: ShapeItem {
12 |
13 | /// A list of shape items.
14 | let items: [ShapeItem]
15 |
16 | private enum CodingKeys : String, CodingKey {
17 | case items = "it"
18 | }
19 |
20 | required init(from decoder: Decoder) throws {
21 | let container = try decoder.container(keyedBy: Group.CodingKeys.self)
22 | self.items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items)
23 | try super.init(from: decoder)
24 | }
25 |
26 | override func encode(to encoder: Encoder) throws {
27 | try super.encode(to: encoder)
28 | var container = encoder.container(keyedBy: CodingKeys.self)
29 | try container.encode(items, forKey: .items)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Merge.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Merge.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum MergeMode: Int, Codable {
11 | case none
12 | case merge
13 | case add
14 | case subtract
15 | case intersect
16 | case exclude
17 | }
18 |
19 | /// An item that define an ellipse shape
20 | final class Merge: ShapeItem {
21 |
22 | /// The mode of the merge path
23 | let mode: MergeMode
24 |
25 | private enum CodingKeys : String, CodingKey {
26 | case mode = "mm"
27 | }
28 |
29 | required init(from decoder: Decoder) throws {
30 | let container = try decoder.container(keyedBy: Merge.CodingKeys.self)
31 | self.mode = try container.decode(MergeMode.self, forKey: .mode)
32 | try super.init(from: decoder)
33 | }
34 |
35 | override func encode(to encoder: Encoder) throws {
36 | try super.encode(to: encoder)
37 | var container = encoder.container(keyedBy: CodingKeys.self)
38 | try container.encode(mode, forKey: .mode)
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Rectangle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Rectangle.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class Rectangle: ShapeItem {
12 |
13 | /// The direction of the rect.
14 | let direction: PathDirection
15 |
16 | /// The position
17 | let position: KeyframeGroup
18 |
19 | /// The size
20 | let size: KeyframeGroup
21 |
22 | /// The Corner radius of the rectangle
23 | let cornerRadius: KeyframeGroup
24 |
25 | private enum CodingKeys : String, CodingKey {
26 | case direction = "d"
27 | case position = "p"
28 | case size = "s"
29 | case cornerRadius = "r"
30 | }
31 |
32 | required init(from decoder: Decoder) throws {
33 | let container = try decoder.container(keyedBy: Rectangle.CodingKeys.self)
34 | self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
35 | self.position = try container.decode(KeyframeGroup.self, forKey: .position)
36 | self.size = try container.decode(KeyframeGroup.self, forKey: .size)
37 | self.cornerRadius = try container.decode(KeyframeGroup.self, forKey: .cornerRadius)
38 | try super.init(from: decoder)
39 | }
40 |
41 | override func encode(to encoder: Encoder) throws {
42 | try super.encode(to: encoder)
43 | var container = encoder.container(keyedBy: CodingKeys.self)
44 | try container.encode(direction, forKey: .direction)
45 | try container.encode(position, forKey: .position)
46 | try container.encode(size, forKey: .size)
47 | try container.encode(cornerRadius, forKey: .cornerRadius)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Repeater.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Repeater.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class Repeater: ShapeItem {
12 |
13 | /// The number of copies to repeat
14 | let copies: KeyframeGroup
15 |
16 | /// The offset of each copy
17 | let offset: KeyframeGroup
18 |
19 | /// Start Opacity
20 | let startOpacity: KeyframeGroup
21 |
22 | /// End opacity
23 | let endOpacity: KeyframeGroup
24 |
25 | /// The rotation
26 | let rotation: KeyframeGroup
27 |
28 | /// Anchor Point
29 | let anchorPoint: KeyframeGroup
30 |
31 | /// Position
32 | let position: KeyframeGroup
33 |
34 | /// Scale
35 | let scale: KeyframeGroup
36 |
37 | private enum CodingKeys : String, CodingKey {
38 | case copies = "c"
39 | case offset = "o"
40 | case transform = "tr"
41 | }
42 |
43 | private enum TransformKeys : String, CodingKey {
44 | case rotation = "r"
45 | case startOpacity = "so"
46 | case endOpacity = "eo"
47 | case anchorPoint = "a"
48 | case position = "p"
49 | case scale = "s"
50 | }
51 |
52 | required init(from decoder: Decoder) throws {
53 | let container = try decoder.container(keyedBy: Repeater.CodingKeys.self)
54 | self.copies = try container.decodeIfPresent(KeyframeGroup.self, forKey: .copies) ?? KeyframeGroup(Vector1D(0))
55 | self.offset = try container.decodeIfPresent(KeyframeGroup.self, forKey: .offset) ?? KeyframeGroup(Vector1D(0))
56 | let transformContainer = try container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform)
57 | self.startOpacity = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .startOpacity) ?? KeyframeGroup(Vector1D(100))
58 | self.endOpacity = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .endOpacity) ?? KeyframeGroup(Vector1D(100))
59 | self.rotation = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
60 | self.position = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .position) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
61 | self.anchorPoint = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .anchorPoint) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
62 | self.scale = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
63 | try super.init(from: decoder)
64 | }
65 |
66 | override func encode(to encoder: Encoder) throws {
67 | try super.encode(to: encoder)
68 | var container = encoder.container(keyedBy: CodingKeys.self)
69 | try container.encode(copies, forKey: .copies)
70 | try container.encode(offset, forKey: .offset)
71 | var transformContainer = container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform)
72 | try transformContainer.encode(startOpacity, forKey: .startOpacity)
73 | try transformContainer.encode(endOpacity, forKey: .endOpacity)
74 | try transformContainer.encode(rotation, forKey: .rotation)
75 | try transformContainer.encode(position, forKey: .position)
76 | try transformContainer.encode(anchorPoint, forKey: .anchorPoint)
77 | try transformContainer.encode(scale, forKey: .scale)
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Shape.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VectorShape.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class Shape: ShapeItem {
12 |
13 | /// The Path
14 | let path: KeyframeGroup
15 |
16 | let direction: PathDirection?
17 |
18 | private enum CodingKeys : String, CodingKey {
19 | case path = "ks"
20 | case direction = "d"
21 | }
22 |
23 | required init(from decoder: Decoder) throws {
24 | let container = try decoder.container(keyedBy: Shape.CodingKeys.self)
25 | self.path = try container.decode(KeyframeGroup.self, forKey: .path)
26 | self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction)
27 | try super.init(from: decoder)
28 | }
29 |
30 | override func encode(to encoder: Encoder) throws {
31 | try super.encode(to: encoder)
32 | var container = encoder.container(keyedBy: CodingKeys.self)
33 | try container.encode(path, forKey: .path)
34 | try container.encodeIfPresent(direction, forKey: .direction)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/ShapeItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeItem.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Used for mapping a heterogeneous list to classes for parsing.
11 | extension ShapeType: ClassFamily {
12 |
13 | static var discriminator: Discriminator = .type
14 |
15 | func getType() -> AnyObject.Type {
16 | switch self {
17 | case .ellipse:
18 | return Ellipse.self
19 | case .fill:
20 | return Fill.self
21 | case .gradientFill:
22 | return GradientFill.self
23 | case .group:
24 | return Group.self
25 | case .gradientStroke:
26 | return GradientStroke.self
27 | case .merge:
28 | return Merge.self
29 | case .rectangle:
30 | return Rectangle.self
31 | case .repeater:
32 | return Repeater.self
33 | case .shape:
34 | return Shape.self
35 | case .star:
36 | return Star.self
37 | case .stroke:
38 | return Stroke.self
39 | case .trim:
40 | return Trim.self
41 | case .transform:
42 | return ShapeTransform.self
43 | default:
44 | return ShapeItem.self
45 | }
46 | }
47 | }
48 |
49 | enum ShapeType: String, Codable {
50 | case ellipse = "el"
51 | case fill = "fl"
52 | case gradientFill = "gf"
53 | case group = "gr"
54 | case gradientStroke = "gs"
55 | case merge = "mm"
56 | case rectangle = "rc"
57 | case repeater = "rp"
58 | case round = "rd"
59 | case shape = "sh"
60 | case star = "sr"
61 | case stroke = "st"
62 | case trim = "tm"
63 | case transform = "tr"
64 | case unknown
65 |
66 | public init(from decoder: Decoder) throws {
67 | self = try ShapeType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown
68 | }
69 | }
70 |
71 | /// An item belonging to a Shape Layer
72 | class ShapeItem: Codable {
73 |
74 | /// The name of the shape
75 | let name: String
76 |
77 | /// The type of shape
78 | let type: ShapeType
79 |
80 | let hidden: Bool
81 |
82 | private enum CodingKeys : String, CodingKey {
83 | case name = "nm"
84 | case type = "ty"
85 | case hidden = "hd"
86 | }
87 |
88 | required init(from decoder: Decoder) throws {
89 | let container = try decoder.container(keyedBy: ShapeItem.CodingKeys.self)
90 | self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Layer"
91 | self.type = try container.decode(ShapeType.self, forKey: .type)
92 | self.hidden = try container.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/ShapeTransform.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TransformItem.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class ShapeTransform: ShapeItem {
12 |
13 | /// Anchor Point
14 | let anchor: KeyframeGroup
15 |
16 | /// Position
17 | let position: KeyframeGroup
18 |
19 | /// Scale
20 | let scale: KeyframeGroup
21 |
22 | /// Rotation
23 | let rotation: KeyframeGroup
24 |
25 | /// opacity
26 | let opacity: KeyframeGroup
27 |
28 | /// Skew
29 | let skew: KeyframeGroup
30 |
31 | /// Skew Axis
32 | let skewAxis: KeyframeGroup
33 |
34 | private enum CodingKeys : String, CodingKey {
35 | case anchor = "a"
36 | case position = "p"
37 | case scale = "s"
38 | case rotation = "r"
39 | case opacity = "o"
40 | case skew = "sk"
41 | case skewAxis = "sa"
42 | }
43 |
44 | required init(from decoder: Decoder) throws {
45 | let container = try decoder.container(keyedBy: ShapeTransform.CodingKeys.self)
46 | self.anchor = try container.decodeIfPresent(KeyframeGroup.self, forKey: .anchor) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
47 | self.position = try container.decodeIfPresent(KeyframeGroup.self, forKey: .position) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
48 | self.scale = try container.decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
49 | self.rotation = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
50 | self.opacity = try container.decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
51 | self.skew = try container.decodeIfPresent(KeyframeGroup.self, forKey: .skew) ?? KeyframeGroup(Vector1D(0))
52 | self.skewAxis = try container.decodeIfPresent(KeyframeGroup.self, forKey: .skewAxis) ?? KeyframeGroup(Vector1D(0))
53 | try super.init(from: decoder)
54 | }
55 |
56 | override func encode(to encoder: Encoder) throws {
57 | try super.encode(to: encoder)
58 | var container = encoder.container(keyedBy: CodingKeys.self)
59 | try container.encode(anchor, forKey: .anchor)
60 | try container.encode(position, forKey: .position)
61 | try container.encode(scale, forKey: .scale)
62 | try container.encode(rotation, forKey: .rotation)
63 | try container.encode(opacity, forKey: .opacity)
64 | try container.encode(skew, forKey: .skew)
65 | try container.encode(skewAxis, forKey: .skewAxis)
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Star.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Star.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum StarType: Int, Codable {
11 | case none
12 | case star
13 | case polygon
14 | }
15 |
16 | /// An item that define an ellipse shape
17 | final class Star: ShapeItem {
18 |
19 | /// The direction of the star.
20 | let direction: PathDirection
21 |
22 | /// The position of the star
23 | let position: KeyframeGroup
24 |
25 | /// The outer radius of the star
26 | let outerRadius: KeyframeGroup
27 |
28 | /// The outer roundness of the star
29 | let outerRoundness: KeyframeGroup
30 |
31 | /// The outer radius of the star
32 | let innerRadius: KeyframeGroup?
33 |
34 | /// The outer roundness of the star
35 | let innerRoundness: KeyframeGroup?
36 |
37 | /// The rotation of the star
38 | let rotation: KeyframeGroup
39 |
40 | /// The number of points on the star
41 | let points: KeyframeGroup
42 |
43 | /// The type of star
44 | let starType: StarType
45 |
46 | private enum CodingKeys : String, CodingKey {
47 | case direction = "d"
48 | case position = "p"
49 | case outerRadius = "or"
50 | case outerRoundness = "os"
51 | case innerRadius = "ir"
52 | case innerRoundness = "is"
53 | case rotation = "r"
54 | case points = "pt"
55 | case starType = "sy"
56 | }
57 |
58 | required init(from decoder: Decoder) throws {
59 | let container = try decoder.container(keyedBy: Star.CodingKeys.self)
60 | self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
61 | self.position = try container.decode(KeyframeGroup.self, forKey: .position)
62 | self.outerRadius = try container.decode(KeyframeGroup.self, forKey: .outerRadius)
63 | self.outerRoundness = try container.decode(KeyframeGroup.self, forKey: .outerRoundness)
64 | self.innerRadius = try container.decodeIfPresent(KeyframeGroup.self, forKey: .innerRadius)
65 | self.innerRoundness = try container.decodeIfPresent(KeyframeGroup.self, forKey: .innerRoundness)
66 | self.rotation = try container.decode(KeyframeGroup.self, forKey: .rotation)
67 | self.points = try container.decode(KeyframeGroup.self, forKey: .points)
68 | self.starType = try container.decode(StarType.self, forKey: .starType)
69 | try super.init(from: decoder)
70 | }
71 |
72 | override func encode(to encoder: Encoder) throws {
73 | try super.encode(to: encoder)
74 | var container = encoder.container(keyedBy: CodingKeys.self)
75 | try container.encode(direction, forKey: .direction)
76 | try container.encode(position, forKey: .position)
77 | try container.encode(outerRadius, forKey: .outerRadius)
78 | try container.encode(outerRoundness, forKey: .outerRoundness)
79 | try container.encode(innerRadius, forKey: .innerRadius)
80 | try container.encode(innerRoundness, forKey: .innerRoundness)
81 | try container.encode(rotation, forKey: .rotation)
82 | try container.encode(points, forKey: .points)
83 | try container.encode(starType, forKey: .starType)
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Stroke.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Stroke.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// An item that define an ellipse shape
11 | final class Stroke: ShapeItem {
12 |
13 | /// The opacity of the stroke
14 | let opacity: KeyframeGroup
15 |
16 | /// The Color of the stroke
17 | let color: KeyframeGroup
18 |
19 | /// The width of the stroke
20 | let width: KeyframeGroup
21 |
22 | /// Line Cap
23 | let lineCap: LineCap
24 |
25 | /// Line Join
26 | let lineJoin: LineJoin
27 |
28 | /// Miter Limit
29 | let miterLimit: Double
30 |
31 | /// The dash pattern of the stroke
32 | let dashPattern: [DashElement]?
33 |
34 | private enum CodingKeys : String, CodingKey {
35 | case opacity = "o"
36 | case color = "c"
37 | case width = "w"
38 | case lineCap = "lc"
39 | case lineJoin = "lj"
40 | case miterLimit = "ml"
41 | case dashPattern = "d"
42 | }
43 |
44 | required init(from decoder: Decoder) throws {
45 | let container = try decoder.container(keyedBy: Stroke.CodingKeys.self)
46 | self.opacity = try container.decode(KeyframeGroup.self, forKey: .opacity)
47 | self.color = try container.decode(KeyframeGroup.self, forKey: .color)
48 | self.width = try container.decode(KeyframeGroup.self, forKey: .width)
49 | self.lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round
50 | self.lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round
51 | self.miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4
52 | self.dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern)
53 | try super.init(from: decoder)
54 | }
55 |
56 | override func encode(to encoder: Encoder) throws {
57 | try super.encode(to: encoder)
58 | var container = encoder.container(keyedBy: CodingKeys.self)
59 | try container.encode(opacity, forKey: .opacity)
60 | try container.encode(color, forKey: .color)
61 | try container.encode(width, forKey: .width)
62 | try container.encode(lineCap, forKey: .lineCap)
63 | try container.encode(lineJoin, forKey: .lineJoin)
64 | try container.encode(miterLimit, forKey: .miterLimit)
65 | try container.encodeIfPresent(dashPattern, forKey: .dashPattern)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/ShapeItems/Trim.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Trim.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/8/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum TrimType: Int, Codable {
11 | case simultaneously = 1
12 | case individually = 2
13 | }
14 | /// An item that define an ellipse shape
15 | final class Trim: ShapeItem {
16 |
17 | /// The start of the trim
18 | let start: KeyframeGroup
19 |
20 | /// The end of the trim
21 | let end: KeyframeGroup
22 |
23 | /// The offset of the trim
24 | let offset: KeyframeGroup
25 |
26 | let trimType: TrimType
27 |
28 | private enum CodingKeys : String, CodingKey {
29 | case start = "s"
30 | case end = "e"
31 | case offset = "o"
32 | case trimType = "m"
33 | }
34 |
35 | required init(from decoder: Decoder) throws {
36 | let container = try decoder.container(keyedBy: Trim.CodingKeys.self)
37 | self.start = try container.decode(KeyframeGroup.self, forKey: .start)
38 | self.end = try container.decode(KeyframeGroup.self, forKey: .end)
39 | self.offset = try container.decode(KeyframeGroup.self, forKey: .offset)
40 | self.trimType = try container.decode(TrimType.self, forKey: .trimType)
41 | try super.init(from: decoder)
42 | }
43 |
44 | override func encode(to encoder: Encoder) throws {
45 | try super.encode(to: encoder)
46 | var container = encoder.container(keyedBy: CodingKeys.self)
47 | try container.encode(start, forKey: .start)
48 | try container.encode(end, forKey: .end)
49 | try container.encode(offset, forKey: .offset)
50 | try container.encode(trimType, forKey: .trimType)
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Text/Font.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Font.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class Font: Codable {
11 |
12 | let name: String
13 | let familyName: String
14 | let style: String
15 | let ascent: Double
16 |
17 | private enum CodingKeys: String, CodingKey {
18 | case name = "fName"
19 | case familyName = "fFamily"
20 | case style = "fStyle"
21 | case ascent = "ascent"
22 | }
23 |
24 | }
25 |
26 | /// A list of fonts
27 | final class FontList: Codable {
28 |
29 | let fonts: [Font]
30 |
31 | enum CodingKeys : String, CodingKey {
32 | case fonts = "list"
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Text/Glyph.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Glyph.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /// A model that holds a vector character
11 | final class Glyph: Codable {
12 |
13 | /// The character
14 | let character: String
15 |
16 | /// The font size of the character
17 | let fontSize: Double
18 |
19 | /// The font family of the character
20 | let fontFamily: String
21 |
22 | /// The Style of the character
23 | let fontStyle: String
24 |
25 | /// The Width of the character
26 | let width: Double
27 |
28 | /// The Shape Data of the Character
29 | let shapes: [ShapeItem]
30 |
31 | private enum CodingKeys: String, CodingKey {
32 | case character = "ch"
33 | case fontSize = "size"
34 | case fontFamily = "fFamily"
35 | case fontStyle = "style"
36 | case width = "w"
37 | case shapeWrapper = "data"
38 | }
39 |
40 | private enum ShapeKey: String, CodingKey {
41 | case shapes = "shapes"
42 | }
43 |
44 | required init(from decoder: Decoder) throws {
45 | let container = try decoder.container(keyedBy: Glyph.CodingKeys.self)
46 | self.character = try container.decode(String.self, forKey: .character)
47 | self.fontSize = try container.decode(Double.self, forKey: .fontSize)
48 | self.fontFamily = try container.decode(String.self, forKey: .fontFamily)
49 | self.fontStyle = try container.decode(String.self, forKey: .fontStyle)
50 | self.width = try container.decode(Double.self, forKey: .width)
51 | if container.contains(.shapeWrapper),
52 | let shapeContainer = try? container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper),
53 | shapeContainer.contains(.shapes) {
54 | self.shapes = try shapeContainer.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .shapes)
55 | } else {
56 | self.shapes = []
57 | }
58 | }
59 |
60 | func encode(to encoder: Encoder) throws {
61 | var container = encoder.container(keyedBy: CodingKeys.self)
62 |
63 | try container.encode(character, forKey: .character)
64 | try container.encode(fontSize, forKey: .fontSize)
65 | try container.encode(fontFamily, forKey: .fontFamily)
66 | try container.encode(fontStyle, forKey: .fontStyle)
67 | try container.encode(width, forKey: .width)
68 |
69 | var shapeContainer = container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper)
70 | try shapeContainer.encode(shapes, forKey: .shapes)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Text/TextAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextAnimator.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class TextAnimator: Codable {
11 |
12 | let name: String
13 |
14 | /// Anchor
15 | let anchor: KeyframeGroup?
16 |
17 | /// Position
18 | let position: KeyframeGroup?
19 |
20 | /// Scale
21 | let scale: KeyframeGroup?
22 |
23 | /// Skew
24 | let skew: KeyframeGroup?
25 |
26 | /// Skew Axis
27 | let skewAxis: KeyframeGroup?
28 |
29 | /// Rotation
30 | let rotation: KeyframeGroup?
31 |
32 | /// Opacity
33 | let opacity: KeyframeGroup?
34 |
35 | /// Stroke Color
36 | let strokeColor: KeyframeGroup?
37 |
38 | /// Fill Color
39 | let fillColor: KeyframeGroup?
40 |
41 | /// Stroke Width
42 | let strokeWidth: KeyframeGroup?
43 |
44 | /// Tracking
45 | let tracking: KeyframeGroup?
46 |
47 | private enum CodingKeys: String, CodingKey {
48 | // case textSelector = "s" TODO
49 | case textAnimator = "a"
50 | case name = "nm"
51 | }
52 |
53 | private enum TextSelectorKeys: String, CodingKey {
54 | case start = "s"
55 | case end = "e"
56 | case offset = "o"
57 | }
58 |
59 | private enum TextAnimatorKeys: String, CodingKey {
60 | case fillColor = "fc"
61 | case strokeColor = "sc"
62 | case strokeWidth = "sw"
63 | case tracking = "t"
64 | case anchor = "a"
65 | case position = "p"
66 | case scale = "s"
67 | case skew = "sk"
68 | case skewAxis = "sa"
69 | case rotation = "r"
70 | case opacity = "o"
71 | }
72 |
73 | required init(from decoder: Decoder) throws {
74 | let container = try decoder.container(keyedBy: TextAnimator.CodingKeys.self)
75 | self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
76 | let animatorContainer = try container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator)
77 | self.fillColor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .fillColor)
78 | self.strokeColor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .strokeColor)
79 | self.strokeWidth = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .strokeWidth)
80 | self.tracking = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .tracking)
81 | self.anchor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .anchor)
82 | self.position = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .position)
83 | self.scale = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .scale)
84 | self.skew = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .skew)
85 | self.skewAxis = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .skewAxis)
86 | self.rotation = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotation)
87 | self.opacity = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .opacity)
88 |
89 | }
90 |
91 | func encode(to encoder: Encoder) throws {
92 | var container = encoder.container(keyedBy: CodingKeys.self)
93 | var animatorContainer = container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator)
94 | try animatorContainer.encodeIfPresent(fillColor, forKey: .fillColor)
95 | try animatorContainer.encodeIfPresent(strokeColor, forKey: .strokeColor)
96 | try animatorContainer.encodeIfPresent(strokeWidth, forKey: .strokeWidth)
97 | try animatorContainer.encodeIfPresent(tracking, forKey: .tracking)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Model/Text/TextDocument.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextDocument.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/9/19.
6 | //
7 |
8 | import Foundation
9 |
10 | enum TextJustification: Int, Codable {
11 | case left
12 | case right
13 | case center
14 | }
15 |
16 | final class TextDocument: Codable {
17 |
18 | /// The Text
19 | let text: String
20 |
21 | /// The Font size
22 | let fontSize: Double
23 |
24 | /// The Font Family
25 | let fontFamily: String
26 |
27 | /// Justification
28 | let justification: TextJustification
29 |
30 | /// Tracking
31 | let tracking: Int
32 |
33 | /// Line Height
34 | let lineHeight: Double
35 |
36 | /// Baseline
37 | let baseline: Double?
38 |
39 | /// Fill Color data
40 | let fillColorData: Color
41 |
42 | /// Scroke Color data
43 | let strokeColorData: Color?
44 |
45 | /// Stroke Width
46 | let strokeWidth: Double?
47 |
48 | /// Stroke Over Fill
49 | let strokeOverFill: Bool?
50 |
51 | let textFramePosition: Vector3D?
52 |
53 | let textFrameSize: Vector3D?
54 |
55 | private enum CodingKeys : String, CodingKey {
56 | case text = "t"
57 | case fontSize = "s"
58 | case fontFamily = "f"
59 | case justification = "j"
60 | case tracking = "tr"
61 | case lineHeight = "lh"
62 | case baseline = "ls"
63 | case fillColorData = "fc"
64 | case strokeColorData = "sc"
65 | case strokeWidth = "sw"
66 | case strokeOverFill = "of"
67 | case textFramePosition = "ps"
68 | case textFrameSize = "sz"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Extensions/ItemsExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemsExtension.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/18/19.
6 | //
7 |
8 | import Foundation
9 |
10 | final class NodeTree {
11 | var rootNode: AnimatorNode? = nil
12 | var transform: ShapeTransform? = nil
13 | var renderContainers: [ShapeContainerLayer] = []
14 | var paths: [PathOutputNode] = []
15 | var childrenNodes: [AnimatorNode] = []
16 | }
17 |
18 | extension Array where Element == ShapeItem {
19 | func initializeNodeTree() -> NodeTree {
20 |
21 | let nodeTree = NodeTree()
22 |
23 | for item in self {
24 | guard item.hidden == false, item.type != .unknown else { continue }
25 | if let fill = item as? Fill {
26 | let node = FillNode(parentNode: nodeTree.rootNode, fill: fill)
27 | nodeTree.rootNode = node
28 | nodeTree.childrenNodes.append(node)
29 | } else if let stroke = item as? Stroke {
30 | let node = StrokeNode(parentNode: nodeTree.rootNode, stroke: stroke)
31 | nodeTree.rootNode = node
32 | nodeTree.childrenNodes.append(node)
33 | } else if let gradientFill = item as? GradientFill {
34 | let node = GradientFillNode(parentNode: nodeTree.rootNode, gradientFill: gradientFill)
35 | nodeTree.rootNode = node
36 | nodeTree.childrenNodes.append(node)
37 | } else if let gradientStroke = item as? GradientStroke {
38 | let node = GradientStrokeNode(parentNode: nodeTree.rootNode, gradientStroke: gradientStroke)
39 | nodeTree.rootNode = node
40 | nodeTree.childrenNodes.append(node)
41 | } else if let ellipse = item as? Ellipse {
42 | let node = EllipseNode(parentNode: nodeTree.rootNode, ellipse: ellipse)
43 | nodeTree.rootNode = node
44 | nodeTree.childrenNodes.append(node)
45 | } else if let rect = item as? Rectangle {
46 | let node = RectangleNode(parentNode: nodeTree.rootNode, rectangle: rect)
47 | nodeTree.rootNode = node
48 | nodeTree.childrenNodes.append(node)
49 | } else if let star = item as? Star {
50 | switch star.starType {
51 | case .none:
52 | continue
53 | case .polygon:
54 | let node = PolygonNode(parentNode: nodeTree.rootNode, star: star)
55 | nodeTree.rootNode = node
56 | nodeTree.childrenNodes.append(node)
57 | case .star:
58 | let node = StarNode(parentNode: nodeTree.rootNode, star: star)
59 | nodeTree.rootNode = node
60 | nodeTree.childrenNodes.append(node)
61 | }
62 | } else if let shape = item as? Shape {
63 | let node = ShapeNode(parentNode: nodeTree.rootNode, shape: shape)
64 | nodeTree.rootNode = node
65 | nodeTree.childrenNodes.append(node)
66 | } else if let trim = item as? Trim {
67 | let node = TrimPathNode(parentNode: nodeTree.rootNode, trim: trim, upstreamPaths: nodeTree.paths)
68 | nodeTree.rootNode = node
69 | nodeTree.childrenNodes.append(node)
70 | } else if let xform = item as? ShapeTransform {
71 | nodeTree.transform = xform
72 | continue
73 | } else if let group = item as? Group {
74 |
75 | let tree = group.items.initializeNodeTree()
76 | let node = GroupNode(name: group.name, parentNode: nodeTree.rootNode, tree: tree)
77 | nodeTree.rootNode = node
78 | nodeTree.childrenNodes.append(node)
79 | /// Now add all child paths to current tree
80 | nodeTree.paths.append(contentsOf: tree.paths)
81 | nodeTree.renderContainers.append(node.container)
82 | }
83 |
84 | if let pathNode = nodeTree.rootNode as? PathNode {
85 | //// Add path container to the node tree
86 | nodeTree.paths.append(pathNode.pathOutput)
87 | }
88 |
89 | if let renderNode = nodeTree.rootNode as? RenderNode {
90 | nodeTree.renderContainers.append(ShapeRenderLayer(renderer: renderNode.renderer))
91 | }
92 | }
93 | return nodeTree
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/NodeProperty.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NodeProperty.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A node property that holds a reference to a T ValueProvider and a T ValueContainer.
12 | class NodeProperty: AnyNodeProperty {
13 |
14 | var valueType: Any.Type { return T.self }
15 |
16 | var value: T {
17 | return typedContainer.outputValue
18 | }
19 |
20 | var valueContainer: AnyValueContainer {
21 | return typedContainer
22 | }
23 |
24 | var valueProvider: AnyValueProvider
25 |
26 | init(provider: AnyValueProvider) {
27 | self.valueProvider = provider
28 | self.typedContainer = ValueContainer(provider.value(frame: 0) as! T)
29 | self.typedContainer.setNeedsUpdate()
30 | }
31 |
32 | func needsUpdate(frame: CGFloat) -> Bool {
33 | return valueContainer.needsUpdate || valueProvider.hasUpdate(frame: frame)
34 | }
35 |
36 | func setProvider(provider: AnyValueProvider) {
37 | guard provider.valueType == valueType else { return }
38 | self.valueProvider = provider
39 | valueContainer.setNeedsUpdate()
40 | }
41 |
42 | func update(frame: CGFloat) {
43 | typedContainer.setValue(valueProvider.value(frame: frame), forFrame: frame)
44 | }
45 |
46 | fileprivate var typedContainer: ValueContainer
47 | }
48 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnyNodeProperty.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | /// A property of a node. The node property holds a provider and a container
11 | protocol AnyNodeProperty {
12 |
13 | /// Returns true if the property needs to recompute its stored value
14 | func needsUpdate(frame: CGFloat) -> Bool
15 |
16 | /// Updates the property for the frame
17 | func update(frame: CGFloat)
18 |
19 | /// The stored value container for the property
20 | var valueContainer: AnyValueContainer { get }
21 |
22 | /// The value provider for the property
23 | var valueProvider: AnyValueProvider { get }
24 |
25 | /// The Type of the value provider
26 | var valueType: Any.Type { get }
27 |
28 | /// Sets the value provider for the property.
29 | func setProvider(provider: AnyValueProvider)
30 | }
31 |
32 | extension AnyNodeProperty {
33 |
34 | /// Returns the most recently computed value for the keypath, returns nil if property wasn't found
35 | func getValueOfType() -> T? {
36 | return valueContainer.value as? T
37 | }
38 |
39 | /// Returns the most recently computed value for the keypath, returns nil if property wasn't found
40 | func getValue() -> Any? {
41 | return valueContainer.value
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnyValueContainer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// The container for the value of a property.
12 | protocol AnyValueContainer: class {
13 |
14 | /// The stored value of the container
15 | var value: Any { get }
16 |
17 | /// Notifies the provider that it should update its container
18 | func setNeedsUpdate()
19 |
20 | /// When true the container needs to have its value updated by its provider
21 | var needsUpdate: Bool { get }
22 |
23 | /// The frame time of the last provided update
24 | var lastUpdateFrame: CGFloat { get }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeypathSettable.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | /// Protocol that provides keypath search functionality. Returns all node properties associated with a keypath.
12 | protocol KeypathSearchable {
13 |
14 | /// The name of the Keypath
15 | var keypathName: String { get }
16 |
17 | /// A list of properties belonging to the keypath.
18 | var keypathProperties: [String : AnyNodeProperty] { get }
19 |
20 | /// Children Keypaths
21 | var childKeypaths: [KeypathSearchable] { get }
22 |
23 | var keypathLayer: CALayer? { get }
24 | }
25 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NodePropertyMap.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/21/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | protocol NodePropertyMap {
12 | var properties: [AnyNodeProperty] { get }
13 | }
14 |
15 | extension NodePropertyMap {
16 |
17 | var childKeypaths: [KeypathSearchable] {
18 | return []
19 | }
20 |
21 | var keypathLayer: CALayer? {
22 | return nil
23 | }
24 |
25 | /// Checks if the node's local contents need to be rebuilt.
26 | func needsLocalUpdate(frame: CGFloat) -> Bool {
27 | for property in properties {
28 | if property.needsUpdate(frame: frame) {
29 | return true
30 | }
31 | }
32 | return false
33 | }
34 |
35 | /// Rebuilds only the local nodes that have an update for the frame
36 | func updateNodeProperties(frame: CGFloat) {
37 | properties.forEach { (property) in
38 | property.update(frame: frame)
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/ValueContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ValueContainer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A container for a node value that is Typed to T.
12 | class ValueContainer: AnyValueContainer {
13 |
14 | private(set) var lastUpdateFrame: CGFloat = CGFloat.infinity
15 |
16 | func setValue(_ value: Any, forFrame: CGFloat) {
17 | if let typedValue = value as? T {
18 | needsUpdate = false
19 | lastUpdateFrame = forFrame
20 | outputValue = typedValue
21 | }
22 | }
23 |
24 | func setNeedsUpdate() {
25 | needsUpdate = true
26 | }
27 |
28 | var value: Any {
29 | return outputValue as Any
30 | }
31 |
32 | var outputValue: T {
33 | didSet {
34 | needsUpdate = false
35 | }
36 | }
37 |
38 | init(_ value: T) {
39 | self.outputValue = value
40 | }
41 |
42 | fileprivate(set) var needsUpdate: Bool = true
43 | }
44 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyframeGroupInterpolator.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/22/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A value provider that produces an array of values from an array of Keyframe Interpolators
12 | final class GroupInterpolator: AnyValueProvider where ValueType: Interpolatable {
13 | var valueType: Any.Type {
14 | return [ValueType].self
15 | }
16 |
17 | func hasUpdate(frame: CGFloat) -> Bool {
18 | let updated = keyframeInterpolators.first(where: {$0.hasUpdate(frame: frame)})
19 | return updated != nil
20 | }
21 |
22 | func value(frame: CGFloat) -> Any {
23 | let output = keyframeInterpolators.map({$0.value(frame: frame) as! ValueType})
24 | return output
25 | }
26 |
27 | /// Initialize with an array of array of keyframes.
28 | init(keyframeGroups: ContiguousArray>>) {
29 | self.keyframeInterpolators = ContiguousArray(keyframeGroups.map({KeyframeInterpolator(keyframes: $0)}))
30 | }
31 | let keyframeInterpolators: ContiguousArray>
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SingleValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | /// Returns a value for every frame.
12 | final class SingleValueProvider: AnyValueProvider {
13 |
14 | var value: ValueType {
15 | didSet {
16 | hasUpdate = true
17 | }
18 | }
19 |
20 | init(_ value: ValueType) {
21 | self.value = value
22 | }
23 |
24 | var valueType: Any.Type {
25 | return ValueType.self
26 | }
27 |
28 | func hasUpdate(frame: CGFloat) -> Bool {
29 | return hasUpdate
30 | }
31 |
32 | func value(frame: CGFloat) -> Any {
33 | hasUpdate = false
34 | return value
35 | }
36 |
37 | private var hasUpdate: Bool = true
38 | }
39 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TransformNodeOutput.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | import QuartzCore
11 |
12 | class GroupOutputNode: NodeOutput {
13 |
14 | init(parent: NodeOutput?, rootNode: NodeOutput?) {
15 | self.parent = parent
16 | self.rootNode = rootNode
17 | }
18 |
19 | let parent: NodeOutput?
20 | let rootNode: NodeOutput?
21 | var isEnabled: Bool = true
22 |
23 | private(set) var outputPath: CGPath? = nil
24 | private(set) var transform: CATransform3D = CATransform3DIdentity
25 |
26 | func setTransform(_ xform: CATransform3D, forFrame: CGFloat) {
27 | transform = xform
28 | outputPath = nil
29 | }
30 |
31 | func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
32 | guard isEnabled else {
33 | let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
34 | outputPath = parent?.outputPath
35 | return upstreamUpdates
36 | }
37 |
38 | let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
39 | if upstreamUpdates {
40 | outputPath = nil
41 | }
42 | let rootUpdates = rootNode?.hasOutputUpdates(forFrame) ?? false
43 | if rootUpdates {
44 | outputPath = nil
45 | }
46 |
47 | var localUpdates: Bool = false
48 | if outputPath == nil {
49 | localUpdates = true
50 |
51 | let newPath = CGMutablePath()
52 | if let parentNode = parent, let parentPath = parentNode.outputPath {
53 | /// First add parent path.
54 | newPath.addPath(parentPath)
55 | }
56 | var xform = CATransform3DGetAffineTransform(transform)
57 | if let rootNode = rootNode,
58 | let rootPath = rootNode.outputPath,
59 | let xformedPath = rootPath.copy(using: &xform) {
60 | /// Now add root path. Note root path is transformed.
61 | newPath.addPath(xformedPath)
62 | }
63 |
64 | outputPath = newPath
65 | }
66 |
67 | return upstreamUpdates || localUpdates
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PassThroughOutputNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | class PassThroughOutputNode: NodeOutput {
12 |
13 | init(parent: NodeOutput?) {
14 | self.parent = parent
15 | }
16 |
17 | let parent: NodeOutput?
18 |
19 | var hasUpdate: Bool = false
20 | var isEnabled: Bool = true
21 |
22 | func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
23 | /// Changes to this node do not affect downstream nodes.
24 | let parentUpdate = parent?.hasOutputUpdates(forFrame) ?? false
25 | /// Changes to upstream nodes do, however, affect this nodes state.
26 | hasUpdate = hasUpdate || parentUpdate
27 | return parentUpdate
28 | }
29 |
30 | var outputPath: CGPath? {
31 | if let parent = parent {
32 | return parent.outputPath
33 | }
34 | return nil
35 | }
36 |
37 | func hasRenderUpdates(_ forFrame: CGFloat) -> Bool {
38 | /// Return true if there are upstream updates or if this node has updates
39 | let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
40 | hasUpdate = hasUpdate || upstreamUpdates
41 | return hasUpdate
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PathNodeOutput.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A node that has an output of a BezierPath
12 | class PathOutputNode: NodeOutput {
13 |
14 | init(parent: NodeOutput?) {
15 | self.parent = parent
16 | }
17 |
18 | let parent: NodeOutput?
19 |
20 | fileprivate(set) var outputPath: CGPath? = nil
21 |
22 | var lastUpdateFrame: CGFloat? = nil
23 | var lastPathBuildFrame: CGFloat? = nil
24 | var isEnabled: Bool = true
25 |
26 | func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
27 | guard isEnabled else {
28 | let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
29 | outputPath = parent?.outputPath
30 | return upstreamUpdates
31 | }
32 |
33 | /// Ask if parent was updated
34 | let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
35 |
36 | /// If parent was updated and the path hasn't been built for this frame, clear the path.
37 | if upstreamUpdates && lastPathBuildFrame != forFrame {
38 | outputPath = nil
39 | }
40 |
41 | if outputPath == nil {
42 | /// If the path is clear, build the new path.
43 | lastPathBuildFrame = forFrame
44 | let newPath = CGMutablePath()
45 | if let parentNode = parent, let parentPath = parentNode.outputPath {
46 | newPath.addPath(parentPath)
47 | }
48 | for path in pathObjects {
49 | for subPath in path.paths {
50 | newPath.addPath(subPath.cgPath())
51 | }
52 | }
53 | outputPath = newPath
54 | }
55 |
56 | /// Return true if there were upstream updates or if this node was updated.
57 | return upstreamUpdates || (lastUpdateFrame == forFrame)
58 | }
59 |
60 | // MARK: Internal
61 |
62 | fileprivate(set) var totalLength: CGFloat = 0
63 | fileprivate(set) var pathObjects: [CompoundBezierPath] = []
64 |
65 | @discardableResult func removePaths(updateFrame: CGFloat?) -> [CompoundBezierPath] {
66 | lastUpdateFrame = updateFrame
67 | let returnPaths = pathObjects
68 | outputPath = nil
69 | totalLength = 0
70 | pathObjects = []
71 | return returnPaths
72 | }
73 |
74 | func setPath(_ path: BezierPath, updateFrame: CGFloat) {
75 | lastUpdateFrame = updateFrame
76 | outputPath = nil
77 | totalLength = path.length
78 | pathObjects = [CompoundBezierPath(path: path)]
79 | }
80 |
81 | func appendPath(_ path: CompoundBezierPath, updateFrame: CGFloat) {
82 | lastUpdateFrame = updateFrame
83 | outputPath = nil
84 | totalLength = totalLength + path.length
85 | pathObjects.append(path)
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FillRenderer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 | import CoreGraphics
11 |
12 | extension FillRule {
13 | var cgFillRule: CGPathFillRule {
14 | switch self {
15 | case .evenOdd:
16 | return .evenOdd
17 | default:
18 | return .winding
19 | }
20 | }
21 |
22 | var caFillRule: CAShapeLayerFillRule {
23 | switch self {
24 | case .evenOdd:
25 | return CAShapeLayerFillRule.evenOdd
26 | default:
27 | return CAShapeLayerFillRule.nonZero
28 | }
29 | }
30 | }
31 |
32 | /// A rendered for a Path Fill
33 | final class FillRenderer: PassThroughOutputNode, Renderable {
34 |
35 | let shouldRenderInContext: Bool = false
36 |
37 | func updateShapeLayer(layer: CAShapeLayer) {
38 | layer.fillColor = color
39 | layer.opacity = Float(opacity)
40 | layer.fillRule = fillRule.caFillRule
41 | hasUpdate = false
42 | }
43 |
44 | var color: CGColor? {
45 | didSet {
46 | hasUpdate = true
47 | }
48 | }
49 |
50 | var opacity: CGFloat = 0 {
51 | didSet {
52 | hasUpdate = true
53 | }
54 | }
55 |
56 | var fillRule: FillRule = .none {
57 | didSet {
58 | hasUpdate = true
59 | }
60 | }
61 |
62 | func render(_ inContext: CGContext) {
63 | guard inContext.path != nil && inContext.path!.isEmpty == false else {
64 | return
65 | }
66 | guard let color = color else { return }
67 | hasUpdate = false
68 | inContext.setAlpha(opacity * 0.01)
69 | inContext.setFillColor(color)
70 | inContext.fillPath(using: fillRule.cgFillRule)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GradientStrokeRenderer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | // MARK: - Renderer
12 |
13 | final class GradientStrokeRenderer: PassThroughOutputNode, Renderable {
14 |
15 | override func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
16 | let updates = super.hasOutputUpdates(forFrame)
17 | return updates || strokeRender.hasUpdate || gradientRender.hasUpdate
18 | }
19 |
20 | var shouldRenderInContext: Bool = true
21 |
22 | func updateShapeLayer(layer: CAShapeLayer) {
23 | /// Not Applicable
24 | }
25 |
26 | let strokeRender: StrokeRenderer
27 | let gradientRender: GradientFillRenderer
28 |
29 | override init(parent: NodeOutput?) {
30 | self.strokeRender = StrokeRenderer(parent: nil)
31 | self.gradientRender = GradientFillRenderer(parent: nil)
32 | self.strokeRender.color = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1, 1, 1, 1])
33 | super.init(parent: parent)
34 | }
35 |
36 | func render(_ inContext: CGContext) {
37 | guard inContext.path != nil && inContext.path!.isEmpty == false else {
38 | return
39 | }
40 |
41 | strokeRender.hasUpdate = false
42 | hasUpdate = false
43 | gradientRender.hasUpdate = false
44 |
45 | strokeRender.setupForStroke(inContext)
46 |
47 | inContext.replacePathWithStrokedPath()
48 |
49 | /// Now draw the gradient.
50 | gradientRender.render(inContext)
51 |
52 | }
53 |
54 | func renderBoundsFor(_ boundingBox: CGRect) -> CGRect {
55 | return strokeRender.renderBoundsFor(boundingBox)
56 | }
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StrokeRenderer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | extension LineJoin {
12 | var cgLineJoin: CGLineJoin {
13 | switch self {
14 | case .bevel:
15 | return .bevel
16 | case .none:
17 | return .miter
18 | case .miter:
19 | return .miter
20 | case .round:
21 | return .round
22 | }
23 | }
24 |
25 | var caLineJoin: CAShapeLayerLineJoin {
26 | switch self {
27 | case .none:
28 | return CAShapeLayerLineJoin.miter
29 | case .miter:
30 | return CAShapeLayerLineJoin.miter
31 | case .round:
32 | return CAShapeLayerLineJoin.round
33 | case .bevel:
34 | return CAShapeLayerLineJoin.bevel
35 | }
36 | }
37 | }
38 |
39 | extension LineCap {
40 | var cgLineCap: CGLineCap {
41 | switch self {
42 | case .none:
43 | return .butt
44 | case .butt:
45 | return .butt
46 | case .round:
47 | return .round
48 | case .square:
49 | return .square
50 | }
51 | }
52 |
53 | var caLineCap: CAShapeLayerLineCap {
54 | switch self {
55 | case .none:
56 | return CAShapeLayerLineCap.butt
57 | case .butt:
58 | return CAShapeLayerLineCap.butt
59 | case .round:
60 | return CAShapeLayerLineCap.round
61 | case .square:
62 | return CAShapeLayerLineCap.square
63 | }
64 | }
65 | }
66 |
67 | // MARK: - Renderer
68 |
69 | /// A rendered that renders a stroke on a path.
70 | final class StrokeRenderer: PassThroughOutputNode, Renderable {
71 |
72 | var shouldRenderInContext: Bool = false
73 |
74 | var color: CGColor? {
75 | didSet {
76 | hasUpdate = true
77 | }
78 | }
79 |
80 | var opacity: CGFloat = 0 {
81 | didSet {
82 | hasUpdate = true
83 | }
84 | }
85 |
86 | var width: CGFloat = 0 {
87 | didSet {
88 | hasUpdate = true
89 | }
90 | }
91 |
92 | var miterLimit: CGFloat = 0 {
93 | didSet {
94 | hasUpdate = true
95 | }
96 | }
97 |
98 | var lineCap: LineCap = .none {
99 | didSet {
100 | hasUpdate = true
101 | }
102 | }
103 |
104 | var lineJoin: LineJoin = .none {
105 | didSet {
106 | hasUpdate = true
107 | }
108 | }
109 |
110 | var dashPhase: CGFloat? {
111 | didSet {
112 | hasUpdate = true
113 | }
114 | }
115 |
116 | var dashLengths: [CGFloat]? {
117 | didSet {
118 | hasUpdate = true
119 | }
120 | }
121 |
122 | func renderBoundsFor(_ boundingBox: CGRect) -> CGRect {
123 | return boundingBox.insetBy(dx: -width, dy: -width)
124 | }
125 |
126 | func setupForStroke(_ inContext: CGContext) {
127 | inContext.setLineWidth(width)
128 | inContext.setMiterLimit(miterLimit)
129 | inContext.setLineCap(lineCap.cgLineCap)
130 | inContext.setLineJoin(lineJoin.cgLineJoin)
131 | if let dashPhase = dashPhase, let lengths = dashLengths {
132 | inContext.setLineDash(phase: dashPhase, lengths: lengths)
133 | } else {
134 | inContext.setLineDash(phase: 0, lengths: [])
135 | }
136 | }
137 |
138 | func render(_ inContext: CGContext) {
139 | guard inContext.path != nil && inContext.path!.isEmpty == false else {
140 | return
141 | }
142 | guard let color = color else { return }
143 | hasUpdate = false
144 | setupForStroke(inContext)
145 | inContext.setAlpha(opacity)
146 | inContext.setStrokeColor(color)
147 | inContext.strokePath()
148 | }
149 |
150 | func updateShapeLayer(layer: CAShapeLayer) {
151 | layer.strokeColor = color
152 | layer.opacity = Float(opacity)
153 | layer.lineWidth = width
154 | layer.lineJoin = lineJoin.caLineJoin
155 | layer.lineCap = lineCap.caLineCap
156 | layer.lineDashPhase = dashPhase ?? 0
157 | layer.fillColor = nil
158 | if let dashPattern = dashLengths {
159 | layer.lineDashPattern = dashPattern.map({ NSNumber(value: Double($0)) })
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EllipseNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/17/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | final class EllipseNodeProperties: NodePropertyMap, KeypathSearchable {
12 |
13 | var keypathName: String
14 |
15 | init(ellipse: Ellipse) {
16 | self.keypathName = ellipse.name
17 | self.direction = ellipse.direction
18 | self.position = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.position.keyframes))
19 | self.size = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.size.keyframes))
20 | self.keypathProperties = [
21 | "Position" : position,
22 | "Size" : size
23 | ]
24 | self.properties = Array(keypathProperties.values)
25 | }
26 |
27 | let direction: PathDirection
28 | let position: NodeProperty
29 | let size: NodeProperty
30 |
31 | let keypathProperties: [String : AnyNodeProperty]
32 | let properties: [AnyNodeProperty]
33 | }
34 |
35 | final class EllipseNode: AnimatorNode, PathNode {
36 |
37 | let pathOutput: PathOutputNode
38 |
39 | let properties: EllipseNodeProperties
40 |
41 | init(parentNode: AnimatorNode?, ellipse: Ellipse) {
42 | self.pathOutput = PathOutputNode(parent: parentNode?.outputNode)
43 | self.properties = EllipseNodeProperties(ellipse: ellipse)
44 | self.parentNode = parentNode
45 | }
46 |
47 | // MARK: Animator Node
48 |
49 | var propertyMap: NodePropertyMap & KeypathSearchable {
50 | return properties
51 | }
52 |
53 | let parentNode: AnimatorNode?
54 | var hasLocalUpdates: Bool = false
55 | var hasUpstreamUpdates: Bool = false
56 | var lastUpdateFrame: CGFloat? = nil
57 | var isEnabled: Bool = true {
58 | didSet{
59 | self.pathOutput.isEnabled = self.isEnabled
60 | }
61 | }
62 |
63 | func rebuildOutputs(frame: CGFloat) {
64 | let ellipseSize = properties.size.value.sizeValue
65 | let center = properties.position.value.pointValue
66 |
67 | // Unfortunately we HAVE to manually build out the ellipse.
68 | // Every Apple method constructs an ellipse from the 3 o-clock position
69 | // After effects constructs from the Noon position.
70 | // After effects does clockwise, but also has a flag for reversed.
71 |
72 | var half = ellipseSize * 0.5
73 | if properties.direction == .counterClockwise {
74 | half.width = half.width * -1
75 | }
76 |
77 |
78 | let q1 = CGPoint(x: center.x, y: center.y - half.height)
79 | let q2 = CGPoint(x: center.x + half.width, y: center.y)
80 | let q3 = CGPoint(x: center.x, y: center.y + half.height)
81 | let q4 = CGPoint(x: center.x - half.width, y: center.y)
82 |
83 | let cp = half * EllipseNode.ControlPointConstant
84 |
85 | var path = BezierPath(startPoint: CurveVertex(point: q1,
86 | inTangentRelative: CGPoint(x: -cp.width, y: 0),
87 | outTangentRelative: CGPoint(x: cp.width, y: 0)))
88 | path.addVertex(CurveVertex(point: q2,
89 | inTangentRelative: CGPoint(x: 0, y: -cp.height),
90 | outTangentRelative: CGPoint(x: 0, y: cp.height)))
91 |
92 | path.addVertex(CurveVertex(point: q3,
93 | inTangentRelative: CGPoint(x: cp.width, y: 0),
94 | outTangentRelative: CGPoint(x: -cp.width, y: 0)))
95 |
96 | path.addVertex(CurveVertex(point: q4,
97 | inTangentRelative: CGPoint(x: 0, y: cp.height),
98 | outTangentRelative: CGPoint(x: 0, y: -cp.height)))
99 |
100 | path.addVertex(CurveVertex(point: q1,
101 | inTangentRelative: CGPoint(x: -cp.width, y: 0),
102 | outTangentRelative: CGPoint(x: cp.width, y: 0)))
103 | path.close()
104 | pathOutput.setPath(path, updateFrame: frame)
105 | }
106 |
107 | static let ControlPointConstant: CGFloat = 0.55228
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PathNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/16/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | final class ShapeNodeProperties: NodePropertyMap, KeypathSearchable {
12 |
13 | var keypathName: String
14 |
15 | init(shape: Shape) {
16 | self.keypathName = shape.name
17 | self.path = NodeProperty(provider: KeyframeInterpolator(keyframes: shape.path.keyframes))
18 | self.keypathProperties = [
19 | "Path" : path
20 | ]
21 | self.properties = Array(keypathProperties.values)
22 | }
23 |
24 | let path: NodeProperty
25 | let keypathProperties: [String : AnyNodeProperty]
26 | let properties: [AnyNodeProperty]
27 |
28 | }
29 |
30 | final class ShapeNode: AnimatorNode, PathNode {
31 |
32 | let properties: ShapeNodeProperties
33 |
34 | let pathOutput: PathOutputNode
35 |
36 | init(parentNode: AnimatorNode?, shape: Shape) {
37 | self.pathOutput = PathOutputNode(parent: parentNode?.outputNode)
38 | self.properties = ShapeNodeProperties(shape: shape)
39 | self.parentNode = parentNode
40 | }
41 |
42 | // MARK: Animator Node
43 | var propertyMap: NodePropertyMap & KeypathSearchable {
44 | return properties
45 | }
46 |
47 | let parentNode: AnimatorNode?
48 | var hasLocalUpdates: Bool = false
49 | var hasUpstreamUpdates: Bool = false
50 | var lastUpdateFrame: CGFloat? = nil
51 | var isEnabled: Bool = true {
52 | didSet{
53 | self.pathOutput.isEnabled = self.isEnabled
54 | }
55 | }
56 |
57 | func rebuildOutputs(frame: CGFloat) {
58 | pathOutput.setPath(properties.path.value, updateFrame: frame)
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FillNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/17/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | final class FillNodeProperties: NodePropertyMap, KeypathSearchable {
12 |
13 | var keypathName: String
14 |
15 | init(fill: Fill) {
16 | self.keypathName = fill.name
17 | self.color = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.color.keyframes))
18 | self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.opacity.keyframes))
19 | self.type = fill.fillRule
20 | self.keypathProperties = [
21 | "Opacity" : opacity,
22 | "Color" : color
23 | ]
24 | self.properties = Array(keypathProperties.values)
25 | }
26 |
27 | let opacity: NodeProperty
28 | let color: NodeProperty
29 | let type: FillRule
30 |
31 | let keypathProperties: [String : AnyNodeProperty]
32 | let properties: [AnyNodeProperty]
33 |
34 | }
35 |
36 | final class FillNode: AnimatorNode, RenderNode {
37 |
38 | let fillRender: FillRenderer
39 | var renderer: NodeOutput & Renderable {
40 | return fillRender
41 | }
42 |
43 | let fillProperties: FillNodeProperties
44 |
45 | init(parentNode: AnimatorNode?, fill: Fill) {
46 | self.fillRender = FillRenderer(parent: parentNode?.outputNode)
47 | self.fillProperties = FillNodeProperties(fill: fill)
48 | self.parentNode = parentNode
49 | }
50 |
51 | // MARK: Animator Node Protocol
52 |
53 | var propertyMap: NodePropertyMap & KeypathSearchable {
54 | return fillProperties
55 | }
56 |
57 | let parentNode: AnimatorNode?
58 | var hasLocalUpdates: Bool = false
59 | var hasUpstreamUpdates: Bool = false
60 | var lastUpdateFrame: CGFloat? = nil
61 | var isEnabled: Bool = true {
62 | didSet {
63 | fillRender.isEnabled = isEnabled
64 | }
65 | }
66 |
67 | func localUpdatesPermeateDownstream() -> Bool {
68 | return false
69 | }
70 |
71 | func rebuildOutputs(frame: CGFloat) {
72 | fillRender.color = fillProperties.color.value.cgColorValue
73 | fillRender.opacity = fillProperties.opacity.value.cgFloatValue * 0.01
74 | fillRender.fillRule = fillProperties.type
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GradientFillNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/22/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | final class GradientFillProperties: NodePropertyMap, KeypathSearchable {
12 |
13 | init(gradientfill: GradientFill) {
14 | self.keypathName = gradientfill.name
15 | self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.opacity.keyframes))
16 | self.startPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.startPoint.keyframes))
17 | self.endPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.endPoint.keyframes))
18 | self.colors = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.colors.keyframes))
19 | self.gradientType = gradientfill.gradientType
20 | self.numberOfColors = gradientfill.numberOfColors
21 | self.keypathProperties = [
22 | "Opacity" : opacity,
23 | "Start Point" : startPoint,
24 | "End Point" : endPoint,
25 | "Colors" : colors
26 | ]
27 | self.properties = Array(keypathProperties.values)
28 | }
29 |
30 | var keypathName: String
31 |
32 | let opacity: NodeProperty
33 | let startPoint: NodeProperty
34 | let endPoint: NodeProperty
35 | let colors: NodeProperty<[Double]>
36 |
37 | let gradientType: GradientType
38 | let numberOfColors: Int
39 |
40 |
41 | let keypathProperties: [String : AnyNodeProperty]
42 | let properties: [AnyNodeProperty]
43 |
44 | }
45 |
46 | final class GradientFillNode: AnimatorNode, RenderNode {
47 |
48 | let fillRender: GradientFillRenderer
49 |
50 | var renderer: NodeOutput & Renderable {
51 | return fillRender
52 | }
53 |
54 | let fillProperties: GradientFillProperties
55 |
56 | init(parentNode: AnimatorNode?, gradientFill: GradientFill) {
57 | self.fillRender = GradientFillRenderer(parent: parentNode?.outputNode)
58 | self.fillProperties = GradientFillProperties(gradientfill: gradientFill)
59 | self.parentNode = parentNode
60 | }
61 |
62 | // MARK: Animator Node Protocol
63 |
64 | var propertyMap: NodePropertyMap & KeypathSearchable {
65 | return fillProperties
66 | }
67 |
68 | let parentNode: AnimatorNode?
69 | var hasLocalUpdates: Bool = false
70 | var hasUpstreamUpdates: Bool = false
71 | var lastUpdateFrame: CGFloat? = nil
72 | var isEnabled: Bool = true {
73 | didSet {
74 | fillRender.isEnabled = isEnabled
75 | }
76 | }
77 |
78 | func localUpdatesPermeateDownstream() -> Bool {
79 | return false
80 | }
81 |
82 | func rebuildOutputs(frame: CGFloat) {
83 | fillRender.start = fillProperties.startPoint.value.pointValue
84 | fillRender.end = fillProperties.endPoint.value.pointValue
85 | fillRender.opacity = fillProperties.opacity.value.cgFloatValue * 0.01
86 | fillRender.colors = fillProperties.colors.value.map { CGFloat($0) }
87 | fillRender.type = fillProperties.gradientType
88 | fillRender.numberOfColors = fillProperties.numberOfColors
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StrokeNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/22/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 | // MARK: - Properties
11 |
12 | final class StrokeNodeProperties: NodePropertyMap, KeypathSearchable {
13 |
14 | init(stroke: Stroke) {
15 | self.keypathName = stroke.name
16 | self.color = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.color.keyframes))
17 | self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.opacity.keyframes))
18 | self.width = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.width.keyframes))
19 | self.miterLimit = CGFloat(stroke.miterLimit)
20 | self.lineCap = stroke.lineCap
21 | self.lineJoin = stroke.lineJoin
22 |
23 | if let dashes = stroke.dashPattern {
24 | var dashPatterns = ContiguousArray>>()
25 | var dashPhase = ContiguousArray>()
26 | for dash in dashes {
27 | if dash.type == .offset {
28 | dashPhase = dash.value.keyframes
29 | } else {
30 | dashPatterns.append(dash.value.keyframes)
31 | }
32 | }
33 | self.dashPattern = NodeProperty(provider: GroupInterpolator(keyframeGroups: dashPatterns))
34 | if dashPhase.count == 0 {
35 | self.dashPhase = NodeProperty(provider: SingleValueProvider(Vector1D(0)))
36 | } else {
37 | self.dashPhase = NodeProperty(provider: KeyframeInterpolator(keyframes: dashPhase))
38 | }
39 | } else {
40 | self.dashPattern = NodeProperty(provider: SingleValueProvider([Vector1D]()))
41 | self.dashPhase = NodeProperty(provider: SingleValueProvider(Vector1D(0)))
42 | }
43 | self.keypathProperties = [
44 | "Opacity" : opacity,
45 | "Color" : color,
46 | "Stroke Width" : width,
47 | "Dashes" : dashPattern,
48 | "Dash Phase" : dashPhase
49 | ]
50 | self.properties = Array(keypathProperties.values)
51 | }
52 |
53 | let keypathName: String
54 | let keypathProperties: [String : AnyNodeProperty]
55 | let properties: [AnyNodeProperty]
56 |
57 | let opacity: NodeProperty
58 | let color: NodeProperty
59 | let width: NodeProperty
60 |
61 | let dashPattern: NodeProperty<[Vector1D]>
62 | let dashPhase: NodeProperty
63 |
64 | let lineCap: LineCap
65 | let lineJoin: LineJoin
66 | let miterLimit: CGFloat
67 |
68 | }
69 |
70 | // MARK: - Node
71 |
72 | /// Node that manages stroking a path
73 | final class StrokeNode: AnimatorNode, RenderNode {
74 |
75 | let strokeRender: StrokeRenderer
76 | var renderer: NodeOutput & Renderable {
77 | return strokeRender
78 | }
79 |
80 | let strokeProperties: StrokeNodeProperties
81 |
82 | init(parentNode: AnimatorNode?, stroke: Stroke) {
83 | self.strokeRender = StrokeRenderer(parent: parentNode?.outputNode)
84 | self.strokeProperties = StrokeNodeProperties(stroke: stroke)
85 | self.parentNode = parentNode
86 | }
87 |
88 | // MARK: Animator Node Protocol
89 |
90 | var propertyMap: NodePropertyMap & KeypathSearchable {
91 | return strokeProperties
92 | }
93 |
94 | let parentNode: AnimatorNode?
95 | var hasLocalUpdates: Bool = false
96 | var hasUpstreamUpdates: Bool = false
97 | var lastUpdateFrame: CGFloat? = nil
98 | var isEnabled: Bool = true {
99 | didSet {
100 | strokeRender.isEnabled = isEnabled
101 | }
102 | }
103 |
104 | func localUpdatesPermeateDownstream() -> Bool {
105 | return false
106 | }
107 |
108 | func rebuildOutputs(frame: CGFloat) {
109 | strokeRender.color = strokeProperties.color.value.cgColorValue
110 | strokeRender.opacity = strokeProperties.opacity.value.cgFloatValue * 0.01
111 | strokeRender.width = strokeProperties.width.value.cgFloatValue
112 | strokeRender.miterLimit = strokeProperties.miterLimit
113 | strokeRender.lineCap = strokeProperties.lineCap
114 | strokeRender.lineJoin = strokeProperties.lineJoin
115 |
116 | /// Get dash lengths
117 | let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue }
118 | if dashLengths.count > 0 {
119 | strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue
120 | strokeRender.dashLengths = dashLengths
121 | } else {
122 | strokeRender.dashLengths = nil
123 | strokeRender.dashPhase = nil
124 | }
125 | }
126 |
127 | }
128 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Protocols/PathNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PathNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/17/19.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol PathNode {
11 | var pathOutput: PathOutputNode { get }
12 | }
13 |
14 | extension PathNode where Self: AnimatorNode {
15 |
16 | var outputNode: NodeOutput {
17 | return pathOutput
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/Protocols/RenderNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RenderNode.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/17/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | import QuartzCore
11 |
12 | /// A protocol that defines a node that holds render instructions
13 | protocol RenderNode {
14 | var renderer: Renderable & NodeOutput { get }
15 | }
16 |
17 | /// A protocol that defines anything with render instructions
18 | protocol Renderable {
19 |
20 | /// The last frame in which this node was updated.
21 | var hasUpdate: Bool { get }
22 |
23 | func hasRenderUpdates(_ forFrame: CGFloat) -> Bool
24 |
25 | /**
26 | Determines if the renderer requires a custom context for drawing.
27 | If yes the shape layer will perform a custom drawing pass.
28 | If no the shape layer will be a standard CAShapeLayer
29 | */
30 | var shouldRenderInContext: Bool { get }
31 |
32 | /// Passes in the CAShapeLayer to update
33 | func updateShapeLayer(layer: CAShapeLayer)
34 |
35 | /// Asks the renderer what the renderable bounds is for the given box.
36 | func renderBoundsFor(_ boundingBox: CGRect) -> CGRect
37 |
38 | /// Renders the shape in a custom context
39 | func render(_ inContext: CGContext)
40 | }
41 |
42 | extension RenderNode where Self: AnimatorNode {
43 |
44 | var outputNode: NodeOutput {
45 | return renderer
46 | }
47 |
48 | }
49 |
50 | extension Renderable {
51 |
52 | func renderBoundsFor(_ boundingBox: CGRect) -> CGRect {
53 | /// Optional
54 | return boundingBox
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeContainerLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | /**
12 | The base layer that holds Shapes and Shape Renderers
13 | */
14 | class ShapeContainerLayer: CALayer {
15 |
16 | private(set) var renderLayers: [ShapeContainerLayer] = []
17 |
18 | override init() {
19 | super.init()
20 | self.actions = [
21 | "position" : NSNull(),
22 | "bounds" : NSNull(),
23 | "anchorPoint" : NSNull(),
24 | "transform" : NSNull(),
25 | "opacity" : NSNull(),
26 | "hidden" : NSNull(),
27 | ]
28 | }
29 |
30 | required init?(coder aDecoder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 |
34 | override init(layer: Any) {
35 | guard let layer = layer as? ShapeContainerLayer else {
36 | fatalError("init(layer:) wrong class.")
37 | }
38 | super.init(layer: layer)
39 | }
40 |
41 | var renderScale: CGFloat = 1 {
42 | didSet {
43 | updateRenderScale()
44 | }
45 | }
46 |
47 | func insertRenderLayer(_ layer: ShapeContainerLayer) {
48 | renderLayers.append(layer)
49 | insertSublayer(layer, at: 0)
50 | }
51 |
52 | func markRenderUpdates(forFrame: CGFloat) {
53 | if self.hasRenderUpdate(forFrame: forFrame) {
54 | self.rebuildContents(forFrame: forFrame)
55 | }
56 | guard self.isHidden == false else { return }
57 | renderLayers.forEach { $0.markRenderUpdates(forFrame: forFrame) }
58 | }
59 |
60 | func hasRenderUpdate(forFrame: CGFloat) -> Bool {
61 | return false
62 | }
63 |
64 | func rebuildContents(forFrame: CGFloat) {
65 | /// Override
66 | }
67 |
68 | func updateRenderScale() {
69 | self.contentsScale = self.renderScale
70 | renderLayers.forEach( { $0.renderScale = renderScale } )
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RenderLayer.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/18/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | /**
12 | The layer responsible for rendering shape objects
13 | */
14 | final class ShapeRenderLayer: ShapeContainerLayer {
15 |
16 | fileprivate(set) var renderer: Renderable & NodeOutput
17 |
18 | let shapeLayer: CAShapeLayer = CAShapeLayer()
19 |
20 | init(renderer: Renderable & NodeOutput) {
21 | self.renderer = renderer
22 | super.init()
23 | self.anchorPoint = .zero
24 | self.actions = [
25 | "position" : NSNull(),
26 | "bounds" : NSNull(),
27 | "anchorPoint" : NSNull(),
28 | "path" : NSNull(),
29 | "transform" : NSNull(),
30 | "opacity" : NSNull(),
31 | "hidden" : NSNull(),
32 | ]
33 | shapeLayer.actions = [
34 | "position" : NSNull(),
35 | "bounds" : NSNull(),
36 | "anchorPoint" : NSNull(),
37 | "path" : NSNull(),
38 | "fillColor" : NSNull(),
39 | "strokeColor" : NSNull(),
40 | "lineWidth" : NSNull(),
41 | "miterLimit" : NSNull(),
42 | "lineDashPhase" : NSNull(),
43 | "hidden" : NSNull(),
44 | ]
45 | addSublayer(shapeLayer)
46 | }
47 |
48 | override init(layer: Any) {
49 | guard let layer = layer as? ShapeRenderLayer else {
50 | fatalError("init(layer:) wrong class.")
51 | }
52 | self.renderer = layer.renderer
53 | super.init(layer: layer)
54 | }
55 |
56 | required init?(coder aDecoder: NSCoder) {
57 | fatalError("init(coder:) has not been implemented")
58 | }
59 |
60 | override func hasRenderUpdate(forFrame: CGFloat) -> Bool {
61 | self.isHidden = !renderer.isEnabled
62 | guard self.isHidden == false else { return false }
63 | return renderer.hasRenderUpdates(forFrame)
64 | }
65 |
66 | override func rebuildContents(forFrame: CGFloat) {
67 |
68 | if renderer.shouldRenderInContext {
69 | if let newPath = renderer.outputPath {
70 | self.bounds = renderer.renderBoundsFor(newPath.boundingBox)
71 | } else {
72 | self.bounds = .zero
73 | }
74 | self.position = bounds.origin
75 | self.setNeedsDisplay()
76 | } else {
77 | shapeLayer.path = renderer.outputPath
78 | renderer.updateShapeLayer(layer: shapeLayer)
79 | }
80 | }
81 |
82 | override func draw(in ctx: CGContext) {
83 | if let path = renderer.outputPath {
84 | if !path.isEmpty {
85 | ctx.addPath(path)
86 | }
87 | }
88 | renderer.render(ctx)
89 | }
90 |
91 | override func updateRenderScale() {
92 | super.updateRenderScale()
93 | shapeLayer.contentsScale = self.renderScale
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Debugging/AnimatorNodeDebugging.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimatorNodeDebugging.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/18/19.
6 | //
7 |
8 | import Foundation
9 |
10 | extension AnimatorNode {
11 |
12 | func printNodeTree() {
13 | parentNode?.printNodeTree()
14 | print(String(describing: type(of: self)))
15 |
16 | if let group = self as? GroupNode {
17 | print("* |Children")
18 | group.rootNode?.printNodeTree()
19 | print("*")
20 | } else {
21 | print("|")
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Extensions/CGFloatExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGFloatExtensions.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/14/19.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | extension CGFloat {
12 |
13 | func isInRangeOrEqual(_ from: CGFloat, _ to: CGFloat) -> Bool {
14 | return (from <= self && self <= to)
15 | }
16 |
17 | func isInRange(_ from: CGFloat, _ to: CGFloat) -> Bool {
18 | return (from < self && self < to)
19 | }
20 |
21 | var squared: CGFloat {
22 | return self * self
23 | }
24 |
25 | var cubed: CGFloat {
26 | return self * self * self
27 | }
28 |
29 | var cubicRoot: CGFloat {
30 | return CGFloat(pow(Double(self), 1.0 / 3.0))
31 | }
32 |
33 | fileprivate static func SolveQuadratic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat) -> CGFloat {
34 | var result = (-b + sqrt(b.squared - 4 * a * c)) / (2 * a);
35 | guard !result.isInRangeOrEqual(0, 1) else {
36 | return result
37 | }
38 |
39 | result = (-b - sqrt(b.squared - 4 * a * c)) / (2 * a);
40 | guard !result.isInRangeOrEqual(0, 1) else {
41 | return result
42 | }
43 |
44 | return -1;
45 | }
46 |
47 | fileprivate static func SolveCubic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat, _ d: CGFloat) -> CGFloat {
48 | if (a == 0) {
49 | return SolveQuadratic(b, c, d)
50 | }
51 | if (d == 0) {
52 | return 0
53 | }
54 | let a = a
55 | var b = b
56 | var c = c
57 | var d = d
58 | b /= a
59 | c /= a
60 | d /= a
61 | var q = (3.0 * c - b.squared) / 9.0
62 | let r = (-27.0 * d + b * (9.0 * c - 2.0 * b.squared)) / 54.0
63 | let disc = q.cubed + r.squared
64 | let term1 = b / 3.0
65 |
66 | if (disc > 0) {
67 | var s = r + sqrt(disc)
68 | s = (s < 0) ? -((-s).cubicRoot) : s.cubicRoot
69 | var t = r - sqrt(disc)
70 | t = (t < 0) ? -((-t).cubicRoot) : t.cubicRoot
71 |
72 | let result = -term1 + s + t;
73 | if result.isInRangeOrEqual(0, 1) {
74 | return result
75 | }
76 | } else if (disc == 0) {
77 | let r13 = (r < 0) ? -((-r).cubicRoot) : r.cubicRoot;
78 |
79 | var result = -term1 + 2.0 * r13;
80 | if result.isInRangeOrEqual(0, 1) {
81 | return result
82 | }
83 |
84 | result = -(r13 + term1);
85 | if result.isInRangeOrEqual(0, 1) {
86 | return result
87 | }
88 |
89 | } else {
90 | q = -q;
91 | var dum1 = q * q * q;
92 | dum1 = acos(r / sqrt(dum1));
93 | let r13 = 2.0 * sqrt(q);
94 |
95 | var result = -term1 + r13 * cos(dum1 / 3.0);
96 | if result.isInRangeOrEqual(0, 1) {
97 | return result
98 | }
99 | result = -term1 + r13 * cos((dum1 + 2.0 * .pi) / 3.0);
100 | if result.isInRangeOrEqual(0, 1) {
101 | return result
102 | }
103 | result = -term1 + r13 * cos((dum1 + 4.0 * .pi) / 3.0);
104 | if result.isInRangeOrEqual(0, 1) {
105 | return result
106 | }
107 | }
108 |
109 | return -1;
110 | }
111 |
112 | func cubicBezierInterpolate(_ P0: CGPoint, _ P1: CGPoint, _ P2: CGPoint, _ P3: CGPoint) -> CGFloat {
113 | var t: CGFloat
114 | if (self == P0.x) {
115 | // Handle corner cases explicitly to prevent rounding errors
116 | t = 0
117 | } else if (self == P3.x) {
118 | t = 1
119 | } else {
120 | // Calculate t
121 | let a = -P0.x + 3 * P1.x - 3 * P2.x + P3.x;
122 | let b = 3 * P0.x - 6 * P1.x + 3 * P2.x;
123 | let c = -3 * P0.x + 3 * P1.x;
124 | let d = P0.x - self;
125 | let tTemp = CGFloat.SolveCubic(a, b, c, d);
126 | if (tTemp == -1) {
127 | return -1;
128 | }
129 | t = tTemp
130 | }
131 |
132 | // Calculate y from t
133 | return (1 - t).cubed * P0.y + 3 * t * (1 - t).squared * P1.y + 3 * t.squared * (1 - t) * P2.y + t.cubed * P3.y;
134 | }
135 |
136 | func cubicBezier(_ t: CGFloat, _ c1: CGFloat, _ c2: CGFloat, _ end: CGFloat) -> CGFloat {
137 | let t_ = (1.0 - t)
138 | let tt_ = t_ * t_
139 | let ttt_ = t_ * t_ * t_
140 | let tt = t * t
141 | let ttt = t * t * t
142 |
143 | return self * ttt_
144 | + 3.0 * c1 * tt_ * t
145 | + 3.0 * c2 * t_ * tt
146 | + end * ttt;
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Extensions/StringExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringExtensions.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | extension String {
12 |
13 | func hexColorComponents() -> (red: CGFloat, green: CGFloat, blue: CGFloat) {
14 |
15 | var cString:String = trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
16 |
17 | if (cString.hasPrefix("#")) {
18 | cString.remove(at: cString.startIndex)
19 | }
20 |
21 | if ((cString.count) != 6) {
22 | return (red: 0, green: 0, blue: 0)
23 | }
24 |
25 | var rgbValue:UInt32 = 0
26 | Scanner(string: cString).scanHexInt32(&rgbValue)
27 |
28 | return (red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
29 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
30 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Helpers/AnimationContext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationContext.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/1/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | import QuartzCore
11 |
12 | /// A completion block for animations. `true` is passed in if the animation completed playing.
13 | public typealias LottieCompletionBlock = (Bool) -> Void
14 |
15 | struct AnimationContext {
16 |
17 | init(playFrom: CGFloat,
18 | playTo: CGFloat,
19 | closure: LottieCompletionBlock?) {
20 | self.playTo = playTo
21 | self.playFrom = playFrom
22 | self.closure = AnimationCompletionDelegate(completionBlock: closure)
23 | }
24 |
25 | var playFrom: CGFloat
26 | var playTo: CGFloat
27 | var closure: AnimationCompletionDelegate
28 |
29 | }
30 |
31 | enum AnimationContextState {
32 | case playing
33 | case cancelled
34 | case complete
35 | }
36 |
37 | class AnimationCompletionDelegate: NSObject, CAAnimationDelegate {
38 |
39 | init(completionBlock: LottieCompletionBlock?) {
40 | self.completionBlock = completionBlock
41 | super.init()
42 | }
43 |
44 | var animationLayer: AnimationContainer?
45 | var animationKey: String?
46 | var ignoreDelegate: Bool = false
47 | var animationState: AnimationContextState = .playing
48 |
49 | let completionBlock: LottieCompletionBlock?
50 |
51 | public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
52 | guard ignoreDelegate == false else { return }
53 | animationState = flag ? .complete : .cancelled
54 | if let animationLayer = animationLayer, let key = animationKey {
55 | animationLayer.removeAnimation(forKey: key)
56 | if flag {
57 | animationLayer.currentFrame = (anim as! CABasicAnimation).toValue as! CGFloat
58 | }
59 | }
60 | if let completionBlock = completionBlock {
61 | completionBlock(flag)
62 | }
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Interpolatable/Interpolatable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Interpolatable.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/14/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | protocol Interpolatable {
12 |
13 | func interpolateTo(_ to: Self,
14 | amount: CGFloat,
15 | spatialOutTangent: CGPoint?,
16 | spatialInTangent: CGPoint?) -> Self
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Interpolatable/KeyframeExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyframeExtensions.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/14/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | extension Keyframe {
12 |
13 | /// Interpolates the keyTime into a value from 0-1
14 | func interpolatedProgress(_ to: Keyframe, keyTime: CGFloat) -> CGFloat {
15 | let startTime = time
16 | let endTime = to.time
17 | if keyTime <= startTime {
18 | return 0
19 | }
20 | if endTime <= keyTime {
21 | return 1
22 | }
23 |
24 | if isHold {
25 | return 0
26 | }
27 |
28 | let outTanPoint = outTangent?.pointValue ?? .zero
29 | let inTanPoint = to.inTangent?.pointValue ?? CGPoint(x: 1, y: 1)
30 | var progress: CGFloat = keyTime.remap(fromLow: startTime, fromHigh: endTime, toLow: 0, toHigh: 1)
31 | if !outTanPoint.isZero || !inTanPoint.equalTo(CGPoint(x: 1, y: 1)) {
32 | /// Cubic interpolation
33 | progress = progress.cubicBezierInterpolate(.zero, outTanPoint, inTanPoint, CGPoint(x: 1, y: 1))
34 | }
35 | return progress
36 | }
37 |
38 | /// Interpolates the keyframes' by a progress from 0-1
39 | func interpolate(_ to: Keyframe, progress: CGFloat) -> T {
40 | return value.interpolateTo(to.value, amount: progress, spatialOutTangent: spatialOutTangent?.pointValue, spatialInTangent: to.spatialInTangent?.pointValue)
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Primitives/ColorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Color.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/14/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | extension Color: Codable {
12 |
13 | public init(from decoder: Decoder) throws {
14 | var container = try decoder.unkeyedContainer()
15 |
16 | var r1: Double
17 | if !container.isAtEnd {
18 | r1 = try container.decode(Double.self)
19 | } else {
20 | r1 = 0
21 | }
22 |
23 | var g1: Double
24 | if !container.isAtEnd {
25 | g1 = try container.decode(Double.self)
26 | } else {
27 | g1 = 0
28 | }
29 |
30 | var b1: Double
31 | if !container.isAtEnd {
32 | b1 = try container.decode(Double.self)
33 | } else {
34 | b1 = 0
35 | }
36 |
37 | var a1: Double
38 | if !container.isAtEnd {
39 | a1 = try container.decode(Double.self)
40 | } else {
41 | a1 = 1
42 | }
43 | if r1 > 1, g1 > 1, b1 > 1, a1 > 1 {
44 | r1 = r1 / 255
45 | g1 = g1 / 255
46 | b1 = b1 / 255
47 | a1 = a1 / 255
48 | }
49 | self.r = r1
50 | self.g = g1
51 | self.b = b1
52 | self.a = a1
53 | }
54 |
55 | public func encode(to encoder: Encoder) throws {
56 | var container = encoder.unkeyedContainer()
57 | try container.encode(r)
58 | try container.encode(g)
59 | try container.encode(b)
60 | try container.encode(a)
61 | }
62 |
63 | }
64 |
65 | extension Color {
66 |
67 | static var clearColor: CGColor {
68 | return CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0, 0, 0, 0])!
69 | }
70 |
71 | var cgColorValue: CGColor {
72 | // TODO: Fix color spaces
73 | let colorspace = CGColorSpaceCreateDeviceRGB()
74 | return CGColor(colorSpace: colorspace, components: [CGFloat(r), CGFloat(g), CGFloat(b), CGFloat(a)]) ?? Color.clearColor
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Private/Utility/Primitives/PathElement.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PathElement.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/11/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /**
12 | A path section, containing one point and its length to the previous point.
13 |
14 | The relationship between this path element and the previous is implicit.
15 | Ideally a path section would be defined by two vertices and a length.
16 | We don't do this however, as it would effectively double the memory footprint
17 | of path data.
18 |
19 | */
20 | struct PathElement {
21 | /// The absolute Length of the path element.
22 | let length: CGFloat
23 |
24 | /// The vertex of the element
25 | let vertex: CurveVertex
26 |
27 | /// Returns a new path element define the span from the receiver to the new vertex.
28 | func pathElementTo(_ toVertex: CurveVertex) -> PathElement {
29 | return PathElement(length: vertex.distanceTo(toVertex), vertex: toVertex)
30 | }
31 |
32 | /// Initializes a new path with length of 0
33 | init(vertex: CurveVertex) {
34 | self.length = 0
35 | self.vertex = vertex
36 | }
37 |
38 | /// Initializes a new path with length
39 | fileprivate init(length: CGFloat, vertex: CurveVertex) {
40 | self.length = length
41 | self.vertex = vertex
42 | }
43 |
44 | func updateVertex(newVertex: CurveVertex) -> PathElement {
45 | return PathElement(length: length, vertex: newVertex)
46 | }
47 |
48 | /// Splits an element span defined by the receiver and fromElement to a position 0-1
49 | func splitElementAtPosition(fromElement: PathElement, atLength: CGFloat) ->
50 | (leftSpan: (start: PathElement, end: PathElement), rightSpan: (start: PathElement, end: PathElement)) {
51 | /// Trim the span. Start and trim go into the first, trim and end go into second.
52 | let trimResults = fromElement.vertex.trimCurve(toVertex: vertex, atLength: atLength, curveLength: length, maxSamples: 3)
53 |
54 | /// Create the elements for the break
55 | let spanAStart = PathElement(length: fromElement.length,
56 | vertex: CurveVertex(point: fromElement.vertex.point,
57 | inTangent: fromElement.vertex.inTangent,
58 | outTangent: trimResults.start.outTangent))
59 | /// Recalculating the length here is a waste as the trimCurve function also accurately calculates this length.
60 | let spanAEnd = spanAStart.pathElementTo(trimResults.trimPoint)
61 |
62 | let spanBStart = PathElement(vertex: trimResults.trimPoint)
63 | let spanBEnd = spanBStart.pathElementTo(trimResults.end)
64 | return (leftSpan: (start: spanAStart, end: spanAEnd),
65 | rightSpan: (start: spanBStart, end: spanBEnd))
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/Animation/AnimationViewInitializers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationViewInitializers.swift
3 | // lottie-swift-iOS
4 | //
5 | // Created by Brandon Withrow on 2/6/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension AnimationView {
11 |
12 | /**
13 | Loads a Lottie animation from a JSON file in the supplied bundle.
14 |
15 | - Parameter name: The string name of the lottie animation with no file
16 | extension provided.
17 | - Parameter bundle: The bundle in which the animation is located.
18 | Defaults to the Main bundle.
19 | - Parameter imageProvider: An image provider for the animation's image data.
20 | If none is supplied Lottie will search in the supplied bundle for images.
21 | */
22 | convenience init(name: String,
23 | bundle: Bundle = Bundle.main,
24 | imageProvider: AnimationImageProvider? = nil,
25 | animationCache: AnimationCacheProvider? = LRUAnimationCache.sharedCache) {
26 | let animation = Animation.named(name, bundle: bundle, subdirectory: nil, animationCache: animationCache)
27 | let provider = imageProvider ?? BundleImageProvider(bundle: bundle, searchPath: nil)
28 | self.init(animation: animation, imageProvider: provider)
29 | }
30 |
31 | /**
32 | Loads a Lottie animation from a JSON file in a specific path on disk.
33 |
34 | - Parameter name: The absolute path of the Lottie Animation.
35 | - Parameter imageProvider: An image provider for the animation's image data.
36 | If none is supplied Lottie will search in the supplied filepath for images.
37 | */
38 | convenience init(filePath: String,
39 | imageProvider: AnimationImageProvider? = nil,
40 | animationCache: AnimationCacheProvider? = LRUAnimationCache.sharedCache) {
41 | let animation = Animation.filepath(filePath, animationCache: animationCache)
42 | let provider = imageProvider ?? FilepathImageProvider(filepath: URL(fileURLWithPath: filePath).deletingLastPathComponent().path)
43 | self.init(animation: animation, imageProvider: provider)
44 | }
45 |
46 | /**
47 | Loads a Lottie animation asynchronously from the URL
48 |
49 | - Parameter url: The url to load the animation from.
50 | - Parameter imageProvider: An image provider for the animation's image data.
51 | If none is supplied Lottie will search in the main bundle for images.
52 | - Parameter closure: A closure to be called when the animation has loaded.
53 | */
54 | convenience init(url: URL,
55 | imageProvider: AnimationImageProvider? = nil,
56 | closure: @escaping AnimationView.DownloadClosure,
57 | animationCache: AnimationCacheProvider? = LRUAnimationCache.sharedCache) {
58 |
59 | if let animationCache = animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
60 | self.init(animation: animation, imageProvider: imageProvider)
61 | closure(nil)
62 | } else {
63 |
64 | self.init(animation: nil, imageProvider: imageProvider)
65 |
66 | Animation.loadedFrom(url: url, closure: { (animation) in
67 | if let animation = animation {
68 | self.animation = animation
69 | closure(nil)
70 | } else {
71 | closure(LottieDownloadError.downloadFailed)
72 | }
73 | }, animationCache: animationCache)
74 | }
75 | }
76 |
77 | typealias DownloadClosure = (Error?) -> Void
78 |
79 | }
80 |
81 | enum LottieDownloadError: Error {
82 | case downloadFailed
83 | }
84 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/AnimationCache/AnimationCacheProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationCacheProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/5/19.
6 | //
7 |
8 | import Foundation
9 | /**
10 | `AnimationCacheProvider` is a protocol that describes an Animation Cache.
11 | Animation Cache is used when loading `Animation` models. Using an Animation Cache
12 | can increase performance when loading an animation multiple times.
13 |
14 | Lottie comes with a prebuilt LRU Animation Cache.
15 | */
16 | public protocol AnimationCacheProvider {
17 |
18 | func animation(forKey: String) -> Animation?
19 |
20 | func setAnimation(_ animation: Animation, forKey: String)
21 |
22 | func clearCache()
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/AnimationCache/LRUAnimationCache.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LRUAnimationCache.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/5/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /**
11 | An Animation Cache that will store animations up to `cacheSize`.
12 |
13 | Once `cacheSize` is reached, the least recently used animation will be ejected.
14 | The default size of the cache is 100.
15 | */
16 | public class LRUAnimationCache: AnimationCacheProvider {
17 |
18 | public init() { }
19 |
20 | /// Clears the Cache.
21 | public func clearCache() {
22 | cacheMap.removeAll()
23 | lruList.removeAll()
24 | }
25 |
26 | /// The global shared Cache.
27 | public static let sharedCache = LRUAnimationCache()
28 |
29 | /// The size of the cache.
30 | public var cacheSize: Int = 100
31 |
32 | public func animation(forKey: String) -> Animation? {
33 | guard let animation = cacheMap[forKey] else {
34 | return nil
35 | }
36 | if let index = lruList.firstIndex(of: forKey) {
37 | lruList.remove(at: index)
38 | lruList.append(forKey)
39 | }
40 | return animation
41 | }
42 |
43 | public func setAnimation(_ animation: Animation, forKey: String) {
44 | cacheMap[forKey] = animation
45 | lruList.append(forKey)
46 | if lruList.count > cacheSize {
47 | let removed = lruList.remove(at: 0)
48 | if removed != forKey {
49 | cacheMap[removed] = nil
50 | }
51 | }
52 | }
53 |
54 | fileprivate var cacheMap: [String : Animation] = [:]
55 | fileprivate var lruList: [String] = []
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/AnimationKeypath.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationKeypath.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 |
10 | /**
11 | `AnimationKeypath` is an object that describes a keypath search for nodes in the
12 | animation JSON. `AnimationKeypath` matches views and properties inside of `AnimationView`
13 | to their backing `Animation` model by name.
14 |
15 | A keypath can be used to set properties on an existing animation, or can be validated
16 | with an existing `Animation`.
17 |
18 | `AnimationKeypath` can describe a specific object, or can use wildcards for fuzzy matching
19 | of objects. Acceptable wildcards are either "*" (star) or "**" (double star).
20 | Single star will search a single depth for the next object.
21 | Double star will search any depth.
22 |
23 | Read More at https://airbnb.io/lottie/#/ios?id=dynamic-animation-properties
24 |
25 | EG:
26 | @"Layer.Shape Group.Stroke 1.Color"
27 | Represents a specific color node on a specific stroke.
28 |
29 | @"**.Stroke 1.Color"
30 | Represents the color node for every Stroke named "Stroke 1" in the animation.
31 | */
32 | public struct AnimationKeypath {
33 |
34 | /// Creates a keypath from a dot separated string. The string is separated by "."
35 | public init(keypath: String) {
36 | self.keys = keypath.components(separatedBy: ".")
37 | }
38 |
39 | /// Creates a keypath from a list of strings.
40 | public init(keys: [String]) {
41 | self.keys = keys
42 | }
43 |
44 | let keys: [String]
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/AnyValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnyValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/30/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /**
12 | `AnyValueProvider` is a protocol that return animation data for a property at a
13 | given time. Every fame an `AnimationView` queries all of its properties and asks
14 | if their ValueProvider has an update. If it does the AnimationView will read the
15 | property and update that portion of the animation.
16 |
17 | Value Providers can be used to dynamically set animation properties at run time.
18 | */
19 | public protocol AnyValueProvider {
20 |
21 | /// The Type of the value provider
22 | var valueType: Any.Type { get }
23 |
24 | /// Asks the provider if it has an update for the given frame.
25 | func hasUpdate(frame: AnimationFrameTime) -> Bool
26 |
27 | /// Asks the provider to update the container with its value for the frame.
28 | func value(frame: AnimationFrameTime) -> Any
29 | }
30 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ColorValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A `ValueProvider` that returns a CGColor Value
12 | public final class ColorValueProvider: AnyValueProvider {
13 |
14 | /// Returns a Color for a CGColor(Frame Time)
15 | public typealias ColorValueBlock = (CGFloat) -> Color
16 |
17 | /// The color value of the provider.
18 | public var color: Color {
19 | didSet {
20 | hasUpdate = true
21 | }
22 | }
23 |
24 | /// Initializes with a block provider
25 | public init(block: @escaping ColorValueBlock) {
26 | self.block = block
27 | self.color = Color(r: 0, g: 0, b: 0, a: 1)
28 | }
29 |
30 | /// Initializes with a single color.
31 | public init(_ color: Color) {
32 | self.color = color
33 | self.block = nil
34 | hasUpdate = true
35 | }
36 |
37 | // MARK: ValueProvider Protocol
38 |
39 | public var valueType: Any.Type {
40 | return Color.self
41 | }
42 |
43 | public func hasUpdate(frame: CGFloat) -> Bool {
44 | if block != nil {
45 | return true
46 | }
47 | return hasUpdate
48 | }
49 |
50 | public func value(frame: CGFloat) -> Any {
51 | hasUpdate = false
52 | let newColor: Color
53 | if let block = block {
54 | newColor = block(frame)
55 | } else {
56 | newColor = color
57 | }
58 | return newColor
59 | }
60 |
61 | // MARK: Private
62 |
63 | private var hasUpdate: Bool = true
64 |
65 | private var block: ColorValueBlock?
66 | }
67 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DoubleValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A `ValueProvider` that returns a CGFloat Value
12 | public final class FloatValueProvider: AnyValueProvider {
13 |
14 | /// Returns a CGFloat for a CGFloat(Frame Time)
15 | public typealias CGFloatValueBlock = (CGFloat) -> CGFloat
16 |
17 | public var float: CGFloat {
18 | didSet {
19 | hasUpdate = true
20 | }
21 | }
22 |
23 | /// Initializes with a block provider
24 | public init(block: @escaping CGFloatValueBlock) {
25 | self.block = block
26 | self.float = 0
27 | }
28 |
29 | /// Initializes with a single float.
30 | public init(_ float: CGFloat) {
31 | self.float = float
32 | self.block = nil
33 | hasUpdate = true
34 | }
35 |
36 | // MARK: ValueProvider Protocol
37 |
38 | public var valueType: Any.Type {
39 | return Vector1D.self
40 | }
41 |
42 | public func hasUpdate(frame: CGFloat) -> Bool {
43 | if block != nil {
44 | return true
45 | }
46 | return hasUpdate
47 | }
48 |
49 | public func value(frame: CGFloat) -> Any {
50 | hasUpdate = false
51 | let newCGFloat: CGFloat
52 | if let block = block {
53 | newCGFloat = block(frame)
54 | } else {
55 | newCGFloat = float
56 | }
57 | return Vector1D(Double(newCGFloat))
58 | }
59 |
60 | // MARK: Private
61 |
62 | private var hasUpdate: Bool = true
63 |
64 | private var block: CGFloatValueBlock?
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GradientValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Enrique Bermúdez on 10/27/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A `ValueProvider` that returns a Gradient Color Value.
12 | public final class GradientValueProvider: AnyValueProvider {
13 |
14 | /// Returns a [Color] for a CGFloat(Frame Time).
15 | public typealias ColorsValueBlock = (CGFloat) -> [Color]
16 | /// Returns a [Double](Color locations) for a CGFloat(Frame Time).
17 | public typealias ColorLocationsBlock = (CGFloat) -> [Double]
18 |
19 | /// The colors values of the provider.
20 | public var colors: [Color] {
21 | didSet {
22 | updateValueArray()
23 | hasUpdate = true
24 | }
25 | }
26 |
27 | /// The color location values of the provider.
28 | public var locations: [Double] {
29 | didSet {
30 | updateValueArray()
31 | hasUpdate = true
32 | }
33 | }
34 |
35 | /// Initializes with a block provider.
36 | public init(block: @escaping ColorsValueBlock,
37 | locations: ColorLocationsBlock? = nil) {
38 | self.block = block
39 | self.locationsBlock = locations
40 | self.colors = []
41 | self.locations = []
42 | }
43 |
44 | /// Initializes with an array of colors.
45 | public init(_ colors: [Color],
46 | locations: [Double] = []) {
47 | self.colors = colors
48 | self.locations = locations
49 | updateValueArray()
50 | hasUpdate = true
51 | }
52 |
53 | // MARK: ValueProvider Protocol
54 |
55 | public var valueType: Any.Type {
56 | return [Double].self
57 | }
58 |
59 | public func hasUpdate(frame: CGFloat) -> Bool {
60 | if block != nil || locationsBlock != nil {
61 | return true
62 | }
63 | return hasUpdate
64 | }
65 |
66 | public func value(frame: CGFloat) -> Any {
67 | hasUpdate = false
68 |
69 | if let block = block {
70 | let newColors = block(frame)
71 | let newLocations = locationsBlock?(frame) ?? []
72 | value = value(from: newColors, locations: newLocations)
73 | }
74 |
75 | return value
76 | }
77 |
78 | // MARK: Private
79 |
80 | private func value(from colors: [Color], locations: [Double]) -> [Double] {
81 |
82 | var colorValues = [Double]()
83 | var alphaValues = [Double]()
84 | var shouldAddAlphaValues = false
85 |
86 | for i in 0.. i ? locations[i] :
91 | (Double(i) / Double(colors.count - 1))
92 |
93 | colorValues.append(location)
94 | colorValues.append(colors[i].r)
95 | colorValues.append(colors[i].g)
96 | colorValues.append(colors[i].b)
97 |
98 | alphaValues.append(location)
99 | alphaValues.append(colors[i].a)
100 | }
101 |
102 | return colorValues + (shouldAddAlphaValues ? alphaValues : [])
103 | }
104 |
105 | private func updateValueArray() {
106 | value = value(from: colors, locations: locations)
107 | }
108 |
109 | private var hasUpdate: Bool = true
110 |
111 | private var block: ColorsValueBlock?
112 | private var locationsBlock: ColorLocationsBlock?
113 | private var value: [Double] = []
114 | }
115 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/ValueProviders/PointValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PointValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | /// A `ValueProvider` that returns a CGPoint Value
11 | public final class PointValueProvider: AnyValueProvider {
12 |
13 | /// Returns a CGPoint for a CGFloat(Frame Time)
14 | public typealias PointValueBlock = (CGFloat) -> CGPoint
15 |
16 | public var point: CGPoint {
17 | didSet {
18 | hasUpdate = true
19 | }
20 | }
21 |
22 | /// Initializes with a block provider
23 | public init(block: @escaping PointValueBlock) {
24 | self.block = block
25 | self.point = .zero
26 | }
27 |
28 | /// Initializes with a single point.
29 | public init(_ point: CGPoint) {
30 | self.point = point
31 | self.block = nil
32 | hasUpdate = true
33 | }
34 |
35 | // MARK: ValueProvider Protocol
36 |
37 | public var valueType: Any.Type {
38 | return Vector3D.self
39 | }
40 |
41 | public func hasUpdate(frame: CGFloat) -> Bool {
42 | if block != nil {
43 | return true
44 | }
45 | return hasUpdate
46 | }
47 |
48 | public func value(frame: CGFloat) -> Any {
49 | hasUpdate = false
50 | let newPoint: CGPoint
51 | if let block = block {
52 | newPoint = block(frame)
53 | } else {
54 | newPoint = point
55 | }
56 | return newPoint.vector3dValue
57 | }
58 |
59 | // MARK: Private
60 |
61 | private var hasUpdate: Bool = true
62 |
63 | private var block: PointValueBlock?
64 | }
65 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SizeValueProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// A `ValueProvider` that returns a CGSize Value
12 | public final class SizeValueProvider: AnyValueProvider {
13 |
14 | /// Returns a CGSize for a CGFloat(Frame Time)
15 | public typealias SizeValueBlock = (CGFloat) -> CGSize
16 |
17 | public var size: CGSize {
18 | didSet {
19 | hasUpdate = true
20 | }
21 | }
22 |
23 | /// Initializes with a block provider
24 | public init(block: @escaping SizeValueBlock) {
25 | self.block = block
26 | self.size = .zero
27 | }
28 |
29 | /// Initializes with a single size.
30 | public init(_ size: CGSize) {
31 | self.size = size
32 | self.block = nil
33 | hasUpdate = true
34 | }
35 |
36 | // MARK: ValueProvider Protocol
37 |
38 | public var valueType: Any.Type {
39 | return Vector3D.self
40 | }
41 |
42 | public func hasUpdate(frame: CGFloat) -> Bool {
43 | if block != nil {
44 | return true
45 | }
46 | return hasUpdate
47 | }
48 |
49 | public func value(frame: CGFloat) -> Any {
50 | hasUpdate = false
51 | let newSize: CGSize
52 | if let block = block {
53 | newSize = block(frame)
54 | } else {
55 | newSize = size
56 | }
57 | return newSize.vector3dValue
58 | }
59 |
60 | // MARK: Private
61 |
62 | private var hasUpdate: Bool = true
63 |
64 | private var block: SizeValueBlock?
65 | }
66 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/ImageProvider/AnimationImageProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieImageProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /**
12 | Image provider is a protocol that is used to supply images to `AnimationView`.
13 |
14 | Some animations require a reference to an image. The image provider loads and
15 | provides those images to the `AnimationView`. Lottie includes a couple of
16 | prebuilt Image Providers that supply images from a Bundle, or from a FilePath.
17 |
18 | Additionally custom Image Providers can be made to load images from a URL,
19 | or to Cache images.
20 | */
21 | public protocol AnimationImageProvider {
22 | func imageForAsset(asset: ImageAsset) -> CGImage?
23 | }
24 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/Primitives/AnimationTime.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationTime.swift
3 | // lottie-swift-iOS
4 | //
5 | // Created by Brandon Withrow on 2/6/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 |
11 | /// Defines animation time in Frames (Seconds * Framerate).
12 | public typealias AnimationFrameTime = CGFloat
13 |
14 | /// Defines animation time by a progress from 0 (beginning of the animation) to 1 (end of the animation)
15 | public typealias AnimationProgressTime = CGFloat
16 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/Primitives/Color.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Color.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public enum ColorFormatDenominator {
11 | case One
12 | case OneHundred
13 | case TwoFiftyFive
14 |
15 | var value: Double {
16 | switch self {
17 | case .One:
18 | return 1.0
19 | case .OneHundred:
20 | return 100.0
21 | case .TwoFiftyFive:
22 | return 255.0
23 | }
24 | }
25 | }
26 |
27 | public struct Color {
28 |
29 | public var r: Double
30 | public var g: Double
31 | public var b: Double
32 | public var a: Double
33 |
34 | public init(r: Double, g: Double, b: Double, a: Double, denominator: ColorFormatDenominator = .One) {
35 | self.r = r / denominator.value
36 | self.g = g / denominator.value
37 | self.b = b / denominator.value
38 | self.a = a / denominator.value
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/Primitives/Vectors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Vectors.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct Vector1D {
11 |
12 | public init(_ value: Double) {
13 | self.value = value
14 | }
15 |
16 | let value: Double
17 |
18 | }
19 |
20 |
21 | /**
22 | A three dimensional vector.
23 | These vectors are encoded and decoded from [Double]
24 | */
25 | public struct Vector3D {
26 |
27 | var x: Double
28 | var y: Double
29 | var z: Double
30 |
31 | public init(x: Double, y: Double, z: Double) {
32 | self.x = x
33 | self.y = y
34 | self.z = z
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/TextProvider/AnimationTextProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationImageProvider.swift
3 | // Lottie_iOS
4 | //
5 | // Created by Alexandr Goncharov on 07/06/2019.
6 | //
7 |
8 | import Foundation
9 |
10 | /**
11 | Text provider is a protocol that is used to supply text to `AnimationView`.
12 | */
13 | public protocol AnimationTextProvider: AnyObject {
14 | func textFor(keypathName: String, sourceText: String) -> String
15 | }
16 |
17 | /// Text provider that simply map values from dictionary
18 | public final class DictionaryTextProvider: AnimationTextProvider {
19 |
20 | public init(_ values: [String: String]) {
21 | self.values = values
22 | }
23 |
24 | let values: [String: String]
25 |
26 | public func textFor(keypathName: String, sourceText: String) -> String {
27 | return values[keypathName] ?? sourceText
28 | }
29 | }
30 |
31 | /// Default text provider. Uses text in the animation file
32 | public final class DefaultTextProvider: AnimationTextProvider {
33 | public func textFor(keypathName: String, sourceText: String) -> String {
34 | return sourceText
35 | }
36 |
37 | public init() {}
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/AnimatedButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimatedButton.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 | import UIKit
11 | /**
12 | An interactive button that plays an animation when pressed.
13 | */
14 | final public class AnimatedButton: AnimatedControl {
15 |
16 | /// Sets the play range for the given UIControlEvent.
17 | public func setPlayRange(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, event: UIControl.Event) {
18 | rangesForEvents[event.rawValue] = (from: fromProgress, to: toProgress)
19 | }
20 |
21 | /// Sets the play range for the given UIControlEvent.
22 | public func setPlayRange(fromMarker fromName: String, toMarker toName: String, event: UIControl.Event) {
23 | if let start = animationView.progressTime(forMarker: fromName),
24 | let end = animationView.progressTime(forMarker: toName) {
25 | rangesForEvents[event.rawValue] = (from: start, to: end)
26 | }
27 | }
28 |
29 | public override init(animation: Animation) {
30 | super.init(animation: animation)
31 | self.accessibilityTraits = UIAccessibilityTraits.button
32 | }
33 |
34 | public override init() {
35 | super.init()
36 | self.accessibilityTraits = UIAccessibilityTraits.button
37 | }
38 |
39 | fileprivate var rangesForEvents: [UInt : (from: CGFloat, to: CGFloat)] = [UIControl.Event.touchUpInside.rawValue : (from: 0, to: 1)]
40 |
41 | required public init?(coder aDecoder: NSCoder) {
42 | super.init(coder: aDecoder)
43 | }
44 |
45 | public override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
46 | let _ = super.beginTracking(touch, with: event)
47 | let touchEvent = UIControl.Event.touchDown
48 | if let playrange = rangesForEvents[touchEvent.rawValue] {
49 | animationView.play(fromProgress: playrange.from, toProgress: playrange.to, loopMode: LottieLoopMode.playOnce)
50 | }
51 | return true
52 | }
53 |
54 | public override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
55 | super.endTracking(touch, with: event)
56 | let touchEvent: UIControl.Event
57 | if let touch = touch, bounds.contains(touch.location(in: self)) {
58 | touchEvent = UIControl.Event.touchUpInside
59 | } else {
60 | touchEvent = UIControl.Event.touchUpOutside
61 | }
62 |
63 | if let playrange = rangesForEvents[touchEvent.rawValue] {
64 | animationView.play(fromProgress: playrange.from, toProgress: playrange.to, loopMode: LottieLoopMode.playOnce)
65 | }
66 | }
67 | }
68 | #endif
69 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/AnimationSubview.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationSubview.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 | import UIKit
11 |
12 | /// A view that can be added to a keypath of an AnimationView
13 | public final class AnimationSubview: UIView {
14 |
15 | var viewLayer: CALayer? {
16 | return layer
17 | }
18 |
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/BundleImageProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieBundleImageProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 1/25/19.
6 | //
7 |
8 | import Foundation
9 | import CoreGraphics
10 | #if os(iOS) || os(tvOS) || os(watchOS)
11 | import UIKit
12 |
13 | /**
14 | An `AnimationImageProvider` that provides images by name from a specific bundle.
15 | The BundleImageProvider is initialized with a bundle and an optional searchPath.
16 | */
17 | public class BundleImageProvider: AnimationImageProvider {
18 |
19 | let bundle: Bundle
20 | let searchPath: String?
21 |
22 | /**
23 | Initializes an image provider with a bundle and an optional subpath.
24 |
25 | Provides images for an animation from a bundle. Additionally the provider can
26 | search a specific subpath for the images.
27 |
28 | - Parameter bundle: The bundle containing images for the provider.
29 | - Parameter searchPath: The subpath is a path within the bundle to search for image assets.
30 |
31 | */
32 | public init(bundle: Bundle, searchPath: String?) {
33 | self.bundle = bundle
34 | self.searchPath = searchPath
35 | }
36 |
37 | public func imageForAsset(asset: ImageAsset) -> CGImage? {
38 |
39 | if asset.name.hasPrefix("data:"),
40 | let url = URL(string: asset.name),
41 | let data = try? Data(contentsOf: url),
42 | let image = UIImage(data: data) {
43 | return image.cgImage
44 | }
45 |
46 | let imagePath: String?
47 | /// Try to find the image in the bundle.
48 | if let searchPath = searchPath {
49 | /// Search in the provided search path for the image
50 | var directoryPath = URL(fileURLWithPath: searchPath)
51 | directoryPath.appendPathComponent(asset.directory)
52 |
53 | if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: directoryPath.path) {
54 | /// First search for the image in the asset provided sub directory.
55 | imagePath = path
56 | } else if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: searchPath) {
57 | /// Try finding the image in the search path.
58 | imagePath = path
59 | } else {
60 | imagePath = bundle.path(forResource: asset.name, ofType: nil)
61 | }
62 | } else {
63 | if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: asset.directory) {
64 | /// First search for the image in the asset provided sub directory.
65 | imagePath = path
66 | } else {
67 | /// First search for the image in bundle.
68 | imagePath = bundle.path(forResource: asset.name, ofType: nil)
69 | }
70 | }
71 |
72 | guard let foundPath = imagePath, let image = UIImage(contentsOfFile: foundPath) else {
73 | /// No image found.
74 | return nil
75 | }
76 | return image.cgImage
77 | }
78 |
79 | }
80 | #endif
81 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CompatibleAnimationKeypath.swift
3 | // Lottie_iOS
4 | //
5 | // Created by Tyler Hedrick on 3/6/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 |
11 | /// An Objective-C compatible wrapper around Lottie's AnimationKeypath
12 | @objc
13 | public final class CompatibleAnimationKeypath: NSObject {
14 |
15 | /// Creates a keypath from a dot separated string. The string is separated by "."
16 | @objc
17 | public init(keypath: String) {
18 | animationKeypath = AnimationKeypath(keypath: keypath)
19 | }
20 |
21 | /// Creates a keypath from a list of strings.
22 | @objc
23 | public init(keys: [String]) {
24 | animationKeypath = AnimationKeypath(keys: keys)
25 | }
26 |
27 | public let animationKeypath: AnimationKeypath
28 | }
29 | #endif
30 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/FilepathImageProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilepathImageProvider.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/1/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 | import UIKit
11 |
12 | /**
13 | Provides an image for a lottie animation from a provided Bundle.
14 | */
15 | public class FilepathImageProvider: AnimationImageProvider {
16 |
17 | let filepath: URL
18 |
19 | /**
20 | Initializes an image provider with a specific filepath.
21 |
22 | - Parameter filepath: The absolute filepath containing the images.
23 |
24 | */
25 | public init(filepath: String) {
26 | self.filepath = URL(fileURLWithPath: filepath)
27 | }
28 |
29 | public init(filepath: URL) {
30 | self.filepath = filepath
31 | }
32 |
33 | public func imageForAsset(asset: ImageAsset) -> CGImage? {
34 |
35 | if asset.name.hasPrefix("data:"),
36 | let url = URL(string: asset.name),
37 | let data = try? Data(contentsOf: url),
38 | let image = UIImage(data: data) {
39 | return image.cgImage
40 | }
41 |
42 | let directPath = filepath.appendingPathComponent(asset.name).path
43 | if FileManager.default.fileExists(atPath: directPath) {
44 | return UIImage(contentsOfFile: directPath)?.cgImage
45 | }
46 |
47 | let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path
48 | if FileManager.default.fileExists(atPath: pathWithDirectory) {
49 | return UIImage(contentsOfFile: pathWithDirectory)?.cgImage
50 | }
51 |
52 | return nil
53 | }
54 |
55 | }
56 | #endif
57 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/LottieView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LottieView.swift
3 | // lottie-swift-iOS
4 | //
5 | // Created by Brandon Withrow on 2/6/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 | import UIKit
11 |
12 | //public typealias LottieView = UIView
13 |
14 | open class LottieView: UIView {
15 |
16 | var viewLayer: CALayer? {
17 | return layer
18 | }
19 |
20 | func layoutAnimation() {
21 |
22 | }
23 |
24 | func animationMovedToWindow() {
25 |
26 | }
27 |
28 | open override func didMoveToWindow() {
29 | super.didMoveToWindow()
30 | animationMovedToWindow()
31 | }
32 |
33 | var screenScale: CGFloat {
34 | return UIScreen.main.scale
35 | }
36 |
37 | func commonInit() {
38 | contentMode = .scaleAspectFit
39 | clipsToBounds = true
40 | NotificationCenter.default.addObserver(self, selector: #selector(animationWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
41 | NotificationCenter.default.addObserver(self, selector: #selector(animationWillMoveToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
42 | }
43 |
44 | open override var contentMode: UIView.ContentMode {
45 | didSet {
46 | setNeedsLayout()
47 | }
48 | }
49 |
50 | open override func layoutSubviews() {
51 | super.layoutSubviews()
52 | self.layoutAnimation()
53 | }
54 |
55 | @objc func animationWillMoveToBackground() {
56 | }
57 |
58 | @objc func animationWillEnterForeground() {
59 | }
60 |
61 | }
62 | #endif
63 |
--------------------------------------------------------------------------------
/Pods/lottie-ios/lottie-swift/src/Public/iOS/UIColorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColorExtension.swift
3 | // lottie-swift
4 | //
5 | // Created by Brandon Withrow on 2/4/19.
6 | //
7 |
8 | import Foundation
9 | #if os(iOS) || os(tvOS) || os(watchOS)
10 | import UIKit
11 |
12 | public extension UIColor {
13 |
14 | var lottieColorValue: Color {
15 | var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
16 | getRed(&r, green: &g, blue: &b, alpha: &a)
17 | return Color(r: Double(r), g: Double(g), b: Double(b), a: Double(a))
18 | }
19 |
20 | }
21 | #endif
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UserOnboarding_iOS
2 | Tutorial to demonstrate a simple way to create UserOnboarding with the help of CollectionView and Lottie.
3 |
4 |
5 |
6 | ## Prerequisites
7 | * Swift 5
8 | * XCode
9 | * CocoaPods
10 |
11 |
12 | ## Technology used
13 | * Xcode
14 | * Swift 5
15 |
16 | ## How to use ?
17 | 1. Download or clone the repository.
18 | 2. Import the project through Xcode.
19 | 3. Run the application in mobile or simulator running iOS 13
20 |
21 | ## Credits
22 | © Shubham Kumar Singh | 2020
23 |
--------------------------------------------------------------------------------
/UserOnboarding.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/UserOnboarding.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UserOnboarding.xcodeproj/xcuserdata/shubham.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | UserOnboarding.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 2
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/UserOnboarding.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/UserOnboarding.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UserOnboarding.xcworkspace/xcuserdata/shubham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/UserOnboarding/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // UserOnboarding
4 | //
5 | // Created by Shubham Singh on 24/04/20.
6 | // Copyright © 2020 Shubham Singh. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 |
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | // MARK: UISceneSession Lifecycle
22 |
23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
24 | // Called when a new scene session is being created.
25 | // Use this method to select a configuration to create the new scene with.
26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
27 | }
28 |
29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
30 | // Called when the user discards a scene session.
31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
33 | }
34 |
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/UserOnboarding/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/UserOnboarding/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/UserOnboarding/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/UserOnboarding/CollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewCell.swift
3 | // UserOnboarding
4 | //
5 | // Created by Shubham Singh on 25/04/20.
6 | // Copyright © 2020 Shubham Singh. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CollectionViewCell: UICollectionViewCell {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/UserOnboarding/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/UserOnboarding/OnboardingCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OnboardingCollectionViewCell.swift
3 | // UserOnboarding
4 | //
5 | // Created by Shubham Singh on 25/04/20.
6 | // Copyright © 2020 Shubham Singh. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Lottie
11 |
12 | // Model to be used by the CollectionView
13 | struct Page {
14 | let animationName: String
15 | let title: String
16 | let description: String
17 | }
18 |
19 | // Custom UICollectionViewCell
20 | class OnboardingCollectionViewCell: UICollectionViewCell {
21 |
22 | @IBOutlet weak var animationContainer: UIView!
23 | @IBOutlet weak var titleLabel: UILabel!
24 | @IBOutlet weak var descriptionTextView: UITextView!
25 |
26 | static let identifier = "OnboardingCollectionViewCell"
27 |
28 | // Instance of the Lottie AnimationView
29 | var animation = AnimationView()
30 |
31 |
32 | override func awakeFromNib() {
33 | super.awakeFromNib()
34 | }
35 |
36 | // function to configure the cell
37 | func configureCell(page: Page){
38 |
39 | // define the animation and the size
40 | animation = AnimationView(name: page.animationName)
41 | animation.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height * 0.8)
42 |
43 | // customize the animation
44 | animation.animationSpeed = 1
45 | animation.loopMode = .loop
46 | animation.play()
47 |
48 | animationContainer.addSubview(animation)
49 |
50 | // set the title and description of the screen
51 | self.titleLabel.text = page.title
52 | self.descriptionTextView.text = page.description
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/UserOnboarding/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // UserOnboarding
4 | //
5 | // Created by Shubham Singh on 24/04/20.
6 | // Copyright © 2020 Shubham Singh. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/UserOnboarding/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // UserOnboarding
4 | //
5 | // Created by Shubham Singh on 24/04/20.
6 | // Copyright © 2020 Shubham Singh. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
12 |
13 | // MARK:- outlets for the viewController
14 | @IBOutlet weak var collectionView: UICollectionView!
15 | @IBOutlet weak var pageControl: UIPageControl!
16 | @IBOutlet weak var getStartedButton: UIButton!
17 |
18 | // data for the Onboarding Screens
19 | let pages: [Page] = [Page(animationName: "animation1", title: "Learn to Code", description: "Find awesome tutorials on how to code and improve your coding practices"),
20 | Page(animationName: "animation2", title: "Code with Friends", description: "Practice with friends and solve problems together to earn points"),
21 | Page(animationName: "animation3", title: "Always there to Help", description: "Having Trouble? Get guidance from our experienced Mentors")]
22 |
23 |
24 | // MARK:- lifeCycle methods for the ViewController
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 |
28 | // to make the button rounded
29 | self.getStartedButton.layer.cornerRadius = 20
30 |
31 | // register the custom CollectionViewCell and assign the delegates to the ViewController
32 | self.collectionView.backgroundColor = .white
33 | self.collectionView.dataSource = self
34 | self.collectionView.delegate = self
35 | self.collectionView.register(UINib(nibName: OnboardingCollectionViewCell.identifier, bundle: Bundle.main),
36 | forCellWithReuseIdentifier: "OnboardingCollectionViewCell")
37 |
38 | // set the number of pages to the number of Onboarding Screens
39 | self.pageControl.numberOfPages = self.pages.count
40 | }
41 |
42 | // MARK:- outlet functions for the viewController
43 | @IBAction func pageChanged(_ sender: Any) {
44 | let pc = sender as! UIPageControl
45 |
46 | // scrolling the collectionView to the selected page
47 | collectionView.scrollToItem(at: IndexPath(item: pc.currentPage, section: 0),
48 | at: .centeredHorizontally, animated: true)
49 | }
50 |
51 | @IBAction func getStartedButtonTapped(_ sender: Any) {
52 | // move the user to the other view controller
53 | print("Move to other view controller")
54 | }
55 |
56 |
57 |
58 | // MARK:- collectionView dataSource & collectionView FlowLayout delegates
59 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
60 | return pages.count
61 | }
62 |
63 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
64 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OnboardingCollectionViewCell.identifier,
65 | for: indexPath) as! OnboardingCollectionViewCell
66 | // function for configuring the cell, defined in the Custom cell class
67 | cell.configureCell(page: pages[indexPath.item])
68 | return cell
69 | }
70 |
71 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
72 | sizeForItemAt indexPath: IndexPath) -> CGSize {
73 | return CGSize(width: self.collectionView.frame.width, height: self.collectionView.frame.height)
74 | }
75 |
76 | // to update the UIPageControl
77 | func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell,
78 | forItemAt indexPath: IndexPath) {
79 | pageControl.currentPage = collectionView.indexPathsForVisibleItems[0].item
80 | }
81 | }
82 |
83 |
--------------------------------------------------------------------------------