导出为 PDF 时避免光栅化 UITextView

问题描述 投票:0回答:1

我正在尝试将

UIView
渲染为 PDF,同时将文本元素保留为实际文本而不是光栅化它们。

我使用 TextKit 2 支持的

UITextView
NSTextLayoutManager
来提供内容。然而,无论我做什么,
UITextView
都会被光栅化为位图。

这是基本代码:

let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)

let data = renderer.pdfData { (context) in
    for page in self.pageViews {
        context.beginPage()
        let cgContext = context.cgContext               
        page.layer.render(in: cgContext)
    }
}

页面视图通常包含一个

UITextView
,它使用了一些高级布局,因此不幸的是我不能将其扔进单个
NSAttributedString
并绘制到 CoreText 上下文中。

有一个 hack 可以让 UILabel

 将自己渲染为非光栅化文本,如果我理解正确的话,它的工作原理是在当前上下文中实际绘制它们。

有趣的是,当使用 TextKit 2 通过

UILabel

 向文本视图提供 
NSTextAttachmentViewProvider
 视图时,文本视图内的 
UILabel
 
不会被光栅化:

这暗示实际的文本片段是在绘制时被光栅化的文本片段,而不是整个视图,我是对的。您可以枚举文本片段并将它们直接绘制在上下文上,这使得它们保留为文本而不是成为位图:

page.textView?.textLayoutManager?.enumerateTextLayoutFragments(from: location, options: [.ensuresLayout, .estimatesSize, .ensuresExtraLineFragment], using: { fragment in let frame = fragment.layoutFragmentFrame fragment.draw(at: frame.origin, in: cgContext) return true })

但是,这会导致其他问题,因为布局坐标将遍布各处,并且不限于文本视图本身(对于我的自定义 
NSTextLayoutFragment

类更是如此),并且文本附件也不会以这种方式绘制,但显示倾斜的占位符图标。

我想知道是否有办法让 

UITextView

NSTextLayoutManager
绘制类似于
UILabel
的内容,这样片段将在 PDF 中保留为文本,而不是成为位图?
    

ios swift uitextview textkit
1个回答
0
投票
UITextView

作为真实文本渲染到 PDF 中的简单方法。它目前仅支持每个段落一个文本片段,因为您显然无法使用

fragment.draw(at:origin:)
来显示文本片段。
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
let data = renderer.pdfData { (context) in

    let cgContext = context.cgContext

    textView.textLayoutManager.enumerateTextLayoutFragments(from: location, options: [.ensuresLayout, .estimatesSize, .ensuresExtraLineFragment], using: { fragment in
        
        let frame = fragment.layoutFragmentFrame
        let origin = page.textView?.frame.origin ?? CGPointZero
        
        var actualFrame = frame
        actualFrame.origin.x += origin.x
        actualFrame.origin.y += origin.y
                                
        
        if let provider = fragment.textAttachmentViewProviders.first, let view = provider.view {
            // Draw a text attachment
            let attachmentFrame = fragment.frameForTextAttachment(at: fragment.rangeInElement.location)
            actualFrame.origin.y += attachmentFrame.origin.y
            
            cgContext.saveGState()
            cgContext.translateBy(x: actualFrame.origin.x, y: actualFrame.origin.y)
            view.layer.render(in: cgContext)
            cgContext.restoreGState()
            
            return true
        } else {
            // Draw a normal paragraph
            fragment.draw(at: origin, in: cgContext)
        }

        return true
    })


}

我不知道为什么苹果决定不将此作为默认行为包含在 
UITextView

中,因为这似乎完全有可能。

    

© www.soinside.com 2019 - 2024. All rights reserved.