0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/* Header for class sun_font_SunLayoutEngine */
0N/A
0N/A#include <jni_util.h>
0N/A#include <stdlib.h>
0N/A
0N/A#include "FontInstanceAdapter.h"
0N/A#include "LayoutEngine.h"
0N/A#include "sun_font_SunLayoutEngine.h"
0N/A#include "sunfontids.h"
0N/A
0N/Avoid getFloat(JNIEnv* env, jobject pt, jfloat &x, jfloat &y) {
0N/A x = env->GetFloatField(pt, sunFontIDs.xFID);
0N/A y = env->GetFloatField(pt, sunFontIDs.yFID);
0N/A}
0N/A
0N/Avoid putFloat(JNIEnv* env, jobject pt, jfloat x, jfloat y) {
0N/A env->SetFloatField(pt, sunFontIDs.xFID, x);
0N/A env->SetFloatField(pt, sunFontIDs.yFID, y);
0N/A}
0N/A
0N/Astatic jclass gvdClass = 0;
0N/Astatic const char* gvdClassName = "sun/font/GlyphLayout$GVData";
0N/Astatic jfieldID gvdCountFID = 0;
0N/Astatic jfieldID gvdFlagsFID = 0;
0N/Astatic jfieldID gvdGlyphsFID = 0;
0N/Astatic jfieldID gvdPositionsFID = 0;
0N/Astatic jfieldID gvdIndicesFID = 0;
0N/A
0N/A#define TYPO_RTL 0x80000000
0N/A#define TYPO_MASK 0x7
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_font_SunLayoutEngine_initGVIDs
0N/A (JNIEnv *env, jclass cls) {
0N/A gvdClass = env->FindClass(gvdClassName);
0N/A if (!gvdClass) {
0N/A JNU_ThrowClassNotFoundException(env, gvdClassName);
0N/A return;
0N/A }
0N/A gvdClass = (jclass)env->NewGlobalRef(gvdClass);
0N/A if (!gvdClass) {
0N/A JNU_ThrowInternalError(env, "could not create global ref");
0N/A return;
0N/A }
0N/A gvdCountFID = env->GetFieldID(gvdClass, "_count", "I");
0N/A if (!gvdCountFID) {
0N/A gvdClass = 0;
0N/A JNU_ThrowNoSuchFieldException(env, "_count");
0N/A return;
0N/A }
0N/A
0N/A gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I");
0N/A if (!gvdFlagsFID) {
0N/A gvdClass = 0;
0N/A JNU_ThrowNoSuchFieldException(env, "_flags");
0N/A return;
0N/A }
0N/A
0N/A gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I");
0N/A if (!gvdGlyphsFID) {
0N/A gvdClass = 0;
0N/A JNU_ThrowNoSuchFieldException(env, "_glyphs");
0N/A return;
0N/A }
0N/A
0N/A gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F");
0N/A if (!gvdPositionsFID) {
0N/A gvdClass = 0;
0N/A JNU_ThrowNoSuchFieldException(env, "_positions");
0N/A return;
0N/A }
0N/A
0N/A gvdIndicesFID = env->GetFieldID(gvdClass, "_indices", "[I");
0N/A if (!gvdIndicesFID) {
0N/A gvdClass = 0;
0N/A JNU_ThrowNoSuchFieldException(env, "_indices");
0N/A return;
0N/A }
0N/A}
0N/A
0N/Aint putGV(JNIEnv* env, jint gmask, jint baseIndex, jobject gvdata, const LayoutEngine* engine, int glyphCount) {
0N/A int count = env->GetIntField(gvdata, gvdCountFID);
0N/A
0N/A jarray glyphArray = (jarray)env->GetObjectField(gvdata, gvdGlyphsFID);
0N/A if (IS_NULL(glyphArray)) {
0N/A JNU_ThrowInternalError(env, "glypharray null");
0N/A return 0;
0N/A }
0N/A jint capacity = env->GetArrayLength(glyphArray);
0N/A if (count + glyphCount > capacity) {
0N/A JNU_ThrowArrayIndexOutOfBoundsException(env, "");
0N/A return 0;
0N/A }
0N/A
0N/A jarray posArray = (jarray)env->GetObjectField(gvdata, gvdPositionsFID);
0N/A if (IS_NULL(glyphArray)) {
0N/A JNU_ThrowInternalError(env, "positions array null");
0N/A return 0;
0N/A }
0N/A jarray inxArray = (jarray)env->GetObjectField(gvdata, gvdIndicesFID);
0N/A if (IS_NULL(inxArray)) {
0N/A JNU_ThrowInternalError(env, "indices array null");
0N/A return 0;
0N/A }
0N/A
0N/A int countDelta = 0;
0N/A
0N/A // le_uint32 is the same size as jint... forever, we hope
0N/A le_uint32* glyphs = (le_uint32*)env->GetPrimitiveArrayCritical(glyphArray, NULL);
0N/A if (glyphs) {
0N/A jfloat* positions = (jfloat*)env->GetPrimitiveArrayCritical(posArray, NULL);
0N/A if (positions) {
0N/A jint* indices = (jint*)env->GetPrimitiveArrayCritical(inxArray, NULL);
0N/A if (indices) {
0N/A LEErrorCode status = (LEErrorCode)0;
0N/A engine->getGlyphs(glyphs + count, gmask, status);
0N/A engine->getGlyphPositions(positions + (count * 2), status);
0N/A engine->getCharIndices((le_int32*)(indices + count), baseIndex, status);
0N/A
0N/A countDelta = glyphCount;
0N/A
0N/A // !!! need engine->getFlags to signal positions, indices data
0N/A /* "0" arg used instead of JNI_COMMIT as we want the carray
0N/A * to be freed by any VM that actually passes us a copy.
0N/A */
0N/A env->ReleasePrimitiveArrayCritical(inxArray, indices, 0);
0N/A }
0N/A env->ReleasePrimitiveArrayCritical(posArray, positions, 0);
0N/A }
0N/A env->ReleasePrimitiveArrayCritical(glyphArray, glyphs, 0);
0N/A }
0N/A
0N/A if (countDelta) {
0N/A count += countDelta;
0N/A env->SetIntField(gvdata, gvdCountFID, count);
0N/A }
0N/A
0N/A return 1;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_font_SunLayoutEngine
0N/A * Method: nativeLayout
0N/A * Signature: (Lsun/font/FontStrike;[CIIIIZLjava/awt/geom/Point2D$Float;Lsun/font/GlyphLayout$GVData;)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout
0N/A (JNIEnv *env, jclass cls, jobject font2d, jobject strike, jfloatArray matrix, jint gmask,
0N/A jint baseIndex, jcharArray text, jint start, jint limit, jint min, jint max,
0N/A jint script, jint lang, jint typo_flags, jobject pt, jobject gvdata,
0N/A jlong upem, jlong layoutTables)
0N/A{
0N/A // fprintf(stderr, "nl font: %x strike: %x script: %d\n", font2d, strike, script); fflush(stderr);
0N/A float mat[4];
0N/A env->GetFloatArrayRegion(matrix, 0, 4, mat);
0N/A FontInstanceAdapter fia(env, font2d, strike, mat, 72, 72, (le_int32) upem, (TTLayoutTableCache *) layoutTables);
0N/A LEErrorCode success = LE_NO_ERROR;
0N/A LayoutEngine *engine = LayoutEngine::layoutEngineFactory(&fia, script, lang, typo_flags & TYPO_MASK, success);
0N/A
0N/A if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */
0N/A // have to copy, yuck, since code does upcalls now. this will be soooo slow
0N/A jint len = max - min;
0N/A jchar buffer[256];
0N/A jchar* chars = buffer;
0N/A if (len > 256) {
4298N/A size_t size = len * sizeof(jchar);
4298N/A if (size / sizeof(jchar) != len) {
4298N/A return;
4298N/A }
4298N/A chars = (jchar*)malloc(size);
0N/A if (chars == 0) {
0N/A return;
0N/A }
0N/A }
0N/A // fprintf(stderr, "nl chars: %x text: %x min %d len %d typo %x\n", chars, text, min, len, typo_flags); fflush(stderr);
0N/A
0N/A env->GetCharArrayRegion(text, min, len, chars);
0N/A
0N/A jfloat x, y;
0N/A getFloat(env, pt, x, y);
0N/A jboolean rtl = (typo_flags & TYPO_RTL) != 0;
0N/A int glyphCount = engine->layoutChars(chars, start - min, limit - start, len, rtl, x, y, success);
6371N/A // fprintf(stderr, "sle nl len %d -> gc: %d\n", len, glyphCount); fflush(stderr);
0N/A
0N/A engine->getGlyphPosition(glyphCount, x, y, success);
0N/A
6371N/A // fprintf(stderr, "layout glyphs: %d x: %g y: %g\n", glyphCount, x, y); fflush(stderr);
6371N/A if (LE_FAILURE(success)) {
6371N/A env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
6371N/A } else {
6371N/A if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) {
6371N/A // !!! hmmm, could use current value in positions array of GVData...
6371N/A putFloat(env, pt, x, y);
6371N/A }
6371N/A }
0N/A
0N/A if (chars != buffer) {
0N/A free(chars);
0N/A }
0N/A
0N/A delete engine;
0N/A
0N/A}