iOS 11 PDFKit 墨水注释 - 无法填充 UIBezierPath

Posted

技术标签:

【中文标题】iOS 11 PDFKit 墨水注释 - 无法填充 UIBezierPath【英文标题】:iOS 11 PDFKit Ink annotation - cannot fill UIBezierPath 【发布时间】:2018-03-01 00:53:40 【问题描述】:

我正在使用带有子类型墨水的 PDFAnnotation() 类向 PDFDocument 添加墨水注释。这个想法是捕获使用触摸绘制的签名。

受 UberSignature 启发,我的 UIBezierPath 是一系列应该用颜色填充的矩形。但是,当我将注释添加到 PDFDocument 时,它没有被填充。

UIBezierPath 的 fill() 方法在添加到 PDFAnnotation 时似乎什么都不做?

如果我使用相同的 UIBezierPath 并将其绘制在 UIImage 上,它会正确填充纯色。

对可能出现的问题有任何想法吗?

有问题的代码:

UIColor.red.setStroke()
UIColor.red.setFill()

var path = UIBezierPath()
path.append(myRectangles)
path.fill()

var annotation = PDFAnnotation(bounds: path.bounds, forType: .ink, withProperties: nil)
annotation.add(path)
myPDFPage.addAnnotation(annotation)

在屏幕截图中,我尝试编写普通文本和两个示例行。左边的线画得很慢,右边的线画得很快。这个想法是让线条的宽度根据绘制速度而变化,以使签名看起来更自然/逼真。

【问题讨论】:

您是否找到了根据 Pencil 的压力、速度和位置调整线条宽度和样式的方法?我尝试实现与 Apple 在其示例应用 (developer.apple.com/documentation/uikit/…) 中使用的相同方式,但遇到了严重的性能问题。 是的,我使用了我的问题和答案中显示的技术,我将线“切碎”成许多不同大小的较小四边形。为了提高性能,我确保制作多个注释而不是将所有内容集中在一起,并且我还实现了位图缓存。 IE。我存储为每 x 次迭代计算的实际位图,这样当添加笔画时,我只需在每次绘制时渲染最新的笔画。其余的被缓存。 【参考方案1】:

我设法找到了一个似乎相对最优的问题的解决方案。

诀窍是创建 PDFAnnotation 的子类并覆盖 draw(with box:, in context:) 函数。在这个函数中我可以使用 drawPath(using: .fill) 方法来填充 bezier 路径。

代码可能如下所示:

class SignatureAnnotation : PDFAnnotation 
  public var myPath : UIBezierPath = UIBezierPath()

  override func draw(with box: PDFDisplayBox, in context: CGContext) 
    context.saveGState()
    self.page?.transform(context, for: box)
    context.beginPath()
    context.setLineWidth(0.1)
    context.setShouldAntialias(true)
    context.addPath(self.myPath.cgPath.mutableCopy()!)
    context.drawPath(using: .fill)
    context.restoreGState()
  

将此注释(类型.stamp)添加到PDF而不是墨水注释,所有内容都将呈现为矢量(完全可缩放而不会被像素化) - 并且在保存到文件时将与PDF的其余部分一起保存或数据缓冲区。

唯一的缺点是 UIBezierPath 不能太复杂,如果 draw() 函数耗时太长会引入闪烁。这可以通过简单地将 UIBezierPath 拆分为多个单独的路径来解决,每个路径都有自己的注释。

【讨论】:

此注释是否在其他 PDF 渲染应用程序中可见?是否可以像注释一样进行操作(移动、更改大小、复制、粘贴)? 是的,在其他 PDF 渲染应用程序中可见(我已经使用 Apple Preview 和内置的 Google Chrome PDF 查看器进行了测试)。之后我对操作注释不感兴趣,所以我没有尝试过。 您好,请您上传一个示例代码,您是如何做到这一点的?将不胜感激! @jksoegaard 谢谢你分享这个。试图在我的项目中实现您的解决方案,我只能绘制 UIBezierPath 的第一部分,而其他部分没有被绘制。能否请您再分享一些您的代码? 您是否尝试在调试器中检查您的 UIBezierPath 以检查实际上有多个段? - 对我来说没有问题。【参考方案2】:

InkAnnotation 呈现为描边路径的集合。没有办法按照PDF reference 1.4 page 508填充颜色。

Apple 的 Preview 使用 Stamp 注释将签名包含在 PDF 中。我尝试使用 PDFKit 对其进行逆向工程,但我看不到任何包含我放置在 PDF 中的签名的矢量数据。 PDFKit 在这里可能不够用。

(lldb) po annotation.annotationKeyValues
▿ 10 elements
  ▿ 0 : 2 elements
    ▿ key : AnyHashable("/AAPL:Hash")
      - value : "/AAPL:Hash"
    - value : /264236ab9aaabfe2d536167a89c26c2d
  ▿ 1 : 2 elements
    ▿ key : AnyHashable("/DA")
      - value : "/DA"
    - value : /Helvetica 12 Tf 0 g
  ▿ 2 : 2 elements
    ▿ key : AnyHashable("/T")
      - value : "/T"
    - value : Wojciech Nagrodzki
  ▿ 3 : 2 elements
    ▿ key : AnyHashable("/F")
      - value : "/F"
    - value : 4
  ▿ 4 : 2 elements
    ▿ key : AnyHashable("/Subtype")
      - value : "/Subtype"
    - value : /Stamp
  ▿ 5 : 2 elements
    ▿ key : AnyHashable("/Name")
      - value : "/Name"
    - value : /Draft
  ▿ 6 : 2 elements
    ▿ key : AnyHashable("/Rect")
      - value : "/Rect"
    - value : NSRect: 5.8745389999999995, 748.38995, 307.66119599999996, 87.648936000000049
  ▿ 7 : 2 elements
    ▿ key : AnyHashable("/Border")
      - value : "/Border"
    - value : PDFBorder: solid lineWidth:2.8 hCorner:0.0 vCorner:0.0 dashCount:0 dashPattern:(
)
  ▿ 8 : 2 elements
    ▿ key : AnyHashable("/Type")
      - value : "/Type"
    - value : /Annot
  ▿ 9 : 2 elements
    ▿ key : AnyHashable("/C")
      - value : "/C"
    - value : kCGColorSpaceModelRGB 0 0 0 1 

你使用的fill()方法在当前图形上下文中填充路径,这与注解无关。

如果使用图章注释失败,您还可以在图形上下文中呈现路径,将其转换为图像并放置在 PDF 中。但我不确定你是否考虑到这一点。

您可以在Adobe's archives 中找到更多 PDF 参考资料。

【讨论】:

遗憾的是,这些都不能真正解决问题。与墨迹注释的矢量格式相反,图像在放大时会像素化,因此不是最理想的。在 PDF 中添加图像也是有问题的,因为 PDFKit 实际上没有任何更改 PDF 内容的机制 - 只有注释。与此同时,前几天我实际上解决了这个问题 - 现在添加一个带有具体细节的答案。

以上是关于iOS 11 PDFKit 墨水注释 - 无法填充 UIBezierPath的主要内容,如果未能解决你的问题,请参考以下文章

PDFKit iOS 11:如何更改Ink注释的线宽?

Apple 的 PDFKit:带有 Ink 注释的免费绘图

如何在 PDFView (swift PDFKit) 中注释圆角填充图像

如何覆盖 PDFAnnotation IOS-PDFKIT 上的绘制方法

IOS PDFKit - 注释内容仅在选中时可见

使用 Swift 5 - PDFKit 在 iOS 中编辑和保存现有的 pdf 文档