Hatena::ブログ(Diary)

マクロツイーター このページをアンテナに追加 RSSフィード Twitter

2011-10-14

dvipdfmx で OpenType する件について (SFD 編-8)

(前回の続き)

TFM 生成ツールにおける SFD ファイルの扱い

これまでの説明は ttf2tfm を用いる場合についてのものであり、次のようにコマンドを起動するのであった。

ttf2tfm mplus-1p-regular.ttf mplus1ps-r-@Samp0TeXStd@

Type1 フォント(afm2tfm 等)は Unicodeエンコーディングを持たないのでそもそも SFD ファイルの対象にならない。従って、残りは otftotfm ということになる。実は otftotfm は SFD ファイルを利用した TFM 生成には対応しておらず、必ず .enc ファイルを用いる必要がある。なので、結局この節では何も書くことがないということになる。

OpenType/CFF で SFD ファイルをどう扱うか

ところがそれで終わっては困ることがある。ttf2tfm は TrueType フォントにしか対応していない。だから OpenType/CFF フォントに対して SFD ファイルでエンコーディングを指定して TFM を生成する手段がないことになる。

しかしこれはそれほど大きな問題ではない。既に何度か触れたように、SFD ファイルは「手段の一つ」でしかない。だから、「本来の」サブフォントを扱う場合であっても、多少面倒ではあるが、.enc ファイルを用意してそれで対応すれば大概の場合は対応できる。

ただし、それでは済まない場合がある。SFD ファイルの話を始めたそもそもの動機は、「日本語 OpenType フォント + dvipdfmx + .enc ファイル」で不具合が起こることであった。だから「前 2 つ + 欧文 TFM」の組み合わせが望まれる場合はどうしても SFD ファイルを用いる必要がある。ところが、ここでも「TFM 生成ツールと DVI ウェアは互いに依存しない」という性質を用いれば解決できる。すなわち、TFM 生成の時には .enc ファイル + otftotfm を用いた上で、dvipdfmx の設定は SFD ファイルを用いるのである。ただし、otftotfm は与えられたエンコーディングを「変換」する機能があるので、よく気をつけないと .enc ファイルと SFD ファイルの内容が一致しないことになる。

・ .enc を SFD の方に合わせる方法

例えば、Unicode.sfd 中の

u4e  0x4E00_0x4EFF

の行に対応する TFM を生成したいとする。この場合、以前に触れたように、

/gen-u4e [
  /uni4E00 /uni4E01 /uni4E02 …… /uni4EFF
] def

というファイル gen-u4e.enc を作成する。そして以下のように、--no-virtual を付して otftotfm を実行する。

otftotfm --no-type1 --no-dotlessj --no-virtual -e gen-u4e.enc -n mplus1ps-r-u4e mplus-1p-regular.ttf

注意すべきこととして、この時に liga 等のリガチャを有効化させてはいけない(つまり -f liga を付けない)。*1((なお、ここで --literal-encoding を使うと、グリフ名が本当に /uni???? である場合にしか対応できないので不適切である。))これで生成される mplus1ps-r-u4e.tfmフォント「mplus1ps-r-u@Unicode@」の一員として用いればよい。

・ SFD を .enc の方に合わせる方法

普通に .enc でエンコーディングを定義するという手順をとり、dvipdfmx のマップ設定のときだけ、(otftotfm による)修正済の .enc と同等な SFD ファイルを後で作るという方法である。この方法は、かなり面倒であり、かつ SFD がフォントに依存してしまうことになるが、前の方法よりもトラブルが起こりにくい。

SFD ファイル SomeEnc.sfd とフォント mplus-1p-regular.ttf から「修正済の SFD」である mplus1pSomeEnc.sfd を作成して dvipdfmx でサブフォント mplus1ps-r-@mplus1pSomeEnc@(これは本来作りたい mplus1ps-r-@SomeEnc@ と同等)を設定する手順を示すことにする。

  • SomeEnc.sfd の各行に対して、以下の手順を行う。以下の説明では、その行の識別子を xyz であるとする。(その行に対応する TFM は mplus1ps-r-xyz となる。)
    • xyz の行に対応する .enc ファイル SomeEnc-xyz.enc を作成する。.enc の代替として SFD を使おうとしていた場合は、元の .enc を使えばよい。
    • その .enc を指定して otftotfm を起動する。
      otftotfm --no-type1 --no-dotlessj -f kern -f liga -e SomeEnc-xyz.enc -n mplus1ps-r-xyz.tfm mplus-1p-regular.ttf
      これで修正済みのエンコーディング a_??????.enc と TFM ファイル mplus1ps-r-xyz.tfm が出力される。この mplus1ps-r-xyz が VF になった場合は、mplus1ps-r-xyz.vf と mplus1ps-r-xyz--base.tfm も出力される。以下、VF である場合を仮定して説明するが、そうでない場合は説明の「mplus1ps-r-xyz--base」を「mplus1ps-r-xyz」で置き換える。
    • エンコーディング a_??????.enc の中に記されたグリフ名を対応する Unicode 符号位置に変換して、SFD の行の記述「xyz 〈符号位置範囲〉」を作成する。
    • その行を mplus1pSomeEnc.sfd に追記する。
    この手順で「修正済」の mplus1pSomeEnc.sfd が出来上がる。
  • その上で、dvipdfmx で次のマップ設定を行う。
    mplus1p-r-@mplus1pSomeEnc@ unicode mplus-1p-regular.ttf

ここで甚だ厄介なのは「グリフ名を Unicode 符号位置に変換する」ところである。otftotfm 自身は glyphlist.txt や texglyphlist.txt を参照してこの処理を行っているので、恐らくこれらを参照すれば見つかると思われる。最大の問題は「Unicode のマップを持たないグリフ」である。リガチャを有効にしていると、こういうグリフが自動挿入されることがある。*2これは SFD では実現できないし、かといって未定義にしてしまうと、実際にそのリガチャが生じた時に文字が抜けてしまう。これを回避するには、そもそもリガチャを有効(-f liga)にするのを止める*3、あるいは --ligkern オプションで当該のリガチャだけを抑止する(詳細は otftotfm のマニュアル*4を参照)等の対策が必要になる。

*1:リガチャを有効化すると、otftotfm は未定義の符号位置にリガチャの結果となるグリフを自動的に挿入するが、そうすると、実際に使う予定である SFD でのエンコーディングと合わなくなる。なお、カーニングは指定してもよいが、そもそもサブフォントを用いる場合、「同じ TFM」の中でしかカーンが起こらないことに注意する必要がある。

*2:この原理は前の脚注にある通り。

*3:ただこの場合、fi や ff 等の「TeX で普通の」リガチャも、.enc ファイル中に LIGKERN 指令を書かない限り、働かないことになる。

*4:texdoc で探そう。