TPPDF is a simple-to-use PDF builder for iOS

Overview

TPPDF

TPPDF is a fast PDF builder for iOS & macOS using simple commands to create advanced documents!

Swift iOS|macOS License
Swift Package Manager Cocoapods Carthage

Created and maintained by Philip Niedertscheider and all the amazing contributors.

FeaturesGetting StartedCommunicationUsageInstallationCreditsLicense

Features

  • Page header and footer
  • Dynamic content layout with page alignment
  • Support for tables and cell alignment
  • Attributed strings
  • Custom spacing
  • Image support
  • Horizontal line separators
  • Custom indentation
  • Custom top offset (good for layered rendering)
  • Pagination
  • Image caption
  • Compress images
  • Custom image size fit
  • Images in the header and footer
  • Horizontal line separators in the header and footer
  • Generate PDF files directly to handle large PDF files (Details)
  • PDF metadata
  • Custom table styling
  • Multi-column sections
  • Swift Package Manager Support
  • Tables with cell merging & automatic page breaking
  • Hyperlinks in text
  • Native progress tracking using Foundation.Progress
  • Documentation

Getting Started

Building a PDF document is very easy:

First, you create a document with a paperformat...

let document = PDFDocument(format: .a4)

...then you add your information to a container...

document.add(.contentCenter, text: "Create PDF documents easily.")

...then you render the document...

let generator = PDFGenerator(document: document)
let url  = try generator.generateURL(filename: "Example.pdf")

...done!

If you need more details, checkout Usage.

Communication

Attention:

TPPDF is an Open Source side-project of techprimate. As we are currently working on multiple other projects, we only have limited time for fixing bugs and enhancing TPPDF.

That's why any issue reporting and especially Pull Requests are very welcome!

If you need professional support for your company, you can reach out to @philprimes on Twitter or on our website techprimate.com! This is mainly for custom or high-priority requests, therefore we won't publish a consulting pricing for now.

For everything else, please see Communication and this message. Thank you!

  • If you need help, use Stack Overflow. (Tag 'TPPDF') Just open up another issue, it might lead to better documentation.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Example

Take a look at the Getting Started Guide or checkout the Examples (using of one of the following):

  • Clone the repository and look at the Example folders
  • Run pod try TPPDF

Apps using TPPDF

If you are using TPPDF in your app and want to be listed here, simply create a pull request or let us know on Twitter or via GitHub. We are always curious to see, who is using our project :)

Burnout Coach - by Stéphane Mégy

Burnout Coach

ChatHistory - by techprimate

ChatHistory

Hikingbook - by Zheng-Xiang Ke

Hikingbook

Bug Journal - by David Johnson

Bug Journal

Energy Tracker - by Stefan Nebel

Energy Tracker

Credits

TPPDF is created and maintained by Philip Niedertscheider, founder of techprimate.

techprimate.com twitter facebook facebook

Contributors

Please consider backing this project by using the following GitHub Sponsor button.

We want to thank all contributors for their effort!

License

TPPDF is available under the MIT license. See the LICENSE file for more info.

