FreeType2をインストールして使ってみる

OSXfreetypeを使った手順について。
※環境はMacOSX10.7、freetype2.4.6です。他にbzip2-v1.0.6、zlib1.2.5も用意しておきます。
※ビルドした静的ライブラリをインストールせずに持ち運んで使ってみます

freetype2のビルド

http://freetype.sourceforge.net/index2.htmlからDownloads stable release を選択>
http://sourceforge.net/projects/freetype/files/からfreetype-2.4.6.tar.bz2をダウンロードして展開します。展開したディレクトリに移動してターミナルで以下のコマンドを実行

./configure
make

objs/.libs/libfreetype.a、libfreetype.6.dylibが作成されています。

Xcodeで利用する

C++のCommandLineToolsプロジェクトを作成します。(例えば//Sample.xcodeproj)
ライブラリとヘッダをコピーします。
//lib/libfreetype.a
//include/ft2build.h
//include/freetype (internalディレクトリは不要)
Link Binary With Librariresでlibfreetype.aをプロジェクトに追加
Search Paths>Search Header PathとLibrary Pathでインクルードパスとライブラリパスをプロジェクトに追加
この時点でmain.cppで適当に関数を呼んでビルドすると、以下のようなリンクエラーになります。

Undefined symbols for architecture x86_64:
  "_inflateInit2_", referenced from:
      _FT_Stream_OpenGzip in libfreetype.a(ftgzip.o)
  "_inflateEnd", referenced from:
      _FT_Stream_OpenGzip in libfreetype.a(ftgzip.o)
      _ft_gzip_stream_close in libfreetype.a(ftgzip.o)
  "_inflate", referenced from:
      _ft_gzip_file_fill_output in libfreetype.a(ftgzip.o)
  "_inflateReset", referenced from:
      _ft_gzip_file_io in libfreetype.a(ftgzip.o)
  "_BZ2_bzDecompressInit", referenced from:
      _FT_Stream_OpenBzip2 in libfreetype.a(ftbzip2.o)
      _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o)
  "_BZ2_bzDecompressEnd", referenced from:
      _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o)
      _ft_bzip2_stream_close in libfreetype.a(ftbzip2.o)
  "_BZ2_bzDecompress", referenced from:
      _ft_bzip2_file_fill_output in libfreetype.a(ftbzip2.o)
ld: symbol(s) not found for architecture x86_64

zlibが足りないので、ビルドして作成したlibz.aを//lib/にコピー、Link Binary With Librariesでターゲットに追加します。これでもまだエラーが出たままなので、さらにbzip2を追加します。

  "_BZ2_bzDecompressInit", referenced from:
      _FT_Stream_OpenBzip2 in libfreetype.a(ftbzip2.o)
      _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o)
  "_BZ2_bzDecompressEnd", referenced from:
      _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o)
      _ft_bzip2_stream_close in libfreetype.a(ftbzip2.o)
  "_BZ2_bzDecompress", referenced from:
      _ft_bzip2_file_fill_output in libfreetype.a(ftbzip2.o)
ld: symbol(s) not found for architecture x86_64

libbzip2.aをビルドして、Link Binary With Librariesでターゲットに追加
さらに//include/bzlib.hをコピー
これでエラーがなくなります。

FreeType2を使ってみる

正確な情報はこちらを参照してください。↓
http://freetype.sourceforge.net/freetype2/docs/tutorial/step1.html

ヘッダのインクルード

下の2つのヘッダをインクルードします。(FT_FREETYPE_Hはヘッダのパスを定義したマクロ)

#include <ft2build.h>
#include FT_FREETYPE_H
初期化

ライブラリを表すFT_Libraryオブジェクトに対してFT_Init_FreeTypeを実行します。ここではFT_Libraryをグローバルに保持しておきます。FreetypeAPIはFT_Error型のエラーコードがかえってきます。エラーが無い場合はFT_Err_Okです。

FT_Library  s_library;
int main{
    FT_Error error = FT_Init_FreeType( &s_library );
フォント読み込み

適当なフォントを用意しておいて、FT_New_Faceを実行します。引数にFT_Face型のfaceオブジェクトを渡します。こちらもグローバルに定義しておきます。

FT_Face     s_face
int main(){
   //  略
error = FT_New_Face( s_library, "/yourFontPath/MyFavoriteFont.ttf", 0, &s_face );

※フォントの場所はOSXのバージョンによって異なる。v10.7では/Libary/Fonts内にあります。

文字サイズを設定する
error = FT_Set_Char_Size( s_face,
            0, 
            16*64,  // 幅と高さ
            300,      // 水平解像度
            300 );    // 垂直解像度
字体を作成する

まずFT_Get_Char_Indexでアスキーコードに対応する字体番号を取得します。文字が用意されていないなら0がかえります。この番号を渡してFT_Load_Glyphを呼ぶと実際に字体が取得されます。取得した字体をレンダリングするにはFT_Render_Glyphを呼び出します。これで内部にレンダリングされたビットマップが作成されています。ちなみに字体の各パラメータはFT_Face構造体のglyphメンバ(FT_GlyphSlot型)に保存されます。

glyph_index = FT_Get_Char_Index( s_face, 'q' );
error = FT_Load_Glyph( s_face, glyph_index, FT_LOAD_DEFAULT );
FT_GlyphSlot slot = s_face->glyph;
error = FT_Render_Glyph( slot, FT_RENDER_MODE_NORMAL );

リンダリングの種類を選ぶこともできます。(FT_RENDER_MODE_NORMALはRGB, FT_RENDER_MODE_MONOが2値画像など)

ビットマップを取り出す

FT_GlyphSlotのbitmapメンバ(FT_Bitmap型)でビットマップを取り出します。FT_Bitmapのbufferメンバがバッファのアドレスになります。

FT_GlyphSlot slot = s_face->glyph;
if( slot->format != FT_GLYPH_FORMAT_BITMAP ) // error
FT_Bitmap bitmap = slot->bitmap;
// ビットマップの情報を取り出す
width = bitmap.width;
height = bitmap.rows;
rawData = bitmap.buffer;

あとは画像データを出力したりテクスチャに利用することができます。

グリフの情報を取り出す

描画位置の補正値やペンの動きなども取得できます。

FT_GlyphSlot slot = s_face->glyph;
slot->bitmap_left; // x + slot->bitmap_left , y + slot->bitmap_topに描画すればOK
slot->bitmap_top; //
int advanceX = slot->advance.x >> 6; // x方向にペンを動かすべき距離
int advanceY = slot->advance.y >> 6; // y方向にペンを動かすべき距離

※その他、追記するかもしれません