2017-06-19 3 views
0

Mein Ziel ist es, Text in ein PDF zu schreiben, wie eine Anmerkung.Zeichnen Sie eine PDF mit Swift auf macOS

Ich habe es geschafft, die PDFPage zu einem NSMage zu transformieren, ich zeichnete auf dem NSImage dann speicherte ich die PDF, die von den Bildern gebildet wurde.

let image = NSImage(size: pageImage.size)   
image.lockFocus() 

let rect: NSRect = NSRect(x: 50, y: 50, width: 60, height: 20) 
"Write it on the page!".draw(in: rect, withAttributes: someAttributes) 

image.unlockFocus() 

let out = PDFPage(image: image) 

Das Problem ist offensichtlich, dass out (die neue Seite der Ausgabe PDF) ist ein PDFPage von Bildern und nicht regelmäßig ein. Die Ausgabe-PDF-Datei ist also sehr groß und Sie können nichts kopieren und einfügen. Es ist nur eine Sequenz von Bildern.

Meine Frage ist, ob es eine Möglichkeit gibt, einfachen Text auf einer PDF-Seite programmgesteuert ohne Verwendung von NSImage hinzuzufügen. Irgendeine Idee?

Hinweis: Es gibt diese Klasse in iOS-Programmierung UIGraphicsBeginPDFPageWithInfo, die in meinem Fall sehr hilfreich sein könnte. Aber ich kann die ähnliche Klasse für die MacOS-Entwicklung nicht finden.

+0

yeah ... Sie können dies mit HTML tun. –

+0

@ClaudioCastro Kein anderer Weg? Hier ist, wie ich mein Problem auf iOS zu lösen, aber ich kann nicht eine gleichwertige Möglichkeit in Mac OS finden: https://stackoverflow.com/questions/32113468/how-to-draw-text-in-pdf-context-in-swift – Matt

+0

Es tut mir leid, du redest über macOS ... Meine Lösung war für iOS, wo ich html verwende, um eine PDF mit Text und Bildern zu erstellen. –

Antwort

3

Sie können einen PDF-Grafikkontext auf macOS erstellen und darin eine PDFPage zeichnen. Dann können Sie weitere Objekte in den Kontext zeichnen, indem Sie entweder Core Graphics oder AppKit-Grafiken verwenden.

Hier ist ein Test PDF ich durch den Druck Ihrer Frage erstellt: input PDF

Und hier ist das Ergebnis von dieser Seite in eine PDF-Kontext zeichnen, dann mehr Text auf ihm zeichnen:

output PDF

Hier ist der Code, den ich das erste PDF in das zweite PDF umwandeln schrieb:

import Cocoa 
import Quartz 

let inUrl: URL = URL(fileURLWithPath: "/Users/mayoff/Desktop/test.pdf") 
let outUrl: CFURL = URL(fileURLWithPath: "/Users/mayoff/Desktop/testout.pdf") as CFURL 

let doc: PDFDocument = PDFDocument(url: inUrl)! 
let page: PDFPage = doc.page(at: 0)! 
var mediaBox: CGRect = page.bounds(for: .mediaBox) 

let gc = CGContext(outUrl, mediaBox: &mediaBox, nil)! 
let nsgc = NSGraphicsContext(cgContext: gc, flipped: false) 
NSGraphicsContext.current = nsgc 
gc.beginPDFPage(nil); do { 
    page.draw(with: .mediaBox, to: gc) 

    let style = NSMutableParagraphStyle() 
    style.alignment = .center 

    let richText = NSAttributedString(string: "Hello, world!", attributes: [ 
     NSFontAttributeName: NSFont.systemFont(ofSize: 64), 
     NSForegroundColorAttributeName: NSColor.red, 
     NSParagraphStyleAttributeName: style 
     ]) 

    let richTextBounds = richText.size() 
    let point = CGPoint(x: mediaBox.midX - richTextBounds.width/2, y: mediaBox.midY - richTextBounds.height/2) 
    gc.saveGState(); do { 
     gc.translateBy(x: point.x, y: point.y) 
     gc.rotate(by: .pi/5) 
     richText.draw(at: .zero) 
    }; gc.restoreGState() 

}; gc.endPDFPage() 
NSGraphicsContext.current = nil 
gc.closePDF() 
+0

Perfekte Antwort! Ich verstehe jetzt. – Matt

+0

Hey Rob! Was ist, wenn ich die neue gezeichnete Seite verwenden muss? Mit Ihrem Code wird die neue Seite im Pfad ** outUrl ** gespeichert, aber es gibt keine Möglichkeit, programmgesteuert darauf zuzugreifen. Das einzige, was ich tun könnte, ist, die PDF-Seite in ** outUrl ** zu speichern und dann wieder zu öffnen. Ich habe auf der Dokumentationsseite von CGContext nachgesehen, aber ich finde nichts, um die PDFPage zu bekommen, die verändert wurde. Irgendeine Idee, wie man es sofort nach ** gc.closePDF() ** call bekommt? Es ist nicht wichtig, es war nur aus Neugierde. – Matt

+1

Verwenden Sie den 'CGContext'-Initialisierer, der ein' CGDataConsumer'-Argument verwendet. Nachdem Sie 'closePDF' haben, können Sie eine neue Instanz von' PDFDocument' aus den Daten erstellen, ohne eine Datei durchlaufen zu müssen. –

Verwandte Themen