123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- //
- // PDFGenerator.swift
- // PDFGenerator
- //
- // Created by Suguru Kishimoto on 2016/02/04.
- //
- //
- import Foundation
- import UIKit
- /// PDFGenerator
- public final class PDFGenerator {
- fileprivate typealias Process = () throws -> Void
-
- /// Avoid creating instance.
- fileprivate init() {}
-
- /**
- Generate from page object.
-
- - parameter page: A `PDFPage`'s object.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ page: PDFPage, to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate([page], to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from page objects.
-
- - parameter pages: Array of `PDFPage`'s objects.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ pages: [PDFPage], to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- guard !pages.isEmpty else {
- throw PDFGenerateError.emptyPage
- }
- guard !path.isEmptyPath else {
- throw PDFGenerateError.emptyOutputPath
- }
- do {
- try render(to: path, password: password) {
- try render(pages, dpi: dpi)
- }
- } catch let error {
- _ = try? FileManager.default.removeItem(at: path.url)
- throw error
- }
- }
-
- /**
- Generate from view.
-
- - parameter view: A view
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ view: UIView, to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate([view], to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from views.
-
- - parameter views: Array of views.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ views: [UIView], to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate(PDFPage.pages(views), to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from image.
-
- - parameter image: An image.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ image: UIImage, to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate([image], to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from images.
-
- - parameter images: Array of images.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ images: [UIImage], to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate(PDFPage.pages(images), to: path, dpi: dpi, password: password)
- }
- /**
- Generate from image path.
-
- - parameter imagePath: An image path.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ imagePath: String, to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate([imagePath], to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from image paths.
-
- - parameter imagePaths: Arrat of image paths.
- - parameter outputPath: An outputPath to save PDF.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
- */
- public class func generate(_ imagePaths: [String], to path: FilePathConvertible, dpi: DPIType = .default, password: PDFPassword = "") throws {
- try generate(PDFPage.pages(imagePaths), to: path, dpi: dpi, password: password)
- }
-
- /**
- Generate from page object.
-
- - parameter page: A `PDFPage`'s object.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by page: PDFPage, dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: [page], dpi: dpi, password: password)
- }
- /**
- Generate from page objects.
-
- - parameter pages: Array of `PDFPage`'s objects.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by pages: [PDFPage], dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- guard !pages.isEmpty else {
- throw PDFGenerateError.emptyPage
- }
- return try rendered(with: password) { try render(pages, dpi: dpi) }
- }
- /**
- Generate from view.
-
- - parameter view: A view
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by view: UIView, dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: [view], dpi: dpi, password: password)
- }
- /**
- Generate from views.
-
- - parameter views: Array of views.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by views: [UIView], dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: PDFPage.pages(views), dpi: dpi, password: password)
- }
-
- /**
- Generate from image.
-
- - parameter image: An image.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by image: UIImage, dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: [image], dpi: dpi, password: password)
- }
- /**
- Generate from images.
-
- - parameter images: Array of images.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by images: [UIImage], dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: PDFPage.pages(images), dpi: dpi, password: password)
- }
-
- /**
- Generate from image path.
-
- - parameter imagePath: An image path.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by imagePath: String, dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: [imagePath], dpi: dpi, password: password)
- }
-
- /**
- Generate from image paths.
-
- - parameter imagePaths: Arrat of image paths.
-
- - throws: A `PDFGenerateError` thrown if some error occurred.
-
- - returns: PDF's binary data (NSData)
- */
-
- public class func generated(by imagePaths: [String], dpi: DPIType = .default, password: PDFPassword = "") throws -> Data {
- return try generated(by: PDFPage.pages(imagePaths), dpi: dpi, password: password)
- }
- }
- // MARK: Private Extension
- /// PDFGenerator private extensions (render processes)
- private extension PDFGenerator {
- class func render(_ page: PDFPage, dpi: DPIType) throws {
- let scaleFactor = dpi.scaleFactor
-
- try autoreleasepool {
- switch page {
- case .whitePage(let size):
- let view = UIView(frame: CGRect(origin: .zero, size: size))
- view.backgroundColor = .white
- try view.renderPDFPage(scaleFactor: scaleFactor)
- case .view(let view):
- try view.renderPDFPage(scaleFactor: scaleFactor)
- case .image(let image):
- try image.asUIImage().renderPDFPage(scaleFactor: scaleFactor)
- case .imagePath(let ip):
- try ip.asUIImage().renderPDFPage(scaleFactor: scaleFactor)
- case .binary(let data):
- try data.asUIImage().renderPDFPage(scaleFactor: scaleFactor)
- case .imageRef(let cgImage):
- try cgImage.asUIImage().renderPDFPage(scaleFactor: scaleFactor)
- }
- }
- }
-
- class func render(_ pages: [PDFPage], dpi: DPIType) throws {
- try pages.forEach { try render($0, dpi: dpi) }
- }
-
- class func render(to path: FilePathConvertible, password: PDFPassword, process: Process) rethrows {
- try { try password.verify() }()
- UIGraphicsBeginPDFContextToFile(path.path, .zero, password.toDocumentInfo())
- try process()
- UIGraphicsEndPDFContext()
- }
-
- class func rendered(with password: PDFPassword, process: Process) rethrows -> Data {
- try { try password.verify() }()
- let data = NSMutableData()
- UIGraphicsBeginPDFContextToData(data, .zero, password.toDocumentInfo())
- try process()
- UIGraphicsEndPDFContext()
- return data as Data
- }
- }
|