PDFは、WordやRTFのようなドキュメントフォーマットとは異なります。これらのフォーマットは、表示時にレンダラーが解釈するコンテンツのシーケンスを格納するため、出力は存在するフォントやレイアウトエンジンに依存します。PDFは、そのプロセスの結果を格納します。つまり、正確なレンダリング命令、フォントプログラム、圧縮された画像ストリーム、およびそれらをすべてのページの自己完結型の説明に結び付けるオブジェクトグラフです。ファイルには、準拠する任意のレンダラーで各ページを同一に再現するための十分な情報が含まれています。これは、PDFの主要な設計目標であると同時に、プログラムでPDFを生成、解析、または変更しようとする際に遭遇する複雑さの主な原因でもあります
オブジェクトモデル
すべてのPDFは、番号付けされたオブジェクトのコレクションです。オブジェクトは、ブール値、整数、実数、名前、文字列、配列、辞書、ストリーム、またはnullのいずれかになります。興味深いもののほとんどは辞書です。辞書は、キーが名前で、値が番号と生成番号による他のオブジェクトへの参照を含む任意の他のオブジェクトタイプであるキーと値のペアのセットです。ストリームは、辞書の後に続くバイトシーケンスであり、通常は圧縮されています
カタログ辞書はルートです。それはページツリーを指し、ページツリーはページ辞書をフラットなリストではなくバランスの取れたツリー構造で編成します。そのため、10,000ページのドキュメントの5,000ページ目に移動する際に、先行するすべてのページ記述子をトラバースする必要はありません。各ページ辞書は、そのコンテンツストリーム(ページ記述演算子の1つ以上のシーケンス)、そのリソース辞書(フォント記述子、カラースペース、および画像XObjectを順に参照する)、およびメディアボックス(ページが存在する座標空間)を参照します。座標の原点は左下隅にあり、正のY軸が上向きに走り、単位は1/72インチです
ファイルの最後には相互参照テーブル(cross-reference table)があり、これは各オブジェクト番号をファイル内のバイトオフセットにマッピングします。これによりランダムアクセスが可能になります。ビューアはまず相互参照テーブルを読み取り、必要なオブジェクトに直接シークします。PDF 1.5では、相互参照ストリームが導入されました。これにより、テーブルがストリームオブジェクトに圧縮され、関連するオブジェクトがオブジェクトストリームにパックされるため、多数の小さなオブジェクトを含むドキュメントのファイルサイズが著しく削減されます
コンテンツストリームとグラフィックスモデル
ページの視覚コンテンツは、1つ以上のコンテンツストリームに存在します。各ストリームは、オペランドが点在するPDFオペレーターのシーケンスです。テキストオペレーター BT はテキストオブジェクトを開始し、Tf はリソース辞書からフォントとサイズを選択し、Td はテキストカーソルを配置し、Tj または TJ は文字列を描画し、ET はテキストオブジェクトを閉じます。ベクターグラフィックスも同様のパターンに従います。m はパスの開始点を設定し、l は線分を追加し、c はベジェ曲線を追加し、f または S はパスを塗りつぶすかストロークします
グラフィックス状態は、現在の変換行列、線幅、カラースペース、塗りつぶし色、ストローク色、およびクリッピングパスなど、演算子間で発生するすべてを管理します。q および Q などの演算子は、グラフィックス状態をスタックにプッシュおよびポップします。これは、PDFが周囲のコンテキストに影響を与えることなく、ローカル座標変換と一時的な状態のオーバーライドを実装する方法です。フォームXObjectはこれを一般化したもので、単一の Do 演算子を使用して、ページ上の任意の位置とスケールで描画できる独自のリソース辞書を持つ自己完結型のコンテンツストリームです
フォントの埋め込みとテキスト抽出
PDFは名前でフォントを参照し、ビューアが何かを代替することに依存できますが、実際には、共有する予定のドキュメントにはフォントデータを埋め込む必要があります。PDFに埋め込まれたType 1またはTrueType/OpenTypeフォントは、フォントファイルストリームを指すフォント記述子辞書を保持しています。TrueTypeフォントの場合、そのストリームにはバイナリフォントプログラムが含まれます。Type 1の場合はPFBデータです。サブセット化(本格的なPDFジェネレーターがすべて行うこと)は、ドキュメントで参照されていないグリフを取り除くことで、大きなUnicodeフォントでもファイルサイズを管理しやすいレベルに保ちます
テキストの抽出は、フォントの埋め込みが逆効果になる部分です。文字の視覚的表現は、埋め込まれたフォントプログラム内のグリフによって決定されます。その文字のUnicode値は、フォント辞書に添付されたToUnicode CMapストリームによって決定されます。ToUnicode CMapが欠落しているか間違っている場合、PDFビューアはテキストを読みやすくレンダリングできますが、意味のあるUnicodeとして抽出することはできません。これが、一部のPDFからコピーアンドペーストすると文字化けが発生する理由です。タグ付きPDF(ISO 32000 §14.8)は、ページのコンテンツを段落、見出し、表のセルなどのドキュメントのセマンティックな役割にマッピングする論理構造ツリーという第2のレイヤーを追加します。スクリーンリーダーやリフローエンジンは、生のコンテンツストリームの順序ではなく構造ツリーを使用します。これにより、視覚的に適切にレイアウトされたPDFでも、タグ付けがないか間違っているとアクセスできない可能性がある理由が説明されます
増分更新とデジタル署名
既存のPDFへの変更をゼロから書き直すことなく保存する場合、新しいオブジェクトは、新しい相互参照セクションと新しいトレイラー辞書とともに、元のファイル本体の後に追加されます。更新されたトレイラーは新しい相互参照データを指し、置き換えられたオブジェクトはファイル内に残りますが、単に新しい相互参照チェーンによって参照されないだけです。これが「増分更新」であり、2つの重要な結果をもたらします
第一に、ファイルは保存サイクルのたびに大きくなります。繰り返し編集されて保存されたドキュメントには、不要になったオブジェクトのレイヤーが蓄積されます。QPDFのようなツールは、ファイルをリニアライズ(最適化)するか圧縮して書き直すことでそのスペースを再利用できますが、デフォルトは蓄積です。第二に、デジタル署名はその整合性モデルを増分更新に依存しています。ISO 32000の署名はファイルのバイト範囲をカバーしており、通常は署名値自体のプレースホルダーを除くすべてを対象とします。追加の増分更新として現れる署名後の変更は、署名後に行われた修正として検証リーダーに表示されます。これはまさに必要とされる監査証跡です。ただし、これは、文書の権限設定(ISO 32000-2 §12.7.6)に変更が準拠している限り、承認署名の追加やフォームフィールドへの入力などの特定の修正が、元の署名を無効にすることなく標準によって明示的に許可されていることも意味します。これらの権限の範囲外の修正は、不正としてフラグが付けられます。この区別を正しく理解することは、下流で連署されるドキュメントを生成する際に重要です
適合性レベルとISO 32000の系譜
PDFは1993年にプロプライエタリなAdobeフォーマットとして始まり、PostScriptのイメージングモデルを吸収し、15のバージョンにわたって機能(1.1での暗号化、1.2での対話型フォーム、1.3でのデジタル署名と論理構造、1.4での透明性、1.5でのオブジェクトストリーム、1.6でのAES暗号化など)を蓄積してきました。Adobeは2007年にPDF 1.7をISOに提出し、その結果ISO 32000-1:2008が誕生しました。ISO 32000-2:2020はPDF 2.0をカバーしており、仕様が不十分だったいくつかの領域を厳格化し、AES-256キー派生を改訂し(リビジョン5をリビジョン6で置換)、関連ファイルとリッチメディアの明示的なサポートを追加しました
サブ標準は同じベースから派生しています。PDF/A(ISO 19005)は、アーカイブの安定性のために機能を引き換えにします(暗号化なし、外部コンテンツへの依存なし、すべてのフォントの埋め込み、デバイスに依存しないカラースペース、XMPメタデータの必須化など)。PDF/A-1はPDF 1.4に基づいており、PDF/A-2はPDF 1.7に基づいており、PDF/A-3は任意の形式の埋め込みファイルを許可します。PDF/X(ISO 15930)は、印刷制作用のサブセットです(出力インテント、裁ち落としとトリムボックス、古い適合レベルでは透明性なし)。PDF/UA(ISO 14289)は、アクセシビリティのためにタグ付き構造、Unicodeマッピング、および言語メタデータを義務付けています。これらは競合するフォーマットではありません。これらはコアPDFの上の追加の制約のセットであり、制約が競合しない限り、1つのファイルが同時に複数の標準に適合することができます
PDFを生成または処理するコードを書く人にとって、実用的なベースラインはISO 32000-2であり、相互参照モデル(§7.5)、グラフィックス状態(§8.4)、テキスト状態演算子(§9.3)、フォント記述子とToUnicode(§9.6および§9.10)、対話型フォーム(§12.7)、およびデジタル署名(§12.8)をカバーするセクションには細心の注意を払う必要があります。標準は長いですが、プログラムによるPDFの作業のほとんどは、その狭い部分に繰り返し触れることになります。オブジェクトモデルと相互参照メカニズムを理解することがエントリーポイントであり、そこから先はすべて専門化です