Swing/SurrogatePair のバックアップ(No.23)
- バックアップ一覧
 - 差分 を表示
 - 現在との差分 を表示
 - 現在との差分 - Visual を表示
 - ソース を表示
 - Swing/SurrogatePair へ行く。
  
- 1 (2012-05-14 (月) 11:54:26)
 - 2 (2012-05-14 (月) 15:01:46)
 - 3 (2012-05-15 (火) 11:17:30)
 - 4 (2012-06-06 (水) 18:42:16)
 - 5 (2012-06-12 (火) 19:09:04)
 - 6 (2012-06-25 (月) 18:37:16)
 - 7 (2012-06-25 (月) 20:42:16)
 - 8 (2012-09-26 (水) 17:11:57)
 - 9 (2012-11-15 (木) 16:55:12)
 - 10 (2012-11-16 (金) 18:26:03)
 - 11 (2012-12-11 (火) 20:55:41)
 - 12 (2013-01-29 (火) 23:48:27)
 - 13 (2013-05-27 (月) 17:03:23)
 - 14 (2013-05-27 (月) 21:55:45)
 - 15 (2014-09-18 (木) 02:36:05)
 - 16 (2014-10-18 (土) 13:03:17)
 - 17 (2014-11-01 (土) 00:46:09)
 - 18 (2014-12-20 (土) 13:29:12)
 - 19 (2014-12-22 (月) 16:47:22)
 - 20 (2015-11-26 (木) 04:20:20)
 - 21 (2017-01-05 (木) 14:19:26)
 - 22 (2017-04-18 (火) 21:07:09)
 - 23 (2017-04-19 (水) 15:39:47)
 - 24 (2017-11-02 (木) 15:34:40)
 - 25 (2017-12-07 (木) 11:48:46)
 - 26 (2017-12-07 (木) 14:09:21)
 - 27 (2018-01-15 (月) 18:56:18)
 - 28 (2018-04-04 (水) 15:27:26)
 - 29 (2018-10-12 (金) 17:44:22)
 - 30 (2018-12-17 (月) 16:24:00)
 - 31 (2020-11-12 (木) 09:44:04)
 - 32 (2022-08-05 (金) 16:04:11)
 - 33 (2022-08-20 (土) 22:15:25)
 - 34 (2022-10-04 (火) 15:57:26)
 - 35 (2025-01-03 (金) 08:57:02)
 - 36 (2025-01-03 (金) 09:01:23)
 - 37 (2025-01-03 (金) 09:02:38)
 - 38 (2025-01-03 (金) 09:03:21)
 - 39 (2025-01-03 (金) 09:04:02)
 - 40 (2025-06-19 (木) 12:41:37)
 - 41 (2025-06-19 (木) 12:43:47)
 
 
- category: swing
folder: SurrogatePair
title: JTextComponentでサロゲートペアのテスト
tags: [JEditorPane, JTextComponent, Unicode]
author: aterai
pubdate: 2012-05-14T11:54:26+09:00
description: JEditorPaneなどで数値文字参照やUnicodeエスケープを使ってサロゲートペアのテストをします。
image: 

 
概要
JEditorPaneなどで数値文字参照やUnicodeエスケープを使ってサロゲートペアのテストをします。
Screenshot

Advertisement
サンプルコード
final URL url = getClass().getResource("SurrogatePair.html");
try (Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) {
  editor1.read(reader , "html");
} catch (Exception ex) {
  editor1.setText(
    "<html><p>(��) (𦹀)<br />(��) (𠮟)</p></html>");
}
JEditorPane editor2 = new JEditorPane();
//editor2.setFont(new Font("IPAexGothic", Font.PLAIN, 24));
editor2.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
editor2.setText("(\uD85B\uDE40) (\u26E40)\n(\uD842\uDF9F) (\u20B9F)");
View in GitHub: Java, Kotlin解説
以下、サロゲートペア対応フォントを使えるようにしてテストしています。Java Web Startで起動した場合、このサンプルのbrowseボタンでjarファイル内のSurrogatePair.htmlを表示することはできません。
- 上: 数値文字参照(
Numeric character reference)- Bug ID: 6836089 Swing HTML parser can't properly decode codepoints outside the Unicode Plane 0 into a surrogate pairで修正されたので、
𦹀などでも正常に文字が表示される(上記のスクリーンショットのように文字化けしない) JEditorPane(HTMLEditorKit)の場合JEditorPane+��:OKJEditorPane+𦹀:NGOK
 - Bug ID: 6836089 Swing HTML parser can't properly decode codepoints outside the Unicode Plane 0 into a surrogate pairで修正されたので、
 
