icuライブラリのU16_NEXTでコードポイントを取得できる。
#include <unicode/ubrk.h> #include <unicode/ustring.h> #ifdef _DEBUG // デバッグ時リンク #pragma comment(lib, "icuucd.lib") #pragma comment(lib, "icuind.lib") #else // リリース用リンク #pragma comment(lib, "icuuc.lib") #pragma comment(lib, "icuin.lib") #endif // Utf16文字列からUtf32文字列に変換 std::u32string u16_to_u32(const char16_t* u16str) { UErrorCode status = U_ZERO_ERROR; // イテレータ作成 UBreakIterator* bi = ubrk_open(UBRK_CHARACTER, nullptr /*文字単位の処理にロケールは不要*/, nullptr, 0, &status); if (U_FAILURE(status)) { return U"";// エラーが発生 } int32_t utf16Length = wcslen((wchar_t*)u16str); // テキストを設定 ubrk_setText(bi, (const UChar*)u16str, utf16Length, &status); if (U_FAILURE(status)) { ubrk_close(bi); return U"";// エラーが発生 } std::u32string ret32; // 文字境界を使ってUTF-16からUTF-32に変換 int32_t start = ubrk_first(bi); // 文字列(utf16)の最後までループ for (int32_t end = ubrk_next(bi); end != UBRK_DONE; start = end, end = ubrk_next(bi)) { int32_t i = start; while(i < end) { UChar32 c32; // ① u16str[i] 以降の文字を一文字コードポイントに変換してcに格納 // ② iを次の文字の位置に進める U16_NEXT(u16str, i, utf16Length, c32); // コードポイントを保存 ret32.push_back(c32); } } // 終了処理 ubrk_close(bi); return ret32; };
変換したところで結果を確認するまともな方法(エディタなど)が少ないので、先に作っておいた前回の render_by_font を使い、結果を出力する。
std::u32stringをFreeType2+HarfBuzzで描画する処理を関数化
#include"u16_to_u32.hpp" int main() { FT_Library library; // handle to library FT_Error error; error = FT_Init_FreeType(&library); if (error) return -1; // HarfBuzzのオブジェクト作成 hb_buffer_t* hbbuf; hbbuf = hb_buffer_create(); ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 出力先を作成 Image image(300, 150); ///////////////////////////////////////////// FaceInfo faces[3] = { FaceInfo( my_LoadFonts(library, "C:\\Windows\\Fonts\\msgothic.ttc"), HB_SCRIPT_HIRAGANA, "jp" ), FaceInfo( my_LoadFonts(library, "C:\\Windows\\Fonts\\seguiemj.ttf"), HB_SCRIPT_HIRAGANA, "jp" ), FaceInfo( my_LoadFonts(library, "C:\\Windows\\Fonts\\Times.ttf"), HB_SCRIPT_LATIN, "en" ) }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// { std::u32string text32 = u16_to_u32(u"あ゙いう"); render_by_font( &image, faces[0].face, text32.c_str(), faces[0].script, hbbuf, faces[0].hbfont, faces[0].lang.c_str() ); pbmP1_Write("freetypetest_jp.pbm", image.imageWidth, image.imageHeight, &image.image[0]); } { std::u32string text32 = u16_to_u32(u"👨👨👧👦"); render_by_font( &image, faces[1].face, text32.c_str(), faces[1].script, hbbuf, faces[1].hbfont, faces[1].lang.c_str() ); pbmP1_Write("freetypetest_mj.pbm", image.imageWidth, image.imageHeight, &image.image[0]); } { std::u32string text32 = u16_to_u32(u"àbâáăã"); render_by_font( &image, faces[2].face, text32.c_str(), faces[2].script, hbbuf, faces[2].hbfont, faces[2].lang.c_str() ); pbmP1_Write("freetypetest_la.pbm", image.imageWidth, image.imageHeight, &image.image[0]); } for(auto& f : faces){ f.Delete(); } ///////////////////////////////////////////// ///////////////////////////////////////////// ///////////////////////////////////////////// // HarfBuzzのオブジェクト破棄 hb_buffer_destroy(hbbuf); // FreeType2の解放 FT_Done_FreeType(library); }