故事#

  • v1.21.0 新增

方法 / 属性

简要描述

Story.reset()

“回退”故事输出到其开头

Story.place()

计算故事内容以适应提供的矩形

Story.draw()

将计算出的内容写入当前页面

Story.element_positions()

记录当前处理的故事内容的回调函数

Story.body

故事底层 body

Story.write()

将 Story 放置并绘制到 DocumentWriter

Story.write_stabilized()

将 html 内容迭代布局到 DocumentWriter

Story.write_with_links()

类似 write() 但也会创建 PDF 链接

Story.write_stabilized_with_links()

类似 write_stabilized() 但也会创建 PDF 链接

Story.fit()

寻找包含故事 self 的最优矩形。

Story.fit_scale()

Story.fit_height()

Story.fit_width()

类 API

class Story#
__init__(self, html=None, user_css=None, em=12, archive=None)#

创建一个 故事,可选提供 HTML 和 CSS 源代码。HTML 会被解析,并作为 DOM (文档对象模型) 保存在 Story 中。

可以修改此结构:可以通过使用 Xml 类的方法来添加、复制、修改或删除内容(文本、图片)。

完成后,故事 可以被写入任何设备;在典型使用中,设备可以由 DocumentWriter 提供以创建新页面。

以下是一些通用说明

  • Story 构造函数解析并验证提供的 HTML 以创建 DOM。

  • PyMuPDF 提供了多种操作 HTML 源代码的方法,通过提供对底层 DOM 节点 的访问。文档可以完全通过编程从头构建,或者可以相当随意地修改现有 DOM。有关此接口的详细信息,请参见 Xml 类。

  • 如果不再需要对 DOM 进行更改,则故事已准备好进行布局并发送到一系列设备(通常由 DocumentWriter 提供以生成新页面)。

  • 下一步是放置故事并将其写出。这可以直接通过循环调用 place()draw() 来完成,或者,循环可以由 write()write_stabilised() 方法为您处理。选择哪种方法主要取决于个人偏好。

    • 要使用第一种方式,应使用以下循环

      1. 获取合适的写入设备;通常通过从 DocumentWriter 请求新的空白页。

      2. 确定页面上一个或多个应接收 故事 数据的矩形。请注意,并非每个页面都需要具有相同的矩形集。

      3. 将每个矩形传递给 故事 以放置它,了解该矩形的哪一部分已被填充,以及是否存在未容纳的更多故事数据。此步骤可以重复多次,并调整矩形,直到调用者对结果满意为止。

      4. 可选地,此时我们可以通过调用 element_positions() 方法来请求有关感兴趣项目放置位置的详细信息。如果项目的整数 heading 属性为非零(对应于 HTML 标签 h1 - h6),如果其 id 属性不是 None(对应于 HTML 标签 id),或者如果其 href 属性不是 None(响应于 HTML 标签 href),则认为它们是感兴趣的项目。这可以方便地用于自动生成目录、图片索引等。

      5. 接下来,使用 draw() 方法将该矩形绘制到设备上。

      6. 如果最近一次调用 place() 表明所有故事数据都已适应,则现在停止。

      7. 否则,我们可以循环回去。如果当前设备(页面)上有更多矩形需要放置,我们跳回步骤 3 - 如果没有,我们跳回步骤 1 获取新设备。

    • 或者,如果您正在使用 DocumentWriter,可以使用 write()write_stabilized() 方法。这些方法为您处理所有循环,作为交换,需要提供控制行为的回调(特别是枚举要使用的矩形/页面的回调)。

  • 故事 的哪一部分会落在哪个矩形/哪个页面上,完全由 Story 对象控制,无法预测。

  • 图片可以是 故事 的一部分。它们将与任何周围文本一起放置。

  • 多个故事可以 - 相互独立地 - 写入同一页面。例如,可以为页面页眉、页面页脚、常规文本、评论框等设置单独的故事。

参数:
  • html (str) – HTML 源代码。如果省略,则生成基本最低内容(见下文)。如果提供,则不需要完整的 HTML 文档。内置源代码解析器将容忍(许多/大多数)HTML 语法错误,并且也接受像 "<b>Hello, World!</b>" 这样的 HTML 片段。

  • user_css (str) – CSS 源代码。如果提供,必须包含有效的 CSS 规范。

  • em (float) – 默认文本字体大小。

  • archive

    一个 Archive,从中加载资源进行渲染。目前支持的资源类型是图片和文本字体。如果省略,故事将不会尝试查找任何此类数据,因此可能产生不完整的输出。

    注意

    除了实际的 archive,也可以提供用于 创建 Archive 的有效参数 – 在这种情况下,将临时构建一个 archive。因此,除了 story = pymupdf.Story(archive=pymupdf.Archive("myfolder")),也可以更简洁地写成 story = pymupdf.Story(archive="myfolder")

place(where)#

计算故事内容中适合提供的矩形的部分。该方法维护一个指针,指示故事内容中已写入的部分,并在下次调用时从该指针的位置恢复。

参数:

