例えば "meiryo.ttc"から「メイリオ」、"msmincho.ttc"から「MS 明朝」などを取得する。
フォントファイル(ttfやttcなど)の中にはsfntテーブルというのがあり、そこにコピーライト、バージョン、フォントファミリ名などが格納されている。
具体的に情報が入っているのはFT_SfntName::string という変数(文字列)なので、これを取り出すことを考える。
sfntテーブルには項目がたくさんあるので、FT_Get_Sfnt_NameCountで項目数を取得してからFT_Get_Sfnt_Nameでi番目の情報を取得する。
// テーブル内の項目数を取得 FT_Int count = FT_Get_Sfnt_Name_Count(face); // 取得した項目をここへ格納 FT_SfntName sfnt_name; // すべての項目を読み込む for (FT_Int i = 0; i < count; i++) { // 取得 FT_Get_Sfnt_Name(face, i, &sfnt_name);
// sfnt_nameを処理
}
上記、sfnt_name変数にデータをとれたので、その情報が何を表しているか(コピーライトかフォント名かなど)を特定する。
まず、プラットフォームという括りでデータが分けられている。
プラットフォーム==Microsoft , フォント名 == メイリオ
プラットフォーム==MAC , フォント名==メイリオ
プラットフォーム==Apple , フォント名==メイリオ
みたいな構造をしている。なのですべてのプラットフォームを見てしまうと情報が重複するので、例えばMicrosoftだけに絞って見たほうがいい。
プラットフォームの種類はマクロで定義されているので、その一覧でswitchする。
プラットフォームの定義: https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_platform_xxx
// 取得 FT_Get_Sfnt_Name(face, i, &sfnt_name); switch (sfnt_name.platform_id) { case TT_PLATFORM_APPLE_UNICODE: // 処理 break; case TT_PLATFORM_MACINTOSH:: // 処理 break; case TT_PLATFORM_ISO:: // 処理 break; case TT_PLATFORM_MICROSOFT:: // 処理 break; case TT_PLATFORM_CUSTOM:: // 処理 break; case TT_PLATFORM_ADOBE:: // 処理 break; }
name_idには情報の種類が定義されている。これで、上記sfnt_nameに入っているデータがフォント名かコピーライトかの区別ができる。
name_idの定義:https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_name_id_xxx
FT_Get_Sfnt_Name(face, i, &sfnt_name); switch (sfnt_name.platform_id) { case TT_PLATFORM_MICROSOFT:
switch (sfnt_name.name_id) { case TT_NAME_ID_FULL_NAME: printf("これはフォント名\n"); break; case TT_NAME_ID_VERSION_STRING: printf("これはバージョン\n"); break; case TT_NAME_ID_COPYRIGHT: printf("これは著作権表記\n"); break; }
break; default: // 今はMicrosoft以外のプラットフォームは考えない break; }
このプログラムをmeiryo.ttcに対して走らせると、以下のように表示される。
なぜ各項目が二つもあるのか。これはその情報が文字列で格納されているのだが、その言語ごとに入っているからだ。
最終的に求めるのが FT_SfntName::string という文字列なのだが、ここに何語で格納されているかという情報がlanguage_idに入っている。そこで言語による切り替えをしてみる。
なおlanguage_idの定義はplatform_idによって分かれている。
platform_idがTT_PLATFORM_MACINTOSHの場合
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_mac_langid_xxx
platform_idがTT_PLATFORM_MICROSOFTの場合
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_ms_langid_xxx
FT_Get_Sfnt_Name(face, i, &sfnt_name); bool target = true; switch (sfnt_name.platform_id) { case TT_PLATFORM_MICROSOFT: switch (sfnt_name.name_id) { case TT_NAME_ID_FULL_NAME: printf("これはフォント名 "); break; case TT_NAME_ID_VERSION_STRING: printf("これはバージョン "); break; case TT_NAME_ID_COPYRIGHT: printf("これは著作権表記 "); break; default: target = false; break; } if (target == true) {
FT_UShort langID = sfnt_name.language_id; switch (langID) { case TT_MS_LANGID_ENGLISH_UNITED_STATES: printf("TT_MS_LANGID_ENGLISH_UNITED_STATES (0x%04x)", langID); break; case TT_MS_LANGID_JAPANESE_JAPAN: printf("TT_MS_LANGID_JAPANESE_JAPAN (0x%04x)", langID); break; }
puts(""); } break; default: // 今はMicrosoft以外のプラットフォームは考えない break; }
このプログラムをmeiryo.ttcに対して走らせると、以下のように表示される。
FT_SfntName::string は言語ごとに入っているといった。これが「同じ項目が複数ある理由」である。
language_idはデータを整理するうえでは重要だが、データを人間が読める形にするためにはあまり意味をなさない。データを実際に取り出すには、encoding_idで分岐する必要がある。
今回は諸事情によりmeiryo.ttcを使うがこの中にはエンコードが一つしかない。
あと、エンコードの一覧もplatform_idごとに分かれている。
TT_PLATFORM_APPLE_UNICODE
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_apple_id_xxx
TT_PLATFORM_MACINTOSH
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_mac_id_xxx
TT_PLATFORM_ISO
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_iso_id_xxx
TT_PLATFORM_MICROSOFT
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_ms_id_xxx
TT_PLATFORM_ADOBE
https://freetype.org/freetype2/docs/reference/ft2-truetype_tables.html#tt_adobe_id_xxx
FT_Get_Sfnt_Name(face, i, &sfnt_name); bool target = true; switch (sfnt_name.platform_id) { case TT_PLATFORM_MICROSOFT: switch (sfnt_name.name_id) { case TT_NAME_ID_FULL_NAME:printf("これはフォント名 ");break; case TT_NAME_ID_VERSION_STRING:printf("これはバージョン ");break; case TT_NAME_ID_COPYRIGHT:printf("これは著作権表記 ");break; default: //それ以外の項目は考えない target = false; break; } if (target == true) { FT_UShort langID = sfnt_name.language_id; switch (langID) { case TT_MS_LANGID_ENGLISH_UNITED_STATES:printf("(英語)");break; case TT_MS_LANGID_JAPANESE_JAPAN:printf("(日本語)");break; default: //それ以外の言語は考えない break; }
FT_UShort encID = sfnt_name.encoding_id; switch (encID) { case TT_MS_ID_UNICODE_CS: printf(" TT_MS_ID_UNICODE_CS (%d)", encID); break; default: //それ以外のエンコードは考えない break; }
puts(""); } break; default: // 今はMicrosoft以外のプラットフォームは考えない break; }
このプログラムをmeiryo.ttcに対して走らせると、以下のように表示される。
ようやくデータを取り出せる。
FT_SfntName::string にはフォント名などが文字列で入っている
FT_SfntName::string_len にはFT_SfntName::stringのサイズがバイト数で入っている。
注意点は、encoding_idがTT_MS_ID_UNICODE_CSの場合、UTF16BEで入っていてwindowsだとそのまま表示できないのでLEに変換してやる必要がある。
FT_UShort encID = sfnt_name.encoding_id; switch (encID) { case TT_MS_ID_UNICODE_CS: { std::wstring wstr; for (size_t i = 0; i < sfnt_name.string_len; i += 2) { char16_t w = *((char16_t*)&sfnt_name.string[i]); // UTF16BEなので2バイトを反転する unsigned char* p = (unsigned char*)&w; std::swap(p[0], p[1]); wstr += w; } printf(" %ls", wstr.c_str()); }
https://freetype.org/freetype2/docs/reference/ft2-sfnt_names.html
疲れた。