GSUB の情報を元に割り当て

GSUB の情報を元に割り当て
前回は、Unicode とのマッピング情報を元にグリフを割り当てましたが、まだ割り当てられるグリフが残っています。
それは、GSUB の情報によって、別のグリフから置き換えられるグリフです。

例えば「、」は、縦書きでは「︑」の位置となるので、横書き用のグリフを元に、縦書き用のグリフに置き換える必要があります。
そういったグリフの置換情報は、フォント内の GSUB テーブルに格納されています。

横書きを行うだけの多くのソフトでは、GSUB のデータはあまり使われることはありませんが、縦書きに対応したソフトや、DTP などの高度な処理を行うソフトでは、使用されます。

このような、GSUB の置換によって使用されるグリフは、ほとんどが Unicode に割り当てられていないため(縦書きなど、一部割り当てられているものもありますが)、GSUB のデータを参照して、存在を確認する必要があります。
CID 割り当ての手順
Adobe-Japan1 では、縦書きなどのグリフにも、すべて CID が割り当てられています。

GSUB によって置き換えられるグリフを、源ノフォントの CID から Adobe-Japan1 の CID に割り当てたい場合、単一のグリフ置換に限定はされますが、間接的に Unicode のマッピング情報を使うことで、ある程度自動的に処理することができます。

置換先のグリフには Unicode が割り当てられていなくても、置換元のグリフには割り当てられていることが多いので、置換元グリフの Unicode 値を元にすれば、対象となる CID を検索することができます。

  1. Adobe-Japan1 の GSUB 情報の、各置換元グリフの CID から、それに割り当てられている Unicode 値を取得。
  2. 変換元フォントにおいて、(1) の Unicode が割り当てられている CID を取得。
  3. 変換元の同じ GSUB 情報から、その CID と一致する置換元グリフの CID を検索。
  4. Adobe-Japan1 の置換先グリフの CID に、変換元フォントの置換先グリフの CID を割り当て。
解説
少しややこしいですが、例えば、GSUB には、横書きのグリフを縦書きのグリフに置き換える、vert または vrt2 という名前の情報があります。
この GSUB の情報が、Adobe-Japan1 と変換元フォントの両方で含まれているものとします。

「、」(U+3001) →「︑」

Adobe-Japan1: CID 634 -> CID 7887
源ノ角ゴシック: CID 1397 -> CID 58980

まず、Adobe-Japan1 の GSUB 情報の、置換元グリフ CID 634 から、割り当てられている Unicode を取得します。
これは、UniJIS2004-UTF32-H ファイルなどから取得できるため、U+3001 となります。

次に、変換元フォントで、U+3001 が割り当てられている CID を検索します。
これは、cmap テーブルの情報から取得できるため、CID 1397 となります。

そして、変換元フォントの GSUB の vert 情報から、CID 1397 が置換元になっているものを検索します。

見つかった場合、変換元フォントにおいて、「、」を縦書きに置き換えたグリフは、CID 58980 であるということがわかるので、Adobe-Japan1 における CID 7887 は、変換元フォントでは CID 58980 のグリフである、ということになります。

実際のフォント内の GSUB データでは、グリフは GID で表されています。
フォントの CFF テーブル内に、GID→CID への変換データが存在するため、AFDKO のコマンドでは、このデータを元に、CID に変換されます。
必要なファイル1
GSUB の情報から CID 割り当てを行う場合、まず、変換元フォントの GSUB 情報が必要になるので、AFDKO の spot コマンドを使います。

$ spot -t GSUB=7 SourceHanSansJP-Regular.otf > gsub.txt

-t GSUB=7 で、フォントの GSUB テーブルの情報を、makeotf が扱う features ファイルのスタイルで出力します。
出力結果は、gsub.txt に保存します。

makeotf は AFDKO に含まれるコマンドで、グリフのアウトラインデータと各定義ファイルから、OpenType フォントを作成するものです。
makeotf においては、フォントの各テーブルの情報は、features ファイルで定義することができます。
それと同じフォーマットで、GSUB の情報を出力します。
ファイルの中身
# Printing lookup 0 in feature 'aalt' for script 'DFLT' language 'dflt'.
# --- Start Lookup [0])
# -------- SubTable 0
 sub \117 by \1644;
 sub \245 by \256;
...
 sub \1 from [ \1396 \63164];
...
 sub \2 \32 by \746;

「# ...in feature 'aalt'」の aalt が、GSUB の feature (処理機能の名前) です。
4文字の英数字となっています。

この名前は、OpenType の仕様として、機能ごとにあらかじめ定義されており、どういう形のグリフに置き換えるかを示すものとなります。

aalt の場合は、一つのグリフを、複数のバリエーションのグリフで置き換えます(どれに置き換えるかは、ユーザーが選択します)。
例えば「1」であれば、全角の1、囲み文字の1、という形で、'1' のグリフに関連するいくつかのグリフのリストとなります。

その後の 'DFLT' や 'dflt' などは、気にしなくて構いません。言語などに関する名前となります。

"sub \117 by \1644;" は、単一グリフの置換情報です。
\117 (CID 117) を \1644 (CID 1644) に置き換える、という意味です。

"sub \1 from [ \1396 \63164];" は、一つのグリフに対して、複数の置換先があるという意味です。

