The next JAVA library(6)

さて、文字の描画です。
当たり前ですが、文字の描画は、drawString()を使います。
前回と同じように、Graphics.drawString()を、こちら側のライブラリでくるんでしまいます。
しかし、ここでいくつか問題があります。
まず、Fontを何で描画するか。通常であれば、Font.getFont()でFontを取得して、それをGraphicsにsetFont()して、それから描画します。
なので、ライブラリ側のdrawString()で、Fontを引数にとって実行するようにすればそれで良いのですが、Fontというのは、ユーザ側が持ち回して使用する物でもないような気がします。
それに、getFont()の仕様が、DoCoMoMIDPで異なるので、その辺の差異を埋めるためにも、こちら側でwrapしてやった方が良いでしょう。

protected Font _font = Font.getDefaultFont();

protected final int FONT_SMALL=0;
protected final int FONT_MEDIUM=1;
protected final int FONT_LARGE=2;
protected int _myFont;

protected void _setFont(int font){
    int face = Font.FACE_SYSTEM;
    int style = Font.STYLE_PLAIN;
    int size = Font.SIZE_MEDIUM;
    switch(font){
    #if DOCOMO
    case FONT_SMALL: size = Font.SIZE_TINY; break;
    #else
    case FONT_SMALL: size = Font.SIZE_SMALL; break;
    #endif
    case FONT_LARGE: size = Font.LARGE; break;
    }
    _myFont = font;
    #if DOCOMO
    _font = Font.getFont(face | style | size);
    #else
    _font = Font.getFont(face, style, size);
    #endif
}

フォントのサイズ以外はほとんど変更することは無いので、サイズだけ指定できるようにして、あとは固定の物を使います。
DoCoMoMIDPのフォントの違いについてですが、まず、DoCoMoで、フェイスをFACE_PROPORTIONALにすると、Font.stringWidth()で、正しい値が返ってこなくなります。
なので、SYSTEMフォントを使用することにします。
スタイルについては、通常はSTYLE_PLAINしか使わないでしょう。
で、フォントのサイズですが、DoCoMoは4種類、MIDPは3種類あります。
で、DoCoMoのTINYフォントは、MIDPのSMALLフォントと同じぐらいの大きさなので、機種ごとに分けて書いています。DoCoMoのSMALLフォントは、機種依存になるので使用しません。


これでフォントの作成については終わりですが、このフォントを取得するためのメソッドを作っていません。
これは、これから作るとかそういうのではなく、取得させません。
安全性のためにFontを隠蔽し、メソッドを作ったのに、それをわざわざ壊すような真似をしたくありません。
取得するにしても、

protected int _getFont(){
    return _myFont;
}

これだけで十分です。
あとは、最低限必要なメソッドだけ委譲してしまいましょう。

protected int _getFontHeight(){
    return _font.getHeight();
}
protected int _getStringWidth(String str){
    return _font.stringWidth(str);
}

これでフォント周りは全部終了です。
必要なフォントがあれば、いつものようにオーバーライドしてもらうことにしましょう。


で、やっと文字の描画です。
最初に説明したとおり、前回のdrawImage()と同じ書き方をすれば良いです。

protected void _drawString(String str, int x, int y, int c){
    _drawString(_img, str, x, y, c, 0);
}
protected void _drawString(String str, int x, int y, int c, int point){
    _drawString(_img, str, x, y, c, point);
}
protected void _drawString(Image img, String str, int x, int y, int c){
    _drawString(img, str, x, y, c, 0);
}

protected void _drawString(Image img, String str, int x, int y,
                            int c, int point){
/*
    0   1   2
    3   4   5
    6   7   8
*/
    int w=_getStringWidth(str);
    int h=_getFontHeight();
    switch(point){
    case 0:                             break;
    case 1:     x-=w/2;                 break;
    case 2:     x-=w;                   break;
    case 3:                 y-=h/2;     break;
    case 4:     x-=w/2;     y-=h/2;     break;
    case 5:     x-=w;       y-=h/2;     break;
    case 6:                 y-=h;       break;
    case 7:     x-=w/2;     y-=h;       break;
    case 8:     x-=w;       y-=h;       break;
    }
    setColor(img, c);
    img.getGraphics().setFont(_font);
    #if DOCOMO
    img.getGraphics().drawString(str, x, y+_font.getAscent());
    #else
    img.getGraphics().drawString(str, x, y, Graphics.LEFT|Graphics.TOP);
    #endif
}

これで完成ヽ(´ー`)ノ
DoCoMoの場合は、描画の位置がベースラインになっているので、それを修正しています。
少しだけ注意しないといけないのは、drawString()の直前にsetFont()をすること。
そうしないと、DoCoMoの場合、デフォルトのフォントで表示されてしまいます。
つまり、

Graphics g1 = img1.getGraphics();
g1.setFont(font);
Graphics g2 = g1;
g2.drawString("ほげほげ", 0, 0);

と書いた場合、"ほげほげ"は、デフォルトフォントで表示されてしまいます。
おそらく、Graphicsの代入は、コピーコンストラクタのような機構を使って実装していて、Imageの参照先等はコピーされますが、その際にフォントがデフォルトになってしまうのでしょう。単なる予想ですが。
まあ、そういうことなので、描画する直前にsetFont()をします。Fontを外に出したくない理由としては、この辺の事情も挙げられますね。


今日はこれでおしまい。次はファイル操作かなぁ(;´Д`)