-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update text provider API to use full AnimationKeypath values #2183
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,12 @@ final class TextCompositionLayer: CompositionLayer { | |
|
||
// MARK: Lifecycle | ||
|
||
init(textLayer: TextLayerModel, textProvider: AnimationTextProvider, fontProvider: AnimationFontProvider) { | ||
init( | ||
textLayer: TextLayerModel, | ||
textProvider: AnimationKeypathTextProvider, | ||
fontProvider: AnimationFontProvider, | ||
rootAnimationLayer: MainThreadAnimationLayer?) | ||
{ | ||
var rootNode: TextAnimatorNode? | ||
for animator in textLayer.animators { | ||
rootNode = TextAnimatorNode(parentNode: rootNode, textAnimator: animator) | ||
|
@@ -57,6 +62,7 @@ final class TextCompositionLayer: CompositionLayer { | |
|
||
self.textProvider = textProvider | ||
self.fontProvider = fontProvider | ||
self.rootAnimationLayer = rootAnimationLayer | ||
|
||
super.init(layer: textLayer, size: .zero) | ||
contentsLayer.addSublayer(self.textLayer) | ||
|
@@ -92,8 +98,18 @@ final class TextCompositionLayer: CompositionLayer { | |
let textDocument: KeyframeInterpolator<TextDocument>? | ||
|
||
let textLayer = CoreTextRenderLayer() | ||
var textProvider: AnimationTextProvider | ||
var textProvider: AnimationKeypathTextProvider | ||
var fontProvider: AnimationFontProvider | ||
weak var rootAnimationLayer: MainThreadAnimationLayer? | ||
|
||
lazy var fullAnimationKeypath: AnimationKeypath = { | ||
// Individual layers don't know their full keypaths, so we have to delegate | ||
// to the `MainThreadAnimationLayer` to search the layer hierarchy and find | ||
// the full keypath (which includes this layer's parent layers) | ||
rootAnimationLayer?.keypath(for: self) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was tricky -- I suppose this is why the Main Thread rendering engine didn't previously work like this |
||
// If that failed for some reason, just use the last path component (which we do have here) | ||
?? AnimationKeypath(keypath: keypathName) | ||
}() | ||
|
||
override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) { | ||
guard let textDocument = textDocument else { return } | ||
|
@@ -108,11 +124,23 @@ final class TextCompositionLayer: CompositionLayer { | |
|
||
// Get Text Attributes | ||
let text = textDocument.value(frame: frame) as! TextDocument | ||
|
||
// Prior to Lottie 4.3.0 the Main Thread rendering engine always just used `LegacyAnimationTextProvider` | ||
// and called it with the `keypathName` (only the last path component of the full keypath). | ||
// Starting in Lottie 4.3.0 we use `AnimationKeypathTextProvider` instead if implemented. | ||
let textString: String | ||
if let keypathTextValue = textProvider.text(for: fullAnimationKeypath, sourceText: text.text) { | ||
textString = keypathTextValue | ||
} else if let legacyTextProvider = textProvider as? LegacyAnimationTextProvider { | ||
textString = legacyTextProvider.textFor(keypathName: keypathName, sourceText: text.text) | ||
} else { | ||
textString = text.text | ||
} | ||
|
||
let strokeColor = rootNode?.textOutputNode.strokeColor ?? text.strokeColorData?.cgColorValue | ||
let strokeWidth = rootNode?.textOutputNode.strokeWidth ?? CGFloat(text.strokeWidth ?? 0) | ||
let tracking = (CGFloat(text.fontSize) * (rootNode?.textOutputNode.tracking ?? CGFloat(text.tracking))) / 1000.0 | ||
let matrix = rootNode?.textOutputNode.xform ?? CATransform3DIdentity | ||
let textString = textProvider.textFor(keypathName: keypathName, sourceText: text.text) | ||
let ctFont = fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize)) | ||
|
||
// Set all of the text layer options | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,6 +115,12 @@ extension KeypathSearchable { | |
return nil | ||
} | ||
|
||
/// Searches this layer's keypaths to find the keypath for the given layer | ||
func keypath(for layer: CALayer) -> AnimationKeypath? { | ||
let allKeypaths = layerKeypaths() | ||
return allKeypaths[layer] | ||
} | ||
|
||
/// Computes the list of animation keypaths that descend from this layer | ||
func allKeypaths(for keyPath: AnimationKeypath? = nil) -> [String] { | ||
var allKeypaths: [String] = [] | ||
|
@@ -138,6 +144,30 @@ extension KeypathSearchable { | |
|
||
return allKeypaths | ||
} | ||
|
||
/// Computes the list of animation keypaths that descend from this layer | ||
func layerKeypaths(for keyPath: AnimationKeypath? = nil) -> [CALayer: AnimationKeypath] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adapted from the |
||
var allKeypaths: [CALayer: AnimationKeypath] = [:] | ||
|
||
let newKeypath: AnimationKeypath | ||
if let previousKeypath = keyPath { | ||
newKeypath = previousKeypath.appendingKey(keypathName) | ||
} else { | ||
newKeypath = AnimationKeypath(keys: [keypathName]) | ||
} | ||
|
||
if let layer = self as? CALayer { | ||
allKeypaths[layer] = newKeypath | ||
} | ||
|
||
for child in childKeypaths { | ||
for (layer, keypath) in child.layerKeypaths(for: newKeypath) { | ||
allKeypaths[layer] = keypath | ||
} | ||
} | ||
|
||
return allKeypaths | ||
} | ||
} | ||
|
||
extension AnimationKeypath { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found and fixed an unrelated bug where the Main Thread rendering engine didn't correctly track and update text layers included in
PreCompositionLayer
s.