FilepathImageProvider.macOS.swift 2.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
//
//  FilepathImageProvider.swift
//  lottie-swift
//
//  Created by Brandon Withrow on 2/1/19.
//

#if os(macOS)
import AppKit

/// An `AnimationImageProvider` that provides images by name from a specific filepath.
public class FilepathImageProvider: AnimationImageProvider {

  // MARK: Lifecycle

  /// Initializes an image provider with a specific filepath.
  ///
  /// - Parameter filepath: The absolute filepath containing the images.
  /// - Parameter contentsGravity: The contents gravity to use when rendering the images.
  ///
  public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = URL(fileURLWithPath: filepath)
    self.contentsGravity = contentsGravity
  }

  /// Initializes an image provider with a specific filepath.
  ///
  /// - Parameter filepath: The absolute filepath containing the images.
  /// - Parameter contentsGravity: The contents gravity to use when rendering the images.
  ///
  public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = filepath
    self.contentsGravity = contentsGravity
  }

  // MARK: Public

  public func imageForAsset(asset: ImageAsset) -> CGImage? {
    if
      asset.name.hasPrefix("data:"),
      let url = URL(string: asset.name),
      let data = try? Data(contentsOf: url),
      let image = NSImage(data: data)
    {
      return image.lottie_CGImage
    }

    let directPath = filepath.appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: directPath) {
      return NSImage(contentsOfFile: directPath)?.lottie_CGImage
    }

    let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: pathWithDirectory) {
      return NSImage(contentsOfFile: pathWithDirectory)?.lottie_CGImage
    }

    LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle")
    return nil
  }

  public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity {
    contentsGravity
  }

  // MARK: Internal

  let filepath: URL
  let contentsGravity: CALayerContentsGravity
}

extension FilepathImageProvider: Equatable {
  public static func ==(_ lhs: FilepathImageProvider, _ rhs: FilepathImageProvider) -> Bool {
    lhs.filepath == rhs.filepath
  }
}

extension NSImage {
  @nonobjc
  var lottie_CGImage: CGImage? {
    guard let imageData = tiffRepresentation else { return nil }
    guard let sourceData = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil }
    return CGImageSourceCreateImageAtIndex(sourceData, 0, nil)
  }
}
#endif