One IT Thing

IT業界で飯を食う為の学習系雑記

java

IPAmj明朝のttfファイルをJVMに読み込ませてSwingで表示(要Java11)

投稿日:2019年7月8日 更新日:

はじめに

今までIPAmj明朝をWebで表示する実験を何度か行ってきました。

Webアプリ上でIPAmj明朝フォントを表示するには、利用者のPCにIPAmj明朝フォントをインストールして貰わなければならないという欠点があります。

Webフォントにする手もありますが6万文字もあるとサイズがばかにならないですし、IME経由での文字入力が絶望的になります。

一転、デスクトップアプリならアプリにIPAmj明朝フォントを同梱して読み込ませ、フォント表示することが出来ます。

しかしこれも残念ながら、Javaのデスクトップアプリ開発APIである「Swing」はIVS(異体字セレクタ)を解釈する機能が実装されていなかった為、IPAmj明朝を使用しても異体字は文字化けする状況でした。

・・・でしたが、

Java11でSwingがIVSを認識するようになった

進化してますJavaさん。ということで文字化けせずに異体字を表示出来るか検証してみます。

Java Swingソース

プロジェクトルートにIPAmj明朝フォントのTTFファイルである「ipamjm.ttf」を置き、Javaから読み込んで使用します。

冒頭画像の10文字をUnicodeエスケープして、IPAmj明朝フォントを設定したJLabelのテキストとして表示してみます。

JavaでIVSが付いた文字を表示するにはWeb「&#x」と違い「\u」でUnicodeエスケープします。\uは確実に2バイトでないといけない為、「0xE0101」といったIVSコードポイントは「\uDB40\uDD01」にサロゲートペアにエンコードしてから使います。

package com.example.demo;

import java.awt.EventQueue;
import java.awt.Font;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class IPAMJFontFrame extends JFrame {

    // フォント表示テスト用ラベル
    private JLabel label;

    // JFrame画面を構築
    public IPAMJFontFrame() throws Exception {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("IPAmj明朝表示確認");
        setSize(800, 200);
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        // IPAmj明朝 ttfファイル読み込み、Fontインスタンス作成
        Font ipamjm = 
            Font.createFont(Font.TRUETYPE_FONT, new FileInputStream("ipamjm.ttf"));
        // 字体の違いが分かるように大きめフォントサイズに設定
        ipamjm = ipamjm.deriveFont(64F);

        // 確認用JLabel、フォントはIPAmj明朝に設定
        this.label = new JLabel();
        label.setFont(ipamjm);

        JPanel panel = new JPanel();
        panel.add(label);
        add(panel);

        setVisible(true);
    }

    public void setLabelText(String text) {
        this.label.setText(text);
    }

    public static void main(String[] args) {
        String javaVersion = System.getProperty("java.version");
        System.out.println(javaVersion);

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    IPAMJFontFrame frame = new IPAMJFontFrame();

                    // 表示用にUnicodeエスケープ 
                    List<String> codeList = new ArrayList<String>();
                    codeList.add("\u9F8F\uDB40\uDD04");
                    codeList.add("\uD87A\uDFDB");
                    codeList.add("\uD87A\uDFE0");
                    codeList.add("\uD874\uDF80\uDB40\uDD01");
                    codeList.add("\u6E5B\uDB40\uDD01");
                    codeList.add("\u6F9A\uDB40\uDD02");
                    codeList.add("\u8352\uDB40\uDD08");
                    codeList.add("\uD86D\uDF51\uDB40\uDD02");
                    codeList.add("\uD875\uDCFD");
                    codeList.add("\u3407");
                    String codePoints = String.join("", codeList);

                    // 文字列を表示
                    frame.setLabelText(codePoints);

//                    byte[] array = { (byte) 0x84, (byte) 0x5B, (byte) 0xDB, (byte) 0x40, (byte) 0xDD, (byte) 0x04 };
//                    frame.setLabelText(new String(array, "UTF-16"));

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

実装完了です。

動作確認

Java 8(1.8.0_202)で実行

サロゲート文字は表示出来ていますがIVS(\uE0101または\uDB40\uDD01等)を解釈出来ておらず、その部分が文字化けしてしまっています。

Java 11(11.0.2)で実行

おお・・・。完璧に表示出来てます。

何気にSwingのデフォルトアイコンがDukeになっている発見。
(でも異体字の違いをなかなか発見出来ない罠・・・)

まとめ

これならPCにフォントをインストールしなくても、凡そ6万文字に及ぶIPAmj明朝フォントを表示することが出来ますね。

なんでもWeb化の潮流でデスクトップアプリが許容されるシーンは限られるかも知れませんが・・・。

ただ異体字が必要とされるシーンも限られているので、難しい文字を入力、表示する必要があるシステムでは、GUIアプリとして提供するソリューションはアリかも知れません。

-java
-, , ,

執筆者:

関連記事

IVS対応フォント「IPAmj明朝」で使えるフォントをWeb上に一覧表示してみる(3)

前回の続きです。 One IT ThingIVS対応フォント「IPAmj明朝」で使えるフォントをWeb上に一覧表示してみる(2)https://one-it-thing.com/2111前回 …

Jerseyで開発したRESTで任意リファラからのCORSアクセスを許可する

package jp.hoge.filter; import java.util.Properties; import javax.servlet.http.HttpServletRequest; i …

JavaでRSA暗号を使う際にCRYPTREC暗号リストに足元をすくわれる可能性を回避する

標準的な暗号しか使わないケースでもJavaでRSAを使う時はBouncyCastleを入れておいた方が無難、という話です。 “ECB”という文字列がプログラム中にあると監査に引 …

IVS対応フォント「IPAmj明朝」で使えるフォントをWeb上に一覧表示してみる(1)

目次1 IPAmj明朝フォントとは2 日本における漢字のコンピュータ表示課題3 サロゲートペアが対応策だが4 IVS(ideographic variation sequence) とは5 そこでIP …

Maven環境別ビルド時、プロファイルの違いでdependencyを変える

MavenのResourceFilteringを使い、production、staging、developmentとかで環境別ビルドしている時、ある環境ビルドの時だけ特定のライブラリを追加する、をmv …

 

shingo.7k24
 

東京在勤、職歴20年越え中年ITエンジニアです。まだ開発現場で頑張っています。

19歳(1996年)から書き始めた個人日記が5,000日を超え、残りの人生は発信をして行きたいと思い、令和元日からこのサイトを開始しました。勉強と試行錯誤をしながら、自分が経験したIT関連情報を投稿しています。

私と同じく、今後IT業界で生計を立てて行きたいと考えている方や、技術共有したいけどフリーランスで孤独、といった方と一緒に成長、知識共有して行けたら楽しいな、と思っています。