Content:文本与结构化内容模型
Content 模块负责构建文本显示运算符、文本状态运算符、文本阴影、文档级 JavaScript 以及标记内容属性字典。它位于布局与内容流之间。
composer require nextpdf/core:^3概念概览
标题为“概念概览”的章节Content 包含用于将解析后文本转换为 PDF 运算符的原语。TextRenderer 是核心组件。它会为字符串构建文本显示运算符,以及位于其前面的文本状态运算符。Tj 运算符使用当前字体及其他文本相关图形参数绘制字符串中的字形——ISO 32000-2 §9。TextRenderer 会根据当前生效的 TypographyMode,在单个显示运算符和带定位的 TJ 数组之间作出选择。当前 TypographyMode 使用 TJ 数组时,它会应用字偶距调整。
文本状态会被完整建模。setTextRenderingMode() 接受一个 TextRenderingMode 枚举值。它的八种取值与 ISO 32000-2 文本渲染模式一一对应:填充、描边、先填充后描边、不可见,以及四种裁剪变体(表 104)。渲染器还会控制描边宽度、字符间距与字词间距、水平拉伸、文本升降、从右到左方向,以及一个可选的 Hyphenator。调用 buildTextStateOperators() 会将累积的状态作为单个运算符块发出。
TextShadow 是一个值对象——包含颜色、以用户单位表示的 X 和 Y 偏移,以及不透明度。渲染器使用它发出带偏移的第二遍绘制。默认偏移为细微的 0.5/−0.5,不透明度为 0.5,与 CSS 风格的柔和阴影相匹配。
JavaScriptManager 负责文档级脚本。includeJs() 注册文档脚本。addJsObject() 注册命名脚本对象。writeJavaScript() / writeOpenAction() 会将它们序列化到目录和 OpenAction 中。该管理器在发出之前会对每个脚本主体进行防护,并执行 PDF 字符串编码。
PropertiesRegistry 是标记内容属性存储区。register() 会为属性字典返回一个稳定的标记 Index(索引)。registerOcg() / registerOcgs() 按对象编号绑定可选内容组。writeProperties() 会将该注册表序列化到页面资源字典中。当 ContentStream 模块以属性列表打开标记序列时,引用的就是这些数据。
这里包含两个图像解码器,因为它们对应 PDF 原生的直通格式。JBig2Loader 和 JpxLoader 会解析 JBIG2 和 JPEG 2000 的段结构,并返回 ImageData,但从不对像素进行栅格化。编码后的字节会原封不动地传递给查看器。当 JBIG2 源携带独立的全局段时,JBig2Loader 会通过图像 XObject 上的 /JBIG2Globals 流引用将其嵌入;而 in-stream/in-line 形式仍会像以前一样往返传递。这只是结构性接线——全局段字节会在未栅格化的情况下直通传递,而不是被解码。
API 一览
标题为“API 一览”的章节| 类 | 关键方法 | 角色 |
|---|---|---|
TextRenderer | buildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation() | 文本显示 + 文本状态运算符构建器 |
TextRenderingMode(枚举) | Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, Clip | ISO 32000-2 文本渲染模式 |
TextShadow | __construct(Color, offsetX, offsetY, opacity) | 偏移绘制遍的值对象 |
JavaScriptManager | includeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction() | 文档级 JavaScript 目录接线 |
PropertiesRegistry | register(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties() | 标记内容 + OCG 属性存储区 |
JBig2Loader | load(), loadFromString(), parseSegments() | JBIG2 直通解码器 |
JpxLoader | load(), loadFromString(), parseBoxes() | JPEG 2000 直通解码器 |
运行 composer docs:generate-api-php -- --module=Content 获取完整的 PHPDoc 表格。
代码示例——快速上手
标题为“代码示例——快速上手”的章节源文件:examples/28-text-rendering.php。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;use NextPDF\Content\TextRenderingMode;
$renderer = new TextRenderer();$renderer ->setTextRenderingMode(TextRenderingMode::FillStroke) ->setTextStrokeWidth(0.3) ->setWordSpacing(0.5);
$stateOps = $renderer->buildTextStateOperators();代码示例——生产环境
标题为“代码示例——生产环境”的章节下面的示例会添加柔和阴影和连字符处理器,然后使用调用方提供的转义函数(来自 ADR-015 规定的 PdfStringEscaper 接缝)构建显示运算符。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;use NextPDF\Content\TextShadow;use NextPDF\Graphics\Color;use NextPDF\Support\PdfStringEscaper;
$renderer = new TextRenderer();$renderer ->setTextShadow(new TextShadow(Color::rgb(0, 0, 0), 0.4, -0.4, 0.45)) ->setRTL(false);
$showOp = $renderer->buildTextShowOperator( text: 'Quarterly report', fontKey: 'F1', metrics: $fontMetrics, escapeSegment: static fn (string $s): string => PdfStringEscaper::escapeLiteral($s),);
$pageContent = $renderer->buildTextStateOperators() . $showOp;边界情况与注意事项
标题为“边界情况与注意事项”的章节buildTextShowOperator()对空输入返回空字符串。不要发出空的Tj——如果你的布局可能产生空白文本段,请在上游加以防护。- 转义回调是必需的,并负责字符串安全。请传入规范的
PdfStringEscaper::escapeLiteral()(ADR-015)。不完整的转义器会产生语法损坏的字面字符串。 TextShadow::offsetY在左上角原点坐标系中为负值表示向下。正的 Y 值会把阴影向上推,这很少是预期效果。JavaScriptManager会对脚本输入进行防护。无效的脚本主体会在注册时被拒绝,而不是在写入时被静默丢弃。JBig2Loader和JpxLoader从不进行栅格化。它们会校验并直通传递编码后的字节。损坏的段会导致解析错误,而不是空白图像。PropertiesRegistry::register()对每个字典都是幂等的——相同的属性字典会复用同一个标记索引。
运算符构建相对于字符串长度为 O(n);当排版模式使用 TJ 数组时,还会增加一次 O(n) 的字偶距处理。这里没有布局或字形整形开销——那部分留在 Typography 和 Layout 模块中。JavaScript 和属性序列化是 O(条目数)。直通图像加载器以 O(字节数) 进行解析,解码开销为零。这是它们在扫描文档工作负载中的主要优势。参考工作负载的 performance_budget 为 1500 ms 实际耗时和 64 MB 峰值。
安全说明
标题为“安全说明”的章节JavaScriptManager 接受可能源自不受信任模板的脚本主体。它会对每个主体进行防护并执行 PDF 字符串编码,但文档 JavaScript 仍然是一个活动内容攻击面。对于不受信任的输出,请禁用它,或使用 /modules/core/security/ 中描述的清理路径将其剥除。JBig2Loader 和 JpxLoader 会解析不受信任的段结构:请限定输入大小和解析时间,并在源由用户提供时,在受限的工作进程中运行提取。文本转义边界就是调用方提供的回调。请始终传入规范的转义器,使控制字节无法从字面字符串中逃逸出来。
一致性
标题为“一致性”的章节该模块发出的文本显示和文本状态运算符与 ISO 32000-2 §9 文本模型保持一致。这包括 Tj 运算符语义,以及 TextRenderingMode 枚举所映射的表 104 渲染模式。这些属于实现事实:运算符的形态由 src/Content/TextRenderer.php 和 TextRenderingMode 枚举产生,并由 tests/Unit/Content/TextRenderer*、JavaScriptManagerIsoTest 和 PropertiesRegistryTest 加以验证。它们并不构成对端到端 PDF 2.0 一致性的断言。字符串转义契约遵循 ADR-015 和 ISO 32000-2 §7.3.4.2。JBIG2 和 JPEG 2000 直通路径会保持编码流不变。独立的 JBIG2 全局段会作为图像 XObject 上的 /JBIG2Globals 流引用被嵌入——经验证,这是结构性接线,而不是解码保真度声明。文档级一致性由 /modules/core/conformance/ 中的预言机与黄金套件加以验证。