Skip to content

Commit

Permalink
Merge branch 'release/1.5.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
philprime committed Jun 6, 2019
2 parents 12df838 + c284e14 commit 9c12812
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 21 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Change Log

## [Unreleased](https://github.com/techprimate/TPPDF/tree/HEAD) (2019-??-??)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/1.5.0...HEAD)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/1.5.1...HEAD)

**Implemented enhancements:**

Expand All @@ -11,6 +11,17 @@

**Merged pull requests:**

## [1.5.1](https://github.com/techprimate/TPPDF/tree/1.5.1) (2019-06-06)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/1.5.0...1.5.1)

**Implemented enhancements:**

- Added merge/combining of multiple documents (Issue #67)

**Closed issues:**

- #67

## [1.5.0](https://github.com/techprimate/TPPDF/tree/1.5.0) (2019-06-05)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/1.4.1...1.5.0)

Expand Down
29 changes: 21 additions & 8 deletions Example/TPPDF/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@ class ViewController: UIViewController {
}

func generateTestPDF() {
let document = PDFDocument(format: .a4)
let document1 = PDFDocument(format: .a4)
for i in 0..<100 {
document1.add(text: "DOC 1 - \(i)")
}

let document2 = PDFDocument(format: .a5)
for i in 0..<100 {
document2.add(text: "DOC 2 - \(i)")
}

do {
let startTime = CFAbsoluteTimeGetCurrent() * 1000
// Generate PDF file and save it in a temporary file. This returns the file URL to the temporary file
let url = try PDFGenerator.generateURL(document: document, filename: "Example.pdf", progress: {
(progressValue: CGFloat) in
print("progress: ", progressValue)
let url = try PDFGenerator.generateURL(documents: [document1, document2], filename: "Example.pdf", progress: { (docIndex: Int, progressValue: CGFloat, totalProgressValue: CGFloat) in
print("doc:", docIndex, "progress:", progressValue, "total:", totalProgressValue)
})
let endTime = CFAbsoluteTimeGetCurrent() * 1000
print("Duration: \(floor(endTime - startTime)) ms")
Expand Down Expand Up @@ -402,6 +409,11 @@ class ViewController: UIViewController {
document.add(.headerRight, textObject: PDFSimpleText(text: "Header Right 2"))
document.add(.headerRight, textObject: PDFSimpleText(text: "Header Right 3"))

// Create a second document and combine them

let secondDocument = PDFDocument(format: .a6)
secondDocument.add(text: "This is a brand new document with a different format!")

/* ---- Execution Metrics ---- */
print("Preparation took: " + stringFromTimeInterval(interval: CFAbsoluteTimeGetCurrent() - startTime))
startTime = CFAbsoluteTimeGetCurrent()
Expand All @@ -413,10 +425,11 @@ class ViewController: UIViewController {

do {
// Generate PDF file and save it in a temporary file. This returns the file URL to the temporary file
let url = try PDFGenerator.generateURL(document: document, filename: "Example.pdf", progress: {
(progressValue: CGFloat) in
print("progress: ", progressValue)
}, debug: true)
let url = try PDFGenerator.generateURL(documents: [document, secondDocument],
filename: "Example.pdf",
progress: { (docIndex: Int, progressValue: CGFloat, totalProgressValue: CGFloat) in
print("doc:", docIndex, "progress:", progressValue, "total:", totalProgressValue)
})

// Load PDF into a webview from the temporary file
(self.view as? UIWebView)?.loadRequest(URLRequest(url: url))
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,26 @@ try PDFGenerator.generate(document: document, to: url, progress: { progress in
}, debug: false)
```

#### Multiple Documents

If you want to combine multiple `PDFDocument` into a single PDF file, use the alternative methods to the ones in the previous section, taking multiple `documents` as a parameter.

The progress will now return three values:

- the current document index
- the progress of the current document
- sum of total progress

**Example:**

```swift
let url = try PDFGenerator.generateURL(documents: [
document1, document2
], filename: "Example.pdf", progress: { (docIndex: Int, progressValue: CGFloat, totalProgressValue: CGFloat) in
print("doc:", docIndex, "progress:", progressValue, "total:", totalProgressValue)
})
```

#### Debug

If you want to enable a debug overlay, set the flag `debug` in `PDFGenerator.generate(..)`, `PDFGenerator.generateURL(..)` or `PDFGenerator.generateData(..)` to `true` and it will add colored outlines of the elements in you document.
Expand Down
26 changes: 24 additions & 2 deletions Source/Layout/Groups/PDFGroupObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ internal class PDFGroupObject: PDFObject {
*/
internal var objects: [(container: PDFGroupContainer, object: PDFObject)]

/**
TODO: Documentation
*/
internal var isFullPage: Bool

/**
TODO: Documentation
*/
Expand Down Expand Up @@ -53,13 +58,15 @@ internal class PDFGroupObject: PDFObject {
*/
internal init(objects: [(container: PDFGroupContainer, object: PDFObject)],
allowsBreaks: Bool,
isFullPage: Bool,
backgroundColor: UIColor?,
backgroundImage: PDFImage?,
backgroundShape: PDFDynamicGeometryShape?,
outline: PDFLineStyle,
padding: UIEdgeInsets) {
self.objects = objects
self.allowsBreaks = allowsBreaks
self.isFullPage = isFullPage
self.backgroundColor = backgroundColor
self.backgroundImage = backgroundImage
self.backgroundShape = backgroundShape
Expand Down Expand Up @@ -97,7 +104,14 @@ internal class PDFGroupObject: PDFObject {
result += calcResult
}

self.frame = calculateFrame(objects: result)
if isFullPage {
self.frame = generator.document.layout.bounds.inset(by: UIEdgeInsets(top: generator.layout.margin.top,
left: generator.layout.margin.left,
bottom: generator.layout.margin.bottom,
right: generator.layout.margin.right))
} else {
self.frame = calculateFrame(objects: result)
}
generator.layout.heights.add(padding.bottom, to: container)
generator.currentPadding = .zero

Expand All @@ -120,7 +134,14 @@ internal class PDFGroupObject: PDFObject {
result += try object.calculate(generator: generator, container: container.contentContainer)
}

self.frame = calculateFrame(objects: result)
if isFullPage {
self.frame = generator.document.layout.bounds.inset(by: UIEdgeInsets(top: generator.layout.margin.top,
left: generator.layout.margin.left,
bottom: generator.layout.margin.bottom,
right: generator.layout.margin.right))
} else {
self.frame = calculateFrame(objects: result)
}
generator.layout.heights.add(padding.bottom, to: container)
generator.currentPadding = .zero

Expand Down Expand Up @@ -176,6 +197,7 @@ internal class PDFGroupObject: PDFObject {
override internal var copy: PDFObject {
return PDFGroupObject(objects: self.objects.map { ($0, $1.copy) },
allowsBreaks: self.allowsBreaks,
isFullPage: self.isFullPage,
backgroundColor: self.backgroundColor,
backgroundImage: self.backgroundImage?.copy,
backgroundShape: self.backgroundShape,
Expand Down
6 changes: 5 additions & 1 deletion Source/Layout/Groups/PDFMasterGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ import UIKit
*/
public class PDFMasterGroup: PDFGroup {

public var isFullPage: Bool

/**
TODO: Documentation
*/
public init() {
public init(isFullPage: Bool = false) {
self.isFullPage = isFullPage

super.init(allowsBreaks: false)
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Layout/PDFPageBreakObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ internal class PDFPageBreakObject: PDFObject {
*/
override internal func draw(generator: PDFGenerator, container: PDFContainer) throws {
if !stayOnSamePage {
UIGraphicsBeginPDFPage()
UIGraphicsBeginPDFPageWithInfo(generator.document.layout.bounds, nil)
generator.drawDebugPageOverlay()
}
}
Expand Down
4 changes: 3 additions & 1 deletion Source/PDFDocument+Objects.swift
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ public extension PDFDocument {
func add(_ container: PDFContainer = PDFContainer.contentLeft, group: PDFGroup) {
objects += [(container, PDFGroupObject(objects: group.objects,
allowsBreaks: group.allowsBreaks,
isFullPage: false,
backgroundColor: group.backgroundColor,
backgroundImage: group.backgroundImage,
backgroundShape: group.backgroundShape,
Expand All @@ -353,9 +354,10 @@ public extension PDFDocument {
/**
TODO: Documentation
*/
func set(master group: PDFGroup) {
func set(master group: PDFMasterGroup) {
self.masterGroup = PDFGroupObject(objects: group.objects,
allowsBreaks: group.allowsBreaks,
isFullPage: group.isFullPage,
backgroundColor: group.backgroundColor,
backgroundImage: group.backgroundImage,
backgroundShape: group.backgroundShape,
Expand Down
121 changes: 115 additions & 6 deletions Source/PDFGenerator+Generation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ extension PDFGenerator {
- throws: PDFError
*/
public static func generateURL(document: PDFDocument, filename: String, progress: ((CGFloat) -> Void)? = nil, debug: Bool = false) throws -> URL {
public static func generateURL(document: PDFDocument,
filename: String,
progress: ((CGFloat) -> Void)? = nil,
debug: Bool = false) throws -> URL {
let name = filename.lowercased().hasSuffix(".pdf") ? filename : (filename + ".pdf")
let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(name)
let generator = PDFGenerator(document: document)
Expand All @@ -39,6 +42,35 @@ extension PDFGenerator {
return url
}

/**
Generates PDF data and writes it to a temporary file.
- parameter document: List of PDFDocument which should be concatenated and then converted into a PDF file.
- parameter filename: Name of temporary file.
- parameter progress: Optional closure for progress handling, showing the current document index, the current document progress and the total progress.
- parameter debug: Enables debugging
- returns: URL to temporary file.
- throws: PDFError
*/
public static func generateURL(documents: [PDFDocument],
filename: String,
info: PDFInfo = PDFInfo(),
progress: ((Int, CGFloat, CGFloat) -> Void)? = nil,
debug: Bool = false) throws -> URL {
assert(!documents.isEmpty, "At least one document is required!")

let name = filename.lowercased().hasSuffix(".pdf") ? filename : (filename + ".pdf")
let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(name)
UIGraphicsBeginPDFContextToFile(url.path, documents.first?.layout.bounds ?? .zero, info.generate())

try process(documents: documents, progress: progress, debug: debug)

UIGraphicsEndPDFContext()
return url
}

/**
Generates PDF data and writes it to a temporary file.
Expand All @@ -47,11 +79,12 @@ extension PDFGenerator {
- parameter progress: Optional closure for progress handling. Parameter is between 0.0 and 1.0
- parameter debug: Enables debugging
- returns: URL to temporary file.
- throws: PDFError
*/
public static func generate(document: PDFDocument, to url: URL, progress: ((CGFloat) -> Void)? = nil, debug: Bool = false) throws {
public static func generate(document: PDFDocument,
to url: URL,
progress: ((CGFloat) -> Void)? = nil,
debug: Bool = false) throws {
let generator = PDFGenerator(document: document)

generator.progressValue = 0
Expand All @@ -62,6 +95,28 @@ extension PDFGenerator {
UIGraphicsEndPDFContext()
}

/**
Generates PDF data and writes it to a temporary file.
- parameter document: List of PDFDocuments which should be concatenated and then converted into a PDF file.
- parameter to url: URL where file should be saved.
- parameter progress: Optional closure for progress handling, showing the current document index, the current document progress and the total progress.
- parameter debug: Enables debugging
- throws: PDFError
*/
public static func generate(documents: [PDFDocument],
to url: URL,
info: PDFInfo = PDFInfo(),
progress: ((Int, CGFloat, CGFloat) -> Void)? = nil,
debug: Bool = false) throws {
assert(!documents.isEmpty, "At least one document is required!")

UIGraphicsBeginPDFContextToFile(url.path, documents.first?.layout.bounds ?? .zero, info.generate())
try process(documents: documents, progress: progress, debug: debug)
UIGraphicsEndPDFContext()
}

/**
Generates PDF data and returns it
Expand All @@ -72,9 +127,10 @@ extension PDFGenerator {
- returns: PDF Data
- throws: PDFError
*/
public static func generateData(document: PDFDocument, progress: ((CGFloat) -> Void)? = nil, debug: Bool = false) throws -> Data {
public static func generateData(document: PDFDocument,
progress: ((CGFloat) -> Void)? = nil,
debug: Bool = false) throws -> Data {
let data = NSMutableData()
let generator = PDFGenerator(document: document)

Expand All @@ -88,8 +144,61 @@ extension PDFGenerator {
return data as Data
}

/**
Generates PDF data and returns it
- parameter documents: List of PDFDocument which should be concatenated and then converted into a PDF file.
- parameter progress: Optional closure for progress handling, showing the current document index, the current document progress and the total progress.
- parameter debug: Enables debugging
- returns: PDF Data
- throws: PDFError
*/
public static func generateData(documents: [PDFDocument],
info: PDFInfo = PDFInfo(),
progress: ((Int, CGFloat, CGFloat) -> Void)? = nil,
debug: Bool = false) throws -> Data {
assert(!documents.isEmpty, "At least one document is required!")

let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, documents.first?.layout.bounds ?? .zero, info.generate())
try process(documents: documents, progress: progress, debug: debug)
UIGraphicsEndPDFContext()

return data as Data
}

// MARK: - INTERNAL FUNCS

/**
Processes multiple documents and renders them into the current PDFContext
- parameter documents: List of PDFDocument to be processed
- parameter progress: Optional closure for progress handling, showing the current document index, the current document progress and the total progress.
- parameter debug: Enables debugging
- throws: PDFError
*/
internal static func process(documents: [PDFDocument], progress: ((Int, CGFloat, CGFloat) -> Void)?, debug: Bool) throws {
let objCounts = documents.map { $0.objects.count }
let objSum = CGFloat(objCounts.reduce(0, +))
let weights = objCounts.map { CGFloat($0) / objSum }

var progressValues = [CGFloat](repeating: 0, count: documents.count)
for (idx, document) in documents.enumerated() {
let generator = PDFGenerator(document: document)

generator.progressValue = 0
generator.debug = debug

try generator.generatePDFContext(progress: { value in
progressValues[idx] = value * weights[idx]
let totalProgress = progressValues.reduce(0, +)
progress?(idx, value, totalProgress)
})
}
}
/**
Generate PDF Context from PDFCommands
Expand Down
2 changes: 1 addition & 1 deletion TPPDF.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TPPDF'
s.version = '1.5.0'
s.version = '1.5.1'
s.summary = 'TPPDF is a simple-to-use PDF builder for iOS'
s.description = <<-DESC
TPPDF is an object-based PDF builder, completely built in Swift.
Expand Down

0 comments on commit 9c12812

Please sign in to comment.