Archive for 2nd 7月 2009

Graphics2Dに文字列を描画

Flashでやったらいいじゃないかとは思いますが、画像ファイルに文字列を描画したい場合があります。
単一行の文字列であれば特に何も考えず、
Graphics2D#drawString
すれば良いです。(参考:drawStringメソッド

しかし複数行にわたる文字列を描画するためには、前述のメソッドでやるには面倒くさい。
現在のy座標の位置と、フォントの高さを計算してさらにどこで文字列を折り返すかもあらかじめ決めておかないと難しい。

そこで、LineBreakMeasurer
というクラスを使用して描画すると多少は簡単になる。
正直、このJavaDocをはじめて見たときはまったく理解出来なかったのですが、
実際やってみると色々わかったことが出てきたのでメモしておきます。

つまりLineBreakMeasurerは、指定した幅に指定した文字列が入りきらなければ(または文の教会と判断したならば)
勝手に行に分割してくれるというものだと思います。

LineBreakMeasurerのコンストラクタに渡すのは

の三つを抑えておけば大丈夫そうです。
AttributedStringには、描画する文字情報を保持させます。TextAttribute
に設定出来る情報があります。
BreakIteratorには、文を分割する境界に関する情報を持たせます。
LineBreakMeasurerでこれを指定しないコンストラクタを使用すると、BreakIterator#getLineInstance()
が使用されるようです。文字を一杯一杯に出したいときは、BreakIterator#getCharacterInstance()
を使用すると良いです。
FontRenderContextは、Graphics2D#getFontRenderContext()
を指定しておけば良いです。実際どう効いてくるのかは未調査です。

行分割出来たらセンタリングと右寄せとか位置を調整したくなってくるのですが、
フォントアセント、フォントディセント、レディング等を考えないといけないのですが、
(アセント、ディセント等はフォントのコンセプトが割と分かりやすいです。)
とりあえず、いいサンプルがあったのでそれを参考にします。

LineBreakMeasurer: getPosition()

LineBreakMeasurer#nextLayout(float)
を呼ぶと次の分割単位(ここでは行を想定)を返します。
行が変わり、描画直前でアセントを設定し、描画し終わったらディセント、レディングを追加します。

ただし、ここまでは良かったのですが、垂直の位置をセンタリングや下寄せにしたい場合はどうしようか?
という問題が出てきました。現状のアイデアとしては、LineBreakMeasurerを最後の行から上に向かって描けば良さそうですがまだ未検証。

こちらも参考にさせていただきました。
Javaで複数行の文字列をレンダリングするときの注意点