上一篇文章我們介紹了一個PDF文檔應該包含的最基本的結構,并且手寫了一個最簡單的 “Hello World” 的PDF文檔。后面我們介紹新的PDF標準給出示例時將以這個文檔為基礎,而不再給出完整的文檔示例,小伙伴想自己測試可以根據上一節的文檔來進行配置。
對象
上一節我們看到一個個奇奇怪怪的元素,可能也好奇它們的寫法,現在我們來正式介紹它們的相關內容,它們就是PDF文檔中一個個的對象。
PDF 支持5種基本對象:
- 整數和實數:例如43和12.2 這種數字
- 字符串,PDF種字符串被包裹在小括號中,例如上一節中的
(hello world)
, 我們也可以給字符串制定編碼,這個在后面介紹 - 名稱:一般用于字典中的鍵,以
/
開頭,例如上一節中的/Page
就是一個名稱的對象 - 布爾值: 由關鍵字 true 和 false表示
- null 對象,由關鍵字 null 表示
PDF支持3種復合對象
- 數組: 包含其他對象的有序集合,數組中的元素可以是其他任何類型的對象,例如可以像
[0 0 0 0 1]
這樣只包含數字,也可以像上一節中的[2 0 R]
包含其他對象的一個引用 - 字典: 字典是由無序對的集合組成,將名稱映射到對象。字典中的映射被包含在
<<>>
對中,例如<</Kids [2 0 R]>>
就是一個字典,它將Kids這個名稱映射到 [2 0 R] 這個間接引用的對象上 - 流:流中一般包含二進制的數據流以及描述屬性的字典,一般page中的content都是一個個的流對象。
間接引用
間接引用形成從一個對象到另一個對象的鏈接,為了將PDF拆分成一個個單獨的對象,我們通過間接引用將它們鏈接在一起,例如上一篇文章中提到的
1 0 obj
<<
/Kids [2 0 R]
/Count 1
/Type /Pages
>>
對象中就包含間接引用,PDF解析器,知道這個對象是一個Pages對象之后,可以通過Kids 對象指定的間接引用對象知道,當前PDF文檔只有一頁,這個頁面對象就是2 0
這個對象。 這里的R
代表 reference
也就是引用,它是一個關鍵字,前面的 2 0 代表的是對象編號是2,世代號是0(這里我們不考慮世代號,默認的世代號都是0)
流和過濾器
流用于存儲二進制數據,它們由字典和一大塊二進制數據組成,字典根據流所放置的特定用途,列出數據的長度,以及可選的其他參數。
從語法上將,流由字典組成,后跟 stream
關鍵字,換行符,0個或者多個字節的數據,另一個換行符,最后是一個endstream
關鍵字。根據上一篇文章中給出的頁面流對象的定義來看
4 0 obj
<<
/Length 202 % 流的長度
>>
stream %關鍵字
1. 0. 0. 1. 50. 700. cm % 202 字節的數據,這里是圖形流,下面是圖形流的數據
BT/F0 36. Tf(Hello, World!) Tj
ET
endstream % 流對象結束的關鍵字
endobj