cmap

OpenTypeにおける文字コード

[120] OpenType ではいろいろな文字コードが使われます。

仕様書

概要

[39] OpenType における文字コードには2つの側面があります。

[42] name cmap は、 利用する文字コードを記述し、その文字コードによって文字を記述または参照しています。

[43] その他のいくつかの文字データは符号化方式決め打ちです。

[119] GSUBGPOS ではグリフIDが使われます。 文字コードグリフ符号の違いに注意。 OpenTypeグリフIDは個々のフォントが独自に決定できるフォント内部の記述用のもので、 情報交換には適しません。 (ただしグリフ名CIDも参照。)

文字符号化

[49] cmap には異なる文字符号化部分表を含められます。 文字符号化は、 (platformID, encodingID, language) の3つの値の組で識別されます。 >>1

[68] Unicode部分表とその他の何種類かの部分表は、 Unicode符号位置(列)からグリフIDへの対応関係を表します。 その他の部分表は、 非Unicode文字符号化からグリフIDへの対応関係を表します。

[69] 現在ではほぼすべての実装が Unicode を使って cmap を引いています。以前 (平成時代初期頃まで) は非Unicode の実装もありました。 現在では非Unicodecmap 部分表を含まないフォントも多いです。 MacRomancmap 部分表を含むフォントも多いですが、 互換性のためというよりは、互換性が必要だった時代の名残りの慣習と思われます。 現在使われているフォントMacRoman cmap は使い物にならないおかしなデータのことも多いです。

platformID

[50] platformID は、 次のいずれかです。

[51] platformID
v
数値
n
名前 >>1, >>121
name
name >>121
cmap
cmap >>1
note
メモ
v
0
n
Unicode
name
cmap
v
1
n
Macintosh
name
cmap
v
2
n
ISO [deprecated]
note
OpenType 1.3 から非推奨 (deprecated) >>1
cmap
v
3
n
Windows
name
cmap
v
4
n
Custom
cmap
v
[ 240, 255 ]
note
利用者定義プラットフォーム予約 (reserved) >>1
cmap
name
>>135

[55] platformIDencodingID名前空間を区別する役割がありますが、 それ以外の意味も処理方法も規定がありません。例えば Linux の実装が Windows platformID を使ってはいけないということはありません。 プラットフォームごとに文字コードの体系がまったく違っていた旧時代の遺物と考えるべきなのでしょう。

[53] すべての値に対応しなければならないとする規定はありません。 未対応のものは無視して構わないと思われます。

[52] 未知の値に遭遇したときどう処理するべきか不明確です。 それが含まれるものは無視するのが妥当でしょう。

[54] 利用者定義の値について、使い方に何の規定もありません。 encodingID は好きに使って良いのでしょう。 未知の値は無視して構わないと考えるのが妥当でしょう。

[74] platformID 1 (Macintosh) の cmap 部分表はかつての Macintosh では必須 (required) でしたが、 現在の Appleプラットフォームでは非推奨 (discouraged) です。 >>1

encodingID

[70] encodingID の意味は platformID に依存します。 encodingID には次のものがあります。

