lottie-ios 4.4.2 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +12 -39
- package/Lottie.xcodeproj/project.pbxproj +28 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +19 -6
- package/Package.resolved +2 -2
- package/Package.swift +1 -1
- package/README.md +2 -2
- package/Rakefile +1 -1
- package/Sources/PrivacyInfo.xcprivacy +1 -1
- package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +2 -2
- package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +6 -6
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +24 -9
- package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +7 -7
- package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +12 -12
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +19 -19
- package/Sources/Private/CoreAnimation/ValueProviderStore.swift +4 -4
- package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +13 -6
- package/Sources/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +3 -3
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift +10 -6
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +4 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift +2 -2
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift +5 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift +2 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +1 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift +2 -2
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/Entry.swift +1 -0
- package/Sources/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +10 -9
- package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +19 -0
- package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +7 -7
- package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +3 -0
- package/Sources/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +24 -14
- package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +11 -10
- package/Sources/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +2 -0
- package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +102 -17
- package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +11 -11
- package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +2 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/DropShadowNode.swift +102 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/LayerEffectNode.swift +24 -0
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +4 -4
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +16 -16
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +4 -4
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +5 -5
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +60 -1
- package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +2 -2
- package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +9 -6
- package/Sources/Private/Model/LayerEffects/EffectValues/EffectValue.swift +4 -4
- package/Sources/Private/Model/LayerEffects/LayerEffect.swift +2 -2
- package/Sources/Private/Model/LayerStyles/LayerStyle.swift +2 -2
- package/Sources/Private/Model/Layers/LayerModel.swift +7 -7
- package/Sources/Private/Model/ShapeItems/ShapeItem.swift +15 -15
- package/Sources/Private/Model/Text/TextAnimator.swift +47 -1
- package/Sources/Private/Utility/Debugging/LayerDebugging.swift +6 -6
- package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +16 -16
- package/Sources/Private/Utility/Extensions/BlendMode+Filter.swift +16 -16
- package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +18 -0
- package/Sources/Private/Utility/Extensions/CGFloatExtensions.swift +23 -23
- package/Sources/Private/Utility/Extensions/MathKit.swift +4 -11
- package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +9 -3
- package/Sources/Private/Utility/LottieAnimationSource.swift +4 -4
- package/Sources/Private/Utility/Primitives/BezierPath.swift +16 -2
- package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +2 -2
- package/Sources/Private/Utility/Primitives/ColorExtension.swift +20 -20
- package/Sources/Private/Utility/Primitives/CompoundBezierPath.swift +9 -9
- package/Sources/Public/Animation/LottieAnimationLayer.swift +36 -31
- package/Sources/Public/Animation/LottieAnimationView.swift +15 -15
- package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +4 -0
- package/Sources/Public/Animation/LottiePlaybackMode.swift +12 -12
- package/Sources/Public/Animation/LottieView.swift +53 -5
- package/Sources/Public/Configuration/ReducedMotionOption.swift +5 -5
- package/Sources/Public/Configuration/RenderingEngineOption.swift +4 -4
- package/Sources/Public/Controls/AnimatedSwitch.swift +2 -2
- package/Sources/Public/DotLottie/DotLottieFile.swift +2 -2
- package/Sources/Public/DynamicProperties/AnyValueProvider.swift +9 -9
- package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +2 -2
- package/Sources/Public/Keyframes/Interpolatable.swift +2 -2
- package/Sources/Public/Primitives/LottieColor.swift +3 -3
- package/Sources/Public/TextProvider/AnimationTextProvider.swift +4 -4
- package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +13 -12
- package/Version.xcconfig +2 -2
- package/lottie-ios.podspec +2 -2
- package/package.json +1 -1
|
@@ -124,12 +124,12 @@ extension KeypathSearchable {
|
|
|
124
124
|
func allKeypaths(for keyPath: AnimationKeypath? = nil) -> [String] {
|
|
125
125
|
var allKeypaths: [String] = []
|
|
126
126
|
|
|
127
|
-
let newKeypath: AnimationKeypath
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
let newKeypath: AnimationKeypath =
|
|
128
|
+
if let previousKeypath = keyPath {
|
|
129
|
+
previousKeypath.appendingKey(keypathName)
|
|
130
|
+
} else {
|
|
131
|
+
AnimationKeypath(keys: [keypathName])
|
|
132
|
+
}
|
|
133
133
|
|
|
134
134
|
allKeypaths.append(newKeypath.fullPath)
|
|
135
135
|
|
|
@@ -148,12 +148,12 @@ extension KeypathSearchable {
|
|
|
148
148
|
func layerKeypaths(for keyPath: AnimationKeypath? = nil) -> [CALayer: AnimationKeypath] {
|
|
149
149
|
var allKeypaths: [CALayer: AnimationKeypath] = [:]
|
|
150
150
|
|
|
151
|
-
let newKeypath: AnimationKeypath
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
let newKeypath: AnimationKeypath =
|
|
152
|
+
if let previousKeypath = keyPath {
|
|
153
|
+
previousKeypath.appendingKey(keypathName)
|
|
154
|
+
} else {
|
|
155
|
+
AnimationKeypath(keys: [keypathName])
|
|
156
|
+
}
|
|
157
157
|
|
|
158
158
|
if let layer = self as? CALayer {
|
|
159
159
|
allKeypaths[layer] = newKeypath
|
|
@@ -197,7 +197,7 @@ extension AnimationKeypath {
|
|
|
197
197
|
keys.joined(separator: ".")
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
/// Pops the top keypath from the stack if the keyname matches.
|
|
201
201
|
func popKey(_ keyname: String) -> AnimationKeypath? {
|
|
202
202
|
guard
|
|
203
203
|
let currentKey,
|
|
@@ -245,11 +245,11 @@ extension String {
|
|
|
245
245
|
var keyPathType: KeyType {
|
|
246
246
|
switch self {
|
|
247
247
|
case "*":
|
|
248
|
-
|
|
248
|
+
.wildcard
|
|
249
249
|
case "**":
|
|
250
|
-
|
|
250
|
+
.fuzzyWildcard
|
|
251
251
|
default:
|
|
252
|
-
|
|
252
|
+
.specific
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
|
|
@@ -10,22 +10,22 @@ extension BlendMode {
|
|
|
10
10
|
/// Supported compositing filters are defined here: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/uid/TP30000136-SW71
|
|
11
11
|
var filterName: String? {
|
|
12
12
|
switch self {
|
|
13
|
-
case .normal:
|
|
14
|
-
case .multiply:
|
|
15
|
-
case .screen:
|
|
16
|
-
case .overlay:
|
|
17
|
-
case .darken:
|
|
18
|
-
case .lighten:
|
|
19
|
-
case .colorDodge:
|
|
20
|
-
case .colorBurn:
|
|
21
|
-
case .hardLight:
|
|
22
|
-
case .softLight:
|
|
23
|
-
case .difference:
|
|
24
|
-
case .exclusion:
|
|
25
|
-
case .hue:
|
|
26
|
-
case .saturation:
|
|
27
|
-
case .color:
|
|
28
|
-
case .luminosity:
|
|
13
|
+
case .normal: nil
|
|
14
|
+
case .multiply: "multiplyBlendMode"
|
|
15
|
+
case .screen: "screenBlendMode"
|
|
16
|
+
case .overlay: "overlayBlendMode"
|
|
17
|
+
case .darken: "darkenBlendMode"
|
|
18
|
+
case .lighten: "lightenBlendMode"
|
|
19
|
+
case .colorDodge: "colorDodgeBlendMode"
|
|
20
|
+
case .colorBurn: "colorBurnBlendMode"
|
|
21
|
+
case .hardLight: "hardLightBlendMode"
|
|
22
|
+
case .softLight: "softLightBlendMode"
|
|
23
|
+
case .difference: "differenceBlendMode"
|
|
24
|
+
case .exclusion: "exclusionBlendMode"
|
|
25
|
+
case .hue: "hueBlendMode"
|
|
26
|
+
case .saturation: "saturationBlendMode"
|
|
27
|
+
case .color: "colorBlendMode"
|
|
28
|
+
case .luminosity: "luminosityBlendMode"
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
import QuartzCore
|
|
5
5
|
|
|
6
6
|
extension CGColor {
|
|
7
|
+
/// Retrieves the red, green, and blue color values from this `CGColor`
|
|
8
|
+
var rgb: (red: CGFloat, green: CGFloat, blue: CGFloat)? {
|
|
9
|
+
guard let components else { return nil }
|
|
10
|
+
|
|
11
|
+
switch numberOfComponents {
|
|
12
|
+
case 2:
|
|
13
|
+
return (red: components[0], green: components[0], blue: components[0])
|
|
14
|
+
|
|
15
|
+
case 3, 4:
|
|
16
|
+
return (red: components[0], green: components[1], blue: components[2])
|
|
17
|
+
|
|
18
|
+
default:
|
|
19
|
+
// Unsupported conversion
|
|
20
|
+
return nil
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
/// Initializes a `CGColor` using the given `RGB` values
|
|
8
25
|
static func rgb(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat) -> CGColor {
|
|
9
26
|
rgba(red, green, blue, 1.0)
|
|
@@ -22,4 +39,5 @@ extension CGColor {
|
|
|
22
39
|
colorSpace: LottieConfiguration.shared.colorSpace,
|
|
23
40
|
components: [red, green, blue, alpha])!
|
|
24
41
|
}
|
|
42
|
+
|
|
25
43
|
}
|
|
@@ -41,19 +41,19 @@ extension CGFloat {
|
|
|
41
41
|
t = 1
|
|
42
42
|
} else {
|
|
43
43
|
// Calculate t
|
|
44
|
-
let a = -P0.x + 3 * P1.x - 3 * P2.x + P3.x
|
|
45
|
-
let b = 3 * P0.x - 6 * P1.x + 3 * P2.x
|
|
46
|
-
let c = -3 * P0.x + 3 * P1.x
|
|
47
|
-
let d = P0.x - self
|
|
48
|
-
let tTemp = CGFloat.SolveCubic(a, b, c, d)
|
|
44
|
+
let a = -P0.x + 3 * P1.x - 3 * P2.x + P3.x
|
|
45
|
+
let b = 3 * P0.x - 6 * P1.x + 3 * P2.x
|
|
46
|
+
let c = -3 * P0.x + 3 * P1.x
|
|
47
|
+
let d = P0.x - self
|
|
48
|
+
let tTemp = CGFloat.SolveCubic(a, b, c, d)
|
|
49
49
|
if tTemp == -1 {
|
|
50
|
-
return -1
|
|
50
|
+
return -1
|
|
51
51
|
}
|
|
52
52
|
t = tTemp
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// Calculate y from t
|
|
56
|
-
return (1 - t).cubed * P0.y + 3 * t * (1 - t).squared * P1.y + 3 * t.squared * (1 - t) * P2.y + t.cubed * P3.y
|
|
56
|
+
return (1 - t).cubed * P0.y + 3 * t * (1 - t).squared * P1.y + 3 * t.squared * (1 - t) * P2.y + t.cubed * P3.y
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
func cubicBezier(_ t: CGFloat, _ c1: CGFloat, _ c2: CGFloat, _ end: CGFloat) -> CGFloat {
|
|
@@ -66,23 +66,23 @@ extension CGFloat {
|
|
|
66
66
|
return self * ttt_
|
|
67
67
|
+ 3.0 * c1 * tt_ * t
|
|
68
68
|
+ 3.0 * c2 * t_ * tt
|
|
69
|
-
+ end * ttt
|
|
69
|
+
+ end * ttt
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// MARK: Fileprivate
|
|
73
73
|
|
|
74
74
|
fileprivate static func SolveQuadratic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat) -> CGFloat {
|
|
75
|
-
var result = (-b + sqrt(b.squared - 4 * a * c)) / (2 * a)
|
|
75
|
+
var result = (-b + sqrt(b.squared - 4 * a * c)) / (2 * a)
|
|
76
76
|
guard !result.isInRangeOrEqual(0, 1) else {
|
|
77
77
|
return result
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
result = (-b - sqrt(b.squared - 4 * a * c)) / (2 * a)
|
|
80
|
+
result = (-b - sqrt(b.squared - 4 * a * c)) / (2 * a)
|
|
81
81
|
guard !result.isInRangeOrEqual(0, 1) else {
|
|
82
82
|
return result
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
return -1
|
|
85
|
+
return -1
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
fileprivate static func SolveCubic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat, _ d: CGFloat) -> CGFloat {
|
|
@@ -110,43 +110,43 @@ extension CGFloat {
|
|
|
110
110
|
var t = r - sqrt(disc)
|
|
111
111
|
t = (t < 0) ? -((-t).cubicRoot) : t.cubicRoot
|
|
112
112
|
|
|
113
|
-
let result = -term1 + s + t
|
|
113
|
+
let result = -term1 + s + t
|
|
114
114
|
if result.isInRangeOrEqual(0, 1) {
|
|
115
115
|
return result
|
|
116
116
|
}
|
|
117
117
|
} else if disc == 0 {
|
|
118
|
-
let r13 = (r < 0) ? -((-r).cubicRoot) : r.cubicRoot
|
|
118
|
+
let r13 = (r < 0) ? -((-r).cubicRoot) : r.cubicRoot
|
|
119
119
|
|
|
120
|
-
var result = -term1 + 2.0 * r13
|
|
120
|
+
var result = -term1 + 2.0 * r13
|
|
121
121
|
if result.isInRangeOrEqual(0, 1) {
|
|
122
122
|
return result
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
result = -(r13 + term1)
|
|
125
|
+
result = -(r13 + term1)
|
|
126
126
|
if result.isInRangeOrEqual(0, 1) {
|
|
127
127
|
return result
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
} else {
|
|
131
|
-
q = -q
|
|
132
|
-
var dum1 = q * q * q
|
|
133
|
-
dum1 = acos(r / sqrt(dum1))
|
|
134
|
-
let r13 = 2.0 * sqrt(q)
|
|
131
|
+
q = -q
|
|
132
|
+
var dum1 = q * q * q
|
|
133
|
+
dum1 = acos(r / sqrt(dum1))
|
|
134
|
+
let r13 = 2.0 * sqrt(q)
|
|
135
135
|
|
|
136
|
-
var result = -term1 + r13 * cos(dum1 / 3.0)
|
|
136
|
+
var result = -term1 + r13 * cos(dum1 / 3.0)
|
|
137
137
|
if result.isInRangeOrEqual(0, 1) {
|
|
138
138
|
return result
|
|
139
139
|
}
|
|
140
|
-
result = -term1 + r13 * cos((dum1 + 2.0 * .pi) / 3.0)
|
|
140
|
+
result = -term1 + r13 * cos((dum1 + 2.0 * .pi) / 3.0)
|
|
141
141
|
if result.isInRangeOrEqual(0, 1) {
|
|
142
142
|
return result
|
|
143
143
|
}
|
|
144
|
-
result = -term1 + r13 * cos((dum1 + 4.0 * .pi) / 3.0)
|
|
144
|
+
result = -term1 + r13 * cos((dum1 + 4.0 * .pi) / 3.0)
|
|
145
145
|
if result.isInRangeOrEqual(0, 1) {
|
|
146
146
|
return result
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
return -1
|
|
150
|
+
return -1
|
|
151
151
|
}
|
|
152
152
|
}
|
|
@@ -33,13 +33,6 @@ extension CGFloat {
|
|
|
33
33
|
return toLow + (self - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/// Returns a value that is clamped between the two numbers
|
|
37
|
-
///
|
|
38
|
-
/// 1. The order of arguments does not matter.
|
|
39
|
-
func clamp(_ a: CGFloat, _ b: CGFloat) -> CGFloat {
|
|
40
|
-
CGFloat(Double(self).clamp(Double(a), Double(b)))
|
|
41
|
-
}
|
|
42
|
-
|
|
43
36
|
/// Returns the difference between the receiver and the given number.
|
|
44
37
|
/// - Parameter absolute: If *true* (Default) the returned value will always be positive.
|
|
45
38
|
func diff(_ a: CGFloat, absolute: Bool = true) -> CGFloat {
|
|
@@ -54,20 +47,20 @@ extension CGFloat {
|
|
|
54
47
|
// MARK: - Double
|
|
55
48
|
|
|
56
49
|
extension Double {
|
|
57
|
-
|
|
58
50
|
func remap(fromLow: Double, fromHigh: Double, toLow: Double, toHigh: Double) -> Double {
|
|
59
51
|
toLow + (self - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
|
|
60
52
|
}
|
|
53
|
+
}
|
|
61
54
|
|
|
55
|
+
extension Numeric where Self: Comparable {
|
|
62
56
|
/// Returns a value that is clamped between the two numbers
|
|
63
57
|
///
|
|
64
58
|
/// 1. The order of arguments does not matter.
|
|
65
|
-
func clamp(_ a:
|
|
59
|
+
func clamp(_ a: Self, _ b: Self) -> Self {
|
|
66
60
|
let minValue = a <= b ? a : b
|
|
67
61
|
let maxValue = a <= b ? b : a
|
|
68
62
|
return max(min(self, maxValue), minValue)
|
|
69
63
|
}
|
|
70
|
-
|
|
71
64
|
}
|
|
72
65
|
|
|
73
66
|
extension CGRect {
|
|
@@ -426,7 +419,7 @@ extension CGPoint {
|
|
|
426
419
|
}
|
|
427
420
|
|
|
428
421
|
func colinear(_ a: CGPoint, _ b: CGPoint) -> Bool {
|
|
429
|
-
let area = x * (a.y - b.y) + a.x * (b.y - y) + b.x * (y - a.y)
|
|
422
|
+
let area = x * (a.y - b.y) + a.x * (b.y - y) + b.x * (y - a.y)
|
|
430
423
|
let accuracy: CGFloat = 0.05
|
|
431
424
|
if area < accuracy, area > -accuracy {
|
|
432
425
|
return true
|
|
@@ -16,7 +16,7 @@ extension LottieColor {
|
|
|
16
16
|
init(h: Double, s: Double, v: Double, a: Double) {
|
|
17
17
|
let i = floor(h * 6)
|
|
18
18
|
let f = h * 6 - i
|
|
19
|
-
let p = v * (1 - s)
|
|
19
|
+
let p = v * (1 - s)
|
|
20
20
|
let q = v * (1 - f * s)
|
|
21
21
|
let t = v * (1 - (1 - f) * s)
|
|
22
22
|
|
|
@@ -25,26 +25,32 @@ extension LottieColor {
|
|
|
25
25
|
r = v
|
|
26
26
|
g = t
|
|
27
27
|
b = p
|
|
28
|
+
|
|
28
29
|
case 1:
|
|
29
30
|
r = q
|
|
30
31
|
g = v
|
|
31
32
|
b = p
|
|
33
|
+
|
|
32
34
|
case 2:
|
|
33
35
|
r = p
|
|
34
36
|
g = v
|
|
35
37
|
b = t
|
|
38
|
+
|
|
36
39
|
case 3:
|
|
37
40
|
r = p
|
|
38
41
|
g = q
|
|
39
42
|
b = v
|
|
43
|
+
|
|
40
44
|
case 4:
|
|
41
45
|
r = t
|
|
42
46
|
g = p
|
|
43
47
|
b = v
|
|
48
|
+
|
|
44
49
|
case 5:
|
|
45
50
|
r = v
|
|
46
51
|
g = p
|
|
47
52
|
b = q
|
|
53
|
+
|
|
48
54
|
default:
|
|
49
55
|
r = 0
|
|
50
56
|
g = 0
|
|
@@ -71,10 +77,10 @@ extension LottieColor {
|
|
|
71
77
|
var h: Double, s: Double, v: Double = maxValue
|
|
72
78
|
|
|
73
79
|
let d = maxValue - minValue
|
|
74
|
-
s = maxValue == 0 ? 0 : d / maxValue
|
|
80
|
+
s = maxValue == 0 ? 0 : d / maxValue
|
|
75
81
|
|
|
76
82
|
if maxValue == minValue {
|
|
77
|
-
h = 0
|
|
83
|
+
h = 0 // achromatic
|
|
78
84
|
} else {
|
|
79
85
|
switch maxValue {
|
|
80
86
|
case r: h = (g - b) / d + (g < b ? 6 : 0)
|
|
@@ -19,9 +19,9 @@ extension LottieAnimationSource {
|
|
|
19
19
|
var animation: LottieAnimation? {
|
|
20
20
|
switch self {
|
|
21
21
|
case .lottieAnimation(let animation):
|
|
22
|
-
|
|
22
|
+
animation
|
|
23
23
|
case .dotLottieFile:
|
|
24
|
-
|
|
24
|
+
dotLottieAnimation?.animation
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -29,9 +29,9 @@ extension LottieAnimationSource {
|
|
|
29
29
|
var dotLottieAnimation: DotLottieFile.Animation? {
|
|
30
30
|
switch self {
|
|
31
31
|
case .lottieAnimation:
|
|
32
|
-
|
|
32
|
+
nil
|
|
33
33
|
case .dotLottieFile(let dotLottieFile):
|
|
34
|
-
|
|
34
|
+
dotLottieFile.animation()
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -343,7 +343,14 @@ extension BezierPath: Codable {
|
|
|
343
343
|
totalLength = totalLength + pathElement.length
|
|
344
344
|
}
|
|
345
345
|
if closed {
|
|
346
|
-
|
|
346
|
+
// Don't use an out tangent for the closing point, since the
|
|
347
|
+
// closing point is exactly equal to the starting point.
|
|
348
|
+
let closeVertex = CurveVertex(
|
|
349
|
+
point: firstVertex.point,
|
|
350
|
+
inTangentRelative: firstVertex.inTangentRelative,
|
|
351
|
+
outTangentRelative: .zero)
|
|
352
|
+
|
|
353
|
+
let closeElement = previousElement.pathElementTo(closeVertex)
|
|
347
354
|
decodedElements.append(closeElement)
|
|
348
355
|
totalLength = totalLength + closeElement.length
|
|
349
356
|
}
|
|
@@ -448,7 +455,14 @@ extension BezierPath: AnyInitializable {
|
|
|
448
455
|
totalLength = totalLength + pathElement.length
|
|
449
456
|
}
|
|
450
457
|
if closed {
|
|
451
|
-
|
|
458
|
+
// Don't use an out tangent for the closing point, since the
|
|
459
|
+
// closing point is exactly equal to the starting point.
|
|
460
|
+
let closeVertex = CurveVertex(
|
|
461
|
+
point: firstVertex.point,
|
|
462
|
+
inTangentRelative: firstVertex.inTangentRelative,
|
|
463
|
+
outTangentRelative: .zero)
|
|
464
|
+
|
|
465
|
+
let closeElement = previousElement.pathElementTo(closeVertex)
|
|
452
466
|
decodedElements.append(closeElement)
|
|
453
467
|
totalLength = totalLength + closeElement.length
|
|
454
468
|
}
|
|
@@ -30,7 +30,7 @@ import Foundation
|
|
|
30
30
|
// shape's vertex distances and the roundedness set in the animation.
|
|
31
31
|
|
|
32
32
|
extension CompoundBezierPath {
|
|
33
|
-
|
|
33
|
+
/// Round corners of a compound bezier
|
|
34
34
|
func roundCorners(radius: CGFloat) -> CompoundBezierPath {
|
|
35
35
|
var newPaths = [BezierPath]()
|
|
36
36
|
for path in paths {
|
|
@@ -43,7 +43,7 @@ extension CompoundBezierPath {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
extension BezierPath {
|
|
46
|
-
|
|
46
|
+
/// Computes a new `BezierPath` with each corner rounded based on the given `radius`
|
|
47
47
|
func roundCorners(radius: CGFloat) -> BezierPath {
|
|
48
48
|
var newPath = BezierPath()
|
|
49
49
|
var uniquePath = BezierPath()
|
|
@@ -16,26 +16,26 @@ extension LottieColor: Codable {
|
|
|
16
16
|
public init(from decoder: Decoder) throws {
|
|
17
17
|
var container = try decoder.unkeyedContainer()
|
|
18
18
|
|
|
19
|
-
var r1: Double
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var g1: Double
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
var b1: Double
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
var r1: Double =
|
|
20
|
+
if !container.isAtEnd {
|
|
21
|
+
try container.decode(Double.self)
|
|
22
|
+
} else {
|
|
23
|
+
0
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var g1: Double =
|
|
27
|
+
if !container.isAtEnd {
|
|
28
|
+
try container.decode(Double.self)
|
|
29
|
+
} else {
|
|
30
|
+
0
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var b1: Double =
|
|
34
|
+
if !container.isAtEnd {
|
|
35
|
+
try container.decode(Double.self)
|
|
36
|
+
} else {
|
|
37
|
+
0
|
|
38
|
+
}
|
|
39
39
|
|
|
40
40
|
if r1 > 1, g1 > 1, b1 > 1 {
|
|
41
41
|
r1 = r1 / 255
|
|
@@ -101,15 +101,15 @@ struct CompoundBezierPath {
|
|
|
101
101
|
return self
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
var positions: [(start: CGFloat, end: CGFloat)]
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
104
|
+
var positions: [(start: CGFloat, end: CGFloat)] =
|
|
105
|
+
if endPosition < startPosition {
|
|
106
|
+
[
|
|
107
|
+
(start: 0, end: endPosition * length),
|
|
108
|
+
(start: startPosition * length, end: length),
|
|
109
|
+
]
|
|
110
|
+
} else {
|
|
111
|
+
[(start: startPosition * length, end: endPosition * length)]
|
|
112
|
+
}
|
|
113
113
|
|
|
114
114
|
var compoundPath = CompoundBezierPath()
|
|
115
115
|
var trim = positions.remove(at: 0)
|
|
@@ -237,12 +237,12 @@ public class LottieAnimationLayer: CALayer {
|
|
|
237
237
|
self.loopMode = loopMode
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
let fromTime: CGFloat
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
let fromTime: CGFloat =
|
|
241
|
+
if let fromName = fromMarker, let from = markers[fromName] {
|
|
242
|
+
CGFloat(from.frameTime)
|
|
243
|
+
} else {
|
|
244
|
+
currentFrame
|
|
245
|
+
}
|
|
246
246
|
|
|
247
247
|
let playTo = playEndMarkerFrame ? CGFloat(to.frameTime) : CGFloat(to.frameTime) - 1
|
|
248
248
|
let context = AnimationContext(
|
|
@@ -339,7 +339,7 @@ public class LottieAnimationLayer: CALayer {
|
|
|
339
339
|
// If we don't have any more markers to play, then the marker sequence has completed.
|
|
340
340
|
completion?(completed)
|
|
341
341
|
} else {
|
|
342
|
-
|
|
342
|
+
play(markers: followingMarkers, completion: completion)
|
|
343
343
|
}
|
|
344
344
|
})
|
|
345
345
|
}
|
|
@@ -370,6 +370,7 @@ public class LottieAnimationLayer: CALayer {
|
|
|
370
370
|
|
|
371
371
|
case .frame(let animationFrameTime):
|
|
372
372
|
currentFrame = animationFrameTime
|
|
373
|
+
|
|
373
374
|
case .time(let timeInterval):
|
|
374
375
|
currentTime = timeInterval
|
|
375
376
|
|
|
@@ -670,9 +671,9 @@ public class LottieAnimationLayer: CALayer {
|
|
|
670
671
|
}
|
|
671
672
|
get {
|
|
672
673
|
if let animation {
|
|
673
|
-
|
|
674
|
+
animation.progressTime(forFrame: currentFrame)
|
|
674
675
|
} else {
|
|
675
|
-
|
|
676
|
+
0
|
|
676
677
|
}
|
|
677
678
|
}
|
|
678
679
|
}
|
|
@@ -692,9 +693,9 @@ public class LottieAnimationLayer: CALayer {
|
|
|
692
693
|
}
|
|
693
694
|
get {
|
|
694
695
|
if let animation {
|
|
695
|
-
|
|
696
|
+
animation.time(forFrame: currentFrame)
|
|
696
697
|
} else {
|
|
697
|
-
|
|
698
|
+
0
|
|
698
699
|
}
|
|
699
700
|
}
|
|
700
701
|
}
|
|
@@ -992,16 +993,20 @@ public class LottieAnimationLayer: CALayer {
|
|
|
992
993
|
case .stop:
|
|
993
994
|
removeCurrentAnimation()
|
|
994
995
|
updateAnimationFrame(currentContext.playFrom)
|
|
996
|
+
|
|
995
997
|
case .pause:
|
|
996
998
|
removeCurrentAnimation()
|
|
999
|
+
|
|
997
1000
|
case .pauseAndRestore:
|
|
998
1001
|
currentContext.closure.ignoreDelegate = true
|
|
999
1002
|
removeCurrentAnimation()
|
|
1000
1003
|
/// Keep the stale context around for when the app enters the foreground.
|
|
1001
1004
|
animationContext = currentContext
|
|
1005
|
+
|
|
1002
1006
|
case .forceFinish:
|
|
1003
1007
|
removeCurrentAnimation()
|
|
1004
1008
|
updateAnimationFrame(currentContext.playTo)
|
|
1009
|
+
|
|
1005
1010
|
case .continuePlaying:
|
|
1006
1011
|
break
|
|
1007
1012
|
}
|
|
@@ -1117,9 +1122,9 @@ public class LottieAnimationLayer: CALayer {
|
|
|
1117
1122
|
fileprivate var activeAnimationName: String {
|
|
1118
1123
|
switch rootAnimationLayer?.primaryAnimationKey {
|
|
1119
1124
|
case .specific(let animationKey):
|
|
1120
|
-
|
|
1125
|
+
animationKey
|
|
1121
1126
|
case .managed, nil:
|
|
1122
|
-
|
|
1127
|
+
_activeAnimationName
|
|
1123
1128
|
}
|
|
1124
1129
|
}
|
|
1125
1130
|
|
|
@@ -1148,15 +1153,15 @@ public class LottieAnimationLayer: CALayer {
|
|
|
1148
1153
|
guard let animation else {
|
|
1149
1154
|
return
|
|
1150
1155
|
}
|
|
1151
|
-
let rootAnimationLayer: RootAnimationLayer?
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1156
|
+
let rootAnimationLayer: RootAnimationLayer? =
|
|
1157
|
+
switch renderingEngine {
|
|
1158
|
+
case .automatic:
|
|
1159
|
+
makeAutomaticEngineLayer(for: animation)
|
|
1160
|
+
case .specific(.coreAnimation):
|
|
1161
|
+
makeCoreAnimationLayer(for: animation)
|
|
1162
|
+
case .specific(.mainThread):
|
|
1163
|
+
makeMainThreadAnimationLayer(for: animation)
|
|
1164
|
+
}
|
|
1160
1165
|
|
|
1161
1166
|
guard let animationLayer = rootAnimationLayer else {
|
|
1162
1167
|
return
|
|
@@ -1259,8 +1264,8 @@ public class LottieAnimationLayer: CALayer {
|
|
|
1259
1264
|
}
|
|
1260
1265
|
}
|
|
1261
1266
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1267
|
+
/// Handles any compatibility issues with the Core Animation engine
|
|
1268
|
+
/// by falling back to the Main Thread engine
|
|
1264
1269
|
fileprivate func automaticEngineLayerDidSetUpAnimation(_ compatibilityIssues: [CompatibilityIssue]) {
|
|
1265
1270
|
// If there weren't any compatibility issues, then there's nothing else to do
|
|
1266
1271
|
if compatibilityIssues.isEmpty {
|
|
@@ -1462,9 +1467,9 @@ public class LottieAnimationLayer: CALayer {
|
|
|
1462
1467
|
private var reducedMotionMarker: Marker? {
|
|
1463
1468
|
switch configuration.reducedMotionOption.currentReducedMotionMode {
|
|
1464
1469
|
case .standardMotion:
|
|
1465
|
-
|
|
1470
|
+
nil
|
|
1466
1471
|
case .reducedMotion:
|
|
1467
|
-
|
|
1472
|
+
animation?.reducedMotionMarker
|
|
1468
1473
|
}
|
|
1469
1474
|
}
|
|
1470
1475
|
|
|
@@ -1503,15 +1508,15 @@ extension LottieLoopMode {
|
|
|
1503
1508
|
var caAnimationConfiguration: (repeatCount: Float, autoreverses: Bool) {
|
|
1504
1509
|
switch self {
|
|
1505
1510
|
case .playOnce:
|
|
1506
|
-
|
|
1511
|
+
(repeatCount: 1, autoreverses: false)
|
|
1507
1512
|
case .loop:
|
|
1508
|
-
|
|
1513
|
+
(repeatCount: .greatestFiniteMagnitude, autoreverses: false)
|
|
1509
1514
|
case .autoReverse:
|
|
1510
|
-
|
|
1515
|
+
(repeatCount: .greatestFiniteMagnitude, autoreverses: true)
|
|
1511
1516
|
case .repeat(let amount):
|
|
1512
|
-
|
|
1517
|
+
(repeatCount: amount, autoreverses: false)
|
|
1513
1518
|
case .repeatBackwards(let amount):
|
|
1514
|
-
|
|
1519
|
+
(repeatCount: amount, autoreverses: true)
|
|
1515
1520
|
}
|
|
1516
1521
|
}
|
|
1517
1522
|
}
|