技術記事

Delphi向けlosLab PDFライブラリの比較:HotPDF、PDFium Component、PDFlibPas

3つのライブラリ。3つの異なる役割。間違ったものを選択すると、回避策に何週間も費やすことになり、1つで済むところに3つすべてを選択すると、予算に組み込んでいないメンテナンスのオーバーヘッドが発生します。ここでは、各losLab PDFライブラリが実際に何を行うか、どこに適しているか、そしてどこで兄弟ライブラリに引き継ぐかについて直接説明します

HotPDF:DelphiでPDFをゼロから作成する

HotPDFはPDFドキュメントを生成するためのネイティブVCLコンポーネントです。そのモデルは命令型かつページ中心です。つまり、THotPDF インスタンスを構築し、ドキュメントのプロパティを設定し、BeginDoc を呼び出し、CurrentPage に描画し、必要に応じてページを追加し、EndDoc で閉じます。この順序が重要です。なぜなら、BeginDoc が実行された瞬間に暗号化辞書と圧縮設定がコミットされるからです。それ以降に割り当てられたものは、遡って適用されるのではなく、静かに無視されます

描画サーフェスは、Delphiレベルで完全なPDFオペレータセットをカバーしています。位置指定されたUnicodeテキスト用の TextOut、TrueTypeの埋め込みを伴う SetFont、ベクタープリミティブ(線、ベジェ曲線、楕円、長方形)、ファイルやメモリからの画像配置、そしてバーコード生成です。座標は左下隅からのポイント単位であり、Yは上に向かって増加します。これは誰もが一度はつまずく点です。フォントの状態は AddPage を越えて保持されないため、改ページのたびに SetFont を呼び出す必要があります

AcroFormフィールドは第一級の市民です。テキストフィールド、チェックボックス、ラジオボタン、コンボボックス、リストボックス、およびプッシュボタンを、それぞれ1回の呼び出しでページオブジェクトに直接追加できます。また、HotPDFは LoadFromFile を通じて既存のPDFをロードし、フィールドの値を入力または読み取ることもできるため、フォームの構築と、その値の入力を自動化するという2つの異なるワークフローで役立ちます

暗号化もドキュメントレベルで処理されます。CryptKeyLength でスキーム(40ビットRC4からAES-256まで)を選択し、ActivateProtection でそれを有効にし、ProtectOptions でISO権限フラグを設定します。2つのAES-256リビジョンモード(R5とR6、UseAES256R6 で制御)が存在するのは、リビジョン6がリビジョン5の既知の弱点を修正しているものの、PDF 2.0対応のビューアを必要とするためです。それらの間の選択は互換性の決定であり、利便性によるものではありません

HotPDFにおけるデジタル署名のサポートはPAdESのベースラインプロファイルをカバーしているため、署名がETSI EN 319 142の要件を満たす必要があるワークフローに適しています。出力の生成だけが必要な場合、最初に手を伸ばすべきライブラリはHotPDFです

PDFium Component:既存のPDFのレンダリング、表示、読み取り

PDFium Componentは、GoogleのPDFiumエンジンをVCLコンポーネントとしてラップしたものであり、HotPDFとは根本的に異なる役割を持ちます。HotPDFが書き込むのに対し、PDFium Componentは読み取りとレンダリングを行います。コアオブジェクトは TPdf であり、FileName を設定して Active := True とすることでファイルを開くドキュメントマネージャーです。ロードの失敗は例外として発生しません。Active が単に False のままになるため、代入後にそれを確認することは必須です

レンダリングは、フォームにドロップして PdfView.Pdf := Pdf を通じて TPdf インスタンスにリンクするビジュアルコンポーネントである TPdfView を通じて実行されます。ズームとフィットモードはドキュメントではなくビューに存在します。人々がつまずく微妙な点が1つあります。それは、Pdf.PageNumberPdfView.PageNumber が独立したプロパティであるということです。一方を設定してももう一方は更新されず、ビューベースの抽出API(単語ボックス、読み取り単位)は、ドキュメントの現在のページではなく、ビューの現在のページを使用します

