1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /* Header for class sun_font_SunLayoutEngine */
26
27 #include <jni_util.h>
28 #include <stdlib.h>
29
30 #include "FontInstanceAdapter.h"
31 #include "LayoutEngine.h"
32 #include "sun_font_SunLayoutEngine.h"
33 #include "sunfontids.h"
34
35 void getFloat(JNIEnv* env, jobject pt, jfloat &x, jfloat &y) {
36 x = env->GetFloatField(pt, sunFontIDs.xFID);
37 y = env->GetFloatField(pt, sunFontIDs.yFID);
38 }
39
40 void putFloat(JNIEnv* env, jobject pt, jfloat x, jfloat y) {
41 env->SetFloatField(pt, sunFontIDs.xFID, x);
42 env->SetFloatField(pt, sunFontIDs.yFID, y);
43 }
44
45 static jclass gvdClass = 0;
46 static const char* gvdClassName = "sun/font/GlyphLayout$GVData";
47 static jfieldID gvdCountFID = 0;
48 static jfieldID gvdFlagsFID = 0;
49 static jfieldID gvdGlyphsFID = 0;
50 static jfieldID gvdPositionsFID = 0;
51 static jfieldID gvdIndicesFID = 0;
52
53 #define TYPO_RTL 0x80000000
54 #define TYPO_MASK 0x7
55
56 JNIEXPORT void JNICALL
57 Java_sun_font_SunLayoutEngine_initGVIDs
58 (JNIEnv *env, jclass cls) {
59 CHECK_NULL(gvdClass = env->FindClass(gvdClassName));
60 CHECK_NULL(gvdClass = (jclass)env->NewGlobalRef(gvdClass));
61 CHECK_NULL(gvdCountFID = env->GetFieldID(gvdClass, "_count", "I"));
62 CHECK_NULL(gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I"));
63 CHECK_NULL(gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I"));
64 CHECK_NULL(gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F"));
65 gvdIndicesFID = env->GetFieldID(gvdClass, "_indices", "[I");
66 }
67
68 int putGV(JNIEnv* env, jint gmask, jint baseIndex, jobject gvdata, const LayoutEngine* engine, int glyphCount) {
69 int count = env->GetIntField(gvdata, gvdCountFID);
70 if (count < 0) {
71 JNU_ThrowInternalError(env, "count negative");
72 return 0;
73 }
74
75 jarray glyphArray = (jarray)env->GetObjectField(gvdata, gvdGlyphsFID);
76 if (IS_NULL(glyphArray)) {
77 JNU_ThrowInternalError(env, "glypharray null");
78 return 0;
79 }
80 jint capacity = env->GetArrayLength(glyphArray);
81 if (count + glyphCount > capacity) {
82 JNU_ThrowArrayIndexOutOfBoundsException(env, "");
83 return 0;
84 }
85
86 jarray posArray = (jarray)env->GetObjectField(gvdata, gvdPositionsFID);
87 if (IS_NULL(glyphArray)) {
88 JNU_ThrowInternalError(env, "positions array null");
89 return 0;
90 }
91 jarray inxArray = (jarray)env->GetObjectField(gvdata, gvdIndicesFID);
92 if (IS_NULL(inxArray)) {
93 JNU_ThrowInternalError(env, "indices array null");
94 return 0;
95 }
96
97 int countDelta = 0;
98
99 // le_uint32 is the same size as jint... forever, we hope
100 le_uint32* glyphs = (le_uint32*)env->GetPrimitiveArrayCritical(glyphArray, NULL);
101 if (glyphs) {
102 jfloat* positions = (jfloat*)env->GetPrimitiveArrayCritical(posArray, NULL);
103 if (positions) {
104 jint* indices = (jint*)env->GetPrimitiveArrayCritical(inxArray, NULL);
105 if (indices) {
106 LEErrorCode status = (LEErrorCode)0;
107 engine->getGlyphs(glyphs + count, gmask, status);
108 engine->getGlyphPositions(positions + (count * 2), status);
109 engine->getCharIndices((le_int32*)(indices + count), baseIndex, status);
110
111 countDelta = glyphCount;
112
113 // !!! need engine->getFlags to signal positions, indices data
114 /* "0" arg used instead of JNI_COMMIT as we want the carray
115 * to be freed by any VM that actually passes us a copy.
116 */
117 env->ReleasePrimitiveArrayCritical(inxArray, indices, 0);
118 }
119 env->ReleasePrimitiveArrayCritical(posArray, positions, 0);
120 }
121 env->ReleasePrimitiveArrayCritical(glyphArray, glyphs, 0);
122 }
123
124 if (countDelta) {
125 count += countDelta;
126 env->SetIntField(gvdata, gvdCountFID, count);
127 }
128
129 return 1;
130 }
131
132 /*
133 * Class: sun_font_SunLayoutEngine
134 * Method: nativeLayout
135 * Signature: (Lsun/font/FontStrike;[CIIIIZLjava/awt/geom/Point2D$Float;Lsun/font/GlyphLayout$GVData;)V
136 */
137 JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout
138 (JNIEnv *env, jclass cls, jobject font2d, jobject strike, jfloatArray matrix, jint gmask,
139 jint baseIndex, jcharArray text, jint start, jint limit, jint min, jint max,
140 jint script, jint lang, jint typo_flags, jobject pt, jobject gvdata,
141 jlong upem, jlong layoutTables)
142 {
143 // fprintf(stderr, "nl font: %x strike: %x script: %d\n", font2d, strike, script); fflush(stderr);
144 float mat[4];
145 env->GetFloatArrayRegion(matrix, 0, 4, mat);
146 FontInstanceAdapter fia(env, font2d, strike, mat, 72, 72, (le_int32) upem, (TTLayoutTableCache *) layoutTables);
147 LEErrorCode success = LE_NO_ERROR;
148 LayoutEngine *engine = LayoutEngine::layoutEngineFactory(&fia, script, lang, typo_flags & TYPO_MASK, success);
149 if (engine == NULL) {
150 env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
151 return;
152 }
153
154 if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */
155 // have to copy, yuck, since code does upcalls now. this will be soooo slow
156 jint len = max - min;
157 jchar buffer[256];
158 jchar* chars = buffer;
159 if (len > 256) {
160 size_t size = len * sizeof(jchar);
161 if (size / sizeof(jchar) != (size_t)len) {
162 return;
163 }
164 chars = (jchar*)malloc(size);
165 if (chars == 0) {
166 return;
167 }
168 }
169 // fprintf(stderr, "nl chars: %x text: %x min %d len %d typo %x\n", chars, text, min, len, typo_flags); fflush(stderr);
170
171 env->GetCharArrayRegion(text, min, len, chars);
172
173 jfloat x, y;
174 getFloat(env, pt, x, y);
175 jboolean rtl = (typo_flags & TYPO_RTL) != 0;
176 int glyphCount = engine->layoutChars(chars, start - min, limit - start, len, rtl, x, y, success);
177 // fprintf(stderr, "sle nl len %d -> gc: %d\n", len, glyphCount); fflush(stderr);
178
179 engine->getGlyphPosition(glyphCount, x, y, success);
180
181 // fprintf(stderr, "layout glyphs: %d x: %g y: %g\n", glyphCount, x, y); fflush(stderr);
182 if (LE_FAILURE(success)) {
183 env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
184 } else {
185 if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) {
186 if (!(env->ExceptionCheck())) {
187 // !!! hmmm, could use current value in positions array of GVData...
188 putFloat(env, pt, x, y);
189 }
190 }
191 }
192
193 if (chars != buffer) {
194 free(chars);
195 }
196
197 delete engine;
198
199 }
--- EOF ---