跳转到内容

ValueObjects:领域原语 + 单位

ValueObjects 模块保存引擎在各处传递的不可变几何原语:PageSizeDimensionPositionMargin,以及 Unit 枚举。它们均为 final readonly 类,因此实例可以自由共享;变换操作会返回新实例。

Terminal window
composer require nextpdf/core:^3

这四个值对象均为 final readonly。它们保存 float 坐标,且不暴露任何修改器;变换方法会使用具名参数重新构造新实例。这样一来,它们可以安全缓存、跨文档传递,并在多个工作进程之间共享,无需防御性复制。

PageSize 存储宽度、高度(以点为单位;1 pt = 1/72 英寸)以及名称。静态工厂涵盖 ISO 216 A 系列(A0A6)、ISO 216 B 系列(B0B5),以及北美尺寸(LetterLegalTabloid)。A/B 系列尺寸遵循 ISO 216 定义的成品纸张尺寸系列。fromName() 以不区分大小写的方式解析名称,对未知名称会抛出 PageLayoutExceptionlandscape()portrait() 返回对应方向的变体(如果已经是该方向,则原样返回 self)。toDimension() 转换为以点为单位的 Dimension

Dimension 存储宽度、高度以及一个 Unit。工厂方法(fromMillimeters()fromPoints()fromInches())按给定单位构造实例。toPoints()toMillimeters() 执行转换(在已经以点为单位时返回 self)。withWidth()withHeight() 返回调整尺寸后的副本。转换使用精确系数:每毫米 72/25.4 点,每厘米 72/2.54 点,每英寸 72 点。

Position 是 PDF 用户空间中的一个二维点(x, y)。origin() 返回 (0, 0)translate(dx, dy) 返回经过偏移的副本。withX() / withY() 返回仅替换其中一个坐标的副本。

Margin 保存 toprightbottomleft。工厂方法包括:uniform()(四边相同值)、symmetric(vertical, horizontal),以及 zero()

Unit 是一个以字符串为背值的枚举——Pointpt)、Millimetermm)、Centimetercm)、Inchin)——其 toPointFactor() 返回换算到点的乘数。

符号种类主要成员
NextPDF\ValueObjects\PageSizefinal readonly 类$width$height$name;工厂方法 A0A6B0B5LetterLegalTabloidfromName()landscape()portrait()toDimension()
NextPDF\ValueObjects\Dimensionfinal readonly 类$width$height$unitfromMillimeters()fromPoints()fromInches()toPoints()toMillimeters()withWidth()withHeight()
NextPDF\ValueObjects\Positionfinal readonly 类$x$yorigin()translate()withX()withY()
NextPDF\ValueObjects\Marginfinal readonly 类$top$right$bottom$leftuniform()symmetric()zero()
NextPDF\ValueObjects\Unit字符串枚举PointMillimeterCentimeterInchtoPointFactor()

使用工厂方法构造几何原语。

<?php
declare(strict_types=1);
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
use NextPDF\ValueObjects\Position;
$page = PageSize::A4(); // 595.276 x 841.890 pt
$margin = Margin::uniform(18.0); // 18 pt all sides
$origin = Position::origin()->translate(72.0, 72.0); // 1 inch in from corner

转换单位、推导方向,并将边距传入配置。

<?php
declare(strict_types=1);
use NextPDF\Core\Config;
use NextPDF\ValueObjects\Dimension;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// A label sized in millimeters, resolved to points for the engine.
$label = Dimension::fromMillimeters(width: 100.0, height: 150.0)->toPoints();
$page = PageSize::A4()->landscape(); // swap to width >= height
$margin = Margin::symmetric(vertical: 20.0, horizontal: 15.0);
$config = (new Config())
->withPageSize($page)
->withMargins($margin);
// $label->width / $label->height are now in points for downstream layout.
  • 除非封装在 Dimension 中并显式指定 Unit,否则所有尺寸都以点为单位。Config 的边距默认也以点为单位。
  • PageSize::landscape() / portrait() 在方向已经匹配时返回同一个实例——不会分配新内存,并保持标识不变。
  • PageSize::fromName() 不区分大小写,但只能解析已命名的工厂。未知名称会抛出 PageLayoutException,而不是返回默认尺寸。
  • 当单位已经是 Point 时,Dimension::toPoints() 返回 self;不要假定会得到新对象。
  • 这些对象保存原始 float 值,且不执行任何范围校验。构造时会接受负值或零尺寸。几何有效性由布局层和写入层强制保证,而不是在这里保证。
  • 浮点转换使用精确的有理系数(72/25.4、72/2.54);仅在展示边界处取整,以保持可复现输出的稳定性。

每个值对象都是一个由浮点数组成的扁平 readonly 结构体。由于不存在嵌套的可变状态,构造和每次变换都只需一次 O(1) 分配,不会进行深拷贝。跨多个文档共享同一实例没有任何额外开销。本参考页的默认 performance_budgetwall_ms: 1500peak_mb: 64

这些值对象不涉及任何 I/O;除页面尺寸名称外,不接受用户提供的字符串,也不持有外部资源句柄,因此不会引入直接攻击面。PageSize::fromName() 会通过抛出异常拒绝未知输入,而不是静默回退;这样格式错误的配置会显式暴露,不会产生意料之外的页面几何。

规范条款主题
ISO 216:2007A / B 系列面向 A* / B* 工厂的成品纸张尺寸(意译;未引用 ISO 原文,未锚定任何片段)

A 系列和 B 系列工厂的尺寸对应于以点表示的 ISO 216 成品尺寸。北美尺寸(LetterLegalTabloid)是事实上的行业尺寸,没有 ISO 依据。本站根据引用策略对 ISO 引用进行了意译。未锚定任何逐字片段。

  • /modules/core/config/ —— Config 使用 PageSizeMargin
  • /modules/core/layout/ —— 使用这些原语的几何层
  • /modules/core/graphics/ —— Position 在绘图坐标空间中的用法
  • /modules/core/contracts/ —— 与 PageSize 搭配使用的 Orientation
  • /modules/core/exception/ —— fromName() 抛出的 PageLayoutException