Story#

  • 新增于 v1.21.0

方法 / 属性

简短描述

Story.reset()

“重置”故事输出至其起始位置

Story.place()

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

Story.draw()

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

Story.element_positions()

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

Story.body

故事的底层 body

Story.write()

将故事放置并绘制到 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()

Class API

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

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

该结构可以被修改:可以使用 Xml 类的方法添加、复制、修改或删除内容(文本、图像)。

完成后, story 可以写入任何设备; 在典型的使用场景中,该设备可能由 DocumentWriter 提供,以创建新页面。

以下是一些一般性说明:

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

  • PyMuPDF 提供了多种方法来操作 HTML 源代码,允许访问底层 DOM 的 节点。文档可以完全从头开始以编程方式构建,或者对现有 DOM 进行任意修改。有关该接口的详细信息,请参阅 Xml 类。

  • 如果不再需要对 DOM 进行更改,则 story 准备好进行布局,并可写入一系列设备(通常是由 DocumentWriter 提供的设备,以生成新页面)。

  • 下一步是放置 story 并将其写入输出。这可以直接完成,通过循环调用 place()draw(),或者使用 write()write_stabilized() 方法让它自动处理循环。选择哪种方式主要取决于个人偏好。

    • 如果选择手动方式,建议使用以下循环:

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

    2. 确定页面上的一个或多个矩形区域,这些区域将用于接收 story 数据。请注意,并非每个页面都需要使用相同的矩形区域集。

    3. 将每个矩形传递给 story 以进行放置,了解该矩形的填充情况,以及是否还有未适应的 story 数据。这一步可以重复多次,并调整矩形区域,直到获得满意的结果。

    4. 在此阶段,可以通过调用 element_positions() 方法请求有关已放置项目的位置的详细信息。如果 heading 属性为非零整数(对应于 HTML 标签 h1 - h6),或者 id 属性不为 None (对应于 HTML 标签 id),或者 href 属性不为 None (对应于 HTML 标签 href),则该元素被视为“感兴趣的元素”。这对于自动生成目录(Table of Contents)、索引或类似用途非常方便。

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

    6. 如果最近一次 place() 调用表明所有 story 数据均已适应,则停止。

    7. 否则,循环回到前面:如果当前设备(页面)上还有更多的矩形需要填充,则返回到步骤 3;如果没有,则返回步骤 1 以获取新设备(页面)。

    可以使用 write()write_stabilized() 方法。 这些方法会自动处理所有循环, 只需提供控制行为的回调(主要是一个枚举矩形/页面的回调函数)。

  • story 的内容将如何分布到哪些矩形 / 页面,完全由 Story 对象控制,无法预知。

  • 图像可以包含在 story 中,并与周围文本一起放置。

  • 多个 story 可以独立地写入同一页面。例如,可以使用不同的 story 分别处理页眉、页脚、正文文本、注释框等。

参数:
  • html (str) – HTML 源代码。如果省略,将生成一个基本的最小结构(见下文)。 如果提供,则无需是完整的 HTML 文档。 内置解析器会容忍(大多数)HTML 语法错误,并接受 HTML 片段,如 "<b>Hello, <i>World!</i></b>"

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

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

  • archive – 一个 Archive 对象,用于加载渲染资源。 目前支持的资源类型包括图像和字体。 如果省略,story 将不会查找任何此类数据,因此可能会导致输出不完整。

备注

除了实际的 archive 对象,也可以提供创建 Archive 的有效参数。 例如,story = pymupdf.Story(archive=pymupdf.Archive("myfolder")) 可以简化为 story = pymupdf.Story(archive="myfolder")

place(where)#

计算 story 内容中可以适应提供矩形的部分。 该方法会维护一个指针,指示 story 内容已经写入的位置, 并在下一次调用时从该指针处继续。

参数:

where (rect_like) – 将当前内容布局到该矩形中。该矩形必须是页面 MediaBox 的子矩形。

返回类型:

tuple[bool, rect_like]

返回:

一个布尔值 more 和一个矩形 filled。 如果 more == 0,则 story 的所有内容均已写入; 否则,仍有内容等待写入后续矩形或页面。 filledwhere 中实际被填充的部分。

draw(dev, matrix=None)#

Story.place() 计算出的内容写入页面。

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

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

element_positions(function, args=None)#

在 story 计算出 HTML 元素在当前页面的位置后, 让它提供这些信息 - 必须在 Story.place() 之后立即调用

Story 将位置信息传递给 function,例如可用于生成目录(Table of Contents)。

参数:
  • function (callable) – 接受一个 ElementPosition 对象的 Python 函数。 该函数会被 Story 对象调用来处理位置信息。 该函数 必须 是一个接受 唯一 一个参数的可调用对象。

  • args (dict) – 可选字典,包含应添加到 ElementPosition 实例中的 额外信息, 例如当前输出页面编号。 该字典的每个键必须是符合 Python 标识符规则的字符串。 下面会详细说明完整的信息集。

reset()#

将 story 文档倒回到起始位置,以便重新开始输出。

body#

story DOM 的 body 部分。 该属性包含 bodyXml 节点。 所有 PDF 生产相关的内容都包含在 “<body>” 和 “</body>” 之间。

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

将 story 放置并绘制到 DocumentWriter,避免调用代码 需要手动实现循环来调用 Story.place()Story.draw()