p
platformID
e
encodingID
o
OpenType の説明 >>1
r
制限 >>1
u
Unicode部分表
note
メモ
p
0 (Unicode)
e
0
o
Unicode 1.0 semantics
r
非推奨 (deprecated) >>1, >>121
u
note
UTF-16BE >>121
p
0 (Unicode)
e
1
o
Unicode 1.1 semantics
r
非推奨 (deprecated) >>1, >>121
u
note
UTF-16BE >>121
p
0 (Unicode)
e
2
o
ISO/IEC 10646 semantics
r
非推奨 (deprecated) >>1, >>121
u
note
UTF-16BE >>121
p
0 (Unicode)
e
3
o
Unicode 2.0 and onwards semantics, Unicode BMP only
r
cmap: 部分表 format 4, 6 で使うべき (should) >>1, name >>121
u
note
UTF-16BE >>121
p
0 (Unicode)
e
4
o
Unicode 2.0 and onwards semantics, Unicode full repertoire
r
cmap : 部分表 format 10, 12 で使うべき (should) >>1, name >>121
u
note
UTF-16BE >>121
p
0 (Unicode)
e
5
o
Unicode Variation Sequences
r
cmap : 部分表 format 14 でのみ使うべき (should) >>1 (name にはなし)
u
p
0 (Unicode)
e
6
o
Unicode full repertoire
r
cmap : 部分表 format 13 でのみ使うべき (should) >>1 (name にはなし)
u
p
0 (Unicode)
e
10
note
Unicode符号点仕様書にないが利用例あり。
u
p
0 (Unicode)
e
その他
u
p
1 (Macintosh)
e
script manager code
r
cmap : 非推奨 (discouraged) >>1, name
p
2 (ISO)
e
0
o
7-bit ASCII
r
cmap : 非推奨 (deprecated)
p
2 (ISO)
e
1
o
ISO 10646
r
cmap : 非推奨 (deprecated)
p
2 (ISO)
e
2
o
ISO 8859-1
r
cmap : 非推奨 (deprecated)
p
2 (ISO)
e
その他
p
3 (Windows)
e
0
o
Symbol
note
symbol encoding
r
通常は cmap format 4。 新たには Unicode を使うべき (should)
p
3 (Windows)
e
1
o
Unicode BMP
u
r
BMP 使用禁止 (must not)
p
3 (Windows)
e
2
o
ShiftJIS
p
3 (Windows)
e
3
o
PRC
p
3 (Windows)
e
4
o
Big5
p
3 (Windows)
e
5
o
Wansung
p
3 (Windows)
e
6
o
Johab
p
3 (Windows)
e
7
o
Reserved
p
3 (Windows)
e
8
o
Reserved
p
3 (Windows)
e
9
o
Reserved
p
3 (Windows)
e
10
o
Unicode full repertoire
u
p
3 (Windows)
e
その他
p
4 (Custom)
e
[ 0, 255 ]
o
cmap : OTF Windows NT compatibility mapping
r
cmap format 0, 6なければ (must) 。 新たに使うべきではない (should not)
p
4 (Custom)
e
その他
p
[ 240, 255 ]
note
cmap : 利用者定義予約
p
その他

[67] OpenType 仕様書では cmap Unicode () (ぶん) (ひょう) (subtable) という語が使われています。 platformID 0platformID 3 encodingID 1, 10 を表すとされています。 >>1

[75] また Windows 用のフォントを作成するときは Unicode cmap () (ぶん) (ひょう) (Unicode cmap subtable) を常に使うべき (should) ともされています。 この Unicode cmap 部分表platformID 3 encodingID 1, 10 を意味するとされています。 >>1

[123] Windowsフォントname については、 platformID 3encodingID 1 (Unicode フォント) または encodingID 0 (Symbol font) とするべきです (should) >>121

[122] name における platformID 3 (Windows) においては、 encodingID は、 cmapplatformID 3 (Windows) の encodingID と一致しているべきです (should) >>121

[78] UnicodeBMP のみと全体とは format が違えば区別可能なはずです。 にも関わらず encodingIDformat の両方に違う値を指定させて区別しています。 format 13 専用の encodingID もそうです。 format だけでの区別では実装上の問題があったのでしょうか。

Windows 符号化

[124] name の文字列は、 encodingID3 (Windows) の場合、 UTF-16BE で符号化しなければなりません (must) >>121

[125] これはつまり、 cmapencodingID と同じ値を指定する (>>122) だけで、その値自体にはそれほど意味がなく、 値に関わらず UTF-16BE を使わなければならないということのようです。

[126] 古い CJK フォントはこの規定に反していることがあります。 例えば MingLi は、 ラテン文字名を UTF-16BE符号化しながらも中文名は encodingID 4 (Big5) で文字列を CP950 で符号化していました。 >>121

[127] これは platformID 1 (Macintosh) が実際に指定された通りの符号化となるのと違う点です。

[128] さて、 OpenType の仕様はこの状況をどう処理するべきなのか何も語っていません。 現在となっては platformID 3 (Windows) のデータを含むフォントは希少となっているようですが、 古いフォントを扱う必要がある (可能性がある) ソフトウェアは、 何らかの方針を立てて対処しなければなりません。

[129] CJKコードページならコードページ通りの符号化、 それ以外なら UTF-16BE、としてしまっていいのでしょうか。 それなら楽なのですが、 CJKコードページUTF-16BEフォントも出回っているなら、文字コード自動判定が必要となります。


[146] なお、 OS/2 にはカバーしているコードページを記述できます。

