CFF テーブルについて
「CFF テーブル」には、PostScript アウトラインのデータが格納されています。
CFF フォントの内容が、そのまま丸ごと入っている形となります。
さらに、OpenType 1.8 では、「CFF2 テーブル」が追加されました。
基本的に CFF テーブルと同じ構造になりますが、いくつかの重複したデータが省略され、可変フォントに対応しています。
CFF フォーマットの仕様書は、下記にあります。
The Compact Font Format Specification (PDF)
CFF フォントの内容が、そのまま丸ごと入っている形となります。
さらに、OpenType 1.8 では、「CFF2 テーブル」が追加されました。
基本的に CFF テーブルと同じ構造になりますが、いくつかの重複したデータが省略され、可変フォントに対応しています。
CFF フォーマットの仕様書は、下記にあります。
The Compact Font Format Specification (PDF)
CFF の構造
バイト順は「ビッグエンディアン」で、すべてのデータでバイト境界はありません。
先頭から順に、以下のデータが並んでいます。
その他のデータは、「Top DICT」などで指定されているオフセット値から、格納されている場所へアクセスできます。
それぞれのデータは、独自形式か、共通したフォーマットである「INDEX 構造」「DICT 構造」のデータで格納されています。
「Name INDEX」は、INDEX のデータ構造で、フォント名が格納されていることになります。
先頭から順に、以下のデータが並んでいます。
Header | ヘッダ |
---|---|
Name INDEX | PostScript フォント名 |
Top DICT INDEX | 各フォントの主要情報 |
String INDEX | フォントで使われるすべての文字列 |
Global Subr INDEX | グローバルサブルーチン |
その他のデータは、「Top DICT」などで指定されているオフセット値から、格納されている場所へアクセスできます。
それぞれのデータは、独自形式か、共通したフォーマットである「INDEX 構造」「DICT 構造」のデータで格納されています。
「Name INDEX」は、INDEX のデータ構造で、フォント名が格納されていることになります。
データ型
Card8 | 符号なし 8bit |
---|---|
Card16 | 符号なし 16bit |
Offset | オフセット値。1〜4 byte の可変サイズ。 |
OffSize | Offset のバイトサイズ (1〜4)。 符号なし 8bit。 |
SID | 文字列 ID (0〜64999)。 符号なし 16bit。 |
ヘッダ
先頭にあるデータです。
Card8 major | メジャーバージョン = 1 |
---|---|
Card8 minor | マイナーバージョン = 0 |
Card8 hdrSize | このヘッダ全体のサイズ (CFF は 4)。 CFF 先頭から、Name INDEX へ移動するための値となります。 なお、CFF2 の場合は 5 で、下の値が u16 topDictLength となっています。 |
OffSize offSize | CFF の先頭を 0 とするオフセット値の、バイトサイズ。 実際には使われないので、無視して構いません。 |
INDEX 構造
データを配列で扱うための構造です。
オフセット値は、data の先頭を 0 とすると、実際には offset - 1 で位置を取得することになるので、注意してください。
空の INDEX は、count が 0 で、以下のデータはなく、全体で 2 byte のデータとなります。
offset 配列の最後の値は、「data のサイズ + 1」となります。
Card16 count | オブジェクトの数 |
---|---|
OffSize offsize | 以下の Offset のバイトサイズ |
Offset offset[count + 1] | 各データのオフセット値の配列。 data の先頭を 1 とした値なので、0 以外となる。 データのサイズは、offset[i + 1] - offset[i] で求める。 |
Card8 data[可変] | オブジェクトデータの領域。 先頭から順にバイトの隙間なく並べる。 |
オフセット値は、data の先頭を 0 とすると、実際には offset - 1 で位置を取得することになるので、注意してください。
空の INDEX は、count が 0 で、以下のデータはなく、全体で 2 byte のデータとなります。
offset 配列の最後の値は、「data のサイズ + 1」となります。
DICT 構造
「キー」と「値」がペアとなる、辞書データです。
- 「値 (複数可)」「キー」「値」「キー」... という順で、連続して並んでいます。
- データのサイズ分、繰り返し読み込んでいきます。
- 「キー」は 1〜2 byte。
「値」は、整数または実数で、可変長データです。
値は複数個連続して並ぶ場合があります。 - 最初のバイト値で、キーか値かを判別できます。
「0〜21」はキー。
「28、29、30、32〜254」は値。
「22〜27、31、255」は予約されています。
キー
キーは、1バイト目が「12」の場合、2バイト目があります。
1バイト目が 12 以外なら、そのまま 1 byte 値となります。
例えば、「12, 1」という 2byte の値であれば、キーは「12 と 1」になります。
2つの値を合わせて、1つの値を作るといったことはしません。
1バイト目が 12 以外なら、そのまま 1 byte 値となります。
例えば、「12, 1」という 2byte の値であれば、キーは「12 と 1」になります。
2つの値を合わせて、1つの値を作るといったことはしません。
値のタイプ
number | 整数値、または実数 |
---|---|
boolean | 0 (false) or 1 (true) |
SID | 文字列 ID |
array | 配列 |
delta | 数値の差分の配列。 2番目以降の値は、一つ前との差の値が格納される。 (a0, a1 - a0, a2 - a1,...) |
整数値
可変長 (1〜5 byte) によって、数値が表されます。
以下は、バイトが順に b0, b1, b2, b3, b4 と並んでいる場合の計算方法です。
以下は、バイトが順に b0, b1, b2, b3, b4 と並んでいる場合の計算方法です。
b0 の値の範囲 | バイト数 | 値の範囲 | 値の計算方法 |
32 - 246 | 1 | -107 〜 107 | b0 - 139 |
---|---|---|---|
247 - 250 | 2 | 108 〜 1131 | (b0 - 247) * 256 + b1 + 108 |
251 - 254 | 2 | -1131 〜 -108 | -(b0 - 251) * 256 - b1 - 108 |
28 | 3 | 16bit 符号あり | (int16)((b1 << 8) | b2) |
29 | 5 | 32bit 符号あり | (int32)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) |
実数
1バイト目が 30 の場合は、可変長の実数値となります。
2バイト目以降は、上位 4bit・下位 4bit にそれぞれ、以下の値が格納されています。
値が -2.25 なら、「1E(30) E2('-2') A2('.2') 5F('5'END)」となります。
2バイト目以降は、上位 4bit・下位 4bit にそれぞれ、以下の値が格納されています。
4bit値 | 意味 |
0 - 9 | 0 〜 9 |
---|---|
10 (0xA) | . (小数点) |
11 (0xB) | E |
12 (0xC) | E- |
13 (0xD) | 予約 |
14 (0xE) | - (マイナス) |
15 (0xF) | 値の終了 |
値が -2.25 なら、「1E(30) E2('-2') A2('.2') 5F('5'END)」となります。
Name INDEX
ヘッダの直後に続くデータです。
すべてのフォントの、PostScript フォント名が格納されています。
INDEX 構造データで、オブジェクトデータは文字列となります。
CFF フォントは複数のフォントを格納できますが、OpenType フォント内の CFF では、1つのフォント名のみとなります。
すべてのフォントの、PostScript フォント名が格納されています。
INDEX 構造データで、オブジェクトデータは文字列となります。
CFF フォントは複数のフォントを格納できますが、OpenType フォント内の CFF では、1つのフォント名のみとなります。
String INDEX
「Name INDEX」の直後に続くデータです。
フォントで使われるすべての文字列が格納されています。
(フォントの名前や、グリフ名など)
INDEX 構造データで、オブジェクトデータは文字列となります。
データがない場合は、空の INDEX データとなります。
ここの文字列は、フォント内の「SID」の値によって参照されます。
フォントで使われるすべての文字列が格納されています。
(フォントの名前や、グリフ名など)
INDEX 構造データで、オブジェクトデータは文字列となります。
データがない場合は、空の INDEX データとなります。
ここの文字列は、フォント内の「SID」の値によって参照されます。
SID 0 〜 390 | 定義済みの標準文字列 |
---|---|
SID 391〜 | String INDEX に格納された文字列。 配列内の、「SID - 391」の位置から文字列を取得することになります。 |
Top DICT INDEX
「String INDEX」の直後に続くデータです。
「Name INDEX」の各フォントに対応した、フォントの主要な情報が格納されています。
INDEX 構造データで、オブジェクトデータは DICT 構造です。
通常は1つのフォントの情報しかないので、INDEX の数は1つとなります。
「Name INDEX」の各フォントに対応した、フォントの主要な情報が格納されています。
INDEX 構造データで、オブジェクトデータは DICT 構造です。
通常は1つのフォントの情報しかないので、INDEX の数は1つとなります。
値の一覧
オフセット値は、CFF の先頭を 0 とした値です。
デフォルト値は、項目が指定されていなかった場合に設定される値です。
デフォルト値は、項目が指定されていなかった場合に設定される値です。
名前 | キー値 | タイプ | デフォルト値、解説 |
version | 0 | SID | - |
---|---|---|---|
Notice | 1 | SID | - |
Copyright | 12, 0 | SID | - |
FullName | 2 | SID | - |
FamilyName | 3 | SID | - |
Weight | 4 | SID | - |
isFixedPitch | 12, 1 | boolean | false |
ItalicAngle | 12, 2 | number | 0 |
UnderlinePosition | 12, 3 | number | -100 |
UnderlineThickness | 12, 4 | number | 50 |
PaintType | 12, 5 | number | 0 |
CharstringType | 12, 6 | number | 2 |
FontMatrix | 12, 7 | array | 0.001, 0, 0, 0.001, 0, 0 |
UniqueID | 13 | number | - |
FontBBox | 5 | array | 0, 0, 0, 0 |
StrokeWidth | 12, 8 | number | 0 |
XUID | 14 | array | - |
charset | 15 | number | 0 charset データのオフセット値 (または charset ID) |
Encoding | 16 | number | 0 Encoding データのオフセット値 |
CharStrings | 17 | number | - CharStrings INDEX のオフセット値 |
Private | 18 | number, number | - Private DICT のサイズとオフセット値 |
SyntheticBase | 12, 20 | number | - |
PostScript | 12, 21 | SID | - |
BaseFontName | 12, 22 | SID | - |
BaseFontBlend | 12, 23 | delta | - |
CID フォント | |||
ROS | 12, 30 | SID, SID, number | - |
CIDFontVersion | 12, 31 | number | 0 |
CIDFontRevision | 12, 32 | number | 0 |
CIDFontType | 12, 33 | number | 0 |
CIDCount | 12, 34 | number | 8720 |
UIDBase | 12, 35 | number | - |
FDArray | 12, 36 | number | 0 Font DICT INDEX のオフセット値 |
FDSelect | 12, 37 | number | 0 FDSelect のオフセット値 |
FontName | 12, 38 | SID | - Font DICT で使われる。 |
Top DICT INDEX 以降のデータ
Top DICT INDEX 以降は、Top DICT で指定された各データのオフセット値を使って、データを読み込んでいきます。
Encoding | ※ OpenType での格納時、このデータは省略されているので、読み込みません。 |
---|---|
charset | GID と SID/CID を関連付けるためのデータ。 |
CharStrings | すべてのグリフのアウトラインデータ。 |
Private | DICT 構造による、フォントの内部的な情報。 |
Charsets
「Top DICT」の「charset (key = 15)」のオフセット値を使って、読み込みます。
各 GID から、対応する SID または CID を取得するためのデータです。
CID フォントの場合は CID、CID フォントでない場合は、SID の値となります。
欧文など、グリフ数が少ないフォントでは、各グリフごとに SID でグリフ名が定義されています。
グリフ数の多い日本語などのフォントでは、グリフの名前ではなく、CID の番号を使います。
フォントによっては、グリフ ID と SID/CID が同一で一致する場合もありますが、そうでない場合もあるので、ここで、GID → SID/CID のマップを定義します。
データは Charsets の独自形式で、フォーマットは3つあります。
各 GID から、対応する SID または CID を取得するためのデータです。
CID フォントの場合は CID、CID フォントでない場合は、SID の値となります。
欧文など、グリフ数が少ないフォントでは、各グリフごとに SID でグリフ名が定義されています。
グリフ数の多い日本語などのフォントでは、グリフの名前ではなく、CID の番号を使います。
フォントによっては、グリフ ID と SID/CID が同一で一致する場合もありますが、そうでない場合もあるので、ここで、GID → SID/CID のマップを定義します。
データは Charsets の独自形式で、フォーマットは3つあります。
charset ID
Top DICT の charset 値が「0〜2」の場合は、定義済みの文字セットとなります。
Top DICT に charset が存在しない場合、デフォルト値は 0 となるため、「ISOAdobe」となります。
Top DICT に charset が存在しない場合、デフォルト値は 0 となるため、「ISOAdobe」となります。
0 | ISOAdobe |
---|---|
1 | Expert |
2 | ExpertSubset |
フォーマット
「GID = 0 (.notdef)」のデータは省略されているため、「GID 1〜」のデータとなります。
nGlyphs は、「CharStrings INDEX」の count 値。
▼ Range1 構造体
GID の 1 から順番に、「GID 〜 GID + nLeft」が、「first 〜 first + nLeft」に対応しています。
データの数は指定されていないので、グリフ数分が処理されるまで、続けます。
▼ Range2 構造体
Format 1 との違いは、nLeft の型。
Format 0 (配列)
Card8 format | フォーマット番号 = 0 |
---|---|
SID glyph[nGlyphs - 1] | SID の配列 |
nGlyphs は、「CharStrings INDEX」の count 値。
Format 1 (範囲: Card8)
Card8 format | フォーマット番号 = 1 |
---|---|
struct Range1[可変] | データの配列 |
▼ Range1 構造体
SID first | 範囲の最初の SID |
---|---|
Card8 nLeft | 範囲の数 - 1 |
GID の 1 から順番に、「GID 〜 GID + nLeft」が、「first 〜 first + nLeft」に対応しています。
データの数は指定されていないので、グリフ数分が処理されるまで、続けます。
Format 2 (範囲: Card16)
Card8 format | フォーマット番号 = 2 |
---|---|
struct Range2[可変] | データの配列 |
▼ Range2 構造体
SID first | 範囲の最初の SID |
---|---|
Card16 nLeft | 範囲の数 - 1 |
Format 1 との違いは、nLeft の型。
CharStrings INDEX
Top DICT の「CharStrings (key = 17)」のオフセット値から読み込みます。
すべてのグリフのアウトラインデータが格納されています。
INDEX 構造データで、オブジェクトデータはバイナリ値です。
INDEX の count 値が、フォントに含まれるグリフ数となります。
配列は、グリフ ID によってアクセスされます (SID/CID ではない)。
最初のグリフは「GID = 0 (.notdef)」である必要があります。
データの形式は、Top DICT の「CharstringType」値で指定されます (OpenType では 2 で固定)。
以下に、Type2 CharString の仕様書があります。
The Type 2 Charstring Format
アウトラインデータのフォーマットについては、後で説明します。
すべてのグリフのアウトラインデータが格納されています。
INDEX 構造データで、オブジェクトデータはバイナリ値です。
INDEX の count 値が、フォントに含まれるグリフ数となります。
配列は、グリフ ID によってアクセスされます (SID/CID ではない)。
最初のグリフは「GID = 0 (.notdef)」である必要があります。
データの形式は、Top DICT の「CharstringType」値で指定されます (OpenType では 2 で固定)。
以下に、Type2 CharString の仕様書があります。
The Type 2 Charstring Format
アウトラインデータのフォーマットについては、後で説明します。
CID フォント
「CID フォント」は、主に CJK (中国語/日本語/韓国語) フォントにおいて、多数のグリフを扱うために設計された、PostScript フォントです。
基本的に CFF のフォーマットのままで扱いますが、格納されているデータが一部異なります。
基本的に CFF のフォーマットのままで扱いますが、格納されているデータが一部異なります。
- 「Top DICT」には、一番最初に「ROS (key = 12,30)」のデータがある。
- 「Top DICT」に、「FDArray」「FDSelect」の値が存在する。
これは両方ともオフセット値である。 - 「Charsets」のデータでは、値を CID として扱う。
なお、CID フォントには、事前定義された文字セットは存在しない。
ROS
ROS は、「Registry Ordering Supplement」の略です。
それぞれ、「登録者」「配列」「追補番号」となっており、CID の文字コレクションを表します。
Top DICT では、この値は「<SID> <SID> <number>」という3つの数値から成り、
それぞれ、「Registry の文字列 ID」「Ordering の文字列 ID」「Supplement の数値」となっています。
「Adobe-Japan1-6」なら、「"Adobe"」「"Japan1"」「6」となります。
源ノ明朝では「Adobe-Identity-0」となっていますが、これは、フォントごとに独自に定義された文字コレクションであることを表します。
それぞれ、「登録者」「配列」「追補番号」となっており、CID の文字コレクションを表します。
Top DICT では、この値は「<SID> <SID> <number>」という3つの数値から成り、
それぞれ、「Registry の文字列 ID」「Ordering の文字列 ID」「Supplement の数値」となっています。
「Adobe-Japan1-6」なら、「"Adobe"」「"Japan1"」「6」となります。
源ノ明朝では「Adobe-Identity-0」となっていますが、これは、フォントごとに独自に定義された文字コレクションであることを表します。
FDArray と FDSelect
※ FD は、「Font DICT」の略です。
CID フォントはグリフ数が多いので、各グリフを、文字種などのいくつかのグループに分けて、それらをサブフォントとして扱います。
FDArray には、各サブフォントの情報の配列があり、FDSelect には、各 GID からサブフォントのインデックス値を取得するためのデータがあります。
まず、FDSelect で、GID に対応したサブフォントのインデックス値を取得し、FDArray (Font DICT INDEX) の配列から、インデックス位置を使って、DICT データを取得します。
DICT データには、「FontName (key = 12,38)」と「Private (key = 18)」のデータのみがあります。
サブフォントのフォント名と、Private DICT のオフセット値です。
CID フォントはグリフ数が多いので、各グリフを、文字種などのいくつかのグループに分けて、それらをサブフォントとして扱います。
FDArray には、各サブフォントの情報の配列があり、FDSelect には、各 GID からサブフォントのインデックス値を取得するためのデータがあります。
まず、FDSelect で、GID に対応したサブフォントのインデックス値を取得し、FDArray (Font DICT INDEX) の配列から、インデックス位置を使って、DICT データを取得します。
DICT データには、「FontName (key = 12,38)」と「Private (key = 18)」のデータのみがあります。
サブフォントのフォント名と、Private DICT のオフセット値です。
FDSelect
Charsets と同じような独自形式となっています。
※ただし、ここでは「GID = 0 (.notdef)」も含まれます。
nGlyphs は、CharStrings INDEX の count 値。
▼ Range3 構造体
同じ FD インデックスを持つ GID のグループが定義されています。
GID は、「first 〜 "次のデータの first" - 1」までの範囲となり、小さい値から順に連続して繋がっています。
一番最初の GID は、0 でなければなりません。
「sentinel」は、Range3 の配列の最後のデータから、次の first を得るための値です。
つまり、「最後の GID + 1」=「グリフ数」となります。
※ただし、ここでは「GID = 0 (.notdef)」も含まれます。
Format 0 (配列)
Card8 format | フォーマット番号 = 0 |
---|---|
Card8 fds[nGlyphs] | 各グリフの FD インデックス値 |
nGlyphs は、CharStrings INDEX の count 値。
Format 3 (範囲)
Card8 format | フォーマット番号 = 3 |
---|---|
Card16 nRanges | 配列の数 |
struct Range3[nRanges] | 範囲データ |
Card16 sentinel | 最後の first 値 (最後の GID + 1) |
▼ Range3 構造体
Card16 first | 範囲の最初の GID |
---|---|
Card8 fd | 範囲の全てのグリフに対応する FD インデックス値 |
同じ FD インデックスを持つ GID のグループが定義されています。
GID は、「first 〜 "次のデータの first" - 1」までの範囲となり、小さい値から順に連続して繋がっています。
一番最初の GID は、0 でなければなりません。
「sentinel」は、Range3 の配列の最後のデータから、次の first を得るための値です。
つまり、「最後の GID + 1」=「グリフ数」となります。
Private DICT の値
Top DICT または Font DICT の「Private (key = 18)」のオフセット値から読み込みます。
グリフに関する各情報が入っています。
グリフに関する各情報が入っています。
名前 | キー値 | データ型 | デフォルト、説明 |
BlueValues | 6 | delta | - |
---|---|---|---|
OtherBlues | 7 | delta | - |
FamilyBlues | 8 | delta | - |
FamilyOtherBlues | 9 | delta | - |
BlueScale | 12,9 | number | 0.039625 |
BlueShift | 12,10 | number | 7 |
BlueFuzz | 12,11 | number | 1 |
StdHW | 10 | number | - |
StdVW | 11 | number | - |
StemSnapH | 12,12 | delta | - |
StemSnapV | 12,13 | delta | - |
ForceBold | 12,14 | boolean | false |
LanguageGroup | 12,17 | number | 0 |
ExpansionFactor | 12,18 | number | 0.06 |
initialRandomSeed | 12,19 | number | 0 |
Subrs | 19 | number | ローカルサブルーチンのオフセット値。 Private DICT データの先頭を 0 とした値。 |
defaultWidthX | 20 | number | 0 デフォルトのグリフ送り幅 (CharString で幅が指定されていない場合) |
nominalWidthX | 21 | number | 0 CharString で幅が指定されていた場合の基本幅 (この値を足す) |