summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/AndroidBidi.java62
-rw-r--r--core/java/android/text/MeasuredText.java6
-rw-r--r--core/jni/Android.bp1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_text_AndroidBidi.cpp72
-rw-r--r--core/tests/coretests/src/android/text/StaticLayoutBidiTest.java2
6 files changed, 52 insertions, 93 deletions
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index bbe152321a38..179d545f8ccd 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -16,6 +16,11 @@
package android.text;
+import android.icu.lang.UCharacter;
+import android.icu.lang.UCharacterDirection;
+import android.icu.lang.UProperty;
+import android.icu.text.Bidi;
+import android.icu.text.BidiClassifier;
import android.text.Layout.Directions;
import com.android.internal.annotations.VisibleForTesting;
@@ -27,26 +32,57 @@ import com.android.internal.annotations.VisibleForTesting;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AndroidBidi {
- public static int bidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo) {
+ private static class EmojiBidiOverride extends BidiClassifier {
+ EmojiBidiOverride() {
+ super(null /* No persisting object needed */);
+ }
+
+ // Tells ICU to use the standard Unicode value.
+ private static final int NO_OVERRIDE =
+ UCharacter.getIntPropertyMaxValue(UProperty.BIDI_CLASS) + 1;
+
+ @Override
+ public int classify(int c) {
+ if (Emoji.isNewEmoji(c)) {
+ // All new emoji characters in Unicode 10.0 are of the bidi class ON.
+ return UCharacterDirection.OTHER_NEUTRAL;
+ } else {
+ return NO_OVERRIDE;
+ }
+ }
+ }
+
+ private static final EmojiBidiOverride sEmojiBidiOverride = new EmojiBidiOverride();
+
+ /**
+ * Runs the bidi algorithm on input text.
+ */
+ public static int bidi(int dir, char[] chs, byte[] chInfo) {
if (chs == null || chInfo == null) {
throw new NullPointerException();
}
- if (n < 0 || chs.length < n || chInfo.length < n) {
+ final int length = chs.length;
+ if (chInfo.length < length) {
throw new IndexOutOfBoundsException();
}
- switch(dir) {
- case Layout.DIR_REQUEST_LTR: dir = 0; break;
- case Layout.DIR_REQUEST_RTL: dir = 1; break;
- case Layout.DIR_REQUEST_DEFAULT_LTR: dir = -2; break;
- case Layout.DIR_REQUEST_DEFAULT_RTL: dir = -1; break;
- default: dir = 0; break;
+ final byte paraLevel;
+ switch (dir) {
+ case Layout.DIR_REQUEST_LTR: paraLevel = Bidi.LTR; break;
+ case Layout.DIR_REQUEST_RTL: paraLevel = Bidi.RTL; break;
+ case Layout.DIR_REQUEST_DEFAULT_LTR: paraLevel = Bidi.LEVEL_DEFAULT_LTR; break;
+ case Layout.DIR_REQUEST_DEFAULT_RTL: paraLevel = Bidi.LEVEL_DEFAULT_RTL; break;
+ default: paraLevel = Bidi.LTR; break;
}
-
- int result = runBidi(dir, chs, chInfo, n, haveInfo);
- result = (result & 0x1) == 0 ? Layout.DIR_LEFT_TO_RIGHT : Layout.DIR_RIGHT_TO_LEFT;
- return result;
+ final Bidi icuBidi = new Bidi(length /* maxLength */, 0 /* maxRunCount */);
+ icuBidi.setCustomClassifier(sEmojiBidiOverride);
+ icuBidi.setPara(chs, paraLevel, null /* embeddingLevels */);
+ for (int i = 0; i < length; i++) {
+ chInfo[i] = icuBidi.getLevelAt(i);
+ }
+ final byte result = icuBidi.getParaLevel();
+ return (result & 0x1) == 0 ? Layout.DIR_LEFT_TO_RIGHT : Layout.DIR_RIGHT_TO_LEFT;
}
/**
@@ -178,6 +214,4 @@ public class AndroidBidi {
}
return new Directions(ld);
}
-
- private native static int runBidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo);
} \ No newline at end of file
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index b09ccc299b28..ffc44a72c357 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -106,8 +106,8 @@ class MeasuredText {
if (mWidths == null || mWidths.length < len) {
mWidths = ArrayUtils.newUnpaddedFloatArray(len);
}
- if (mChars == null || mChars.length < len) {
- mChars = ArrayUtils.newUnpaddedCharArray(len);
+ if (mChars == null || mChars.length != len) {
+ mChars = new char[len];
}
TextUtils.getChars(text, start, end, mChars, 0);
@@ -151,7 +151,7 @@ class MeasuredText {
boolean isRtl = textDir.isRtl(mChars, 0, len);
bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR;
}
- mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false);
+ mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels);
mEasy = false;
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 256b920ee34a..3043810290f4 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -77,7 +77,6 @@ cc_library_shared {
"android_view_ThreadedRenderer.cpp",
"android_view_VelocityTracker.cpp",
"android_text_AndroidCharacter.cpp",
- "android_text_AndroidBidi.cpp",
"android_text_Hyphenator.cpp",
"android_text_StaticLayout.cpp",
"android_os_Debug.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index deb4d5ab9e8c..a04780e4bea9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -175,7 +175,6 @@ extern int register_android_net_TrafficStats(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_Hyphenator(JNIEnv *env);
extern int register_android_text_StaticLayout(JNIEnv *env);
-extern int register_android_text_AndroidBidi(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
@@ -1324,7 +1323,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_Hyphenator),
REG_JNI(register_android_text_StaticLayout),
- REG_JNI(register_android_text_AndroidBidi),
REG_JNI(register_android_view_InputDevice),
REG_JNI(register_android_view_KeyCharacterMap),
REG_JNI(register_android_os_Process),
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
deleted file mode 100644
index f72f0f0dc60a..000000000000
--- a/core/jni/android_text_AndroidBidi.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/* //device/libs/android_runtime/android_text_AndroidBidi.cpp
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "AndroidUnicode"
-
-#include <nativehelper/JNIHelp.h>
-#include "core_jni_helpers.h"
-#include "utils/misc.h"
-#include "utils/Log.h"
-#include "unicode/ubidi.h"
-#include <minikin/Emoji.h>
-
-namespace android {
-
-static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
- jbyteArray infoArray, jint n, jboolean haveInfo)
-{
- // Parameters are checked on java side
- // Failures from GetXXXArrayElements indicate a serious out-of-memory condition
- // that we don't bother to report, we're probably dead anyway.
- jint result = 0;
- jchar* chs = env->GetCharArrayElements(chsArray, NULL);
- if (chs != NULL) {
- jbyte* info = env->GetByteArrayElements(infoArray, NULL);
- if (info != NULL) {
- UErrorCode status = U_ZERO_ERROR;
- UBiDi* bidi = ubidi_openSized(n, 0, &status);
- // Set callbacks to override bidi classes of new emoji
- ubidi_setClassCallback(
- bidi, minikin::emojiBidiOverride, nullptr, nullptr, nullptr, &status);
- ubidi_setPara(bidi, reinterpret_cast<const UChar*>(chs), n, dir, NULL, &status);
- if (U_SUCCESS(status)) {
- for (int i = 0; i < n; ++i) {
- info[i] = ubidi_getLevelAt(bidi, i);
- }
- result = ubidi_getParaLevel(bidi);
- } else {
- jniThrowException(env, "java/lang/RuntimeException", NULL);
- }
- ubidi_close(bidi);
-
- env->ReleaseByteArrayElements(infoArray, info, 0);
- }
- env->ReleaseCharArrayElements(chsArray, chs, JNI_ABORT);
- }
- return result;
-}
-
-static const JNINativeMethod gMethods[] = {
- { "runBidi", "(I[C[BIZ)I", (void*) runBidi }
-};
-
-int register_android_text_AndroidBidi(JNIEnv* env)
-{
- return RegisterMethodsOrDie(env, "android/text/AndroidBidi", gMethods, NELEM(gMethods));
-}
-
-}
diff --git a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
index d16cce8b40b3..8092203033c2 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
@@ -96,7 +96,7 @@ public class StaticLayoutBidiTest {
int n = chs.length;
byte[] chInfo = new byte[n];
- int resultDir = AndroidBidi.bidi(dir, chs, chInfo, n, false);
+ int resultDir = AndroidBidi.bidi(dir, chs, chInfo);
{
StringBuilder sb = new StringBuilder("info:");