32
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TATEditorAdvent Calendar 2016

Day 18

FreeTypeの使い方

Posted at

FreeTypeとは

FreeTypeはフォント描画ライブラリです。
フォントファイルのファイルパス/ファイルデータを読み込んで、指定された文字のビットマップやそれに付随する情報を取得することができます。
C言語で書かれているため、様々なOSで動かすことができます。
(少なくともWindows, macOS, Ubuntu, Android, iOSでは動作しました)

FreeTypeの準備

  1. ビルドする
    • カラー絵文字(PNG)を読み込む場合
      • ftoption.h#define FT_CONFIG_OPTION_USE_PNGを有効にする
      • この場合はlibpngが必要になる(インクルードディレクトリに追加)
    • WindowsならVisual Studioのプロジェクトファイルを使えばOK
    • 他のデスクトップOSならautogen.shとかconfigureとかmakeで普通にビルドできるはず
    • iOSとmacOSなら適当にXcodeプロジェクトを作って.cファイルを追加するだけもOK
    • AndroidならCMakeFile.txtに必要な.cファイルを追加する
      • ビルドに必要な.cはVisual Studioのプロジェクトを見ればわかる気がする
  2. 作成するプログラムのプロジェクトから
    • インクルードディレクトリを追加
    • スタティックライブラリをリンクする
      • カラー絵文字(PNG)を使う場合はlibpngもリンクする

FreeTypeの利用

一番使いたい関数を探しやすいのはここかな。
FreeTypeの基本的な使い方は以下のとおり。

  1. includeする
    • #include <ft2build.h>
      • まずincludeするべきはこれ
    • #include FT_FREETYPE_H
      • 他のヘッダは上みたく#defineされてる
      • 必要なものを適宜includeする
  2. FT_Library library;を初期化する
    • FT_Init_FreeType(&library)する
    • libraryはFreeTypeを使っている間はずっと使用します
  3. FT_Face face;を用意する
    • FT_New_Face(library, font_path, font_index, &face)
      • フォントのパスから作成する
    • FT_New_Memory_Face(library, font_data_memory, font_data_length, font_index, &face)
      • メモリ上のフォントデータから作成する
    • ここでfont_indexttcotcの場合に読み込まれるフォントを指定するもの
    • ひとつのlibraryで複数のfaceを持てる
  4. 用意したfaceを使って色々する
    • グリフを取得するとか
  5. FT_Face face;を破棄する
    • FT_Done_Face(face)
  6. FT_Library library;を破棄する
    • FT_Done_FreeType(library)

フォントファイルの取得方法

フォントファイルは大抵の場合、どこかのフォルダにまとめて格納されています。
ただ、そうしたフォントファイルの管理はOSに密に結びついていることが多いです。
そのため、その場所を知るためのクロスプラットフォームな方法は存在しません。
おや、IMEのときにも似たようなことが……?
素晴らしき世界(文字列周りの平常運行)。

  • Windowsではパスを取得するのが穏便な方法(DirectWrite以降)
    • それよりも前のOSならバイナリを取得しましょう
      • ただしMacTypeというソフトによって動かなくなります
  • macOSではメモリ上に頑張ってフォントファイルを組み上げる
    • フォントテーブルごとに取得して結合して綺麗にする
  • Ubuntuなどではパスを取得
    • Fontconfigというものがありましてね

FreeTypeのサンプル

基本的に必要なことは3つくらいです。

  • グリフのIDを取得する
  • ビットマップグリフを取得する
  • アウトライングリフを取得する

他にもアウトラインを変形したり、描画オプションを指定したりといったこともできますが些細なことです。

グリフIDの取得

cmapをいい感じに読み込んで変換してくれます。
GID 0が返ってきた場合は見つからなかった場合です。
複数のフォントを使用していないならGID 0をそのまま使えばOKです。

  • Unicodeのコードポイントから
    • FT_Get_Char_Index(face, unicode)
  • UVSが付いている場合
    • FT_Face_GetCharVariantIndex(face, unicode, uvs)
    • 0が返ってきたらFT_Get_Char_Index(face, unicode)にフォールバックする

ビットマップグリフを取得する

  1. FT_Select_Size(face, size_index)
    • size_indexface->available_sizesと欲しいサイズをみて決める
  2. FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT)
    • このときface->glyph->format == FT_GLYPH_FORMAT_BITMAPなら埋め込みビットマップ
    • face->glyph->bitmapに(多くの場合モノクロの)ビットマップが入ってる

ビットマップグリフ(カラー絵文字)を取得する

  • 上の2.でFT_Load_Glyph(face, gid, FT_LOAD_DEFAULT | FT_LOAD_COLOR)する
    • FT_LOAD_COLORを追加されてる
    • このときface->glyph->format == FT_GLYPH_FORMAT_BITMAP && face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRAならカラー絵文字(PNG)
    • face->glyph->bitmapにBGRAビットマップが入ってる

アウトライングリフを取得する

  • 生のアウトラインデータを取得する場合
    • FT_Load_Glyph(face, gid, FT_LOAD_NO_SCALE | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_BITMAP)
    • Composite GlyphはFreeTypeが処理してくれる
  • 適切なサイズにスケーリング・ヒンティングしたものを取得する場合
    1. FT_Set_Pixel_Sizes(f->face, width, height)
    2. FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP)
      • face->glyph->outlineにアウトラインが入ってる
    3. (オプション)face->glyph->outlineをラスタライズする
      • FT_Render_Glyph(face->glyph, FT_RENDER_MODE_LCD)
      • FT_RENDER_MODE_LCDFT_RENDER_MODE_NORMAL等、適切なものを選ぶ

おわりに

さて、とても簡単にFreeTypeのコードの基本的な使い方について書きました。
ちなみに、縦書きをFreeTypeで適切に扱うのは難しいです。頑張ってください。

明日はICUかwxWidgetsについて書きます(多分)。

32
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?