Display and manipulate PDF documents in your applications using PDFKit.

Posts under PDFKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

Push Button captions not properly written to PDF document using PDFKit
The Problem Push buttons (created as a PDFAnnotation using PDFKit) do not properly write the associated caption's key-value pair (within the annotation's appearance characteristics dictionary) to a PDF document. What is Happening Push button widget annotations can have a caption that is displayed as the button’s label. In the PDF 1.7 specification (ISO PDF32000-2008, s. 12.5.6.19), a widget annotation can have an ‘appearance characteristics dictionary’ (MK) with properties to construct the appearance of the widget. The caption property (CA) is used to construct a button’s caption/label. PDFKit uses the PDFAnnotation .caption property to set the value of a push button’s caption as a string. Observation 1: In an open PDF document (using PDFView), a push button widget annotation can be created and added to a PDFPage using the following code: let pushButton = PDFAnnotation(bounds: pushButtonBounds, forType: .widget, withProperties: nil) pushButton.widgetFieldType = .button pushButton.widgetControlType = .pushButtonControl pushButton.caption = "My Button" page.addAnnotation(pushButton) The PDFAnnotation .caption property is used to set the caption to the required string. As a result, the push button is correctly displayed on the PDFPage with the correct label being display on the button. While the PDF document remains open, the appearance characteristics dictionary (an PDFAppearanceCharacteristics object) retains a key-value pair for the caption with the correct value as expected. On saving/writing to the PDF file, however, the key-value pair for the caption in the appearance characteristics dictionary is not written to the PDF document’s file. Resulting PDF markup: 6 0 obj << /Rect [ 256 299.8977 356 399.8977 ] /Border [ 0 0 0 ] /T (button23) /F 4 /Subtype /Widget /DA (/.AppleSystemUIFont 13 Tf 0 g) /MK 8 0 R /C [ 0 ] /AP 9 0 R /V /Off /M (D:20250330154918Z00'00') /FT /Btn /Type /Annot /Ff 65536 >> endobj 9 0 obj << /N 10 0 R >> endobj 8 0 obj << /BG [ 0.75 ] >> endobj 10 0 obj << /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 100 100] /Resources 11 0 R /Length 170 >> stream x }ê1 Ç0 Öw~≈ ahÈ KÈ q1q0\‚`ú Ÿ¿ 8¯Ôm% u0óª‰.Ô{yπ åP°H-}ª‡à y3 ¸ %≠¡‰ %› g¨$•µMVXø‡Hé†Ö ”î“¿˜® BI•L ˆ†b A pü‰Ã @ÓpB∫ †æœs ãÙ:d8Éwÿr»/}” €∂I÷Bõ B;'+gm Ô˝„ mÙ~ L*>• endstream endobj On closing the PDF document, the assigned value for the push button’s caption is not written to the file and is lost. Observation 2: On reopening the PDF document, and assigning a new value for the already-created push button’s caption, a key-value pair for the caption is again correctly added to the PDFAnnotation appearance characteristics dictionary. On saving/writing to the PDF file, this time, the caption key-value pair in the appearance characteristics dictionary is correctly written/saved to the PDF document file. Resulting PDF markup: 6 0 obj << /Border [ 0 0 0 ] /Rect [ 256 299.8977 356 399.8977 ] /T (button23) /F 4 /BS 8 0 R /Subtype /Widget /DA (/.AppleSystemUIFont 13 Tf 0 g) /MK 9 0 R /C [ 0 ] /AP 10 0 R /V /Off /M (D:20250330154918Z00'00') /FT /Btn /Type /Annot /Ff 65536 >> endobj 10 0 obj << /N 11 0 R >> endobj 9 0 obj << /BG [ 0.75 ] /CA (My Button) >> endobj 8 0 obj << /W 0 >> endobj 11 0 obj << /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 100 100] /Resources 12 0 R /Length 163 >> stream x uè1 ¬@ Ö˜˛ä7∂√]ì´◊Î≠ ¡A 8à”a∑Vj·ø˜jë™ !ÅÑ|y/=ˆËA1òʺ]pDá|=0¬“Œb ø+Õ gùf2E≤∞Ê≈N` û·Xm©-BãZ†H Ÿ ¿≈ºPÄ= Ø míãp •¡ ÈÓÅ˙>é “kó· Ÿb#—¬ Ûã¶2∂Ñ2fiΠ;óDÌiÓ?ü>LÁûÊy;} endstream endobj Impact on User Experience: Push button captions may not be properly saved to the PDF document’s file. This may result in an application redrawing a push button without a caption/label. More so, an application that uses the caption value to “read” a button’s label (e.g., for accessibility purposes) will not be able to do so.
1
0
322
Apr ’25
Occasional PDFKit crash at PageLayout::getWordRange(unsigned long, long)
At this line of code (SketchTextSelectionManager.swift:449), sometimes there will be crashes based on crashlytics reports. let selection = pdfPage.selectionForWord(at: location) This is directly calling into PDFKit's PDFPage#selection method: https://developer.apple.com/documentation/pdfkit/pdfpage/selectionforword(at:) Attached the full stacktrace: Crashed: com.apple.root.user-initiated-qos.cooperative 0 CoreGraphics 0x30c968 PageLayout::getWordRange(unsigned long, long) const + 908 1 CoreGraphics 0x30bbc0 PageLayout::getTextRangeIndex(CGPoint, CGPDFSelectionType, SelectionPrecision) const + 2292 2 CoreGraphics 0x44a53c CGPDFSelectionCreateBetweenPointsWithOptions + 384 3 PDFKit 0x8d5f8 -[PDFPage selectionFromPoint:toPoint:type:] + 168 4 PDFKit 0x92040 -[PDFPage _rvItemAtPoint:] + 64 5 PDFKit 0x91f4c -[PDFPage rvItemAtPoint:] + 84 6 PDFKit 0x8caa8 -[PDFPage selectionForWordAtPoint:] + 40 7 MyApp 0x8420e0 closure #1 in SketchTextSelectionManager.startNewTextSelection(pageId:location:) + 449 (SketchTextSelectionManager.swift:449) 8 MyApp 0x841a70 SketchTextSelectionManager.startNewTextSelection(pageId:location:) + 205 (CurrentNoteManager.swift:205) 9 libswift_Concurrency.dylib 0x61104 swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 10 libswift_Concurrency.dylib 0x63a28 (anonymous namespace)::ProcessOutOfLineJob::process(swift::Job*) + 480 11 libswift_Concurrency.dylib 0x611c4 swift::runJobInEstablishedExecutorContext(swift::Job*) + 444 12 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 13 libdispatch.dylib 0x15d8c _dispatch_root_queue_drain + 392 14 libdispatch.dylib 0x16590 _dispatch_worker_thread2 + 156 15 libsystem_pthread.dylib 0x4c40 _pthread_wqthread + 228 16 libsystem_pthread.dylib 0x1488 start_wqthread + 8 ```
0
1
496
Feb ’25
Random PDFKit crash on text selection
At this line of code (SketchTextSelectionManager.swift:378), sometimes there will be crashes based on crashlytics reports. In the reports, it seems like this only happens for RTL text range. let selection = pdfPage.selection( from: CGPoint(x: fromStart.x + 1, y: fromStart.y - 1), to: CGPoint(x: toEnd.x - 1, y: toEnd.y + 1) ) This is directly calling into PDFKit's PDFPage#selection method: https://developer.apple.com/documentation/pdfkit/pdfpage/selection(from:to:) Attached the full stacktrace: Crashed: com.apple.root.user-initiated-qos.cooperative 0 CoreGraphics 0x30598c PageLayout::convertRTLTextRangeIndexToStringRangeIndex(long) const + 156 1 CoreGraphics 0x44c3f0 CGPDFSelectionCreateBetweenPointsWithOptions + 224 2 PDFKit 0x91d00 -[PDFPage selectionFromPoint:toPoint:type:] + 168 3 MyApp 0x841044 closure #1 in SketchTextSelectionManager.handleUserTouchMoved(_:) + 378 (SketchTextSelectionManager.swift:378) 4 MyApp 0x840cb0 SketchTextSelectionManager.handleUserTouchMoved(_:) + 205 (CurrentNoteManager.swift:205) 5 libswift_Concurrency.dylib 0x60f5c swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 6 libswift_Concurrency.dylib 0x63a28 (anonymous namespace)::ProcessOutOfLineJob::process(swift::Job*) + 480 7 libswift_Concurrency.dylib 0x6101c swift::runJobInEstablishedExecutorContext(swift::Job*) + 444 8 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 9 libdispatch.dylib 0x15ec0 _dispatch_root_queue_drain + 392 10 libdispatch.dylib 0x166c4 _dispatch_worker_thread2 + 156 11 libsystem_pthread.dylib 0x3644 _pthread_wqthread + 228 12 libsystem_pthread.dylib 0x1474 start_wqthread + 8
0
1
475
Feb ’25
Exact Extract of Text from PDF
The problem is that when I read out the text in a PDF with page.string or page.attributedString, the context of the lines is lost. Instead of TermA....23,45 TermB....2,13 in an index document TermA TermB 23,45 2,13 is issued. The context of the lines (and the sequence of the letters) is lost. Is there a way to read the text from a PDF line by line?
1
1
732
Jan ’25
PDFKit - beginFindString
I am creating an iOS app that needs to parse the text from a PDF document. I can read the entire PDF document's text using the string property, but if it's a large PDF document, this could cause delays for users. From the documentation, I came across the beginFindString function, which seems to asynchronously, with no return? https://developer.apple.com/documentation/pdfkit/pdfdocument/beginfindstring(_:withoptions:)) Unfortunately I cannot find examples on how to use this function or its intended purpose/functionality, so any guidance would be appreciated. My goal is to read the PDF document one line at a time, searching for newlines ('\n'), then parsing that line as needed. I'm hoping the beginFindString function will be useful.
0
0
498
Jan ’25
iOS 18.x PDFKit Page.string and Page.attributedString return some text way out of oder
Reading text out of PDFs with PDFKit results in some text being returned way out of order when using .string or .attributedString functions. Way out of order means not just wrong sorting of words on a line or wrongly showing up on the next line (as has happened with PDFKit on older iOS releases, e.g. 17.x), but some text (one or more words) may show up near the end of a page of text, while it should show near the beginning. As Page.characterBounds(at:) is buggy in iOS 18.x returns wrong bounds, devs cannot correct such faulty PDFKit behaviour programmatically. I believe it is on Apple to fix this iOS 18 bug asap. Thank you for giving it priority as this is killing apps that need PDFKit to get and parse text data out of PDFs. I have filed Feedback FB16264926.
3
1
1.1k
Jan ’25
Issue with page.selectionForWord(at:) in Mac Designed for iPad Mode
I’m encountering an issue with the page.selectionForWord(at:) method in my application. This method has stopped working in Mac Designed for iPad mode. The functionality works fine on physical devices such as iPhone and iPad, as well as on Mac, but in this specific mode, the method no longer works, and the application crashes. It is crucial for me that this functionality works in Mac Designed for iPad mode, as rewriting the entire code for Mac would be too time-consuming, especially considering the size of the application. Interestingly, a similar method, page.selectionForLine(at:), works perfectly with the same parameters in all environments, including the Mac Designed for iPad mode. This makes the issue even more puzzling. The issue began after the latest update. The app no longer responds to the page.selectionForWord(at:) method, which causes the application to crash. I have attached a test app to reproduce the error.
1
0
637
Dec ’24
CoreGraphics: CGPDFPageCopyRootTaggedNode
My app uses PDFKit, but I don't know how to solve this bug at all. Under the same IOS system and device model, some users' devices may experience crashes, while our own devices are functioning normally. The following is the stack information for crashing: 0 libsystem_platform.dylib__os_unfair_lock_recursive_abort + 36 1 libsystem_platform.dylib__os_unfair_lock_lock_slow + 308 2 CoreGraphics_CGPDFPageCopyRootTaggedNode + 56 3 PDFKit-[PDFPageViewAccessibility accessibilityElements] + 76 4 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityElements] + 56 5 UIAccessibility-[NSObjectAccessibility accessibilityElementCount] + 68 6 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityHasOrderedChildren] + 44 7 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFrameForSorting] + 216 8 UIAccessibility-[NSObject _accessibilityCompareGeometry:] + 116 9 UIAccessibility-[NSObject(AXPrivCategory) accessibilityCompareGeometry:] + 52 10 CoreFoundation___CFSimpleMergeSort + 100 11 CoreFoundation___CFSimpleMergeSort + 248 12 CoreFoundation_CFSortIndexes + 260 13 CoreFoundation-[NSArray sortedArrayFromRange:options:usingComparator:] + 732 14 CoreFoundation-[NSMutableArray sortedArrayFromRange:options:usingComparator:] + 60 15 CoreFoundation-[NSArray sortedArrayUsingSelector:] + 168 16 UIAccessibility___57-[NSObject(AXPrivCategory) _accessibilityFindDescendant:]_block_invoke + 268 17 UIAccessibility___96-[NSObject(AXPrivCategory) _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:]_block_invoke + 140 18 UIAccessibility-[NSObject _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:] + 244 19 UIAccessibility-[NSObject _accessibilityFindFirstAXDescendantPassingTest:byYieldingElements:] + 272 20 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFindDescendant:] + 100 21 UIAccessibility__axuiElementForNotificationData + 276 22 UIAccessibility__massageAssociatedElementBeforePost + 36 23 UIAccessibility__UIAXBroadcastMainThread + 292 24 libdispatch.dylib__dispatch_call_block_and_release + 32 25 libdispatch.dylib__dispatch_client_callout + 20 26 libdispatch.dylib__dispatch_main_queue_drain + 980 27 libdispatch.dylib__dispatch_main_queue_callback_4CF + 44 28 CoreFoundation___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 29 CoreFoundation___CFRunLoopRun + 1996 30 CoreFoundation_CFRunLoopRunSpecific + 572 31 GraphicsServices_GSEventRunModal + 164 32 UIKitCore-[UIApplication _run] + 816 33 UIKitCore_UIApplicationMain + 340 34 SwiftUIclosure #1 (Swift.UnsafeMutablePointer<Swift.UnsafeMutablePointer<Swift.Int8>?>) -> Swift.Never in SwiftUI.(KitRendererCommon in _ACC2C5639A7D76F611E170E831FCA491)(Swift.AnyObject.Type) -> Swift.Never + 168 35 SwiftUI SwiftUI.runApp(A) -> Swift.Never + 100 36 SwiftUI static (extension in SwiftUI):SwiftUI.App.main() -> () + 180
2
2
1.1k
Oct ’24
PDFKit PDFPage.setBounds(_:for:) returns unexpected results in Xcode16
In XCode15, if you specify mediaBox for PDFDisplayBox, the page will be shrunk to fit the specified range. However, in XCode16, the page is cropped to fit the specified range, as when cropBox is specified for PDFDisplayBox. I think it's a bug because the setBounds documentation hasn't been updated, but has anyone had the same problem? Please let me know if there are any workarounds.
0
1
697
Sep ’24
PDFKit shows popup asking to download embedded font. Any way to disable this behavior?
I'm building a MacOS app which reads a lot of PDFs in the background. Some of these PDF's have an embedded font which is not installed on the system. In such cases the app shows a popup asking whether to Download or Skip the font. This seems to be a PDFKit behavior because I see the same behavior when I open the file in Preview (see screenshot) This behavior is disruptive to the user experience and I'd like to be able to disable font downloads. However I don't see any option in the PDFKit API to do so. Any ideas?
0
0
689
Sep ’24
Save large PDF file with UIDocument
Hi, I'm working with UIDocument to store a PDF file. This is code I use for saving a file. document.close(completionHandler: { (success) in if success { document.save(to: url, for: .forOverwriting, completionHandler: { (success) in if success { print("Saved file successfully") } }) } }) This code works well with a small file size. But if it's a large file like 100MB, it takes around 2-5 minutes to save the file. Is there a way to save file with the changes only? Or create an auto save function triggered whenever the user edit the file?
2
0
843
Sep ’24
View flashes when setting new PDFDocument in PDFView
I have a SwiftUI View containing a PDFView from PDFKit (via NSViewRepresentable). When setting a new PDFDocument the view flashes briefly with the background color before displaying the new document. Curiously the flashing is vastly reduced (but not eliminated) by calling layoutDocumentView() which should already be called from setDocument according to its documentation. struct SheetView: NSViewRepresentable { var pdf: PDFDocument? func makeNSView(context: Context) -> PDFView { let pdfView = PDFView() pdfView.displaysPageBreaks = false pdfView.displayMode = .singlePage pdfView.pageShadowsEnabled = false pdfView.autoScales = true return pdfView } func updateNSView(_ pdfView: PDFView, context: Context) { if pdf != pdfView.document { pdfView.document = pdf pdfView.layoutDocumentView() // reduces flashing but does not eliminate it } } }
1
0
900
Sep ’24
The application crashes when an image of a certain PDF (50 MB, 1 page) is drawn on the context page in background.
Hi Team, I am using CGPDFPage and CGContext to convert the PDF to an image. It is working fine in all circumstances but fails in one circumstance where the size of the PDF is above 50 MB and when the application is made to be on background and again opened. It is also occurring only on physical devices; emulators are working fine. We are using the following code for this conversation: fileStream.CopyTo(memoryStream); CGDataProvider provider = new CGDataProvider(memoryStream.ToArray()); CGPDFDocument cGPDFDocument = null; image = null; cGPDFDocument = new CGPDFDocument(provider); using(CGPDFPage pdfPage = cGPDFDocument?.GetPage(1)) { if (pdfPage != null) { CGRect rect = pdfPage.GetBoxRect(CGPDFBox.Media); if (pdfPage.RotationAngle == 90 || pdfPage.RotationAngle == 270) { rect = new CGRect(rect.X, rect.Y, rect.Height, rect.Width); } nfloat factor = (nfloat)0.5; CGRect bounds = new CGRect(rect.X * factor, rect.Y * factor, rect.Width * factor, rect.Height * factor); UIGraphics.BeginImageContext(bounds.Size); CGContext context = UIGraphics.GetCurrentContext(); context.SetFillColor(1.0f, 1.0f, 1.0f, 1.0f); context.FillRect(bounds); context.TranslateCTM(0, bounds.Height); context.ScaleCTM(factor, -factor); context.ConcatCTM(pdfPage.GetDrawingTransform(CGPDFBox.Crop, rect, 0, true)); context.SetRenderingIntent(CGColorRenderingIntent.Default); context.InterpolationQuality = CGInterpolationQuality.Default; context.DrawPDFPage(pdfPage); image = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); imageView.Image = image; parentView.AddSubview(imageView); } } We have added a simple application created on Xamarin.iOS platform that replicates this issue in Assets we have added the PDF with this issue https://www.syncfusion.com/downloads/support/directtrac/general/ze/PdfToImageSample-556012354 We have recorded this for the reference, https://www.syncfusion.com/downloads/support/directtrac/general/ze/CrashBGImgRec-1376481150 This issue is constantly occurring on the "context.DrawPDFPage(pdfPage);" line in my application. On the provided sample, this issue is occurring consistently when the break point is placed on the "context.DrawPDFPage(pdfPage);" line. It also occurs randomly without placing the breakpoint. We are invoking this function on DidEnterBackground override method of AppDelegate Do we need to set any to properly retrieve the image from CGPDFPage and add them into context?
1
0
1.1k
Aug ’24
PDFKit's characterIndex(at:) Method Innacurate on iOS 17 (REGRESSION)
PDFKit’s characterIndex(at:) method consistently returns the incorrect character index on iOS 17. It seems to get worse the further down the page you get. This breaks critical functionality that my app relies on. Prior to iOS 17, it would be wrong sometimes but not as consistently. This is the method in question: https://developer.apple.com/documentation/pdfkit/pdfpage/1503775-characterindex I've filed feedback FB12951475 with a sample project attached.
3
0
1.3k
Aug ’24
PDFKit - Wrapping text
Dear all, I have an app in which I'm trying to create a pdf from the data stored. Everything is working fine except the fact that the text is not following the page margins, going out of the page of being truncated without being written on the line below. Has anybody experienced the same in the past? Please assist, I'm getting out of my mind with this in the last two days... Here the code of the function which is creating the PDF. let pdfMetaData = [ kCGPDFContextCreator: "Your App Name", kCGPDFContextAuthor: "Your Name", kCGPDFContextTitle: "Allenamento" ] let pageWidth = 8.5 * 72.0 // Standard letter size in points (8.5 x 11 inches) let pageHeight = 11 * 72.0 let pageSize = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight) let margin: CGFloat = 20.0 let pdfData = NSMutableData() guard let consumer = CGDataConsumer(data: pdfData as CFMutableData) else { print("Errore nella creazione del consumer") return } var mediaBox = pageSize guard let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, pdfMetaData as CFDictionary) else { print("Errore nella creazione del contesto PDF") return } pdfContext.beginPDFPage(nil) // Parte superiore della pagina ... // Disegno del rettangolo "MATERIALE DA ALLENAMENTO" ... // Disegno del rettangolo "ESERCITAZIONI ALLENAMENTO" let exercisesRect = CGRect(x: margin, y: cellYPosition - 45, width: pageWidth - 2 * margin, height: 25) pdfContext.setFillColor(NSColor.lightGray.cgColor) pdfContext.fill(exercisesRect) pdfContext.setStrokeColor(NSColor.black.cgColor) pdfContext.stroke(exercisesRect) let exercisesText = "ESERCITAZIONI ALLENAMENTO" let exercisesAttributedString = NSAttributedString(string: exercisesText, attributes: boldAttributes) let exercisesTextPosition = CGPoint(x: exercisesRect.midX - exercisesAttributedString.size().width / 2, y: exercisesRect.midY - 5) drawText(attributedString: exercisesAttributedString, position: exercisesTextPosition, context: pdfContext) // Iniziamo a disegnare le informazioni degli esercizi let sortedExercises = training.trainingExercises.sorted { $0.order < $1.order } var currentY = exercisesRect.minY - 30 for trainingExercise in sortedExercises { // Gestione del wrap text e posizionamento su più pagine let remainingHeight = currentY - margin if remainingHeight < 100 { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegna la durata let durationText = "\(trainingExercise.duration) min" let durationAttributedString = NSAttributedString(string: durationText, attributes: boldAttributes) drawText(attributedString: durationAttributedString, position: CGPoint(x: margin, y: currentY), context: pdfContext) currentY -= 20 // Disegna la descrizione con wrap text let descriptionText = trainingExercise.exercise.exerciseDescription let descriptionAttributedString = NSAttributedString(string: descriptionText, attributes: regularAttributes) let maxTextWidth = pageWidth - 2 * margin let descriptionBoundingBox = descriptionAttributedString.boundingRect(with: CGSize(width: maxTextWidth, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading]) if currentY - descriptionBoundingBox.height < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegno della descrizione con supporto per il wrap text let descriptionFramesetter = CTFramesetterCreateWithAttributedString(descriptionAttributedString) let descriptionPath = CGPath(rect: CGRect(x: margin, y: currentY - descriptionBoundingBox.height, width: maxTextWidth, height: descriptionBoundingBox.height), transform: nil) let descriptionFrame = CTFramesetterCreateFrame(descriptionFramesetter, CFRangeMake(0, 0), descriptionPath, nil) CTFrameDraw(descriptionFrame, pdfContext) currentY -= descriptionBoundingBox.height + 10 // Disegna l'immagine sotto la descrizione if let imagePath = trainingExercise.exercise.imagePath, let image = NSImage(contentsOfFile: imagePath) { let imageCG = image.cgImage(forProposedRect: nil, context: nil, hints: nil) let imageAspect = CGFloat(imageCG!.width) / CGFloat(imageCG!.height) let targetWidth = min(maxTextWidth, CGFloat(400)) let targetHeight = targetWidth / imageAspect if currentY - targetHeight < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } let imageTargetRect = CGRect(x: margin, y: currentY - targetHeight, width: targetWidth, height: targetHeight) pdfContext.draw(imageCG!, in: imageTargetRect) currentY -= targetHeight + 10 } // Disegna una linea sottile come separatore pdfContext.setStrokeColor(NSColor.lightGray.cgColor) pdfContext.setLineWidth(1.0) let lineYPosition = currentY - 5 pdfContext.move(to: CGPoint(x: margin, y: lineYPosition)) pdfContext.addLine(to: CGPoint(x: pageWidth - margin, y: lineYPosition)) pdfContext.strokePath() currentY -= 20 // Spazio tra esercizi } pdfContext.endPDFPage() pdfContext.closePDF() let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let fileName = "Allenamento_\(dateFormatter.string(from: training.date)).pdf" if let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { let fileURL = documentsURL.appendingPathComponent(fileName) do { ... } } catch { print("Errore durante il salvataggio del PDF: \(error)") } } } private func drawText(attributedString: NSAttributedString, position: CGPoint, context: CGContext) { let line = CTLineCreateWithAttributedString(attributedString) context.textPosition = position CTLineDraw(line, context) }
0
1
862
Aug ’24
Push Button captions not properly written to PDF document using PDFKit
The Problem Push buttons (created as a PDFAnnotation using PDFKit) do not properly write the associated caption's key-value pair (within the annotation's appearance characteristics dictionary) to a PDF document. What is Happening Push button widget annotations can have a caption that is displayed as the button’s label. In the PDF 1.7 specification (ISO PDF32000-2008, s. 12.5.6.19), a widget annotation can have an ‘appearance characteristics dictionary’ (MK) with properties to construct the appearance of the widget. The caption property (CA) is used to construct a button’s caption/label. PDFKit uses the PDFAnnotation .caption property to set the value of a push button’s caption as a string. Observation 1: In an open PDF document (using PDFView), a push button widget annotation can be created and added to a PDFPage using the following code: let pushButton = PDFAnnotation(bounds: pushButtonBounds, forType: .widget, withProperties: nil) pushButton.widgetFieldType = .button pushButton.widgetControlType = .pushButtonControl pushButton.caption = "My Button" page.addAnnotation(pushButton) The PDFAnnotation .caption property is used to set the caption to the required string. As a result, the push button is correctly displayed on the PDFPage with the correct label being display on the button. While the PDF document remains open, the appearance characteristics dictionary (an PDFAppearanceCharacteristics object) retains a key-value pair for the caption with the correct value as expected. On saving/writing to the PDF file, however, the key-value pair for the caption in the appearance characteristics dictionary is not written to the PDF document’s file. Resulting PDF markup: 6 0 obj << /Rect [ 256 299.8977 356 399.8977 ] /Border [ 0 0 0 ] /T (button23) /F 4 /Subtype /Widget /DA (/.AppleSystemUIFont 13 Tf 0 g) /MK 8 0 R /C [ 0 ] /AP 9 0 R /V /Off /M (D:20250330154918Z00'00') /FT /Btn /Type /Annot /Ff 65536 >> endobj 9 0 obj << /N 10 0 R >> endobj 8 0 obj << /BG [ 0.75 ] >> endobj 10 0 obj << /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 100 100] /Resources 11 0 R /Length 170 >> stream x }ê1 Ç0 Öw~≈ ahÈ KÈ q1q0\‚`ú Ÿ¿ 8¯Ôm% u0óª‰.Ô{yπ åP°H-}ª‡à y3 ¸ %≠¡‰ %› g¨$•µMVXø‡Hé†Ö ”î“¿˜® BI•L ˆ†b A pü‰Ã @ÓpB∫ †æœs ãÙ:d8Éwÿr»/}” €∂I÷Bõ B;'+gm Ô˝„ mÙ~ L*>• endstream endobj On closing the PDF document, the assigned value for the push button’s caption is not written to the file and is lost. Observation 2: On reopening the PDF document, and assigning a new value for the already-created push button’s caption, a key-value pair for the caption is again correctly added to the PDFAnnotation appearance characteristics dictionary. On saving/writing to the PDF file, this time, the caption key-value pair in the appearance characteristics dictionary is correctly written/saved to the PDF document file. Resulting PDF markup: 6 0 obj << /Border [ 0 0 0 ] /Rect [ 256 299.8977 356 399.8977 ] /T (button23) /F 4 /BS 8 0 R /Subtype /Widget /DA (/.AppleSystemUIFont 13 Tf 0 g) /MK 9 0 R /C [ 0 ] /AP 10 0 R /V /Off /M (D:20250330154918Z00'00') /FT /Btn /Type /Annot /Ff 65536 >> endobj 10 0 obj << /N 11 0 R >> endobj 9 0 obj << /BG [ 0.75 ] /CA (My Button) >> endobj 8 0 obj << /W 0 >> endobj 11 0 obj << /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 100 100] /Resources 12 0 R /Length 163 >> stream x uè1 ¬@ Ö˜˛ä7∂√]ì´◊Î≠ ¡A 8à”a∑Vj·ø˜jë™ !ÅÑ|y/=ˆËA1òʺ]pDá|=0¬“Œb ø+Õ gùf2E≤∞Ê≈N` û·Xm©-BãZ†H Ÿ ¿≈ºPÄ= Ø míãp •¡ ÈÓÅ˙>é “kó· Ÿb#—¬ Ûã¶2∂Ñ2fiΠ;óDÌiÓ?ü>LÁûÊy;} endstream endobj Impact on User Experience: Push button captions may not be properly saved to the PDF document’s file. This may result in an application redrawing a push button without a caption/label. More so, an application that uses the caption value to “read” a button’s label (e.g., for accessibility purposes) will not be able to do so.
Replies
1
Boosts
0
Views
322
Activity
Apr ’25
iOS 18 emulator wkwebview loading pdf display blank
iOS 18 emulator wkwebview loading pdf display blank
Replies
1
Boosts
0
Views
545
Activity
Mar ’25
Occasional PDFKit crash at PageLayout::getWordRange(unsigned long, long)
At this line of code (SketchTextSelectionManager.swift:449), sometimes there will be crashes based on crashlytics reports. let selection = pdfPage.selectionForWord(at: location) This is directly calling into PDFKit's PDFPage#selection method: https://developer.apple.com/documentation/pdfkit/pdfpage/selectionforword(at:) Attached the full stacktrace: Crashed: com.apple.root.user-initiated-qos.cooperative 0 CoreGraphics 0x30c968 PageLayout::getWordRange(unsigned long, long) const + 908 1 CoreGraphics 0x30bbc0 PageLayout::getTextRangeIndex(CGPoint, CGPDFSelectionType, SelectionPrecision) const + 2292 2 CoreGraphics 0x44a53c CGPDFSelectionCreateBetweenPointsWithOptions + 384 3 PDFKit 0x8d5f8 -[PDFPage selectionFromPoint:toPoint:type:] + 168 4 PDFKit 0x92040 -[PDFPage _rvItemAtPoint:] + 64 5 PDFKit 0x91f4c -[PDFPage rvItemAtPoint:] + 84 6 PDFKit 0x8caa8 -[PDFPage selectionForWordAtPoint:] + 40 7 MyApp 0x8420e0 closure #1 in SketchTextSelectionManager.startNewTextSelection(pageId:location:) + 449 (SketchTextSelectionManager.swift:449) 8 MyApp 0x841a70 SketchTextSelectionManager.startNewTextSelection(pageId:location:) + 205 (CurrentNoteManager.swift:205) 9 libswift_Concurrency.dylib 0x61104 swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 10 libswift_Concurrency.dylib 0x63a28 (anonymous namespace)::ProcessOutOfLineJob::process(swift::Job*) + 480 11 libswift_Concurrency.dylib 0x611c4 swift::runJobInEstablishedExecutorContext(swift::Job*) + 444 12 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 13 libdispatch.dylib 0x15d8c _dispatch_root_queue_drain + 392 14 libdispatch.dylib 0x16590 _dispatch_worker_thread2 + 156 15 libsystem_pthread.dylib 0x4c40 _pthread_wqthread + 228 16 libsystem_pthread.dylib 0x1488 start_wqthread + 8 ```
Replies
0
Boosts
1
Views
496
Activity
Feb ’25
Random PDFKit crash on text selection
At this line of code (SketchTextSelectionManager.swift:378), sometimes there will be crashes based on crashlytics reports. In the reports, it seems like this only happens for RTL text range. let selection = pdfPage.selection( from: CGPoint(x: fromStart.x + 1, y: fromStart.y - 1), to: CGPoint(x: toEnd.x - 1, y: toEnd.y + 1) ) This is directly calling into PDFKit's PDFPage#selection method: https://developer.apple.com/documentation/pdfkit/pdfpage/selection(from:to:) Attached the full stacktrace: Crashed: com.apple.root.user-initiated-qos.cooperative 0 CoreGraphics 0x30598c PageLayout::convertRTLTextRangeIndexToStringRangeIndex(long) const + 156 1 CoreGraphics 0x44c3f0 CGPDFSelectionCreateBetweenPointsWithOptions + 224 2 PDFKit 0x91d00 -[PDFPage selectionFromPoint:toPoint:type:] + 168 3 MyApp 0x841044 closure #1 in SketchTextSelectionManager.handleUserTouchMoved(_:) + 378 (SketchTextSelectionManager.swift:378) 4 MyApp 0x840cb0 SketchTextSelectionManager.handleUserTouchMoved(_:) + 205 (CurrentNoteManager.swift:205) 5 libswift_Concurrency.dylib 0x60f5c swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 6 libswift_Concurrency.dylib 0x63a28 (anonymous namespace)::ProcessOutOfLineJob::process(swift::Job*) + 480 7 libswift_Concurrency.dylib 0x6101c swift::runJobInEstablishedExecutorContext(swift::Job*) + 444 8 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 9 libdispatch.dylib 0x15ec0 _dispatch_root_queue_drain + 392 10 libdispatch.dylib 0x166c4 _dispatch_worker_thread2 + 156 11 libsystem_pthread.dylib 0x3644 _pthread_wqthread + 228 12 libsystem_pthread.dylib 0x1474 start_wqthread + 8
Replies
0
Boosts
1
Views
475
Activity
Feb ’25
CGPDFOperatorTableSetCallback fails with `ID' isn't an operator.
Does anyone know why the following call fails? CGPDFOperatorTableSetCallback(operatorTable, "ID", &callback); The PDF specification seems to indicate that ID is an operator? BTW what is the proper topic/subtopic for questions about Quartz? Wasn't sure what topic on the new forums to post this under.
Replies
1
Boosts
0
Views
1.6k
Activity
Jan ’25
Exact Extract of Text from PDF
The problem is that when I read out the text in a PDF with page.string or page.attributedString, the context of the lines is lost. Instead of TermA....23,45 TermB....2,13 in an index document TermA TermB 23,45 2,13 is issued. The context of the lines (and the sequence of the letters) is lost. Is there a way to read the text from a PDF line by line?
Replies
1
Boosts
1
Views
732
Activity
Jan ’25
PDFKit - beginFindString
I am creating an iOS app that needs to parse the text from a PDF document. I can read the entire PDF document's text using the string property, but if it's a large PDF document, this could cause delays for users. From the documentation, I came across the beginFindString function, which seems to asynchronously, with no return? https://developer.apple.com/documentation/pdfkit/pdfdocument/beginfindstring(_:withoptions:)) Unfortunately I cannot find examples on how to use this function or its intended purpose/functionality, so any guidance would be appreciated. My goal is to read the PDF document one line at a time, searching for newlines ('\n'), then parsing that line as needed. I'm hoping the beginFindString function will be useful.
Replies
0
Boosts
0
Views
498
Activity
Jan ’25
iOS 18.x PDFKit Page.string and Page.attributedString return some text way out of oder
Reading text out of PDFs with PDFKit results in some text being returned way out of order when using .string or .attributedString functions. Way out of order means not just wrong sorting of words on a line or wrongly showing up on the next line (as has happened with PDFKit on older iOS releases, e.g. 17.x), but some text (one or more words) may show up near the end of a page of text, while it should show near the beginning. As Page.characterBounds(at:) is buggy in iOS 18.x returns wrong bounds, devs cannot correct such faulty PDFKit behaviour programmatically. I believe it is on Apple to fix this iOS 18 bug asap. Thank you for giving it priority as this is killing apps that need PDFKit to get and parse text data out of PDFs. I have filed Feedback FB16264926.
Replies
3
Boosts
1
Views
1.1k
Activity
Jan ’25
Issue with page.selectionForWord(at:) in Mac Designed for iPad Mode
I’m encountering an issue with the page.selectionForWord(at:) method in my application. This method has stopped working in Mac Designed for iPad mode. The functionality works fine on physical devices such as iPhone and iPad, as well as on Mac, but in this specific mode, the method no longer works, and the application crashes. It is crucial for me that this functionality works in Mac Designed for iPad mode, as rewriting the entire code for Mac would be too time-consuming, especially considering the size of the application. Interestingly, a similar method, page.selectionForLine(at:), works perfectly with the same parameters in all environments, including the Mac Designed for iPad mode. This makes the issue even more puzzling. The issue began after the latest update. The app no longer responds to the page.selectionForWord(at:) method, which causes the application to crash. I have attached a test app to reproduce the error.
Replies
1
Boosts
0
Views
637
Activity
Dec ’24
PDFAnnotation type FreeText not showing
When added a PDFAnnotation to a pdf file which already have type stamp annotation type annotation showing in PDFKit but in QLPreviewController not coming
Replies
0
Boosts
0
Views
574
Activity
Nov ’24
CoreGraphics: CGPDFPageCopyRootTaggedNode
My app uses PDFKit, but I don't know how to solve this bug at all. Under the same IOS system and device model, some users' devices may experience crashes, while our own devices are functioning normally. The following is the stack information for crashing: 0 libsystem_platform.dylib__os_unfair_lock_recursive_abort + 36 1 libsystem_platform.dylib__os_unfair_lock_lock_slow + 308 2 CoreGraphics_CGPDFPageCopyRootTaggedNode + 56 3 PDFKit-[PDFPageViewAccessibility accessibilityElements] + 76 4 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityElements] + 56 5 UIAccessibility-[NSObjectAccessibility accessibilityElementCount] + 68 6 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityHasOrderedChildren] + 44 7 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFrameForSorting] + 216 8 UIAccessibility-[NSObject _accessibilityCompareGeometry:] + 116 9 UIAccessibility-[NSObject(AXPrivCategory) accessibilityCompareGeometry:] + 52 10 CoreFoundation___CFSimpleMergeSort + 100 11 CoreFoundation___CFSimpleMergeSort + 248 12 CoreFoundation_CFSortIndexes + 260 13 CoreFoundation-[NSArray sortedArrayFromRange:options:usingComparator:] + 732 14 CoreFoundation-[NSMutableArray sortedArrayFromRange:options:usingComparator:] + 60 15 CoreFoundation-[NSArray sortedArrayUsingSelector:] + 168 16 UIAccessibility___57-[NSObject(AXPrivCategory) _accessibilityFindDescendant:]_block_invoke + 268 17 UIAccessibility___96-[NSObject(AXPrivCategory) _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:]_block_invoke + 140 18 UIAccessibility-[NSObject _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:] + 244 19 UIAccessibility-[NSObject _accessibilityFindFirstAXDescendantPassingTest:byYieldingElements:] + 272 20 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFindDescendant:] + 100 21 UIAccessibility__axuiElementForNotificationData + 276 22 UIAccessibility__massageAssociatedElementBeforePost + 36 23 UIAccessibility__UIAXBroadcastMainThread + 292 24 libdispatch.dylib__dispatch_call_block_and_release + 32 25 libdispatch.dylib__dispatch_client_callout + 20 26 libdispatch.dylib__dispatch_main_queue_drain + 980 27 libdispatch.dylib__dispatch_main_queue_callback_4CF + 44 28 CoreFoundation___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 29 CoreFoundation___CFRunLoopRun + 1996 30 CoreFoundation_CFRunLoopRunSpecific + 572 31 GraphicsServices_GSEventRunModal + 164 32 UIKitCore-[UIApplication _run] + 816 33 UIKitCore_UIApplicationMain + 340 34 SwiftUIclosure #1 (Swift.UnsafeMutablePointer<Swift.UnsafeMutablePointer<Swift.Int8>?>) -> Swift.Never in SwiftUI.(KitRendererCommon in _ACC2C5639A7D76F611E170E831FCA491)(Swift.AnyObject.Type) -> Swift.Never + 168 35 SwiftUI SwiftUI.runApp(A) -> Swift.Never + 100 36 SwiftUI static (extension in SwiftUI):SwiftUI.App.main() -> () + 180
Replies
2
Boosts
2
Views
1.1k
Activity
Oct ’24
how to refresh PDFPageOverlayViewProvid
I am using PDFPageOverlayViewProvider from pdfkit. I would like to detect changes in the overlaid view and refresh PDFPageOverlayViewProvider. Currently, it does not refresh even when the overlaid view changes. Is there a way to refresh it?
Replies
0
Boosts
0
Views
734
Activity
Oct ’24
PDFKit PDFPage.setBounds(_:for:) returns unexpected results in Xcode16
In XCode15, if you specify mediaBox for PDFDisplayBox, the page will be shrunk to fit the specified range. However, in XCode16, the page is cropped to fit the specified range, as when cropBox is specified for PDFDisplayBox. I think it's a bug because the setBounds documentation hasn't been updated, but has anyone had the same problem? Please let me know if there are any workarounds.
Replies
0
Boosts
1
Views
697
Activity
Sep ’24
PDFKit shows popup asking to download embedded font. Any way to disable this behavior?
I'm building a MacOS app which reads a lot of PDFs in the background. Some of these PDF's have an embedded font which is not installed on the system. In such cases the app shows a popup asking whether to Download or Skip the font. This seems to be a PDFKit behavior because I see the same behavior when I open the file in Preview (see screenshot) This behavior is disruptive to the user experience and I'd like to be able to disable font downloads. However I don't see any option in the PDFKit API to do so. Any ideas?
Replies
0
Boosts
0
Views
689
Activity
Sep ’24
Save large PDF file with UIDocument
Hi, I'm working with UIDocument to store a PDF file. This is code I use for saving a file. document.close(completionHandler: { (success) in if success { document.save(to: url, for: .forOverwriting, completionHandler: { (success) in if success { print("Saved file successfully") } }) } }) This code works well with a small file size. But if it's a large file like 100MB, it takes around 2-5 minutes to save the file. Is there a way to save file with the changes only? Or create an auto save function triggered whenever the user edit the file?
Replies
2
Boosts
0
Views
843
Activity
Sep ’24
View flashes when setting new PDFDocument in PDFView
I have a SwiftUI View containing a PDFView from PDFKit (via NSViewRepresentable). When setting a new PDFDocument the view flashes briefly with the background color before displaying the new document. Curiously the flashing is vastly reduced (but not eliminated) by calling layoutDocumentView() which should already be called from setDocument according to its documentation. struct SheetView: NSViewRepresentable { var pdf: PDFDocument? func makeNSView(context: Context) -> PDFView { let pdfView = PDFView() pdfView.displaysPageBreaks = false pdfView.displayMode = .singlePage pdfView.pageShadowsEnabled = false pdfView.autoScales = true return pdfView } func updateNSView(_ pdfView: PDFView, context: Context) { if pdf != pdfView.document { pdfView.document = pdf pdfView.layoutDocumentView() // reduces flashing but does not eliminate it } } }
Replies
1
Boosts
0
Views
900
Activity
Sep ’24
Can DRM Be Applied to pdfkit?
I need to apply security measures to a PDF. My goal is to prevent it from being leaked, and even if it is leaked, I want to ensure that the PDF cannot be viewed. Is it possible to use pdfkit and apply DRM to achieve this?​⬤
Replies
0
Boosts
0
Views
765
Activity
Sep ’24
The application crashes when an image of a certain PDF (50 MB, 1 page) is drawn on the context page in background.
Hi Team, I am using CGPDFPage and CGContext to convert the PDF to an image. It is working fine in all circumstances but fails in one circumstance where the size of the PDF is above 50 MB and when the application is made to be on background and again opened. It is also occurring only on physical devices; emulators are working fine. We are using the following code for this conversation: fileStream.CopyTo(memoryStream); CGDataProvider provider = new CGDataProvider(memoryStream.ToArray()); CGPDFDocument cGPDFDocument = null; image = null; cGPDFDocument = new CGPDFDocument(provider); using(CGPDFPage pdfPage = cGPDFDocument?.GetPage(1)) { if (pdfPage != null) { CGRect rect = pdfPage.GetBoxRect(CGPDFBox.Media); if (pdfPage.RotationAngle == 90 || pdfPage.RotationAngle == 270) { rect = new CGRect(rect.X, rect.Y, rect.Height, rect.Width); } nfloat factor = (nfloat)0.5; CGRect bounds = new CGRect(rect.X * factor, rect.Y * factor, rect.Width * factor, rect.Height * factor); UIGraphics.BeginImageContext(bounds.Size); CGContext context = UIGraphics.GetCurrentContext(); context.SetFillColor(1.0f, 1.0f, 1.0f, 1.0f); context.FillRect(bounds); context.TranslateCTM(0, bounds.Height); context.ScaleCTM(factor, -factor); context.ConcatCTM(pdfPage.GetDrawingTransform(CGPDFBox.Crop, rect, 0, true)); context.SetRenderingIntent(CGColorRenderingIntent.Default); context.InterpolationQuality = CGInterpolationQuality.Default; context.DrawPDFPage(pdfPage); image = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); imageView.Image = image; parentView.AddSubview(imageView); } } We have added a simple application created on Xamarin.iOS platform that replicates this issue in Assets we have added the PDF with this issue https://www.syncfusion.com/downloads/support/directtrac/general/ze/PdfToImageSample-556012354 We have recorded this for the reference, https://www.syncfusion.com/downloads/support/directtrac/general/ze/CrashBGImgRec-1376481150 This issue is constantly occurring on the "context.DrawPDFPage(pdfPage);" line in my application. On the provided sample, this issue is occurring consistently when the break point is placed on the "context.DrawPDFPage(pdfPage);" line. It also occurs randomly without placing the breakpoint. We are invoking this function on DidEnterBackground override method of AppDelegate Do we need to set any to properly retrieve the image from CGPDFPage and add them into context?
Replies
1
Boosts
0
Views
1.1k
Activity
Aug ’24
PDFKit's characterIndex(at:) Method Innacurate on iOS 17 (REGRESSION)
PDFKit’s characterIndex(at:) method consistently returns the incorrect character index on iOS 17. It seems to get worse the further down the page you get. This breaks critical functionality that my app relies on. Prior to iOS 17, it would be wrong sometimes but not as consistently. This is the method in question: https://developer.apple.com/documentation/pdfkit/pdfpage/1503775-characterindex I've filed feedback FB12951475 with a sample project attached.
Replies
3
Boosts
0
Views
1.3k
Activity
Aug ’24
PDFKit - Wrapping text
Dear all, I have an app in which I'm trying to create a pdf from the data stored. Everything is working fine except the fact that the text is not following the page margins, going out of the page of being truncated without being written on the line below. Has anybody experienced the same in the past? Please assist, I'm getting out of my mind with this in the last two days... Here the code of the function which is creating the PDF. let pdfMetaData = [ kCGPDFContextCreator: "Your App Name", kCGPDFContextAuthor: "Your Name", kCGPDFContextTitle: "Allenamento" ] let pageWidth = 8.5 * 72.0 // Standard letter size in points (8.5 x 11 inches) let pageHeight = 11 * 72.0 let pageSize = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight) let margin: CGFloat = 20.0 let pdfData = NSMutableData() guard let consumer = CGDataConsumer(data: pdfData as CFMutableData) else { print("Errore nella creazione del consumer") return } var mediaBox = pageSize guard let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, pdfMetaData as CFDictionary) else { print("Errore nella creazione del contesto PDF") return } pdfContext.beginPDFPage(nil) // Parte superiore della pagina ... // Disegno del rettangolo "MATERIALE DA ALLENAMENTO" ... // Disegno del rettangolo "ESERCITAZIONI ALLENAMENTO" let exercisesRect = CGRect(x: margin, y: cellYPosition - 45, width: pageWidth - 2 * margin, height: 25) pdfContext.setFillColor(NSColor.lightGray.cgColor) pdfContext.fill(exercisesRect) pdfContext.setStrokeColor(NSColor.black.cgColor) pdfContext.stroke(exercisesRect) let exercisesText = "ESERCITAZIONI ALLENAMENTO" let exercisesAttributedString = NSAttributedString(string: exercisesText, attributes: boldAttributes) let exercisesTextPosition = CGPoint(x: exercisesRect.midX - exercisesAttributedString.size().width / 2, y: exercisesRect.midY - 5) drawText(attributedString: exercisesAttributedString, position: exercisesTextPosition, context: pdfContext) // Iniziamo a disegnare le informazioni degli esercizi let sortedExercises = training.trainingExercises.sorted { $0.order < $1.order } var currentY = exercisesRect.minY - 30 for trainingExercise in sortedExercises { // Gestione del wrap text e posizionamento su più pagine let remainingHeight = currentY - margin if remainingHeight < 100 { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegna la durata let durationText = "\(trainingExercise.duration) min" let durationAttributedString = NSAttributedString(string: durationText, attributes: boldAttributes) drawText(attributedString: durationAttributedString, position: CGPoint(x: margin, y: currentY), context: pdfContext) currentY -= 20 // Disegna la descrizione con wrap text let descriptionText = trainingExercise.exercise.exerciseDescription let descriptionAttributedString = NSAttributedString(string: descriptionText, attributes: regularAttributes) let maxTextWidth = pageWidth - 2 * margin let descriptionBoundingBox = descriptionAttributedString.boundingRect(with: CGSize(width: maxTextWidth, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading]) if currentY - descriptionBoundingBox.height < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegno della descrizione con supporto per il wrap text let descriptionFramesetter = CTFramesetterCreateWithAttributedString(descriptionAttributedString) let descriptionPath = CGPath(rect: CGRect(x: margin, y: currentY - descriptionBoundingBox.height, width: maxTextWidth, height: descriptionBoundingBox.height), transform: nil) let descriptionFrame = CTFramesetterCreateFrame(descriptionFramesetter, CFRangeMake(0, 0), descriptionPath, nil) CTFrameDraw(descriptionFrame, pdfContext) currentY -= descriptionBoundingBox.height + 10 // Disegna l'immagine sotto la descrizione if let imagePath = trainingExercise.exercise.imagePath, let image = NSImage(contentsOfFile: imagePath) { let imageCG = image.cgImage(forProposedRect: nil, context: nil, hints: nil) let imageAspect = CGFloat(imageCG!.width) / CGFloat(imageCG!.height) let targetWidth = min(maxTextWidth, CGFloat(400)) let targetHeight = targetWidth / imageAspect if currentY - targetHeight < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } let imageTargetRect = CGRect(x: margin, y: currentY - targetHeight, width: targetWidth, height: targetHeight) pdfContext.draw(imageCG!, in: imageTargetRect) currentY -= targetHeight + 10 } // Disegna una linea sottile come separatore pdfContext.setStrokeColor(NSColor.lightGray.cgColor) pdfContext.setLineWidth(1.0) let lineYPosition = currentY - 5 pdfContext.move(to: CGPoint(x: margin, y: lineYPosition)) pdfContext.addLine(to: CGPoint(x: pageWidth - margin, y: lineYPosition)) pdfContext.strokePath() currentY -= 20 // Spazio tra esercizi } pdfContext.endPDFPage() pdfContext.closePDF() let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let fileName = "Allenamento_\(dateFormatter.string(from: training.date)).pdf" if let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { let fileURL = documentsURL.appendingPathComponent(fileName) do { ... } } catch { print("Errore durante il salvataggio del PDF: \(error)") } } } private func drawText(attributedString: NSAttributedString, position: CGPoint, context: CGContext) { let line = CTLineCreateWithAttributedString(attributedString) context.textPosition = position CTLineDraw(line, context) }
Replies
0
Boosts
1
Views
862
Activity
Aug ’24