参数:
  • writerDocumentWriter 实例,或 None

  • rectfn

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

    • mediabox: None 或者表示新页面的矩形。

    • rect: 下一块应放置内容的矩形区域。

    • ctm: NoneMatrix 变换矩阵。

  • positionfn

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

    • position: 一个 ElementPosition 实例,具有额外的 .page_num 成员。

    该函数通常会在生成标题元素或具有 id 的元素时被多次调用。

  • pagefnNone,或一个可调用对象,接受 (page_num, mediabox, 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

例如,这允许在确保页码稳定的情况下添加目录(Table of Contents)部分。

该方法会重复执行以下操作:

  1. 使用 (contentfn(), user_css, em, archive) 创建新的 Story 实例。

  2. 通过内部调用 Story.write() 进行布局,并使用 None 作为 writer 提取 ElementPosition 列表,该列表会传递给下一次 contentfn() 调用。

  3. contentfn() 生成的 HTML 内容不再变化时,执行最终迭代,并使用 writer 进行最终写入。

参数:
  • writer – 一个 DocumentWriter

  • contentfn – 一个函数,接受 ElementPositions 列表,并返回包含 HTML 内容的字符串。 返回的 HTML 可以依赖于该列表,例如用于在文档开头生成目录。

  • rectfn

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

    • mediabox: None 或者新页面的矩形。

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

    • ctm: Matrix 变换矩阵。

  • pagefnNone,或一个可调用对象,接受 (page_num, mediabox, dev, after); 在每个页面的开始 (after=0) 和结束 (after=1) 处调用。

  • archive – 资源存储 Archive,可用于加载图像和字体。

  • add_header_ids – 若为 True,则对所有没有 id 的 HTML 标题标签(如 <h1>-<h6>)添加唯一的 id, 以便自动生成目录。

返回:

None

类似于 write(),但没有 writer 参数, 并返回一个包含内部 HTML 链接的 PDF Document

类似于 write_stabilized(),但没有 writer 参数, 而是返回一个包含内部 HTML 链接的 PDF Document

class FitResult#

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

成员:

big_enough:

True,表示内容适应成功。

filled:

最后一次 Story.place() 调用填充的矩形。

more:

False,表示适应成功。

numcalls:

调用了 self.place() 的次数。

parameter:

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

Rect:

parameter 生成的矩形。

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

查找能包含 self 的最优矩形。

返回一个 Story.FitResult 实例。

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

参数:
  • fn

    一个可调用对象,接受一个浮点数 parameter 并返回 pymupdf.Rect()。 如果返回的矩形为空,则认为故事无法适应该矩形,并不会调用 self.place()

    该函数必须保证 self.place()fn(parameter) 增大时单调递增。 这通常意味着宽度和高度随着 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 实例。

参数:
  • 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 – 矩形的宽度。

  • height_min – 需要考虑的最小高度,必须大于等于 0

  • height_max – 需要考虑的最大高度,必须大于等于 height_min,或 None 表示无限。

  • origin – 矩形的 (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 – 矩形的高度。

  • width_min – 需要考虑的最小宽度,必须大于等于 0

  • width_max – 需要考虑的最大宽度,必须大于等于 width_min,或 None 表示无限。

  • origin – 矩形的 (x0, y0) 坐标。

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

  • verbose – 若为 True,则输出诊断信息。

  • New in v1.21.0

Method / Attribute

Short Description

Story.reset()

“rewind” story output to its beginning

Story.place()

compute story content to fit in provided rectangle

Story.draw()

write the computed content to current page

Story.element_positions()

callback function logging currently processed story content

Story.body

the story’s underlying body

Story.write()

places and draws Story to a DocumentWriter

Story.write_stabilized()

iterative layout of html content to a DocumentWriter

Story.write_with_links()

like write() but also creates PDF links

Story.write_stabilized_with_links()

like write_stabilized() but also creates PDF links

Story.fit()

Finds optimal rect that contains the story self.

Story.fit_scale()

Story.fit_height()

Story.fit_width()

Class API

元素定位回调函数#

Element Positioning CallBack function

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

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

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")  # 页面大小
WHERE = MEDIABOX + (36, 36, -36, -36)  # 留出0.5英寸的边框
story = pymupdf.Story(html=HTML)  # 创建故事
writer = pymupdf.DocumentWriter("test.pdf")  # 创建写入器
pno = 0  # 当前页码
more = 1  # 完成时设置为0
while more:  # 循环,直到所有故事内容处理完
    dev = writer.begin_page(MEDIABOX)  # 创建设备以在页面上写入
    more, filled = story.place(WHERE)  # 计算页面上的内容位置
    story.element_positions(recorder, {"page": pno})  # 另外提供页面号码
    story.draw(dev)
    writer.end_page()
    pno += 1  # 增加页码
writer.close()  # 关闭输出文件

def recorder(elpos):
    pass

The callback function can be used to log information about story output. The function’s access to the information is read-only: it has no way to influence the story’s output.

A typical loop for executing a story with using this method would look like this:

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 类的属性#

Attributes of the ElementPosition class

必须向 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*() 函数时存在。

Exactly one parameter must be passed to the function provided by Story.element_positions(). It is an object with the following attributes:

The parameter passed to the recorder function is an object with the following attributes:

  • elpos.depth (int) – depth of this element in the box structure.

  • elpos.heading (int) – the header level, 0 if no header, 1-6 for h1 - h6.

  • elpos.href (str) – value of the href attribute, or None if not defined.

  • elpos.id (str) – value of the id attribute, or None if not defined.

  • elpos.rect (tuple) – element position on page.

  • elpos.text (str) – immediate text of the element.

  • elpos.open_close (int bit field) – bit 0 set: opens element, bit 1 set: closes element. Relevant for elements that may contain other elements and thus may not immediately be closed after being created / opened.

  • elpos.rect_num (int) – count of rectangles filled by the story so far.

  • elpos.page_num (int) – page number; only present when using pymupdf.Story.write*() functions.


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