Comments
  • PDFSection overlap

    PDFSection overlap

    I'm trying with the example target provided with this project

    minimum code to reproduce the problem

    let document = PDFDocument(format: .a4)
    let section = PDFSection(columnWidths: [0.3, 0.7])
            section.columns[0].addText(.left, text: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem")
            section.columns[1].addText(.left, text: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.")
            
    document.addSection(section)
            
    document.addSection(section)
    

    simulator screen shot - ipad air 2 - 2018-05-30 at 16 57 18 simulator screen shot - ipad air 2 - 2018-05-30 at 16 57 27

    Help would be appreciated

    pending 
    opened by omiz 28
  • problem with showHeadersOnEveryPage

    problem with showHeadersOnEveryPage

    Hi , i am using TPPDF 2.2.0 and integrating in a personal iOS app i am writing . a great library , thank you but i am trying to understand showHeadersOnEveryPage when showHeadersOnEveryPage is true, the header row overwrites the top row on the next page and ends up hiding it. i don't see any properties to add space after the header row. being new, i might have overlooked something

    here are two screenshots.. without a header and with. the 20:12 entry is overwritten by the header row without header with header

    thank you Sami

    bug 
    opened by Sgkhour 24
  • Column Wrap

    Column Wrap

    Is it possible to have content wrap to the next column instead of the next page? Or to get the height of each added object (text, table, etc) so I can manually wrap object to the next column in a section?

    enhancement testing 
    opened by donnnyrewq 22
  • Getting UIGraphicsGetCurrentContext() nil

    Getting UIGraphicsGetCurrentContext() nil

    I am getting UIGraphicsGetCurrentContext() nil when the app is run in device, it works fine in simulator.

    Here's the method where UIGraphicsGetCurrentContext() is nil:

        override func draw(generator: PDFGenerator, container: PDFContainer) throws {
            if attributedString == nil {
                throw PDFError.textObjectNotCalculated
            }
    
            // Get current graphics context
            let currentContext = UIGraphicsGetCurrentContext()!
    
            // Create a core text frame setter
            let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
    
            // Save context pre manipulation
            currentContext.saveGState()
    
            // Reset text matrix, so no text scaling is affected
            currentContext.textMatrix = CGAffineTransform.identity
    
            // Create the frame and a rectangular path of the text frame
            let frameRect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
            let framePath = UIBezierPath(rect: frameRect).cgPath
    
            // Create core text frame for the given attributed string
            // The whole text should fit the frame, as calculations were already done
            let frameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributedString.length), framePath, nil)
    
            // Translate by 100% graphics height up and reverse scale, as core text does draw from bottom up and not from top down
            currentContext.translateBy(x: 0, y: UIGraphicsGetPDFContextBounds().height)
            currentContext.scaleBy(x: 1.0, y: -1.0)
    
            // Translate context to actual position of text
            currentContext.translateBy(x: frame.minX, y: UIGraphicsGetPDFContextBounds().height - frame.maxY)
    
            // Draw text into context
            CTFrameDraw(frameRef, currentContext)
    
            // Restore context to pre manipulation
            currentContext.restoreGState()
    
            // If debugging is enabled, draw a outline around the text
            if generator.debug {
                PDFGraphics.drawRect(rect: self.frame, outline: PDFLineStyle(type: .dashed, color: .red, width: 1.0), fill: .clear)
            }
        }
    

    Any help on this would be much appreciated. Thanks.

    bug help wanted 
    opened by zaeem-khatib 18
  • Blank page at the end of each batched document (external document)

    Blank page at the end of each batched document (external document)

    I am currently using the 'develop' branch in order to test adding external PDFs. While the functionality is running great I keep running into an issue were a blank page is added in the end after importing an external document.

    Here is what I am using batchPagesv2.add(externalDocument: PDFExternalDocument(url: url, pages: pages[count]))

    Whats interesting is that if I duplicate the batch job multiple times, only one extra blank page is added on the end. If I do not use external documents there is no blank page added either. So I am a bit lost as to where this page is coming from.

    So either this can be flagged as a bug or a feature suggestion to maybe make a boolean to filter out blank pages upon generation.

    bug pending 
    opened by hajjD 17
  • Dynamically Add A Page while creating a PDFDocument

    Dynamically Add A Page while creating a PDFDocument

    I am using this library to generate a PDF of content added by the user. I am using: let pdfDocument = PDFDocument(format: .a4) and then adding text, table as required.

    I wanted to know if there is a way to dynamically create a new page once content had reached the end of page one. Please advise.

    bug 
    opened by harishchopra86 14
  • Carthage Support is broken [1.5.3]

    Carthage Support is broken [1.5.3]

    At least on my end, Carthage can not build the framework for the latest release 1.5.3.

    The first error that came up was the missing shared scheme as described in #98. Unchecking and checking the box for the TPPDF scheme as described in this comment did fix the issue.

    However the framework still does not build due to a missing .plist file. Here's the error message when running carthage build --verbose --platform "iOS" --no-skip-current TPPDF:

    error: could not read data from '$(SRC_ROOT)/Carthage/Checkouts/TPPDF/Example/Pods/Target Support Files/TPPDF/TPPDF-Info.plist': The file “TPPDF-Info.plist” couldn’t be opened because there is no such file.
    

    And indeed there is no such file; The actual directory contents are:

    $ tree Target\ Support\ Files
                                                                                                                                                                                         
    Target\ Support\ Files
    ├── Nimble
    │   ├── Nimble-dummy.m
    │   ├── Nimble-prefix.pch
    │   ├── Nimble-umbrella.h
    │   ├── Nimble.modulemap
    │   └── Nimble.xcconfig
    ├── Pods-TPPDF_Example
    │   ├── Pods-TPPDF_Example-acknowledgements.markdown
    │   ├── Pods-TPPDF_Example-acknowledgements.plist
    │   ├── Pods-TPPDF_Example-dummy.m
    │   ├── Pods-TPPDF_Example-frameworks.sh
    │   ├── Pods-TPPDF_Example-umbrella.h
    │   ├── Pods-TPPDF_Example.debug.xcconfig
    │   ├── Pods-TPPDF_Example.modulemap
    │   └── Pods-TPPDF_Example.release.xcconfig
    ├── Pods-TPPDF_Tests
    │   ├── Pods-TPPDF_Tests-acknowledgements.markdown
    │   ├── Pods-TPPDF_Tests-acknowledgements.plist
    │   ├── Pods-TPPDF_Tests-dummy.m
    │   ├── Pods-TPPDF_Tests-frameworks.sh
    │   ├── Pods-TPPDF_Tests-umbrella.h
    │   ├── Pods-TPPDF_Tests.debug.xcconfig
    │   ├── Pods-TPPDF_Tests.modulemap
    │   └── Pods-TPPDF_Tests.release.xcconfig
    ├── Quick
    │   ├── Quick-dummy.m
    │   ├── Quick-prefix.pch
    │   ├── Quick-umbrella.h
    │   ├── Quick.modulemap
    │   └── Quick.xcconfig
    └── TPPDF
        ├── TPPDF-dummy.m
        ├── TPPDF-prefix.pch
        ├── TPPDF-umbrella.h
        ├── TPPDF.modulemap
        └── TPPDF.xcconfig
    

    Edit: 1.4.1 fails with the same error message (missing .plist file). But the shared TPPDF scheme is present after checkout.

    opened by mbger 13
  • no shared framework schemes

    no shared framework schemes

    Hi

    I'm new to this and i got an Error, which i think a had somewhen before. Could you please help me and fix this? ERROR: *** Skipped building TPPDF due to the error: Dependency "TPPDF" has no shared framework schemes for any of the platforms: iOS If you believe this to be an error, please file an issue with the maintainers at https://github.com/Techprimate/TPPDF/issues/new

    THANX A LOT!!!!! Reinhard

    bug 
    opened by reinhardjung 13
  • Image as NSTextAttachment gets lost

    Image as NSTextAttachment gets lost

    Hey. I try to have an image attached into the NSAttributedString but the image gets lost.

            let pdf = PDFGenerator(format: .a4)
            
            let typeDetails = NSMutableAttributedString()
            let attachment = NSTextAttachment()
            attachment.image = Img.checked
            attachment.bounds = CGRect(x: 0, y: 0, width: 10, height: 10)
            let attachmentStr = NSAttributedString(attachment: attachment)
            
            typeDetails.append( NSAttributedString(string: ">>>>>") )
            typeDetails.append(attachmentStr)
            typeDetails.append( NSAttributedString(string: "<<<<<") )
            pdf.addAttributedText(text: typeDetails)
    
    screen shot 2017-11-03 at 2 25 28 pm

    I have tried several approaches as well as several images.

    idea?

    bug wontfix 
    opened by davidseek 13
  • PDFTable Image Quality

    PDFTable Image Quality

    Hello,

    Thank you for this wonderful library. This is so helpful.

    I just want to ask if would it be possible to control the image quality on the table? 'Cause right now it kinda blurry. I would like to remain the quality of the image as possible so it won't appear blurry. Thank you in advance for your help.

    opened by yhelfronda 11
  • Table cells cut off at end of page

    Table cells cut off at end of page

    down vote favorite

    I posted this on stackoverflow, but I couldn't find a TPPDF tag to tag it with.

    I'm having a problem with a table cell being cut off at the bottom of the page when using the TPPDF cocoapod in a swift 4 app for i-pad. Only part of the cell shows with no text

    I'm creating a series of tables in my document. Because the column widths are variable I'm adding a new table for each row.

    Is there a way to either prevent this from happening or to determine when to add a page break? screen shot 2018-09-12 at 10 29 39 am

    bug pending 
    opened by ghost 11
  • Adding a header image and a PDFTable in the document header cuts off the top of the table

    Adding a header image and a PDFTable in the document header cuts off the top of the table

    ℹ Please fill out this template when filing an issue. All lines beginning with an ℹ symbol instruct you with what info we expect. You can delete those lines once you've filled in the info.

    What did you do?

    I added a banner image to the document's .headerLeft and a table in the .headerLeft. The table has an Image to the left and Text to the right of the image.

    document.add(.headerLeft, image: bannerPDFImage)
    
    document.add(.headerLeft, table: headerTable)
    

    What did you expect to happen?

    I expected to see the full image and text beneath the banner image. Instead, there's a gap between the banner image and table below, with the top of the table cut off.

    What happened instead?

    image

    TPPDF Environment

    TPPDF version: 2.5.3 Xcode version: 14.2 Swift version: 5.7

    Demo Code / Project

    From the TableExampleFactory.swift file:

    
    //
    //  TableExampleFactory.swift
    //  TPPDF_Example
    //
    //  Created by Philip Niedertscheider on 16.12.19.
    //  Copyright © 2022 techprimate GmbH. All rights reserved.
    //
    
    #if os(iOS)
    import UIKit
    #elseif os(macOS)
    import AppKit
    #endif
    
    import TPPDF
    
    class TableExampleFactory: ExampleFactory {
    
        func generateDocument() -> [PDFDocument] {
            let document = PDFDocument(format: .a4)
    
    		let headerStyle = PDFTableStyleDefaults.none
    
    		let headerTable = PDFTable(rows: 1, columns: 2)
    		headerTable.widths = [0.1, 0.9]
    		headerTable.style = headerStyle
    		
    		var tableContent : [[PDFTableContentable]] = [[PDFTableContentable]]()
    		var rowContent : [PDFTableContentable] = [PDFTableContentable]()
    		
    		if #available(macOS 12.0, *) {
    
    			let bannerImage = Image(named: "Business Logo Banner.jpg")
    			if let bannerImage = bannerImage {
    				let bannerPDFImage = PDFImage(image: bannerImage)
    				document.add(.headerLeft, image: bannerPDFImage)
    			}
    			
    			var formIcon = Image(systemSymbolName: "doc.plaintext", accessibilityDescription: "")
    			formIcon?.resizingMode = .tile
    			var config = NSImage.SymbolConfiguration(textStyle: .largeTitle,
    													 scale: .large)
    			config = config.applying(NSImage.SymbolConfiguration.preferringMulticolor())
    			formIcon = formIcon?.withSymbolConfiguration(config)
    			if let formIcon = formIcon {
    				rowContent.append(formIcon)
    			} else {
    				rowContent.append("")
    			}
    			
    			headerStyle.contentStyle = PDFTableCellStyle(
    				
    				borders: PDFTableCellBorders(left: PDFLineStyle(type: .none),
    											 top: PDFLineStyle(type: .none),
    											 right: PDFLineStyle(type: .none),
    											 bottom: PDFLineStyle(type: .none)),
    				
    				font: Font.systemFont(ofSize: 28, weight: .light)
    			)
    			
    			rowContent.append("Test Header Text Content")
    			
    			tableContent.append(rowContent)
    			headerTable.content = tableContent
    			headerTable.rows.allCellsAlignment = .left
    			document.add(.headerLeft, table: headerTable)
    			
    		} else {
    			// Fallback on earlier versions
    		}
    
    		
            // Create a table
            var table = PDFTable(rows: 34, columns: 4)
    
            // Tables can contain Strings, Numbers, Images or nil, in case you need an empty cell.
            // If you add a unknown content type, an assertion will be thrown and the rendering will stop.
            table.content = [
                [nil, "Name",      "Image",                        "Description"],
                [1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
                [2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
                [3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
                [4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
                [1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
                [2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
                [3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
                [4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    			[1,   "Waterfall", Image(named: "Image-1.jpg")!, "Water flowing down stones."],
    			[2,   "Forrest",   Image(named: "Image-2.jpg")!, "Sunlight shining through the leafs."],
    			[3,   "Fireworks", Image(named: "Image-3.jpg")!, "Fireworks exploding into 100.000 stars"],
    			[4,   "Fields",    Image(named: "Image-4.jpg")!, "Crops growing big and providing food."],
    
                [nil, nil,         nil,                            "Many beautiful places"]
            ]
            table.rows.allRowsAlignment = [.center, .left, .center, .right]
    
            // The widths of each column is proportional to the total width, set by a value between 0.0 and 1.0, representing percentage.
    
            table.widths = [
                0.1, 0.25, 0.35, 0.3
            ]
    
            // To speed up table styling, use a default and change it
    
            let style = PDFTableStyleDefaults.simple
    
            // Change standardized styles
            style.footerStyle = PDFTableCellStyle(
                colors: (
                    fill: Color(red: 0.171875,
                                  green: 0.2421875,
                                  blue: 0.3125,
                                  alpha: 1.0),
                    text: Color.white
                ),
                borders: PDFTableCellBorders(left: PDFLineStyle(type: .full),
                                             top: PDFLineStyle(type: .full),
                                             right: PDFLineStyle(type: .full),
                                             bottom: PDFLineStyle(type: .full)),
    
                font: Font.systemFont(ofSize: 10)
            )
    
            // Simply set the amount of footer and header rows
    
            style.columnHeaderCount = 1
            style.footerCount = 1
    
            table.style = style
    
            // Style each cell individually
            table[1,1].style = PDFTableCellStyle(colors: (fill: Color.yellow, text: Color.black))
    
            // Set table padding and margin
            table.padding = 5.0
            table.margin = 10.0
    
            // In case of a linebreak during rendering we want to have table headers on each page.
    
            table.showHeadersOnEveryPage = true
    
            document.add(table: table)
    
            // Another table:
    
            table = PDFTable(rows: 50, columns: 4)
            table.widths = [0.1, 0.3, 0.3, 0.3]
            table.margin = 10
            table.padding = 10
            table.showHeadersOnEveryPage = false
            table.style.columnHeaderCount = 3
    
            for row in 0..<table.size.rows {
                table[row, 0].content = "\(row)".asTableContent
                for column in 1..<table.size.columns {
                    table[row, column].content = "\(row),\(column)".asTableContent
                }
            }
    
            for i in stride(from: 3, to: 48, by: 3) {
                table[rows: i...(i + 2), column: 1].merge(with: PDFTableCell(content: Array(repeating: "\(i),1", count: 3).joined(separator: "\n").asTableContent,
                                                               alignment: .center))
            }
            for i in stride(from: 4, to: 47, by: 3) {
                table[rows: i...(i + 2), column: 2].merge(with: PDFTableCell(content: Array(repeating: "\(i),2", count: 3).joined(separator: "\n").asTableContent,
                                                               alignment: .center))
            }
            for i in stride(from: 5, to: 48, by: 3) {
                table[rows: i...(i + 2), column: 3].merge(with: PDFTableCell(content: Array(repeating: "\(i),3", count: 3).joined(separator: "\n").asTableContent,
                                                               alignment: .center))
            }
    
            table[rows: 0..<2, column: 2].merge()
            table[rows: 1..<3, column: 3].merge()
    
            document.add(table: table)
    
            return [document]
        }
    }
    
    

    and here's the banner image I added to the project for testing purposes.

    Business Logo Banner

    opened by brendand 3
  • Image in header with 0 margins along with text in header with standard margins

    Image in header with 0 margins along with text in header with standard margins

    What's the best way to get a header image to use up. the entire space of the header part of the page, ignoring the margins, while some text and a line separator in the header respects the margins?

    It seems to work for the first page, but subsequent pages the image I'm adding is being indented.

    image

    I'm using the following code to set the margins to 0 and the indentation to whatever the user has specified.

    let pdfImage = PDFImage(image: image)
    document.add(headerPosition, image: pdfImage)
    document.add(headerPosition, space: 20)
    document.layout.margin = EdgeInsets(top: 0, left: 0, bottom: reportSettings.marginBottom, right: 0)
    document.set(indent: reportSettings.marginLeft, left: true)
    document.set(indent: reportSettings.marginRight, left: false)
    document.set(.headerLeft, indent: reportSettings.marginLeft, left: true)
    document.set(.headerLeft, indent: reportSettings.marginRight, left: false)
    document.set(.footerLeft, indent: reportSettings.marginLeft, left: true)
    document.set(.footerLeft, indent: reportSettings.marginRight, left: false)
    
    opened by brendand 0
  • Footer separator line

    Footer separator line

    I want to put a separator line at the top of the footer before the body of the footer. but the divider is not at the top, but at the bottom. How should I do this? Looking forward to your reply, thanks.

    my code. let line = PDFLineStyle.init(type: .full, color: .blue, width: 1.0) document.addLineSeparator(.footerLeft, style: line) document.add(.footerLeft, textObject: PDFSimpleText(text: "Footer Left"))

    TPPDF Environment

    TPPDF version: 2.3.5 Xcode version: 14.1 Swift version: 5.2

    pending 
    opened by peterhoucll 1
  • Display total page count in UI

    Display total page count in UI

    How should the feature work?

    Is it possible to get total amount of page and display in certain place (not only in footer, header, center etc.)?

    What should it look like?

    I am trying to add this amount of page above signature place, to be sure that user had signed the document with this page count. Here is a screenshot.

    Screenshot 2022-08-31 at 22 53 56

    What happened instead?

    I can only add page numeration in foster, header etc.

    TPPDF Environment

    TPPDF version: 2.3.5 Xcode version: 13.3.1 Swift version: 5

    enhancement 
    opened by tarasChernysh 3
  • Group doesn't fit inside section column

    Group doesn't fit inside section column

    What did you do?

    I created section with 2 column. In right column we have group with images. In left - some text description. I see that group of images does not fit to right column's width (you can see that group on screenshot below with purple background color). Screenshot 2022-08-30 at 17 11 51 Screenshot 2022-08-30 at 17 12 33

    What did you expect to happen?

    Group fits to column's width. I want to create something like here Screenshot 2022-08-30 at 17 46 43

    What happened instead?

    Group crosses column border

    TPPDF Environment

    TPPDF version: 2.3.5 Xcode version: 13.3.1 Swift version: 5

    Demo Code / Project

    func generateDocument() -> [PDFDocument] {
            let textualItem  = [
                "Hello",
                "World",
                "Hello worid!"
            ]
            
            let images = [
                Image(named: "Image-2.jpg")!,
                Image(named: "Image-2.jpg")!,
                Image(named: "Image-2.jpg")!,
                Image(named: "Image-2.jpg")!,
                Image(named: "Image-2.jpg")!
            ]
            
            let items = [
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images),
                RowItem(textItems: textualItem, images: images)
            ]
            
            let document = PDFDocument(format: .a4)
            
            for item in items {
                let leftColomn = PDFSectionColumn(width: 0.4)
                let size = CGSize(width: document.layout.bounds.width, height: 200)
                let path = PDFBezierPath(ref: CGRect(origin: .zero, size: size))
                path.move(to: PDFBezierPathVertex(position: .init(x: size.width, y: 0), anchor: .topRight))
                path.addLine(to: PDFBezierPathVertex(position: .init(x: size.width, y: size.height), anchor: .bottomRight))
                let shape = PDFDynamicGeometryShape(path: path, fillColor: .white, stroke: .init(type: .full, color: .gray, width: 1, radius: 0))
                let groupLeft = PDFGroup(
                    allowsBreaks: true,
                    backgroundColor: .white,
                    backgroundImage: nil,
                    backgroundShape: shape,
                    outline: .none,
                    padding: .init(top: 0, left: 0, bottom: 0, right: 0)
                )
                
                for nestedContent in item.textItems {
                    groupLeft.add(.left, text: nestedContent)
                }
                groupLeft.add(space: 8)
                // setting color to clear allows to fit group to section colomn't width
                groupLeft.addLineSeparator(style: .init(type: .full, color: .clear, width: 1, radius: 0))
                leftColomn.add(group: groupLeft)
                
                // right colomn
                let rightColomn = PDFSectionColumn(width: 0.4)
                 let imageGroup = PDFGroup(
                     allowsBreaks: false,
                     backgroundColor: .purple,
                     backgroundImage: nil,
                     backgroundShape: .none,
                     outline: .none,
                 padding: EdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
                 )
                 
                 var images: [PDFImage] = []
                 
                for image in item.images {
                    let pdfImage = PDFImage(
                        image: image,
                        size: .init(width: 51, height: 51),
                        sizeFit: .widthHeight,
                        options: [.resize, .compress],
                        cornerRadius: 0
                    )
                    images.append(pdfImage)
                 }
                 
                imageGroup.add(space: 8)
                imageGroup.add(.left, imagesInRow: images, spacing: 2)
                imageGroup.add(space: 8)
                rightColomn.add(group: imageGroup)
                
                let section = PDFSection([leftColomn, rightColomn])
                section.columnMargin = 0
                document.add(section: section)
                document.addLineSeparator(style: .init(type: .full, color: .black, width: 1, radius: 0))
                document.add(space: 2)
            }
            
            return [document]
        }
    
    struct RowItem {
        let textItems: [String]
        let images: [Image]
    }
    
    
    bug 
    opened by tarasChernysh 1
Releases(2.4.0)
  • 2.4.0(Dec 17, 2022)

  • 2.3.5(Apr 11, 2021)

    Fixed bugs:

    • Fixed PDFList not calculating available content height correctly (#267)
    • Removed PDFTable initializer size defaults (#269)

    Closed issues:

    • Issue #267
    • Issue #269

    Merged pull requests:

    • PR #268 (by philprime)
    Source code(tar.gz)
    Source code(zip)
  • 2.3.4(Mar 15, 2021)

    Fixed bugs:

    • Fixed table header position when activating showHeaderOnEveryPage (#222)

    Closed issues:

    • Issue #222

    Merged pull requests:

    • PR #264 (by Sgkhour)
    Source code(tar.gz)
    Source code(zip)
  • 2.3.3(Jan 6, 2021)

    Fixed bugs:

    • Fixed empty pages between external documents (#247)
    • Fixed total page count calculations (#248)

    Closed issues:

    • Issue #247
    • Issue #248

    Merged pull requests:

    • Issue #258
    Source code(tar.gz)
    Source code(zip)
  • 2.3.2(Dec 5, 2020)

    Implemented enhancements:

    • Added optional table cell splicing disabling (#205)

    Fixed bugs:

    • Fixed carthage version missing (#236)

    Closed issues:

    • Issue #205
    • Issue #222
    • Issue #236
    • Issue #243
    • Issue #249
    • Issue #233

    Merged pull requests:

    • PR #223
    • PR #252 [by lpeancovschi]
    • PR #255
    Source code(tar.gz)
    Source code(zip)
  • 2.3.1(Sep 23, 2020)

  • 2.3.0(Jul 16, 2020)

  • 2.2.0(Jul 16, 2020)

  • 2.1.2(Jun 27, 2020)

    Fixed bugs:

    • Height of image captions are now calcuated correctly (Issue #208)

    Closed issues:

    • Issue #208

    Merged pull requests:

    • PR #214 [by chrisgonzgonz]
    Source code(tar.gz)
    Source code(zip)
  • 2.1.1(Jun 18, 2020)

    Implemented enhancements:

    • Added raw representable to PDFTableCellAlignment
    • Added support for groups inside section columns

    Fixed bugs:

    • Fixed indentations inside sections
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Jun 18, 2020)

    Implemented enhancements:

    • Added raw representable values to PDFPageFormat
    • Added raw representable type to PDFLineType
    • Added constant none to PDFTableCellStyle and PDFTableCellBorders
    • Added background color to PDFSectionColumn (Issue #122)

    Fixed bugs:

    • Added note to documentation about not reusing PDFSection instances (Issue #122)
    • Added missing font and text color reset to generator

    Closed issues:

    • #73
    • #122
    • #204
    • #197
    • #189
    • #186
    • #184
    • #183

    Merged pull requests:

    • #211
    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(May 31, 2020)

    Implemented enhancements:

    • Removed JSON representation
    • Added deprecation for table.generateCells

    Fixed bugs:

    • Missing page break after space which overlaps page end (#204)

    Closed issues:

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(May 19, 2020)

    Implemented enhancements:

    • Table Merging
    • Swift Package Manager Support
    • Hyperlinks in texts

    Fixed bugs:

    • External document including empty pages

    Closed issues:

    • #41
    • #86
    • #148
    • #178
    • #179
    • #182
    • #183
    • #184
    • #185
    • #186
    • #196
    • #197

    Merged pull requests:

    • #181
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0(May 19, 2020)

    Implemented enhancements:

    • Added progress reporting using iOS internal Foundation.Progress (Issue #155)
    • Added a better test example experience
    • Added support to embed external PDF document (Issue #31)
    • Added clickable URL support for images (Issue #170)
    • Added support for NSAttributedString link attributes (Issue #71)
    • Added subscript range access to PDFTable and deprecated PDFTable.setCellStyle

    Fixed bugs:

    • Fixed TravisCI configuration

    Closed issues:

    • #155
    • #31
    • #170
    • #71

    Merged pull requests:

    • #171
    • #172
    • #174
    • #177
    Source code(tar.gz)
    Source code(zip)
  • 1.5.4(Dec 11, 2019)

  • 1.5.3(Dec 11, 2019)

  • 1.5.2(Dec 11, 2019)

  • 1.5.1(Dec 11, 2019)

  • 1.5.0(Dec 11, 2019)

    Implemented enhancements:

    • Changed framework methods to be "more Swift(y)"
    • Added groups
    • Added dynamic shapes for group background
    • Added column with automatic wrapping (Issue #113)
    • Added document wide text styles (Issue #57)
    • Added automatic table of content based on text styles (Issue #58)

    Fixed bugs:

    • Fixed line separator in header and footer (Issue #88)
    • Fixed image in footer layout calcuations (Issue #132)

    Closed issues:

    • #9
    • #57
    • #58
    • #88
    • #113
    • #118
    • #127
    • #132
    • #136
    • #137
    • #138
    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Jun 6, 2019)

  • 1.4.0(May 14, 2019)

    Implemented enhancements:

    • Added rounded corner clipping to images (#123)
    • Added Swift 5 support

    Fixed bugs:

    • Line separator skewed (#128)

    Closed issues:

    • #123
    • #125
    • #128
    Source code(tar.gz)
    Source code(zip)
  • 1.3.3(May 14, 2019)

  • 1.3.2(May 14, 2019)

    Implemented enhancements:

    • Changed accessor methods of PDFPageFormat to be publicly accessible.
    • Added public accessor method to PDFPageLayout

    Closed issues:

    • Issue #11
    • Issue #111

    Merged pull requests:

    • PR #106 [by protspace]
    Source code(tar.gz)
    Source code(zip)
  • 1.3.1(May 14, 2019)

  • 1.3.0(May 14, 2019)

  • 1.2.1(May 14, 2019)

  • 1.2.0(May 14, 2019)

    Implemented enhancements:

    • Added options to PDFImage, allowing more precise control about resizing and compression.
    • Improvements to internal image resizing and compression methods.

    Closed issues:

    • Issue #77
    • Issue #78
    Source code(tar.gz)
    Source code(zip)
A Static Library to be embedded on iOS applications to display pdf documents derived from Fast PDF

FastPdfKit This repository contains the FastPdfKit iOS library with some sample projects. FastPdfKit is a library that let you show pdf documents in i

Dimension 1.2k Dec 22, 2022
A simple generator of PDF written in Swift.

Features | Requirements | Installation | Usage | Communication | LICENSE PDFGenerator PDFGenerator is a simple PDF generator that generates with UIVie

Suguru Kishimoto 712 Dec 29, 2022
An iOS PDF viewer and annotator written in Swift that can be embedded into any application.

Requirements iOS 9 or above Xcode 8 or above Swift 3.0 Note This project is still in early stages. Right now the PDF reader works both programmaticall

UXM Studio 269 Dec 11, 2022
PDF Reader Core for iOS

PDF Reader Core for iOS This project is no longer supported or maintained. It is only here for historical reasons. Please see the UXReader PDF Framewo

Julius Oklamcak 4.3k Jan 6, 2023
Small utility to import PDF slides as vector images into Keynote for iOS.

Small utility to import PDF files into Keynote for iOS. This utility is especially helpful when presenting slideshows created by LaTeX

Luming Yin 6 Jun 14, 2022
Draw Week Time Table on PDF using PDFKit in iOS Swift

DrawPDFTimeTable Draw Week Time Table on PDF using PDFKit in iOS Swift. Image Info This is the pdf of time table drawn using PDFKit in iOS Swift with

Kushagra Chandra 6 Nov 22, 2022
SimplePDF is a wrapper of UIGraphics PDF context written in Swift.

SimplePDF is a wrapper of UIGraphics PDF context written in Swift. You can: add texts, images, spaces and lines, table set up page layout, adjust cont

Nutchaphon Rewik 238 Dec 29, 2022
PDF generator using UIViews or UIViews with an associated XIB

Description Create UIView objects using any method you like, including interface builder with Auto-layout and size classes enabled. Then generate a PD

null 34 Dec 17, 2022
Generate beautiful .pdf Files from xib

Description The Library generates a PDF directly from interface builder with Auto-layouted views! Swift Version of UIView_2_PDF. Installation Download

Simon C. Krüger 16 Dec 17, 2022
UIImage PDF extensions.

UIImagePlusPDF UIImage extensions to use PDF files. Using UIImagePlusPDF you can avoid a lot png images files (1x, 2x, 3x sizes) and simply replace ea

Dmytro Mishchenko 35 Jan 4, 2023
Estrutura Simples para Navegacao Web e Download PDF

Download-PDF-WebView Projeto desenvolvido em Swift com a função de criar uma estrutura simples para navegação Web em seu Aplicativo, permitindo a visu

Josué Rodrigues 1 Nov 30, 2021
PdfBuilder: a swift library made to make creation of the Pdf file from code simpler

PdfBuilder PdfBuilder is a swift library made to make creation of the Pdf file f

null 4 Jul 22, 2022
Mephisto - A command line tool to convert Comic Book Zip archives to PDF and share them over AirDrop

mephisto A command line tool written in Swift to convert Comic Book Zip archives

null 0 Feb 7, 2022
Swift package that uses WebKit to render PDF files from URLs

Swift package for generating a PDF file from a URL (rendered by WebKit)

aaronland 1 Feb 25, 2022
PLHKit: A Swift DSL for Rendering and creating PDF Files.

PLHKit PLH is a tribute to Portsaid Light House, Port Said Lighthouse was the first building in the world created with reinforced concrete. ?? PLHKit

null 10 Sep 2, 2022
About PDFKit learning project on iOS 11, Like iBooks.app.

iBook About PDFKit learning project on iOS 11, Like iBooks.app. 书库 书库页面获取PDF相关数据, 可以通过KVC获取。 PDF书名 if let title = documentAttributes["Title"] as? Stri

Jovins 31 Sep 15, 2022
📚 A Swift ePub reader and parser framework for iOS.

FolioReaderKit is an ePub reader and parser framework for iOS written in Swift. Features ePub 2 and ePub 3 support Custom Fonts Custom Text Size Text

FolioReader 2.5k Jan 8, 2023
TPPDF is a simple-to-use PDF builder for iOS

TPPDF is a fast PDF builder for iOS & macOS using simple commands to create advanced documents! Created and maintained by Philip Niedertscheider and a

techprimate 581 Dec 29, 2022
A Static Library to be embedded on iOS applications to display pdf documents derived from Fast PDF

FastPdfKit This repository contains the FastPdfKit iOS library with some sample projects. FastPdfKit is a library that let you show pdf documents in i

Dimension 1.2k Dec 22, 2022
A simple generator of PDF written in Swift.

Features | Requirements | Installation | Usage | Communication | LICENSE PDFGenerator PDFGenerator is a simple PDF generator that generates with UIVie

Suguru Kishimoto 712 Dec 29, 2022