スポンサーリンク

FreeType2でフォントファイルのSFNT Nameを読んでフォント名などを取り出す(1)

例えば “meiryo.ttc”から「メイリオ」、”msmincho.ttc”から「MS 明朝」などを取得する。

フォントファイル(ttfやttcなど)の中にはsfntテーブルというのがあり、そこにコピーライト、バージョン、フォントファミリ名などが格納されている。

具体的に情報が入っているのはFT_SfntName::string という変数(文字列)なので、これを取り出すことを考える。

方法

1.データの取得

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を処理


 }

2.データの種類の特定

上記、sfnt_name変数にデータをとれたので、その情報が何を表しているか(コピーライトかフォント名かなど)を特定する。

platform_id

まず、プラットフォームという括りでデータが分けられている。

プラットフォーム==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

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に対して走らせると、以下のように表示される。

これは著作権表記
これはフォント名
これはバージョン
これは著作権表記
これはフォント名
これはバージョン

なぜ各項目が二つもあるのか。これはその情報が文字列で格納されているのだが、その言語ごとに入っているからだ。

language_id

最終的に求めるのが 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に対して走らせると、以下のように表示される。

これは著作権表記 TT_MS_LANGID_ENGLISH_UNITED_STATES (0x0409)
これはフォント名 TT_MS_LANGID_ENGLISH_UNITED_STATES (0x0409)
これはバージョン TT_MS_LANGID_ENGLISH_UNITED_STATES (0x0409)
これは著作権表記 TT_MS_LANGID_JAPANESE_JAPAN (0x0411)
これはフォント名 TT_MS_LANGID_JAPANESE_JAPAN (0x0411)
これはバージョン TT_MS_LANGID_JAPANESE_JAPAN (0x0411)

encoding_id

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に対して走らせると、以下のように表示される。

これは著作権表記 (英語) TT_MS_ID_UNICODE_CS (1)
これはフォント名 (英語) TT_MS_ID_UNICODE_CS (1)
これはバージョン (英語) TT_MS_ID_UNICODE_CS (1)
これは著作権表記 (日本語) TT_MS_ID_UNICODE_CS (1)
これはフォント名 (日本語) TT_MS_ID_UNICODE_CS (1)
これはバージョン (日本語) TT_MS_ID_UNICODE_CS (1)

string, string_len

ようやくデータを取り出せる。

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());
}
これは著作権表記 (英語) c 2019 Microsoft Corporation. All Rights Reserved.
これはフォント名 (英語) Meiryo
これはバージョン (英語) Version 6.50
これは著作権表記 (日本語) c 2019 Microsoft Corporation. All Rights Reserved.
これはフォント名 (日本語) メイリオ
これはバージョン (日本語) Version 6.50

参考:

https://freetype.org/freetype2/docs/reference/ft2-sfnt_names.html

所感

疲れた。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: