features ファイル

features ファイル
features ファイルは、makeotf でフォントを作成する際に、フォント内に含まれる各テーブルの情報を指定するためのファイルです。

仕様書はこちらにあります。
https://github.com/adobe-type-tools/afdko/blob/develop/docs/OpenTypeFeatureFileSpecification.md

GSUB や GPOS のほか、色々なテーブルの値を設定することができます。

すべて説明するのは大変なので、ここでは、最低限必要な情報だけ解説していきます。

なお、このファイル内では基本的に、OpenType のフォーマットにおける値をそのまま指定するので、詳しい値は、以下のサイトをご覧ください。
https://docs.microsoft.com/en-us/typography/opentype/spec/
head テーブル
head テーブルでは、フォントの基本的な情報を指定します。
ここで設定できるのは、フォントのバージョン番号だけです。

table head {
  FontRevision 1.000;
} head;

FontRevision で、小数点以下3桁までの数値を指定します。

この数値は、name テーブルのバージョン文字列に、以下のような形で、自動的にセットされます。

Version 1.000;hotconv 1.0.118;makeotfexe 2.5.65603
OS/2 テーブル
OS/2 テーブルでは、フォントの色々な情報を指定します。
"$ spot -t OS/2 FONTFILE" で、フォントの OS/2 テーブルの情報を表示できるので、参考にしてください。

OS/2 テーブルの値を指定しなかった場合は、デフォルトで値が設定されますが、以下、場合によって任意での設定が必要な項目のみ説明します。

table OS/2 {
    WeightClass 400;
    WidthClass 5;
    FSType 0;
    FamilyClass 0;
    Panose (空白で区切った10個の数値);
    Vendor "ADBO";
    TypoLineGap 0;
} OS/2;

WeightClassフォントの太さを数値で表します。
フォント一覧から太さで検索するときなどに使われます。
400 = Regular
700 = Bold
WidthClassフォントの文字幅を指定します。
横に縮めたグリフなどの場合は、おおよその % で指定します。
3 = Condensed (75%)
5 = 100%
FSTypeフォントの埋め込みに関するフラグです。
0 = 埋め込みとインストール可
2 = 埋め込みを許可しない
4 = 表示と印刷のみのために埋め込み可 (デフォルト)
8 = 表示と印刷に加え、編集も可
FamilyClasssans serif といったファミリーの分類を指定します。
0 で指定なし (デフォルト)。
源ノ角ゴシックと源ノ明朝は 0 となっています。
Panoseフォントの書体に関する詳細を指定します。
Venderフォントの事業者の ID (4文字)。
デフォルトで "ADBO" (Adobe) となりますが、自作のフォントであれば、適当な名前にしても構いません。
TypoLineGap行間 (フォントの高さに加算する値)。
hhea でも同じような項目がありますが、Windows では、この値が行間として使われる場合があります。
hhea テーブル
hhea テーブルでは、横書き時のレイアウトなどの情報を指定します。
"$ spot -t hhea FONTFILE" で、フォントの hhea テーブルの情報を表示できます。

指定しない場合、自動的に値が設定されるので、基本的にはデフォルトで構いませんが、LineGap のみ注意が必要です。

table hhea {
    Ascender 880;
    Descender -120;
    LineGap 0;
    CaretOffset 0;
} hhea;

Ascenderグリフ座標での、上端 Y 位置。
フォントの高さに影響するので、デフォルトの値で問題がある場合は、指定してください。
Descenderグリフ座標での、下端 Y 位置。
ascender - descender がフォントの高さになります。
LineCap行と行の間の間隔 (グリフ座標単位)。
※デフォルトで 1000 = 1em となっているので、そのままでは、1行分の空白が空くことになります。
※ Windows 上では、OS/2 の TypoLineGap の値が使われる場合があります。

基本的には 0 を基準として、行間を空けたい場合は、値を調整してください。
CaretOffset斜体のグリフの場合、文字位置のカーソルを表示する時に、指定値分 X 位置を移動する。
vhea テーブル
vhea テーブルは、hhea の縦書き版です。
縦書き時に使われる情報となるので、縦書きに対応していないフォントの場合は不要です。

table vhea {
  VertTypoAscender 500;
  VertTypoDescender -500;
  VertTypoLineGap 0;
} vhea;

VertTypoAscenderEMBOX の中央をベースラインとして、右端までの距離
VertTypoDescenderEMBOX の中央をベースラインとして、左端までの距離
VertTypoLineGap行間。
デフォルトで 1000 となるので、注意してください。

VertTypoAscender と VertTypoDescender については、デフォルトの 500 と -500 で問題ありません。
name テーブル
name テーブルでは、フォント名以外の各文字列を指定します。
"$ spot -t name=3 FONTFILE" で、name テーブルの情報を表示できます。