[145] OS/2 - OS/2 and Windows metrics table (OpenType 1.9) - Typography | Microsoft Learn, PeterCon, https://learn.microsoft.com/ja-jp/typography/opentype/spec/os2#cpr

platformID 4

[79] platformID 4 (Custom) は、 encodingID [ 0, 255 ] が OTF Windows NT compatibility mapping として使われます。 >>1

[81] platformID 4 は、 Type 1 フォント由来の OpenType フォントを通じて古い応用との互換性を維持するための遺物です。 cmap platformID 4 を使って、 非Unicode 応用に対してフォントWindows ANSI符号化されているように見せかけられます。 >>1

[82] Windows ANSI符号化でない Type 1 フォント、 例えばキリル文字中欧フォントは、 過去 Adobe が出荷した際に .PFM ファイルの CharSet 欄を 0 (Windows ANSI) としていました。 ATM for Windows 9xCharSet を無視していました。 >>1

[83] AdobeEncodingStandardEncoding でない Type1 フォントから変換された OpenType フォントにおいて cmap platformID 4 を使います。 >>1

[84] platformID 4encodingID は、 元の Type 1 フォント.PFM ファイルの Windows charset 値 [ 0, 255 ] に設定しなければなりません (must) >>1

[85] platformID 4 encodingID [ 0, 255 ] が CFF アウトラインの OpenType フォントで使われた場合、 Windows NTOTF フォントドライバーは、 次のように動作します。 >>1

[90] cmap符号化は、 CFF符号化同一 (identical) でなければなりません (must) >>1

[80] platformID 4 は、現在広くは用いられていません。 新しいフォントでは使うべきではありません (should not) >>1

[89] cmap 部分表format0, 6 でなければなりません (must) >>1

[91] フォント依存符号化も参照。

各IDの実利用例

[24] 互換性のためか platformID = 0 (Macintosh), encodingID = 0 (MacRoman) で、 0x100, 0x101 だけの cmap 部分表が含まれるフォントがままあります。

[32] Nishiki-tekiplatformID = 0 (Unicode), encodingID = 10 という cmap subtable を持っています。 でも platformID 0 encodingID 10 は Microsoft の仕様書にも Apple の仕様書にも載っていません。

[33] 中身は Unicode のようです。 platformID = 3 (Windows) だと encodingID = 10 が Unicode なので、 それの誤りなのでしょうか。

[34] Makoto Comic にも platformID = 0 (Unicode), encodingID = 10 があります。

言語ID

[130] name では3種類の言語符号の体系が使われています。 cmap ではそのうち1種類 (の変種) が使われています。 なお OpenType の他の場所では他の体系も使われています。 OpenTypeにおける言語


[131] name の項目を表す NameRecordlanguageID言語を表します。

[132] languageID の値の意味は当該 name versionNameRecordplatformID に依存して決まります。 >>121

[141] nameplatformID0 (Unicode) の場合、 languageID 0 を使うことができます。 この値は特定の言語を表しません。 >>121

[143] nameplatformID1 (Macintosh) の場合、 languageID には Macintosh language ID を指定できます。 >>121

[144] nameplatformID3 (Windows) の場合、 languageID には Windows language ID を指定できます。 >>121


[133] nameversion には 01 がありますが、 1 のとき、 IETF言語タグを任意個設定できます。 各 NameRecord はこの言語タグを参照することによって言語を記述できます。 >>121

[134] version 1 では、 languageID0x8000 以上のとき、 言語タグを表すと解釈され、 それ未満のとき、 platformID 依存の言語符号と解釈されます。 >>121

[140] version 0 では、 languageID は原則として 0x8000 未満の値を使わなければなりません (must) >>121

[142] version 0languageID でも、 例外的に、 platformID が [ 240, 255 ] のときは 0x8000 以上の値を使うことが禁止されていません。 >>121

[135] nameplatformID の規定には利用者定義が使えるとは書かれていない (cmap の方にだけ書かれている) のですが、このような規定があるのは謎です。

[137] IETF言語タグを設定したときは、 languageID ではそれを 0x8000, 0x8001, ... といった値で参照できます。 数値は言語タグが記述された順序で割り振られていきます。 >>121

[138] 指定された値に対応する言語タグが存在していないときは、 言語は未知となります。そのような値は使うべきではありません (should not) >>121