テキスト抽出は、losLabのラインナップの中でPDFium Componentに直接の競合が存在しない分野です。ReadablePageContent は読み取り順序を考慮した構造化されたテキストを返し、PageWordBoxes は単語レベルの境界矩形を提供し、DocumentReadingUnits はドキュメント全体を走査します。アクセシビリティの作業のために、IsTagged は構造ツリーが存在するかどうかを伝え、ValidatePdfUa はUAの適合性チェックを実行します。これらのAPIにより、PDFium Componentは新しいPDFを生成するのではなく、既存のPDFの内容を理解する必要があるワークフローにとって自然な選択肢となります

フォームへの入力は、基盤となるエンジンが公開するのと同じAcroFormレイヤーを通じて、PDFium側でも機能します。これは、ソースドキュメントがすでに存在し、自分でフォームフィールドを構築するのではなく、入力の完了を自動化する場合に適しています

PDFlibPas:操作、コンプライアンス署名、および直接ファイルアクセス

PDFlibPas(バージョン3.73.0)は、複雑さのスペクトルの反対側に位置します。これは、同じドキュメントモデルの上に3つのAPIレイヤーを公開します。Quick-PDFの呼び出し規約と互換性のあるフラットなハンドルベースのファサード(TPDFlib)、完全なオブジェクトツリーレイヤー(TPDFDocument)、そして完全なオブジェクトグラフをロードすることなくファイルのバイト列を直接操作するストリーミングパーサー(TSmartPDFReader / TSmartPDFWriter)です

ストリーミングレイヤーこそが、PDFlibPasが大きなドキュメントにとって正しい選択となる理由です。TSmartPDFWriter は、相互参照テーブル全体を再構築することなく、ディスク上のファイルに増分更新を追加できます。これは、効率的な再保存とPAdESの長期検証(LTV)スタンプの両方の基盤となるメカニズムです。署名されたハッシュが特定のバイト範囲をカバーする必要があり、ドキュメントを書き換えることなく署名が適用される、コンプライアンスレベルの署名ワークフローにとって、このレイヤーは唯一の実行可能なパスです

TPDFDocument レベルでのドキュメント操作には、Merge による結合、範囲文字列を用いた CopyPagesFromDoc による選択的なページのコピー、および SetMinimumVersionLockSaveVersion によるバージョンのガバナンスが含まれます。出力がロックされたバージョンを超えるような機能を保存しようとすると、バージョンロックによってエラー602が発生します。これは、アーカイブのコンプライアンスのために出力が特定のPDFリビジョン内にとどまることを保証する必要がある場合に便利です

PDF/Aサポート(ISO 19005)はPDFlibPasのコンフォーマンスワークベンチにあります。仕様により、暗号化とPDF/Aは相互に排他的であることに注意してください。1つのファイルに両方を持たせることはできません。暗号化された配布用コピーとPDF/Aのアーカイブ用コピーの両方を必要とするワークフローでは、2つの別々の成果物を生成する必要があります

それらの間の選択

典型的な決定木は短いです。データから新しいドキュメントを生成する場合はHotPDFを使用します。DelphiのVCLアプリケーションで既存のドキュメントからテキストをレンダリングまたは抽出する場合はPDFium Componentを使用します。既存のPDFを大規模に、または増分保存のセマンティクスを用いて操作、結合、またはコンプライアンス署名する場合はPDFlibPasを使用します。多くの本番システムでは、3つのうち2つを使用しています。例えば、HotPDFで出力を生成し、アーカイブする前にPDFlibPasでそれに長期検証スタンプを適用したり、HotPDFが生成したものをPDFium Componentでプレビューしてから下流に送信したりします

3つすべてがDelphiとC++Builder向けのネイティブPascalソースとして出荷されており、VCL以外のランタイム依存関係はありません。PDFium Componentは追加でPDFium DLLをバンドルしており、これがエンジンのレンダリングと解析作業をカバーします。各ライブラリの製品ページには、完全なAPIリファレンスと現在のバージョン履歴が掲載されています

個々のライブラリの詳細については、こちらをご覧ください: HotPDF ComponentPDFium Component、および PDFlibPas