日志记录#

从版本 1.19.0 开始,更新 PDF 文档时支持日志记录功能。

日志记录是一种日志机制,允许对 PDF 文档的更改进行撤销重新应用。类似于现代数据库系统中的 LUW(“逻辑工作单元”),可以将一组更新操作组合成一个“操作”。在 MuPDF 的日志记录功能中,一个操作扮演着 LUW 的角色。

注意

与数据库系统中的 LUW 实现不同的是,MuPDF 的日志记录功能发生在文档级别。不支持同时更新多个 PDF 文档:需要在此处建立自己的逻辑。

  • 必须通过文档方法来启用日志记录功能。对于现有文档或新文档,日志记录功能都是可用的。只能通过关闭文件来禁用日志记录功能。

  • 一旦启用,所有更改都必须在一个操作内部进行,否则将引发异常。操作通过文档方法启动和停止。在这两个调用之间发生的更新组成一个 LUW,因此可以集体回滚或重新应用,或者,在 MuPDF 术语中称为“撤销”和“重做”。

  • 在任何时候,可以查询日志记录状态:日志记录是否启用、已记录了多少个操作、是否可以“撤销”或“重做”、当前在日志中的位置等等。

  • 日志可以保存到文件或文件加载。这些都是文档方法。

  • 加载日志文件时,会检查与文档的兼容性,并在成功时自动启用日志记录功能。

  • 对于正在进行日志记录的现有 PDF 文档,提供了一个特殊的新保存方法:Document.save_snapshot()。这会执行一个特殊的增量保存,其中包括到目前为止的所有日志记录的更新。如果其日志文件同时保存(紧随文档快照之后),那么文档和日志就是同步的,之后可以一起用于撤销或重做操作,或继续进行日志记录的更新 – 就如同没有中断发生一样。

  • 快照 PDF 在各方面都是有效的 PDF 文档,且完全可用。然而,如果文档在不使用其日志文件的情况下以任何方式发生更改,就会发生不同步,并且日志文件将无法使用。

  • 快照文件的结构类似于增量更新。然而,内部日志记录逻辑要求,保存操作必须发生在新文件中。因此用户应制定文件命名约定,以支持原始 PDF(例如 original.pdf)与其快照集(例如 original-snap1.pdf / original-snap1.logoriginal-snap2.pdf / original-snap2.log 等)之间可识别的关系。

示例会话 1#

描述

  • 创建一个新的 PDF 并启用日志记录功能。然后添加一个页面和一些文本行 – 每一项都作为一个独立的操作。

  • 在日志中导航,撤销和重做这些更新,并显示状态和文件结果

    >>> import pymupdf
    >>> doc=pymupdf.open()
    >>> doc.journal_enable()
    
    >>> # try update without an operation:
    >>> page = doc.new_page()
    mupdf: No journalling operation started
    ... omitted lines
    RuntimeError: No journalling operation started
    
    >>> doc.journal_start_op("op1")
    >>> page = doc.new_page()
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op2")
    >>> page.insert_text((100,100), "Line 1")
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op3")
    >>> page.insert_text((100,120), "Line 2")
    >>> doc.journal_stop_op()
    
    >>> doc.journal_start_op("op4")
    >>> page.insert_text((100,140), "Line 3")
    >>> doc.journal_stop_op()
    
    >>> # show position in journal
    >>> doc.journal_position()
    (4, 4)
    >>> # 4 operations recorded - positioned at bottom
    >>> # what can we do?
    >>> doc.journal_can_do()
    {'undo': True, 'redo': False}
    >>> # currently only undos are possible. Print page content:
    >>> print(page.get_text())
    Line 1
    Line 2
    Line 3
    
    >>> # undo last insert:
    >>> doc.journal_undo()
    >>> # show combined status again:
    >>> doc.journal_position();doc.journal_can_do()
    (3, 4)
    {'undo': True, 'redo': True}
    >>> print(page.get_text())
    Line 1
    Line 2
    
    >>> # our position is now second to last
    >>> # last text insertion was reverted
    >>> # but we can redo / move forward as well:
    >>> doc.journal_redo()
    >>> # our combined status:
    >>> doc.journal_position();doc.journal_can_do()
    (4, 4)
    {'undo': True, 'redo': False}
    >>> print(page.get_text())
    Line 1
    Line 2
    Line 3
    >>> # line 3 has appeared again!
    

示例会话 2#

描述

  • 类似于上一个,但在撤销了一些操作之后,我们现在添加了一个不同的更新。这将导致

    • 已撤销的日志条目被永久移除

    • 新的更新操作将成为新的最后一个条目。

    >>> doc=pymupdf.open()
    >>> doc.journal_enable()
    >>> doc.journal_start_op("Page insert")
    >>> page=doc.new_page()
    >>> doc.journal_stop_op()
    >>> for i in range(5):
            doc.journal_start_op("insert-%i" % i)
            page.insert_text((100, 100 + 20*i), "text line %i" %i)
            doc.journal_stop_op()
    
    >>> # combined status info:
    >>> doc.journal_position();doc.journal_can_do()
    (6, 6)
    {'undo': True, 'redo': False}
    
    >>> for i in range(3):  # revert last three operations
            doc.journal_undo()
    >>> doc.journal_position();doc.journal_can_do()
    (3, 6)
    {'undo': True, 'redo': True}
    
    >>> # now do a different update:
    >>> doc.journal_start_op("Draw some line")
    >>> page.draw_line((100,150), (300,150))
    Point(300.0, 150.0)
    >>> doc.journal_stop_op()
    >>> doc.journal_position();doc.journal_can_do()
    (4, 4)
    {'undo': True, 'redo': False}
    
    >>> # this has changed the journal:
    >>> # previous last 3 text line operations were removed, and
    >>> # we have only 4 operations: drawing the line is the new last one
    

本软件按“原样”提供,不提供任何明示或暗示的担保。本软件根据许可分发,除该许可条款明确授权外,不得复制、修改或分发。请参考 artifex.com 上的许可信息,或联系 Artifex Software Inc., 39 Mesa Street, Suite 108A, San Francisco CA 94129, United States 获取更多信息。