前回はiOSのAPIを使ってPDFドキュメントからテキストデータを抜き出す事はできたが、日本語は文字化けしてしまっていた。今回は、この原因を究明し、どのように対応を行えばいいかを説明していこう。

PDFのフォント情報

例によって、Voyeurを使ってPDFデータを確認してみよう。テキストデータが格納されているのは、Tjオペレータの前だった。そのデータの前を見てみると、「Tf」というオペレータがあるのが分かる。PDFの仕様書によると、Tfは「Set text font and size」を示すオペレータである。つまり、テキストを表示するためのフォントを指定しているのだ。

上に挙げた例では、Tfが示す値として「/F2.1」が読み取れる。これが、フォントを表す識別子となる。

となると、次はフォントの定義を確認してみよう。再びVoyeurを使う。テキストデータは、それぞれのページの「/Contents」キーの下にある。それに対して、フォント情報は「/Resources」キーの下になる。ここには、カラースペースや画像オブジェクトといったリソースデータが格納される。フォント情報は、「/Font」の下にある。

ここに格納されているフォント情報を確認しよう。上の例では、フォント名は「/FGYQQA+HiraKakuProN-W3」になっている。つまり、ヒラギノ角ゴシックだ。そして、エンコーディングとして「/Identity-H」という値が指定されている。これが、テキストデータのエンコーディングとなるのだ。

では、次の疑問である。このIdentity-Hとは、なにものであろうか?

Identity-Hエンコーディングとは

Identity-Hエンコーディングは、PDFの仕様書によると次のように定義されている。「The horizontal identity mapping for 2-byte CIDs;」。つまり、CIDの値と言う事だ。では、CIDとは何か。これは、Adobeが定めるCIDフォントの識別番号である。

具体的に説明していこう。AdobeのCIDフォントでは、「Adobe-Japan1」という文字コレクションが使われている。これは、フォントが持つ字の形のIDを定義したものである。その仕様書は、Adobeのサイトから確認する事ができる。それを見ると、次のような字形とコードの表が与えられている。

このコードがCIDであり、Identity-Hの値であり、ひいてはPDFドキュメントに使われている値である。つまり、PDFのTjオペレータから取り出した値は、この表に示されているものなのだ。

CIDの値は、一般の文字コードとは違うものである事を理解しておいてほしい。CIDは、フォントの「字形」(または「グリフ」)に対して与えられるIDだ。文字の意味が同じでも、画面に表示されるときの形が違うものは、別のIDが与えられる。たとえば、異字体や縦書き用の字形に対するものだ。これらは文字コードは同じだがCIDの値は違う、ということが発生する。

一般に文字コードはフォントとは別に定義されるものだが、Identity-Hのエンコーディングはフォントに依存することになる。これが、PDFドキュメントにおいて、フォント情報の中にテキストエンコーディングが含まれる理由だろう。

CIDからUnicodeへの変換

これでPDFドキュメントに含まれるテキストデータのエンコーディングは分かった。最後の問題は、これをプログラム中で取り扱い易いように、Unicodeに変換する事である。

一般にフォントファイルには、Unicodeから自身が持っている字形(グリフ)のIDを取得するための、変換テーブルを持っている。これは、CMap (Character Map)テーブルと呼ばれる。たとえば、OpenTypeフォントのCMapテーブルの定義は、こちらで確認する事ができる。

CIDからUnicodeを取得するには、CMapテーブルとは逆の変換を行うことになる。これを行うテーブルはどうやって取得すればよいのだろう?PDFドキュメントによっては、このテーブルがドキュメント内部に含まれていることがある。これは、ToUnicode CMapsと呼ばれる。これから解析するPDFドキュメントがこのテーブルを持っている場合、これを使って変換を行えば良い。

しかし、現在流通している多くのPDFドキュメントは、このテーブルを持っていない。したがって、あらかじめアプリケーション側で、Adobe-Japan1のようなメジャーなCIDに対するToUnicodeマップを作成して組み込んでおく必要があるだろう。

これで、PDFから日本語テキストを取り出すために必要な情報が揃った。次回は、これらを組み込んだソースコードを紹介しよう。