【问题标题】:CATiledLayer basics: Why is CATiledLayer's drawLayer:inContext: called so often when rendering PDFs?CATiledLayer 基础知识:为什么在渲染 PDF 时经常调用 CATiledLayer 的 drawLayer:inContext:?
【发布时间】:2012-05-13 19:39:07
【问题描述】:

我试图了解CATiledLayer 在使用CGContextDrawPDFPage() 呈现PDF 页面时的工作原理。

我的理解是drawLayer:inContext: 在每个图块和详细级别调用一次。对吗?

在我的平铺层的代表中,我调用CGContextDrawPDFPage(). 但是,我注意到(通过将日志放入drawLayer:inContext:)如果我将平铺层的平铺尺寸变小,drawLayer:inContext: 会被更频繁地调用。 这让我想知道:

  • 我的 PDF 页面是否绘制/渲染了 x 次?
  • 还是 CGContextDrawPDFPage() 神奇地知道要绘制页面的哪个部分?
  • 渲染PDF页面时,CATiledLayer是不是很浪费资源?它有什么优势?

【问题讨论】:

    标签: objective-c ios core-graphics catiledlayer


    【解决方案1】:

    我注意到,如果我将平铺层的平铺尺寸缩小,drawLayer:inContext: 会更频繁地被调用。

    是的,当然。假设您的图层大小相同,那么如果您告诉它使用较小的图块,它将需要更多的图块来覆盖该区域。

    我的 PDF 页面是否被绘制/渲染了 x 次?

    因为您对每个图块调用一次 CGContextDrawPDFPage(),所以是的。

    不过,这可能不是问题,因为:

    CGContextDrawPDFPage() 是否神奇地知道要绘制页面的哪个部分?

    可以,但不需要任何魔法。

    在 CATiledLayer 调用 -drawLayer:inContext: 之前,它会将 CGContext 的剪辑设置为仅包含该图块的区域。 PDF 绘图代码可以获取剪辑边界(通过CGContextGetClipBoundingBox),然后选择仅呈现该矩形内的内容。

    也就是说,有两个警告:

    1. CGContextDrawPDFPage() 是一个黑匣子,因此它实际上可能不会进行优化。这似乎很明显,但您必须检查性能数据,看看它是否真的发生了。
    2. 在解析和布局 PDF 内容时仍有相当大的开销。每次调用 CGContextDrawPDFPage 时,您仍可能会产生部分费用——这实际上取决于 CG 的智能程度,以及它是否在内部缓存内容。

    渲染PDF页面时,CATiledLayer是不是很浪费资源?它有什么优势?

    CATiledLayer 的优势主要在于节省内存:存储渲染内容的位图非常大,因此渲染并仅保留当前在屏幕上可见的内容是值得的。它还提供了一种机制,用于缓存最近可见或可能很快再次可见的区域,具体取决于用户缩放和滚动的方式。

    折衷方案是:您必须将绘图分离到每个图块的单独调用中,并且您可能需要比其他方式更频繁地渲染到图块中。

    根据视图的大小、放大/缩小的程度、绘制 PDF 的成本以及应用程序中发生的其他情况,使用 CATiledLayer 可能有意义,也可能没有意义。您可以查看性能数据并做出决定。

    【讨论】:

    • 我明白了。感谢您对这个话题有所了解。我希望,Apple 有一天会在这里添加更多文档和 API。特别是他们现在似乎能够在 Safari 中查看 PDF 时支持文本选择,但 API 并未公开。也许如果那样的话,文档将被更新到。
    • 如果您想查看有关此主题的其他文档,请向 Apple 提出建议,方法是提交错误或使用“此文档对您有帮助吗?”基于 Web 的文档上的按钮。请具体说明您认为缺少哪些文档,因为它们无法读懂您的想法。
    • 我今天刚刚在查看developer.apple.com/library/ios/#samplecode/ZoomingPDFViewer/… 示例代码时遇到了这个问题,它似乎在 TitledPDFView 中,它填充了滚动视图的整个大小的矩形(这是不正确的,它应该只填充由上下文的边界框表示的区域),然后它只是调用 CGContextDrawPDFPage,而没有提及要显示 pdf 页面的哪个部分。我知道它有上下文,但仍然不清楚 CGContextDrawPDFPage 是否足够聪明,只能渲染该区域,或者以该区域为中心的整个 pdf,等等
    • 减少开销的一种方法是设置图块大小,以便覆盖暴露的屏幕区域需要不超过 4 个图块。
    【解决方案2】:

    因为食人魔...啊哼,PDF 就像洋葱一样。 QuartzCore大量基于 PDF 渲染方法(以至于它的早期文档甚至提到了这个事实),并且 CATiledLayer 使用特定的“平铺”渲染方法,它指定要重复绘制的对象.因此,当 tile 被移动或更新或其他任何事情时,图层需要更多数据,因此在一个或多个后台线程中调用 drawLayer:inContext:。

    CATiledLayers 也非常高效,因为它们大量使用缓存并且只加载可见层。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-15
      • 2017-01-26
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2011-07-31
      • 1970-01-01
      相关资源
      最近更新 更多