[139] OpenType 仕様にしては珍しくエラー処理らしきものが(少しだけ)決められています。 言語が未知ということは、特定の言語の値を探す処理では無視されるべきなのでしょうし、 どんな言語でもいいような処理では受理されるべきなのでしょう。 (未知の言語だから致死的エラーとすることも、必ずしも否定されていませんが... ニュアンスとしてはそれはあまり好ましい挙動ではなさそうです。)

[93] cmap 部分表language文字符号化言語を表します。

[92] platformID 1 (Macintosh) 以外cmap 部分表language は、 0 でなければなりません (must) >>1

[94] platformID 1 (Macintosh) の cmap 部分表language は、

とします。 >>1

[95] Mac OS Roman cmap では、 言語依存の符号化ではありませんから、 0 としなければなりません (must) >>1

[96] Mac OS Turkish cmap では、 TurkishMacintosh language ID17 なので、 language18 とします。 >>1

[105] languageformat 依存の部分表に属しています。 ということは古い Macintosh でしか使われていないこの欄をいつまでも残しておく必要も無さそうなものですが、 新しそうな format でもそのまま引き継がれています。

[106] ただし format 14 には language 欄がありません。この format だけ Unicode に完全に依存している (= language があってもまったく使いようがない) 関係なのでしょうかね。 (他は、少なくても理屈の上では、 Unicode に限定されていないので使い道がないとはいえない。)

cmap

[111] cmap は一部例外を除き、1つの文字 (を表す符号位置ビット組合せ) に対して1つのグリフを与える写像です。

[112] 言語的な理由や文字コード設計の事情で複数の文字を1つのグリフで表したい場合 (合字) や、 書体設計的な事情で1つの文字を複数のグリフで表したい場合には、 cmap だけでは実現できず、 GSUB (または shaping engine による文字前処理) との組み合わせが必要となります。

[56] cmap encodingRecords に含められる EncodingRecord は、 その platformID, encodingID, 部分表language の優先順で整列しなければなりません (must) >>1 ここでの順序数値の小さい順と思われます。

[57] cmap にあっては EncodingRecordplatformID, encodingID, 部分表language の組み合わせは、 高々1回しか出現でき (may) ません。 >>1

[58] 順序が不適切な場合や重複を含む場合にどう処理するべきなのかは定かではありません。 順序を無視する実装もあり得ますし、 求めるものより大きな値が出現したら探索を止める実装もあり得ます。 最初の一致を採る実装も、無作為に選ぶ実装もあり得ます。 エラーにする実装もあり得ます。 主要な実装はどうしているのでしょうか?

[59]部分表は、 format14 の場合を除き、 排他的であります。 つまり応用は、そのうちの1つだけを選び、他を無視するべき (should) です。 >>1

[60] Unicode部分表が含まれる場合で、 16ビットの format のものと 32ビットの format のものが両方含まれるなら、32ビットの部分表に含まれる文字は、 16ビットの部分表に含まれる文字超集合であるべき (should) です。 応用は、 32ビットの部分表を使うべきです (should) >>1

[61] 仕様上は要求されていませんが、常識的に考えて32ビットの部分表のうち [ U+0000, U+FFFE ] の部分と16ビットの部分表が一致しているべきです。

[63] platformID が違い format が同じ Unicode部分表が含まれる場合、 応用はそのいずれを選んでも構いません (may) が、 そのフォントの利用時にどの部分表が選ばれるかは一貫しているべきです (should) >>1

[97] 明示的には定められていませんが、その趣旨からして、 未対応の組み合わせが出現しても、 実装は黙って無視するべきと思われます。

[98] 指定されたすべての組み合わせが未対応の場合にどうするかは定められていません。 エラーとしてまったく受理しない実装もあるかもしれませんし、 黙って他のフォントにフォールバックするような実装戦略もあるかもしれません。

[62] 複数の部分表を含めても応用が使うのは1つだけです。 これによって対応する文字コードが異なるプラットフォームで共通して使えるフォントを提供できるというわけです。 実際に多くのフォントがそうしていますが、 一方で敢えて重複した部分表を含めないフォントもあります。 (format 14 を除けば) もはやプラットフォームの違いによる互換性の問題はおおむね解消しており、 必要だからというより今までそうしてきたからというところが大きそうです。

format

[47] cmap format文字コードからグリフIDへの写像の記述方法を表します。 >>1

[48] 多くの方法が定義されていますが、新しいフォントはそのうちの 4, 12、 用途により 13, 14 が適切です。 それ以外は新しいフォントには推奨されません (not recommended) >>1

