LuaLaTeXで簡単日中混植

この記事はTUT Advent Calendar 2019 13日目の記事です。 Advent Calendarがスカスカだと適当な日付を指定して記事を投げ込めるというのはとてもいいことですね。 よくはないが。 ちなみに 2015年から投稿しているので5年連続です。控えろ控えろ

皆さんはLaTeXを使っていますか? もちろん、理工系の大学に通っているみなさんは、レポートに論文にとLaTeXが大活躍していることと思います。

そんなLaTeX処理系の一つであるLuaLaTeXでは、従来のLaTeX処理系と異なって、フォントファイルの実態を取り扱えるようになっています *1

この事によって、従来のLaTeX文書では考えられなかった、複数のフォントファイルを用いた文章を極めて簡単に作成することができるようになっているので、 今回はその紹介として日本語フォントと中国語(簡体字)フォントの混植を実現する方法を取り上げます。 とても簡単ですよ!

(2019.12.17 追記) 具体的には、日本語文書内で簡体字が必要となった時に、適切な簡体字を出すための方法についてです。 書いているときは、この意味で十分伝わると思いこんでいましたが、あらゆるフォントが簡体字字形になったり、 あるいは簡体字であることが文中で明記されていない場合にも簡体字になるかのような曖昧性を抱えていたので、注記しておきます。

ちなみにこの記事は私も参加しているサークル『おるみん党』の冬のコミックマーケット宣伝のために執筆されています。 ここで言及したテクニックも登場する、おるみん党の機関誌『測点』Vol.2は冬のコミックマーケット(C97)4日目に南リー31bで頒布されます。 読書好きの皆さんに向けた叢書管理ツールEnju Leafを使った書誌情報管理や、Web Assemblyの紹介、中国メーカーから販売されているRISC-Vプロセッサ採用ボードの調査記録などの記事を取り揃えてお待ちしています。 頒布価格は500円。お誕生日席に配置されたので、かなりわかりやすいと思います。皆さん、冬の有明南展示場で会いましょう。

用意するもの

まずTeX Liveなどを使って、LuaTeXをインストールしてください。 今回のテストではTeX Live 2019にバンドルされているLuaTeX v1.11.2を使っています。

LuaTeX上でCJKフォントを扱う手法として、luatexjaチームが開発しているパッケージ群が利用できます。

とりあえず次のようなファイルを用意して、LuaTeXで正しくコンパイルできることを確認しましょう

\documentclass{ltjsarticle}
\usepackage{luatex85, lautexja}
\usepackage{bxjalipsum}

\begin{document}
\jalipsum{kusamakura}
\end{document}

正しくコンパイルできれば草枕の冒頭が書かれたPDFが生成されるはずです。 LuaTeXのコンパイルを初めて行うときは、フォントデータベース生成のためにコンパイルに時間がかかる点に気をつけてください。

フォントを取り扱う

次にシステムにインストールされているフォントを明示的に取り扱ってみます。 TeX Liveをインストールすると日本語標準フォントとしてIPAexフォントがバンドルされているので、 これを指定してPDFファイルを生成してみます。

\documentclass{ltjsarticle}
\usepackage{luatex85, lautexja}
\usepackage[ipaex]{luatexja-preset} % この行を追加
\usepackage{bxjalipsum}

\begin{document}
\jalipsum{kusamakura}
\end{document}

luatexja-presetパッケージによって、一般的なフォントであれば簡単にPDFに埋め込むことができます。

再度文書をコンパイルすれば、IPAexフォントが埋め込まれたPDFが生成されることでしょう。

簡単日中混植

それでは本題の日本語+中国語(簡体字)混植を試してみましょう。 luatexjaパッケージはluatexja-fontspecというパッケージを提供しています。 これはfontspecパッケージ(())をCJK向けに拡張したパッケージで、CJK向けに便利な機能がいくつか追加されています。 中でも便利なのがAltFontと呼ばれるフォント機能で、これを利用することで簡単に複数のフォントを切り替えて使うことができます。 例えば、公式ドキュメントからサンプルを引っ張ってくると

\jfontspec[
    AltFont={
       {Range="4E00-"67EF, Font=KozGoPr6N-Medium} ,
       {Range="6800-"9EFF, FakeBold=4},
       {Range="3040-"306F, Font=KozGoPr6N-Regular}
    }
][KozMinPr6N-Regular]

