1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. 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 #include <stdlib.h>
19 #include <unicode/ubidi.h>
20 #include <string.h>
21 #include "BidiWrapperInterface.h"
22
23 typedef struct {
24 UBiDi *pBiDi;
25 void *embeddingLevels;
26 } BiDiData;
27
28 void check_fail (JNIEnv * env, int err);
29
Java_org_apache_harmony_text_BidiWrapper_ubidi_1open(JNIEnv * env,jclass clazz)30 JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1open
31 (JNIEnv * env, jclass clazz)
32 {
33 BiDiData *data = (BiDiData *)malloc(sizeof(BiDiData));
34 (*data).pBiDi = ubidi_open ();
35 (*data).embeddingLevels = NULL;
36 return (jlong) (data);
37 }
38
Java_org_apache_harmony_text_BidiWrapper_ubidi_1close(JNIEnv * env,jclass clazz,jlong pBiDi)39 JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1close
40 (JNIEnv * env, jclass clazz, jlong pBiDi)
41 {
42 BiDiData *data = (BiDiData *)pBiDi;
43
44 ubidi_close ((*data).pBiDi);
45
46 if ((*data).embeddingLevels != NULL)
47 free((*data).embeddingLevels);
48 free(data);
49 }
50
Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara(JNIEnv * env,jclass clazz,jlong pBiDi,jcharArray text,jint length,jbyte paraLevel,jbyteArray embeddingLevels)51 JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara
52 (JNIEnv * env, jclass clazz, jlong pBiDi, jcharArray text, jint length,
53 jbyte paraLevel, jbyteArray embeddingLevels)
54 {
55 UErrorCode err = 0;
56 jchar *_text = NULL;
57 BiDiData *data = (BiDiData *)pBiDi;
58 /* Remembering old embedding levels */
59 void *embLvls = (*data).embeddingLevels;
60
61 _text = (*env)->GetCharArrayElements (env, text, NULL);
62
63 if (embeddingLevels != NULL)
64 {
65 jbyte *el = (*env)->GetByteArrayElements (env, embeddingLevels, NULL);
66 (*data).embeddingLevels = malloc(length);
67 memcpy(((*data).embeddingLevels), el, length);
68 (*env)->ReleaseByteArrayElements (env, embeddingLevels, el, 0);
69 } else
70 {
71 (*data).embeddingLevels = NULL;
72 }
73
74 ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
75 ((*data).embeddingLevels), &err);
76 check_fail (env, err);
77
78 /* Freeing old embedding levels */
79 if (embLvls != NULL) {
80 free(embLvls);
81 }
82
83 (*env)->ReleaseCharArrayElements (env, text, _text, 0);
84 }
85
Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine(JNIEnv * env,jclass clazz,jlong pBiDi,jint start,jint limit)86 JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine
87 (JNIEnv * env, jclass clazz, jlong pBiDi, jint start, jint limit)
88 {
89 UErrorCode err = 0;
90 BiDiData *data = (BiDiData *)pBiDi;
91 BiDiData *lineData = (BiDiData *) malloc(sizeof(BiDiData));
92 (*lineData).embeddingLevels = NULL;
93
94 (*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
95 check_fail (env, err);
96
97 ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi,
98 &err);
99 check_fail (env, err);
100
101 return (jlong) lineData;
102 }
103
Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection(JNIEnv * env,jclass clazz,jlong pBiDi)104 JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection
105 (JNIEnv * env, jclass clazz, jlong pBiDi)
106 {
107 BiDiData *data = (BiDiData *)pBiDi;
108 return ubidi_getDirection ((*data).pBiDi);
109 }
110
Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLength(JNIEnv * env,jclass clazz,jlong pBiDi)111 JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLength
112 (JNIEnv * env, jclass clazz, jlong pBiDi)
113 {
114 BiDiData *data = (BiDiData *)pBiDi;
115 return ubidi_getLength ((*data).pBiDi);
116 }
117
Java_org_apache_harmony_text_BidiWrapper_ubidi_1getParaLevel(JNIEnv * env,jclass clazz,jlong pBiDi)118 JNIEXPORT jbyte JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getParaLevel
119 (JNIEnv * env, jclass clazz, jlong pBiDi)
120 {
121 BiDiData *data = (BiDiData *)pBiDi;
122 return ubidi_getParaLevel ((*data).pBiDi);
123 }
124
Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels(JNIEnv * env,jclass clazz,jlong pBiDi)125 JNIEXPORT jbyteArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels
126 (JNIEnv * env, jclass clazz, jlong pBiDi)
127 {
128 UErrorCode err = 0;
129 const UBiDiLevel *levels = NULL;
130 jbyteArray result = NULL;
131 int len = 0;
132 BiDiData *data = (BiDiData *)pBiDi;
133
134 levels = ubidi_getLevels ((*data).pBiDi, &err);
135 check_fail (env, err);
136
137 len = ubidi_getLength ((*data).pBiDi);
138 result = (*env)->NewByteArray (env, len);
139 (*env)->SetByteArrayRegion (env, result, 0, len, (jbyte *) levels);
140
141 return result;
142 }
143
Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns(JNIEnv * env,jclass clazz,jlong pBiDi)144 JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns
145 (JNIEnv * env, jclass clazz, jlong pBiDi)
146 {
147 UErrorCode err = 0;
148 BiDiData *data = (BiDiData *)pBiDi;
149
150 int count = ubidi_countRuns ((*data).pBiDi, &err);
151 check_fail (env, err);
152
153 return count;
154 }
155
Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns(JNIEnv * env,jclass clz,jlong pBiDi)156 JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns
157 (JNIEnv * env, jclass clz, jlong pBiDi)
158 {
159 int runCount = 0;
160 int start = 0;
161 int limit = 0;
162 int i = 0;
163 UBiDiLevel level = 0;
164 jclass run_clazz = 0;
165 jmethodID initID = 0;
166 jobject run = 0;
167 jobjectArray runs;
168 UErrorCode err = 0;
169 BiDiData *data = (BiDiData *)pBiDi;
170
171 run_clazz = (*env)->FindClass (env, "org/apache/harmony/text/BidiRun");
172 initID = (*env)->GetMethodID (env, run_clazz, "<init>", "(III)V");
173
174 runCount = ubidi_countRuns ((*data).pBiDi, &err);
175 check_fail (env, err);
176
177 runs = (*env)->NewObjectArray(env, runCount,run_clazz, NULL);
178 for (i = 0; i < runCount; i++) {
179 ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
180 run = (*env)->NewObject (env, run_clazz, initID, start, limit, level);
181 (*env)->SetObjectArrayElement(env, runs, i, run);
182 start = limit;
183 }
184 return runs;
185 }
186
187 void
check_fail(JNIEnv * env,int err)188 check_fail (JNIEnv * env, int err)
189 {
190 char message[] = "ICU Internal Error: ";
191
192 if (U_FAILURE (err))
193 {
194 sprintf (message, "ICU Internal Error: %d", err);
195 jniThrowException(env, "java/lang/RuntimeException",
196 message);
197 }
198 }
199
Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual(JNIEnv * env,jclass clazz,jbyteArray levels,jint length)200 JNIEXPORT jintArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual
201 (JNIEnv * env, jclass clazz, jbyteArray levels, jint length)
202 {
203 UBiDiLevel *local_levels = 0;
204 int *local_indexMap = 0;
205 jintArray result = 0;
206
207 local_indexMap = (int *) malloc(sizeof (int) * length);
208 local_levels = (*env)->GetByteArrayElements (env, levels, NULL);
209
210 ubidi_reorderVisual (local_levels, length, local_indexMap);
211
212 result = (*env)->NewIntArray (env, length);
213 (*env)->SetIntArrayRegion (env, result, 0, length, (jint *) local_indexMap);
214
215 free(local_indexMap);
216 (*env)->ReleaseByteArrayElements (env, levels, local_levels, 0);
217
218 return result;
219 }
220
221 /*
222 * JNI registration
223 */
224 static JNINativeMethod gMethods[] = {
225 /* NAME , SIGNATURE , FUNCPTR */
226 { "ubidi_open" , "()J" ,
227 Java_org_apache_harmony_text_BidiWrapper_ubidi_1open },
228 { "ubidi_close" , "(J)V" ,
229 Java_org_apache_harmony_text_BidiWrapper_ubidi_1close },
230 { "ubidi_setPara" , "(J[CIB[B)V" ,
231 Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara },
232 { "ubidi_setLine" , "(JII)J" ,
233 Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine },
234 { "ubidi_getDirection" , "(J)I" ,
235 Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection },
236 { "ubidi_getLength" , "(J)I" ,
237 Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLength },
238 { "ubidi_getParaLevel" , "(J)B" ,
239 Java_org_apache_harmony_text_BidiWrapper_ubidi_1getParaLevel },
240 { "ubidi_getLevels" , "(J)[B" ,
241 Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels },
242 { "ubidi_countRuns" , "(J)I" ,
243 Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns },
244 { "ubidi_getRuns" , "(J)[Lorg/apache/harmony/text/BidiRun;",
245 Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns },
246 { "ubidi_reorderVisual", "([BI)[I" ,
247 Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual },
248 };
register_org_apache_harmony_text_BidiWrapper(JNIEnv * env)249 int register_org_apache_harmony_text_BidiWrapper(JNIEnv *env)
250 {
251 return jniRegisterNativeMethods(env, "org/apache/harmony/text/BidiWrapper",
252 gMethods, NELEM(gMethods));
253 }
254