where (rect_like) – 将当前内容部分布局以适应此矩形。这必须是页面 MediaBox 的子矩形。

返回类型:

tuple[bool, rect_like]

返回:

一个布尔值(整数)more 和一个矩形 filled。如果 more == 0,表示故事的所有内容都已写入,否则表示还有更多内容等待写入后续矩形/页面。矩形 filledwhere 中实际被填充的部分。

draw(dev, matrix=None)#

Story.place() 准备的内容部分写入页面。

参数:
  • dev – 由 dev = writer.begin_page(mediabox) 创建的 Device。该设备知道如何调用所有写入内容所需的 MuPDF 函数。

  • matrix (matrix_like) – 写入页面时用于转换内容的矩阵。例如,可能是写入旋转文本。默认表示不进行转换(即 Identity 矩阵)。

element_positions(function, args=None)#

一旦某些 HTML 元素在当前页面上的位置计算完成,让 Story 提供其定位信息 - 即在调用 Story.place() 之后立即 调用此方法。

Story 会将位置信息传递给 function。例如,此信息可用于生成目录。

参数:
  • function (callable) – 接受 ElementPosition 对象的 Python 函数。Story 对象将调用它来处理定位信息。该函数 必须 是接受且仅接受一个参数的可调用对象。

  • args (dict) – 一个可选字典,包含应添加到传递给 functionElementPosition 实例中的任何 附加 信息。例如当前的输出页码。此字典中的每个键必须是符合有效 Python 标识符规则的字符串。下面解释了完整的 G 集信息。

reset()#

将故事文档回退到开头,以便重新开始输出。

body#

故事 DOM 的 body 部分。此属性包含 bodyXml 节点。所有用于 PDF 生成的相关内容都包含在 “<body>” 和 “</body>” 之间。

write(writer, rectfn, positionfn=None, pagefn=None)#

将 Story 放置并绘制到 DocumentWriter。避免了调用代码实现循环调用 Story.place()Story.draw() 等的需求,代价是必须提供至少 rectfn() 回调。

参数:
  • writer – 一个 DocumentWriter 或 None。

  • rectfn

    一个接受 (rect_num: int, filled: Rect) 并返回 (mediabox, rect, ctm) 的可调用对象

    • mediabox: None 或用于新页面的 rect。

    • rect: 应放置内容的下一个矩形。

    • ctm: None 或一个 Matrix

  • positionfn

    None,或一个接受 (position: ElementPosition) 的可调用对象

    • position

      一个带有额外 .page_num 成员的 ElementPosition

    通常在生成标题或带有 id 的元素时多次调用。

  • pagefn – None,或一个接受 (page_num, medibox, dev, after) 的可调用对象;在每页的开始 (after=0) 和结束 (after=1) 时调用。

static write_stabilized(writer, contentfn, rectfn, user_css=None, em=12, positionfn=None, pagefn=None, archive=None, add_header_ids=True)#

执行 html 内容到 DocumentWriter 的迭代布局的静态方法。

例如,这允许添加目录部分,同时确保页码被修补直到稳定。

重复地从 (contentfn(), user_css, em, archive) 创建新的 Story,并使用内部调用 Story.write() 进行布局;使用 None writer 并提取 ElementPosition 列表,该列表被传递给下一次调用 contentfn()

contentfn() 的 html 变得不变时,我们使用 writer 进行最后一次迭代。

参数:
  • writer – 一个 DocumentWriter

  • contentfn – 一个函数,接受 ElementPositions 列表并返回包含 html 的字符串。返回的 html 可以依赖于位置列表,例如在开头附近生成目录。

  • rectfn

    一个接受 (rect_num: int, filled: Rect) 并返回 (mediabox, rect, ctm) 的可调用对象

    • mediabox: None 或用于新页面的 rect。

    • rect: 应放置内容的下一个矩形。

    • ctm: 一个 Matrix

  • pagefn – None,或一个接受 (page_num, medibox, dev, after) 的可调用对象;在每页的开始 (after=0) 和结束 (after=1) 时调用。

  • archive

  • add_header_ids – 如果为 true,我们为所有尚未有 id 的头部标签添加唯一 id。这有助于自动生成目录。

返回

None。

类似于 write(),但我们没有 writer 参数,而是返回一个 PDF Document,其中为每个内部 html 链接创建了链接。

类似于 write_stabilized(),但我们没有 writer 参数,而是返回一个 PDF Document,其中为每个内部 html 链接创建了链接。

class FitResult#

Story.fit*() 方法的结果。

成员

big_enough:

如果拟合成功,则为 True

filled:

来自最后一次调用 Story.place()

more:

如果拟合成功,则为 False

numcalls:

调用 self.place() 的次数。

parameter:

成功的参数值,或最大的失败值。

Rect:

parameter 创建的 rect。

fit(self, fn, pmin=None, pmax=None, delta=0.001, verbose=False)#

寻找包含故事 self 的最优矩形。

返回一个 Story.FitResult 实例。

成功时,最后一次调用 self.place() 将使用返回的矩形,因此可以直接使用 self.draw()

