/* * Copyright (c) 1995, 2014, Oracle and/or its affiliates. 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #ifndef HEADLESS #include "awt_p.h" #include #include "java_awt_Component.h" #include "java_awt_Font.h" #include "java_awt_FontMetrics.h" #include "sun_awt_X11GraphicsEnvironment.h" #include "awt_Font.h" #include "java_awt_Dimension.h" #include "Disposer.h" #endif /* !HEADLESS */ #include #ifndef HEADLESS #include #define defaultXLFD "-*-helvetica-*-*-*-*-12-*-*-*-*-*-iso8859-1" struct FontIDs fontIDs; struct PlatformFontIDs platformFontIDs; static void pDataDisposeMethod(JNIEnv *env, jlong pData); /* #define FONT_DEBUG 2 */ /* 1- print failures, 2- print all, 3- terminate on failure */ #if FONT_DEBUG static XFontStruct *XLoadQueryFontX(Display *display, char *name) { XFontStruct *result = NULL; result = XLoadQueryFont(display, name); #if FONT_DEBUG < 2 if (result == NULL) #endif fprintf(stderr, "XLoadQueryFont(\"%s\") -> 0x%x.\n", name, result); #if FONT_DEBUG >= 3 if (result == NULL) exit(-1); #endif return result; } #define XLoadQueryFont XLoadQueryFontX #endif #endif /* !HEADLESS */ /* * Class: java_awt_Font * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for Font.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_java_awt_Font_initIDs (JNIEnv *env, jclass cls) { #ifndef HEADLESS CHECK_NULL(fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J")); CHECK_NULL(fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I")); CHECK_NULL(fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I")); CHECK_NULL(fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getFontPeer", "()Ljava/awt/peer/FontPeer;")); CHECK_NULL(fontIDs.getFamily = (*env)->GetMethodID(env, cls, "getFamily_NoClientCode", "()Ljava/lang/String;")); #endif /* !HEADLESS */ } #ifndef HEADLESS /* fieldIDs for FontDescriptor fields that may be accessed from C */ static struct FontDescriptorIDs { jfieldID nativeName; jfieldID charsetName; } fontDescriptorIDs; #endif /* !HEADLESS */ /* * Class: sun_awt_FontDescriptor * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for FontDescriptor.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_sun_awt_FontDescriptor_initIDs (JNIEnv *env, jclass cls) { #ifndef HEADLESS CHECK_NULL(fontDescriptorIDs.nativeName = (*env)->GetFieldID(env, cls, "nativeName", "Ljava/lang/String;")); CHECK_NULL(fontDescriptorIDs.charsetName = (*env)->GetFieldID(env, cls, "charsetName", "Ljava/lang/String;")); #endif /* !HEADLESS */ } /* * Class: sun_awt_PlatformFont * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for PlatformFont.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_sun_awt_PlatformFont_initIDs (JNIEnv *env, jclass cls) { #ifndef HEADLESS CHECK_NULL(platformFontIDs.componentFonts = (*env)->GetFieldID(env, cls, "componentFonts", "[Lsun/awt/FontDescriptor;")); CHECK_NULL(platformFontIDs.fontConfig = (*env)->GetFieldID(env,cls, "fontConfig", "Lsun/awt/FontConfiguration;")); CHECK_NULL(platformFontIDs.makeConvertedMultiFontString = (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString", "(Ljava/lang/String;)[Ljava/lang/Object;")); CHECK_NULL(platformFontIDs.makeConvertedMultiFontChars = (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars", "([CII)[Ljava/lang/Object;")); #endif /* !HEADLESS */ } #ifndef HEADLESS XFontStruct * loadFont(Display * display, char *name, int32_t pointSize) { XFontStruct *f = NULL; /* try the exact xlfd name in font configuration file */ f = XLoadQueryFont(display, name); if (f != NULL) { return f; } /* * try nearly font * * 1. specify FAMILY_NAME, WEIGHT_NAME, SLANT, POINT_SIZE, * CHARSET_REGISTRY and CHARSET_ENCODING. * 2. change POINT_SIZE to PIXEL_SIZE * 3. change FAMILY_NAME to * * 4. specify only PIXEL_SIZE and CHARSET_REGISTRY/ENCODING * 5. change PIXEL_SIZE +1/-1/+2/-2...+4/-4 * 6. default font pattern */ { /* * This code assumes the name contains exactly 14 '-' delimiter. * If not use default pattern. */ int32_t i, length, pixelSize; Boolean useDefault = FALSE; char buffer[BUFSIZ], buffer2[BUFSIZ]; char *family = NULL, *style = NULL, *slant = NULL, *encoding = NULL; char *start = NULL, *end = NULL; if (strlen(name) > BUFSIZ - 1) { useDefault = TRUE; } else { strcpy(buffer, name); } #define NEXT_HYPHEN\ start = end + 1;\ end = strchr(start, '-');\ if (end == NULL) {\ useDefault = TRUE;\ break;\ }\ *end = '\0' do { end = buffer; /* skip FOUNDRY */ NEXT_HYPHEN; /* set FAMILY_NAME */ NEXT_HYPHEN; family = start; /* set STYLE_NAME */ NEXT_HYPHEN; style = start; /* set SLANT */ NEXT_HYPHEN; slant = start; /* skip SETWIDTH_NAME, ADD_STYLE_NAME, PIXEL_SIZE POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, SPACING and AVERAGE_WIDTH */ NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; NEXT_HYPHEN; /* set CHARSET_REGISTRY and CHARSET_ENCODING */ encoding = end + 1; } while (0); #define TRY_LOAD\ f = XLoadQueryFont(display, buffer2);\ if (f != NULL) {\ strcpy(name, buffer2);\ return f;\ } if (!useDefault) { char *altstyle = NULL; /* Regular is the style for TrueType fonts -- Type1, F3 use roman */ if (strcmp(style, "regular") == 0) { altstyle = "roman"; } #if defined(__linux__) || defined(MACOSX) if (!strcmp(family, "lucidasans")) { family = "lucida"; } #endif /* try 1. */ jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", family, style, slant, pointSize, encoding); TRY_LOAD; if (altstyle != NULL) { jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", family, altstyle, slant, pointSize, encoding); TRY_LOAD; } /* search bitmap font */ pixelSize = pointSize / 10; /* try 2. */ jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", family, style, slant, pixelSize, encoding); TRY_LOAD; if (altstyle != NULL) { jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", family, altstyle, slant, pixelSize, encoding); TRY_LOAD; } /* try 3 */ jio_snprintf(buffer2, sizeof(buffer2), "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", style, slant, pixelSize, encoding); TRY_LOAD; if (altstyle != NULL) { jio_snprintf(buffer2, sizeof(buffer2), "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", altstyle, slant, pixelSize, encoding); TRY_LOAD; } /* try 4 */ jio_snprintf(buffer2, sizeof(buffer2), "-*-*-*-%s-*-*-%d-*-*-*-*-*-%s", slant, pixelSize, encoding); TRY_LOAD; /* try 5. */ jio_snprintf(buffer2, sizeof(buffer2), "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", pixelSize, encoding); TRY_LOAD; /* try 6. */ for (i = 1; i < 4; i++) { if (pixelSize < i) break; jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", family, style, slant, pixelSize + i, encoding); TRY_LOAD; jio_snprintf(buffer2, sizeof(buffer2), "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", family, style, slant, pixelSize - i, encoding); TRY_LOAD; jio_snprintf(buffer2, sizeof(buffer2), "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", pixelSize + i, encoding); TRY_LOAD; jio_snprintf(buffer2, sizeof(buffer2), "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", pixelSize - i, encoding); TRY_LOAD; } } } strcpy(name, defaultXLFD); return XLoadQueryFont(display, defaultXLFD); } /* * Hardwired list of mappings for generic font names "Helvetica", * "TimesRoman", "Courier", "Dialog", and "DialogInput". */ static char *defaultfontname = "fixed"; static char *defaultfoundry = "misc"; static char *anyfoundry = "*"; static char *anystyle = "*-*"; static char *isolatin1 = "iso8859-1"; static char * Style(int32_t s) { switch (s) { case java_awt_Font_ITALIC: return "medium-i"; case java_awt_Font_BOLD: return "bold-r"; case java_awt_Font_BOLD + java_awt_Font_ITALIC: return "bold-i"; case java_awt_Font_PLAIN: default: return "medium-r"; } } static int32_t awtJNI_FontName(JNIEnv * env, jstring name, char **foundry, char **facename, char **encoding) { char *cname = NULL; if (JNU_IsNull(env, name)) { return 0; } cname = (char *) JNU_GetStringPlatformChars(env, name, NULL); if (cname == NULL) { (*env)->ExceptionClear(env); JNU_ThrowOutOfMemoryError(env, "Could not create font name"); return 0; } /* additional default font names */ if (strcmp(cname, "serif") == 0) { *foundry = "adobe"; *facename = "times"; *encoding = isolatin1; } else if (strcmp(cname, "sansserif") == 0) { *foundry = "adobe"; *facename = "helvetica"; *encoding = isolatin1; } else if (strcmp(cname, "monospaced") == 0) { *foundry = "adobe"; *facename = "courier"; *encoding = isolatin1; } else if (strcmp(cname, "helvetica") == 0) { *foundry = "adobe"; *facename = "helvetica"; *encoding = isolatin1; } else if (strcmp(cname, "timesroman") == 0) { *foundry = "adobe"; *facename = "times"; *encoding = isolatin1; } else if (strcmp(cname, "courier") == 0) { *foundry = "adobe"; *facename = "courier"; *encoding = isolatin1; } else if (strcmp(cname, "dialog") == 0) { *foundry = "b&h"; *facename = "lucida"; *encoding = isolatin1; } else if (strcmp(cname, "dialoginput") == 0) { *foundry = "b&h"; *facename = "lucidatypewriter"; *encoding = isolatin1; } else if (strcmp(cname, "zapfdingbats") == 0) { *foundry = "itc"; *facename = "zapfdingbats"; *encoding = "*-*"; } else { #ifdef DEBUG jio_fprintf(stderr, "Unknown font: %s\n", cname); #endif *foundry = defaultfoundry; *facename = defaultfontname; *encoding = isolatin1; } if (cname != NULL) JNU_ReleaseStringPlatformChars(env, name, (const char *) cname); return 1; } /* * Registered with the 2D disposer to be called after the Font is GC'd. */ static void pDataDisposeMethod(JNIEnv *env, jlong pData) { struct FontData *fdata = NULL; int32_t i = 0; Display *display = XDISPLAY; AWT_LOCK(); fdata = (struct FontData *)pData; if (fdata == NULL) { AWT_UNLOCK(); return; } if (fdata->xfs != NULL) { XFreeFontSet(display, fdata->xfs); } /* AWT fonts are always "multifonts" and probably have been in * all post 1.0 releases, so this test for multi fonts is * probably not needed, and the singleton xfont is probably never used. */ if (fdata->charset_num > 0) { for (i = 0; i < fdata->charset_num; i++) { free((void *)fdata->flist[i].xlfd); JNU_ReleaseStringPlatformChars(env, NULL, fdata->flist[i].charset_name); if (fdata->flist[i].load) { XFreeFont(display, fdata->flist[i].xfont); } } free((void *)fdata->flist); /* Don't free fdata->xfont because it is equal to fdata->flist[i].xfont for some 'i' */ } else { if (fdata->xfont != NULL) { XFreeFont(display, fdata->xfont); } } free((void *)fdata); AWT_UNLOCK(); } #endif /* !HEADLESS */