フォント名は FontMenuNameDB から、バージョンの文字列は CID フォントの情報から自動でセットされますが、それ以外の文字列をセットする場合は、こちらで記述します。

table name {
 nameid 0 "著作権";
 nameid 9 "作者名";
 nameid 12 "作者の URL";
 nameid 13 "ライセンス文";
 nameid 14 "ライセンスの URL";
} name;

nameid の後に、文字列の種類の番号を指定します。
各番号によって、何の文字列を指定するかが決まっています。

その後には、任意で、「platform ID」「script ID」「language ID」の数値を指定できます。
指定しなかった場合、デフォルトでは、platform = 3 [Windows]、script = 1 [Unicode]、language = 0x0409 [English] となるので、上記の場合は、基本的に英語の文字列を記述します。

日本語での文字列を追加する場合は、以下のようになります。
nameid 9 3 1 0x411 "日本語の作者名";

" " で囲まれた部分が文字列となります。
FontMenuNameDB の時とは違い、" " 内では、文字列をそのまま記述します。
ただし、テキストは UTF-8 の文字コードで保存する必要があります。

文字列内では、「\ + 16進数」で、直接 UTF-16 の文字を指定することもできます。
vmtx テーブル
vmtx テーブルでは、縦書き時の各グリフの、原点 Y 位置と送り幅を指定します。

原点 Y 位置に関しては、実際のフォントでは、VORG テーブルに出力されますが、features ファイル内では、まとめて vmtx 内に設定します。

table vmtx {
 VertAdvanceY \65140 500;
 VertOriginY \736 867;
} vmtx;

VertAdvanceY で、グリフの CID と、縦書き時の Y 方向の送り幅を指定します。
VertOriginY で、グリフの CID と、原点 Y 位置を指定します。
VertAdvanceY
横書き時の送り幅(グリフの原点から、次のグリフまでの幅)は、グリフデータ内に含まれているので、features ファイルで指定する必要はありませんが、縦書き時の送り幅は、グリフデータ内に含まれていないので、各グリフごとに指定する必要があります。

ただし、縦書き時の送り幅は、基本的に全角幅であることが多いため、指定がない場合は、デフォルトで 1 em (= 1000) として扱われます。
よって、ほとんどのグリフでは、VertAdvanceY を指定しなくても大丈夫です。

ただし、vrt2 で 90 度回転した欧文など、送り幅が全角幅でないグリフは、直接指定する必要があります。
VertOriginY
グリフのアウトラインの座標は、横書き時の原点位置(左端、欧文のベースライン位置)を基準として、値が設定されていますが、縦書き時は、グリフの上端をベースラインとして、描画することになります。

縦書きのグリフ描画時は、横書き用のグリフのアウトライン座標をそのまま使うことになるので、座標を、横書きの原点から、縦書きの原点位置へと変換する必要があります。
その時に必要となるのが、グリフの縦書きの原点 Y 位置です。

デフォルトでは ascender の値となるので、多くのグリフではそれで問題ありませんが、例えば、全角の「jqy」など、横書き時に、欧文ベースラインの下にアウトラインがあるようなグリフでは、ascender を原点とすると、少し下に下がるような結果となります。

そういったグリフの縦書き時の Y 位置を調整するために、VertOriginY で原点の Y 位置を指定することができます。
変換元のフォントの値を使う
縦書き時の送り幅や原点位置は、各フォントのグリフのアウトラインによるので、Adobe-Japan1 における既定値などはありません。

そのため、合成したフォントなどの場合は、変換元フォントの vmtx と VORG テーブルの情報を取得して、その値を変換先の同じグリフにセットする必要があります。
※ VORG テーブルは、TrueType フォント内には存在しません。

各テーブルの値は、spot コマンドで出力できます。

## vmtx
$ spot -t vmtx=7 FONTFILE

## VORG
$ spot -t VORG=4 FONTFILE
GSUB テーブル
GSUB テーブルにはグリフの置換情報、GPOS テーブルにはグリフのアウトラインの調整値が含まれています。

GSUB と GPOS は、フォント内では別のテーブルに分かれていますが、features ファイル内では、両方を feature { } 内でまとめて記述します。
(vert など、一部、GSUB と GPOS で同じタグ名になるものがありますが、基本的には、GSUB と GPOS でほとんどタグ名は異なります)

feature <タグ名> {
 substitute ...;
 sub ...; # 省略形
 position ...;
 pos ...; # 省略形
} <タグ名>;

feature の後に、機能を表すタグ名を指定します。

substitute (sub) が GSUB、position (pos) が GPOS の値を設定します。
Adobe-Japan1 の features ファイル
CID フォントの場合、CID の指定グリフを、別の CID グリフで置き換えるという情報になります。

規定の ROS であれば、CID とグリフの定義は一定であるため、あらかじめ定義された features ファイルを使うことができます (GSUB の情報のみ)。

