埋め込みフォント

埋め込みフォント
フォントを PDF 内に埋め込む場合、フォント辞書の FontDescriptor エントリで指定した辞書内で、
FontFile, FontFile2, FontFile3 のいずれかのエントリを使って、ストリームを指定します。

どのエントリを使うかは、フォントのタイプによります。

各エントリの値では、フォントデータを埋め込んだストリームを指定します。
ストリーム辞書では、各フォントタイプによって、追加のエントリが必要な場合があります。
FontDescriptor 辞書の各エントリで使用できるフォント
エントリサブタイプ説明
FontFile-Type 1 フォント
[Type1, MMType1]
FontFile2-TrueType フォント
[TrueType (PDF 1.1), CIDFont2 (PDF 1.3)]
FontFile3Type1C(PDF 1.2) CFF フォント (1バイトコード用)
[Type1, MMType]
FontFile3CIDFontType0C(PDF 1.3) CFF フォント (CID)
[CIDFontType0]
FontFile3OpenType(PDF 1.6) OpenType フォント
[CIDFontType0, CIDFontType2]

「サブタイプ」は、フォントを埋め込んだストリーム辞書の Subtype エントリで指定する名前です。

[] の中の名前は、そのエントリで使用することができる、PDF のフォントタイプです。
(フォント辞書、または CIDFont 辞書の Subtype エントリで指定されたタイプ)

CFF フォントは、OpenType 内の CFF テーブルの内容と同じです。
OpenType フォントを丸ごと埋め込む場合は FontFile3 (OpenType)、OpenType から CFF テーブルを抽出して埋め込む場合は、FontFile3 (CIDFontType0C) を使うことになります。
ストリーム辞書の追加エントリ
フォントを埋め込んだストリーム辞書で指定できるエントリです。

Length1integer(Type 1 or TrueType で必須)
Type 1 時は、クリアテキスト部分の長さ。
TrueType 時は、ファイル全体の長さ。
(ともに、フィルタデコード後のサイズ)
Length2integer(Type 1 で必須) Type 1 フォントの暗号化された部分の長さ (フィルタデコード後)
Length3integer(Type 1 で必須) Type 1 フォントの固定コンテンツ部分の長さ (フィルタデコード後)
Subtypename(PDF 1.2。FontFile3 の場合必須) フォントプログラムを指定する名前。
/Type1C, /CIDFontType0C, /OpenType
Metadatastream(PDF 1.4) メタデータストリーム

CFF 形式の場合は、Length1,2,3 のエントリは必要ありません。
TrueType の埋め込み
1byte の文字コードのみを使用するのであば、フォント辞書の Subtype エントリで /TrueType を指定し、FontFile2 エントリを使って、フォントストリームを指定します。
その場合、ストリーム辞書に Length1 エントリを追加します。

CJK フォントなどで、256 文字以上を使用するのであれば、Type 0 フォントで子孫のタイプを /CIDFontType2 とし、FontFile2 または FontFile3 エントリを使って、フォントストリームを指定します。

フォント内で必須となるテーブルは [ glyf, head, hhea, hmtx, loca, maxp ] です。
必要であれば、[ cvt, fpgm, prep ] も含めます。

縦書き時の情報である [ vhea, vmtx ] は、PDF 内では使用されません。
縦書き時のグリフ情報は、CIDFont 辞書の DW2, W2 エントリで指定します。

必要なグリフだけ抜き出したサブセットとして埋め込む場合は、フォント内の必要なテーブルとグリフだけを取り出して、それを元に TrueType フォントファイルを再構築し、そのデータを埋め込みます。

TTC ファイル (複数のフォントが格納されたフォントコレクション) の場合は、単一のフォントごとに埋め込む必要があります。
OpenType/CFF の埋め込み
OpenType ファイル内では、CFF 形式のフォントファイルが、CFF テーブル内にそのまま埋め込まれている形となっています。
そのため、OpenType ファイル内から CFF テーブルのみを抽出して埋め込む場合と、OpenType ファイルそのままで埋め込む場合の、2通りがあります。

※ OpenType ファイルとして埋め込む場合は、PDF 1.6 以降である必要があります。

FontFile3 エントリを使ってフォントストリームを指定し、ストリーム辞書の Subtype エントリで、埋め込むフォントの形式を指定する必要があります。

