Skip to content

Instantly share code, notes, and snippets.

@krzyzanowskim
Last active April 7, 2024 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krzyzanowskim/5f2a090f258b075c142a83d0744ba1b7 to your computer and use it in GitHub Desktop.
Save krzyzanowskim/5f2a090f258b075c142a83d0744ba1b7 to your computer and use it in GitHub Desktop.
Minimal setup of TextKit2 components to produce PDF document
import Cocoa
let loremIpsum = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque erat risus, laoreet et eros id, lobortis elementum sem. Nullam nec magna massa. Donec gravida felis at odio tincidunt pretium et in orci. Curabitur suscipit porta purus non faucibus. Cras dapibus felis eu enim rutrum, vel aliquet lacus volutpat. Quisque fermentum vulputate dictum. Morbi mattis orci quis dui posuere, id vulputate turpis tempus. Sed vulputate augue at ullamcorper feugiat. Phasellus nec lacus eget sapien congue lacinia vel et nulla. Phasellus sollicitudin gravida dapibus. Donec molestie ullamcorper lacus eu rutrum. Praesent lacinia dignissim dui eu ultricies. Integer in lacus lobortis, porttitor sem eu, tincidunt dolor. Cras dignissim nisl in maximus ullamcorper.
Proin nec vulputate magna. In interdum leo sit amet arcu consequat facilisis. Fusce ut malesuada ante, nec malesuada nisl. Mauris porta velit quis tortor mollis, in suscipit augue efficitur. Praesent eleifend mollis neque, non semper diam tempus at. Cras sed nibh ac ante vehicula aliquet id eu velit. In hac habitasse platea dictumst. Aliquam id odio leo. Aenean eget porta nulla, a commodo ipsum. Suspendisse id molestie orci. Vivamus iaculis pulvinar augue id volutpat. Curabitur in lorem lectus. Quisque sit amet urna ut felis lobortis finibus. Pellentesque non turpis in tortor efficitur pellentesque in eget odio.
"""
let textContainer = NSTextContainer()
textContainer.lineFragmentPadding = 0
textContainer.size.width = 300
let contentManager = NSTextContentStorage()
let layoutManager = NSTextLayoutManager()
layoutManager.textContainer = textContainer
contentManager.addTextLayoutManager(layoutManager)
contentManager.attributedString = NSAttributedString(string: loremIpsum)
// First layout in the text container
layoutManager.ensureLayout(for: contentManager.documentRange)
// Adjust text container size to the size required to layout content
textContainer.size = layoutManager.usageBoundsForTextContainer.size
layoutManager.ensureLayout(for: contentManager.documentRange)
// Draw/Layout fragments
// create PDF CGContext boilerplate
let pdfData = NSMutableData()
var mediaBox = CGRect(origin: .zero, size: textContainer.size)
let context = CGContext(consumer: CGDataConsumer(data: pdfData)!, mediaBox: &mediaBox, nil)!
context.beginPage(mediaBox: &mediaBox)
context.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: mediaBox.size.height))
layoutManager.enumerateTextLayoutFragments(from: contentManager.documentRange.location, options: [.ensuresLayout], using: { textLayoutFragment in
textLayoutFragment.draw(at: textLayoutFragment.layoutFragmentFrame.origin, in: context)
return true
})
//let viewportDelegate = CustomViewportDelegate(context: context)
//layoutManager.textViewportLayoutController.delegate = viewportDelegate
//layoutManager.textViewportLayoutController.layoutViewport()
// Write PDF to file
context.endPage()
context.closePDF()
try! pdfData.write(to: URL(filePath: "/Users/marcinkrzyzanowski/Downloads/output.pdf"))
//class CustomViewportDelegate: NSObject, NSTextViewportLayoutControllerDelegate {
// let context: CGContext
//
// init(context: CGContext) {
// self.context = context
// }
//
// func viewportBounds(for textViewportLayoutController: NSTextViewportLayoutController) -> CGRect {
// CGRect(
// origin: .zero,
// size: textViewportLayoutController.textLayoutManager?.textContainer?.size ?? .zero
// )
// }
//
// func textViewportLayoutController(_ textViewportLayoutController: NSTextViewportLayoutController, configureRenderingSurfaceFor textLayoutFragment: NSTextLayoutFragment) {
// textLayoutFragment.draw(
// at: textLayoutFragment.layoutFragmentFrame.origin,
// in: context
// )
// }
//}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment