miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

NetBeans でも gdi++ は効くらしい

昨日「Migu 1M は gdi++ 使わないと表示が汚いけど、NetBeans は Swing は独自の描画をしているので gdi++ は効かない」みたいなことを書いたんですが。どうやら勘違いだったのでとりあえず訂正しておきます。

きっかけ

「独自の描画をしている」ってどんな処理なんだろ?と OpenJDK のソースを覗いてみたところ、openjdk\jdk\src\windows\native\sun\windows\awt_Font.cpp に

/*
 * This is a faster version of the same function, which does most of
 * the work in Java.
 */
SIZE  AwtFont::DrawStringSize_sub(jstring str, HDC hDC,
                                  jobject font, long x, long y, BOOL draw,
                                  UINT codePage)
(中略)
                if (unicodeUsed) {
                    VERIFY(!draw || ::TextOutW(hDC, x, y, (LPCWSTR)offsetBuffer, buflen / 2));
                    VERIFY(::GetTextExtentPoint32W(hDC, (LPCWSTR)offsetBuffer, buflen / 2, &temp));
                }
                else {
                    VERIFY(!draw || ::TextOutA(hDC, x, y, offsetBuffer, buflen));
                    VERIFY(::GetTextExtentPoint32A(hDC, offsetBuffer, buflen, &temp));
                }

こんな処理を見つけて。内容ぜんぜんわかってないけど、ふつうに Win32API 呼び出してるんなら gdi++ 効くんじゃないの?と思ったのがきっかけ。

試してみる

gdi++ Helium で ModuleListOrder=1 にして特定のプログラムだけ gdi++ を効くようにしてあるので、[AllowModule] に netbeans.exe を加えて設定反映とか再描画とかかけてみたけど、やっぱり gdi++ は効いてないみたい。

OpenJDK 7 のソースだから念のため JDK も 7 にしてみるかなー、と netbeans.conf の設定を書き換えて再起動してみると・・・なんか gdi++ 効いてる。JDK 7 じゃないとダメなのかと思ったらそういうわけではなく、gdi++ を有効にした状態で起動しなおす必要があるみたいで。Swing では一度描画したフォントの情報をキャッシュしてるから、起動中に gdi++ を有効にしてもそれ以前に一度でも描画されていた文字は汚いままで、それ以降に描画された文字だけきれいになるという理屈みたい。

gdi++ を有効にして NetBeans を起動→gdi++ を無効にして別ファイルを開いてみると、こんな(↓)感じで gdi++ が効いている文字と効いていない文字が混ざったりして面白いです。


見た目の比較

まず gdi++ が効いてない状態。(↓)

gdi++ を有効にするとこうなります(↓)。「場」みたいに線が多い文字でも、線同士がくっついたりせずきれいに表示されているのがわかると思います。

awt.useSystemAAFontSettings=on も試してみました(↓)。縦方向のアンチエイリアスが Swing 任せだからちょっと汚いような。

gdi++ 側と Swing 側の両方でアンチエイリアスがかかってる気がするから、実は awt.useSystemAAFontSettings=off が一番きれいなんじゃないの?と試してみたけどこれは失敗。とびっきり汚い(↓)。

もう少し綺麗に表示する方法もあるかもしれませんが、とり急ぎ訂正ということで。