[104] いくつかの formatデータ構造上、 矛盾した値を記述することができます。 例えば開始よりも終了が小さな値の範囲を記述できたり、 小さい順に整列と規定されている (が構文上は無視できる) ことがあります。 それらの一部は仕様書上で明確に禁止されています。 しかし禁止されている場合や当然に異常とみなされる場合に、 どう処理するべきかは明確ではありません。 (これは cmap に限らず OpenType 全般でそうです。)

format 0 (1バイト符号)

[4] format = 0 : [ 0x00, 0xFF ] のビット組合せに対応するグリフIDが順番に格納されています。 >>1, >>2

[100] 古い Macintosh ではこれが標準でした。 >>1

[5] 新しい Appleプラットフォームでは必須ではありません。 >>1 今はあまり使われていません。 対応していない実装もあります。

format 2 (1バイトと2バイトの多バイト符号)

[6] format = 2 : 1バイト (8ビット) または2バイト (16ビット) の多バイト符号に対応するグリフIDが順番に格納されています。 >>1, >>2

[99] 記述のないバイトグリフID 0 に対応するものと解釈されます。 >>1

[101] CJK非Unicode多バイト符号に適していました。 シフトJIS型符号

[7] 古い時代に用いられていたもので、今はあまり使われていません。 対応していない実装もあります。

format 4, 6, 12, 10, 13 (16ビット符号と32ビット符号)

[11] 4, 6 は Unicode BMP 用, 12, 10 は Unicode 全体に使われています。

[10] 4, 12 は連続した符号位置グリフIDが割り当てられた密なもの、 6, 10 は疎なものに適したデータ構造になっています。

[28] 6 に対応していない実装もあります。

[16] 10 はあまり使われておらず、 Windows は対応していません。 >>1, >2

[20] 当初 4 が使われ後に 12 が使われるようになった経緯のため、 古い実装は 12 に対応していません。 多くのフォントは 4 と 12 の両方の cmap 部分表を含めているようです。 (そうできると明記されていますが、必須ではありません。 >>1) 古い実装は 4 の方を見るので、 BMP文字だけは使えます。

[64] format46Unicode部分表を同時に含めるべきではありません (should) format1012Unicode部分表を同時に含めるべきではありません (should) 。 これらの場合、 412 を使うべきです (should) >>1

[76] Windows (platformID 3) で Unicode BMP のみ対応するフォントは、 encodingID 1 format 4 部分表を使わなければなりません (must) >>1

[77] Windows (platformID 3) で UnicodeBMP に対応するフォントは、 encodingID 10 format 12 部分表を使わなければなりません (must) >>1

[15] format = 13 は format = 12 の変種。 複数の連続した符号位置の範囲を1つのグリフIDに割り当てる。 >>1, >>2

[18] last-resort font (適当なグリフを用意できないときに代替グリフを提供するためのフォント) 用とされています。 その性質上ほとんど使われておらず、 対応していない実装もあります。

[73] format 13 部分表は、 platformID 0 encodingID 6 でのみ使うべきです (should) >>1


[149] format 4 のとき最後に startCode 0xFFFF, endCode 0xFFFF の segment が必須です。 >>1

[150] 妥当な写像でもそうでもなくても構わない >>1 とされます。 つまり U+FFFF 用のグリフ情報を含めることも、 含めないこともできますが、 どちらの場合も機械的にこの segment が必要となります。


[154] ChromeFirefox も、指定された符号が仕様通り昇順になっていないとき、 構文解析エラーとしてフォントを無視します。 Chrome開発者ツールcmap のエラーである旨のみを表示しますが、 それくらいしか情報がありません。 Firefox開発者ツールに符号の値を表示してくれます。


[164] format 12format 13 の両方があるとき、 ChromeFirefoxformat 13 の方は無視します。 cmap 中の順序は関係ありません。 (format だけによって決まるのか encodingID などでも決まるのかはよく分かりません。)


[114] format 4部分表のサイズ上限を超えるようなフォントを作ろうとすると、 AFDKOmakeotf は最初の2つの segment だけ残して後は捨ててしまいます。 >>113

[115] Windowsメモ帳Microsoft Excelformat 4 が存在すること、という heuristics を実装しています。 それへの対処として、 format 12 を使うときでも format 4 部分表を含めなければなりません。 >>113 (その場合でも format 12 が使われるので、 format 4 は不完全でも存在していればOKらしいです。)