参数:
  • fn

    一个可调用对象,接受一个浮点数 parameter 并返回一个 pymupdf.Rect()。如果 rect 为空,我们假设故事无法适应,并且不调用 self.place()

    必须保证当给定 rect fn(parameter) 且 parameter 增加时,self.place() 表现出单调性。这通常意味着宽度和高度都会随着 parameter 的增加而增加或保持不变。

  • pmin – 要考虑的最小参数;None 表示负无穷大。

  • pmax – 要考虑的最大参数;None 表示正无穷大。

  • delta – 返回的 parameter 的最大误差。

  • verbose – 如果为 true,则输出诊断信息。

fit_scale(self, rect, scale_min=0, scale_max=None, delta=0.001, verbose=False)#

在范围 scale_min..scale_max 中找到最小的 scale 值,使得 scale * rect 足以包含故事 self

返回一个 Story.FitResult 实例。

参数:
  • width – rect 的宽度。

  • height – rect 的高度。

  • scale_min – 要考虑的最小比例;必须 >= 0。

  • scale_max – 要考虑的最大比例,必须 >= scale_min 或 None 表示无穷大。

  • delta – 返回比例的最大误差。

  • verbose – 如果为 true,则输出诊断信息。

fit_height(self, width, height_min=0, height_max=None, origin=(0, 0), delta=0.001, verbose=False)#

在范围 height_min..height_max 中找到最小高度,使得大小为 (width, height) 的矩形足以包含故事 self

返回一个 Story.FitResult 实例。

参数:
  • width – rect 的宽度。

  • height_min – 要考虑的最小高度;必须 >= 0。

  • height_max – 要考虑的最大高度,必须 >= height_min 或 None 表示无穷大。

  • origin – rect 的 (x0, y0)

  • delta – 返回高度的最大误差。

  • verbose – 如果为 true,则输出诊断信息。

fit_width(self, height, width_min=0, width_max=None, origin=(0, 0), delta=0.001, verbose=False)#

在范围 width_min..width_max 中找到最小宽度,使得大小为 (width, height) 的矩形足以包含故事 self

返回一个 Story.FitResult 实例。

参数:
  • height – rect 的高度。

  • width_min – 要考虑的最小宽度;必须 >= 0。

  • width_max – 要考虑的最大宽度,必须 >= width_min 或 None 表示无穷大。

  • origin – rect 的 (x0, y0)

  • delta – 返回宽度的最大误差。

  • verbose – 如果为 true,则输出诊断信息。

元素定位回调函数#

回调函数可用于记录故事输出的信息。该函数对信息的访问是只读的:它无法影响故事的输出。

使用此方法执行故事的典型循环如下所示

HTML = """
<html>
    <head></head>
    <body>
        <h1>Header level 1</h1>
        <h2>Header level 2</h2>
        <p>Hello MuPDF!</p>
    </body>
</html>
"""
MEDIABOX = pymupdf.paper_rect("letter")  # size of a page
WHERE = MEDIABOX + (36, 36, -36, -36)  # leave borders of 0.5 inches
story =  pymupdf.Story(html=HTML)  # make the story
writer = pymupdf.DocumentWriter("test.pdf")  # make the writer
pno = 0 # current page number
more = 1  # will be set to 0 when done
while more:  # loop until all story content is processed
    dev = writer.begin_page(MEDIABOX)  # make a device to write on the page
    more, filled = story.place(WHERE)  # compute content positions on page
    story.element_positions(recorder, {"page": pno})  # provide page number in addition
    story.draw(dev)
    writer.end_page()
    pno += 1  # increase page number
writer.close()  # close output file

def recorder(elpos):
    pass

ElementPosition 类的属性#

必须且仅向 Story.element_positions() 提供的函数传递一个参数。它是一个具有以下属性的对象

传递给 recorder 函数的参数是一个具有以下属性的对象

  • elpos.depth (int) – 此元素在框结构中的深度。

  • elpos.heading (int) – 头部级别,0 表示无头部,1-6 对应于 h1 - h6

  • elpos.href (str) – href 属性的值,如果未定义则为 None。

  • elpos.id (str) – id 属性的值,如果未定义则为 None。

  • elpos.rect (tuple) – 元素在页面上的位置。

  • elpos.text (str) – 元素的直接文本。

  • elpos.open_close (int bit field) – 位 0 设置:打开元素,位 1 设置:关闭元素。适用于可能包含其他元素,因此在创建/打开后可能不会立即关闭的元素。

  • elpos.rect_num (int) – 故事到目前为止填充的矩形计数。

  • elpos.page_num (int) – 页码;仅在使用 pymupdf.Story.write*() 函数时存在。


本软件按“原样”提供,不附带任何明示或暗示的保证。本软件在许可下分发,除非该许可条款明确授权,否则不得复制、修改或分发。有关许可信息,请参阅 artifex.com 或联系 Artifex Software Inc., 39 Mesa Street, Suite 108A, San Francisco CA 94129, United States 获取更多信息。