Javaでフォントについて理解しよう!

こんなに簡単!JavaでFont一覧を表示 | hiro345」のようにして、フォント一覧を取得できたら、もう少しフォントについて理解を深めるためにプログラムを作成してみましょう。

具体的には、次のような画像ファイルを生成してみます。

詳細はJavaのjava.awt.FontMetricsクラスの説明を読むと良いのですが、簡単に説明をしておきます。フォントの描画にあたっては、フォントの位置は、参照ポイントといわれる点の座標を x, y で指定します。このポイントのy座標の水平ラインがベースラインとなります(さきほどの図では赤線)。英字では、p, q のように、このラインより下にはみでる文字があります。

Javaでは、フォントの高さは、アセント、ディセント、レディング(行間の間隔)の合計になりますが、手元の通常の文字用フォントではレディングは0でしたから、通常はアセントとディセントを意識しておけばよいでしょう。

さきほどの図では、フォントの高さ分をダークグレーの線で表示しています。また、アセントの幅は赤線と緑線間の幅、ディセントの幅は赤線と青線間の幅で表示しています。レディングはピンクの線でわかるようにしてみましたが、使ったフォントでは0だったので、線が重ならないように表示上の調整をしています。

画像ファイルの生成には、ImageIOクラスを使って、ものすごく簡単に実現しています。最初、Gimpなどで同様のプログラムを作成しようかとも思いましたが、Javaの方が慣れていて簡単そうだったので、止めました。

実際に作成したプログラムは、ちょっと長いですが、次のようなプログラムになります。ライン描画用にy座標をいろいろ計算しているところがわかりにくいかもしれませんが、コンソール画面にでるそれぞれの値と、生成される画像ファイルの結果を見て照らし合わせれば、どういうことをしているのかわかるはずです。

package org.sssg.soft.sample.fontlist;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;

public class FontImageCreator {
  private FontMetrics getFontMetrics(Font font) {
    BufferedImage image = new BufferedImage(1, 1,
        BufferedImage.TYPE_INT_RGB);
    Graphics2D g = image.createGraphics();
    FontMetrics fm = g.getFontMetrics(font);
    g.dispose();

    return fm;
  }

  public void checkLeading() {
    GraphicsEnvironment genv = GraphicsEnvironment
        .getLocalGraphicsEnvironment();
    List<Font> values = Arrays.asList(genv.getAllFonts());
    System.out.println("checkLeading start ... ");
    for (Font font : values) {
      FontMetrics fm = getFontMetrics(font);
      if (fm.getLeading() != 0) {
        System.out.println(" " + font.getName());
      }
    }
    System.out.println("checkLeading end ... ");
    System.out.println("");
  }

  public void draw(String fontName, String fileName) {
    Font font = Font.decode(fontName).deriveFont(24.0f);
    FontMetrics fm = getFontMetrics(font);

    String str = "あいうえおABCPQRSTUabcpqrstu";
    int width = fm.charWidth(str.charAt(0)) * (str.length() + 4);
    int height = fm.getHeight() + 20;

    BufferedImage image = new BufferedImage(width, height,
        BufferedImage.TYPE_INT_RGB);
    Graphics2D g = image.createGraphics();

    int fw = fm.stringWidth(str);
    int fh = fm.getHeight();
    System.out.println("Font Name:" + font.getName());
    System.out.println(" Font Width:" + fm.stringWidth(str));
    System.out.println(" Font Height:" + fm.getHeight()); // アセント+ディセント+標準レディング
    System.out.println(" Font Ascent:" + fm.getAscent()); // アセント
    System.out.println(" Font Descent:" + fm.getDescent());// ディセント
    System.out.println(" Font Leading:" + fm.getLeading());// 標準レディング
                                // (行間の間隔)

    int x_left_margin = (width - fw) / 2;
    int y_top_margin = (height - fh) / 2;
    int x = x_left_margin;
    int y = y_top_margin + fm.getAscent();
    System.out.println(" width:" + width);
    System.out.println(" height:" + height);
    System.out.println(" x:" + x);
    System.out.println(" y:" + y);

    g.setColor(Color.WHITE);
    g.fillRect(0, 0, image.getWidth(), image.getHeight());

    // ベースライン
    int lineY = y;
    g.setColor(Color.RED);
    g.drawLine(0, lineY, width, lineY);
    // レディング上, 表示の都合で調整
    g.setColor(Color.PINK);
    int fLeading = fm.getLeading();
    if (fLeading == 0) {
      fLeading = 1;
    }
    lineY = y + fm.getMaxDescent() - fm.getHeight() - fLeading - 1;
    g.drawLine(0, lineY, width, lineY);
    // レディング下, 表示の都合で調整
    lineY = y + fm.getMaxDescent() + fLeading + 1;
    g.drawLine(0, lineY, width, lineY);

    // フォントの高さ上, 表示の都合で -1
    g.setColor(Color.DARK_GRAY);
    lineY = y + fm.getMaxDescent() - fm.getHeight() - 1;
    g.drawLine(0, lineY, width, lineY);
    // フォントの高さ下, 表示の都合で +1
    lineY = y + fm.getMaxDescent() + 1;
    g.drawLine(0, lineY, width, lineY);

    // アセント
    g.setColor(Color.GREEN);
    lineY = y - fm.getMaxAscent();
    g.drawLine(0, lineY, width, lineY);
    // ディセント
    g.setColor(Color.BLUE);
    lineY = y + fm.getMaxDescent();
    g.drawLine(0, lineY, width, lineY);

    g.setColor(Color.BLACK);
    g.setFont(font);
    g.drawString(str, x, y);

    g.dispose();
    try {
      ImageIO.write(image, "png", new File(fileName));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    FontImageCreator app = new FontImageCreator();
    app.checkLeading();
    app.draw("Monospaced", "monospaced.png");
    app.draw("Sazanami Mincho Regular", "sazanami.png");
  }
}
同じタグの記事: Font
同じタグの記事: Java
同じカテゴリの記事: Java
関連書籍: Java