0

I'm trying to use a PDF file (contains a form with table for several 'records') as a template. My idea is to read in the original file as a template, and then use Swifts drawing features to insert the text at the relevant positions before saving as a new pdf file and printing.

My problem is that i'm seeing a small loss of resolution (fonts are slightly wooly, gridlines are no longer crisp) when re-saving the output.

I've tried two approaches, the first with my 'template' as a file in the project, and the second with it as an Asset (Scales: Single Scale, Resizing: Preserve Vector Data).

Here is my code:

func createCompletedForm(records: [MyDataObject]) -> URL? {
    
    let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = URL(fileURLWithPath: "pdfToPrint", relativeTo: directoryURL).appendingPathExtension("pdf")
    guard let templateUrl = Bundle.main.url(forResource: "MyPdfTemplate", withExtension: "pdf") else { return nil }
    guard let document = CGPDFDocument(templateUrl as CFURL) else { return nil }
    guard let page = document.page(at: 1) else { return nil }
    let pageTemplate = page.getBoxRect(.mediaBox)
    
    UIGraphicsBeginPDFContextToFile(fileURL.path, pageTemplate, nil)
    
    guard let pdfContext = UIGraphicsGetCurrentContext() else {
        print("Unable to access PDF Context.")
        return nil
    }
    
    // Mark the beginning of the page.
    pdfContext.beginPDFPage(nil)

    // Save the context state to restore after we are done drawing the image.
    pdfContext.saveGState()

    // Change the PDF context to match the UIKit coordinate system.
    pdfContext.translateBy(x: 0, y: StandardPageDimensions.ISO216_A4.height)
    pdfContext.scaleBy(x: 1, y: -1)

    // Option 1: Draw PDF from a file added to my project
    DrawingHelper.drawPDFfromCGPDF(page: page, drawingArea: pageTemplate)
    
    // Option 2: Draw PDF from Assets
    //let baseTemplate = UIImage(named: "MyPdfTemplate")
    //baseTemplate?.draw(at: CGPoint(x: 0, y: 0))

    // Draw the records over the template - NOT the source of the problem, happens even when commented out
    //addRecordsToTemplate(records: records)

    // Restoring the context back to its original state.
    pdfContext.restoreGState()

    // Mark the end of the current page.
    pdfContext.endPDFPage()
    
    UIGraphicsEndPDFContext()
    
    // Useful to find and open the file produced on the simulator
    print("pdf created at : \(fileURL.path)")
    
    return fileURL
}

    // And the drawing function from my helper class
    static func drawPDFfromCGPDF(page: CGPDFPage, drawingArea: CGRect) {

    let renderer = UIGraphicsImageRenderer(size: drawingArea.size)
    let img = renderer.image { ctx in
        UIColor.white.set()
        ctx.fill(drawingArea)

        ctx.cgContext.translateBy(x: 0.0, y: drawingArea.size.height)
        ctx.cgContext.scaleBy(x: 1.0, y: -1.0)

        ctx.cgContext.drawPDFPage(page)
    }

    img.draw(at: CGPoint(x: 0, y: 0))
}
Andy P
  • 667
  • 7
  • 14
  • So the resolution issue happens for the newly added text or for the original template also? – SamB Sep 27 '21 at 16:50
  • How was the original PDF created? PDF is generally a vector format, but it can contain embedded raster images. If the original PDF contains a raster image of the original form, then it will scale as a raster image. – Scott Thompson Sep 27 '21 at 17:51
  • @SamB the original template is losing resolution – Andy P Sep 28 '21 at 08:04
  • @ScottThompson Afraid I have no idea how the original document was created. I did wonder if perhaps the loss of resolution is due to the translate/scale to fit with UIKit. I guess I should try simply loading the document and saving it again without performing any operations on it – Andy P Sep 28 '21 at 08:10
  • 1
    You can open the document in Preview, or Acrobat Reader, and zoom in on it. If the doc is raster, they shouldn't be able to scale it any better than UIKit. – Scott Thompson Sep 28 '21 at 14:25

0 Answers0