https://github.com/adobe-type-tools/Adobe-Japan1
- GSUB/*.fea

ファイル名に jp04 が付いているものは、JIS2004 のフォント用です。
JIS2004 の字形から 90JIS の字形に置き換える、jp90 の feature が含まれます。

jp04 が付いていないものは、90JIS のフォント用です。
JIS2004 以外の字形から JIS2004 の字形に置き換える、jp04 の feature が含まれます。

makeotf では、features ファイルは一つしか指定できないため、実際にこのファイルを使う場合は、GSUB の情報に加えて、他のテーブルの情報も追加することになります。
空グリフの注意点
Adobe-Japan1 でないフォントを、Adobe-Japan1 に変換した場合、グリフが割り当てられず、.notdef で置き換えたグリフが含まれています。

あらかじめ定義された GSUB の features ファイルでは、すべてのグリフが実際に存在するものとして、置換情報が設定されていますが、変換したフォント上において、実際は空となっているグリフが、置換元/置換先として GSUB データに存在すると、.notdef のグリフに置き換えられてしまうので、問題となります。

例えば、'A' は vrt2 で90度回転のグリフに置き換えられますが、源ノフォントでは、90度回転のグリフは含まれていないため、縦書き時は .notdef のグリフに置き換えられてしまいます。

置換元/置換先のグリフが実際には存在しないのであれば、そのグリフは、GSUB データから除外する必要があります。
GPOS テーブル
GPOS テーブルでは、各機能に応じて、グリフの位置や送り幅を調整することができます。

例えば、'kern' では、2つの指定グリフが並んだ場合、1つ目のグリフの送り幅を狭めたり広げたりできます。

ただし、GPOS の値は、グリフのアウトラインによるので、GSUB のような規定の値はありませんし、GPOS テーブルは、(kern を除き)基本的に DTP などのソフト上でしか使われないので、必要がなければ、なくても問題ありません。

変換元フォントから GPOS をコピーしたい場合は、spot コマンドで取得できます。

$ spot -t GPOS=7 FONTFILE
源ノフォントの Adobe-Japan1 用 features ファイルを作成
以上を踏まえて、源ノフォントを Adobe-Japan1 として作成するための、features ファイルを作成します。

  • GSUB テーブルは、Adobe-Japan1 の定義ファイルを元にして、変換元から割り当てられていないグリフを除外する。
  • VORG テーブルは、変換元フォントの情報を spot コマンドで取得して、変換先の対応する CID に同じ値を設定する。
  • GPOS テーブルは、変換元フォントの情報を spot コマンドで取得して、変換先の対応する CID に同じ値を設定する。
  • その他の情報は、手動で記述する。
スクリプトで処理
GSUB/VORG/GPOS テーブルの情報は、Python3 スクリプトで自動処理します。

>> make-features.py

$ spot -t VORG SourceHanSansJP-Regular.otf > vorg.txt
$ spot -t GPOS=7 SourceHanSansJP-Regular.otf > gpos.txt

$ python3 make-features.py 7 out2.txt aj17-gsub-jp04.fea vorg.txt gpos.txt > features.fea 

まず、spot -t VORG で、変換元フォントの VORG 情報を取得します。
同じく、spot -t GPOS=7 で、変換元フォントの GPOS 情報を、features ファイルのスタイルで出力します。

make-features.py は、
1番目の引数に、作成するフォントの ROS の Supplement の番号 (3〜7)。
2番目に、remap-gsub.py で出力した、CID マッピング情報のファイル。
3番目に、Adobe-Japan1 の GSUB features ファイル。
4番目に、変換元フォントの VORG 情報のファイル (省略または "" でなし)。
5番目に、変換元フォントの GPOS 情報のファイル (省略または "" でなし)
を指定してください。

GSUB features ファイルは、JIS2004 のフォントを作成するのであれば、aj17-gsub-jp04.fea
JIS2004 でないフォントを作成するのであれば、aj17-gsub.fea を指定してください。

※スクリプトでは、一部、複雑な GSUB/GPOS 情報はスキップしています。
他のテーブル情報を追加
後は、出力した features ファイルに、手動で他の情報を追加します。
追加する位置は先頭でも終端でも構いませんが、先頭の方が良いでしょう。

table head {
  FontRevision 1.000;
} head;

table OS/2 {
  TypoLineGap 0;
} OS/2;

table hhea {
  LineGap 0;
} hhea;

table vhea {
  VertTypoLineGap 0;
} vhea;

table name {
 nameid 0 "著作権";
 nameid 9 "作者名";
 nameid 13 "This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an \0022AS IS\0022 BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.";
 nameid 14 "http://scripts.sil.org/OFL";
} name;

...

行間はデフォルトで 1000 になるので、0 にセットしています。
OS/2 のフォント書体に関する項目については、源ノフォントのソースの features ファイルからコピーしても構いません。