1/* //device/libs/android_runtime/android_text_AndroidBidi.cpp
2**
3** Copyright 2010, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "AndroidUnicode"
19
20#include <nativehelper/JNIHelp.h>
21#include "core_jni_helpers.h"
22#include "utils/misc.h"
23#include "utils/Log.h"
24#include "unicode/ubidi.h"
25#include <minikin/Emoji.h>
26
27namespace android {
28
29static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
30                    jbyteArray infoArray, jint n, jboolean haveInfo)
31{
32    // Parameters are checked on java side
33    // Failures from GetXXXArrayElements indicate a serious out-of-memory condition
34    // that we don't bother to report, we're probably dead anyway.
35    jint result = 0;
36    jchar* chs = env->GetCharArrayElements(chsArray, NULL);
37    if (chs != NULL) {
38        jbyte* info = env->GetByteArrayElements(infoArray, NULL);
39        if (info != NULL) {
40            UErrorCode status = U_ZERO_ERROR;
41            UBiDi* bidi = ubidi_openSized(n, 0, &status);
42            // Set callbacks to override bidi classes of new emoji
43            ubidi_setClassCallback(
44                    bidi, minikin::emojiBidiOverride, nullptr, nullptr, nullptr, &status);
45            ubidi_setPara(bidi, reinterpret_cast<const UChar*>(chs), n, dir, NULL, &status);
46            if (U_SUCCESS(status)) {
47                for (int i = 0; i < n; ++i) {
48                  info[i] = ubidi_getLevelAt(bidi, i);
49                }
50                result = ubidi_getParaLevel(bidi);
51            } else {
52                jniThrowException(env, "java/lang/RuntimeException", NULL);
53            }
54            ubidi_close(bidi);
55
56            env->ReleaseByteArrayElements(infoArray, info, 0);
57        }
58        env->ReleaseCharArrayElements(chsArray, chs, JNI_ABORT);
59    }
60    return result;
61}
62
63static const JNINativeMethod gMethods[] = {
64        { "runBidi", "(I[C[BIZ)I", (void*) runBidi }
65};
66
67int register_android_text_AndroidBidi(JNIEnv* env)
68{
69    return RegisterMethodsOrDie(env, "android/text/AndroidBidi", gMethods, NELEM(gMethods));
70}
71
72}
73