レイヤー編の続きでも書こうと思っていましたが、こっちを先に書いておこうかと思ってこっちにしました。
テキストの描画ルーチンはだいたい次の方法を使って描画します。
- TextOut関数、ExtTextOut関数を使ってHDCに直接出力する
- GetGlyphOutline関数で一文字ずつ文字情報を受け取って自前でサーフェイスに出力する
- DirectXのテキスト出力インターフェイスを使ってテクスチャに描画する
で、ライブラリを完全にUNICODE対応させようかな~と文字描画系の処理をいじっていてちょっと思ったのが、
「UNICODEのサロゲートペアの文字はどうやってGetGlyphOutlineに渡すのか?」
という問題でした。TextOut系の関数なら文字列をそのまま渡せばいいのでこの問題に遭遇することはないと思います。
渡すとすれば以下のいずれかなんだろうと思っていましたが・・・・
- UNICODEのサロゲートペアをそのまま渡す(上位サロゲートを上位ワード、下位サロゲートを下位ワードに)
- 面の状態を切り替えてその値で渡す(U+10000~U+10FFFFになるようにサロゲートペアを変換する)
・・・どちらもだめだったんですね・・・。
ちょっと気になったので、Vista対応フォントをインストールしてみてサロゲートの状態がGetGlyphOutlineでどう扱われるか調べてみようと思って
0x10000以上でループをさせてみて気がつきました・・・。
「もしかして上位ワードが無視されていないか・・・?」
そうです。GetGlyphOutlineの文字引数はUINT(32bit値)なのに、それを処理する側のGetGlyphOutlineがなんと16bit値までしか受け入れてくれないみたいなのです。(OSはWinXPSP3でテスト)
・・・自分がテストした方法が間違っていたのか、それともMicrosoftの一種のバグなのか・・・。また微妙な現象を見つけてしまったものです・・・。
とりあえず、サロゲートペアがあることだけ検知するように変更しましたが、これって問い合わせてみてもいいものなのでしょうか・・・?
今更コメントも必要無いかと思いますが、GetGlyphOutlineWは如何でしょう。