CFF テーブル (1)

CFF テーブルについて
CFF テーブル」には、PostScript アウトラインのデータが格納されています。
CFF フォントの内容が、そのまま丸ごと入っている形となります。

さらに、OpenType 1.8 では、「CFF2 テーブル」が追加されました。
基本的に CFF テーブルと同じ構造になりますが、いくつかの重複したデータが省略され、可変フォントに対応しています。

CFF フォーマットの仕様書は、下記にあります。
http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
CFF の構造
バイト順は「ビッグエンディアン」で、すべてのデータでバイト境界はありません。

先頭から順に、以下のデータが並んでいます。

Headerヘッダ
Name INDEXPostScript フォント名
Top DICT INDEX各フォントの主要情報
String INDEXフォントで使われるすべての文字列
Global Subr INDEXグローバルサブルーチン

その他のデータは、「Top DICT」などで指定されているオフセット値から、格納されている場所へアクセスできます。

それぞれのデータは、独自形式か、共通したフォーマットである「INDEX 構造」「DICT 構造」のデータで格納されています。

Name INDEX」は、INDEX のデータ構造で、フォント名が格納されていることになります。
データ型
Card8符号なし 8bit
Card16符号なし 16bit
Offsetオフセット値。1〜4 byte の可変サイズ。
OffSizeOffset のバイトサイズ (1〜4)。
符号なし 8bit。
SID文字列 ID (0〜64999)。
符号なし 16bit。
INDEX 構造
配列として扱うためのデータ構造です。

Card16 countオブジェクトの数
OffSize offsizeオフセット値のバイトサイズ
Offset offset[count + 1]オフセットの配列。
data の先頭を 1 とした値」なので、0 以外となる。
データのサイズは、offset[i + 1] - offset[i] で求める。
Card8 data[可変]オブジェクトデータの領域

オフセット値は、「data の先頭 - 1」を 0 とした値なので、注意してください。

空の 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バイト目があります。
12 以外なら、1 byte 値となります。

1バイト目と2バイト目は、組み合わせて値を作るようなことはありません。
「12, 1」という 2byte の値であれば、キーは「12 と 1」になります。
値のタイプ
number整数値、または実数
boolean0 (false) or 1 (true)
SID文字列 ID
array配列
delta数値の差分の配列。
2番目以降の値は、一つ前との差の値が格納される。
[a0, a1 - a0, a2 - a1,...]
整数値
可変長 (1〜5 byte) によって、数値が表されます。
最初のバイトが b0、続いて b1, b2, b3, b4。

b0 の値の範囲バイト数値の範囲値の計算方法
32 - 2461-107 〜 107b0 - 139
247 - 2502108 〜 1131(b0 - 247) * 256 + b1 + 108
251 - 2542-1131 〜 -108-(b0 - 251) * 256 - b1 - 108
28316bit 符号あり(b1 << 8) | b2
29532bit 符号あり(b1 << 24) | (b2 << 16) | (b3 << 8) | b4
実数
1バイト目が 30 の場合は、可変長の実数値となります。
2バイト目以降は、上位 4bit・下位 4bit にそれぞれ、以下の値が格納されています。

4bit値意味
0 - 90 〜 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)」となります。
ヘッダ
先頭にあるデータです。

Card8 majorメジャーバージョン = 1
Card8 minorマイナーバージョン = 0
Card8 hdrSizeこのヘッダ全体のサイズ (通常は 4)。
Name INDEX へ移動するための値となります。
OffSize offSizeCFF の先頭を 0 とするオフセット値の、バイトサイズ
Name INDEX
ヘッダの後に続くデータです。
すべてのフォントの、PostScript フォント名が格納されています。

INDEX 構造データで、オブジェクトデータは文字列となります。

CFF フォントは複数のフォントを格納できますが、OpenType フォント内の CFF では、1つのフォント名のみとなります。
String INDEX
「Name INDEX」の後に続くデータです。

フォントで使われるすべての文字列が格納されています。
(フォントの名前や、グリフ名など)

INDEX 構造データで、オブジェクトデータは文字列となります。
データがない場合は、空の INDEX データとなります。

文字列は、「SID」の値によって参照されます。

SID 0 〜 390」は、定義済みの標準文字列です。
SID 391〜」の文字列が String INDEX に格納されており、SID 391 以上の文字列は、この配列の「SID - 391」の位置のデータから取得することになります。
Top DICT INDEX
「String INDEX」の後に続くデータです。

「Name INDEX」の各フォントに対応した、フォントの主要な情報が格納されています。
INDEX 構造データで、オブジェクトデータは DICT 構造です。

通常は1つのフォントの情報しかないので、INDEX の数は1つとなります。
値の一覧
オフセット値は、CFF の先頭を 0 とした値です。
デフォルト値は、項目が指定されていなかった場合に設定される値です。

