HOME

XeTeX メモ (XeLaTex ではない)

2015-5-26(Tue)

LaTeX 君は結構勝手に気を利かせてくる。たぶん自分でもはなかなかスマートだと思ってるんじゃないかな。でも時には「僕は論文を書きたいわけじゃないんだ!」って叫びたくなることもある。しかも LaTeX 君は結構頑固で、言うことを聞かせるのにそれなりの行数のマクロを書かなきゃならないこともしばしばだ。僕がちょっと洒落た買い物メモを作ろうとするときに必要なのは、もっと朴訥で、少ない口数でコミュニケーションをとることができる相手だ。

僕は troff 爺さんのところに行ってみた。みんなが思っているよりずっと気さくで愉快な爺さんだった。正直なところ、僕はこの爺さんと仕事をしたいとまで思った。でも、爺さんは日本語が不得意だった。Linux のディストリビューションを変えるたびに、爺さんに日本語を教えなければならないのには、さすがに閉口してしまった。

どんな環境でもほとんど同じに使えて、朴訥で、口数の少ない清書マンを探していた僕は、LaTeX 君が、TeX おじさんのところに指定書を持って行って組版してもらっていることを思い出した。そこで、自分で TeX おじさんのところに原稿を持ち込んでみることにした。

じつのところ、僕が LaTeX 君と呼んでいるのは、正式には XeLaTeX 君だ。そして、XeLaTeX 君は XeTeX おじさんに組版を依頼している。だから、僕が相手にすることにしたのは、正確には XeTeX おじさんだ。

そういうわけで、これは XeTeX おじさんと一緒に仕事をしようと思って作ったメモだ(正直に言うと、作りかけなんだけどね)。Plain TeX にも共通する部分が多いが、そういうこともメモから除外しないつもり。

起動

僕の環境では端末からたんに tex と打つと、自動的に tex.fmt というフォーマット(マクロの集合体)が読み込まれる(これは Plain TeX と称される)。それと同じように、僕の環境では端末からたんに xetex と打つと xetex.fmt というフォーマットが読み込まれる。生の XeTeX を使うほど漢(おとこ)じゃないから、このフォーマットファイルは使わせてもらうことにする。

ちなみに、端末からたんに xetex と打つと xetex.fmt が読み込まれるのは、xetex がプログラム名と同じフォーマットファイルを自動的に読み込むからだ。これを避けて生の XeTeX を使うには、(たとえばシンボリックリンクを用いて)xetex に xeinitex という名前をつけて呼び出すか、あるいは、-ini というオプションをつけて起動すればいい。まあ、僕はそこまで漢じゃないから、そんなことはしない。

