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) -> Void in decodeYUVAToRGBA(bytes, pixelData, Int32(width), Int32(height), Int32(bytesPerRow)) } case .argb: data.withUnsafeBytes { (bytes: UnsafePointer) -> 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 }) } } }