マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

(x)dvipdfmx が文書情報を Unicode する件に関するメモ(2)

前回の続き)

引き続きメモメモ。

PDF のページ番号を☃にするとアレな件

LaTeX 文書において、ページ番号を☃にしたいとする。本当は☃の 1 進数が理想的であるが、今の問題の本質とは無関係なので、ここでは簡単に、「☃1、☃2、……」で済ませることにする。

% 文字コードUTF-8
\documentclass[autodetect-engine,dvipdfmx-if-dvi,
  a4paper,ja=standard]{bxjsarticle}
\usepackage{hyperref}
\hypersetup{pdftitle={☃文書}}
\renewcommand{\thepage}{\arabic{page}}
\begin{document}
\section{☃と{\TeX}の関係}
アレ。
\newpage
\section{☃はアレなのか}
☃「違います」
\end{document}

この文書を LuaLaTeX・XeLaTeX・upLaTeX + dvipdfmx のそれぞれで PDF 文書に変換すると、upLaTeX + dvipdfmx の場合だけ、「PDFのページ番号情報」(PDF ビューアの UI に出てくるやつ)の中の☃が文字化けしてしまう。アウトラインや他の文書情報中の☃は正常であるにも関わらず、である。*1

なぜ☃できないか

この原因は単純にいうと、次の通り。

ソレには ToUnicode 指定が効いていないから。

次のような文書で実験してみる。

% plain upTeX/XeTeX 文書, 文字コードUTF-8
%\special{pdf:tounicode UTF8-UTF16}
% PDFのページ番号表示を設定する
\special{pdf:docview << /PageLabels << /Nums [ 
    0 << /P (☃) >>          % UTF-8  → NG
    1 << /P <E29883> >>      % UTF-8  → NG
    2 << /P <FEFF2603> >>    % UTF-16 → OK
] >> >>}
% 空のページを出力する
\nopagenumbers
\null\vfil\eject \null\vfil\eject \null\vfil\eject \bye

これをこのまま uptex + dvipdfmx で変換すると、ページ番号の文字列を UTF-8 で書いている 1、2 ページ目は文字化けし、UTF-16BE で書いている 3 ページ目は正常になる。(PDF の仕様を既知とすれば)これは当然であろう。ところがこの文書の場合、さらに次のようなことが起こる。

  • xetex (xdvipdfmx) でも同じ結果になる。
  • さらに、pdf:tounicode special を有効にしても同じ結果になる。

前回の話を踏まえて考えると、この 2 つの場合では (x)dvipdfmx が UTF-8→UTF-16BE の変換を行うことが予想されるが、実際にはそうならない。PDF の中を覗いて実際に出力された Catalog 辞書の中を調べると、全く変換が行われていないことが判る。

1 0 obj
<< %※整形済
  /PageLabels << /Nums [
      0 << /P <e29883> >>  % 変換されて
      1 << /P <e29883> >>  % いない!
      2 << /P <feff2603> >>
    ] >>
  /Pages 12 0 R
  /Type /Catalog
>>
endobj

ということは、何となく「Catalog 辞書(pdf:docview special)は変換の対象から漏れている」という仕様であるように見える。ところが実はそうでもないらしい。例えば、

\special{pdf:docview << /Snowman (☃) >>

を書いて xdvipdfmx で変換した場合は、Catalog 辞書中の文字列はちゃんと UTF-16BE に変換されている。どうやら、「何が変換対象であるか」を具体的に調べ上げる必要があるらしい。

*1:BXJS クラスの標準設定では、XeLaTeX や LuaLaTeX の場合は hyperref に unicode オプションが自動的に付加され、upLaTeX の場合は自動的に適切な ToUnicode special が発行される。