--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/awt/multi_font.c Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,795 @@
+/*
+ * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * These routines are used for display string with multi font.
+ */
+
+#ifdef HEADLESS
+ #error This file should not be included in headless library
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <jni.h>
+#include <jni_util.h>
+#include <jvm.h>
+#ifndef XAWT
+#include <Xm/Display.h>
+#endif
+#include "awt_Font.h"
+#ifndef XAWT
+#include "awt_Component.h"
+#endif
+#include "awt_MenuItem.h"
+#include "awt_p.h"
+#include "multi_font.h"
+
+extern XFontStruct *loadFont(Display *, char *, int32_t);
+
+extern struct FontIDs fontIDs;
+extern struct MComponentPeerIDs mComponentPeerIDs;
+extern struct MMenuItemPeerIDs mMenuItemPeerIDs;
+extern struct PlatformFontIDs platformFontIDs;
+extern struct MFontPeerIDs mFontPeerIDs;
+
+/*
+ * make string with str + string representation of num
+ * This string is used as tag string of Motif Compound String and FontList.
+ */
+static void
+makeTag(char *str, int32_t num, char *buf)
+{
+ int32_t len = strlen(str);
+
+ strcpy(buf, str);
+ buf[len] = '0' + num % 100;
+ buf[len + 1] = '\0';
+}
+#ifndef XAWT
+jobject
+awtJNI_CreateAndSetGlobalRef(JNIEnv * env, jobject this)
+{
+ jobject gRef;
+
+ gRef = (*env)->NewGlobalRef(env, this);
+
+ JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.jniGlobalRef, gRef);
+
+ return gRef;
+}
+
+struct gRefStruct
+{
+ jobject gRef;
+ struct gRefStruct *next;
+};
+
+static struct gRefStruct *gRefHead = NULL;
+static struct gRefStruct *gRefTail = NULL;
+
+/*
+ * This function is called by components that
+ * are being disposed. It used to invalidate
+ * the global ref immediately, but the awt is
+ * rather full of thread race conditions involving
+ * component disposal and outstanding events.
+ * Now we queue up 'to be deleted' global refs
+ * as they come in, and don't invalidate them
+ * until the X event queue is empty. Callers of
+ * either of these functions _must_ have AWT_LOCK'd
+ * before using them!
+ */
+void
+awtJNI_DeleteGlobalRef(JNIEnv * env, jobject this)
+{
+ jobject gRef;
+ struct gRefStruct *newGRef;
+ struct gRefStruct *temp;
+
+ gRef = (jobject)
+ JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.jniGlobalRef);
+ JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.jniGlobalRef, NULL);
+
+ /*
+ * Verra handy for tracking down race conditions. If you
+ * have a peer getting called after its been disposed...
+ */
+ /* jio_fprintf(stderr,"%p\n",(void *)gRef); */
+
+ newGRef = (struct gRefStruct *)malloc((size_t)sizeof(struct gRefStruct));
+
+ if(newGRef == NULL)
+ (*env)->DeleteGlobalRef(env, gRef);
+ else
+ {
+ newGRef->gRef = gRef;
+ newGRef->next = NULL;
+
+ if(gRefHead == NULL)
+ {
+ gRefTail = newGRef;
+ gRefHead = newGRef;
+ }
+ else
+ {
+ gRefTail->next = newGRef;
+ gRefTail = newGRef;
+ }
+ }
+}
+
+void
+awtJNI_DeleteGlobalMenuRef(JNIEnv * env, jobject this)
+{
+ jobject gRef;
+ struct gRefStruct *newGRef;
+ struct gRefStruct *temp;
+
+ gRef = (jobject)
+ JNU_GetLongFieldAsPtr(env, this, mMenuItemPeerIDs.jniGlobalRef);
+ JNU_SetLongFieldFromPtr(env, this, mMenuItemPeerIDs.jniGlobalRef, NULL);
+
+ /*
+ * Verra handy for tracking down race conditions. If you
+ * have a peer getting called after its been disposed...
+ */
+ /* jio_fprintf(stderr,"%p\n",(void *)gRef); */
+
+ newGRef = (struct gRefStruct *)malloc((size_t)sizeof(struct gRefStruct));
+
+ if(newGRef == NULL)
+ (*env)->DeleteGlobalRef(env, gRef);
+ else
+ {
+ newGRef->gRef = gRef;
+ newGRef->next = NULL;
+
+ if(gRefHead == NULL)
+ {
+ gRefTail = newGRef;
+ gRefHead = newGRef;
+ }
+ else
+ {
+ gRefTail->next = newGRef;
+ gRefTail = newGRef;
+ }
+ }
+}
+
+void awtJNI_CleanupGlobalRefs()
+{
+ struct gRefStruct *working,*next;
+ JNIEnv *env;
+ int32_t count = 0;
+
+ if(gRefHead == NULL) {
+ return;
+ }
+
+ env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ working = gRefHead;
+ gRefHead = gRefTail = NULL;
+
+ while(working != NULL)
+ {
+ count++;
+ next = working->next;
+ (*env)->DeleteGlobalRef(env, working->gRef);
+
+ free((void *)working);
+
+ working = next;
+ }
+}
+#endif
+static int32_t
+awtJNI_GetFontDescriptorNumber(JNIEnv * env
+ ,jobject font
+ ,jobject fd)
+{
+ int32_t i = 0, num;
+ /* initialize to NULL so that DeleteLocalRef will work. */
+ jobjectArray componentFonts = NULL;
+ jobject peer = NULL;
+ jobject temp = NULL;
+ jboolean validRet = JNI_FALSE;
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+ goto done;
+
+ peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
+ if (peer == NULL)
+ goto done;
+
+ componentFonts = (jobjectArray)
+ (*env)->GetObjectField(env,peer,platformFontIDs.componentFonts);
+
+ if (componentFonts == NULL)
+ goto done;
+
+ num = (*env)->GetArrayLength(env, componentFonts);
+
+ for (i = 0; i < num; i++) {
+ temp = (*env)->GetObjectArrayElement(env, componentFonts, i);
+
+ if ((*env)->IsSameObject(env, fd, temp)) {
+ validRet = JNI_TRUE;
+ break;
+ }
+ (*env)->DeleteLocalRef(env, temp);
+ }
+
+ done:
+ (*env)->DeleteLocalRef(env, peer);
+ (*env)->DeleteLocalRef(env, componentFonts);
+
+ if (validRet)
+ return i;
+
+ return 0;
+}
+#ifndef XAWT
+jobject
+awtJNI_GetFont(JNIEnv * env, jobject this)
+{
+ jobject target = NULL;
+ jobject font = NULL;
+
+ target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
+ // SECURITY: Must call _NoClientCode() methods to ensure that we
+ // are not invoking client code on the privileged thread
+ font = JNU_CallMethodByName(env,
+ NULL,
+ target,
+ "getFont_NoClientCode",
+ "()Ljava/awt/Font;").l;
+ (*env)->DeleteLocalRef(env, target);
+ return font;
+}
+#endif
+jobject
+awtJNI_GetFMFont(JNIEnv * env, jobject this)
+{
+ return JNU_CallMethodByName(env, NULL, this, "getFont_NoClientCode",
+ "()Ljava/awt/Font;").l;
+}
+
+jboolean
+awtJNI_IsMultiFont(JNIEnv * env, jobject this)
+{
+ jobject peer = NULL;
+ jobject fontConfig = NULL;
+
+ if (this == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
+ return JNI_FALSE;
+ }
+
+ peer = (*env)->CallObjectMethod(env,this,fontIDs.getPeer);
+ if (peer == NULL) {
+ return JNI_FALSE;
+ }
+
+ fontConfig = (*env)->GetObjectField(env,peer,platformFontIDs.fontConfig);
+ (*env)->DeleteLocalRef(env, peer);
+
+ if (fontConfig == NULL) {
+ return JNI_FALSE;
+ }
+ (*env)->DeleteLocalRef(env, fontConfig);
+
+ return JNI_TRUE;
+}
+
+jboolean
+awtJNI_IsMultiFontMetrics(JNIEnv * env, jobject this)
+{
+ jobject peer = NULL;
+ jobject fontConfig = NULL;
+ jobject font = NULL;
+
+ if (JNU_IsNull(env, this)) {
+ return JNI_FALSE;
+ }
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0) {
+ return JNI_FALSE;
+ }
+
+ font = JNU_CallMethodByName(env, NULL, this, "getFont_NoClientCode",
+ "()Ljava/awt/Font;").l;
+ if (JNU_IsNull(env, font)) {
+ return JNI_FALSE;
+ }
+
+ peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
+ (*env)->DeleteLocalRef(env, font);
+
+ if (peer == NULL) {
+ return JNI_FALSE;
+ }
+
+ fontConfig = (*env)->GetObjectField(env,peer,platformFontIDs.fontConfig);
+ (*env)->DeleteLocalRef(env, peer);
+ if (fontConfig == NULL) {
+ return JNI_FALSE;
+ }
+ (*env)->DeleteLocalRef(env, fontConfig);
+
+ return JNI_TRUE;
+}
+#ifndef XAWT
+#ifdef __linux__
+XmString
+unicodeXmStringCreate(char* text, char* tag, int len) {
+ XmString ret_val;
+ XtProcessLock();
+ ret_val = _XmStringNCreate (text, tag, len);
+ XtProcessUnlock();
+ return ret_val;
+}
+#endif
+
+/*
+ * Unicode to Motif Multi Font Compound String converter
+ *
+ * ASSUMES: We are not running on a privileged thread
+ */
+XmString
+awtJNI_MakeMultiFontString(JNIEnv * env, jstring s, jobject font)
+{
+ XmString xmstr = NULL, xmtmp1, xmtmp2;
+ jobjectArray dataArray = NULL;
+ char *err = NULL;
+ int32_t stringCount,i;
+ int32_t fdnumber;
+ struct FontData *fdata = awtJNI_GetFontData(env, font, &err);
+ jobject fontDescriptor = NULL;
+ jbyteArray data = NULL;
+ char *stringData = NULL;
+ char tag[BUFSIZ];
+
+ if ((*env)->PushLocalFrame(env, 16) < 0)
+ return NULL;
+
+ if (!JNU_IsNull(env, s) && !JNU_IsNull(env, font)) {
+ jobject peer;
+
+ peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
+
+ DASSERT(!awt_currentThreadIsPrivileged(env));
+ dataArray =
+ (*env)->CallObjectMethod(
+ env,
+ peer,
+ platformFontIDs.makeConvertedMultiFontString,
+ s);
+
+ if ((*env)->ExceptionOccurred(env)) {
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+
+ (*env)->PopLocalFrame(env, NULL);
+ return (XmString) NULL;
+ }
+
+ if(dataArray == NULL) {
+ (*env)->PopLocalFrame(env, NULL);
+ return (XmString) NULL;
+ }
+ } else {
+ (*env)->PopLocalFrame(env, NULL);
+ return (XmString) NULL;
+ }
+
+ stringCount = (*env)->GetArrayLength(env, dataArray);
+
+ for (i = 0; i < stringCount; i+=2) {
+ fontDescriptor = (*env)->GetObjectArrayElement(env, dataArray, i);
+ data = (*env)->GetObjectArrayElement(env, dataArray, i + 1);
+
+ /* Bail if we've finished */
+ if(fontDescriptor == NULL || data == NULL)
+ break;
+
+ fdnumber = awtJNI_GetFontDescriptorNumber(env, font, fontDescriptor);
+ fdata = awtJNI_GetFontData(env, font, &err);
+
+ makeTag(fdata->flist[fdnumber].charset_name, fdnumber, tag);
+
+ stringData = (char *)(*env)->GetPrimitiveArrayCritical(env, data, NULL);
+ if(stringData != NULL) {
+ unsigned char* buf = stringData;
+ int len;
+ char *offsetStringData;
+
+ offsetStringData = stringData + (4 * sizeof(char));
+#ifdef __linux__
+ len = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+ /* Motif XmStringCreate() API requests "text must be a NULL-terminated
+ string" and its implementation uses "strlen()" to calculate the length
+ of the text string. Unfortunately when we deal with iso10646 font
+ on linux, the "text" is requested to be encoded in UTF16, which has the
+ posibility of including code points like "0xYY00" ("0xYY" + "0x00") that
+ causes problem when XmStringCreate() calls _XmStringNCreate() without
+ specifying a specific text lenth (see Motif XmString.c). The workaround is
+ to call _XmStringNCreate() directly with specific text length at this
+ cirsumstance.
+ */
+ if (strstr(fdata->flist[fdnumber].charset_name, "UnicodeBigUnmarked"))
+ xmtmp1 = unicodeXmStringCreate(offsetStringData, tag, len);
+ else
+ xmtmp1 = XmStringCreate(offsetStringData, tag);
+ if (xmstr == NULL)
+ xmstr = xmtmp1;
+ else {
+ xmtmp2 = XmStringConcat(xmstr, xmtmp1);
+ XmStringFree(xmtmp1);
+ XmStringFree(xmstr);
+ xmstr = xmtmp2;
+ }
+#else
+ if(xmstr == NULL) {
+ xmstr = XmStringCreate(offsetStringData, tag);
+ }
+ else {
+ xmtmp1 = XmStringCreate(offsetStringData, tag);
+ xmtmp2 = XmStringConcat(xmstr, xmtmp1);
+ XmStringFree(xmtmp1);
+ XmStringFree(xmstr);
+ xmstr = xmtmp2;
+ }
+#endif
+ }
+
+ (*env)->ReleasePrimitiveArrayCritical(env, data, stringData, JNI_ABORT);
+ (*env)->DeleteLocalRef(env, fontDescriptor);
+ (*env)->DeleteLocalRef(env, data);
+ }
+ (*env)->PopLocalFrame(env, NULL);
+ return xmstr;
+}
+
+/*
+ * Find the character encoding for a given font and register that encoding
+ * with the given tag. The encoding is the last two fields of the XLFD of
+ * the font (converted to uppercase).
+ */
+static void registerEncoding(char *xlfd, char *tag)
+{
+ char *e = xlfd + strlen(xlfd);
+ char *ret = NULL;
+
+ do { --e; } while (e != xlfd && *e != '-');
+ do { --e; } while (e != xlfd && *e != '-');
+ if (e != xlfd) {
+ char *encoding = strdup(++e);
+ char *u = NULL;
+
+ for (u = encoding; *u != '\0'; ++u) {
+ if (islower(*u)) {
+ *u = toupper(*u);
+ }
+ }
+
+ /*
+ * Motif will core dump on or otherwise mishandle unknown (or
+ * non-standard) character encodings (in conversion to compound
+ * text, bug 4122785). Register Sun private encodings for
+ * Symbol or dingbat fonts as ISO8859-1, which is a lie,
+ * but produces predictable results.
+ */
+ if (strncmp(encoding, "SUN-", 4) == 0) {
+ free(encoding);
+ encoding = strdup("ISO8859-1");
+ }
+ ret = XmRegisterSegmentEncoding(tag, encoding);
+ if (ret != NULL)
+ XtFree(ret);
+ free(encoding);
+ }
+}
+
+
+XmFontList
+awtJNI_GetFontList(JNIEnv * env, jobject font)
+{
+ int32_t i;
+ XmFontListEntry fle;
+ XmFontList fontlist;
+ XFontStruct *xf = NULL;
+ int32_t size;
+ struct FontData *fdata = NULL;
+ char *err = NULL, tag[BUFSIZ];
+
+ fdata = awtJNI_GetFontData(env, font, &err);
+
+ makeTag(fdata->flist[0].charset_name, 0, tag);
+
+ size = (int32_t) (*env)->GetIntField(env, font, fontIDs.size);
+
+ if (fdata->flist[0].load == 0) {
+ xf = loadFont(awt_display, fdata->flist[0].xlfd, size * 10);
+
+ if (xf == NULL) {
+ /* printf("Cannot load font: %s\n", fdata->list[0].xlfd); */
+ } else {
+ fdata->flist[0].xfont = xf;
+ fdata->flist[0].load = 1;
+
+ if (xf->min_byte1 == 0 && xf->max_byte1 == 0)
+ fdata->flist[0].index_length = 1;
+ else
+ fdata->flist[0].index_length = 2;
+ }
+ }
+ registerEncoding(fdata->flist[0].xlfd, tag);
+ fle = XmFontListEntryCreate(tag, XmFONT_IS_FONT,
+ (XtPointer) fdata->flist[0].xfont);
+
+ fontlist = XmFontListAppendEntry(NULL, fle);
+ /*
+ * Some versions of motif have a bug in
+ * XmFontListEntryFree() which causes it to free more than it
+ * should. Use XtFree() is used instead. See O'Reilly's
+ * Motif Reference Manual for more information.
+ */
+ XmFontListEntryFree(&fle);
+
+ for (i = 1; i < fdata->charset_num; i++) {
+ makeTag(fdata->flist[i].charset_name, i, tag);
+
+ if (fdata->flist[i].load == 0) {
+ xf = loadFont(awt_display, fdata->flist[i].xlfd, size * 10);
+
+ if (xf == NULL) {
+ /* printf("Cannot load font: %s\n", fdata->flist[0].xlfd); */
+ continue;
+ }
+ fdata->flist[i].xfont = xf;
+ fdata->flist[i].load = 1;
+ if (xf->min_byte1 == 0 && xf->max_byte1 == 0) {
+ fdata->flist[i].index_length = 1;
+ } else {
+ fdata->flist[i].index_length = 2;
+ }
+ }
+ registerEncoding(fdata->flist[i].xlfd, tag);
+ fle = XmFontListEntryCreate(tag, XmFONT_IS_FONT,
+ (XtPointer) fdata->flist[i].xfont);
+ fontlist = XmFontListAppendEntry(fontlist, fle);
+ /*
+ * Some versions of motif have a bug in
+ * XmFontListEntryFree() which causes it to free more than it
+ * should. Use XtFree() instead. See O'Reilly's
+ * Motif Reference Manual for more information.
+ */
+ XmFontListEntryFree(&fle);
+ }
+
+ return fontlist;
+}
+#endif
+/* #define FONT_DEBUG 2 */
+
+XFontSet
+awtJNI_MakeFontSet(JNIEnv * env, jobject font)
+{
+ jstring xlfd = NULL;
+ char *xfontset = NULL;
+ int32_t size;
+ int32_t length = 0;
+ char *realxlfd = NULL, *ptr = NULL, *prev = NULL;
+ char **missing_list = NULL;
+ int32_t missing_count;
+ char *def_string = NULL;
+ XFontSet xfs;
+ jobject peer = NULL;
+ jstring xfsname = NULL;
+#ifdef FONT_DEBUG
+ char xx[1024];
+#endif
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+ return 0;
+
+ size = (*env)->GetIntField(env, font, fontIDs.size) * 10;
+
+ peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
+ xfsname = (*env)->GetObjectField(env, peer, mFontPeerIDs.xfsname);
+
+ if (JNU_IsNull(env, xfsname))
+ xfontset = "";
+ else
+ xfontset = (char *)JNU_GetStringPlatformChars(env, xfsname, NULL);
+
+ realxlfd = malloc(strlen(xfontset) + 50);
+
+ prev = ptr = xfontset;
+ while ((ptr = strstr(ptr, "%d"))) {
+ char save = *(ptr + 2);
+
+ *(ptr + 2) = '\0';
+ jio_snprintf(realxlfd + length, strlen(xfontset) + 50 - length,
+ prev, size);
+ length = strlen(realxlfd);
+ *(ptr + 2) = save;
+
+ prev = ptr + 2;
+ ptr += 2;
+ }
+ strcpy(realxlfd + length, prev);
+
+#ifdef FONT_DEBUG
+ strcpy(xx, realxlfd);
+#endif
+ xfs = XCreateFontSet(awt_display, realxlfd, &missing_list,
+ &missing_count, &def_string);
+#if FONT_DEBUG >= 2
+ fprintf(stderr, "XCreateFontSet(%s)->0x%x\n", xx, xfs);
+#endif
+
+#if FONT_DEBUG
+ if (missing_count != 0) {
+ int32_t i;
+ fprintf(stderr, "XCreateFontSet missing %d fonts:\n", missing_count);
+ for (i = 0; i < missing_count; ++i) {
+ fprintf(stderr, "\t\"%s\"\n", missing_list[i]);
+ }
+ fprintf(stderr, " requested \"%s\"\n", xx);
+#if FONT_DEBUG >= 3
+ exit(-1);
+#endif
+ }
+#endif
+
+ free((void *)realxlfd);
+
+ if (xfontset && !JNU_IsNull(env, xfsname))
+ JNU_ReleaseStringPlatformChars(env, xfsname, (const char *) xfontset);
+
+ (*env)->DeleteLocalRef(env, peer);
+ (*env)->DeleteLocalRef(env, xfsname);
+ return xfs;
+}
+
+/*
+ * get multi font string width with multiple X11 font
+ *
+ * ASSUMES: We are not running on a privileged thread
+ */
+int32_t
+awtJNI_GetMFStringWidth(JNIEnv * env, jcharArray s, int offset, int sLength, jobject font)
+{
+ char *err = NULL;
+ unsigned char *stringData = NULL;
+ char *offsetStringData = NULL;
+ int32_t stringCount, i;
+ int32_t size;
+ struct FontData *fdata = NULL;
+ jobject fontDescriptor = NULL;
+ jbyteArray data = NULL;
+ int32_t j;
+ int32_t width = 0;
+ int32_t length;
+ XFontStruct *xf = NULL;
+ jobjectArray dataArray = NULL;
+#ifndef XAWT
+ DASSERT(!awt_currentThreadIsPrivileged(env));
+#endif
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ return 0;
+
+ if (!JNU_IsNull(env, s) && !JNU_IsNull(env, font))
+ {
+ jobject peer;
+ peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
+
+ dataArray = (*env)->CallObjectMethod(
+ env,
+ peer,
+ platformFontIDs.makeConvertedMultiFontChars,
+ s, offset, sLength);
+
+ if ((*env)->ExceptionOccurred(env))
+ {
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ }
+
+ (*env)->DeleteLocalRef(env, peer);
+
+ if(dataArray == NULL)
+ {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ fdata = awtJNI_GetFontData(env, font, &err);
+
+ stringCount = (*env)->GetArrayLength(env, dataArray);
+
+ size = (*env)->GetIntField(env, font, fontIDs.size);
+
+ for (i = 0; i < stringCount; i+=2)
+ {
+ fontDescriptor = (*env)->GetObjectArrayElement(env, dataArray, i);
+ data = (*env)->GetObjectArrayElement(env, dataArray, i + 1);
+
+ /* Bail if we've finished */
+ if (fontDescriptor == NULL || data == NULL) {
+ (*env)->DeleteLocalRef(env, fontDescriptor);
+ (*env)->DeleteLocalRef(env, data);
+ break;
+ }
+
+ j = awtJNI_GetFontDescriptorNumber(env, font, fontDescriptor);
+
+ if (fdata->flist[j].load == 0) {
+ xf = loadFont(awt_display,
+ fdata->flist[j].xlfd, size * 10);
+ if (xf == NULL) {
+ (*env)->DeleteLocalRef(env, fontDescriptor);
+ (*env)->DeleteLocalRef(env, data);
+ continue;
+ }
+ fdata->flist[j].load = 1;
+ fdata->flist[j].xfont = xf;
+ if (xf->min_byte1 == 0 && xf->max_byte1 == 0)
+ fdata->flist[j].index_length = 1;
+ else
+ fdata->flist[j].index_length = 2;
+ }
+ xf = fdata->flist[j].xfont;
+
+ stringData =
+ (unsigned char *)(*env)->GetPrimitiveArrayCritical(env, data,NULL);
+ length = (stringData[0] << 24) | (stringData[1] << 16) |
+ (stringData[2] << 8) | stringData[3];
+ offsetStringData = (char *)(stringData + (4 * sizeof(char)));
+
+ if (fdata->flist[j].index_length == 2) {
+ width += XTextWidth16(xf, (XChar2b *)offsetStringData, length/2);
+ } else {
+ width += XTextWidth(xf, offsetStringData, length);
+ }
+
+ (*env)->ReleasePrimitiveArrayCritical(env, data, stringData, JNI_ABORT);
+ (*env)->DeleteLocalRef(env, fontDescriptor);
+ (*env)->DeleteLocalRef(env, data);
+ }
+ (*env)->DeleteLocalRef(env, dataArray);
+
+ return width;
+}