などとすれば、簡単に混植が実現できます。 この例だと、基本的には小塚明朝 Pr6Nを使いますが、Unicodeの文字範囲U+3040~U+306fでは小塚ゴシック Pr6N Regularを U+4E00からU+67EFの文字範囲では小塚ゴシック Pr6N MediumをU+6800からU+9EFFの文字範囲では小塚明朝を擬似ボールド体にして利用しています。

というわけで、これを真似すれば簡単に日本語と簡体字の混植ができそうです。 詳細について話すまでもなかったですね。というわけにはいかないのが現実です。

CJK統合漢字の罠

では次のようなTeXソースを用意してコンパイルしてみましょう。 ここでは、Windows環境を想定して、簡体字フォントにSimSunを使う例です。 お手持ちの環境に合わせて簡体字フォント部分を入れ替えてください。

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[ipaex]{luatexja-preset}

\begin{document}
{
\jfontspec[
    AltFont={
       {Range="4E00-"9FEF, Font=SimSun}, % Unicode CJK 統合漢字面をすべて簡体字に置き換える
    }
]{IPAexMincho}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
}
\end{document}

ここでは「简」「现」「采」「从」「汉」の5字が、簡体字字形として表示されることが期待される文字です。 他の文字は、和文字形として表示されていて、この部分だけ簡体字になってくれていれば、目的を達したと言えます。

コンパイルに成功するとブラウザ表示で簡体字になっている部分が、豆腐にならずに正しく簡体字字体で表示されていることがわかるでしょう。 例えばこんな感じです。

f:id:akahana_1:20191215185553j:plain

ところで問題は、簡体字で書かれていない箇所においても、字形が簡体字相当になっている問題です。 これはCJK統合漢字面全体を簡体字字形を利用したフォントに置き換えているからです。 では、簡体字部分だけに置き換え範囲を限定してすればよいというのが直感的ですが、ここに一つ問題があります。 というのも、簡体字が割り当てられているコードポイントは、UnicodeのCJK統合漢字面の上に広くまたがっており、特定の範囲を指定することで解決する問題ではないからです。 このあたりは明らかにUnicodeの不具合では?という気持ちになるのですが、規格として制定されているのであれば仕方がないので、なんとかしてこれを解決しなければなりません。

文字種を限定した解決策

CJK統合漢字面全体にまたがって、簡体字字形のものと和文字形のものが存在しているということは、文字範囲の指定という統一的な枠組みで二つの字形を混植することは難しく、都度都度アノテーションを行っていくしかないという結論になります。 というわけで解決策として取りうる方法の一つは AltFontのRangeキーに対応する値として字形を変更したい対象を列挙する となります。

先ほどの文書であれば

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[ipaex]{luatexja-preset}

\begin{document}
{
\jfontspec[
    AltFont={
       {Range={`简, `现, `从, `汉}, Font=SimSun}, % 簡体字で表示したい字形を列挙する
    }
]{IPAexMincho}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
}
\end{document}

f:id:akahana_1:20191215185728j:plain

これで簡体字で表示したい漢字のみが簡体字字形で、その他の漢字は和文字形で表示されるようになりました。 このように、和文字形と簡体字あるいは繁体字字形をLuaTeX上で混植させるには、多少気にしなればならないことがあるという紹介でした。

おまけ

ところでSource Han Sans CJKみたいにCJK多言語対応しているフォントを使えばいいのでは?と思われた人はいないでしょうか。 おそらく一番正しい解決法はそれです。 確認するためにluatexja-presetsourcehanオプションを指定して、コンパイルしてみましょう。

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[sourcehan]{luatexja-preset}

\begin{document}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
\end{document}

思った通りの出力になりましたね。というわけで、和文簡体字で異なるフォントを使いたいという希望がなければ、これが最も簡単な解決法です。

f:id:akahana_1:20191215185808j:plain

というわけで、このように和文中において特定の文字において簡体字を指定せざるを得ない状況が発生したときは

  1. Source Han CJKのような基本字形として和文字形を採用し、その他に簡体字のみの文字コードに対して正しく字形が存在してるフォントを使う
  2. luatexja-fontspecが提供するAltFontオプションを利用して、簡体字文字コード部分を対応する適切なフォントに置き換える

の選択肢を取ることが出来ます。

*1:今までのLaTeXはフォントファイルをそのまま取り扱っていませんでした