Swiftgram/submodules/AnimatedStickerNode/Sources/SoftwareAnimationRenderer.swift
2020-10-30 17:24:56 +04:00

91 lines
3.6 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import YuvConversion
final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
private var highlightedContentNode: ASDisplayNode?
private var highlightedColor: UIColor?
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) {
queue.async { [weak self] in
switch type {
case .argb:
let calculatedBytesPerRow = (4 * Int(width) + 15) & (~15)
assert(bytesPerRow == calculatedBytesPerRow)
case .yuva:
break
}
let image = generateImagePixel(CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, pixelGenerator: { _, pixelData, bytesPerRow in
switch type {
case .yuva:
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
decodeYUVAToRGBA(bytes, pixelData, Int32(width), Int32(height), Int32(bytesPerRow))
}
case .argb:
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
memcpy(pixelData, bytes, data.count)
}
}
})
Queue.mainQueue().async {
self?.contents = image?.cgImage
self?.updateHighlightedContentNode()
completion()
}
}
}
private func updateHighlightedContentNode() {
guard let highlightedContentNode = self.highlightedContentNode, let highlightedColor = self.highlightedColor, let contents = self.contents, CFGetTypeID(contents as CFTypeRef) == CGImage.typeID else {
return
}
(highlightedContentNode.view as! UIImageView).image = UIImage(cgImage: contents as! CGImage).withRenderingMode(.alwaysTemplate)
highlightedContentNode.tintColor = highlightedColor
}
func setOverlayColor(_ color: UIColor?, animated: Bool) {
var updated = false
if let current = self.highlightedColor, let color = color {
updated = !current.isEqual(color)
} else if (self.highlightedColor != nil) != (color != nil) {
updated = true
}
if !updated {
return
}
self.highlightedColor = color
if let _ = color {
if let highlightedContentNode = self.highlightedContentNode {
highlightedContentNode.alpha = 1.0
} else {
let highlightedContentNode = ASDisplayNode(viewBlock: {
return UIImageView()
}, didLoad: nil)
highlightedContentNode.displaysAsynchronously = false
self.highlightedContentNode = highlightedContentNode
highlightedContentNode.frame = self.bounds
self.addSubnode(highlightedContentNode)
}
self.updateHighlightedContentNode()
} else if let highlightedContentNode = self.highlightedContentNode {
highlightedContentNode.alpha = 0.0
highlightedContentNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, completion: { [weak self] completed in
guard let strongSelf = self, completed else {
return
}
strongSelf.highlightedContentNode?.removeFromSupernode()
strongSelf.highlightedContentNode = nil
})
}
}
}