原ノ味フォント 20200516 から、KR のみ format 4 と format 12 に対し、 Unicode コードポイントで一つだけ抜けている (両隣は存在するが該当箇所は存在しない)ものに .notdef を割り当てる加工をしています。 これは、何もしないと format 4 のサイズが 64 KB を超えてしまい、 ttx でのフォント生成が例外で落ちてしまったためです。 format 12 はサイズの問題がないし format 4 の情報もすべて含んだ上位互換なので、 format 4 がなくてもいいだろうと削除してみたら落ちなくなりましたが、 Windows がフォントとして認識してくれません。 仕方なく format 4 の仕様書とにらめっこしてサイズを低減する方法を模索し、 上記の処理を入れました。 なお format 12 も BMP の範囲は format 4 と同じである必要があるため、 BMP 範囲内のみ同じ処理を入れてあります。

原ノ味フォント 20200612 から、 KR で入れていた Unicode コードポイントで一つだけ抜けているものに .notdef を割り当てる加工 をやめ、代わりに Adobe-KR のドキュメントに記載されている format 4 から CJK Unified Ideographs (U+4E00..U+9FFF) と CJK Compatibility Ideographs (U+F900..U+FAFF) のブロックを削除する方法に変更しました。 これは .notdef を割り当てる加工をしていて、 かつ(関係ないはずの) GPOS テーブルが存在すると、 なぜか Windows がフォントを認識してくれないことが分かったためです。 OpenType 仕様的には(というか Windows 向けとしては) format 4 と format 12 の BMP 部分は一致するようにするのが推奨されていますが、 サイズ的に収まらないので仕方がなく Adobe お勧めの対処法に従った処理を行ったものです。

format 8 (16ビットと32ビットの混合符号)

[12] format = 8 : 16ビットまたは32ビットの符号用。 >>1, >>2

[103] 上位が 0x0000 となる32ビット符号に グリフを割り当てることも禁止はされていません。 しかし 0x0000 と上位 0x0000 の32ビット符号の両方にグリフを割り当てることは禁止 (may not) されています。 >>1 そのような場合にどうするべきなのかは不明。

[13] U+10FFFF まで使う Unicode を想定したものでした。

[102] この format はあまり使われていません。 対応していない実装もあります。 非推奨 (discouraged) とされています >>1

format 14 (Unicode 異体列)

[21] format = 14 : UVS 用。 >>1, >>2

[22] 他の format と違って入力が1つの文字 (符号位置) ではなく2つの文字 (符号位置)。 Unicode異体列の専用の仕組みになっています。 (2, 8 の入力は多バイトであっても1文字。 4, 6, 10, 12, 13 も同じ。 4, 6, 8, 10, 12, 13 は Unicode 想定であっても、専用ではない。)

[23] 同じく複数の Unicode文字で1つのものを表現する結合列合字GSUBグリフレベルの操作を使っていますが、 VS だけなぜか専用の仕組みが cmap文字レベルで追加されました。

[25] 異体列に対し「異体選択子なしと同じ」を指定するものと、 グリフIDを指定するものの2種類の指定方法があります。 前者が得られた場合には他の cmap 部分表を使って再探索することになります。

[26] 実際のフォントは前者の方法を使わずすべて後者の方法によるものと、 前者の方法を適宜使うものがあります。 前者を使った方がデータ量はいくらか少なくなるのでしょうが、 グリフ取得が少し遅くなります。 といっても現在の計算機の性能からみればどちらの差分もほとんど誤差みたいなものでしょう。

[27] その誤差みたいな節約のために前者の方法を導入してるのが無駄に思えるのですが、 OpenType の複雑性の中ではそれも誤差みたいな複雑性かもしれませんw

[29] VS日本語蒙古文字の表示には必須の機能ですが、 欧米では必要とされないことや、 比較的歴史の浅い機能であることから、 14 に対応していない実装もあります。

[30] 日本語フォントで多くの文字を含んだものにはよく使われています。

[31] 14 を使わなくても GSUB でも対応できますが (そちらの方が対応してる実装は多いかも知れませんが)、 そのようなフォントがあるのかは不明。

[65] Unicode部分表が使われる場合、 platformID 0 encodingID 5 format 14部分表UVS に対応することができます。 format 14 部分表は、 platformID 0 encodingID 5 でのみ使うべきです (should) >>1

