PDF 序列化¶
PdfWriter 是 NextPDF 的最後一個管線階段,負責將記憶體中的 PDF 物件圖(Object Graph)序列化為符合 ISO 32000-2 標準的二進位 PDF 格式。輸出的 PDF 包含完整的交叉參考資訊,確保 PDF 閱讀器能以 O(1) 時間定位任意物件。
序列化概覽¶
finalize() 呼叫
├── 完成渲染管線(字型子集化、頁首頁尾填充)
├── 建立 PDF 物件圖
│ ├── Catalog(文件目錄)
│ ├── Pages(頁面樹)
│ ├── Resources(字型、影像、色彩空間)
│ └── 其他字典(Info、Metadata、AcroForm 等)
├── PdfWriter 序列化
│ ├── PDF 檔頭 (%PDF-2.0)
│ ├── 物件本體(間接物件序列)
│ ├── 交叉參考(xref table 或 xref stream)
│ └── 檔案尾碼(Trailer 字典 + startxref)
└── 輸出位元組串流
交叉參考格式¶
NextPDF 使用 PDF 1.5+ 引入的交叉參考串流(xref stream),相較傳統 xref 表有更高的壓縮率:
傳統 xref 表(PDF 1.4 以前):
0000000009 00000 n ← 每條 20 bytes ASCII
0000000058 00000 n
交叉參考串流(PDF 1.5+):
- 使用 FlateDecode 壓縮
- 支援 Offset Width(變長偏移量)
- 可選 Predictor(PNG 濾波器進一步壓縮)
物件串流(Object Streams)¶
NextPDF 將小型物件打包進物件串流(ObjStm),減少整體 PDF 體積:
use NextPDF\Writer\WriterOptions;
$options = WriterOptions::create(
useObjectStreams: true, // 啟用物件串流(預設:true)
compressionLevel: 6, // zlib 壓縮等級(0-9,預設:6)
maxObjectsPerStream: 200, // 每個物件串流的最大物件數
);
$pdfBytes = $document->finalize(writerOptions: $options);
字典鍵排序¶
PDF 字典鍵的順序不影響語義,但 NextPDF 預設按字母順序排序以提高確定性(deterministic output):
$options = WriterOptions::create(
deterministicOutput: true, // 相同輸入總是產生相同 SHA-256
sortDictionaryKeys: true, // 字典鍵字母排序
);
輸出後處理¶
// 輸出到標準輸出(HTTP 回應)
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="report.pdf"');
echo $document->finalize();
// 輸出到檔案(原子寫入)
$document->finalizeToFile(path: '/output/report.pdf');
// 輸出到資源串流(PSR-7 StreamInterface 相容)
$stream = $document->finalizeToStream();