XeTeX はフォントにまつわること以外は TeX とほぼ同じなので、有名な The TeX Book が参考になる(ぐぐってすぐ入手だ!)。また、XeTeX 特有のことについては、「The XeTeX Companion: TeX meets OpenType and Unicode」(http://xml.web.cern.ch/XML/lgc2/xetexmain.pdf)を参考にした。また、http://plain-xetex.neocities.org/index.html というのに実用上の知識がうまくまとめてあるのを見つけた。

Hello World!

まず、ターミナル上で対話的に使ってみる。ターミナルから xetex とだけ打って起動。XeTeX プログラムを起動したいちばん最初だけプロンプトは ** になっている。ここで \relax という特に何もしないコントロール・シーケンス(コマンド)を打ち込むと、プロンプトが * に変わる。プロンプトが * の状態になると、印刷したい文字を受け付ける。文字を打ち終わったら、\end と入力すると、pdf ファイルが作られる。どうだろう、この簡単さときたら。買い物メモを作るのに最適じゃないか。

$ xetex
This is XeTeX, Version 3.1415926-2.5-0.9999.3 (TeX Live 2013/Debian)
 restricted \write18 enabled.
**\relax
entering extended mode
*Hello World!
*\end
[1]
Output written on texput.pdf (1 page).
Transcript written on texput.log.

texput.pdf という pdf ファイルができている(pdf ファイルを生成する前に、中間的な形のものが使われるが、これは通常僕たちの目にふれることはない)。texput という名前はデフォルトの名前。[1] というのは、1ページが出力されたということ。\relax は実際は何もしないが、これを実行するとプロンプトが ** から * に変わり、文字の入力を受け付ける状態になる。

ちなみに、プロンプトが ** のときは、印刷する文字列の代わりに、ファイル名を受け取る。(また、フォーマットファイルを指定して **&xxxxx hello.tex とすると、xxxxx というフォーマットファイルが使われる。これは、ファイルの中に書いてあるフォーマットの指示より優先される)。

Hello World! とだけ書き込んだ hello.tex なるファイルがあるとき、tex を起動してターミナルから

**hello.tex
*\end

とすると(hello.tex は、hello と省略してもよい)、"Hello World!" がそのまま hello.pdf ファイルに出力される。なお、プロンプトが * のときにファイルを読み込むには、\input というコントロール・シーケンス(コマンド)を使えばいい。

コマンドラインから tex を引数つきで起動すると、対話環境においてその引数が与えられたのと同じ効果がある。だから、プロンプトから tex \\rerax と打ち込むと(ひとつ目の \ は二番目の \ をエスケープするため)、いきなりテキストを入力できる状態になる。だから、Hello World は、コマンドラインから xetex \\relax Hello World! \\end と打ち込んでもいい。さらに素敵なことに、echo '\relax Hello World \end' | xetex のように標準入力から読み込んでもよい。

こんにちは世界

Hello World! に成功したら、次は日本語を使ってみたいのが人情だ。

$ echo "\font\mincho='IPA明朝' at 12pt \mincho こんにちは、世界!\end" | xetex

これが、日本語版 Hello World! になる。もちろん、これをファイルに書き込んで、

\font\mincho='IPA明朝' at 12pt
\mincho こんにちは、世界!
\end

のようにして、xetex hello_jp.tex としてもいい。以後、わざわざ長いワンライナーを書くのが嫌だから、入力はファイルに書いて読み込むことにする。

この例で「IPA明朝」というフォント名が指定されている。これは、たとえば僕の Linux では、端末から fc-list コマンドを打ったときに得られるようなフォント名、つまり、OSが認識できるフォント名ならどれでも使える。TeX ではそれができなかったわけで、ここに XeTeX の大きな利点がある。また、XeTeX がフォントのメトリック情報をフォントファイルそのものから取得することも、デザイン上の有利だ。

エスケープが必要な文字

XeTeX は utf-8 での入力するので、ユニコードのさまざまの文字を直接タイプできる。引用符も “…” ‘…’のようなものが直接使える。TeX で用いられた ``...'' という方法は、フォントの宣言のところで mapping=tex-text としておくと引き続き使用できる。

しかし、直接タイプしても出力できない文字もある。\ { } $ # % & _ ^ ~ がそれで、それぞれ、$\backslash$  $\{$  $\}$  \$  \#  \%  \&  \_  \^{}  \~{} のようにすればよい。

でも、ちょっと待て。これだと、普通のテキスト書類を sed なんかの置換でエスケープしてやろうとするとき、問題が起こるじゃないか。普通にやると、\ を置換したときに $ が使われ、$ を置換したときに \ が使われているという事態を乗り切ることができない。この問題を解決するためには、\ か $ を文中で絶対に使われない文字に一度置換する必要がある。たとえば「埋め込まれた改行」を使って、

#!/bin/sed -f
s/\\/\
/g
s/\$/\\$/g
s/{/$\\{$/g
s/}/$\\}$/g
s/#/\\#/g
s/%/\\%/g
s/&/\\&/g
s/_/\\_/g
s/\^/\\^{}/g
s/~/\\~{}/g
s/\n/$\\backslash$/g

などとすればよい。(これを xetexescape.sed と名づけて $ chmod u+x しておくとしよう)

ユニコードのコードポイントを利用することもでき、たとえば \char"5011 のように書けば、みんなが好きな「們」(ものかげからきゅうにとびだしてひとをおどろかせるときにはっするこえ)が出力される。

ちなみに ~(チルダ)を生のまま書くと、普通のスペースのように出力されるが、行をまたがって分割されることがない。これは TeX に同じ。

“引用符”など

僕たちは、TeX の流儀に従って二重引用符について、`` '' と書く癖を持っているわけでだけど(The TeX Book p.3 参照)、XeTeX では、これが二重引用符には変換される保証はない。Unicode には二重引用符“ ”(U+201C, U+201D)があるので、こうした書き方は必要ないということだろう。しかし、古い習慣との互換性を維持したいこともあるし、二重引用符のグリフを持っていないフォントもある。そこで、次のような解決策が用意されている。

\font\mincho='IPA明朝':mapping=tex-text at 12pt
\mincho こんにちは、``世界''!
\end

`` '' が二重引用符に変換されるのは、TeX の低レベルなところで行われていたことであって、マクロで行われているのではないから、この問題を解決するのにはマッピングを変更するという方法によるのだということだ。(http://xml.web.cern.ch/XML/lgc2/xetexmain.pdf の 2.2.5 Font mappings using TECkit 参照)。(ちなみに ` は \lq というマクロによっても入力でき、' は \rq というマクロによっても入力できることは TeX 同様)

もっとも、このようにマッピングで解決するものはそう多くはなく、以下のようなものだけだ。

--  en dash
--- em dash
'   right single quote
''  right double quote
"   right double quote
`   left single quote
``  left double quote
!`  inverted exclam
?`  inverted question

TeX では é (アクセントつき e) を \'e のように書けるが、XeTeX でも同様。ただし、TeX と違って本物の é をテキスト中に書くこともできる。\^e (サーカムフレックスつき) \~e (チルダつき) も同様。

日本語の段落

さて、XeTeX で日本語の文章を打つと、ページの右端で自動的に起こるべき改行をきちんと処理してくれない。単語がスペースで区切ってある英文用の改行規則がデフォルトだからだ。そこで、

\font\mincho='IPA明朝' at 12pt
\XeTeXlinebreaklocale "ja_JP"
\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em
\XeTeXlinebreakpenalty=0
\mincho こんにちは、世界!
\end

と書いておくといい。この呪文については、http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?XeTeX を参照した。

思案

正直なところ、日本語くらいそのまま打ちたいのが本音。右端での自動的な改行なんかもほしい。しかし、それらの設定を毎回買い物メモを作成するときに打ち込むなんて、考えられない。

ここが思案のしどころだ。何らかの形で TeX のマクロを書き、他のファイルに保存して使い回せば解決するのだが、それをやると他の環境で使いにくくなる。マシンを引っ越したときにマクロ集を持参するのを忘れがちだし、XeTeX ファイルを人に渡すときにも不便だ(だれでもマイナーなスタイルシートを使った LaTeX ファイルをもらって困惑したことがあるのではなかろうか)。

こうしたとき、僕は最も原始的な解決方法を選ぶようにしている。標準入力またはファイルから原稿を受け取って、必要な設定を書き加えて標準出力に出すシェルスクリプトを書いておけばいいのだ。$ cat test.txt | myfmt.sh | xetex とか $ myfmt.sh text.txt | xetex などとして使える。

シェルスクリプトを入れたファイルは必ず引っ越しのときに持っていくから、紛失の恐れがないし、他人に XeTeX のファイルを渡すときは、$ myfmt.sh text.txt > text4u.tex なんてやればいい。

と思って作ってみた myfmt.sh の内容は次の通り。

#! /bin/sh
cat << \END
\font\smallm='IPA明朝' at 10pt
\font\m='IPA明朝' at 12pt
\font\middlem='IPA明朝' at 14pt
\font\bigm='IPA明朝' at 20pt
\font\smallg='IPAゴシック' at 10pt
\font\g='IPAゴシック' at 12pt
\font\middleg='IPAゴシック' at 14pt
\font\bigg='IPAゴシック' at 20pt
\baselineskip=20pt
\XeTeXlinebreaklocale "ja_JP"
\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em
\XeTeXlinebreakpenalty=0
\obeylines
\parindent=0pt
\nopagenumbers
\m
END
cat $1
echo "\end"

\obeylines というのは、行末に必ず \par がついていると考えるようにするもの。つまり、改行ひとつで段落を作ることができるようになる(The TeX Book p.94 参照)。これについては、http://tex.stackexchange.com/questions/57318/is-there-a-counterpart-antidote-for-obeylines に面白いコメントが載っている。この種のものをいじるためには、カテゴリーコードという概念が出てくるから、ちょっと The Tex Book を読まないといけないかもしれない。

\parindent=0pt というのは、段落頭字下げ幅をデフォルトで 0pt にするもの。(The Tex Book p.86 )

では、さっそく試してみる。test.txt の内容が次のようになっているとする。(なお、medskip, smallskip, bigskip, centerline, rightline は XeTeX が初めから持っている命令。bigm と middleg は、myfmt.sh で定義した命令。)

原稿は青空文庫( http://www.aozora.gr.jp/cards/000148/files/790.html )からお借りしてきたものです。ありがとう青空さん。

\medskip
\centerline{\bigm 吾輩は猫である}
\smallskip
\rightline{\middleg 夏目漱石}
\bigskip
 吾輩は猫である。名前はまだ無い。
 どこで生まれたか頓と見當がつかぬ。何ても暗薄いじめじめした所でニャー/\泣いて居た事丈は記憶して居る。吾輩はこゝで始めて人間といふものを見た。然もあとで聞くとそれは書生といふ人間で一番獰惡な種族であつたさうだ。此書生といふのは時々我々を捕へて煮て食ふといふ話である。然し其當時は何といふ考もなかつたから別段恐しいとも思はなかつた。但彼の掌に載せられてスーと持ち上げられた時何だかフハフハした感じが有つた許りである。掌の上で少し落ち付いて書生の顏を見たが所謂人間といふものゝ見始であらう。此の時妙なものだと思つた感じが今でも殘つて居る。第一毛を以て裝飾されべき筈の顏がつる/\して丸で藥罐だ。其後猫にも大分逢つたがこんな片輪には一度も出會はした事がない。加之顏の眞中が餘りに突起して居る。そうして其穴の中から時々ぷう/\と烟を吹く。どうも咽せぽくて實に弱つた。是が人間の飮む烟草といふものである事は漸く此頃知つた。
 此書生の掌の裏でしばらくはよい心持に坐つて居つたが、暫くすると非常な速力で運轉し始めた。書生が動くのか自分丈が動くのか分らないが無暗に眼が廻る。胸が惡くなる。到底助からないと思つて居ると、どさりと音がして眼から火が出た。夫迄は記憶して居るがあとは何の事やらいくら考へ出さうとしても分らない。
 ふと氣が付いて見ると書生は居ない。澤山居つた兄弟が一疋も見えぬ。肝心の母親さへ姿を隱して仕舞つた。其上今迄の所とは違つて無暗に明るい。眼を明いて居られぬ位だ。果てな何でも容子が可笑いと、のそ/\這ひ出して見ると非常に痛い。吾輩は藁の上から急に笹原の中へ棄てられたのである。

これを入力として、

$ myfmt.sh test.txt | xetex -jobname=wagahai

でできた wagahai.pdf は、こんな感じ。(標準入力を使ったときの出来上がり pdf のファイル名はジョブ名になるから、xetex の -jobname オプションを変えておけば pdf ファイルの名前が変えられるってわけ)

また、こうしたやり方は、パイプラインにつないで使えるというのも、わりと大きな利点だ。

ためしに、インスタペーパーごっごをやってみよう。このページの内容を html タグを削除して pdf にするには、

$ wget http://www.kabipan.com/densan/xetex.html -O - | 
sed -e 's/<[^>]*>//g' | 
xetexescape.sed | myfmt.sh | xetex

とすれば、texput.pdf という pdf ファイルが出来上がる。なお、xetexescape.sed というのは、少し前の項で作った特殊文字エスケープ用のスクリプト。中間的なファイルを作っていないところに、密やかな喜びがある。

ああ、そうそう、忘れてた。作りたいのは買い物メモだった……

縦書き

XeTeX は、フォントが持っている情報を使って文字を置いていく。そこで、縦書きにする設定というのも、フォント名を決めるところで行う。

最も単純な使い方で縦書きを実現してみると、

\font\Mincho="IPA明朝:vertical,+vert" at 12pt
\Mincho これは、「縦書き」ですよー。 
\bye

みたいな感じだ。「IPA明朝」というフォント名の後に feature と呼ばれるオプションをカンマで区切って書いてやる。vertical というのは vertical typesetting のことで、これを書いておくと、グリフの回転を可能にする。これは、XeTeX が用意した feature らしい。(ftp://ftp.dante.de/pub/tex/documentation/xetexref/xetex-reference.pdf 1.2.5)

その後に続く +vert というのは、フォントが持っている feature をオン(+)にするという意味で、こうしておくと回転したときに約物のグリフが正しくなる。(vert については、Microsoft のページに説明がある https://www.microsoft.com/typography/otspec/features_uz.htm#vert)

OpeyType は、latin とか漢字とかいった文字の集合を考え、これを script と呼ぶ。同じ script を使うについても異なる言語ではグリフに異同があるべきだから、language ということを考える。ここにフォントはいくつかの script の集合であり、各 script において language を選択することができて、その後に feature を定めるという順序となる。「IPA明朝」は、script として hani(漢字)、kana(仮名)、latin を持っていて、どの script も vert という feature を持っている。(hani というのは、Han unification と関係し、これは中国語、日本語、韓国語を一つの文字セットにまとめること。)。しかるに、「IPA明朝」は日本語以外で使われることを想定していないからか、script や language について何も書かずに、feature だけ上に掲げたように書けば XeTeX で縦書きにすることができる。

なお、フォントがどういう feature を持っているかということは、次のようにして調べられる。XeTeX のディストリビューションは、opentype-info.tex という書類を含んでいて、この XeTeX ソースをエディタで開き、最初のほうにあるフォント名を興味のあるフォント名に書き換え(たとえば \def\myfontname{IPAMincho} のように)てから xetex すればよ なお、\font\title や \font\tenrm や \font\tentt のところを自分の持っているフォントが書いてあるかもしれないので、その場合にはここいらのフォント指定も書き換えておく必要あり。

さっそく IPAMincho でやってみたところ、(「IPA明朝」と書いても私のとこでは同じこと)

OpenType Layout features found in `IPAMincho'
script = 'hani'
  language = ⟨default⟩
    features = 'ccmp' 'vert'
script = 'kana'
  language = 'JAN '
    features = 'ccmp' 'vert'
  language = ⟨default⟩
    features = 'ccmp' 'vert'
script = 'latn'
  language = ⟨default⟩
    features = 'ccmp' 'vert'

のようになった。

ついでに言っておくと、\font\myname="[/mydir/myfontfile]" のようにすると、インストールしていないフォントも使える。ただし、この場合はフォント固有の feature は使うことができない。

なお、フォント指定の一般的な書式は、

\font\myname="[fontname]{font-options}:{font-features}"{TEXfont-features}

である。(http://xml.web.cern.ch/XML/lgc2/xetexmain.pdf 2.3 参照)

なおここで、{font-options} というのは、

/B   太字
/I   斜体
/BI  斜体の太字
/IB  /BIに同じ
/S=x 選択されたフォントのxポイント用に最適化されたバージョン
/AAT Mac OS X において ATSUI を明示的に使う
/ICU ICU OpenType renderer を明示的に使う(Mac OS X でのみ意味がある)

これらのオプションはフォントが OS を通じて選択された場合のみ使える。残念ながら、日本語フォントは、たいがいこれらの別バージョンを持っていないだろうと思うけど。

{font-features} は , か ; で区切られたリストで、いろいろな ATT フォントまたは OpenType フォントの feature をオンにしたりオフにしたりする。

OpenType font features は、standard tags names (http://www.microsoft.com/typography/otspec/featuretags.htm 参照) をカンマかセミコロンで区切り、+tag_name -tag_name によってオンにしたりオフにしたりする。

XeTeX はどのフォントでも使える feature をいくつか用意している。

mapping を使って、mapping=tex-text のようにすると、''を " に変換するなど、TeX のように使えるようにする。

color を使って、color=RRGGBB のようにすると、テキストに色をつけることができる。

letterspace は文字間のスペース。

ちょっと謎なのは、vertical という feature で、これはフォントごとにあるわけではなくて、XeTeX が用意しているものなのだが、どのフォントにでも効くというわけではない。

script は、フォントの script を選び、langage はフォントの言語を選ぶ。これは前に触れた。

面白いのは pseudo-features というのがあって、斜体や長体、平体が別途用意されていないようなフォント(日本語フォントはほとんどそうだと思う)に、無理に傾かせたり延ばしたりできる。(むかしむかしのワープロに 2 倍角とかあったのを思い出すことですよ)。これは、slant=0.2 とか、extend=1.5 とかいうように使う。次の例はいわゆる横倍角の斜体(!)。美しいものではないから、嫌いな人はやってみないほうがいいかもw

\font\Mincho="IPA明朝:extend=2,slant=0.2" at 12pt

condensed とか anti-slanted とか数値を指定しないで使える pseudo-features もある。

せっかくだから、「猫」の縦書きバージョンを作ってみた。

こんな具合であるよ。

とりあえずおしまい