diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/text/AndroidCharacter.java | 39 | ||||
-rw-r--r-- | core/jni/android_text_AndroidCharacter.cpp | 65 |
2 files changed, 101 insertions, 3 deletions
diff --git a/core/java/android/text/AndroidCharacter.java b/core/java/android/text/AndroidCharacter.java index 6dfd64d..af93b5d 100644 --- a/core/java/android/text/AndroidCharacter.java +++ b/core/java/android/text/AndroidCharacter.java @@ -22,6 +22,13 @@ package android.text; */ public class AndroidCharacter { + public static final int EAST_ASIAN_WIDTH_NEUTRAL = 0; + public static final int EAST_ASIAN_WIDTH_AMBIGUOUS = 1; + public static final int EAST_ASIAN_WIDTH_HALF_WIDTH = 2; + public static final int EAST_ASIAN_WIDTH_FULL_WIDTH = 3; + public static final int EAST_ASIAN_WIDTH_NARROW = 4; + public static final int EAST_ASIAN_WIDTH_WIDE = 5; + /** * Fill in the first <code>count</code> bytes of <code>dest</code> with the * directionalities from the first <code>count</code> chars of <code>src</code>. @@ -30,6 +37,38 @@ public class AndroidCharacter */ public native static void getDirectionalities(char[] src, byte[] dest, int count); + + /** + * Calculate the East Asian Width of a character according to + * <a href="http://unicode.org/reports/tr11/">Unicode TR#11</a>. The return + * will be one of {@link #EAST_ASIAN_WIDTH_NEUTRAL}, + * {@link #EAST_ASIAN_WIDTH_AMBIGUOUS}, {@link #EAST_ASIAN_WIDTH_HALF_WIDTH}, + * {@link #EAST_ASIAN_WIDTH_FULL_WIDTH}, {@link #EAST_ASIAN_WIDTH_NARROW}, + * or {@link #EAST_ASIAN_WIDTH_WIDE}. + * + * @param input the character to measure + * @return the East Asian Width for input + */ + public native static int getEastAsianWidth(char input); + + /** + * Fill the first <code>count</code> bytes of <code>dest</code> with the + * East Asian Width from the first <code>count</code> chars of + * <code>src</code>. East Asian Width is calculated based on + * <a href="http://unicode.org/reports/tr11/">Unicode TR#11</a>. Each entry + * in <code>dest> will be one of {@link #EAST_ASIAN_WIDTH_NEUTRAL}, + * {@link #EAST_ASIAN_WIDTH_AMBIGUOUS}, {@link #EAST_ASIAN_WIDTH_HALF_WIDTH}, + * {@link #EAST_ASIAN_WIDTH_FULL_WIDTH}, {@link #EAST_ASIAN_WIDTH_NARROW}, + * or {@link #EAST_ASIAN_WIDTH_WIDE}. + * + * @param src character array of input to measure + * @param start first character in array to measure + * @param count maximum number of characters to measure + * @param dest byte array of results for each character in src + */ + public native static void getEastAsianWidths(char[] src, int start, + int count, byte[] dest); + /** * Replace the specified slice of <code>text</code> with the chars' * right-to-left mirrors (if any), returning true if any diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp index 05d7b73..1353478 100644 --- a/core/jni/android_text_AndroidCharacter.cpp +++ b/core/jni/android_text_AndroidCharacter.cpp @@ -23,7 +23,8 @@ #include "utils/Log.h" #include "unicode/uchar.h" -#define DIRECTIONALITY_UNDEFINED (-1) +#define PROPERTY_UNDEFINED (-1) + // ICU => JDK mapping static int directionality_map[U_CHAR_DIRECTION_COUNT] = { 0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0) @@ -79,7 +80,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, j (src[i + 1] & 0x3FF); int dir = u_charDirection(c); if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT) - dir = DIRECTIONALITY_UNDEFINED; + dir = PROPERTY_UNDEFINED; else dir = directionality_map[dir]; @@ -89,7 +90,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, j int c = src[i]; int dir = u_charDirection(c); if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT) - dest[i] = DIRECTIONALITY_UNDEFINED; + dest[i] = PROPERTY_UNDEFINED; else dest[i] = directionality_map[dir]; } @@ -100,6 +101,60 @@ DIRECTION_END: env->ReleaseByteArrayElements(destArray, dest, JNI_ABORT); } +static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input) +{ + int width = u_getIntPropertyValue(input, UCHAR_EAST_ASIAN_WIDTH); + if (width < 0 || width >= U_EA_COUNT) + width = PROPERTY_UNDEFINED; + + return width; +} + +static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray, + int start, int count, jbyteArray destArray) +{ + jchar* src = env->GetCharArrayElements(srcArray, NULL); + jbyte* dest = env->GetByteArrayElements(destArray, NULL); + if (src == NULL || dest == NULL) { + jniThrowException(env, "java/lang/NullPointerException", NULL); + goto EA_END; + } + + if (start < 0 || start > start + count + || env->GetArrayLength(srcArray) < (start + count) + || env->GetArrayLength(destArray) < count) { + jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); + goto EA_END; + } + + for (int i = 0; i < count; i++) { + const int srci = start + i; + if (src[srci] >= 0xD800 && src[srci] <= 0xDBFF && + i + 1 < count && + src[srci + 1] >= 0xDC00 && src[srci + 1] <= 0xDFFF) { + int c = 0x00010000 + ((src[srci] - 0xD800) << 10) + + (src[srci + 1] & 0x3FF); + int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH); + if (width < 0 || width >= U_EA_COUNT) + width = PROPERTY_UNDEFINED; + + dest[i++] = width; + dest[i] = width; + } else { + int c = src[srci]; + int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH); + if (width < 0 || width >= U_EA_COUNT) + width = PROPERTY_UNDEFINED; + + dest[i] = width; + } + } + +EA_END: + env->ReleaseCharArrayElements(srcArray, src, JNI_ABORT); + env->ReleaseByteArrayElements(destArray, dest, JNI_ABORT); +} + static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count) { jchar* data = env->GetCharArrayElements(charArray, NULL); @@ -140,6 +195,10 @@ static jchar getMirror(JNIEnv* env, jobject obj, jchar c) static JNINativeMethod gMethods[] = { { "getDirectionalities", "([C[BI)V", (void*) getDirectionalities }, + { "getEastAsianWidth", "(C)I", + (void*) getEastAsianWidth }, + { "getEastAsianWidths", "([CII[B)V", + (void*) getEastAsianWidths }, { "mirror", "([CII)Z", (void*) mirror }, { "getMirror", "(C)C", |