unioil-loyalty-rn-app/ios/Pods/lottie-ios/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift

162 lines
4.1 KiB
Swift

//
// LayerContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/22/19.
//
import Foundation
import QuartzCore
// MARK: - CompositionLayer
/// The base class for a child layer of CompositionContainer
class CompositionLayer: CALayer, KeypathSearchable {
// MARK: Lifecycle
init(layer: LayerModel, size: CGSize) {
transformNode = LayerTransformNode(transform: layer.transform)
if let masks = layer.masks?.filter({ $0.mode != .none }), !masks.isEmpty {
maskLayer = MaskContainerLayer(masks: masks)
} else {
maskLayer = nil
}
matteType = layer.matte
inFrame = layer.inFrame.cgFloat
outFrame = layer.outFrame.cgFloat
timeStretch = layer.timeStretch.cgFloat
startFrame = layer.startTime.cgFloat
keypathName = layer.name
childKeypaths = [transformNode.transformProperties]
super.init()
anchorPoint = .zero
actions = [
"opacity" : NSNull(),
"transform" : NSNull(),
"bounds" : NSNull(),
"anchorPoint" : NSNull(),
"sublayerTransform" : NSNull(),
]
contentsLayer.anchorPoint = .zero
contentsLayer.bounds = CGRect(origin: .zero, size: size)
contentsLayer.actions = [
"opacity" : NSNull(),
"transform" : NSNull(),
"bounds" : NSNull(),
"anchorPoint" : NSNull(),
"sublayerTransform" : NSNull(),
"hidden" : NSNull(),
]
compositingFilter = layer.blendMode.filterName
addSublayer(contentsLayer)
if let maskLayer = maskLayer {
contentsLayer.mask = maskLayer
}
name = layer.name
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? CompositionLayer else {
fatalError("Wrong Layer Class")
}
transformNode = layer.transformNode
matteType = layer.matteType
inFrame = layer.inFrame
outFrame = layer.outFrame
timeStretch = layer.timeStretch
startFrame = layer.startFrame
keypathName = layer.keypathName
childKeypaths = [transformNode.transformProperties]
maskLayer = nil
super.init(layer: layer)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Internal
weak var layerDelegate: CompositionLayerDelegate?
let transformNode: LayerTransformNode
let contentsLayer = CALayer()
let maskLayer: MaskContainerLayer?
let matteType: MatteType?
let inFrame: CGFloat
let outFrame: CGFloat
let startFrame: CGFloat
let timeStretch: CGFloat
// MARK: Keypath Searchable
let keypathName: String
final var childKeypaths: [KeypathSearchable]
var renderScale: CGFloat = 1 {
didSet {
updateRenderScale()
}
}
var matteLayer: CompositionLayer? {
didSet {
if let matte = matteLayer {
if let type = matteType, type == .invert {
mask = InvertedMatteLayer(inputMatte: matte)
} else {
mask = matte
}
} else {
mask = nil
}
}
}
var keypathProperties: [String: AnyNodeProperty] {
[:]
}
var keypathLayer: CALayer? {
contentsLayer
}
final func displayWithFrame(frame: CGFloat, forceUpdates: Bool) {
transformNode.updateTree(frame, forceUpdates: forceUpdates)
let layerVisible = frame.isInRangeOrEqual(inFrame, outFrame)
/// Only update contents if current time is within the layers time bounds.
if layerVisible {
displayContentsWithFrame(frame: frame, forceUpdates: forceUpdates)
maskLayer?.updateWithFrame(frame: frame, forceUpdates: forceUpdates)
}
contentsLayer.transform = transformNode.globalTransform
contentsLayer.opacity = transformNode.opacity
contentsLayer.isHidden = !layerVisible
layerDelegate?.frameUpdated(frame: frame)
}
func displayContentsWithFrame(frame _: CGFloat, forceUpdates _: Bool) {
/// To be overridden by subclass
}
func updateRenderScale() {
contentsScale = renderScale
}
}
// MARK: - CompositionLayerDelegate
protocol CompositionLayerDelegate: AnyObject {
func frameUpdated(frame: CGFloat)
}