- ブラウザ(試したのは
IE,FireFox,Chrome,Opera)の場合Browser+��:NGBrowser+𦹀:OK
 
- 下: 
Unicodeエスケープ(Unicode escapes)JEditorPane+\uD85B\uDE40:OKJEditorPane+\u26E40:NG
 
JTextComponentとブラウザでサロゲートペアの表現が異なるようなので、これらの文字をどちらの環境でも正しく表示したい場合は、数値文字参照やUnicodeエスケープは使用せず、ソースコードなどをUTF-8にしてそのまま𦹀や𠮟と書く(メモ帳などの対応済みエディタで)のがよさそうです。
Windows 7, JDK 1.7.0_02の環境では、JTextComponentからメモ帳などにサロゲートペアの文字をコピーペーストは可能ですが、逆にメモ帳やブラウザからJTextComponentにサロゲートペアの文字をコピーペーストすることができないようです。
JTextComponent(Java 1.7.0)は、異体字セレクタに対応していません。
- フォントを
IVSに対応しているIPAmj明朝などに変更し、異体字セレクタ付き文字列のあるUTF-8のテキストをJTextAreaなどに読み込んでも異体字セレクタが下駄になる - 数値文字参照、
Unicodeエスケープを使う方法でも下駄になる- Java IVSの異体字を元の字と同一視して比較する - terazzoの日記のように、
VSをUTF-16に(例えばU+E0101を\uDB40\uDD01に)しても、JTextComponentでは駄目 
 - Java IVSの異体字を元の字と同一視して比較する - terazzoの日記のように、
 
- 参考メモ: MS IVSアドインでDTPにはどんな影響があるのか - ちくちく日記
Adobe-Japan1 collection:小塚明朝 Pr6NなどHanyo-Denshi collection:IPAmj明朝など
 
Windows 10 64bit、JDK 1.8.0_112、小塚明朝 Pr6N R(KozMinPr6N-Regular.otf)で、Font.createFont(...)を使ってFontを作成するとIllegalArgumentExceptionが発生する場合がある
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Length must be >= 0. at javax.swing.text.GlyphPainter2.getBoundedPosition(GlyphPainter2.java: 205)
import java.awt.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class OTFTest {
  public JComponent makeUI() {
    JTextArea textArea = new JTextArea("1234567890\n \uD85B\uDE40");
    String str = "file:///C:/Program Files (x86)/Adobe/Acrobat 2015/Resource/CIDFont/KozMinPr6N-Regular.otf";
    //String str = "file:///C:/Program Files (x86)/Adobe/Reader 11.0/Resource/CIDFont/KozMinPr6N-Regular.otf";
    //String str = "file:///C:/Windows/Fonts/meiryo.ttc";
    //String str = "file:///C:/Windows/Fonts/ipaexg.ttf";
    //String str = "file:///C:/Windows/Fonts/A-OTF-ShinGoPro-Regular.otf";
    try (InputStream is = new URL(str).openStream()) {
      //textArea.setFont(Font.createFont(Font.TRUETYPE_FONT, is));
      textArea.setFont(Font.createFont(Font.TRUETYPE_FONT, is).deriveFont(32f));
    } catch (IOException | FontFormatException ex) {
      ex.printStackTrace();
    }
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(textArea));
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new OTFTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}