diff --git a/api/current.xml b/api/current.xml
index 91344d6f6cbe0..9c663fed93a57 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -147852,6 +147852,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
count bytes of dest with the
* directionalities from the first count chars of src.
@@ -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
+ * Unicode TR#11. 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 count bytes of dest with the
+ * East Asian Width from the first count chars of
+ * src. East Asian Width is calculated based on
+ * Unicode TR#11. Each entry
+ * in 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 text 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 05d7b73c47ada..1353478f39f46 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",