Java の Font 周りの比較的ディープな話(後編)

技研の (あ) です。Java の Font の話の続きです。

>>Java の Font 周りの比較的ディープな話(前編)はコチラ

前回は幅や高さの話でしたが、話は換わって使えるフォントの種類について、
などです。

使えるフォントの種類

“Write once, run anywhere” を標榜して登場した Java ですので、
フォント名にはシステム非依存の名前がいくつか用意されています (論理フォント)。
Dialog, DialogInput, Monospaced, SanSerif, Serif の五種があり、
この名前を文字列で Font のコンストラクタに渡せば使えます。
これに加えて、各システムにインストールされているフォントもだいたい使えます。
「だいたい」と書いたのは一部使えないものがある、ということです (詳しくは後述)。

実行中の環境で利用できる (はず) のフォントの名称のリストは、

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] font_list = ge.getAvailableFontFamilyNames();

という感じで取得できます。これは正確には「フォントファミリー」のリストです。
フォントファミリーとは、同じ系統の複数の太さ (weight) のフォント (フォントフェース) をひっくるめた名前です。
「なんちゃら」というフォントファミリーに、
「なんちゃら」「なんちゃら Bold」「なんちゃら Italic」というフォントフェースがあったり、という感じです。
細かなフォントフェースの一覧は、

Font[] fonts = ge.getAllFonts();

で取得できます。こちらは名称でなく Font オブジェクトのリストで返ってくるところがややこしいですね。

ge.getAvailableFontFamilyNames() で得られる名前は
Font のコンストラクタに渡すことで使えますが、
前述のように、一部使えないフォントがあります。
システムに標準でインストールされているものは大丈夫なようで、
非標準のフォントだけの一部だけではありますが、

  1. FontMetrics で height や width などがきちんと取れない (0 が返ってくる)
  2. それらの値は取れるが、表示位置がおかしくなる
  3. 値が取れ、表示もできるが、違うフォント (確認した範囲では “Dialog”) で表示される

の三つのパターンを確認しています。
1 は FontMetrics を使うと「おかしい」ことが判るのでまだよいのですが、
2 は表示を確認するしかないので、困り者です…。
3 は Font.getFamily() で (“Dialog” を設定してないのに) “Dialog” が返ってくる、
ということで判別できます。
ちなみにこれらのフォントも PhotoShop や PowerPoint などでは当然普通に使えているので、
恐らく、Java がフォントのパラメータのちょっと変わったところを参照していて、
そこが設定されていないものがあったりする、というようなことなのでしょう。

フォントの重複

上の方法で得たフォントのリストの中には、違う名前で同じフォントを指す重複もあります。
かなや漢字を使った表記の名前とアルファベット表記の名前がある場合、などです。
重複がある場合、font.getFamily() で得られる名前が、コンストラクタに渡したものと違うことがあります。
これで得られる名前が代表名と考えておいてよいかと思います。

一つ注意点は、「違う名前が返ってくる」と言っても、
前述のように何故か使えない日本語フォントなどに対して font.getFamily() で “Dialog”
が返ってくる場合がある、ということです。
これは正しいフォントファミリー名が返っていない、ということになります。

似たようなメソッドで font.getFontName() はフォントフェース名を返し、
font.getName() は論理名を返します。

 

細かいフォントフェースの設定

Font のコンストラクタでは Bold や Italic あるいはこの組み合わせくらいしか weight などを設定することはできませんが、
多くの weight をサポートするフォントファミリーの場合は、フォントフェースを指定することもできます。
前出の

Font[] fonts = ge.getAllFonts();

で得られるフォントの fonts[i].getFontName() で確認し、
その名前をコンストラクタに渡します。
フォントフェースを指定しても、さらに Font.BOLD や Font.ITALIC の指定もできたりもします。
フォントの種類によっては指定しないのと変わらなかったりするかもしれませんが。

 

その他もろもろ

既存の Font オブジェクトを複製し、新しい Font を作る font.deriveFont()
というメソッドが、引数違いで何種類かあります。その一つに、float で
サイズの指定できる font.deriveFont(float size) があるので、
「おっ、小数点以下のサイズの調整もできるのか?」と思って試してみましたが、
整数で指定するのと変わらない結果になりました (四捨五入される)。

あるフォントでアルファベットや漢字が表示できるか? というチェックは

font.canDisplay(文字);

でチェックできるはずです。はずです、というのはこの辺りはまだ
あまり実際の挙動を確かめていないからです。
今後の課題ということで…。

文字がガタガタにしか表示されないんですけど…という場合は、
テキスト描画に関するアンチエイリアスの設定を入れて下さい。
線の描画などに関する設定とは別の RenderingHints になっています。

graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                                                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

システムによっては効かないかもしれません。

 

おわりに

長々と書いてきましたが、これでもまだ全ては調べ尽くしていない感じです。
見落とし、勘違い等もあるかもしれません。
他の環境で試すとどうなの? ってのもあります。
また気が向いたときに続きを調べるかもしれません。

 

  • このエントリーをはてなブックマークに追加