のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

Unicode サロゲートペア 計算方法

 具体的には、以下の手順に従います。

文字コードから0x10000を引いて1番左の桁を"2"から"1"にする。これをXとする。
Xを0x400で割ってその商を0xD800に足す。これを「上位サロゲート」とする。
Xを0x400で割ってその剰余を0xDC00に足す。これを「下位サロゲート」とする。
上位サロゲート、下位サロゲートの順番で出力する。
 例としてJavaScriptでのサンプルコードを挙げます。

サロゲートペアを使用しない文字の場合:「あ Unicode:0x3042」をダイアログに表示

var x;
var s;
x = 0x3042;  //文字コードをセット
s = String.fromCharCode(x);
alert(s);

サロゲートペアを使用する文字の場合:「叱 Unicode:0x20B9F」をダイアログに表示

var x;
var s;
var a;  //上位サロゲート
var b;  //下位サロゲート
x = 0x20B9F;  //文字コードをセット
x -= 0x10000;
a = Math.floor(x / 0x400);  //Math.floor()で整数値に変換
a += 0xD800;
b = x % 0x400;
b += 0xDC00;
s = String.fromCharCode(a,b);
alert(s);
   2013     public static int toChars(int codePoint, char[] dst, int dstIndex) {
   2014         checkValidCodePoint(codePoint);
   2015         if (dst == null) {
   2016             throw new NullPointerException("dst == null");
   2017         }
   2018         if (dstIndex < 0 || dstIndex >= dst.length) {
   2019             throw new IndexOutOfBoundsException();
   2020         }
   2021 
   2022         if (isSupplementaryCodePoint(codePoint)) {
   2023             if (dstIndex == dst.length - 1) {
   2024                 throw new IndexOutOfBoundsException();
   2025             }
   2026             // See RFC 2781, Section 2.1
   2027             // http://www.ietf.org/rfc/rfc2781.txt
   2028             int cpPrime = codePoint - 0x10000;
   2029             int high = 0xD800 | ((cpPrime >> 10) & 0x3FF);
   2030             int low = 0xDC00 | (cpPrime & 0x3FF);
   2031             dst[dstIndex] = (char) high;
   2032             dst[dstIndex + 1] = (char) low;
   2033             return 2;
   2034         }
   2035 
   2036         dst[dstIndex] = (char) codePoint;
   2037         return 1;
   2038     }
   2053     public static char[] toChars(int codePoint) {
   2054         checkValidCodePoint(codePoint);
   2055         if (isSupplementaryCodePoint(codePoint)) {
   2056             int cpPrime = codePoint - 0x10000;
   2057             int high = 0xD800 | ((cpPrime >> 10) & 0x3FF);
   2058             int low = 0xDC00 | (cpPrime & 0x3FF);
   2059             return new char[] { (char) high, (char) low };
   2060         }
   2061         return new char[] { (char) codePoint };
   2062     }
   1549     private static void checkValidCodePoint(int codePoint) {
   1550         if (!isValidCodePoint(codePoint)) {
   1551             throw new IllegalArgumentException("Invalid code point: " + codePoint);
   1552         }
   1553     }
   1631     public static boolean isSupplementaryCodePoint(int codePoint) {
   1632         return (MIN_SUPPLEMENTARY_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint);
   1633     }
   479  public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
   493  public static final int MAX_CODE_POINT = 0x10FFFF;