Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a15fd848 authored by Roozbeh Pournader's avatar Roozbeh Pournader
Browse files

Replace JNI portion of AndroidBidi with calls to ICU4J

We no longer need the native calls to ICU since we have ICU4J.

Fixes: 67786879
Test: bit FrameworksCoreTests:android.text.
Change-Id: Ib2ec93017000b4f0343756814ca388bd31457849
parent f73f9ed5
Loading
Loading
Loading
Loading
+48 −14
Original line number Original line Diff line number Diff line
@@ -16,6 +16,11 @@


package android.text;
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 android.text.Layout.Directions;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -27,26 +32,57 @@ import com.android.internal.annotations.VisibleForTesting;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AndroidBidi {
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) {
        if (chs == null || chInfo == null) {
            throw new NullPointerException();
            throw new NullPointerException();
        }
        }


        if (n < 0 || chs.length < n || chInfo.length < n) {
        final int length = chs.length;
        if (chInfo.length < length) {
            throw new IndexOutOfBoundsException();
            throw new IndexOutOfBoundsException();
        }
        }


        final byte paraLevel;
        switch (dir) {
        switch (dir) {
            case Layout.DIR_REQUEST_LTR: dir = 0; break;
            case Layout.DIR_REQUEST_LTR: paraLevel = Bidi.LTR; break;
            case Layout.DIR_REQUEST_RTL: dir = 1; break;
            case Layout.DIR_REQUEST_RTL: paraLevel = Bidi.RTL; break;
            case Layout.DIR_REQUEST_DEFAULT_LTR: dir = -2; break;
            case Layout.DIR_REQUEST_DEFAULT_LTR: paraLevel = Bidi.LEVEL_DEFAULT_LTR; break;
            case Layout.DIR_REQUEST_DEFAULT_RTL: dir = -1; break;
            case Layout.DIR_REQUEST_DEFAULT_RTL: paraLevel = Bidi.LEVEL_DEFAULT_RTL; break;
            default: dir = 0; break;
            default: paraLevel = Bidi.LTR; break;
        }
        }

        final Bidi icuBidi = new Bidi(length /* maxLength */, 0 /* maxRunCount */);
        int result = runBidi(dir, chs, chInfo, n, haveInfo);
        icuBidi.setCustomClassifier(sEmojiBidiOverride);
        result = (result & 0x1) == 0 ? Layout.DIR_LEFT_TO_RIGHT : Layout.DIR_RIGHT_TO_LEFT;
        icuBidi.setPara(chs, paraLevel, null /* embeddingLevels */);
        return result;
        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);
        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
+3 −3
Original line number Original line Diff line number Diff line
@@ -106,8 +106,8 @@ class MeasuredText {
        if (mWidths == null || mWidths.length < len) {
        if (mWidths == null || mWidths.length < len) {
            mWidths = ArrayUtils.newUnpaddedFloatArray(len);
            mWidths = ArrayUtils.newUnpaddedFloatArray(len);
        }
        }
        if (mChars == null || mChars.length < len) {
        if (mChars == null || mChars.length != len) {
            mChars = ArrayUtils.newUnpaddedCharArray(len);
            mChars = new char[len];
        }
        }
        TextUtils.getChars(text, start, end, mChars, 0);
        TextUtils.getChars(text, start, end, mChars, 0);


@@ -151,7 +151,7 @@ class MeasuredText {
                boolean isRtl = textDir.isRtl(mChars, 0, len);
                boolean isRtl = textDir.isRtl(mChars, 0, len);
                bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR;
                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;
            mEasy = false;
        }
        }
    }
    }
+0 −1
Original line number Original line Diff line number Diff line
@@ -77,7 +77,6 @@ cc_library_shared {
        "android_view_ThreadedRenderer.cpp",
        "android_view_ThreadedRenderer.cpp",
        "android_view_VelocityTracker.cpp",
        "android_view_VelocityTracker.cpp",
        "android_text_AndroidCharacter.cpp",
        "android_text_AndroidCharacter.cpp",
        "android_text_AndroidBidi.cpp",
        "android_text_Hyphenator.cpp",
        "android_text_Hyphenator.cpp",
        "android_text_StaticLayout.cpp",
        "android_text_StaticLayout.cpp",
        "android_os_Debug.cpp",
        "android_os_Debug.cpp",
+0 −2
Original line number Original line Diff line number Diff line
@@ -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_AndroidCharacter(JNIEnv *env);
extern int register_android_text_Hyphenator(JNIEnv *env);
extern int register_android_text_Hyphenator(JNIEnv *env);
extern int register_android_text_StaticLayout(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_opengl_classes(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_android_server_NetworkManagementSocketTagger(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_AndroidCharacter),
    REG_JNI(register_android_text_Hyphenator),
    REG_JNI(register_android_text_Hyphenator),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_text_AndroidBidi),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_Process),
+0 −72
Original line number Original line Diff line number Diff line
/* //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));
}

}
Loading