🔗

hyperref パッケージは PDF の注釈機能を用いて実現されている

2023/02/16に公開

PDF(Portable Document Format)形式の文書を読んでいると、時折ハイパーリンクが埋め込まれた箇所を見掛けることがあります。これは PDF における注釈機能によって実現されているものです。

hyperref パッケージ

LaTeX における hyperref パッケージは、文書内へのハイパーリンクの埋め込みを実現するコマンドです。\url\href コマンドを記述した文書をコンパイルすると図 1 の出力が得られ、色付きの矩形に囲われた領域をクリックすることで、指定された Web ページへとジャンプできます。

\documentclass{jarticle}
\usepackage[dvipdfmx]{hyperref}
\usepackage{pxjahyper}
\begin{document}
  \url{https://example.com} のように URL を直接埋め込めるほか、
  Markdown における \verb|[Example Domain](https://example.com)| に相当する
  \href{https://example.com}{Example Domain} といった記述もサポートされている。
\end{document}

LaTeX で生成した、ハイパーリンクを含む PDF 文書のスクリーンショット
図 1:LaTeX における \url, \href コマンドの出力

さて PDF の仕様において、このハイパーリンクはどのように定義されているのでしょうか。ディスプレイ上では表示されるものの、印刷すると消失する謎の枠線も気になるところです。

注釈

PDF の仕様書としてお馴染み PDF References sixth edition を参照してみると、URL へのジャンプといったインタラクティブな行為はアクションとして定義され、アクションのトリガとして注釈・しおりが指定されています。hyperref のように文書中にリンクを設ける場合は注釈が用いられます。

注釈やしおりは、文書中のある場所への移動の代わりに、アプリケーションの起動、音声の再生、注釈の表示の変更といった、ビューアが実行するアクション(PDF 1.1)を指定できます。注釈・しおり項目の辞書内の A エントリ(任意、p. 606 8.15, p.585 8.4を参照)に、注釈・しおり項目が有効化したときに実行するアクションを指定します。
出典:Adobe Systems Incorporated: PDF References sixth edition - Adobe® Portable Document Format Version 1.7, p.647(筆者訳)

Annotation dictionaries

PDF ファイルは連鎖的な辞書構造を用いて構成されます。
今回使用する注釈を定義するには、Annotation dictionaries と呼ばれる辞書を定義します。定義した 1 つ以上の Annotation dictionaries を、Page Objects の Annots エントリに配列として記述することで、ページに注釈が関連付けられます。

Annotation dictionaries は、以下のエントリを要求します(リンクの記述に必要なエントリのみを抜粋)。

エントリ名 必須 詳細
Type name o Annot
Subtype name o 注釈の種類を指定する。リンクの場合は Link
Rect rectangle o 注釈の座標と大きさを指定する。left, bottom, right, top を要素とする数値型の配列
F integer - 注釈の特徴を指定する。後述するビットフラグを使用
BS dictionary - 枠線のスタイルを指定する(後述)
Border array - 枠線のスタイルを指定する(後述)

枠線のスタイル

枠線のスタイルを指定するには、BS エントリに以下の辞書を設定します。
BS エントリに競合する存在として Border エントリも存在しますが、PDF 1.2 で新たに定義された BS エントリでは、より詳細なスタイル指定が可能となっています。PDF 1.2 以降であれば基本的に前者を使用して問題なさそうです。

エントリ名 必須 詳細 デフォルト値
Type name - Border -
W number - 枠線の幅をポイント単位で指定する 1
S name - 枠線のスタイルを指定する。以下の値を選択。
S: solid, D dashed, B: beveled, I: inset, U: underline
S
D array - S エントリに D を指定した場合に指定する。graphic state における line dash pattern を記述 [3]

line dash pattern は数値型の配列です。[3 2] と指定すると、長さ 3 の線が描画され、続いて長さ 2 の間隔が設けられます。

Anotation flags

F エントリにはビットフラグを用いて、最下位から順に注釈の特徴を指定します。指定のないビットは 0 とします。印刷時における注釈の表示等はここで設定されていたんですね。

位置 名称 バージョン 有効な場合
1 Invisible - 注釈が標準的なタイプに属さず、ハンドラも利用できない場合に、注釈を非表示にする
2 Hidden PDF 1.2 ― 種類や注釈ハンドラによらず、画面上で注釈を非表示にする
3 Print PDF 1.2 ― 印刷時に注釈を表示する。Acrobat 3.0 よりも前ではフラグの値によらず印刷時は非表示
4 NoZoom PDF 1.3 ― ページの倍率によらず、注釈を拡大しない
5 NoRotate PDF 1.3 ― ページの回転によらず、注釈を回転させない
6 NoView PDF 1.3 ― Hidden + ReadOnly
7 ReadOnly PDF 1.3 ― マウスクリックやマウスオーバーに反応しない
8 Locked PDF 1.4 ― 注釈の削除・編集を禁止する
9 ToggleNoView PDF 1.5 ― 特定のイベントに対して NoView のフラグを反転させる。マウスオーバー時等に使用する
10 LockedContents PDF 1.7 ― 注釈の内容の変更を禁止する

以下のコードを用いてビットフラグを求めます。

public static int GetBitFlags(byte[] bits)
{
    int no = 0;
    for (int i = 0; i < bits.Length; i++)
    {
        no |= bits[i] << i;
    }
    return no;
}

注釈を描画してみる

これらを用いて、以下の矩形によって表される注釈を描画します。

  • 座標:左下を原点として (10 pt, 10 pt)
  • サイズ:幅 40 pt、高さ 10 pt
  • 枠線:RGB(255, 0, 102)、幅 2pt、[4, 4] の破線
1 0 obj <<
  /Type /Page
  ...
  /Annots [ 1 0 R ]
>>
endobj

2 0 obj <<
  /Type /Annot
  /Rect [5 5 20 20]
  /Subtype /Link
  /BS 3 0 R
>>
endobj

3 0 obj <<
  /Type /Border
  /W 2.0000000
  /S /D
  /D [ 4.0000000 4.0000000 ]
>>
endobj

間接オブジェクト 2 0 obj として Annotation Dictionaries を定義し、これを Page Objects 1 0 obj から参照しています。これを Adobe Acrobat で開くと、図 2 の通りピンク色の矩形が出現しました。これが注釈です。

Adobe Acrobat に注釈のある PDF 文書が表示されたスクリーンショット

アクション

この注釈をクリックした際に Web サイトに遷移するように、URI Actions を追加します。URI Actions も例によって辞書として定義され、以下のエントリを持ちます。

エントリ名 必須 詳細
S name o URI
URI ASCII string - 7 ビット ASCII で URI を指定する
IsMap boolean - true にした場合、URI が解決された時点でのマウス座標が URI のクエリパラメータとして追加される。初期値 false
(例:https://example.com/?5,6

URI Actions の辞書を、先程用意した Annotation Dictionaries の A エントリに追加します。

2 0 obj <<
  ...
  /A <<
    /S /URI
    /URI (https://www.tsukuba.ac.jp)
    /IsMap false
  >>
>>

アクションを追記した PDF を開き、注釈の箇所をクリックすると、Web ブラウザが起動し、指定された URI(https://www.tsukuba.ac.jp)が開かれました。あとはこれにテキストを重畳すれば、hyperref パッケージが提供するコマンドと同等の機能が再現できます。

Adobe Acrobat で PDF 文書上の注釈をクリックし、Web ページに遷移するスクリーンショット
図 2:注釈をクリックすると Web ページへと遷移する

なお \ref コマンドで実現されるような文書中の相互参照は、Action Types を Go-To Actions に変更することで実現されます。

参考文献

[1] Adobe Systems Incorporated: PDF References sixth edition - Adobe® Portable Document Format Version 1.7. (2006), https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.7old.pdf

Discussion