跳转到内容
getnextpdf.com

Pro 版本

Projection — 深度参考

本页是 Pro Projection 模块的深度参考,记录公开的 tokenize、emit 与往返(round-trip)接口、意图门(intent gate)以及内容流往返语义。ContentProjectionWriter 将一个 PDF 内容流词法解析(lex)为一个扁平、有序的 token 列表,然后再把一个 token 列表重新序列化为一个新的内容流。该模型是单向的:写出(emission)产生一个新的流,绝不是对原件的原地编辑。

注意。 此处的 “Projection” 指内容流 token 投影,而非坐标投影或地理空间投影。

此能力随 NextPDF Pronextpdf/pro)交付,并通过 Pro 层级的许可信封(license envelope)激活。没有该授权的部署不会加载此能力的类。比较版本并获取许可

不存在单项功能许可标志。这是一项 Pro 版本能力。写出还额外要求一个由类型系统强制、而非许可开关的显式 ProjectionIntent 参数。

Terminal window
composer require nextpdf/pro:^3

该模块位于 NextPDF\Pro\Projection 命名空间。ContentProjectionWriter 上的所有操作均为静态方法。

符号参数默认行为返回抛出或失败于备注
ContentProjectionWriter::tokenizestring $contentStream将流词法解析为一个扁平、有序的 token 列表;规范化空白、丢弃注释、跳过无法识别的字节list<ContentToken>无;畸形或控制字节被跳过,而非被拒绝只读;不需要意图。
ContentProjectionWriter::emitlist<ContentToken> $tokensProjectionIntent $intent将 token 序列化为一个新的内容流;输出与意图取值无关string方法体内无;缺失或非 ProjectionIntent 的参数在类型边界处失败意图是调用点门(call-site gate),而非运行时开关。
ContentProjectionWriter::roundTripstring $contentStream先 tokenize,再原样重新 emit,不作修改;即验证门string输出并非字节一致;运算符序列与操作数值被保留。
ContentToken::__constructContentTokenType $typestring|int|float|bool|null $value = null构造一个不可变 token;不执行任何校验ContentToken无;类型不兼容的 $value 在类型边界处失败readonlytypevalue 为 public。
ContentToken::isTextOperator报告该 token 是否为文本运算符(BT、ET、Tj、TJ、Td、TD、Tm、T*、Tf、Tc、Tw、Tz、TL、Tr、Ts、'"bool无;对非运算符 token 返回 false
ContentToken::isTextShowingOperator报告该 token 是否为文本显示运算符(Tj、TJ、'"bool无;对非运算符 token 返回 false文本运算符的子集。
ContentTokenType—(string 支撑的枚举)枚举 token 判别值:LiteralString、HexString、Number、Name、Operator、ArrayBegin、ArrayEnd、DictBegin、DictEnd、Boolean、Null支撑值是稳定标识符。
ProjectionIntent—(纯枚举)枚举两种被允许的写出意图:Sanitization、SteganographicEmbedding无通用取值,因此静态分析会标记未声明的使用。
public static function tokenize(string $contentStream): array
public static function emit(array $tokens, ProjectionIntent $intent): string
public static function roundTrip(string $contentStream): string
enum ProjectionIntent
{
case Sanitization;
case SteganographicEmbedding;
}
public function __construct(
public ContentTokenType $type,
public string|int|float|bool|null $value = null,
) {}
public function isTextOperator(): bool
public function isTextShowingOperator(): bool

ContentProjectionWriter::tokenize($contentStream) 将流词法解析为一个扁平、有序的 list<ContentToken>。它涵盖字面字符串、十六进制字符串、name、数字、数组与字典定界符、布尔值、null 以及运算符。空白与注释被消费并丢弃;无法识别的字节推进游标而不产生 token。该遍是只读的,且不需要意图。

emit($tokens, $intent) 将一个 token 列表序列化回内容流字节,并要求一个 ProjectionIntent。意图仅是一个调用点声明:无论传入哪种取值,写出的字节都是相同的。数字保留其整数/浮点数的区分——整数按原样写出,浮点数以最多六位小数写出并去除末尾零。字面字符串被重新转义,十六进制字符串以大写十六进制写出,name 带有其前导 solidus。每个运算符后跟一个换行符;数组与字典定界符会抑制相邻的分隔符。

roundTrip($contentStream) 先 tokenize,再原样重新 emit,不作改动。它是验证门:在信任任何“修改并写出”的序列之前,先确认一个干净的结果。输出与输入并非字节一致——空白被规范化、注释已消失——但运算符序列与操作数值被保留。

ProjectionIntent 恰好有两种取值:Sanitization(破坏性、不可逆的 redaction)与 SteganographicEmbedding(隐藏载荷嵌入)。没有通用取值,因此静态分析可以标记任何缺少声明的、已知目的的写出。ContentToken 是一个不可变的 readonly 值,携带一个 type 判别值与一个已解码的 valueisTextOperator()isTextShowingOperator() 对运算符 token 进行分类,并对每个非运算符 token 返回 false

  • 在任何“修改并写出”的序列之前,先确认一次干净的往返。请把往返失败视为一个停止条件。
  • Sanitization 意图是不可逆的。被移除的 token 在输出中不存在,也无法从中恢复。
  • 意图不改变输出。emit() 对两种取值都产生相同的字节;该参数是一个调用点门。redaction 与隐写编辑由调用方在写出前对 token 列表进行修改来施加。
  • 写出器会规范化空白并丢弃注释,因此即便是未经修改的往返,与原件的字节级比较也会出现差异。
  • 浮点操作数以最多六位小数格式化,然后去零。需要更高精度的值在写出时被舍入;整数是精确的。
  • 输入的字面字符串转义解码包括 \n\r\t\b\f、被转义的定界符,以及被钳制为一个字节的至多三位八进制转义。
  • 十六进制字符串若位数为奇数,则在输入时以一个末尾零填充,符合 ISO 十六进制字符串规则。
  • 畸形或控制字节被跳过,而非被拒绝;tokenize() 对意外输入不抛出任何异常。
  • 本模块不执行任何密码学操作,也未定义任何 FIPS 特定行为。

Tokenization 将流视为标准 PDF 对象语法中的运算符与操作数序列,依据 ISO 32000-2:2020, 8.2。字节到 token 的分组遵循 ISO 32000-2:2020, 7.2 的词法字符类。奇数长度的十六进制字符串将末尾数字填充为零,依据 ISO 32000-2:2020, 7.3.4.3。这些条款记录在本页的引用记录中。

这些陈述描述的是相对于所引条款的能力。NextPDF 未持有任何一致性认证,对某一条款的支持并非认证主张。

  • 自该模块的 1.10.0 发行版起可用;三个操作均为 ContentProjectionWriter 上的静态入口点。
  • Tokenize 与 emit 在内容流长度上是线性的。没有公布的吞吐量数字;请以有代表性的流进行测量。
  • 扁平 token 模型——每个词法元素一个 token,而非按运算符分组——正是它使诸如调整一个 TJ 数组内某个数字这样的外科式编辑成为可能。按运算符分组的表示存在于 Pro 树的其他位置,不在本页范围内。
  • ContentToken 是不可变的。请通过构造新 token、而非修改已有 token 来构建一个修改后的列表。
  • 请在你的流水线中保留往返门:一个通过的 roundTrip() 是该模块在任何破坏性编辑之前所围绕设计的前置条件。

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