[66] とだけしか定められてはいないのですが、 Unicode部分表がないときは format 14 は使えないということでしょうか。 (実用上それ以外で format 14 を使いたいことはなさそうですが。)

[71] UVS は、cmap format 14 部分表で指定するべき (should) です。 >>1

[72] この「べき」規定の意味するところは不明瞭です。 GSUB による UVS の実装を否定する趣旨と理解していいのでしょうか。

[117] 利用者:emk - GlyphWiki, https://glyphwiki.org/wiki/User:emk#i0

Windows 7でIVSを認識させるには、以下の条件をすべて満たす必要があるようです。

[165] ChromeFirefox も、 異体選択子が0個だとエラーとしてフォントを無視します。 従って1つも VS を含まないフォントでは format 14 部分表全体を省かなければなりません。

[155] 仕様書上は特に制限されているようには読めませんが、 ChromeFirefox異体選択子以外の符号位置が書かれていると、 cmap の構文解析エラーとしてフォントを無視します。

[156] Chrome でも Firefox でも漢字 + 通常 SVS, 漢字 + IVS はうまく動作しますが、 漢字 + 蒙古文字自由異体選択子は動作しません。

format の実利用例

[3] GitHub - nixeneko/nxTokiACF, https://github.com/nixeneko/nxTokiACF

format = 0, 4

[19] Release Version 14.000 Release · unicode-org/last-resort-font · GitHub, https://github.com/unicode-org/last-resort-font/releases/tag/14.000

LastResort-Regular.ttf は 7.89MB のフォントformat = 12 と format = 4 (空)。

LastResortHE-Regular.ttf は 506KB のフォントformat = 13 (platformID 3, encodingID 10), format = 4 (platformID 3, encodingID 1) (空)。

(ファイルサイズの違いは format の違いに起因するものではない。)

グリフID

[46] cmap では、 フォント中に対応するグリフを持たない文字コードグリフID 0写像するべきです (should) >>1 グリフID

[151] この規定と関係するのかどうか、実装によっては cmapグリフID 0 に対応付けるように設定しても、無視される (ように見える) ことがあります。 それが仕様通りの動作なのかどうかはよくわかりません。

[152] グリフID 0 のとき未実装とみなして他のフォントフォールバックしているのかもしれません。

[153] Chromeformat 13フォントで全符号位置グリフID 0 にしても、エラーにはなりませんが、そのグリフは使われずに他のフォントで表示されます。 フォント内のグリフ0 1個だけではだめなのかと他のグリフを入れてみても変わりません。 グリフID 0 以外に設定すればちゃんと使われるので、 グリフID 0 を使ったことに起因するのは間違いありません。

処理

[107] cmap文字のレンダリングのためにフォントグリフを取得する過程の1つとして参照されます。 文字のレンダリング

[108] cmap写像を引く入力となる文字コードは、 必ずしも情報交換に使う Unicode文字列を構成するUnicode符号位置の列そのものではないことに注意が必要です。

[109] bidi に関係して鏡像化のための符号位置の書き換えが事前に発生していることがあります。 書字方向依存グリフ

[110] その他 shaping に属する前処理で符号位置の変更が事前に発生していることがあります。 shaping engine

関連

[3] TrueTypecmapCIDFontCMap は、 似たような用途ですが、 技術的にはまったくの別物です。 正式な表記は大文字と小文字で区別できますが、 俗に cmap, CMAP, CMap と混用されているので、文脈で注意して区別するしかありません。

[35] OpenType glyph processing (part 2) - Typography | Microsoft Docs, alib-ms, https://docs.microsoft.com/ja-jp/typography/develop/processing-part2#cmap-table

[36] >>35 公式ドキュメントですが、ここでは CMAP になっています。 cmap にしないと正常動作しないと思いますが、どうなんでしょう。

メモ

[37] Character-level mirroring では cmap で得られる値が 0 か検査します。

[161] 開発者ツールで見られるエラーは Chrome より Firefox の方が親切です。

[162] gecko-dev/gfx/ots/src/cmap.cc at master · mozilla/gecko-dev · GitHub, https://github.com/mozilla/gecko-dev/blob/master/gfx/ots/src/cmap.cc

[163] そしてエラーのより詳しい意味は >>162 のソースを見るとわかります。