LaTeX で日本語組版をやろうとすると、最初に決めなければならないのは「どの経路を通るか」です。いま生きている道は三本——upLaTeX + dvipdfmx、LuaLaTeX + LuaTeX-ja、XeLaTeX + zxjatype。同じ .tex が三本とも通り、三本とも同じ本文フォントを PDF に埋め込みます。違うのは速さと、使えるパッケージと、事故の起きる場所です。このページでは TeX Live 2024 で実際に三経路をコンパイルして測った数字をもとに、経路と文書クラスの選び方を決め切ります。
日本語 LaTeX の三経路 — 何がどこに置かれているか
三経路の本当の違いは、日本語組版の知識がシステムのどの層に置かれているか です。upLaTeX では知識がエンジンの中にあります——縦組も禁則も文字間のグルーも C で書かれた組版器の一部で、だから速い。LuaLaTeX では知識が Lua のコールバックにあり、LuaTeX が組んだノードの列を LuaTeX-ja が走査して和文の規則を適用します——だから遅く、そのぶん書き換えやすい。XeLaTeX では知識が zxjatype(内部で xeCJK を使う)というマクロパッケージにあり、これは日本語専用というより CJK 全般の仕組みを日本語向けに調整したものです。出力の作り方も違い、upLaTeX だけが DVI を経由して dvipdfmx で PDF にします。残り二つは PDF を直接吐きます。
| 経路 | エンジン | 出力 | 和文フォント |
|---|---|---|---|
uplatex + dvipdfmx | e-upTeX(pTeX 系) | DVI → PDF | TFM/VF 経由。埋め込みは dvipdfmx が担当 |
lualatex + luatexja | LuaTeX | PDF 直接 | OpenType を直接。\setmainjfont で指定 |
xelatex + zxjatype | XeTeX | XDV → PDF(xdvipdfmx) | OS のフォントも可。zxjafont が定番 |
この表の右下に、日本語 TeX の歴史がひとつ隠れています。dvipdfmx は Mark A. Wicks の dvipdfm を多バイト・CID 対応に拡張したもの——つまり日本語のために生まれた道具です。ところが XeTeX が自分の出力段としてこれを採用し、xdvipdfmx になりました。TeX Live 2024 の実際のインストールを見ると、dvipdfmx は xdvipdfmx への シンボリックリンク です。日本語の都合で作られた変換器が、いまや日本語と無関係な XeTeX 文書すべての最終工程を担っている、というわけです。
どれくらい速さが違うのか — 同じ原稿を三経路で測る
同じ 10 ページの和文原稿を TeX Live 2024 でコンパイルすると、uplatex + dvipdfmx が 0.31 秒、lualatex(ltjsarticle)が 0.59 秒、xelatex(bxjsarticle + zxjatype)が 0.74 秒 でした。おおむね 1 : 1.9 : 2.4 で、この比は 1 ページでもほぼ同じです——差の大半は起動と組版そのものであって、原稿の長さではありません。0.3 秒と 0.6 秒の差は一回なら誰も気にしませんが、latexmk -pvc で保存のたびに走らせる書き方をしていると、体感として効いてきます。逆に言えば、それが pLaTeX 経路が二十年以上たっても消えない理由でもあります。生成された PDF はどれも同じ Harano Aji Mincho をサブセット埋め込みしており、pdftotext で本文を取り出すと三つとも正しい日本語が返ってきます。つまり「速い経路は品質が低い」ということはありません。
# route 1 -- fastest; DVI in between
uplatex main.tex && dvipdfmx main.dvi
ptex2pdf -l -u main # the same two steps in one command
# route 2 -- LuaTeX-ja, PDF straight out
lualatex main.tex
# route 3 -- XeTeX via zxjatype
xelatex main.tex文書クラスの選び方 — jsclasses・jlreq・ltjsclasses・bxjscls
経路を決めたら、対応する文書クラスはほぼ自動的に決まります。upLaTeX なら jsarticle(jsclasses)か jlreq、LuaLaTeX なら ltjsarticle(ltjsclasses)か jlreq、XeLaTeX なら bxjsarticle(bxjscls)。ただし例外がひとつ——jlreq は pLaTeX・upLaTeX・LuaLaTeX の三つに対応しますが、XeLaTeX には対応しません。実際に xelatex で \documentclass{jlreq} を通すと ! Undefined control sequence. が出て、そのまま ! LaTeX Error: Missing \begin{document}. まで転がり落ちます。「クラスを固定しておけばエンジンを乗り換えられる」というのは正しいのですが、その乗り換え先に XeLaTeX は含まれません。
| クラス | 通るエンジン | 素性 |
|---|---|---|
jsarticle | pLaTeX / upLaTeX | 奥村晴彦氏の jsclasses(書籍は jsbook)。事実上の標準で、既存資産が最も多い |
jlreq | pLaTeX / upLaTeX / LuaLaTeX | W3C の JLReq に沿った設計。縦組は tate オプション一つ |
ltjsarticle | LuaLaTeX のみ | jsclasses を LuaTeX-ja へ移植したもの。移行の互換性が高い |
bxjsarticle | pdfLaTeX / XeLaTeX / LuaLaTeX / (u)pLaTeX | bxjscls。エンジンをまたぐ薄い共通層で、XeLaTeX 経路の入口 |
クラス選びで一度は驚かされるのが、同じ 10pt が同じ大きさを意味しない ことです。jsarticle を 10pt で組んで漢字一文字の幅を測ると 9.24683pt しかありません。クラスファイルに \def\Cjascale{0.924690} と書かれていて、和文フォントを欧文の 0.924690 倍で読み込んでいるからです。同じことを jlreq でやると、漢字はきっかり 10pt。つまり jsarticle から jlreq にクラスを差し替えると、行長も一行の字数も版面も変わります。移行するときは「同じ設定のまま比べる」のではなく、版面を組み直すつもりでいてください。
% route 1: uplatex main.tex && dvipdfmx main.dvi
\documentclass[uplatex,dvipdfmx]{jsarticle}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}% route 2: lualatex main.tex
\documentclass{ltjsarticle}
\usepackage{luatexja-fontspec}
\setmainjfont{Harano Aji Mincho}
\setsansjfont{Harano Aji Gothic}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}pLaTeX 経路で使えなくなるパッケージ — fontspec・unicode-math・microtype
速い代わりに、pLaTeX 経路では OpenType を前提とする現代のパッケージ群がまとめて使えません。\usepackage{fontspec} は ! Fatal Package fontspec Error: The fontspec package requires either XeTeX or (続いて LuaTeX)で止まり、unicode-math は ! Package unicode-math Error: Cannot be run with uptex! を出します。厄介なのは microtype で、これは エラーにならず、ログに Package microtype Warning: You don't seem to be using pdftex, luatex or xetex. と出したまま黙って何もしません。読み込んだのに効いていない、という一番気づきにくい壊れ方です。逆に graphicx・hyperref・tikz はドライバさえ合っていれば普通に動くので、「昔のパッケージしか使えない」という話ではありません。境界は OpenType とマイクロタイポグラフィのところに引かれています。
しおりが文字化けする — hyperref と pxjahyper
(u)pLaTeX + hyperref で日本語の見出しを書くと、PDF のしおり(ブックマーク)だけが文字化けします。本文は正しいのに、目次パネルの文字が崩れる。原因は、hyperref が見出しの UTF-8 バイト列をそのまま UTF-16BE に流し込んでしまうことです。実際に生成される .out を覗くと \376\377\000\346\000\227\000\245… のように、1 バイトごとにヌルが挟まった列になっています。\usepackage{pxjahyper} を足すと同じ見出しが \376\377\145\345\147\054\212\236…——0x65E5 0x672C 0x8A9E すなわち「日本語」——になります。(u)pLaTeX で hyperref を使うなら pxjahyper はほぼ必須 と覚えてください。LuaLaTeX + LuaTeX-ja では素の hyperref だけで正しい UTF-16BE が出るので、この一手間は要りません。
% (u)pLaTeX: load pxjahyper AFTER hyperref, or the outline panel is garbage
\documentclass[uplatex,dvipdfmx]{jsarticle}
\usepackage{hyperref}
\usepackage{pxjahyper}
\begin{document}
\section{日本語の見出し}
本文。
\end{document}結局どれを選ぶか
新しく書き始めるなら LuaLaTeX + LuaTeX-ja(ltjsarticle か jlreq)を選んでください。0.3 秒ぶんの遅さと引き換えに、Unicode がそのまま通り、OS のフォントが使え、fontspec も unicode-math も microtype も動き、しおりも黙って正しく出ます。既存の卒論テンプレートや学会のスタイルファイルが jsclasses 前提で配られている場合、あるいはビルド時間が本当に効く反復作業なら、upLaTeX + dvipdfmx のままでかまいません——古い道ではなく、いまも最速の道です。XeLaTeX + zxjatype を選ぶのは、すでに XeLaTeX の資産があってそこに日本語を足したいときで、日本語だけのために新規に選ぶ理由はあまりありません。無印の platex を新規に選ぶ理由はもう無く、uplatex にしておけば扱える文字の範囲が広がります(この違いは「文字コードと改行」で扱います)。
- 新規・研究室の縛りなし →
lualatex+ltjsarticle(またはjlreq)。Unicode・OS フォント・microtypeが全部使える。 - 既存テンプレートが
jsclasses前提/ビルドが速い方がいい →uplatex+dvipdfmx。ptex2pdf -l -uで 1 コマンドにできる。 - すでに XeLaTeX の文書がある →
bxjsarticle+zxjatype+zxjafont。jlreqは XeLaTeX では動かない。 - (u)pLaTeX で
hyperrefを使うならpxjahyperを必ず読み込む。 しおりだけが化けるという症状はほぼこれ。 microtypeは (u)pLaTeX では警告だけ出して無効。 効かせたいなら Lua か Xe の経路へ。