跳转到内容
getnextpdf.com

Pro 版本

Flow Layout — 深度参考

本页是 Pro Flow Layout 模块的深度参考。它涵盖布局引擎、元素模型、分页策略、它们的行为契约以及各自的失败模式。StreamingLayoutEngine 会按顺序遍历一个 FlowElement 值的列表。它为每个元素分配一个从零开始的页面索引以及一个位于 LayoutRegion 内的位置。其结果是一个由不可变的 PlacedElement 记录构成的 LayoutResult。该模块只计算布局;它不进行任何渲染,也不执行任何 I/O。

此能力随 NextPDF Pronextpdf/pro)发布,并通过 Pro 级别的授权信封激活。没有该授权的部署不会加载此能力的类。比较版本并获取授权

不存在逐功能的授权标记。这是一项 Pro 版本级别的能力。

所有符号都位于 NextPDF\Pro\FlowLayout 命名空间中。所有值对象都是 final 且不可变的。

符号参数默认行为返回抛出或失败于说明
StreamingLayoutEngine::__constructLayoutRegion $region, PageBreakStrategy $strategy = PageBreakStrategy::Greedy将逐页内容区域绑定到一个分页策略StreamingLayoutEngine策略默认为 Greedy
StreamingLayoutEngine::layoutlist<FlowElement> $elements单次前向遍历;由策略驱动分页的顺序布局LayoutResult永不抛出空列表产生一个空白页。
StreamingLayoutEngine::withStrategyPageBreakStrategy $strategy派生一个区域相同的新引擎self接收方保持不变。
StreamingLayoutEngine::withRegionLayoutRegion $region派生一个策略相同的新引擎self接收方保持不变。
FlowElement::__constructFlowElementType $type, string $content, float $widthPt = 0, float $heightPt = 0, float $marginTopPt = 0, float $marginBottomPt = 0, bool $keepWithNext = false不可变的元素值对象FlowElementTable 元素唯一的构造路径。
FlowElement::textstring $content, float $height带有调用方测量高度的文本元素self(静态)宽度 0 在布局时解析为区域宽度。
FlowElement::imagestring $path, float $width, float $height图像元素;content 承载路径self(静态)引擎从不打开该文件。
FlowElement::spacerfloat $height内容为空的垂直空白self(静态)
FlowElement::pageBreak显式的断页标记self(静态)不产生任何 PlacedElement
FlowElement::totalHeight高度加上下边距float所有适配检查都使用此值。
FlowElementType枚举成员 TextImageTableSpacerPageBreak以字符串为后端:textimagetablespacerpage_break
FlowElementType::isBreakableTextTable 返回 true;其他返回 falsebool仅为分类;参见下文的原子布局契约。
LayoutRegion::__constructfloat $x, float $y, float $width, float $height以左上为原点的内容盒,以点为单位度量LayoutRegion不做校验;值按给定取用。
LayoutRegion::containsfloat $px, float $py含边界的点是否在区域内的测试bool
LayoutRegion::remainingHeightfloat $currentY区域高度减去已消耗的垂直偏移float一旦游标溢出即为零或负值。
LayoutResult::__constructlist<PlacedElement> $placements, int $pageCount, float $totalHeightPt不可变的布局结果LayoutResult
LayoutResult::placementsOnPageint $pageIndex按从零开始的页面索引筛选布局项list<PlacedElement>返回的列表会重新索引。
LayoutResult::isEmpty当没有任何元素被放置时为 truebool对空输入与仅含断页的输入均为 true。
PageBreakStrategy枚举成员 GreedyAvoidOrphansKeepTogether以字符串为后端:greedyavoid_orphanskeep_together
PageBreakStrategy::label人类可读的策略标签string
PlacedElement::__constructFlowElement $element, int $pageIndex, float $x, float $y, float $width, float $height不可变的布局记录PlacedElement坐标以点为单位,左上为原点。
public function layout(array $elements): LayoutResult
public function withStrategy(PageBreakStrategy $strategy): self
public function withRegion(LayoutRegion $region): self
public static function text(string $content, float $height): self
public static function image(string $path, float $width, float $height): self
public static function spacer(float $height): self
public static function pageBreak(): self

StreamingLayoutEngine::layout() 对输入列表执行一次前向遍历。对每个元素,它检查适配情况,在需要时断页,然后记录一个 PlacedElement。空输入列表返回一个没有任何布局项、页数为 1、总高度为 0 的 LayoutResult