"sub \2 \32 by \746;" は、合字などで使われ、複数のグリフを結合した形を、一つのグリフで表現することになります。
GSUB のグリフ置換を確認する
こういった定義だけでは、実際にどういう置き換えが行われるのかがわかりにくいので、視覚的に確認してみます。

spot コマンドを使うと、GSUB の置換情報を、グリフのアウトラインで出力することができます。
※ただし、PostScript を直接出力する形となっているため、実際に確認するには、PostScript → PDF 変換を行う必要があります。

PostScript を PDF に変換するには、Ghostscript の ps2pdf コマンドを使います。
ghostscript をインストールした後、以下を実行してください。

$ spot -t GSUB=8 SourceHanSansJP-Regular.otf | ps2pdf - gsub.pdf

-t GSUB=8 で、GSUB のグリフ置換を、PostScript で標準出力に出力します。
パイプでつないだ pdf2pdf コマンドで、標準入力から PostScript を読み込み、gsub.pdf に出力します。

少し時間がかかるので、出力し終わったら、PDF ファイルを開いてみてください。
必要なファイル2
次に、Adobe-Japan1 における GSUB 情報が必要となります。

Adobe-Japan1 のグリフ置換は、あらかじめ定義されたファイルがあるので、それを使います。
以下のファイルをダウンロードしてください。

https://github.com/adobe-type-tools/Adobe-Japan1
- GSUB/aj17-gsub-jp04.fea

GSUB/*.fea のファイルは、makeotf で、Adobe-Japan1 の CID フォントを作成する際に使われます。
Adobe-Japan1 でのグリフの GSUB 置換情報が記述されています。

ファイル名の先頭の aj17 は、Adobe-Japan1-7 の略です。
もし新しいバージョンがあれば、そのファイルを使ってください。

また、aj17-gsub.fea というファイルもあると思いますが、今回は aj17-gsub-jp04.fea の方を使います。

aj17-gsub-jp04.feaJIS2004 のフォントを作成する時に使う。
グリフを 90JIS の字形に置き換える、jp90 の feature が含まれる。
aj17-gsub.feaJIS2004 ではない、90JIS のフォントを作成する時に使う。
JIS2004 以外のグリフから JIS2004 の字形に置き換える、jp04 の feature が含まれる。
JIS について
上記2つのファイルの違いを説明するためには、まず、JIS2004 が何なのかというところから説明します。

日本において、漢字などの文字は、JIS 規格によって定義されています。
(世界的な規格は ISO ですが、これは日本国内での規格です)

1978年の規格から始まって、今に至るまで複数回改定されており、その中で、いくつかの漢字の字形が変更されてきました。
現在では、実質的に 2004年改定の JIS2004 が最新の状態となっています。

その前の改定で字形が変更されたのは、1990年の通称 90JIS ですが、90JIS と JIS2004 では、168 個の漢字の字形が変更されています。



このように、微妙に字形が異なるため、有料フォントなどでは、90JIS と JIS2004 で、フォントファイルを分けて作成している場合があります。

なお、Adobe-Japan1 では、JIS2004 の字形に加え、それ以前の 90JIS や 78JIS/83JIS の字形も含まれているため、グリフデータ自体は、90JIS と JIS2004 どちらのフォントでも同じです。

これらのフォントで異なるのは、Unicode にどの字形のグリフを割り当てているかということと、GSUB に含まれる情報の違いです。
features ファイルの違い
ここで、GSUB の features ファイルの違いに戻ります。

90JIS として作成したフォントの場合は、そもそも、デフォルトで 90JIS の字形が使われるので、グリフを 90JIS の字形に置き換える jp90 の GSUB データは必要ありません。

同じように、JIS2004 として作成したフォントの場合は、デフォルトで JIS2004 の字形が使われるので、グリフを JIS2004 の字形に置き換える jp04 の GSUB データは必要ありません。

こういった違いがあるため、features ファイルは、aj17-gsub.fea と aj17-gsub-jp04.fea で、各字形用の2つに分かれている、ということです。

makeotf で実際にフォントを作成する場合は、それぞれで必要なファイルを使いますが、今回の場合は、単に CID の再割当てをするための情報として使いたいだけなので、最新の JIS2004 用のファイルを使います。
そのため、前回でも、JIS2004 用の UniJIS2004-UTF32-H ファイルを使いました。
スクリプトで処理
Python3 スクリプトで、GSUB データによる CID 再割当てを行うプログラムを作ったので、こちらを使ってください。

>> remap-gsub.py
(右クリックで、名前を付けて保存してください)

$ python3 remap-gsub.py out1.txt gsub.txt aj17-gsub-jp04.fea > out2.txt

1番目の引数に、前回の remap-unicode.py で出力したファイル。
2番目に、spot -t GSUB=7 で出力した、変換元フォントの GSUB 情報ファイル。
3番目に、Adobe-Japan1 の GSUB features ファイル (省略で 'aj17-gsub-jp04.fea')
を、それぞれ指定してください。

前回の CID 割り当ての情報に、GSUB 情報による割り当てを追加する形で、処理を行います。
結果は標準出力に出力されるので、ここでは out2.txt に出力します。
出力結果
16685/23060 (72.35%)

前回の 16431/23059 (71.26%) と比べると、254 個のグリフが追加されました。

とりあえず、自動で変換できるのはここまでです。

この状態でも、普通に使うには十分なグリフが含まれていますが、まだ残っているグリフもあるので、必要であれば、さらに手動で割り当てていく形になります。