NetBeans で太字を使うと桁位置がずれる件とその対策
今回の PHP 開発では PDT でなく NetBeans を使う方向なのですが。以前 NetBeans を導入して困ったのが、「等幅フォントを使っていても太字があると桁位置がずれてしまう」というもの。
たとえばこの YAML ファイル。
せっかく文字列リテラル部分の桁位置が合うように空白を入れて調整しているのに、NetBeans で表示すると太字になった文字数ぶんだけ表示位置がずれてしまっています。以前は仕方なく太字設定を片っ端から解除していたのですが、対策方法を調べてみたのでそのお話。
とっかかり
太字の問題についてどこかで報告されていないか調べていて発見した
このブログ。
- 等幅フォントなのに太字にすると桁位置がずれてしまう
- NetBeans で使っていたフォント「Lucida Sans Typewriter」が標準と太字で幅が違うせいだった
- フォントを「monospaced」に変更したら解決した
みたいなことが書かれています。
手元の NetBeans で「ツール」→「オプション」→「フォントと色」の設定を見ると、ちゃんとフォントは「Monospaced 12」になっているようで、単純に Monospaced にすればよいという問題ではなさそうです。とはいえ、てっきり NetBeans の描画処理に問題があると思っていたので、フォントで挙動が違うというのは重要な情報でした。
いろんなフォントで比較してみる
NetBeans の描画処理を少し覗いてみると、太字の処理は単純に BOLD の属性を設定しているだけのようで。Swing で作られているようなので、Groovy の Groovy - Swing Builder で等幅フォントがどのように表示されるか動作を確認してみました。
使ったスクリプト
に上げてますが、いくつかのフォントで標準と太字で文字列を表示していくだけのスクリプトです。Swing Builder のサンプルを適当にいじっただけで、あまり効率のいい処理ではないと思います。
対象のフォント
Windows 7 標準で入っているフォント以外は以下のような感じです。
- Inconsolata
- Inconsolata からダウンロード。
- MeiryoKe_Console
- メイリオ 『ことば・その周辺』 のジェネレータを使用。
- M+2VM+IPAG circle
- M+ と IPAフォントの合成フォント(旧サイト)からダウンロード。
- Migu 1M
- Miguフォント : M+とIPAの合成フォント からダウンロード。
- Ricty、Ricty Discord
- プログラミング用フォント Ricty で公開されている 3.1.0 を Ubuntu 上でビルド。
ちなみに Monospaced は論理フォント名で、Windows で特に設定を行っていない場合は MS Gothic が使われるようです。(詳細については後のリンクを参照。)
結果
- Migu 1M と Ricty(Ricty Discord)は幅のずれがなく、日本語も正しく表示できる
- Iconsolata、MS Gothic(Monospaced)、MeiryoKe_Console、M+2VM+IPAG circle は太字になると横幅が変わる
- Courier New、Consolas は太字になっても幅が変わらないが、日本語が表示できない
- NetBeans - hd 4.0 によるとフォントリンクも利かないとのこと。
とりあえず私は Migu 1M を使っていこうと思います。
今回 NetBeans に限定して書きましたが、たぶんプロポーショナルフォントが使えるエディタ や IDE に共通の話なんでしょうね、これ。
日本語表示の文字幅について補足
「Consolas 等では日本語を表示できない」と書きましたが、JDKのフォント設定を変更すれば Monospaced フォントとして Consolas とメイリオを併用したりできます。このあたりについては下記ページにものすごく詳しく載っています。
ただ、この方法だと半角文字と全角文字の横幅が 1:2 にならないので、気になる方はこのような調整が行われているフォント(M+2VM+IPAG circle や Migu、Ricty 等)を使ったほうがいいと思います。
そのときの注意点なのですが、Ricty の公式ページに載っているよう、
一部のフォントサイズで半角文字と全角文字の横幅比が 1:2 にならないことがあります。
ピクセル値 (px) が偶数でないとき、どのフォントにおいても起こりうる問題です。
一般的な 96 DPI のフォントレンダリングでは、9 pt、10.5 pt、12 pt、13.5 pt、15 pt など、1.5 の倍数を指定すると 1:2 で表示されると思います。
のようなサイズで表示しないとずれてしまうそうです。1 point = 1/72 inch = 96/72 pixcels(@96 DPI) = 4/3 pixels だから point を 3/4 の倍数にしないと整数にならないよね→実質 1.5 の倍数でいいよね、という話だと思います。でも Swing での描画は Windows 7 の描画よりも一回り小さいし、これが当てはまるのかはよくわかりません・・・。
表示が汚いのはなんとかならないの?
ということで、Migu 1M を使うことにしたんですが、このフォントも特にサイズが小さいとあまりきれいに描画されません。普段は gdi++ Helium を使っているので問題ないのですが、Swing は独自の描画をしているので gdi++ は効かないようで。
(追記)
gdi++ が効かないというのは勘違いでした。詳細はこちらをご覧ください。
(追記 ここまで)
結局どうにもなっていないんですが、試したことをいくつか書いておきます。
awt.useSystemAAFontSettings の調整
こちらに載っていた、アンチエイリアスを有効にする
-J-Dawt.useSystemAAFontSettings=lcd
オプションの追加ですが、Windows 7 でアンチエイリアスを有効にしている場合は、特に設定を行わなくてもこれと同等の設定になっているようです。
を参考に「lcd」を「on」に変えたりもしたのですが、縦方向にもアンチエイリアシングが走って縦の荒さは目立たなくなる一方で、全体的に縦にぼやけてしまいました。この設定を行うと MS Gothic でもビットマップフォントが使われなくなるようで、メニュー部分やタブ部分にもアンチエイリアスが利く、という変化がありました。
- awt.useSystemAAFontSettings=lcd
- awt.useSystemAAFontSettings=on
個人的にはくっきり表示されたほうが好きなので lcd のままにしていますが、今後気分しだいでは on に変えるかもしれません。
JGoodies looks の利用
のように紹介されていたのでとりあえず試してみました。
ということで、変化があるのはツリービューやプルダウンといった部分ですね。エディタ部分の見た目は変わりませんし、個人的にはビットマップフォントも嫌いではないので、どちらでもいいかなという感じです。