名前キー値タイプデフォルト値、解説
version0SID-
Notice1SID-
Copyright12, 0SID-
FullName2SID-
FamilyName3SID-
Weight4SID-
isFixedPitch12, 1booleanfalse
ItalicAngle12, 3number0
UnderlinePosition12, 3number-100
UnderlineThickness12, 4number50
PaintType12, 5number0
CharstringType12, 6number2
FontMatrix12, 7array0.001, 0, 0, 0.001, 0, 0
UniqueID13number-
FontBBox5array0, 0, 0, 0
StrokeWidth12, 8number0
XUID14array-
charset15number0
charset データのオフセット値 (または charset ID)
Encoding16number0
Encoding データのオフセット値
CharStrings17number-
CharStrings INDEX のオフセット値
Private18number, number-
Private DICT のサイズとオフセット値
SyntheticBase12, 20number-
PostScript12, 21SID-
BaseFontName12, 22SID-
BaseFontBlend12, 23delta-
CID フォント
ROS12, 30SID, SID, number-
CIDFontVersion12, 31number0
CIDFontRevision12, 32number0
CIDFontType12, 33number0
CIDCount12, 34number8720
UIDBase12, 35number-
FDArray12, 36number0
Font DICT INDEX のオフセット値
FDSelect12, 37number0
FDSelect のオフセット値
FontName12, 38SID-
Font DICT で使われる。
オフセット値が指定されている各データについて
これ以降は、各フォントごとに指定されたオフセット値の位置へ飛び、各データを読み込んでいきます。

Encoding
CID フォントの場合、エンコーディングはありません。
また、OpenType での格納時は、このデータは省略されます。
charset
GID と SID/CID を関連付けるためのデータです。
CharStrings
すべてのグリフのアウトラインデータが格納されています。
Private
DICT 構造による、フォントの内部的な情報です。
Charsets
「Top DICT」の「charset (key = 15)」値が、このデータのオフセット位置です。

CFF/CID フォントでは、各グリフは、SID または CID で関連付けられています。

欧文などグリフ数が少ない場合は、SID でグリフ名が定義されており、
CJK フォントでは、Adobe が定義した CID によって番号が付けられています。

フォントによっては、グリフ ID と SID/CID が同一で一致する場合もありますが、そうでない場合もあります。

「Charsets」には、グリフ ID に対応した SID/CID を取得するためのデータがあります。
データは独自形式で、フォーマットは3つあります。
charset ID
Top DICT の charset 値が「0〜2」の場合は、定義済みの文字セットとなります。
Top DICT に charset が存在しない場合、デフォルト値は 0 となるため、「ISOAdobe」となります。

0ISOAdobe
1Expert
2ExpertSubset
フォーマット
GID = 0 (.notdef)」のデータは省略されているため、「GID 1〜」の対応データとなります。

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 によってアクセスされ、最初のグリフは「GID = 0 (.notdef)」である必要があります。

データの形式は、Top DICT の「CharstringType」値で指定されます (デフォルト = 2)。
それぞれ、以下に仕様書があります。

format 1: Adobe Type 1 Font Format
format 2: The Type 2 Charstring Format

ここでは、アウトラインデータのフォーマットについては省略します。
CID フォント
CID フォント」は、主に CJK フォントなどの多数のグリフを扱うために設計された PostScript フォントです。

CID フォントが格納されている CFF では、一部、格納されているデータなどが異なります。

  • 「Top DICT」には、一番最初に「ROS (key = 12,30)」のデータがある。
  • 「Top DICT」に「FDArray」「FDSelect」の値が存在する。
    これは両方ともオフセット値である。
  • 「Charsets」のデータでは、SID の値を 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」となっていますが、これは、フォントごとに独自に定義されたものであることを表します。
FDArray と FDSelect
※ FD は、「Font DICT」の略です。

FDSelect」には、GID から「Font DICT」のインデックス値を取得するためのデータがあります。

FDArray」は「Font DICT INDEX」のデータで、各グリフの情報 (DICT 構造) があります。

まず、FDSelect でグリフに対応したインデックス値を取得し、FDArray (Font DICT INDEX) でそのインデックス位置のデータを参照して、DICT 情報を取得します。
FDSelect
Charsets と似たような、独自形式となっています。
※「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センチネル GID

▼ Range3 構造体
Card16 first範囲の最初の GID
Card8 fd範囲の全てのグリフに対応する FD インデックス値

同じ FD インデックスを持つ GID のグループが定義されています。

GID は、「first 〜 "次のデータの first" - 1」までの範囲となり、小さい値から順に連続して繋がっています。
一番最初の GID は、0 でなければなりません。

「sentinel」は、Range3 の配列の最後のデータから、次の first を得るための値です。
つまり、「最後の GID + 1」=「グリフ数」となります。
Private DICT の値
名前キー値データ型デフォルト、説明
BlueValues6delta-
OtherBlues7delta-
FamilyBlues8delta-
FamilyOtherBlues9delta-
BlueScale12,9number0.039625
BlueShift12,10number7
BlueFuzz12,11number1
StdHW10number-
StdVW11number-
StemSnapH12,12delta-
StemSnapV12,13delta-
ForceBold12,14booleanfalse
LanguageGroup12,17number0
ExpansionFactor12,18number0.06
initialRandomSeed12,19number0
Subrs19numberローカルサブルーチンのオフセット値。
Private DICT データの先頭を 0 とした値。
defaultWidthX20number0
nominalWidthX21number0