TeXでつくるプロポーショナル組日本語文書

More than 1 year has passed since last update.


これは「TeX & LaTeX Advent Caleandar 2017」の1日目の記事です。

(2日目は ワトソン さん です。)


今年も無事に「TeX & LaTeX Advent Calendar」が始まりました。今年の重点テーマは「TeXでつくるアレ」、ということで、「LuaLaTeXでつくる日本語プロポーショナル組文書」の話をします。


例によって前口上

(例によってTL;DR


LuaLaTeXって何?

簡単にいうと、「スゴイLaTeXエンジン」です。次のような特長をもちます。


  • Unicodeにネイティブに1対応。

  • 任意のOpenTypeフォント2を直接3扱える。

  • OpenTypeの高度なレイアウト機能(字体切替など)を利用できる。

  • Lua言語スクリプトでLaTeX(やTeX)を制御可能。

LuaLaTeXはそれ自身は日本語組版に対応していませんが、日本語組版の機能を提供する「LuaTeX-ja」というパッケージが開発されていて、これを組み合わせると「スゴイ日本語LaTeX環境」ができあがります。


  • LaTeX史上最高の和文組版品質を実現。

  • 前述の「LuaLaTeXのスゴイ機能」はもちろん和文にも適用できる。

LuaTeXエンジンは長らくベータ版の状態4でしたが、2016年9月についに正式版である“バージョン1.0”がリリースされました(TeX Live 2017に収録)。最新のTeX配布においては、スゴイLuaLaTeXを実用で使う準備は既にできあがっているのです。


(u)pLaTeXでのプロポーショナル組

実をいうと、(u)pLaTeXでもプロポーショナル組はできないわけではありません。(u)pLaTeXを利用したプロポーショナル組は実際に行われていて、出版物でも使われています。しかし、(u)pLaTeXでのプロポーショナル組が一般のユーザにとって“使える”機能になっていないのも事実です5

これに対して、スゴイLuaLaTeXでは、普通のLaTeXユーザでも比較的容易にプロポーショナル組が実現できます。日本語LaTeXでプロポーショナル組を使いたいという人は、スゴイLuaLaTeXの使用を検討する価値は大いにあるでしょう。

※なお本記事では「どんな場合に日本語プロポーショナル組を使うべきか?」という議論については一切立ち入らないことにします。


前提知識



  • LuaLaTeX+LuaTeX-jaによる日本語文書作成のキホン的な知識(えっ)

    この記事は特定の話題(プロポーショナル組)に関するものなので、それ以外の一般的な日本語LuaLaTeXに関する解説は敢えて避けています。残念ながら、現在は日本語LuaLaTeXの一通りのキホンについて学習できる手頃な文献が存在しませんが、取りあえずTeX Wikiの入門記事の程度の最初歩の内容を身につけていれば、この記事の内容の追試はできるでしょう。




まずは普通に全角組(源真ゴシック)

プロポーショナル組の話に入る前に、LuaLaTeX+LuaTeX-jaで「自由にフォントを指定する」方法を練習(復習)しておくとよいでしょう。そこで、まずは「源真ゴシック」を指定して普通に全角組の文書を作ってみます。


フォントファイルの導入

「源真ゴシック Regular」のフォントファイル GenShinGothic-Regular.ttf をTeXで使えるように配置します。

※フォントファイルの導入方法はどのフォントでも同じなので、以降では導入の話は省略します。


普通にLaTeX文書を作る

フォントファイルの準備ができたら、早速「源真ゴシック」を指定したLaTeX文書を作りましょう。


test-genshin.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% 既定の欧文フォントを"源真ゴシック Regular"にする
\setmainfont{Gen Shin Gothic Regular}
% 既定の和文フォントを"源真ゴシック Regular"にする
\setmainjfont{Gen Shin Gothic Regular}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。

そしたらなんか人がめちゃくちゃいっぱいで座れないんです。
で、よく見たらなんか垂れ幕下がってて、150円引き、とか書いてあるんです。

もうね、アホかと。馬鹿かと。
お前らな、150円引き如きで普段来てない吉野家に来てんじゃねーよ、ボケが。
150円だよ、150円。
なんか親子連れとかもいるし。
一家4人で吉野家か。おめでてーな。
よーしパパ特盛頼んじゃうぞー、とか言ってるの。もう見てらんない。
お前らな、150円やるからその席空けろと。

\end{document}


(サンプルの文章は「吉野家コピペ」です。)

日本語LuaLaTeX文書において使用するフォントを指定するにはluatexja-fontspecパッケージを利用します。このパッケージの使用法の説明はこの記事の目的ではないので省略しますが、取りあえず以下の点だけ知っておいてください6



  • \setmainfont命令で、その文書の既定の欧文フォントを指定する。


  • \setmainjfont命令で、その文書の既定の和文フォントを指定する。

このLaTeX文書をlualatexコマンドでコンパイルすると、以下のような出力が得られます。

test-genshin.png

これは「いつもの日本語LaTeXを組み方」ですね7


単純なOpenTypeフォントでプロポーショナル組(源真ゴシックP)

それでは、いよいよプロポーショナル組を始めましょう。まずは、源真ゴシックのプロポーショナル版である「源真ゴシックP」を利用することにします。これは、「既定のグリフがプロポーショナル」である“単純な”OpenTypeフォントです。

「源真ゴシックP Regular」のフォントファイル8 GenShinGothic-P-Regular.ttf を先ほどと同じ手順で配置します。


うまくいかない例

先ほどの例では\setmain(j)fontにフォント名を指定するだけで全てうまくいきました。今回も同じようにしてみましょう。


test-genshinp-1.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% フォントを"源真ゴシックP Regular"に変えた
\setmainfont{Gen Shin Gothic P Regular}
\setmainjfont{Gen Shin Gothic P Regular}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-genshinp-1.png

アレアレ、ひらがなの組み方が何か気持ち悪くなっただけで、全然プロポーショナルっぽくなっていません。よく見ると、先ほどの全角組の例と改行位置が全く同じです。つまり、今回も和文文字は「全角幅で」組まれてしまったようです。


和文フォントメトリック(JFM)

先の失敗の原因は、LuaTeX-jaの和文フォントメトリック(JFM)にあります。JFMとは簡単にいうと「和文の“組み方”のパラメタのセット」のことです。\setmainjfontで和文のフォントを指定する際には付随してJFMが指定されるのですが、そのJFMの既定値(横組はujis、縦組はujisv)は「全角組用」のものになっています。そのため、プロポーショナル幅のグリフの「源真ゴシックP」を指定した時も、それで無理やり全角組をしようとしたために奇妙な組み方になってしまったわけです。


うまくいく例

幸いなことに、LuaTeX-jaではプロポーショナルのフォントに適したpropという名前のJFM(横組用)を提供しているので、これを利用することにしましょう。次のように、和文用の\setmainjfontの方のオプションにJFM=propを指定します9


test-genshinp-2.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% フォントは"源真ゴシックP Regular"
\setmainfont{Gen Shin Gothic P Regular}
\setmainjfont[
YokoFeatures={JFM=prop}, %JFMを指定する
]{Gen Shin Gothic P Regular}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-genshinp-2.png

プロポーショナル組になりました! 案外簡単でしたね。


チョット調整してみる

先の出力では、「150円」のように欧文と和文が隣接する箇所に入る空き(和欧文間空白)の量が0.25zw(四分)となっています。これは全角組をする場合の標準的な値ですが、プロポーショナル組においては大きすぎると感じられるかもしれません。

BXJSクラス(bxjsarticleクラスなど)の場合10\setxkanjiskipという命令で和欧文間空白の量を設定できます。下記の例では、この値を0.1zw(全角の10%)としています。


test-genshinp-3.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% フォントは"源真ゴシックP Regular"
\setmainfont{Gen Shin Gothic P Regular}
\setmainjfont[
YokoFeatures={JFM=prop}, %JFMを指定する
]{Gen Shin Gothic P Regular}
% 和欧文間空白を調整する
\setxkanjiskip{0.1\zw minus 0.1\zw}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-genshinp-3.png

※和文全角幅の単位zwはLuaLaTeXでは\zwと書く必要があります。


Proportionalでプロポーショナル組(游明朝)

「源真ゴシックP」は“単純にプロポーショナル幅のグリフをもつ”フォントでしたので、単純にJFM=propを指定するだけでした。しかし、特に高級なフォントの場合は、「一つのフォントで全角幅とプロポーショナル幅の両方のグリフをもち、OpenTypeのレイアウト設定でどちらを使うかを指定する」という仕組になっているものもあります。例として、商用フォントの「游明朝」を使ってプロポーショナル組をしてみます。


OSバンドルの游明朝を使う方法

Windows(8.1/10)やmacOSにバンドルされた游明朝のフォントをLuaLaTeXで利用する場合の手順です。


  • Windowsの場合は最初から使える状態になっています。



  • macOSでTeX Live系(MacTeXも含む)の場合は以下の手順に従います11



    1. Kpathsea変数OSFONTDIRが未設定(またはダミー値/please/set/osfontdir/in/the/environment)であることを確認します。

      ※既に有意義な値が入っている場合はここで示した手順は使えません。

      $ kpsewhich -var-value=OSFONTDIR
      
      /please/set/osfontdir/in/the/environment



    2. Kpathsea変数OSFONTDIRを設定します。

      $ tlmgr conf texmf OSFONTDIR '/System/Library/Assets//'
      



    3. LuaTeXのフォントデータベースを更新します。

      $ luaotfload-tool -u -f
      





普通に游明朝を使う

まずは試しに「Yu Mincho Regular」(Windows)/「YuMincho Medium」(macOS)を普通に指定した文書をコンパイルしてみましょう。


test-yumincho-1.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
%%------------------------------ Windowsの場合
% フォント名は"Yu Mincho Regular"
\setmainfont{Yu Mincho Regular}
\setmainjfont{Yu Mincho Regular}
%%------------------------------ macOSの場合
% フォント名は"YuMincho Medium"
%\setmainfont{YuMincho Medium}
%\setmainjfont{YuMincho Medium}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-yumincho-1.png

この通り、全角組で普通に(“気持ち悪く”ならずに)組めています。つまり「游明朝」の既定の和文文字は全角幅であることが判ります。


プロポーショナル幅を指定する

「游明朝」でプロポーショナル幅の和文文字に切り替えるには、\setmainjfontのオプションにCharacterWidth=Proportionalを指定します。それに加えて、以下の指定を行うことにします。


  • 文字の組み方を変更するために、JFM=prop

  • 和文のカーニングを有効にするために、Kerning=On

    \setmainjfontでは既定でKerning=Offが指定されている。


  • \setmainjfontでは既定でScript=CJKが指定されるが、(少なくとも「游明朝」では)これではカーニングが適用されないので、Script=Defaultを指定する。


test-yumincho-2.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
%%------------------------------ Windowsの場合
% フォント名は"Yu Mincho Regular"
\setmainfont{Yu Mincho Regular}
\setmainjfont[
Script=Default,
YokoFeatures={JFM=prop},
CharacterWidth=Proportional,
Kerning=On,
]{Yu Mincho Regular}
%%------------------------------ macOSの場合
% フォント名は"YuMincho Medium"
%\setmainfont{YuMincho Medium}
%\setmainjfont[
% Script=Default,
% YokoFeatures={JFM=prop},
% CharacterWidth=Proportional,
% Kerning=On,
%]{YuMincho Medium}
%
% 和欧文間空白を調整する
\setxkanjiskip{0.1\zw minus 0.1\zw}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-yumincho-2.png

プロポーショナル組になったようです。ただし、プロポーショナル幅になっているのは仮名文字だけで、句読点は全角幅のままです。(CharacterWidth=Proportional指定の場合はこうなるのが普通のようです。)


なぜカーニングか

先ほどの例では和文のカーニングを有効にしました。これはプロポーショナル組をする場合にはその方が望ましいためです。

genome.png

実は、和文の組版においてカーニングができるというのはLuaLaTeX+LuaTeX-jaのもつ大きな特長です。(u)pLaTeXおよびXeLaTeX+xeCJKによる和文組版の場合、プロポーショナル組はできたとしても、カーニングを活かすことが原理的にできないのです。


AlternateProportionalでプロポーショナル組(源ノ明朝)

「全角幅とプロポーショナル幅をOpenTypeのレイアウト設定で切り替える」フォントのもう一つの例として、「源ノ明朝(Source Han Serif)」を使ってプロポーショナル組を行ってみます。(結論からいうと、これは現状ではあまりうまくいきません。)

「源ノ明朝 Regular」(SourceHanSerif-Regular.otf または SourceHanSerif-Regular.ttc)を配置します。


ProportionalかAlternateProportionalか

OpenTypeフォントでのプロポーショナル組を指定には次の2つの方式があります。



  1. CharacterWidth=Proportional: グリフ自体をプロポーショナル幅のものに置き換える方式(pwidフィーチャ)


  2. CharacterWidth=AlternateProportional: グリフ自体は変えずに“組み方”を変える方式(paltフィーチャ)

そしてフォントによってサポートされている方式が異なります。「游明朝」は両方の方式に対応しているのですが、「源ノ明朝」では後者のAlternateProportionalの方式にしか対応していません。従って、「源ノ明朝」でプロポーショナル組をするのならば、これを利用するしかありません。


test-genmincho-1.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% フォント名は"Source Han Serif Regular"
\setmainfont{Source Han Serif Regular}
\setmainjfont[
YokoFeatures={JFM=prop},
CharacterWidth=AlternateProportional,
]{Source Han Serif Regular}
% 和欧文間空白を調整する
\setxkanjiskip{0.1\zw minus 0.1\zw}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-genmincho-1.png

一見良さそうな出力が得られました。先の「游明朝でProportional指定」の場合とは異なり、今回は句読点も狭い幅になっています。(AlternateProportional指定の場合はこうなるのが普通のようです。)

しかしそう思ってよく見ると、出力5行目末尾の「…るし。」の部分が奇妙です。ここは改段落ではなく成り行きの改行なので「。」は本文領域の完全に右端にあるべきところが、二分ほどの空きがあります。もし「。」が全角幅ならそれで辻褄が合ってますが、今回は「。」も狭い幅なので矛盾しています。

「吉野家コピペ」の後半部分を同じ設定で組んでみます。

test-genmincho-1a.png

括弧も狭い幅であるため、4行目頭の「(玉子)」の前に空きがあるのも変です。そしてもっと詳しく見ると、行末がきちんと揃っていないことも判ります。つまり、和文の行分割処理に異常をきたしているのです。

この不具合の原因は「LuaTeX自体のAlternateProportionalの処理とLuaTeX-jaの和文処理が衝突している」であり、簡単に解決できそうにないことが解っています。現状ではAlternateProportionalを利用して(つまり「源ノ明朝」を利用して)段落をプロポーショナルで組むのは諦めた方がよさそうです。


それでも使いどころはあるかも

ただしこの不具合は行分割の際に起こるものです。従って、出力が1行しかない場合には全く影響を受けないし、また改行を全て強制改行(\\)で行う場合も不具合の影響を受けません。


test-genmincho-2.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
% フォント名は"Source Han Serif Regular"
\setmainfont{Source Han Serif Regular}
\setmainjfont[
Script=Default,
YokoFeatures={JFM=prop},
CharacterWidth=AlternateProportional,
Kerning=On,
]{Source Han Serif Regular}
% 和欧文間空白を調整する
\setxkanjiskip{0.1\zw minus 0.1\zw}
\begin{document}
\noindent
そしたらなんか人がめちゃくちゃいっぱいで座れないんです。\\
で、よく見たらなんか垂れ幕下がってて、\\
「150円引き」\\
とか書いてあるんです。
\end{document}

test-genmincho-2.png

従って、「本文組は普通に全角組とするが、見出しはプロポーショナル組にする」という場合に限って、見出しテキストの改行を全て強制改行で行うことにすれば、不具合の影響を受けずにAlternateProportionalのプロポーショナル組を実用できるかもしれません。


JFMをカスタマイズする

結局、本文組をプロポーショナルにする場合には、現状ではProportionalを使う選択肢しかないわけですが、句読点が全角幅になるのは少しバランスが悪い気がします。もう少し句読点の右側の空きを小さくできないでしょうか。

このように「空きを自分好みに調整したい」と思うのであれば、もう「自分用のJFMをカスタマイズして作る」しかないでしょう。以下では、LuaTeX-ja標準のpropをチョットだけ改造して自作のJFMmypropを作ってみます。

LuaTeX-jaではJFMはLuaのソースコード(一種のDSL)として表現され、そのファイル名をjfm-<名前>.luaとする規則になっています。propを表すJFMのファイルjfm-prop.luaは次のような非常に簡単なものです。


jfm-prop.lua

luatexja.jfont.define_jfm {

dir = 'yoko',
zw = 1.0, zh = 1.0,

[0] = {
align = 'left', left = 0.0, down = 0.0,
width = 'prop', height = 0.88, depth = 0.12, italic=0.0,
}
}


これを修正して、次のようなファイルjfm-myprop.luaを作ります。これがmypropの定義となります。


jfm-myprop.lua

luatexja.jfont.define_jfm {

dir = 'yoko',
zw = 1.0, zh = 1.0,
[0] = { -- 他の全ての文字は元来の字幅を保持
align = 'left', left = 0.0, down = 0.0,
width = 'prop', height = 0.88, depth = 0.12, italic = 0.0,
},
[1] = { -- <(>は左の空きを削って半角幅
chars = {'('},
-- 0.5zwの幅に右揃えでグリフを配置
align = 'right', left = 0.0, down = 0.0,
width = 0.5, height = 0.88, depth = 0.12, italic = 0.0,
},
[2] = { -- <)>は右の空きを削って半角幅
chars = {')'},
-- 0.5zwの幅に左揃えでグリフを配置
align = 'left', left = 0.0, down = 0.0,
width = 0.5, height = 0.88, depth = 0.12, italic = 0.0,
},
[3] = { -- <、>も半角幅だが右側に若干伸縮空きを入れる
chars = {'、'},
align = 'left', left = 0.0, down = 0.0,
width = 0.5, height = 0.88, depth = 0.12, italic = 0.0,
glue = {
[0] = { 0.2, 0.0, 0.2 }, -- 直後が"その他"か<(>の場合
[1] = { 0.2, 0.0, 0.2 }, -- 0.2zw plus 0.0zw minus 0.2zw
} -- を挿入する
},
[4] = { -- <。>も半角幅だが右側に若干伸縮空きを入れる
chars = {'。'},
align = 'left', left = 0.0, down = 0.0,
width = 0.5, height = 0.88, depth = 0.12, italic = 0.0,
glue = {
[0] = { 0.2, 0.1, 0.0 },
[1] = { 0.2, 0.1, 0.0 },
}
},
}

それでは早速今作ったJFMmypropを適用して游明朝で組んでみましょう。


test-yumincho-3.tex

% LuaLaTeX文書; UTF-8

\documentclass[lualatex,a5paper,ja=standard]{bxjsarticle}
\usepackage{luatexja-fontspec}
%%------------------------------ Windowsの場合
\setmainfont{Yu Mincho Regular}
\setmainjfont[
Script=Default,
YokoFeatures={JFM=myprop}, % カスタムのJFMを指定する
CharacterWidth=Proportional,
Kerning=On,
]{Yu Mincho Regular}
%%------------------------------ macOSの場合
%...(省略)
% 和欧文間空白を調整する
\setxkanjiskip{0.1\zw minus 0.1\zw}
\begin{document}

昨日、近所の吉野家行ったんです。吉野家。
%……以下省略


test-yumincho-3a.png

自分好みになってますね!


LuaLaTeXのフォント指定は自由自在

LuaLaTeXを使うと和文のプロポーショナル組が容易に実現できることを見てきました。LuaLaTeXのフォントの扱いはかなり自由度が高いため、従来のLaTeXでは面倒な準備作業が必要だった複雑なフォント設定が、“文書中の設定”として簡単に実現できます。いくつかの実用例を挙げておきます。


まとめ

スゴイLuaLaTeXでスゴイ日本語文書をつくろう!





  1. 「ネイティブ」とは入出力だけでなく内部処理も(バイト単位やレガシー文字コードでなく)Unicodeで行うことを指します。 



  2. 本記事では、“CFFグリフ”と“TrueTypeグリフ”のOpenTypeフォントの両方を単に「OpenTypeフォント」と呼びます。一般的に後者は「TrueTypeフォント」と呼ばれることがあります。 



  3. 従来のLaTeX(pdfLaTeXや(u)pLaTeXも含む)では、新しいフォントを導入する際に、それに呼応する“論理フォント(TFM)”のデータファイルを作成する必要がありました。そして、特に和文フォントの場合はその作成が手順が確立されていないため、一般のユーザが新しいフォントを導入することは非常に困難でした。 



  4. この時期には後方非互換な仕様変更が割と頻繁に行われ、これがLuaLaTeXを実用で使う上での大きな障害になっていました。 



  5. 一般のLaTeXユーザが使えるパッケージ機能としては、japanese-otfパッケージでヒラギノフォントを使っている場合に\propshape命令でプロポーショナル組ができる、というものがあります。 



  6. \setmainfontはセリフの総称ファミリ(\rmfamily)、\setmainjfontは明朝の総称ファミリ(\mcfamily)に対応するものであるため、サンセリフ・ゴシック系のフォントを“既定”にする場合は、それを\setmain(j)fontで指定するのではなく、\setsans(j)fontで一旦指定してから\(kanji)familydefaultの再定義をするのが正統な方法かもしれません。しかし本記事では“横着をして”全て\setmain(j)fontで指定することにします。 



  7. 「源真ゴシック」は和文文字は全角の等幅ですが、欧文文字(英数字など)は全角でも半角でもなくプロポーショナル幅です。先の出力をよく見ると、欧文数字「150」が半角幅でなくプロポーショナルであることが判ります。もちろん、日本語LaTeXではそれが普通です。 



  8. 「源真ゴシックP」のフォントファイルは「源真ゴシック」のアーカイブに一緒に含まれてます。 



  9. \setmainjfontの設定内容(オプションを含む)は通常は横組・縦組の両方のフォントに適用されます。ところが、propは横組用のJFMであり縦組では指定できないため、「横組のときにのみ適用する」ことを表すために、JFM=propYokoFeatures={...}で囲ってしてします。 



  10. \setxkanjiskip命令はBXJSクラスに特有のものです。jsclassesバンドルのクラス(jsarticleなど)、およびそのLuaTeX-ja版互換クラス(ltjsarticleなど)では大域的に和欧文間空白の量を設定する方法は用意されていません。 



  11. もしかしたら、ここで挙げた設定は「(u)pLaTeXでmacOS付属のフォントを使うための設定」と相性が悪いかもしれません。元に戻したい場合は、「tlmgr conf texmf --delete OSFONTDIR」「luaotfload-tool -u -f」を実行します。