OpenType フォントとして埋め込む場合は、[ CFF, cmap ] テーブルが必要です。
CMap
埋め込みフォントの場合、文字エンコーディングを指定するための CMap は、任意の形で指定することができます。

  • 「文字コード = CID またはグリフインデックス」とする場合、CMap に /Identity-H, /Identity-V を指定します。
  • 文字列を任意のエンコーディングで記述したい場合、文字コードから CID へのマッピングを行う CMap を指定します。

サブセットフォントの場合は、/Identity-H, /Identity-V を使う場合が多いです。
CMap ストリーム
CMap は、「文字コードから CID へのマッピング」や、「CID から Unicode へのマッピング」を行うための情報です。

ストリームで定義し、ストリームのデータ部分では、PostScript によってテキスト形式で記述します。
CMap のストリーム辞書の追加エントリ
Typename(必須) オブジェクトのタイプ。常に /CMap
CMapNamename(必須) CMap の PostScript 名。
CMap 定義内の名前と同じであること。
CIDSystemInfodictionary(必須) 文字コレクションを定義するエントリを含む辞書
WModeinteger0 で横書き用、1 で縦書き用。
default = 0
UseCMapname or streamこの CMap のベースとして使用される CMap。
定義済みの CMap 名、または CMap のストリーム。
これによって、ベースとの差分のみを定義できます。
例 (CID から Unicode へのマッピング)
形式がほぼ決まっているので、以下を参考に記述してください。
なお、以下の例は、CID またはグリフインデックスを Unicode 値にマッピングするためのものです。

※ U+10000 以上の場合、UTF-16BE として記述します。

10 0 obj
<< /Type /CMap
  /CMapName /FONTNAME-UTF16-H
  /CIDSystemInfo <<
    /Registry (Adobe)
    /Ordering (UCS)
    /Supplement 0
  >>
  /WMode 0
  /Length 1000
>>
stream
% CMap ファイルの処理に必要なルーチンを読み込み
/CIDInit /ProcSet findresource begin
% 12 は辞書エントリのサイズ。とりあえず固定でよい
12 dict begin
% CMap 定義の開始
begincmap

% CMap 名
/CMapName /FONTNAME-UTF16 def
% CMap タイプ
% 1 = CID への変換
% 2 = Unicode への変換
/CMapType 2 def
% 文字コレクション
/CIDSystemInfo <<
  /Registry (Adobe)
  /Ordering (UCS)
  /Supplement 0
>> def

% コードスペース範囲 (notdef を含む)
% 先頭の数値はエントリの数
% 2つの値をペアとして、開始と終了を指定 (16進数。1byte or 2byte)
1 begincodespacerange
<0000> <FFFF>
endcodespacerange

% 個々の入力コードと、対応する文字コードを定義
% 先頭の数値はエントリの数
6 beginbfchar
<0316> <2026>
<07BD> <3042>
<07BF> <3044>
<07D8> <305D>
<07DE> <3063>
<07DF> <3064>
endbfchar

% 指定範囲の入力コードに対応する、連続した文字コードを定義
% 開始入力コード、終了入力コード、文字コードの先頭
9 beginbfrange
<0793> <0795> <3000>
<07C1> <07C3> <3046>
<07C5> <07CC> <304A>
...
endbfrange

...

% CMap 定義の終了
endcmap
% この形で常に記述
CMapName currentdict /CMap defineresource pop
% dict の end
end
% /CIDInit /ProcSet findresource begin の end
end

コードスペース範囲の指定によって、入力コードのバイト数が決まります。
1byte なら <00> <FF>、2byte なら <0000> <FFFF> を指定します。

beginbfchar〜endbfchar、beginbfrange〜endbfrange は、入力コードを文字コード (Unicode) に変換するためのマッピング定義部分です。
開始時の先頭の数値は、エントリの数です。

これらを必要な分だけ記述して、定義していきます。
文字コードから CID へのマッピングの場合
文字コードから CID へのマッピングの場合もほぼ同じ形となりますが、一部記述が異なります。

CMapType には 1 を指定し、コードのマッピング部分では、別の命令を使います。

begincidchar〜endcidchar : 個々の文字コードに対する CID を定義
begincidrange〜endcidrange : 連続した範囲の文字コードに対する CID を定義

また、文字コードから CID へのマッピング定義時、指定文字コードを、フォント内で定義されていないグリフとして、別の CID に割り当てたい場合は、beginnotdefchar〜endnotdefchar、beginnotdefrange〜endnotdefrange を使います。

% 00-1F の文字コードを CID 231 に割り当て
1 beginnotdefrange
<00> <1F> 231
endnotdefrange