布局几何是确定性的:

  • x 是区域的左边缘。
  • y 是当前游标位置加上元素的上边距。
  • width 在元素的 widthPt 为正时取该值,否则取区域宽度。
  • height 是元素的 heightPt,与提供的值完全一致。

每次布局后,游标按 totalHeight() 前进,含边距。相同的量会累加到 LayoutResult::totalHeightPt

分页规则,按求值顺序:

  • 显式的 PageBreak 元素会递增页面索引,并将游标重置到区域顶部。它不产生任何布局项,也不给总高度增加任何值。
  • 当某个元素的 totalHeight() 超过剩余高度时,引擎会断页——除非游标已经位于页面顶部。
  • Greedy 不附加任何进一步的条件:能放下的元素总是被放置。
  • AvoidOrphans 会在放下一个能容纳的元素之前断页,前提是放置后剩下的空间为正、但低于该元素自身所需高度的一半。参照单位是元素自身的高度,除数固定为二;不涉及任何字体度量。它从不在页面顶部断页。
  • KeepTogether 会在放下一个能容纳的元素之前断页,前提是其 keepWithNext 标志已设置、存在下一个元素、游标不在页面顶部,且两个元素合并的 totalHeight() 超过剩余空间。位于最后一个元素上的该标志没有作用。

原子布局:引擎将每个元素作为一个整体来放置。它从不把元素内容拆分到多页。FlowElementType::isBreakable() 对调用方可以预先拆分为更小元素的类型进行分类;引擎自身并不查阅它。

无状态性与确定性:引擎只持有它的区域与策略。layout() 在多次调用之间不共享任何状态,相同的输入产生相同的结果。withStrategy()withRegion() 返回新的引擎,从不修改接收方。

  • 本模块中没有任何方法会抛出异常。没有需要捕获的异常层级。
  • 构造函数不做任何校验。为负或为零的区域尺寸、为负的元素高度以及为负的边距都会被接受,并原样流经算术运算。
  • 高于区域的元素仍会被放置。在页面顶部时它被放置在那里并溢出;在其他位置时引擎会先断页,然后它在一个新页上溢出。随后的下一个元素总会触发断页,因此溢出被限定在一页内。
  • 位于开头的 PageBreak 会把第一个内容元素放到页面索引 1,使页数至少为 2。
  • 连续的 PageBreak 元素各自推进页面计数,产生空白页。位于末尾的一个会在 pageCount 中留下一个最终的空白页。
  • keep-together 仅在成对的两个元素都能一起放进同一页时才成立。合并高度超过整页的一对仍会被拆开。
  • 非正的 widthPt 解析为区域宽度;该替换检查严格大于零。
  • 一旦游标溢出,remainingHeight() 可能返回零或负值。contains() 将区域边界视为在内部。
  • 使用越界索引的 placementsOnPage() 返回一个空列表。
  • 本模块不执行任何密码学操作,也不定义任何 FIPS 特定的行为。

Flow Layout 实现的是 NextPDF 定义的布局行为。它不针对任何外部的布局或排版标准,因此本页不携带任何规范性引用表。这些分页策略是 NextPDF 的语义;它们不是 CSS 分片属性或任何 XSL-FO keep 模型的实现。所有尺寸均以点表示,与 Core writer 所消费的单位一致。

这些陈述仅描述能力。NextPDF 不持有任何一致性认证,也未做出或暗示任何认证声明。

  • 在上游测量内容。引擎消费调用方提供的高度;它没有字体度量,也不执行任何文本测量。
  • 在布局之前,把过长的文本或表格内容预先拆分为多个元素。用 isBreakable() 来决定分块器可以拆分哪些类型。
  • 每种页面几何复用一个引擎。用 withStrategy()withRegion() 廉价地派生变体。
  • 逐页渲染时,用 placementsOnPage() 按页对输出进行分组。
  • 布局是单次遍历,其复杂度随元素数量线性增长,并且不保留任何文档树。结果是确定性的,这适合黄金文件测试。
  • 对于 HTML 转 PDF 的渲染,请改用 Core HTML 流水线;本模块不是 HTML 或 CSS 引擎。

本页仅记录外部可观察的行为以及受支持的公共 API 接口面。内部命名空间路径、辅助类、机制表、运行手册文件名以及工单前缀均不在范围之内。