| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| #include "AndroidSystemNatives.h" |
| #include <JNIHelp.h> |
| #include "ErrorCode.h" |
| #include "unicode/ubidi.h" |
| #include <stdlib.h> |
| #include <string.h> |
| |
| struct BiDiData { |
| BiDiData(UBiDi* biDi) : mBiDi(biDi), embeddingLevels(NULL) { |
| } |
| ~BiDiData() { |
| ubidi_close(mBiDi); |
| delete[] embeddingLevels; |
| } |
| UBiDi* mBiDi; |
| jbyte* embeddingLevels; |
| }; |
| |
| static BiDiData* biDiData(jlong ptr) { |
| return reinterpret_cast<BiDiData*>(static_cast<uintptr_t>(ptr)); |
| } |
| |
| static jlong BidiWrapper_ubidi_open(JNIEnv* env, jclass) { |
| return reinterpret_cast<uintptr_t>(new BiDiData(ubidi_open())); |
| } |
| |
| static void BidiWrapper_ubidi_close(JNIEnv* env, jclass, jlong ptr) { |
| delete biDiData(ptr); |
| } |
| |
| static void BidiWrapper_ubidi_setPara(JNIEnv* env, jclass, jlong ptr, jcharArray text, jint length, jbyte paraLevel, jbyteArray newEmbeddingLevels) { |
| BiDiData* data = biDiData(ptr); |
| jbyte* oldEmbeddingLevels = data->embeddingLevels; |
| // Copy the new embedding levels from the Java heap to the native heap. |
| if (newEmbeddingLevels != NULL) { |
| data->embeddingLevels = new jbyte[length]; |
| env->GetByteArrayRegion(newEmbeddingLevels, 0, length, data->embeddingLevels); |
| } else { |
| data->embeddingLevels = NULL; |
| } |
| UErrorCode err = U_ZERO_ERROR; |
| jchar* _text = env->GetCharArrayElements(text, NULL); |
| ubidi_setPara(data->mBiDi, _text, length, paraLevel, (UBiDiLevel*) data->embeddingLevels, &err); |
| env->ReleaseCharArrayElements(text, _text, 0); |
| delete[] oldEmbeddingLevels; |
| icu4jni_error(env, err); |
| } |
| |
| static jlong BidiWrapper_ubidi_setLine(JNIEnv* env, jclass, jlong ptr, jint start, jint limit) { |
| UErrorCode err = U_ZERO_ERROR; |
| UBiDi* sized = ubidi_openSized(limit - start, 0, &err); |
| if (icu4jni_error(env, err)) { |
| return 0; |
| } |
| BiDiData* lineData = new BiDiData(sized); |
| BiDiData* data = biDiData(ptr); |
| ubidi_setLine(data->mBiDi, start, limit, lineData->mBiDi, &err); |
| icu4jni_error(env, err); |
| return reinterpret_cast<uintptr_t>(lineData); |
| } |
| |
| static jint BidiWrapper_ubidi_getDirection(JNIEnv * env, jclass clazz, jlong ptr) { |
| return ubidi_getDirection(biDiData(ptr)->mBiDi); |
| } |
| |
| static jint BidiWrapper_ubidi_getLength(JNIEnv* env, jclass, jlong ptr) { |
| return ubidi_getLength(biDiData(ptr)->mBiDi); |
| } |
| |
| static jbyte BidiWrapper_ubidi_getParaLevel(JNIEnv* env, jclass, jlong ptr) { |
| return ubidi_getParaLevel(biDiData(ptr)->mBiDi); |
| } |
| |
| static jbyteArray BidiWrapper_ubidi_getLevels(JNIEnv* env, jclass, jlong ptr) { |
| BiDiData* data = biDiData(ptr); |
| UErrorCode err = U_ZERO_ERROR; |
| const UBiDiLevel* levels = ubidi_getLevels(data->mBiDi, &err); |
| if (icu4jni_error(env, err)) { |
| return NULL; |
| } |
| int len = ubidi_getLength(data->mBiDi); |
| jbyteArray result = env->NewByteArray(len); |
| env->SetByteArrayRegion(result, 0, len, reinterpret_cast<const jbyte*>(levels)); |
| return result; |
| } |
| |
| static jint BidiWrapper_ubidi_countRuns(JNIEnv* env, jclass, jlong ptr) { |
| BiDiData* data = biDiData(ptr); |
| UErrorCode err = U_ZERO_ERROR; |
| int count = ubidi_countRuns(data->mBiDi, &err); |
| icu4jni_error(env, err); |
| return count; |
| } |
| |
| static jobjectArray BidiWrapper_ubidi_getRuns(JNIEnv* env, jclass, jlong ptr) { |
| BiDiData* data = biDiData(ptr); |
| UErrorCode err = U_ZERO_ERROR; |
| int runCount = ubidi_countRuns(data->mBiDi, &err); |
| if (icu4jni_error(env, err)) { |
| return NULL; |
| } |
| jclass bidiRunClass = env->FindClass("org/apache/harmony/text/BidiRun"); |
| jmethodID bidiRunConstructor = env->GetMethodID(bidiRunClass, "<init>", "(III)V"); |
| jobjectArray runs = env->NewObjectArray(runCount, bidiRunClass, NULL); |
| UBiDiLevel level = 0; |
| int start = 0; |
| int limit = 0; |
| for (int i = 0; i < runCount; ++i) { |
| ubidi_getLogicalRun(data->mBiDi, start, &limit, &level); |
| jobject run = env->NewObject(bidiRunClass, bidiRunConstructor, start, limit, level); |
| env->SetObjectArrayElement(runs, i, run); |
| start = limit; |
| } |
| return runs; |
| } |
| |
| static jintArray BidiWrapper_ubidi_reorderVisual(JNIEnv* env, jclass, jbyteArray levels, jint length) { |
| int* local_indexMap = new int[length]; |
| jbyte* local_levelBytes = env->GetByteArrayElements(levels, NULL); |
| UBiDiLevel* local_levels = reinterpret_cast<UBiDiLevel*>(local_levelBytes); |
| ubidi_reorderVisual(local_levels, length, local_indexMap); |
| jintArray result = env->NewIntArray(length); |
| env->SetIntArrayRegion(result, 0, length, local_indexMap); |
| delete[] local_indexMap; |
| env->ReleaseByteArrayElements(levels, local_levelBytes, 0); |
| return result; |
| } |
| |
| static JNINativeMethod gMethods[] = { |
| { "ubidi_close", "(J)V", (void*) BidiWrapper_ubidi_close }, |
| { "ubidi_countRuns", "(J)I", (void*) BidiWrapper_ubidi_countRuns }, |
| { "ubidi_getDirection", "(J)I", (void*) BidiWrapper_ubidi_getDirection }, |
| { "ubidi_getLength", "(J)I", (void*) BidiWrapper_ubidi_getLength }, |
| { "ubidi_getLevels", "(J)[B", (void*) BidiWrapper_ubidi_getLevels }, |
| { "ubidi_getParaLevel", "(J)B", (void*) BidiWrapper_ubidi_getParaLevel }, |
| { "ubidi_getRuns", "(J)[Lorg/apache/harmony/text/BidiRun;", (void*) BidiWrapper_ubidi_getRuns }, |
| { "ubidi_open", "()J", (void*) BidiWrapper_ubidi_open }, |
| { "ubidi_reorderVisual", "([BI)[I", (void*) BidiWrapper_ubidi_reorderVisual }, |
| { "ubidi_setLine", "(JII)J", (void*) BidiWrapper_ubidi_setLine }, |
| { "ubidi_setPara", "(J[CIB[B)V", (void*) BidiWrapper_ubidi_setPara }, |
| }; |
| int register_org_apache_harmony_text_BidiWrapper(JNIEnv* env) { |
| return jniRegisterNativeMethods(env, "org/apache/harmony/text/BidiWrapper", |
| gMethods, NELEM(gMethods)); |
| } |