FreeType の異体字セレクタ機能を使用
OpenType フォントのcmapテーブルに platform: 0, encoding: 5 のテーブルがあれば、異体字[1]のための別のグリフを利用できるかもしれない。文字のデータベースもある[4]。
1: http://www.unicode.org/reports/tr37/
4: http://www.unicode.org/ivd/
対応はフォントに依存する。
FreeType (2.3.6 以降)ではGSUBやGPOSテーブルをサポートしていないものの、cmap によるグリフ選択をサポートしている[2]。
2: http://www.freetype.org/freetype2/docs/reference/ft2-glyph_variants.html
今回は Mgen+ [3] フォントを使用する。
3: http://jikasei.me/font/mgenplus/
利用可能なセレクタを取得
FT_Face_GetVariantSelectors でフォント中で定義されている利用可能なセレクタの一覧を取得できる。
#include <iostream> #include <freetype/ft2build.h> #include FT_FREETYPE_H int main() { FT_Library ft; FT_Face face; FT_Init_FreeType(&ft); FT_New_Face(ft, "/home/asuka/.fonts/mgenplus-1m-regular.ttf", 0, &face); FT_Set_Char_Size(face, 0, 16 << 6, 96, 96); FT_UInt32* pSelectors = FT_Face_GetVariantSelectors(face); while (*pSelectors) std::cout << std::hex << "0x" << *pSelectors++ << std::endl; /* Result: 0xe0100 0xe0101 0xe0102 0xe0103 0xe0104 0xe0105 0xe0107 */ FT_Done_Face(face); FT_Done_FreeType(ft); }
このフォントでは7種類のセレクタが利用できる。
指定したコードポイントで利用可能なセレクタを取得
お嬢様で有名な芦屋[1]から、そのコードポイントに対して利用可能なセレクタを取得する。
FT_ULong c = static_cast<FT_ULong>(L'芦'); FT_UInt32* pSelectors = FT_Face_GetVariantsOfChar(face, c); while (*pSelectors) std::cout << std::hex << "0x" << *pSelectors++ << std::endl; /* Result 0xe0100 0xe0101 0xe0102 0xe0103 */
セレクタごとに利用できるコードポイント一覧
指定したセレクタに対して定義されているコードポイントが取得できる。
int length = 0; FT_UInt32* pSelectors = FT_Face_GetVariantSelectors(face); while (*pSelectors++) length++; FT_UInt32* p = new FT_UInt32[length+1]; memcpy(p, pSelectors - length -1, sizeof(FT_UInt32) * length); p[length] = 0; while(*p) { std::cout << std::hex << "Selector: 0x" << *p << std::endl; std::cout << "----" << std::endl; FT_UInt32* pCodePoints = FT_Face_GetCharsOfVariant(face, *p++); while (*pCodePoints++) std::cout << std::hex << "0x" << *pCodePoints++ << std::endl; std::cout << "----" << std::endl; }
FT_Face_GetVariantSelectors 関数の呼び出し結果の配列は次の FreeType 関数の呼び出しで破壊される可能性があるため、コピーして利用する。
異体字のためのグリフインデックスを取得
FT_ULong c = static_cast<FT_ULong>(L'芦'); FT_UInt gindex = FT_Face_GetCharVariantIndex(face, c, 0xE0103); if (gindex == 0) { gindex = FT_Get_Char_Index(face, c); } FT_Load_Glyph(face, gindex, FT_LOAD_RENDER);
グリフインデックスが0の場合は普通の方法でグリフインデックスを取得し直す。