lottie-ios 3.4.2 → 3.4.3
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/Lottie.xcodeproj/project.pbxproj +4 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +16 -0
- package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +17 -5
- package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +5 -4
- package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +25 -12
- package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +3 -0
- package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -0
- package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +2 -2
- package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +3 -3
- package/Sources/Private/CoreAnimation/Layers/TextLayer.swift +15 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
- package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +12 -1
- package/Sources/Public/Animation/AnimationPublic.swift +2 -1
- package/Sources/Public/Animation/AnimationView.swift +2 -0
- package/Tests/AutomaticEngineTests.swift +1 -0
- package/Tests/SnapshotConfiguration.swift +15 -1
- package/Tests/SnapshotTests.swift +4 -0
- package/Tests/Utils/HardcodedTextProvider.swift +27 -0
- package/lottie-ios.podspec +1 -1
- package/package.json +1 -1
- package/Tests/Samples/9squares_AlBoardman.json +0 -1
- package/Tests/Samples/Boat_Loader.json +0 -1
- package/Tests/Samples/HamburgerArrow.json +0 -1
- package/Tests/Samples/IconTransitions.json +0 -1
- package/Tests/Samples/Images/dog.png +0 -0
- package/Tests/Samples/Issues/issue_1125.json +0 -1
- package/Tests/Samples/Issues/issue_1260.json +0 -1
- package/Tests/Samples/Issues/issue_1403.json +0 -1
- package/Tests/Samples/Issues/issue_1407.json +0 -1
- package/Tests/Samples/Issues/issue_1460.json +0 -1
- package/Tests/Samples/Issues/issue_1488.json +0 -1
- package/Tests/Samples/Issues/issue_1505.json +0 -1
- package/Tests/Samples/Issues/issue_1541.json +0 -1
- package/Tests/Samples/Issues/issue_1557.json +0 -1
- package/Tests/Samples/Issues/issue_1603.json +0 -1
- package/Tests/Samples/Issues/issue_1628.json +0 -1
- package/Tests/Samples/Issues/issue_1636.json +0 -1
- package/Tests/Samples/Issues/issue_1643.json +0 -1
- package/Tests/Samples/Issues/issue_1655.json +0 -1
- package/Tests/Samples/Issues/issue_1664.json +0 -1
- package/Tests/Samples/Issues/issue_1683.json +0 -1
- package/Tests/Samples/Issues/issue_1687.json +0 -1
- package/Tests/Samples/Issues/issue_1711.json +0 -1
- package/Tests/Samples/Issues/issue_1717.json +0 -1
- package/Tests/Samples/Issues/issue_769.json +0 -1
- package/Tests/Samples/Issues/issue_885.json +0 -1
- package/Tests/Samples/Issues/issue_965.json +0 -1
- package/Tests/Samples/Issues/pr_1536.json +0 -1
- package/Tests/Samples/Issues/pr_1563.json +0 -8439
- package/Tests/Samples/Issues/pr_1592.json +0 -5527
- package/Tests/Samples/Issues/pr_1599.json +0 -738
- package/Tests/Samples/Issues/pr_1604_1.json +0 -1
- package/Tests/Samples/Issues/pr_1604_2.json +0 -1
- package/Tests/Samples/Issues/pr_1632_1.json +0 -1
- package/Tests/Samples/Issues/pr_1632_2.json +0 -1
- package/Tests/Samples/Issues/pr_1686.json +0 -513
- package/Tests/Samples/Issues/pr_1698.json +0 -1
- package/Tests/Samples/Issues/pr_1699.json +0 -1
- package/Tests/Samples/LottieFiles/LICENSE.md +0 -14
- package/Tests/Samples/LottieFiles/bounce_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/cactus.json +0 -1
- package/Tests/Samples/LottieFiles/dog_car_ride.json +0 -1
- package/Tests/Samples/LottieFiles/draft_icon.json +0 -1
- package/Tests/Samples/LottieFiles/fireworks.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_1.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_2.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_pill.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_shapes.json +0 -1
- package/Tests/Samples/LottieFiles/gradient_square.json +0 -1
- package/Tests/Samples/LottieFiles/growth.json +0 -1
- package/Tests/Samples/LottieFiles/infinity_loader.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_1.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_2.json +0 -1
- package/Tests/Samples/LottieFiles/loading_dots_3.json +0 -1
- package/Tests/Samples/LottieFiles/loading_gradient_strokes.json +0 -1
- package/Tests/Samples/LottieFiles/settings_slider.json +0 -1
- package/Tests/Samples/LottieFiles/shop.json +0 -1
- package/Tests/Samples/LottieFiles/step_loader.json +0 -1
- package/Tests/Samples/LottieLogo1.json +0 -1
- package/Tests/Samples/LottieLogo1_masked.json +0 -1
- package/Tests/Samples/LottieLogo2.json +0 -1
- package/Tests/Samples/MotionCorpse_Jrcanest.json +0 -1
- package/Tests/Samples/Nonanimating/BasicLayers.json +0 -1
- package/Tests/Samples/Nonanimating/DisableNodesTest.json +0 -1
- package/Tests/Samples/Nonanimating/FirstText.json +0 -1
- package/Tests/Samples/Nonanimating/GeometryTransformTest.json +0 -1
- package/Tests/Samples/Nonanimating/Text_AnimatedProperties.json +0 -1
- package/Tests/Samples/Nonanimating/Text_Glyph.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoAnimation.json +0 -1
- package/Tests/Samples/Nonanimating/Text_NoGlyph.json +0 -1
- package/Tests/Samples/Nonanimating/Zoom.json +0 -1
- package/Tests/Samples/Nonanimating/_dog.json +0 -1
- package/Tests/Samples/Nonanimating/base64Test.json +0 -1
- package/Tests/Samples/Nonanimating/blend_mode_test.json +0 -1
- package/Tests/Samples/Nonanimating/keypathTest.json +0 -1
- package/Tests/Samples/Nonanimating/verifyLineHeight.json +0 -1
- package/Tests/Samples/PinJump.json +0 -1
- package/Tests/Samples/Switch.json +0 -1
- package/Tests/Samples/Switch_States.json +0 -1
- package/Tests/Samples/TwitterHeart.json +0 -1
- package/Tests/Samples/TwitterHeartButton.json +0 -1
- package/Tests/Samples/TypeFace/A.json +0 -1
- package/Tests/Samples/TypeFace/Apostrophe.json +0 -1
- package/Tests/Samples/TypeFace/B.json +0 -1
- package/Tests/Samples/TypeFace/BlinkingCursor.json +0 -1
- package/Tests/Samples/TypeFace/C.json +0 -1
- package/Tests/Samples/TypeFace/Colon.json +0 -1
- package/Tests/Samples/TypeFace/Comma.json +0 -1
- package/Tests/Samples/TypeFace/D.json +0 -1
- package/Tests/Samples/TypeFace/E.json +0 -1
- package/Tests/Samples/TypeFace/F.json +0 -1
- package/Tests/Samples/TypeFace/G.json +0 -1
- package/Tests/Samples/TypeFace/H.json +0 -1
- package/Tests/Samples/TypeFace/I.json +0 -1
- package/Tests/Samples/TypeFace/J.json +0 -1
- package/Tests/Samples/TypeFace/K.json +0 -1
- package/Tests/Samples/TypeFace/L.json +0 -1
- package/Tests/Samples/TypeFace/M.json +0 -1
- package/Tests/Samples/TypeFace/N.json +0 -1
- package/Tests/Samples/TypeFace/O.json +0 -1
- package/Tests/Samples/TypeFace/P.json +0 -1
- package/Tests/Samples/TypeFace/Q.json +0 -1
- package/Tests/Samples/TypeFace/R.json +0 -1
- package/Tests/Samples/TypeFace/S.json +0 -1
- package/Tests/Samples/TypeFace/T.json +0 -1
- package/Tests/Samples/TypeFace/U.json +0 -1
- package/Tests/Samples/TypeFace/V.json +0 -1
- package/Tests/Samples/TypeFace/W.json +0 -1
- package/Tests/Samples/TypeFace/X.json +0 -1
- package/Tests/Samples/TypeFace/Y.json +0 -1
- package/Tests/Samples/TypeFace/Z.json +0 -1
- package/Tests/Samples/Watermelon.json +0 -1
- package/Tests/Samples/setValueTest.json +0 -1
- package/Tests/Samples/timeremap.json +0 -1
- package/Tests/Samples/vcTransition1.json +0 -1
- package/Tests/Samples/vcTransition2.json +0 -1
|
@@ -554,6 +554,7 @@
|
|
|
554
554
|
2EAF5B0427A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
555
555
|
2EAF5B0527A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
556
556
|
2EAF5B0627A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
|
|
557
|
+
36E57EAC28AF7ADF00B7EFDA /* HardcodedTextProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */; };
|
|
557
558
|
6D0E635F28246BD0007C5DB6 /* Difference in Frameworks */ = {isa = PBXBuildFile; productRef = 6D0E635E28246BD0007C5DB6 /* Difference */; };
|
|
558
559
|
6D99D6432823790700E5205B /* LegacyGradientFillRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */; };
|
|
559
560
|
6D99D6442823790700E5205B /* LegacyGradientFillRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */; };
|
|
@@ -783,6 +784,7 @@
|
|
|
783
784
|
2EAF59EF27A0798700E00531 /* GradientValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientValueProvider.swift; sourceTree = "<group>"; };
|
|
784
785
|
2EAF59F027A0798700E00531 /* PointValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointValueProvider.swift; sourceTree = "<group>"; };
|
|
785
786
|
2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationFontProvider.swift; sourceTree = "<group>"; };
|
|
787
|
+
36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HardcodedTextProvider.swift; sourceTree = "<group>"; };
|
|
786
788
|
6D99D6422823790700E5205B /* LegacyGradientFillRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyGradientFillRenderer.swift; sourceTree = "<group>"; };
|
|
787
789
|
6DB3BDB528243FA5002A276D /* ValueProvidersTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ValueProvidersTests.swift; sourceTree = "<group>"; tabWidth = 2; };
|
|
788
790
|
6DB3BDB7282454A6002A276D /* DictionaryInitializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryInitializable.swift; sourceTree = "<group>"; };
|
|
@@ -876,6 +878,7 @@
|
|
|
876
878
|
2E8040BF27A07343006E74CB /* Snapshotting+presentationLayer.swift */,
|
|
877
879
|
2EAF59A627A076BC00E00531 /* Bundle+Module.swift */,
|
|
878
880
|
2E09FA0527B6CEB600BA84E5 /* HardcodedFontProvider.swift */,
|
|
881
|
+
36E57EAB28AF7ADF00B7EFDA /* HardcodedTextProvider.swift */,
|
|
879
882
|
);
|
|
880
883
|
path = Utils;
|
|
881
884
|
sourceTree = "<group>";
|
|
@@ -1876,6 +1879,7 @@
|
|
|
1876
1879
|
6DEF696E2824A76C007D640F /* BundleTests.swift in Sources */,
|
|
1877
1880
|
2EAF59A727A076BC00E00531 /* Bundle+Module.swift in Sources */,
|
|
1878
1881
|
2E8044AE27A07347006E74CB /* Snapshotting+presentationLayer.swift in Sources */,
|
|
1882
|
+
36E57EAC28AF7ADF00B7EFDA /* HardcodedTextProvider.swift in Sources */,
|
|
1879
1883
|
2E72128527BB32DB0027BC56 /* PerformanceTests.swift in Sources */,
|
|
1880
1884
|
6DB3BDC328245AA2002A276D /* ParsingTests.swift in Sources */,
|
|
1881
1885
|
6DB3BDB628243FA5002A276D /* ValueProvidersTests.swift in Sources */,
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate
CHANGED
|
Binary file
|
package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
CHANGED
|
@@ -18,5 +18,21 @@
|
|
|
18
18
|
endingLineNumber = "44">
|
|
19
19
|
</BreakpointContent>
|
|
20
20
|
</BreakpointProxy>
|
|
21
|
+
<BreakpointProxy
|
|
22
|
+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
23
|
+
<BreakpointContent
|
|
24
|
+
uuid = "90B95B81-4B28-4BCD-AE7B-59ED8AA81AC1"
|
|
25
|
+
shouldBeEnabled = "No"
|
|
26
|
+
ignoreCount = "0"
|
|
27
|
+
continueAfterRunningActions = "No"
|
|
28
|
+
filePath = "Sources/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift"
|
|
29
|
+
startingColumnNumber = "9223372036854775807"
|
|
30
|
+
endingColumnNumber = "9223372036854775807"
|
|
31
|
+
startingLineNumber = "49"
|
|
32
|
+
endingLineNumber = "49"
|
|
33
|
+
landmarkName = "update(frame:)"
|
|
34
|
+
landmarkType = "7">
|
|
35
|
+
</BreakpointContent>
|
|
36
|
+
</BreakpointProxy>
|
|
21
37
|
</Breakpoints>
|
|
22
38
|
</Bucket>
|
|
@@ -36,11 +36,23 @@ extension GradientRenderLayer {
|
|
|
36
36
|
type: GradientContentType,
|
|
37
37
|
context: LayerAnimationContext) throws
|
|
38
38
|
{
|
|
39
|
-
// We have to set `colors` to
|
|
40
|
-
// for the
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
// We have to set `colors` and `locations` to non-nil values
|
|
40
|
+
// for the animations below to actually take effect
|
|
41
|
+
locations = []
|
|
42
|
+
|
|
43
|
+
// The initial value for `colors` must be an array with the exact same number of colors
|
|
44
|
+
// as the gradient that will be applied in the `CAAnimation`
|
|
45
|
+
switch type {
|
|
46
|
+
case .rgb:
|
|
47
|
+
colors = .init(
|
|
48
|
+
repeating: CGColor.rgb(0, 0, 0),
|
|
49
|
+
count: gradient.numberOfColors)
|
|
50
|
+
|
|
51
|
+
case .alpha:
|
|
52
|
+
colors = .init(
|
|
53
|
+
repeating: CGColor.rgb(0, 0, 0),
|
|
54
|
+
count: gradient.colorConfiguration(from: gradient.colors.keyframes[0].value, type: .alpha).count)
|
|
55
|
+
}
|
|
44
56
|
|
|
45
57
|
try addAnimation(
|
|
46
58
|
for: .colors,
|
|
@@ -55,12 +55,13 @@ extension CAShapeLayer {
|
|
|
55
55
|
try addOpacityAnimation(for: stroke, context: context)
|
|
56
56
|
|
|
57
57
|
if let (dashPattern, dashPhase) = stroke.dashPattern?.shapeLayerConfiguration {
|
|
58
|
-
lineDashPattern = try dashPattern.map {
|
|
58
|
+
let lineDashPattern = try dashPattern.map {
|
|
59
59
|
try KeyframeGroup(keyframes: $0)
|
|
60
|
-
.exactlyOneKeyframe(context: context, description: "stroke dashPattern").cgFloatValue
|
|
60
|
+
.exactlyOneKeyframe(context: context, description: "stroke dashPattern").cgFloatValue
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
|
|
63
|
+
if lineDashPattern.isSupportedLayerDashPattern {
|
|
64
|
+
self.lineDashPattern = lineDashPattern as [NSNumber]
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
try addAnimation(
|
|
@@ -17,6 +17,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
17
17
|
init(
|
|
18
18
|
animation: Animation,
|
|
19
19
|
imageProvider: AnimationImageProvider,
|
|
20
|
+
textProvider: AnimationTextProvider,
|
|
20
21
|
fontProvider: AnimationFontProvider,
|
|
21
22
|
compatibilityTrackerMode: CompatibilityTracker.Mode,
|
|
22
23
|
logger: LottieLogger)
|
|
@@ -24,6 +25,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
24
25
|
{
|
|
25
26
|
self.animation = animation
|
|
26
27
|
self.imageProvider = imageProvider
|
|
28
|
+
self.textProvider = textProvider
|
|
27
29
|
self.fontProvider = fontProvider
|
|
28
30
|
self.logger = logger
|
|
29
31
|
compatibilityTracker = CompatibilityTracker(mode: compatibilityTrackerMode, logger: logger)
|
|
@@ -44,6 +46,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
44
46
|
animation = typedLayer.animation
|
|
45
47
|
currentAnimationConfiguration = typedLayer.currentAnimationConfiguration
|
|
46
48
|
imageProvider = typedLayer.imageProvider
|
|
49
|
+
textProvider = typedLayer.textProvider
|
|
47
50
|
fontProvider = typedLayer.fontProvider
|
|
48
51
|
didSetUpAnimation = typedLayer.didSetUpAnimation
|
|
49
52
|
compatibilityTracker = typedLayer.compatibilityTracker
|
|
@@ -92,6 +95,16 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
92
95
|
didSet { reloadImages() }
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
/// The `AnimationTextProvider` that `TextLayer`'s use to retrieve texts,
|
|
99
|
+
/// that they should use to render their text context
|
|
100
|
+
var textProvider: AnimationTextProvider {
|
|
101
|
+
didSet {
|
|
102
|
+
// We need to rebuild the current animation after updating the text provider,
|
|
103
|
+
// since this is used in `TextLayer.setupAnimations(context:)`
|
|
104
|
+
rebuildCurrentAnimation()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
95
108
|
/// The `FontProvider` that `TextLayer`s use to retrieve the `CTFont`
|
|
96
109
|
/// that they should use to render their text content
|
|
97
110
|
var fontProvider: AnimationFontProvider {
|
|
@@ -203,6 +216,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
203
216
|
LayerContext(
|
|
204
217
|
animation: animation,
|
|
205
218
|
imageProvider: imageProvider,
|
|
219
|
+
textProvider: textProvider,
|
|
206
220
|
fontProvider: fontProvider,
|
|
207
221
|
compatibilityTracker: compatibilityTracker,
|
|
208
222
|
layerName: "root layer")
|
|
@@ -234,6 +248,7 @@ final class CoreAnimationLayer: BaseAnimationLayer {
|
|
|
234
248
|
compatibilityTracker: compatibilityTracker,
|
|
235
249
|
logger: logger,
|
|
236
250
|
currentKeypath: AnimationKeypath(keys: []),
|
|
251
|
+
textProvider: textProvider,
|
|
237
252
|
logHierarchyKeypaths: configuration.logHierarchyKeypaths)
|
|
238
253
|
|
|
239
254
|
// Perform a layout pass if necessary so all of the sublayers
|
|
@@ -314,11 +329,18 @@ extension CoreAnimationLayer: RootAnimationLayer {
|
|
|
314
329
|
}
|
|
315
330
|
|
|
316
331
|
var isAnimationPlaying: Bool? {
|
|
317
|
-
switch playbackState {
|
|
332
|
+
switch pendingAnimationConfiguration?.playbackState {
|
|
318
333
|
case .playing:
|
|
319
|
-
return
|
|
320
|
-
case
|
|
334
|
+
return true
|
|
335
|
+
case .paused:
|
|
321
336
|
return false
|
|
337
|
+
case nil:
|
|
338
|
+
switch playbackState {
|
|
339
|
+
case .playing:
|
|
340
|
+
return animation(forKey: #keyPath(animationProgress)) != nil
|
|
341
|
+
case nil, .paused:
|
|
342
|
+
return false
|
|
343
|
+
}
|
|
322
344
|
}
|
|
323
345
|
}
|
|
324
346
|
|
|
@@ -383,15 +405,6 @@ extension CoreAnimationLayer: RootAnimationLayer {
|
|
|
383
405
|
(sublayers ?? []).filter { $0 is AnimationLayer }
|
|
384
406
|
}
|
|
385
407
|
|
|
386
|
-
var textProvider: AnimationTextProvider {
|
|
387
|
-
get { DictionaryTextProvider([:]) }
|
|
388
|
-
set {
|
|
389
|
-
logger.assertionFailure("""
|
|
390
|
-
The Core Animation rendering engine currently doesn't support `textProvider`s")
|
|
391
|
-
""")
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
408
|
func reloadImages() {
|
|
396
409
|
// When the image provider changes, we have to update all `ImageLayer`s
|
|
397
410
|
// so they can query the most up-to-date image from the new image provider.
|
|
@@ -41,6 +41,9 @@ struct LayerAnimationContext {
|
|
|
41
41
|
/// The AnimationKeypath represented by the current layer
|
|
42
42
|
var currentKeypath: AnimationKeypath
|
|
43
43
|
|
|
44
|
+
/// The `AnimationTextProvider`
|
|
45
|
+
var textProvider: AnimationTextProvider
|
|
46
|
+
|
|
44
47
|
/// Whether or not to log `AnimationKeypath`s for all of the animation's layers
|
|
45
48
|
/// - Used for `CoreAnimationLayer.logHierarchyKeypaths()`
|
|
46
49
|
var logHierarchyKeypaths: Bool
|
|
@@ -9,6 +9,7 @@ import QuartzCore
|
|
|
9
9
|
struct LayerContext {
|
|
10
10
|
let animation: Animation
|
|
11
11
|
let imageProvider: AnimationImageProvider
|
|
12
|
+
let textProvider: AnimationTextProvider
|
|
12
13
|
let fontProvider: AnimationFontProvider
|
|
13
14
|
let compatibilityTracker: CompatibilityTracker
|
|
14
15
|
var layerName: String
|
|
@@ -68,12 +68,12 @@ final class PreCompLayer: BaseCompositionLayer {
|
|
|
68
68
|
try setupLayerAnimations(context: context)
|
|
69
69
|
|
|
70
70
|
// Precomp layers can adjust the local time of their child layers (relative to the
|
|
71
|
-
// animation's global time) via `timeRemapping` or a custom `startTime`
|
|
71
|
+
// animation's global time) via `timeRemapping` or a custom `startTime` / `timeStretch`
|
|
72
72
|
let contextForChildren = context.withTimeRemapping { [preCompLayer, timeRemappingInterpolator] layerLocalFrame in
|
|
73
73
|
if let timeRemappingInterpolator = timeRemappingInterpolator {
|
|
74
74
|
return timeRemappingInterpolator.value(frame: layerLocalFrame) as? AnimationFrameTime ?? layerLocalFrame
|
|
75
75
|
} else {
|
|
76
|
-
return layerLocalFrame + AnimationFrameTime(preCompLayer.startTime)
|
|
76
|
+
return (layerLocalFrame * AnimationFrameTime(preCompLayer.timeStretch)) + AnimationFrameTime(preCompLayer.startTime)
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -253,9 +253,9 @@ extension CALayer {
|
|
|
253
253
|
pathForChildren.append(group.name)
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
let childItems = group.items
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
let childItems = group.items
|
|
257
|
+
.filter { !$0.hidden }
|
|
258
|
+
.map { ShapeItemLayer.Item(item: $0, groupPath: pathForChildren) }
|
|
259
259
|
|
|
260
260
|
return try GroupLayer(
|
|
261
261
|
group: group,
|
|
@@ -36,6 +36,21 @@ final class TextLayer: BaseCompositionLayer {
|
|
|
36
36
|
|
|
37
37
|
// MARK: Internal
|
|
38
38
|
|
|
39
|
+
override func setupAnimations(context: LayerAnimationContext) throws {
|
|
40
|
+
try super.setupAnimations(context: context)
|
|
41
|
+
let textAnimationContext = context.addingKeypathComponent(textLayerModel.name)
|
|
42
|
+
|
|
43
|
+
let sourceText = try textLayerModel.text.exactlyOneKeyframe(
|
|
44
|
+
context: textAnimationContext,
|
|
45
|
+
description: "text layer text")
|
|
46
|
+
|
|
47
|
+
renderLayer.text = context.textProvider.textFor(
|
|
48
|
+
keypathName: textAnimationContext.currentKeypath.fullPath,
|
|
49
|
+
sourceText: sourceText.text)
|
|
50
|
+
|
|
51
|
+
renderLayer.sizeToFit()
|
|
52
|
+
}
|
|
53
|
+
|
|
39
54
|
func configureRenderLayer(with context: LayerContext) throws {
|
|
40
55
|
// We can't use `CATextLayer`, because it doesn't support enough features we use.
|
|
41
56
|
// Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation)
|
|
@@ -54,7 +69,6 @@ final class TextLayer: BaseCompositionLayer {
|
|
|
54
69
|
""")
|
|
55
70
|
}
|
|
56
71
|
|
|
57
|
-
renderLayer.text = text.text
|
|
58
72
|
renderLayer.font = context.fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
|
|
59
73
|
|
|
60
74
|
renderLayer.alignment = text.justification.textAlignment
|
package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift
CHANGED
|
@@ -140,7 +140,7 @@ final class GradientStrokeNode: AnimatorNode, RenderNode {
|
|
|
140
140
|
|
|
141
141
|
/// Get dash lengths
|
|
142
142
|
let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue }
|
|
143
|
-
if dashLengths.count > 0,
|
|
143
|
+
if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern {
|
|
144
144
|
strokeRender.strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue
|
|
145
145
|
strokeRender.strokeRender.dashLengths = dashLengths
|
|
146
146
|
} else {
|
|
@@ -118,7 +118,7 @@ final class StrokeNode: AnimatorNode, RenderNode {
|
|
|
118
118
|
|
|
119
119
|
/// Get dash lengths
|
|
120
120
|
let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue }
|
|
121
|
-
if dashLengths.count > 0,
|
|
121
|
+
if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern {
|
|
122
122
|
strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue
|
|
123
123
|
strokeRender.dashLengths = dashLengths
|
|
124
124
|
} else {
|
|
@@ -167,3 +167,14 @@ extension Array where Element == DashElement {
|
|
|
167
167
|
return (dashPatterns, dashPhase)
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
|
|
171
|
+
extension Array where Element == CGFloat {
|
|
172
|
+
// If all of the items in the dash pattern are zeros, then we shouldn't attempt to render it.
|
|
173
|
+
// This causes Core Animation to have extremely poor performance for some reason, even though
|
|
174
|
+
// it doesn't affect the appearance of the animation.
|
|
175
|
+
// - We check for `== 0.01` instead of `== 0` because `dashPattern.shapeLayerConfiguration`
|
|
176
|
+
// converts all `0` values to `0.01` to work around a different Core Animation rendering issue.
|
|
177
|
+
var isSupportedLayerDashPattern: Bool {
|
|
178
|
+
!allSatisfy { $0 == 0.01 }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -172,13 +172,14 @@ extension Animation {
|
|
|
172
172
|
///
|
|
173
173
|
public static func loadedFrom(
|
|
174
174
|
url: URL,
|
|
175
|
+
session: URLSession = .shared,
|
|
175
176
|
closure: @escaping Animation.DownloadClosure,
|
|
176
177
|
animationCache: AnimationCacheProvider?)
|
|
177
178
|
{
|
|
178
179
|
if let animationCache = animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
|
|
179
180
|
closure(animation)
|
|
180
181
|
} else {
|
|
181
|
-
let task =
|
|
182
|
+
let task = session.dataTask(with: url) { data, _, error in
|
|
182
183
|
guard error == nil, let jsonData = data else {
|
|
183
184
|
DispatchQueue.main.async {
|
|
184
185
|
closure(nil)
|
|
@@ -996,6 +996,7 @@ final public class AnimationView: AnimationViewBase {
|
|
|
996
996
|
let coreAnimationLayer = try CoreAnimationLayer(
|
|
997
997
|
animation: animation,
|
|
998
998
|
imageProvider: imageProvider.cachedImageProvider,
|
|
999
|
+
textProvider: textProvider,
|
|
999
1000
|
fontProvider: fontProvider,
|
|
1000
1001
|
compatibilityTrackerMode: .track,
|
|
1001
1002
|
logger: logger)
|
|
@@ -1030,6 +1031,7 @@ final public class AnimationView: AnimationViewBase {
|
|
|
1030
1031
|
let coreAnimationLayer = try CoreAnimationLayer(
|
|
1031
1032
|
animation: animation,
|
|
1032
1033
|
imageProvider: imageProvider.cachedImageProvider,
|
|
1034
|
+
textProvider: textProvider,
|
|
1033
1035
|
fontProvider: fontProvider,
|
|
1034
1036
|
compatibilityTrackerMode: .abort,
|
|
1035
1037
|
logger: logger)
|
|
@@ -19,6 +19,7 @@ final class AutomaticEngineTests: XCTestCase {
|
|
|
19
19
|
let animationLayer = try XCTUnwrap(CoreAnimationLayer(
|
|
20
20
|
animation: animation,
|
|
21
21
|
imageProvider: BundleImageProvider(bundle: Bundle.main, searchPath: nil),
|
|
22
|
+
textProvider: DefaultTextProvider(),
|
|
22
23
|
fontProvider: DefaultFontProvider(),
|
|
23
24
|
compatibilityTrackerMode: .track,
|
|
24
25
|
logger: .shared))
|
|
@@ -22,6 +22,9 @@ struct SnapshotConfiguration {
|
|
|
22
22
|
/// A custom `AnimationImageProvider` to use when rendering this animation
|
|
23
23
|
var customImageProvider: AnimationImageProvider?
|
|
24
24
|
|
|
25
|
+
/// A custom `AnimationTextProvider` to use when rendering this animation
|
|
26
|
+
var customTextProvider: AnimationTextProvider?
|
|
27
|
+
|
|
25
28
|
/// A custom `AnimationFontProvider` to use when rendering this animation
|
|
26
29
|
var customFontProvider: AnimationFontProvider?
|
|
27
30
|
|
|
@@ -44,7 +47,6 @@ extension SnapshotConfiguration {
|
|
|
44
47
|
"Nonanimating/FirstText": .precision(0.99),
|
|
45
48
|
"Nonanimating/verifyLineHeight": .precision(0.99),
|
|
46
49
|
"Nonanimating/blend_mode_test": .precision(0.99),
|
|
47
|
-
"Issues/issue_885": .precision(0.99),
|
|
48
50
|
|
|
49
51
|
/// Test cases for the `AnimationKeypath` / `AnyValueProvider` system
|
|
50
52
|
"Nonanimating/keypathTest": .customValueProviders([
|
|
@@ -70,6 +72,9 @@ extension SnapshotConfiguration {
|
|
|
70
72
|
// Test cases for `AnimatedImageProvider`
|
|
71
73
|
"Nonanimating/_dog": .customImageProvider(HardcodedImageProvider(imageName: "Samples/Images/dog.png")),
|
|
72
74
|
|
|
75
|
+
// Test cases for `AnimatedTextProvider`
|
|
76
|
+
"Issues/issue_1722": .customTextProvider(HardcodedTextProvider(text: "Bounce-bounce")),
|
|
77
|
+
|
|
73
78
|
// Test cases for `AnimationFontProvider`
|
|
74
79
|
"Nonanimating/Text_Glyph": .customFontProvider(HardcodedFontProvider(font: UIFont(name: "Chalkduster", size: 36)!)),
|
|
75
80
|
|
|
@@ -128,6 +133,15 @@ extension SnapshotConfiguration {
|
|
|
128
133
|
return configuration
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
static func customTextProvider(
|
|
137
|
+
_ customTextProvider: AnimationTextProvider)
|
|
138
|
+
-> SnapshotConfiguration
|
|
139
|
+
{
|
|
140
|
+
var configuration = SnapshotConfiguration.default
|
|
141
|
+
configuration.customTextProvider = customTextProvider
|
|
142
|
+
return configuration
|
|
143
|
+
}
|
|
144
|
+
|
|
131
145
|
/// A `SnapshotConfiguration` value using the given custom value providers
|
|
132
146
|
static func customFontProvider(
|
|
133
147
|
_ customFontProvider: AnimationFontProvider)
|
|
@@ -256,6 +256,10 @@ extension SnapshotConfiguration {
|
|
|
256
256
|
animationView.imageProvider = customImageProvider
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
if let customTextProvider = snapshotConfiguration.customTextProvider {
|
|
260
|
+
animationView.textProvider = customTextProvider
|
|
261
|
+
}
|
|
262
|
+
|
|
259
263
|
if let customFontProvider = snapshotConfiguration.customFontProvider {
|
|
260
264
|
animationView.fontProvider = customFontProvider
|
|
261
265
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Created by Igor Katselenbogen on 08/19/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import Lottie
|
|
5
|
+
|
|
6
|
+
// MARK: - HardcodedTextProvider
|
|
7
|
+
|
|
8
|
+
/// An `AnimationTextProvider` that always returns a specific hardcoded text
|
|
9
|
+
class HardcodedTextProvider: AnimationTextProvider {
|
|
10
|
+
|
|
11
|
+
// MARK: Lifecycle
|
|
12
|
+
|
|
13
|
+
init(text: String) {
|
|
14
|
+
self.text = text
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// MARK: Internal
|
|
18
|
+
|
|
19
|
+
func textFor(keypathName _: String, sourceText _: String) -> String {
|
|
20
|
+
text
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: Private
|
|
24
|
+
|
|
25
|
+
private let text: String
|
|
26
|
+
|
|
27
|
+
}
|
package/lottie-ios.podspec
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lottie-ios",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.3",
|
|
4
4
|
"description": "Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as json with bodymovin and renders the vector animations natively on mobile and through React Native!",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|