マクロツイーター

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

xdvipdfmx がうまくいきません

PDFタイトルで🍣するとアレ

以前の記事で述べたように、XeTeX(xdvipdfmx)の既定の動作*1では、pdf:docview special などで与えられる「PDF の文書情報の文字列」について、UTF-8 → UTF-16BE の変換を行う。

% plain XeTeX 文書, 文字コードUTF-8
\special{pdf:minorversion 4}% オブジェクト圧縮を回避
\special{pdf:docinfo << /Title (☃) >>}% U+2603 SNOWMAN
\nopagenumbers \null \bye

(文書情報のオブジェクト*2

2 0 obj
<<
  /Creator ( XeTeX output 2016.05.21:1924)
  /Title <feff2603> % UTF-16BE に変換済
  /Producer (xdvipdfmx \(20150315\))/CreationDate(D:20160521192429+09'00')
>>
endobj

もちろん、“UTF-16BE に”変換しているので、BMP 外の文字があっても大丈夫……。

% plain XeTeX 文書, 文字コードUTF-8
\special{pdf:minorversion 4}
\special{pdf:docinfo << /Title (🍣) >>}% U+1F363 SUSHI
\nopagenumbers \null \bye
2 0 obj
<<
  /Creator ( XeTeX output 2016.05.21:1929)
  /Title <feffdf63d83c>
  /Producer (xdvipdfmx \(20150315\))/CreationDate(D:20160521192940+09'00')
>>
endobj

……アレ?

/Title <feffdf63d83c> % UTF-16BE…?

アレアレ??

df63d83c

違う! これだとサロゲートペアの値の順番が逆!

そういうわけで、この文書の Adobe Reader で開いて文書情報を見てもタイトルの🍣は正常に表示されない。

当該の部分のソース(spc_pdfm.c の 500 行目付近)を見てみると……あれまあ。

    if (usv > 0xFFFF) {
      /* supplementary-plane character: generate high surrogate */
      unsigned long hi = 0xdc00 + (usv - 0x10000) % 0x0400;   /*←これは low surrogate!*/
      if (op > wbuf + WBUF_SIZE - 2)
        return -1; /* out of space */
      *op++ = hi / 256;
      *op++ = hi % 256;
      usv = 0xd800 + (usv - 0x10000) / 0x0400;                /*←これは high surrogate!*/
      /* remaining value in usv is the low surrogate */
    }
    if (op > wbuf + WBUF_SIZE - 2)
      return -1; /* out of space */
    *op++ = usv / 256;
    *op++ = usv % 256;

なお、このバグについては、r39201 [2015/12/26] においてリファクタリングが行われるのに巻き込まれて(いつの間にか?)直ったらしい。従って、もうすぐリリースされる TeX Live 2016 では正常になっているはずである。

LaTeX では問題なし

ちなみに、このバグの影響範囲であるが。

  • up(La)TeX + dvipdfmx で UTF-8 → UTF-16BE の文字コード変換を行う場合は「pdf:tounicode UTF8-UTF16」の special 実行が必須であり、この場合は ToUnicode CMap の適用の処理が行われる。
  • XeLaTeX で hyperref パッケージを用いる場合は、hyperref 自体が(TeX 言語で)UTF-8 → UTF-16BE の変換を 行うので、xdvipdfmx の変換処理は使われない。

そういうわけで、LaTeX の範囲においてはこのバグを踏むことはほぼ無いといっていいだろう。

*1:pdf:tounicode special が指定されない場合。

*2:見やすさのため整形して示している。