0N/A/*
2362N/A * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
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#ifndef HEADLESS
0N/A
0N/A#include "awt_p.h"
0N/A#include <string.h>
0N/A#include "java_awt_Component.h"
0N/A#include "java_awt_Font.h"
0N/A#include "java_awt_FontMetrics.h"
0N/A#include "sun_awt_motif_MToolkit.h"
0N/A#include "sun_awt_motif_X11FontMetrics.h"
0N/A#include "sun_awt_X11GraphicsEnvironment.h"
0N/A
0N/A#include "awt_Font.h"
0N/A
0N/A#include "java_awt_Dimension.h"
0N/A#include "multi_font.h"
0N/A#include "Disposer.h"
0N/A#endif /* !HEADLESS */
0N/A#include <jni.h>
0N/A#ifndef HEADLESS
0N/A#include <jni_util.h>
0N/A
0N/A#define defaultXLFD "-*-helvetica-*-*-*-*-12-*-*-*-*-*-iso8859-1"
0N/A
0N/Astruct FontIDs fontIDs;
0N/Astruct PlatformFontIDs platformFontIDs;
0N/A
0N/Astatic void pDataDisposeMethod(JNIEnv *env, jlong pData);
0N/A
0N/A/* #define FONT_DEBUG 2 */
0N/A/* 1- print failures, 2- print all, 3- terminate on failure */
0N/A#if FONT_DEBUG
0N/Astatic XFontStruct *XLoadQueryFontX(Display *display, char *name)
0N/A{
0N/A XFontStruct *result = NULL;
0N/A result = XLoadQueryFont(display, name);
0N/A#if FONT_DEBUG < 2
0N/A if (result == NULL)
0N/A#endif
0N/A fprintf(stderr, "XLoadQueryFont(\"%s\") -> 0x%x.\n", name, result);
0N/A#if FONT_DEBUG >= 3
0N/A if (result == NULL)
0N/A exit(-1);
0N/A#endif
0N/A return result;
0N/A}
0N/A#define XLoadQueryFont XLoadQueryFontX
0N/A#endif
0N/A#endif /* !HEADLESS */
0N/A
0N/A/*
0N/A * Class: java_awt_Font
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/A
0N/A/* This function gets called from the static initializer for Font.java
0N/A to initialize the fieldIDs for fields that may be accessed from C */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_java_awt_Font_initIDs
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A#ifndef HEADLESS
0N/A /** We call "NoClientCode" methods because they won't invoke client
0N/A code on the privileged toolkit thread **/
0N/A fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
0N/A fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I");
0N/A fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I");
0N/A fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getPeer_NoClientCode",
0N/A "()Ljava/awt/peer/FontPeer;");
0N/A fontIDs.getFamily =
0N/A (*env)->GetMethodID(env, cls, "getFamily_NoClientCode",
0N/A "()Ljava/lang/String;");
0N/A#endif /* !HEADLESS */
0N/A}
0N/A
0N/A#ifndef HEADLESS
0N/A
0N/A/* fieldIDs for X11FontMetrics fields that may be accessed from C */
0N/Astatic struct X11FontMetricsIDs {
0N/A jfieldID widths;
0N/A jfieldID font;
0N/A jfieldID ascent;
0N/A jfieldID descent;
0N/A jfieldID leading;
0N/A jfieldID height;
0N/A jfieldID maxAscent;
0N/A jfieldID maxDescent;
0N/A jfieldID maxHeight;
0N/A jfieldID maxAdvance;
0N/A} x11FontMetricsIDs;
0N/A
0N/A/*
0N/A * Class: sun_awt_motif_X11FontMetrics
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/A
0N/A/* This function gets called from the static initializer for
0N/A X11FontMetrics.java to initialize the fieldIDs for fields
0N/A that may be accessed from C */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_awt_motif_X11FontMetrics_initIDs
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A x11FontMetricsIDs.widths = (*env)->GetFieldID(env, cls, "widths", "[I");
0N/A x11FontMetricsIDs.font =
0N/A (*env)->GetFieldID(env, cls, "font", "Ljava/awt/Font;");
0N/A x11FontMetricsIDs.ascent =
0N/A (*env)->GetFieldID(env, cls, "ascent", "I");
0N/A x11FontMetricsIDs.descent =
0N/A (*env)->GetFieldID(env, cls, "descent", "I");
0N/A x11FontMetricsIDs.leading =
0N/A (*env)->GetFieldID(env, cls, "leading", "I");
0N/A x11FontMetricsIDs.height =
0N/A (*env)->GetFieldID(env, cls, "height", "I");
0N/A x11FontMetricsIDs.maxAscent =
0N/A (*env)->GetFieldID(env, cls, "maxAscent", "I");
0N/A x11FontMetricsIDs.maxDescent =
0N/A (*env)->GetFieldID(env, cls, "maxDescent", "I");
0N/A x11FontMetricsIDs.maxHeight =
0N/A (*env)->GetFieldID(env, cls, "maxHeight", "I");
0N/A x11FontMetricsIDs.maxAdvance =
0N/A (*env)->GetFieldID(env, cls, "maxAdvance", "I");
0N/A}
0N/A
0N/A
0N/A/* fieldIDs for FontDescriptor fields that may be accessed from C */
0N/Astatic struct FontDescriptorIDs {
0N/A jfieldID nativeName;
0N/A jfieldID charsetName;
0N/A} fontDescriptorIDs;
0N/A#endif /* !HEADLESS */
0N/A
0N/A/*
0N/A * Class: sun_awt_FontDescriptor
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/A
0N/A/* This function gets called from the static initializer for
0N/A FontDescriptor.java to initialize the fieldIDs for fields
0N/A that may be accessed from C */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_awt_FontDescriptor_initIDs
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A#ifndef HEADLESS
0N/A fontDescriptorIDs.nativeName =
0N/A (*env)->GetFieldID(env, cls, "nativeName",
0N/A "Ljava/lang/String;");
0N/A fontDescriptorIDs.charsetName =
0N/A (*env)->GetFieldID(env, cls, "charsetName",
0N/A "Ljava/lang/String;");
0N/A#endif /* !HEADLESS */
0N/A}
0N/A
0N/A#ifndef HEADLESS
0N/Astruct MFontPeerIDs mFontPeerIDs;
0N/A/*
0N/A * Class: sun_awt_motif_MFontPeer
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/A
0N/A/* This function gets called from the static initializer for
0N/A MFontPeer.java to initialize the fieldIDs for fields
0N/A that may be accessed from C */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_awt_motif_MFontPeer_initIDs
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A mFontPeerIDs.xfsname =
0N/A (*env)->GetFieldID(env, cls, "xfsname", "Ljava/lang/String;");
0N/A}
0N/A#endif /* !HEADLESS */
0N/A
0N/A/*
0N/A * Class: sun_awt_PlatformFont
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/A
0N/A/* This function gets called from the static initializer for
0N/A PlatformFont.java to initialize the fieldIDs for fields
0N/A that may be accessed from C */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_awt_PlatformFont_initIDs
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A#ifndef HEADLESS
0N/A platformFontIDs.componentFonts =
0N/A (*env)->GetFieldID(env, cls, "componentFonts",
0N/A "[Lsun/awt/FontDescriptor;");
0N/A platformFontIDs.fontConfig =
0N/A (*env)->GetFieldID(env,cls, "fontConfig",
0N/A "Lsun/awt/FontConfiguration;");
0N/A
0N/A platformFontIDs.makeConvertedMultiFontString =
0N/A (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString",
0N/A "(Ljava/lang/String;)[Ljava/lang/Object;");
0N/A
0N/A platformFontIDs.makeConvertedMultiFontChars =
0N/A (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars",
0N/A "([CII)[Ljava/lang/Object;");
0N/A#endif /* !HEADLESS */
0N/A}
0N/A
0N/A#ifndef HEADLESS
0N/AXFontStruct *
0N/AloadFont(Display * display, char *name, int32_t pointSize)
0N/A{
0N/A XFontStruct *f = NULL;
0N/A
0N/A /* try the exact xlfd name in font configuration file */
0N/A f = XLoadQueryFont(display, name);
0N/A if (f != NULL) {
0N/A return f;
0N/A }
0N/A
0N/A /*
0N/A * try nearly font
0N/A *
0N/A * 1. specify FAMILY_NAME, WEIGHT_NAME, SLANT, POINT_SIZE,
0N/A * CHARSET_REGISTRY and CHARSET_ENCODING.
0N/A * 2. change POINT_SIZE to PIXEL_SIZE
0N/A * 3. change FAMILY_NAME to *
0N/A * 4. specify only PIXEL_SIZE and CHARSET_REGISTRY/ENCODING
0N/A * 5. change PIXEL_SIZE +1/-1/+2/-2...+4/-4
0N/A * 6. default font pattern
0N/A */
0N/A {
0N/A /*
0N/A * This code assumes the name contains exactly 14 '-' delimiter.
0N/A * If not use default pattern.
0N/A */
0N/A int32_t i, length, pixelSize;
0N/A Boolean useDefault = FALSE;
0N/A
0N/A char buffer[BUFSIZ], buffer2[BUFSIZ];
0N/A char *family = NULL, *style = NULL, *slant = NULL, *encoding = NULL;
0N/A char *start = NULL, *end = NULL;
0N/A
0N/A if (strlen(name) > BUFSIZ - 1) {
0N/A useDefault = TRUE;
0N/A } else {
0N/A strcpy(buffer, name);
0N/A }
0N/A
0N/A#define NEXT_HYPHEN\
0N/A start = end + 1;\
0N/A end = strchr(start, '-');\
0N/A if (end == NULL) {\
0N/A useDefault = TRUE;\
0N/A break;\
0N/A }\
0N/A *end = '\0'
0N/A
0N/A do {
0N/A end = buffer;
0N/A
0N/A /* skip FOUNDRY */
0N/A NEXT_HYPHEN;
0N/A
0N/A /* set FAMILY_NAME */
0N/A NEXT_HYPHEN;
0N/A family = start;
0N/A
0N/A /* set STYLE_NAME */
0N/A NEXT_HYPHEN;
0N/A style = start;
0N/A
0N/A /* set SLANT */
0N/A NEXT_HYPHEN;
0N/A slant = start;
0N/A
0N/A /* skip SETWIDTH_NAME, ADD_STYLE_NAME, PIXEL_SIZE
0N/A POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, SPACING
0N/A and AVERAGE_WIDTH */
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A NEXT_HYPHEN;
0N/A
0N/A /* set CHARSET_REGISTRY and CHARSET_ENCODING */
0N/A encoding = end + 1;
0N/A }
0N/A while (0);
0N/A
0N/A#define TRY_LOAD\
0N/A f = XLoadQueryFont(display, buffer2);\
0N/A if (f != NULL) {\
0N/A strcpy(name, buffer2);\
0N/A return f;\
0N/A }
0N/A
0N/A if (!useDefault) {
0N/A char *altstyle = NULL;
0N/A
0N/A /* Regular is the style for TrueType fonts -- Type1, F3 use roman */
0N/A if (strcmp(style, "regular") == 0) {
0N/A altstyle = "roman";
0N/A }
4632N/A#if defined(__linux__) || defined(MACOSX)
0N/A if (!strcmp(family, "lucidasans")) {
0N/A family = "lucida";
0N/A }
0N/A#endif
0N/A /* try 1. */
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s",
0N/A family, style, slant, pointSize, encoding);
0N/A TRY_LOAD;
0N/A
0N/A if (altstyle != NULL) {
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s",
0N/A family, altstyle, slant, pointSize, encoding);
0N/A TRY_LOAD;
0N/A }
0N/A
0N/A /* search bitmap font */
0N/A pixelSize = pointSize / 10;
0N/A
0N/A /* try 2. */
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A family, style, slant, pixelSize, encoding);
0N/A TRY_LOAD;
0N/A
0N/A if (altstyle != NULL) {
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A family, altstyle, slant, pixelSize, encoding);
0N/A TRY_LOAD;
0N/A }
0N/A
0N/A /* try 3 */
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A style, slant, pixelSize, encoding);
0N/A TRY_LOAD;
0N/A if (altstyle != NULL) {
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A altstyle, slant, pixelSize, encoding);
0N/A TRY_LOAD;
0N/A }
0N/A
0N/A /* try 4 */
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-*-%s-*-*-%d-*-*-*-*-*-%s",
0N/A slant, pixelSize, encoding);
0N/A
0N/A TRY_LOAD;
0N/A
0N/A /* try 5. */
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
0N/A pixelSize, encoding);
0N/A TRY_LOAD;
0N/A
0N/A /* try 6. */
0N/A for (i = 1; i < 4; i++) {
0N/A if (pixelSize < i)
0N/A break;
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A family, style, slant, pixelSize + i, encoding);
0N/A TRY_LOAD;
0N/A
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A family, style, slant, pixelSize - i, encoding);
0N/A TRY_LOAD;
0N/A
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
0N/A pixelSize + i, encoding);
0N/A TRY_LOAD;
0N/A
0N/A jio_snprintf(buffer2, sizeof(buffer2),
0N/A "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
0N/A pixelSize - i, encoding);
0N/A TRY_LOAD;
0N/A }
0N/A }
0N/A }
0N/A
0N/A strcpy(name, defaultXLFD);
0N/A return XLoadQueryFont(display, defaultXLFD);
0N/A}
0N/A
0N/A/*
0N/A * Hardwired list of mappings for generic font names "Helvetica",
0N/A * "TimesRoman", "Courier", "Dialog", and "DialogInput".
0N/A */
0N/Astatic char *defaultfontname = "fixed";
0N/Astatic char *defaultfoundry = "misc";
0N/Astatic char *anyfoundry = "*";
0N/Astatic char *anystyle = "*-*";
0N/Astatic char *isolatin1 = "iso8859-1";
0N/A
0N/Astatic char *
0N/AStyle(int32_t s)
0N/A{
0N/A switch (s) {
0N/A case java_awt_Font_ITALIC:
0N/A return "medium-i";
0N/A case java_awt_Font_BOLD:
0N/A return "bold-r";
0N/A case java_awt_Font_BOLD + java_awt_Font_ITALIC:
0N/A return "bold-i";
0N/A case java_awt_Font_PLAIN:
0N/A default:
0N/A return "medium-r";
0N/A }
0N/A}
0N/A
0N/Astatic int32_t
0N/AawtJNI_FontName(JNIEnv * env, jstring name, char **foundry, char **facename, char **encoding)
0N/A{
0N/A char *cname = NULL;
0N/A
0N/A if (JNU_IsNull(env, name)) {
0N/A return 0;
0N/A }
0N/A cname = (char *) JNU_GetStringPlatformChars(env, name, NULL);
0N/A
0N/A /* additional default font names */
0N/A if (strcmp(cname, "serif") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "times";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "sansserif") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "helvetica";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "monospaced") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "courier";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "helvetica") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "helvetica";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "timesroman") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "times";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "courier") == 0) {
0N/A *foundry = "adobe";
0N/A *facename = "courier";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "dialog") == 0) {
0N/A *foundry = "b&h";
0N/A *facename = "lucida";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "dialoginput") == 0) {
0N/A *foundry = "b&h";
0N/A *facename = "lucidatypewriter";
0N/A *encoding = isolatin1;
0N/A } else if (strcmp(cname, "zapfdingbats") == 0) {
0N/A *foundry = "itc";
0N/A *facename = "zapfdingbats";
0N/A *encoding = "*-*";
0N/A } else {
0N/A#ifdef DEBUG
0N/A jio_fprintf(stderr, "Unknown font: %s\n", cname);
0N/A#endif
0N/A *foundry = defaultfoundry;
0N/A *facename = defaultfontname;
0N/A *encoding = isolatin1;
0N/A }
0N/A
0N/A if (cname != NULL)
0N/A JNU_ReleaseStringPlatformChars(env, name, (const char *) cname);
0N/A
0N/A return 1;
0N/A}
0N/A
0N/Astruct FontData *
0N/AawtJNI_GetFontData(JNIEnv * env, jobject font, char **errmsg)
0N/A{
0N/A /* We are going to create at most 4 outstanding local refs in this
0N/A * function. */
0N/A if ((*env)->EnsureLocalCapacity(env, 4) < 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A if (!JNU_IsNull(env, font) && awtJNI_IsMultiFont(env, font)) {
0N/A struct FontData *fdata = NULL;
0N/A int32_t i, size;
0N/A char *fontsetname = NULL;
0N/A char *nativename = NULL;
0N/A jobjectArray componentFonts = NULL;
0N/A jobject peer = NULL;
0N/A jobject fontDescriptor = NULL;
0N/A jstring fontDescriptorName = NULL;
0N/A jstring charsetName = NULL;
0N/A
0N/A fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font,
0N/A fontIDs.pData);
0N/A
0N/A if (fdata != NULL && fdata->flist != NULL) {
0N/A return fdata;
0N/A }
0N/A size = (*env)->GetIntField(env, font, fontIDs.size);
0N/A fdata = (struct FontData *) malloc(sizeof(struct FontData));
0N/A
0N/A peer = (*env)->CallObjectMethod(env, font, fontIDs.getPeer);
0N/A
0N/A componentFonts =
0N/A (*env)->GetObjectField(env, peer, platformFontIDs.componentFonts);
0N/A /* We no longer need peer */
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A
0N/A fdata->charset_num = (*env)->GetArrayLength(env, componentFonts);
0N/A
0N/A fdata->flist = (awtFontList *) malloc(sizeof(awtFontList)
0N/A * fdata->charset_num);
0N/A fdata->xfont = NULL;
0N/A for (i = 0; i < fdata->charset_num; i++) {
0N/A /*
0N/A * set xlfd name
0N/A */
0N/A
0N/A fontDescriptor = (*env)->GetObjectArrayElement(env, componentFonts, i);
0N/A fontDescriptorName =
0N/A (*env)->GetObjectField(env, fontDescriptor,
0N/A fontDescriptorIDs.nativeName);
0N/A
0N/A if (!JNU_IsNull(env, fontDescriptorName)) {
0N/A nativename = (char *) JNU_GetStringPlatformChars(env, fontDescriptorName, NULL);
0N/A } else {
0N/A nativename = "";
0N/A }
0N/A
0N/A fdata->flist[i].xlfd = malloc(strlen(nativename)
0N/A + strlen(defaultXLFD));
0N/A jio_snprintf(fdata->flist[i].xlfd, strlen(nativename) + 10,
0N/A nativename, size * 10);
0N/A
0N/A if (nativename != NULL && nativename != "")
0N/A JNU_ReleaseStringPlatformChars(env, fontDescriptorName, (const char *) nativename);
0N/A
0N/A /*
0N/A * set charset_name
0N/A */
0N/A
0N/A charsetName =
0N/A (*env)->GetObjectField(env, fontDescriptor,
0N/A fontDescriptorIDs.charsetName);
0N/A
0N/A fdata->flist[i].charset_name = (char *)
0N/A JNU_GetStringPlatformChars(env, charsetName, NULL);
0N/A
0N/A /* We are done with the objects. */
0N/A (*env)->DeleteLocalRef(env, fontDescriptor);
0N/A (*env)->DeleteLocalRef(env, fontDescriptorName);
0N/A (*env)->DeleteLocalRef(env, charsetName);
0N/A
0N/A /*
0N/A * set load & XFontStruct
0N/A */
0N/A fdata->flist[i].load = 0;
0N/A
0N/A /*
0N/A * This appears to be a bogus check. The actual intent appears
0N/A * to be to find out whether this is the "base" font in a set,
0N/A * rather than iso8859_1 explicitly. Note that iso8859_15 will
0N/A * and must also pass this test.
0N/A */
0N/A
0N/A if (fdata->xfont == NULL &&
0N/A strstr(fdata->flist[i].charset_name, "8859_1")) {
0N/A fdata->flist[i].xfont =
0N/A loadFont(awt_display, fdata->flist[i].xlfd, size * 10);
0N/A if (fdata->flist[i].xfont != NULL) {
0N/A fdata->flist[i].load = 1;
0N/A fdata->xfont = fdata->flist[i].xfont;
0N/A fdata->flist[i].index_length = 1;
0N/A } else {
0N/A if (errmsg != NULL) {
0N/A *errmsg = "java/lang" "NullPointerException";
0N/A }
0N/A (*env)->DeleteLocalRef(env, componentFonts);
0N/A return NULL;
0N/A }
0N/A }
0N/A }
0N/A (*env)->DeleteLocalRef(env, componentFonts);
0N/A /*
0N/A * XFontSet will create if the peer of TextField/TextArea
0N/A * are used.
0N/A */
0N/A fdata->xfs = NULL;
0N/A
0N/A JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata);
0N/A Disposer_AddRecord(env, font, pDataDisposeMethod, ptr_to_jlong(fdata));
0N/A return fdata;
0N/A } else {
0N/A Display *display = NULL;
0N/A struct FontData *fdata = NULL;
0N/A char fontSpec[1024];
0N/A int32_t height;
0N/A int32_t oheight;
0N/A int32_t above = 0; /* tries above height */
0N/A int32_t below = 0; /* tries below height */
0N/A char *foundry = NULL;
0N/A char *name = NULL;
0N/A char *encoding = NULL;
0N/A char *style = NULL;
0N/A XFontStruct *xfont = NULL;
0N/A jstring family = NULL;
0N/A
0N/A if (JNU_IsNull(env, font)) {
0N/A if (errmsg != NULL) {
0N/A *errmsg = "java/lang" "NullPointerException";
0N/A }
0N/A return (struct FontData *) NULL;
0N/A }
0N/A display = XDISPLAY;
0N/A
0N/A fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font,fontIDs.pData);
0N/A if (fdata != NULL && fdata->xfont != NULL) {
0N/A return fdata;
0N/A }
0N/A
0N/A family = (*env)->CallObjectMethod(env, font, fontIDs.getFamily);
0N/A
0N/A if (!awtJNI_FontName(env, family, &foundry, &name, &encoding)) {
0N/A if (errmsg != NULL) {
0N/A *errmsg = "java/lang" "NullPointerException";
0N/A }
0N/A (*env)->DeleteLocalRef(env, family);
0N/A return (struct FontData *) NULL;
0N/A }
0N/A style = Style((*env)->GetIntField(env, font, fontIDs.style));
0N/A oheight = height = (*env)->GetIntField(env, font, fontIDs.size);
0N/A
0N/A while (1) {
0N/A jio_snprintf(fontSpec, sizeof(fontSpec), "-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
0N/A foundry,
0N/A name,
0N/A style,
0N/A height,
0N/A encoding);
0N/A
0N/A /*fprintf(stderr,"LoadFont: %s\n", fontSpec); */
0N/A xfont = XLoadQueryFont(display, fontSpec);
0N/A
0N/A /* XXX: sometimes XLoadQueryFont returns a bogus font structure */
0N/A /* with negative ascent. */
0N/A if (xfont == (Font) NULL || xfont->ascent < 0) {
0N/A if (xfont != NULL) {
0N/A XFreeFont(display, xfont);
0N/A }
0N/A if (foundry != anyfoundry) { /* Use ptr comparison here, not strcmp */
0N/A /* Try any other foundry before messing with the sizes */
0N/A foundry = anyfoundry;
0N/A continue;
0N/A }
0N/A /* We couldn't find the font. We'll try to find an */
0N/A /* alternate by searching for heights above and below our */
0N/A /* preferred height. We try for 4 heights above and below. */
0N/A /* If we still can't find a font we repeat the algorithm */
0N/A /* using misc-fixed as the font. If we then fail, then we */
0N/A /* give up and signal an error. */
0N/A if (above == below) {
0N/A above++;
0N/A height = oheight + above;
0N/A } else {
0N/A below++;
0N/A if (below > 4) {
0N/A if (name != defaultfontname || style != anystyle) {
0N/A name = defaultfontname;
0N/A foundry = defaultfoundry;
0N/A height = oheight;
0N/A style = anystyle;
0N/A encoding = isolatin1;
0N/A above = below = 0;
0N/A continue;
0N/A } else {
0N/A if (errmsg != NULL) {
0N/A *errmsg = "java/io/" "FileNotFoundException";
0N/A }
0N/A (*env)->DeleteLocalRef(env, family);
0N/A return (struct FontData *) NULL;
0N/A }
0N/A }
0N/A height = oheight - below;
0N/A }
0N/A continue;
0N/A } else {
0N/A fdata = ZALLOC(FontData);
0N/A
0N/A if (fdata == NULL) {
0N/A if (errmsg != NULL) {
0N/A *errmsg = "java/lang" "OutOfMemoryError";
0N/A }
0N/A } else {
0N/A fdata->xfont = xfont;
0N/A JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata);
0N/A Disposer_AddRecord(env, font, pDataDisposeMethod,
0N/A ptr_to_jlong(fdata));
0N/A }
0N/A (*env)->DeleteLocalRef(env, family);
0N/A return fdata;
0N/A }
0N/A }
0N/A /* not reached */
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_awt_motif_X11FontMetrics
0N/A * Method: getMFCharsWidth
0N/A * Signature: ([CIILjava/awt/Font;)I
0N/A */
0N/AJNIEXPORT jint JNICALL Java_sun_awt_motif_X11FontMetrics_getMFCharsWidth
0N/A (JNIEnv *env, jobject this, jcharArray data, jint offset, jint length, jobject font)
0N/A{
0N/A jint retVal = 0;
0N/A
0N/A AWT_LOCK();
0N/A
0N/A retVal = awtJNI_GetMFStringWidth(env, data, offset, length, font);
0N/A
0N/A AWT_UNLOCK();
0N/A return retVal;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_awt_motif_X11FontMetrics
0N/A * Method: bytesWidth
0N/A * Signature: ([BII)I
0N/A */
0N/AJNIEXPORT jint JNICALL Java_sun_awt_motif_X11FontMetrics_bytesWidth
0N/A (JNIEnv *env, jobject this, jbyteArray str, jint off, jint len)
0N/A{
0N/A jint w = 0;
0N/A unsigned char *s = NULL, *tmpPointer = NULL;
0N/A int32_t ch = 0;
0N/A int32_t cnt = 0;
0N/A jobject widths = NULL;
0N/A jint tempWidths[256];
0N/A jint maxAdvance = 0;
0N/A int32_t widlen = 0;
0N/A
0N/A if (JNU_IsNull(env, str)) {
0N/A JNU_ThrowNullPointerException(env, "NullPointerException");
0N/A return 0;
0N/A }
0N/A
0N/A cnt = (*env)->GetArrayLength(env, str);
0N/A if (cnt == 0) {
0N/A return 0;
0N/A }
0N/A
0N/A widths = (*env)->GetObjectField(env, this, x11FontMetricsIDs.widths);
0N/A maxAdvance = (*env)->GetIntField(env, this, x11FontMetricsIDs.maxAdvance);
0N/A if (!JNU_IsNull(env, widths)) {
0N/A w = 0;
0N/A widlen = (*env)->GetArrayLength(env, widths);
0N/A (*env)->GetIntArrayRegion(env, widths, 0, widlen, (jint *) tempWidths);
0N/A
0N/A s = tmpPointer = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, str, NULL);
0N/A if (s == NULL) {
0N/A return 0;
0N/A }
0N/A
0N/A while (--cnt >= 0) {
0N/A ch = *tmpPointer++;
0N/A if (ch < widlen) {
0N/A w += tempWidths[ch];
0N/A } else {
0N/A w += maxAdvance;
0N/A }
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, str, (jchar *) s, JNI_ABORT);
0N/A } else {
0N/A w = maxAdvance * cnt;
0N/A }
0N/A return w;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_awt_motif_X11FontMetrics
0N/A * Method: init
0N/A * Signature: ()V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_awt_motif_X11FontMetrics_init
0N/A (JNIEnv *env, jobject this)
0N/A{
0N/A jobject font = NULL;
0N/A struct FontData *fdata = NULL;
0N/A jint tempWidths[256];
0N/A jintArray widths = NULL;
0N/A int32_t ccount = 0;
0N/A int32_t i = 0;
0N/A int32_t tempWidthsIndex = 0;
0N/A char *err = NULL;
0N/A
0N/A if (JNU_IsNull(env, this)) {
0N/A JNU_ThrowNullPointerException(env, "NullPointerException");
0N/A return;
0N/A }
0N/A AWT_LOCK();
0N/A
0N/A font = (*env)->GetObjectField(env, this, x11FontMetricsIDs.font);
0N/A if (JNU_IsNull(env, this)) {
0N/A JNU_ThrowNullPointerException(env, "NullPointerException");
0N/A AWT_UNLOCK();
0N/A return;
0N/A }
0N/A fdata = awtJNI_GetFontData(env, font, &err);
0N/A if (fdata == NULL) {
0N/A JNU_ThrowInternalError(env, err);
0N/A AWT_UNLOCK();
0N/A return;
0N/A }
0N/A
0N/A /*
0N/A * Bug 4103248, 4120310. We must take all of the fonts into
0N/A * consideration in providing the metrics, not just the 8859-1 font,
0N/A * because the underlying Motif widgets are.
0N/A */
0N/A if (awtJNI_IsMultiFont(env, font) && fdata->xfs == NULL) {
0N/A fdata->xfs = awtJNI_MakeFontSet(env, font);
0N/A }
0N/A if (fdata->xfs != NULL) {
0N/A XFontSetExtents *fs_extents = NULL;
0N/A fs_extents = XExtentsOfFontSet(fdata->xfs);
0N/A
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxAscent,
0N/A (jint)(-fs_extents->max_logical_extent.y));
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxDescent,
0N/A (jint)(fs_extents->max_logical_extent.height +
0N/A fs_extents->max_logical_extent.y));
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxAdvance,
0N/A (jint)(fs_extents->max_logical_extent.width));
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.ascent,
0N/A (jint)(-fs_extents->max_ink_extent.y));
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.descent,
0N/A (jint)(fs_extents->max_ink_extent.height +
0N/A fs_extents->max_ink_extent.y));
0N/A } else {
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxAscent,
0N/A (jint) fdata->xfont->max_bounds.ascent);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxDescent,
0N/A (jint) fdata->xfont->max_bounds.descent);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxAdvance,
0N/A (jint) fdata->xfont->max_bounds.width);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.ascent,
0N/A (jint) fdata->xfont->ascent);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.descent,
0N/A (jint) fdata->xfont->descent);
0N/A }
0N/A
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.leading, (jint) 1);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.height,
0N/A (jint) fdata->xfont->ascent + fdata->xfont->descent + 1);
0N/A (*env)->SetIntField(env, this, x11FontMetricsIDs.maxHeight,
0N/A (jint) fdata->xfont->max_bounds.ascent
0N/A + fdata->xfont->max_bounds.descent + 1);
0N/A
0N/A
0N/A widths = (*env)->NewIntArray(env, 256);
0N/A (*env)->SetObjectField(env, this, x11FontMetricsIDs.widths, widths);
0N/A if (JNU_IsNull(env, widths)) {
0N/A JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
0N/A AWT_UNLOCK();
0N/A return;
0N/A }
0N/A /*
0N/A * We could pin the array and then release it, but I believe this method
0N/A * is faster and perturbs the VM less
0N/A *
0N/A */
0N/A memset(tempWidths, 0, 256 * sizeof(jint));
0N/A
0N/A tempWidthsIndex = fdata->xfont->min_char_or_byte2;
0N/A
0N/A ccount = fdata->xfont->max_char_or_byte2 - fdata->xfont->min_char_or_byte2;
0N/A
0N/A if (fdata->xfont->per_char) {
0N/A for (i = 0; i <= ccount; i++) {
0N/A tempWidths[tempWidthsIndex++] = (jint) fdata->xfont->per_char[i].width;
0N/A }
0N/A } else {
0N/A for (i = 0; i <= ccount; i++) {
0N/A tempWidths[tempWidthsIndex++] = (jint) fdata->xfont->max_bounds.width;
0N/A }
0N/A }
0N/A
0N/A (*env)->SetIntArrayRegion(env, widths, 0, 256, (jint *) tempWidths);
0N/A
0N/A AWT_UNLOCK();
0N/A}
0N/A
0N/A/*
0N/A * Registered with the 2D disposer to be called after the Font is GC'd.
0N/A */
0N/Astatic void pDataDisposeMethod(JNIEnv *env, jlong pData)
0N/A{
0N/A struct FontData *fdata = NULL;
0N/A int32_t i = 0;
0N/A Display *display = XDISPLAY;
0N/A
0N/A AWT_LOCK();
0N/A fdata = (struct FontData *)pData;
0N/A
0N/A if (fdata == NULL) {
0N/A AWT_UNLOCK();
0N/A return;
0N/A }
0N/A
0N/A if (fdata->xfs != NULL) {
0N/A XFreeFontSet(display, fdata->xfs);
0N/A }
0N/A
0N/A /* AWT fonts are always "multifonts" and probably have been in
0N/A * all post 1.0 releases, so this test test for multi fonts is
0N/A * probably not needed, and the singleton xfont is probably never used.
0N/A */
0N/A if (fdata->charset_num > 0) {
0N/A for (i = 0; i < fdata->charset_num; i++) {
0N/A free((void *)fdata->flist[i].xlfd);
0N/A JNU_ReleaseStringPlatformChars(env, NULL,
0N/A fdata->flist[i].charset_name);
0N/A if (fdata->flist[i].load) {
0N/A XFreeFont(display, fdata->flist[i].xfont);
0N/A }
0N/A }
0N/A
0N/A free((void *)fdata->flist);
0N/A
0N/A /* Don't free fdata->xfont because it is equal to fdata->flist[i].xfont
0N/A for some 'i' */
0N/A } else {
0N/A if (fdata->xfont != NULL) {
0N/A XFreeFont(display, fdata->xfont);
0N/A }
0N/A }
0N/A
0N/A free((void *)fdata);
0N/A
0N/A AWT_UNLOCK();
0N/A}
0N/A#endif /* !HEADLESS */