Я тоже пережил этот кошмар много лет назад, и теперь я много знаю обо всем этом. Я подумал, что должен ответить и дать несколько ответов.
1) Вы не можете предполагать, что «loca» следует за «cmap». Порядок может варьироваться в зависимости от шрифта. Расположение каждого блока определяется OffsetTable, который обычно начинается с байта 0 файла шрифта. (http://www.microsoft.com/typography/otspec/otff.htm)
2) Вы не можете предполагать, что «идентификатор кодировки заголовка cmap равен 0, по крайней мере, в формате TTF 4» означает символьные шрифты. Я точно знаю, что некоторые старые арабские шрифты также используют эту кодировку. На сегодняшний день я до сих пор не знаю, как их дифференцировать. Винда делает это но я не знаю как. Я не знаю, как точно знать, что шрифт является символьным шрифтом. Даже проверки таблицы OS / 2 на бит 32 кодовой страницы недостаточно во многих случаях.
3) Вы не можете просто использовать магический номер 0xF000 и добавить его к своему маленькому 0-255 числу, чтобы получить символ, который даст вам отображение глифа, которое вы ищете. Это связано с тем, что эти небольшие коды ASCII от 0 до 255 будут различаться в зависимости от языкового стандарта вашей системы.
Шрифт символов - это особый способ их обработки в Windows.
В отличие от обычного шрифта, в котором сопоставление между глифами и символами является статическим, сопоставление шрифтов символов зависит от системной кодовой страницы по умолчанию для приложения, не являющегося кодировкой Unicode, или CP_ACP.
Например, представьте, что ваш шрифт символа имеет следующий символ: «%». Если в вашей системе по умолчанию используется CP 1252, то для рендеринга этого глифа вам, например, необходимо отобразить значение символа '0xC2'.
Если в вашей системе по умолчанию используется CP 1251, то для рендеринга этого глифа вам, например, необходимо отразить значение символа '0x416', которое совершенно другое.
Иначе говоря, диапазоны Юникода шрифта варьируются в зависимости от кодовой страницы, не являющейся кодировкой Юникода по умолчанию!
После исследования мы обнаружили, что действительными символьными значениями для шрифтов являются значения, полученные путем преобразования 0–255, если они были значением CP_ACP в Unicode.
Что это значит? Это означает, что вы хотите использовать MultiByteToWideChar с CP_ACP, чтобы получить сопоставление значений от 0 до 255 с их локализованным значением Юникода в зависимости от языкового стандарта вашей системы (CP_ACP).
Таким образом, это даст вам карту типа:
ASCII -> localized non-static UNICODE
0x00 -> 0x00
0x01 -> 0x01
0x02 -> 0x02
...
0xC2 -> 0x416 <----- This is correct : the value will be different in some cases.
...
0xE3 -> 0xE3
Значения от 0xF000 до 0xF0FF являются статическими значениями UNICODE: они никогда не меняются.
Таким образом, чтобы получить идентификатор глифа для «локализованного нестатического UNICODE», сначала вы используете свою карту выше, чтобы найти соответствующее значение ASCII, а затем добавляете к ней 0xF000, а затем получаете идентификатор глифа для этого.
Конечно, это бессмысленное не задокументировано MS ... или я никогда не смог бы его найти.