blob: 064379a3f93e3be632ecca1c3f88cc32e75b8dc9 [file]
/*
* 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 <unicode/ubidi.h>
#include <stdlib.h>
#include "vmi.h"
#include "BidiWrapper.h"
#include "exceptions.h"
typedef struct {
UBiDi *pBiDi;
void *embeddingLevels;
} BiDiData;
void check_fail (JNIEnv * env, int err);
JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1open
(JNIEnv * env, jclass clazz)
{
PORT_ACCESS_FROM_ENV (env);
BiDiData *data = (BiDiData *)hymem_allocate_memory(sizeof(BiDiData));
(*data).pBiDi = ubidi_open ();
(*data).embeddingLevels = NULL;
return (jlong) (data);
}
JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1close
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
PORT_ACCESS_FROM_ENV (env);
BiDiData *data = (BiDiData *)pBiDi;
ubidi_close ((*data).pBiDi);
if ((*data).embeddingLevels != NULL)
hymem_free_memory((*data).embeddingLevels);
hymem_free_memory(data);
}
JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara
(JNIEnv * env, jclass clazz, jlong pBiDi, jcharArray text, jint length,
jbyte paraLevel, jbyteArray embeddingLevels)
{
PORT_ACCESS_FROM_ENV (env);
UErrorCode err = 0;
jchar *_text = NULL;
BiDiData *data = (BiDiData *)pBiDi;
/* Remembering old embedding levels */
void *embLvls = (*data).embeddingLevels;
_text = (*env)->GetCharArrayElements (env, text, NULL);
if (embeddingLevels != NULL)
{
jbyte *el = (*env)->GetByteArrayElements (env, embeddingLevels, NULL);
(*data).embeddingLevels = hymem_allocate_memory(length);
memcpy(((*data).embeddingLevels), el, length);
(*env)->ReleaseByteArrayElements (env, embeddingLevels, el, 0);
} else
{
(*data).embeddingLevels = NULL;
}
ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
((*data).embeddingLevels), &err);
check_fail (env, err);
/* Freeing old embedding levels */
if (embLvls != NULL) {
hymem_free_memory(embLvls);
}
(*env)->ReleaseCharArrayElements (env, text, _text, 0);
}
JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine
(JNIEnv * env, jclass clazz, jlong pBiDi, jint start, jint limit)
{
PORT_ACCESS_FROM_ENV (env);
UErrorCode err = 0;
BiDiData *data = (BiDiData *)pBiDi;
BiDiData *lineData = (BiDiData *)hymem_allocate_memory(sizeof(BiDiData));
(*lineData).embeddingLevels = NULL;
(*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
check_fail (env, err);
ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi,
&err);
check_fail (env, err);
return (jlong) lineData;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
BiDiData *data = (BiDiData *)pBiDi;
return ubidi_getDirection ((*data).pBiDi);
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLength
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
BiDiData *data = (BiDiData *)pBiDi;
return ubidi_getLength ((*data).pBiDi);
}
JNIEXPORT jbyte JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getParaLevel
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
BiDiData *data = (BiDiData *)pBiDi;
return ubidi_getParaLevel ((*data).pBiDi);
}
JNIEXPORT jbyteArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
UErrorCode err = 0;
const UBiDiLevel *levels = NULL;
jbyteArray result = NULL;
int len = 0;
BiDiData *data = (BiDiData *)pBiDi;
levels = ubidi_getLevels ((*data).pBiDi, &err);
check_fail (env, err);
len = ubidi_getLength ((*data).pBiDi);
result = (*env)->NewByteArray (env, len);
(*env)->SetByteArrayRegion (env, result, 0, len, (jbyte *) levels);
return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
UErrorCode err = 0;
BiDiData *data = (BiDiData *)pBiDi;
int count = ubidi_countRuns ((*data).pBiDi, &err);
check_fail (env, err);
return count;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns
(JNIEnv * env, jclass clz, jlong pBiDi)
{
int runCount = 0;
int start = 0;
int limit = 0;
int i = 0;
UBiDiLevel level = 0;
jclass run_clazz = 0;
jmethodID initID = 0;
jobject run = 0;
jobjectArray runs;
UErrorCode err = 0;
BiDiData *data = (BiDiData *)pBiDi;
run_clazz = (*env)->FindClass (env, "org/apache/harmony/text/BidiRun");
initID = (*env)->GetMethodID (env, run_clazz, "<init>", "(III)V");
runCount = ubidi_countRuns ((*data).pBiDi, &err);
check_fail (env, err);
runs = (*env)->NewObjectArray(env, runCount,run_clazz, NULL);
for (i = 0; i < runCount; i++) {
ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
run = (*env)->NewObject (env, run_clazz, initID, start, limit, level);
(*env)->SetObjectArrayElement(env, runs, i, run);
start = limit;
}
return runs;
}
void
check_fail (JNIEnv * env, int err)
{
char message[] = "ICU Internal Error: ";
if (U_FAILURE (err))
{
sprintf (message, "ICU Internal Error: %d", err);
throwNewExceptionByName(env, "java/lang/RuntimeException",
message);
}
}
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual
(JNIEnv * env, jclass clazz, jbyteArray levels, jint length)
{
UBiDiLevel *local_levels = 0;
int *local_indexMap = 0;
jintArray result = 0;
PORT_ACCESS_FROM_ENV (env);
local_indexMap = (int *) hymem_allocate_memory (sizeof (int) * length);
local_levels = (*env)->GetByteArrayElements (env, levels, NULL);
ubidi_reorderVisual (local_levels, length, local_indexMap);
result = (*env)->NewIntArray (env, length);
(*env)->SetIntArrayRegion (env, result, 0, length, (jint *) local_indexMap);
hymem_free_memory (local_indexMap);
(*env)->ReleaseByteArrayElements (env, levels, local_levels, 0);
return result;
}