尋夢新聞LINE@每日推播熱門推薦文章,趣聞不漏接❤️
#愛否精選#
PDF 作為當代數字生活中的「紙」,在互聯網中有著最接近現實紙的體驗,但也有諸多不便,為什麼 PDF 會變成數字紙呢?
————————
本內容經授權轉載自「少數派」;由愛否科技精選推送。
來源 | 少數派(ID:sspaime)
引言
PDF 是我們打交道最多的文件格式之一。提到這個格式,即使是對技術並不熟悉的用戶,也能說出「通用性好」、「格式不會亂變」這些優點。但同時,PDF 也是讓我們感到困惑最多的格式之一,因為與 Word 文檔等其他常見辦公軟件格式相比,PDF 似乎有著太多的「怪癖」,例如復制文字困難、幾乎沒法編輯等等。PDF 軟件數量繁多、質量良莠不齊的現狀,也進一步讓很多用戶無法正確理解和使用 PDF。
然而,事實並非如此。這些問題大多不是 PDF 格式的「缺陷」,而是因為我們在觀念上把 PDF 當成了和其他辦公文檔格式相近的東西,並因此期待 PDF 也具有和後者相似的功能和特徵。
盡管 PDF 格式和 Word 格式在實際用途上有諸多重疊之處,但那只是表面現象。從技術角度看,兩種格式之間的差異要遠遠大於 Word 文檔和網頁之間的差異,甚至還要大於 Word 文檔和 Excel 表格之間的差異。
但這並不意味著 PDF 就是一種難以理解的格式。恰恰相反,對大多數用戶來說,PDF 可能是他們接觸到的格式中最「接地氣」、與現實生活最接近的。因為,PDF 與其說是一種數字文檔,不如說是實體文檔在數字世界中的影像。對 PDF 的操作,很大程度上可以看成對真實紙張的操作,只是操作環境從物理世界換到了數字世界而已。PDF 的創建就是一種虛擬的列印,復制 PDF 文字的過程更像是一種抄寫,而 PDF 的編輯實質上是一種塗改。
一旦接受了這個觀念,PDF 的很多「怪癖」就顯得順理成章了:列印出來的東西當然不會因為位置的變化而改變外觀;抄寫的結果很可能與原文存在誤差,並且受制於抄寫者對文字的理解;塗改的可行性則取決於原有布局留下了多少改動空間,並且再輕微的塗改也會對紙張造成損傷。
當然,只給出這樣的結論並不足以令人信服。因此,下文的主要任務就是通過回答幾個關於 PDF 格式普遍關心的問題,結合 PDF 的結構和語法,解釋為什麼「PDF 的本質就是數字化的紙張」,從而深化對 PDF 格式的理解。
❶為什麼 PDF 的外觀非常穩定?
在我們日常使用的文檔格式中,PDF 文件的外觀是最穩定的。一經生成,無論在什麼操作系統上、用什麼軟件打開,得到的顯示效果幾乎總是一致的。相比之下,Word 所使用 docx 格式的保真性就差得多了:哪怕只是換台電腦,顯示效果都可能發生了變化,更不要說用不同版本的 Word 或者第三方軟件打開了。
PDF 的這種保真性讓它廣受青睞,但它究竟是如何做到這一點的?PDF 的穩定是絕對的嗎?
「列印」出來的 PDF
如果平時注意觀察,容易發現各種軟件中涉及 PDF 的操作,用詞都比較特別。其他格式都是被「新建」(new / create)出來或者「保存」(save)下來的,只有 PDF 是被「導出」(export)甚至「列印」(print)出來的。這些詞語並不是隨意選用的,它們本身就說明了 PDF 的重要特徵:「導出」暗示著文件編輯已經告一段落,而「列印」則更是形象地表明 PDF 的創建是一個「固化」的過程。
為了進一步理解這種區別,讓我們來對比一組外觀上完全相同的 Word 文檔和 PDF 文檔。下圖中,右側的 PDF 格式文件是由左側的 Word 文件導出得到的,兩者的內容都只有「Hello world!」一行居中文字。(註:為了避免不必要的複雜性,我們暫時只以英文文檔為例。)
一對內容相同的 Word 文檔和 PDF 文檔
先來看 Word 是如何做到這一版式效果的。用任意解壓工具將該文檔解開(docx 文件 實質上 就是一個壓縮包),找到其中的 /word/_rels/document.xml
並打開。其中的關鍵部分如下(代碼經過整理):
<w:pPr> <w:jc w:val="center"/> <w:rPr><w:rFonts w:ascii="Times" w:hAnsi="Times"/><w:lang w:val="en-US"/></w:rPr></w:pPr><w:r w:rsidRPr="003C75CF"> <w:rPr><w:rFonts w:ascii="Times" w:hAnsi="Times"/></w:rPr> <w:t>Hello world!</w:t></w:r>
不必恐懼這些陌生的代碼,它們的意義很容易從文檔內容本身反推出來。先看倒數第二行,這里記錄了整個文檔最重要的信息——「Hello world!」這串文字。在它的上面一行,w:rFonts 屬性將字體設置為 Times。那麼前四行是做什麼的呢?從第二行的 center 字樣不難猜出,它們控制的是文字所在段落的樣式,包括居中對齊等等。
這就是 docx 格式這類 標記語言 (Markup Language)文檔的特徵:在純文本上包裹各種「標籤」(tag)來描述文本的樣式(顏色、位置、字體等等),從而獲得格式豐富多變的文檔。常見的網頁(HTML)、Evernote 筆記( ENML )所用的語法本質上都是標記語言,區別只在於支持的標籤各不相同、因此能做到的格式有多有少罷了。
PDF 又是怎麼做的呢?我們用純文本編輯器打開上圖中的 PDF 文件(是的,PDF 可以用文本編輯器打開查看源碼),其中的關鍵部分如下(經過處理):
BT 1 0 0 1 1036 572 Tm /TT1 12 Tf [ (He) 24 (l) -48 (l) -48 (o) ] TJETBT 1 0 0 1 1147 572 Tm /TT1 12 Tf TjETBT 1 0 0 1 1160 572 Tm /TT1 12 Tf [ (w) 24 (or) -84 (l) -24 (d) ] TJET
即使你被這些凌亂的數字和代號弄得一頭霧水,大概也能看出它與 docx 格式有著截然不同的畫風。如果我們粗略地把這些語句翻譯成「人話」:
【文字開始】 縮放比例1倍 坐標(1036,572) 【文字定位】 /TT1 12磅 【選擇字體】 [ (He) 間距24 (l) 間距-48 (l) 間距-48 (o) ] 【繪制文字】【文字結束】【文字開始】 縮放比例1倍 坐標(1147,572) 【文字定位】 /TT1 12磅 【選擇字體】 (空格) 【繪制文字】【文字結束】【文字開始】 縮放比例1倍 坐標(1060,572) 【文字定位】 /TT1 12磅 【選擇字體】 [ (w) 間距24 (or) 間距-84 (l) 間距-24 (d) ] 【繪制文字】【文字結束】
請在頭腦中想像一下這個過程——是不是有一種強烈的「機械感」?如果說 Word 文檔使用的標記語言很像是給人下命令(「這里有一段話,把它用 Times 字體寫出來,位置上居中對齊……」),那麼 PDF 的語言則更像是在控制機器,定位、調整、落筆、抬起,移動到下一行;如此重復。聯想一下,鉛字排版和列印機的工作機制不也是類似的嗎?可見,用「列印」一詞來搭配 PDF 是十分恰當的。
如此對比之下,PDF 顯示效果的保真性就容易解釋了。雖然 Word 格式使用的語法明顯更容易理解,但問題在於不同「人」——不同軟件環境——聽到同樣一段指令,頭腦中的反應未必是相同的。「用 Times 字體顯示」——哪個是 Times 字體?沒有安裝這個字體怎麼辦?「居中對齊」——以什麼為參照物居中?怎麼計算居中?Word 文檔對此笑而不語,把問題留給了軟件去思考。正是這種自由裁量的空間為顯示效果的差異留下了隱患。
用 Pages 打開 Word 文檔出現的字體缺失問題
在 PDF 中,這樣的問題就很難出現。與標記語言那種相對的、描述式的標籤不同,PDF 語言幾乎都是絕對的、指令式的。例如,上面的 PDF 中,文字明顯是居中的,但代碼中從頭到尾沒有半個字提到「居中」;相反,它直接指明了文字的坐標。因此,無論什麼閱讀器讀到這份文件,只要根據坐標「照葫蘆畫瓢」地繪制,一定能得到相同的顯示效果。
類似地,下面這段代碼的作用是繪制出一個點狀的「L」形,很難想像它會給軟件留下什麼「自由發揮」的空間:
8 w 1 J [20] 0 d【設置畫筆為 8pt 寬、末端圓角、20pt 點狀線】200 200 m 200 100 l 250 100 l 【移動到(200,200) 畫直線到(200,100) 畫直線到(250,100) 】S 【確認繪制】
PDF 外觀穩定性的另一個原因是它嵌入了各種需要用到的外部資源。我們注意到,上面的 PDF 在設置字體時,沒有像 docx 文件那樣直接指定字體名稱,而是引用了一個代號般的 /TT1。實際上,/TT1 指向的是一個內嵌的字體,存儲在 PDF 內部的偏後位置。顯示時,閱讀器將根據這個代號找到字體,按照其中記載的形狀、寬度等信息,將字符「書寫」在指定的坐標上——就好比活字排版工按指示從字盤中取出字模,並放在母版上的特定位置一樣。相反,Word 文檔默認是不嵌入字體的;只要另一台電腦上沒有安裝用到的字體,或者安裝了不同版本的字體,就會導致顯示效果的差異。
活字
保真性的例外
不過,PDF 的這種保真性也不是絕對的。盡管 PDF 語句已經非常精確,也不能排除存在不同解讀方式的可能。特別是在 PDF 文件本身有瑕疵(例如語法不合規範、資源文件缺損等)時,閱讀器就必須「猜測」文件原本的意圖,誤差也就因此產生了。
例如,下面這份 PDF 格式論文是從中國知網下載的。在用 Adobe 的官方 PDF 工具 Acrobat 打開時,文件基本顯示正常。而在用 macOS 自帶的預覽 app 或 PDF Expert 打開時,就能明顯看出顯示效果是有問題的——所有的中文都變成了黑體,而不是應有的宋體。(你可能注意到從知網下載的 PDF 經常存在字體顯示問題。這是因為它們並非由排版軟件直接導出的「一手」版本,而是從私有的 CAJ 格式轉制而來的,存在很多兼容性問題。)
存在字體顯示問題的知網 PDF
為什麼會出現這樣的問題呢?用 Acrobat 附帶的 Preflight 工具檢查文件,可以發現它引用了包含 STSong-Light
(即華文宋體細版)在內的數個字體,但卻沒有嵌入對應的字體文件。顯然,這種空頭支票式的做法會引起閱讀器的困惑,它們將只能「猜測」該用什麼來代替STSong-Light
,不同的猜測結論將引發不同的顯示結果。
檢查發現問題 PDF 沒有嵌入應有的中文字體
其中,Acrobat 是一個非常「仁慈」的閱讀器,會盡可能做一些合理推測來修復文件本身的瑕疵。可以看出,它選擇了一個類似的字體——同屬宋體的 Adobe Song Std Light——來代替這個不存在的 STSong-Light
。相反,自帶的預覽 app 就沒有那麼多考慮了,它選擇直接回退到系統界面的默認字體—— 蘋方 來顯示,於是我們就只能和一片黑糊糊的黑體大眼瞪小眼。而如果用 Acrobat 的修復功能將缺失的字體文件補充進 PDF 後,將會發現預覽 app 也能正確顯示中文字體了,這印證了我們對問題成因的分析。
❷
為什麼 PDF 中的文字經常難以復制?
如果說 PDF 顯示效果的穩定是它吸引人們使用的主要優勢,那麼「文字難復制」一定是它讓很多人敬而遠之的原因之首。確實,從網頁上復制文字的那種方便靈活在 PDF 這里幾乎是一種奢望。很多時候,就連第一關——準確選中要復制的文字,都是難以跨越的障礙。
PDF 為什麼對復制操作這麼不友好呢?換種問法,滿足什麼條件的 PDF 才能正確復制出文字呢?答案是,PDF 文件的內容、文本的排列方式,以及文本和字體的編碼都會影響到文本的復制。另外,閱讀器對於復制操作的優化也是不可忽視的。
從掃描版 PDF 復制文本
要把文字復制出來,一個前提是 PDF 中必須真的包含文字。這聽起來好像是一句廢話,但實踐中大多數「文字復制不出來」的問題,原因都是目標 PDF 中根本沒有文本。這尤其多見於那些掃描而來的電子書和電子文檔;如果不經處理,它們的每一頁不過是原始文件的一張「照片」而已,顯然無法復制出文字。
當然,掃描版 PDF 是完全可能支持復制的。OCR(光學字符識別)工具可以識別出圖像中的文本,並將其寫入 PDF 中,使其支持選中和復制;這也是很多收費 PDF 軟件主要宣傳的功能點。需要避免的一個認識錯誤是,即使經過 OCR 處理的 PDF,其中的文本也並不是「附身」在原來的圖片上的。相反,它們通常被存儲在一個單獨的文本對象中,與圖片中的文字位置一一對齊。只不過由於 PDF 中的文本可以被設置為隱藏,當用戶試圖選中和復制這些隱藏文本時,看起來就好像是直接在圖片上選中和復制文字一樣。
經過 OCR 處理的掃描版 PDF 同樣可以選中和復制
這就解釋了為什麼在一些掃描版 PDF 中,文字選中效果看起來是「歪」的;而在另一些 PDF 中,選中和復制操作總是不連續或不完整。前者是因為加入的隱藏文本圖層沒有與圖片上的文字位置對齊,後者則是因為 OCR 識別不全,或者將連續的文本識別成了孤立的文字。
跨行和跨段復制文本
麻煩還遠沒有結束。即使確認了 PDF 中包含文本,也並不意味著就能把它們原封不動地復制出來。在復制跨越數行乃至數段的大片文本時,我們往往不能得到所預期的完整段落,而是多了一些無用的空白或者換行。例如,在下圖所示的復制結果中,PDF 似乎把頁面上的換行和連字符照單全收了,即使它們顯然不是原文的一部分。同樣的問題也會影響到文本搜尋,很多 PDF 中,斷成兩行的詞是無法正常搜尋的。
復制操作容易把不需要的內容也一並復制出來
這類現象仍然可以從「紙」的比喻中得到解釋。和紙質文件一樣,PDF 只負責記載形態而不記載含義。一個可能違反直覺的事實是,PDF 對於「段落」是沒有概念的。在其他格式中復制跨越兩行的文本,之所以能得到連續的結果,是因為軟件知道這串文字屬於同一個段落,顯示成兩行只是因為文檔寬度的限制。類似地,如果一個長單詞被拆成兩行顯示,其他格式在復制時是不會帶上連字符的,因為軟件知道那不是單詞的一部分。
在 PDF 中,這些結論都不適用。還是以上面那份 PDF 為例。觀察它的第一段第二行到第二段第一行:這三行涉及了分詞(行尾連字符)和分段兩個排版要素。這一部分在 PDF 代碼中的反映是:
q 1 0 0 1 57 755 cm BT 【定位到(57,755)】 13 0 0 13 0 0 Tm /Tc1 1 Tf 【設定字體】 [(…略去之前部分…) -141.7 (indepen) ] TJ 【繪制第一段第二行】ET Qq 1 0 0 1 533 755 cm BT 【定位到(533,755)】 13 0 0 13 0 0 Tm /Tc1 1 Tf 【設定字體】 (-) Tj 【繪制行尾的連字符】ET Qq 1 0 0 1 57 738 cm BT 【定位到(57,738)】 13 0 0 13 0 0 Tm /Tc1 1 Tf 【設定字體】 [ (dent o) 6 (…略去中間部分…) (ems) 5 (. ) ] TJ 【繪制第一段第三行】ET Qq 1 0 0 1 57 715 cm BT 【定位到(57,715)】 13 0 0 13 0 0 Tm /Tc1 1 Tf 【設定字體】 [ (Based ) (…略去之後部分…)] TJ 【繪制第二段第一行】ET Q
這里,我們需要關注的只有兩點:第一,代碼中的 Tj 或 TJ(繪制文字)命令每次處理的文字都不超過一行。實際上,PDF 做到換行和分段的方法,只不過是把那個「想像中的筆尖」移動到下一行或下一段的起始坐標處罷了。換句話說,除了筆尖移動幅度更大(以反映段間距),分段和普通分行在 PDF 中沒有任何區別。
第二,原文第二行行尾的連字符出現在了 PDF 代碼中。在同一份文檔的 Word 版本代碼中,這個連字符是不存在的,因為它並不是輸入內容的一部分。換句話說,其他格式不在文件中記錄,只在打開時才根據需要顯示的排版特性,制成 PDF 後卻被「固化」下來了。
既然 PDF 不記錄段落信息,而換行和連字符又明明白白地寫在文件中,它們會出現在復制結果里也就並不奇怪了。
當然,閱讀器可以根據文本的內容和布局等特徵進行推斷,提供更為合理的復制效果。例如打開上面的 PDF 時,PDF Expert 和 Chrome 瀏覽器內建的閱讀器都會對行尾的連字符作特殊處理,復制的結果是一個完整的單詞,搜尋中間斷開的「independent」整詞也能定位到結果;相反,用 macOS 自帶的預覽 app 和 Firefox 內建的閱讀器打開時,復制操作會把連字符當作單詞的一部分,搜尋整詞也得不到結果。
可能有人會問:PDF 為什麼連如此基礎的段落功能都不支持呢?這實際上是一種有意為之的選擇。PDF 是作為一種電子化的列印被 發明 出來的,而列印意味著編輯工作的終點。因此,PDF 完全可以不考慮宏觀層面的排版功能(因為用來創建它的字處理和制版軟件在這方面更專業),而只保留對少數局部版式(例如文字間距/Kerning)的支持。這不僅有利於節省文件空間,也進一步強化了 PDF 跨平台顯示的穩定性。
復制 PDF 文本的亂碼問題
確認了 PDF 里有文字,文本的排列也很整齊,是不是就能皆大歡喜了呢?很遺憾,對於中文用戶來說,從 PDF 中復制文字經常還會遇到一道坎:亂碼。
亂碼問題雖然在其他場合(例如網頁、遊戲等)也存在,但那基本都是發生在文字的顯示階段。既然 PDF 都正確顯示了文字,為什麼一經復制卻變得不是那回事了呢?
如上所述,PDF 的生成本質上就是一個「虛擬列印」的過程。這個比喻的言外之意——列印機是不識字的。它的全部使命,就是在紙張上按照坐標和字體記載的形狀,照葫蘆畫瓢地排列出指定的文字;整個過程完全不涉及「這是什麼字」之類的問題。類似地,PDF 繪制文本的流程,也不過是從字體資源文件中取出特定碼位上的字符(glyph),放置在某個坐標位置上。至於取出來的到底是什麼字,PDF 根本不關心。
可如果 PDF 是一個「文盲」,它在復制操作中又是靠什麼給出我們需要的文本的呢?
我們知道,計算機中的文字是通過編碼來區分和調用的。目前,最通用和常見的編碼方案是 Unicode。另一方面,在 PDF 內部嵌入的字體文件中,每個字符也有一個編碼;繪制文字時,Tj
/TJ
命令可以通過這個編碼向字體文件索取需要的字符。
上述兩套編碼可以是(並且在非英文環境下往往是)不同的,它們之間的「橋梁」,就是字體所附帶的 ToUnicode
屬性。ToUnicode
的值是一張映射關係表(稱作 character map / CMap),它給出了字體文件中每個碼位上的字符與 Unicode 編碼的對應關係。在復制、搜尋等操作中,PDF 就是靠 CMap 這張表得知每個字符到底是什麼「字」的。
PDF 涉及的兩套編碼
問題是:如果這張表弄丟了呢?或者雖然沒有丟,但是缺損了一塊?或者被人惡意篡改了?
讓我們來做一個「指鹿為馬」的實驗。下圖是一個非常簡單的 PDF 文件,上面只有一個「鹿」字。
示例 PDF 和它的 CMap 片段
用文本編輯器打開 PDF,可以看到 <ba6f> Tj
這一語句。不難猜出,該語句的作用是繪制字體文件中編碼為0xBA6F
的字符。根據 PDF 對象的交叉引用關係(後文會介紹)找到 CMap,其關鍵部分為:
<w:pPr> <w:jc w:val="center"/> <w:rPr><w:rFonts w:ascii="Times" w:hAnsi="Times"/><w:lang w:val="en-US"/></w:rPr></w:pPr><w:r w:rsidRPr="003C75CF"> <w:rPr><w:rFonts w:ascii="Times" w:hAnsi="Times"/></w:rPr> <w:t>Hello world!</w:t></w:r>
不難看出,這個 CMap 告訴閱讀器:字體文件中編碼為 0x6ABF 的字符對應 Unicode 中的 U+2FC5。查 Unicode 碼表可知,U+2FC5 正是漢字「鹿」。
現在,我們將上面代碼中的 2FC5
改成9A6C
,然後重新打開 PDF 文件。外觀上,文件似乎並沒有任何變化。但如果你試著把這個字復制出來,會發現得到的結果是「馬」。
「指鹿為馬」
這並不是什麼靈異事件,因為「馬」在 Unicode 中正是 U+9A6C
。
上述實驗表明,PDF 中的「所見」未必就是「所得」。只要 /ToUnicode
的內容(較舊的或者英文的 PDF 也可能是/Encoding
屬性)發生丟失或者錯誤,文字復制就會出現亂碼。與此同時,PDF 的顯示卻不會受到任何影響(因為文字繪制是由與編碼完全無關的語句控制的)。反過來思考,利用亂碼故障的原理,也可以通過故意破壞或者修改 CMap,製造出表面正常但完全無法復制和搜尋的文件,間接達到加密的效果。
❸為什麼 PDF 很難編輯?
除了顯示、復制上的問題,PDF 難以編輯的特性也經常引發用戶的疑問。不僅大多數可以免費獲得的 PDF 工具都只有閱讀功能,即使是那些具有編輯功能的軟件,編輯效果也往往達不到預期,甚至反而影響其他部分的格式。
如何解釋 PDF 的這一特徵呢?還是回到本文一以貫之的思路:把 PDF 看作真實的紙張來理解。
試想你手上有一份紙質筆記或者文件需要臨時塗改。生活經驗告訴我們下面幾點事實:第一,塗改操作只可能是小範圍的、逐字逐詞的。即使真的不得不修改一大段內容,你也只能慢慢用塗改液或者膠帶把它們抹去。第二,紙上原有的內容越多、格式越複雜,塗改起來就越困難。在增刪文字時必須要考慮到前後文的限制;原來的內容越密集,留下的修改餘地就越小。第三,很難做到完全不留痕跡的塗改。任何塗改操作都會對紙張造成損傷;對文字的修正,從紙張的角度看反而是一種「污染」。
這些描述幾乎完全適用於 PDF 文件的編輯,而原因還是要從內部結構來分析。前文中,我們已經了解了 PDF 語句如何在局部層面繪制出文本和圖形,這里再從宏觀角度簡單介紹一下 PDF 的構造。
一個 PDF 文件主要由四個部分構成,依次是文件頭(Header)、主體(Body)、交叉引用表(Cross-Reference Table)和文件尾(Trailer)。在其中最重要的主體部分,頁面、文本等元素和字體、圖片等資源存儲在稱為「對象」(object)的單元中。每個對象都有唯一的編號,並且可以無盡地相互包含和引用。例如,一個編號為 2 的頁面對象可以包含一個編號為 3 的子對象來描述頁面尺寸,又包含一個編號為 4 的子對象來存儲該頁上的文本;後者在指定字體時,又可以引用一個編號為 20 的字體對象,而這個字體對象的大小、字符寬度、曲線輪廓等信息也是分別存儲在其他對象中的;等等。
一個可能的 PDF 的構造
讀取 PDF 時,閱讀器首先從文件頭確定文件類型和版本號,旋即跳轉到文件尾,獲取交叉引用表的位置(以字節位置表示),它進而列出了 PDF 中所有對象的位置。憑借這張表,閱讀器就能找到每個對象,解析它們之間的包含和引用關係,並按照其中的命令將文件的全貌繪制出來。
這樣的構造對 PDF 的編輯有什麼潛在影響呢?可以看出,PDF 的結構是高度固化並且相互依賴的。它就像是一個積木堆,其中的每一塊「積木」——PDF 中的一個對象——都不是獨立的,而是與四周的其他積木相互支撐。編輯 PDF 文件就如同試圖改變一個成型的積木堆:移去或挪動一塊積木(對象),周圍的木塊不僅不會自動補上空白,反而可能因為失去支撐(對象的交叉引用關係)而變形。比如,從 PDF 中刪去一段,後面的文本並不會自動調整位置;相反,如果繪制它們的語句引用了被刪除部分的樣式,這些樣式也可能隨著刪除操作而丟失。
用 PDF Expert 刪除一段文字,後面的段落無法自動補齊空隙
而如果要往積木堆上增加一塊——往 PDF 中增加內容,面臨的風險同樣很大。且不論現有的空隙是否允許這麼做,你也無法預知剩餘的積木塊中是否有自己需要的。例如,出於節省體積的考慮,PDF 中嵌入的字體文件往往都是高度「子集化」的,只包含文件中用上的那部分字符。如果準備追加的字恰好不在其列,就很可能引發顯示問題。
退一步說,即使編輯操作幸運地沒有引發任何問題,它的成本也是很高的。哪怕只是插入一個字母的「微量」編輯,也會導致排在它之後所有內容的地址向後偏移 1 字節,於是依靠字節計數來定位的交叉引用表必須整個重寫。假如你的改動幅度更大(例如用了新的字體),就需要靠新增對象來做到,於是其他對象也必須相應更新以反映對象編號的變化。另一方面,從 PDF 中刪去內容時,編輯器未必能聰明到把不再有用的對象一並刪去。很多時候,這些成為空殼的對象就被「拋棄」在原地,白白占用空間,並且增加閱讀器解析文件時的計算成本。
作為對比,Word 格式那種標記語言的特性——在純文本上包裹標籤來記載格式信息——決定了它對於編輯操作是十分友好的。由於文本的內容和格式相互獨立,修改文本內容並不會對格式造成影響,反之亦然。這就好比把水倒在有造型的容器中,換掉一部分水,剩下的水依然服從於容器的形狀;換一個容器,水的形狀隨之變化,但還是原來那些水。
需要加以區分的是,對 PDF 的標註(annotation)操作——包括高亮、下劃線、筆記等——不屬於「編輯」的范疇。在做到層面,PDF 中的標註是附屬於所在頁面的子對象,其中記載了標註的類型、位置、形狀(如果有)、文本(如果有)等,與存儲文件內容的對象相互獨立。它們就像是紙上的便利貼,可以隨時移除而不留下痕跡。
那作為用戶,如果確實遇到編輯 PDF 的需求,應當如何解決呢?
首先,應當考慮是不是真的需要修改 PDF 文件本身。假如你將一份文件列印出來以後發現了錯別字,第一反應恐怕是回到電腦上修改、然後重新列印那一頁,而不是用膠帶黏去錯字然後手寫。類似地,既然 PDF 文件的本質就是「電子紙張」,如果發現錯誤,最正確和簡捷的做法應該是改動用於生成這個 PDF 的原始文檔,然後重新導出一遍,而不是考慮怎麼修改 PDF 本身。
即使手上沒有生成 PDF 的原始文檔,在直接修改 PDF 時也應該盡量控制編輯幅度。因為修改越多,對文件的「污染」就越大,也就越有可能造成格式混亂、體積膨脹等結果。如果要修改的內容確實很多,甚至可以考慮轉換/ OCR 為其他格式—編輯文字—導出為 PDF 這樣的路徑,或許效果反而比直接編輯好得多。
最後,盡管 PDF 對編輯操作非常不友好,但畢竟「事在人為」,不同軟件的編輯能力有很大差別。例如,來自第一方的 Acrobat Pro 就明顯高於平均水平。根據測試,它不僅能從 PDF 的布局中判斷出段落並以此為單位編輯(而不是孤立的文本塊),還能在編輯中一定程度上維持原有的對齊方式、段間距等設置。更為「黑科技」的是 Acrobat 的 OCR 功能,它甚至可以做到在識別文字的同時,將文本矢量化後、分離到與背景獨立的圖層中,從而能增刪掃描版 PDF 中的文字。
Acrobat 可以將掃面版 PDF 中的文字矢量化後做到編輯
結語
任何文件格式都有自己最擅長的用途。對 PDF 來說,它擅長的領域就是跨平台交換和文件歸檔,而那些需要頻繁編輯文本內容和版式的應用場景,則是其不能勝任的。只是在日常使用中,我們常常被 PDF 和其他文檔格式在外觀上的相似所誤導,把它用在了不擅長的領域,然後反過來抱怨這種格式在編輯和復制中的「笨拙」。這多少是錯怪了 PDF。本文之所以一再將 PDF 類比為實體文檔,一方面是為了便於解釋技術原理,另一方面也是為了提供一種選用 PDF 格式的標準:適合列印出來的內容,一般也才適合「列印」成 PDF。
理解 PDF 的原理也有助於挑選合適的閱讀/編輯工具。如上所述,軟件對瑕疵 PDF 的寬容度和修復能力,對文本搜尋、復制的識別、優化能力等細節,是最值得重點考察的;這些看似不起眼的功能點對使用體驗和工作效率有極大影響。相反,那些頻繁被當作行銷「亮點」的功能,特別是 PDF 編輯、格式轉換等,反而不那麼重要。因為 PDF 從結構上就不適合修改,這些所謂的編輯功能很難達到用戶的預期,何況還有大量類似於 SmallPDF 的免費工具可以滿足臨時的、精度不高的編輯需求。至於嚴肅、專業的 PDF 編輯,Acrobat 可能是唯一的選擇。
最後需要說明的是,PDF 涉及的技術非常複雜,這篇文章只是從日常使用的角度做了最粗淺的介紹。文中很多地方為了便於理解,採用的解釋和比喻是過度簡化的。如果對 PDF 格式的原理有進一步的興趣,建議直接閱讀 PDF 的 標準文件。這份標準雖然十分冗長,但並不難讀。哪怕只是挑選幾個關心的主題來瀏覽,相信都會對理解 PDF 格式以至排版技術有很大的啟發。