| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /** |
| * @author Ilya S. Okomin |
| * |
| */ |
| #include <X11/Xft/Xft.h> |
| #include <freetype/tttables.h> |
| #include <freetype/t1tables.h> |
| |
| #include <jni.h> |
| |
| #include "FontLibExports.h" |
| |
| #if (FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2) |
| |
| #undef HAS_FREETYPE_INTERNAL |
| #include <freetype/ftsizes.h> |
| #include <freetype/ftglyph.h> |
| #ifndef FALSE |
| #define FALSE (0) |
| #define TRUE (1) |
| #endif /* FALSE */ |
| |
| #else /* FREETYPE_MAJOR ... */ |
| |
| #define HAS_FREETYPE_INTERNAL 1 |
| #include <freetype/internal/tttypes.h> |
| |
| #endif /* FREETYPE_MAJOR ... */ |
| |
| #include <freetype/ftsnames.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include<string.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| #include <wchar.h> |
| #include <math.h> |
| |
| #include "LinuxNativeFont.h" |
| #include "exceptions.h" |
| #include "org_apache_harmony_awt_gl_font_LinuxNativeFont.h" |
| /* debug code marker - to print debug information change to DEBUG */ |
| # define NO_DEBUG |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getFontFamiliesNames |
| * Signature: ()[Ljava/lang/String; |
| * Returns array of Strings that represents list of all font families names |
| * available on the system. |
| */ |
| JNIEXPORT jobjectArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getFontFamiliesNames(JNIEnv *env, jclass jobj){ |
| |
| jobjectArray families; |
| |
| XftObjectSet *os = 0; |
| XftPattern *xftPattern; |
| XftFontSet *fs; |
| int j, i; |
| int len; |
| int numFamilies; |
| FcChar8 *family; |
| char** famList; |
| jclass strClass; |
| jstring initStr; |
| |
| |
| /* Create pattern */ |
| xftPattern = XftPatternCreate(); |
| |
| if (!XftPatternAddBool (xftPattern, XFT_OUTLINE, True)){ |
| throwNPException(env, "Outline value can't be added to XftPattern"); |
| } |
| |
| /* Just need to add which fields you want to list */ |
| os = XftObjectSetBuild (XFT_FAMILY, (char *) 0); |
| |
| fs = FcFontList (0, xftPattern, os); |
| |
| XftObjectSetDestroy (os); |
| |
| if(xftPattern){ |
| XftPatternDestroy(xftPattern); |
| } |
| |
| if (!fs){ |
| throwNPException(env, "Font list can't be created"); |
| return NULL; |
| } else { |
| numFamilies = fs->nfont; |
| famList = (char** )malloc(numFamilies * sizeof(char *)); |
| |
| for (j = 0; j < numFamilies; j++) { |
| |
| #ifdef DEBUG |
| FcChar8* font = FcNameUnparse (fs->fonts[j]); |
| printf ("%s\n", font); |
| free (font); |
| #endif /* DEBUG */ |
| |
| if (XftPatternGetString (fs->fonts[j], XFT_FAMILY, 0, &family) == XftResultMatch){ |
| |
| #ifdef DEBUG |
| printf (" %s", family); |
| #endif /* DEBUG */ |
| |
| len = (strlen((char *)family)+1); |
| famList[j] = (char*)malloc(sizeof(char) * len); |
| |
| strncpy(famList[j], (char *)family, len); |
| } else { |
| /* |
| * TODO |
| * We should add special handling for this case |
| */ |
| famList[j] = 0; |
| } |
| } |
| XftFontSetDestroy (fs); |
| } |
| |
| strClass = (*env)->FindClass(env, "java/lang/String"); |
| initStr = (*env)->NewStringUTF(env, ""); |
| |
| families = (jobjectArray)(*env)->NewObjectArray(env, |
| numFamilies, |
| strClass, |
| initStr); |
| |
| if (families == NULL){ |
| for (i = 0;i < numFamilies;i++){ |
| free(famList[i]); |
| } |
| free(famList); |
| throwNPException(env, "Not enough memory to create families list"); |
| return NULL; |
| } |
| |
| for (i = 0;i < numFamilies;i++){ |
| // number of chars == length of string -1 |
| (*env)->SetObjectArrayElement(env, families,i,(*env)->NewStringUTF(env, famList[i])); |
| free(famList[i]); |
| } |
| free(famList); |
| |
| return families; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: embedFontNative |
| * Signature: (Ljava/lang/String;)Z |
| * |
| * Returns true if the new font was added to the system, false otherwise. |
| * Methods checks if the number of system fonts changed after font configuration |
| * was rebuilt. |
| */ |
| JNIEXPORT jstring JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_embedFontNative(JNIEnv *env, jclass obj, jstring fName){ |
| |
| int fontAdded = FALSE; |
| FcConfig *config; |
| |
| config = FcConfigGetCurrent(); |
| if (!config){ |
| return 0; |
| } |
| |
| char *path = (char *)(*env)->GetStringUTFChars(env, fName, 0); |
| fontAdded = FcConfigAppFontAddFile(config, (unsigned char*)path); |
| |
| unsigned short *familyName = 0; |
| |
| if (fontAdded) { |
| getFontFamilyName(path, &familyName); |
| } |
| |
| (*env)->ReleaseStringUTFChars(env, fName, path); |
| |
| jstring res = 0; |
| if (fontAdded && familyName) { |
| int len = 0; |
| for (; familyName[len] != 0; len++); |
| res = (*env)->NewString(env, (jchar *)familyName, len); |
| free(familyName); |
| } |
| |
| return res; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: initializeFont |
| * Signature: (Lorg/apache/harmony/awt/gl/font/LinuxFont;Ljava/lang/String;IILjava/lang/String;)J |
| * Initiailzes native Xft font object from specified parameters and returns |
| * font handle, also sets font type to the font peer parameter. |
| * NullPointerException is thrown if there are errors in native code. |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_initializeFont(JNIEnv *env, jclass jobj, jobject linuxFont, jstring jName, jint jStyle, jint size, jstring jFaceStyle){ |
| |
| jclass cls; |
| jfieldID fid; |
| jmethodID mid; |
| jboolean iscopy; |
| |
| int slant; |
| int weight; |
| const char* name; |
| |
| XftPattern *pattern; |
| XftPattern *matchPattern; |
| XftResult result; |
| Display *dpy; |
| int scr; |
| FcChar8 *faceStyle = NULL; |
| XftFont *xftFnt; |
| int font_type = FONT_TYPE_UNDEF; |
| double fSize; |
| FT_Face face; |
| |
| /* Initialize part */ |
| cls = (*env)->GetObjectClass(env, linuxFont); |
| |
| fid=(*env)->GetFieldID(env, cls, "display", "J"); |
| if (fid == 0) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| dpy = (Display *)(long)(*env)->GetLongField(env, linuxFont, fid); |
| |
| if (dpy == NULL){ |
| throwNPException(env, "Cannot connect to XServer"); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| if (jStyle & FONT_BOLD) { |
| // TODO: need to be defined from TextAttributes |
| weight = XFT_WEIGHT_BOLD; |
| #ifdef DEBUG |
| printf("Weight is bold"); |
| #endif // DEBUG |
| } else { |
| // TODO: need to be defined from TextAttributes |
| weight = XFT_WEIGHT_MEDIUM; |
| #ifdef DEBUG |
| printf("Weight is medium"); |
| #endif // DEBUG |
| } |
| |
| if (jStyle & FONT_ITALIC){ |
| slant = XFT_SLANT_ITALIC; |
| } else { |
| slant = XFT_SLANT_ROMAN; |
| } |
| |
| fid=(*env)->GetFieldID(env, cls, "screen", "I"); |
| if (fid == 0) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| scr = (*env)->GetIntField(env, linuxFont, fid); |
| |
| name = (*env)->GetStringUTFChars(env, jName, &iscopy); |
| if (jFaceStyle){ |
| faceStyle = (FcChar8 *)(*env)->GetStringUTFChars(env, jFaceStyle, &iscopy); |
| } |
| |
| /* Xft part */ |
| /* Create pattern */ |
| pattern = XftPatternCreate(); |
| |
| if (!XftPatternAddString (pattern, XFT_FAMILY, name)){ |
| if(name){ |
| (*env)->ReleaseStringUTFChars(env, jName, name); |
| } |
| if(faceStyle){ |
| (*env)->ReleaseStringUTFChars(env, jFaceStyle, (char *)faceStyle); |
| } |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding family name to XFTPattern structure"); |
| } |
| |
| /* We do not need name any more */ |
| if(name){ |
| (*env)->ReleaseStringUTFChars(env, jName, name); |
| } |
| |
| if (faceStyle && !XftPatternAddString (pattern, XFT_STYLE, faceStyle)){ |
| if(faceStyle){ |
| (*env)->ReleaseStringUTFChars(env, jFaceStyle, (char *)faceStyle); |
| } |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding style name to XFTPattern structure"); |
| } |
| |
| /* We do not need faceStyle any more */ |
| if(faceStyle){ |
| XftPatternDestroy (pattern); |
| (*env)->ReleaseStringUTFChars(env, jFaceStyle, (char *)faceStyle); |
| } |
| |
| if (!XftPatternAddInteger(pattern, XFT_SLANT, slant)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font slant to XFTPattern structure"); |
| } |
| |
| if (!XftPatternAddInteger(pattern, XFT_WEIGHT, weight)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font weight to XFTPattern structure"); |
| } |
| |
| /* We set antialias mode for simple text rendering without antialiasing */ |
| if (!XftPatternAddBool(pattern, XFT_ANTIALIAS, False)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font antialias set to false to XFTPattern structure"); |
| } |
| |
| /* |
| * |
| * To comply with Java specification and results we have to use DPI value |
| * equals to 96. Actually, it is properly to use resolution Y value instead of DPI value |
| * the correct formula resolutionY = (XDisplayHeight(dpy, scr)/(XDisplayHeightMM(dpy, scr)/25.4)); |
| * hence size = size / (double)resolutionY * 72; |
| */ |
| |
| fSize = (double)size / 96 * 72; |
| |
| if (!XftPatternAddDouble (pattern, XFT_SIZE, fSize)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font size to XFTPattern structure"); |
| } |
| |
| /* if (!XftPatternAddBool (pattern, FC_HINTING, True)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font hinting set to false to XFTPattern structure"); |
| } |
| */ |
| |
| if (!XftPatternAddBool (pattern, XFT_RENDER, True)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font RENDER set to true to XFTPattern structure"); |
| } |
| |
| |
| if (!XftPatternAddBool (pattern, FC_AUTOHINT, True)){ |
| XftPatternDestroy (pattern); |
| throwNPException(env, "Error during adding font autohinting set to false to XFTPattern structure"); |
| } |
| |
| matchPattern = XftFontMatch (dpy, scr, pattern, &result); |
| |
| #ifdef DEBUG |
| printf ("Pattern "); |
| FcPatternPrint (pattern); |
| if (matchPattern) |
| { |
| printf ("Match "); |
| FcPatternPrint (matchPattern); |
| } |
| else { |
| printf ("No Match\n"); |
| } |
| #endif /* DEBUG */ |
| |
| XftPatternDestroy (pattern); |
| |
| if (!matchPattern){ |
| XftPatternDestroy (matchPattern); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| xftFnt = XftFontOpenPattern (dpy, matchPattern); |
| |
| if (!xftFnt){ |
| XftPatternDestroy (matchPattern); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| /* defining font type */ |
| face = XftLockFace(xftFnt); |
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) && |
| !(face->face_flags & FT_FACE_FLAG_FIXED_SIZES) && |
| !(face->face_flags & FT_FACE_FLAG_SFNT)) { |
| font_type = FONT_TYPE_T1; |
| } else { |
| font_type = FONT_TYPE_TT; |
| } |
| XftUnlockFace(xftFnt); |
| |
| if (font_type == FONT_TYPE_UNDEF){ |
| XftFontClose (dpy, xftFnt); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| /* Set Font type in LinuxFont object (upcall) */ |
| mid=(*env)->GetMethodID(env, cls, "setFontType", "(I)V"); |
| |
| if (mid == 0) { |
| #ifdef DEBUG |
| printf("Can't find \"setFontType\" method"); |
| #endif // DEBUG |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| (*env)->CallVoidMethod(env, linuxFont, mid, font_type); |
| |
| if((*env)->ExceptionOccurred(env)) { |
| #ifdef DEBUG |
| printf("Error occured when calling \"setFontType\" method"); |
| #endif // DEBUG |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| return (jlong)(IDATA)xftFnt; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: initializeFontFromFP |
| * Signature: (Lorg/apache/harmony/awt/gl/font/LinuxFont;Ljava/lang/String;)J |
| * Initializes native Xft font object from xlfd string and returns font handle, |
| * also sets font type to the font peer parameter. If font |
| * that is described by the given xlfd doesn't exist onto a system returned value |
| * is null. NullPointerException is thrown if there are errors in native code. |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_initializeFontFromFP(JNIEnv *env, jclass jobj, jobject linuxFont, jstring jXLFD, jint size){ |
| |
| jclass cls; |
| jfieldID fid; |
| jmethodID mid; |
| jboolean iscopy; |
| |
| const char* xlfd; |
| Display *dpy; |
| int scr; |
| XftFont *xftFnt; |
| int font_type = FONT_TYPE_UNDEF; |
| FT_Face face; |
| |
| char **fn; |
| int n = 0; |
| int buf_size; |
| char *buffer; |
| |
| XftPattern *pattern; |
| XftPattern *matchPattern; |
| XftResult result; |
| |
| // Initialize part |
| cls = (*env)->GetObjectClass(env, linuxFont); |
| |
| /* get display value */ |
| fid=(*env)->GetFieldID(env, cls, "display", "J"); |
| if (fid == 0) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| dpy = (Display *)(long)(*env)->GetLongField(env, linuxFont, fid); |
| |
| if (dpy == NULL){ |
| throwNPException(env, "Cannot connect to XServer"); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| xlfd = (*env)->GetStringUTFChars(env, jXLFD, &iscopy); |
| buf_size = (*env)->GetStringLength(env, jXLFD) + 8; |
| buffer = (char *)malloc(buf_size); |
| |
| snprintf(buffer, buf_size, xlfd, (int)((double)(size*10) / 96 * 72)); |
| (*env)->ReleaseStringUTFChars(env, jXLFD, xlfd); |
| |
| /* get screen value */ |
| fid=(*env)->GetFieldID(env, cls, "screen", "I"); |
| if (fid == 0) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| free(buffer); |
| return (jlong)(IDATA)NULL; |
| } |
| scr = (*env)->GetIntField(env, linuxFont, fid); |
| |
| /* check if there any fonts with specified xlfd structure */ |
| fn = XListFonts( dpy, buffer, 10, &n ); |
| if (fn != NULL){ |
| XFreeFontNames(fn); |
| } |
| |
| if (n == 0){ |
| free(buffer); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| /* Xft part */ |
| /* Create xlfd pattern */ |
| pattern = XftXlfdParse(buffer, False, True); |
| |
| /* We set antialias mode for simple text rendering without antialiasing */ |
| if (!XftPatternAddBool(pattern, XFT_ANTIALIAS, False)){ |
| throwNPException(env, "Error during adding font antialias set to false to XFTPattern structure"); |
| } |
| |
| if (!XftPatternAddBool (pattern, XFT_RENDER, True)){ |
| throwNPException(env, "Error during adding font RENDER set to true to XFTPattern structure"); |
| } |
| |
| |
| if (!XftPatternAddBool (pattern, FC_AUTOHINT, True)){ |
| throwNPException(env, "Error during adding font autohinting set to false to XFTPattern structure"); |
| } |
| |
| |
| matchPattern = XftFontMatch (dpy, scr, pattern, &result); |
| |
| #ifdef DEBUG |
| printf ("Pattern "); |
| FcPatternPrint (pattern); |
| if (matchPattern) |
| { |
| printf ("Match "); |
| FcPatternPrint (matchPattern); |
| } |
| else { |
| printf ("No Match\n"); |
| } |
| #endif // DEBUG |
| |
| XftPatternDestroy (pattern); |
| |
| if (!matchPattern){ |
| XftPatternDestroy (matchPattern); |
| return (long)NULL; |
| } |
| |
| xftFnt = XftFontOpenPattern (dpy, matchPattern); |
| |
| if (!xftFnt){ |
| XftPatternDestroy (matchPattern); |
| return (long)NULL; |
| } |
| |
| free(buffer); |
| |
| if (!xftFnt){ |
| return (long)NULL; |
| } |
| |
| face = XftLockFace(xftFnt); |
| |
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) && |
| !(face->face_flags & FT_FACE_FLAG_FIXED_SIZES)){ |
| if (face->face_flags & FT_FACE_FLAG_SFNT){ |
| font_type = FONT_TYPE_TT; |
| } else { |
| font_type = FONT_TYPE_T1; |
| } |
| } |
| XftUnlockFace(xftFnt); |
| |
| |
| if (font_type == FONT_TYPE_UNDEF){ |
| XftFontClose (dpy, xftFnt); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| /* Set Font type in LinuxFont object (upcall) */ |
| mid=(*env)->GetMethodID(env, cls, "setFontType", "(I)V"); |
| |
| if (mid == 0) { |
| #ifdef DEBUG |
| printf("Can't find \"setFontType\" method"); |
| #endif // DEBUG |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| (*env)->CallVoidMethod(env, linuxFont, mid, font_type); |
| |
| if((*env)->ExceptionOccurred(env)) { |
| #ifdef DEBUG |
| printf("Error occured when calling \"setFontType\" method"); |
| #endif // DEBUG |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| return (jlong)(IDATA)NULL; |
| } |
| |
| return (long)xftFnt; |
| |
| } |
| |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getNumGlyphsNative |
| * Signature: (J)I |
| * Returns number of glyphs in specified XftFont if success. |
| */ |
| JNIEXPORT jint JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getNumGlyphsNative(JNIEnv *env, jclass obj, jlong fnt){ |
| |
| jint numGlyphs = 0; |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| |
| if(!xftFnt){ |
| return 0; |
| } |
| face = XftLockFace(xftFnt); |
| |
| if(!face) |
| return 0; |
| numGlyphs = face->num_glyphs; |
| |
| #ifdef DEBUG |
| printf("Num glyphs = %d\n", numGlyphs); |
| #endif /* DEBUG */ |
| |
| XftUnlockFace(xftFnt); |
| |
| |
| return numGlyphs; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: canDisplayCharNative |
| * Signature: (JC)Z |
| * Returns true, if XftFont object can display specified char. |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_canDisplayCharNative(JNIEnv *env, jclass obj, jlong fnt, jchar c){ |
| |
| jboolean canDisplay = 0; |
| |
| /* TODO: implement method - or we can use getGlyphCode results to find out, |
| * whether we can display char or not. |
| */ |
| |
| return canDisplay; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getFamilyNative |
| * Signature: (J)Ljava/lang/String; |
| * Returns family name of the XftFont object. |
| */ |
| JNIEXPORT jstring JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getFamilyNative(JNIEnv *env, jclass obj, jlong fnt){ |
| |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| |
| jstring familyName = NULL; |
| char* family; |
| |
| if (XftPatternGetString (xftFnt->pattern, XFT_FAMILY, 0, &family) != XftResultMatch){ |
| throwNPException(env, "Can not get font family value"); |
| } |
| |
| familyName = (*env)->NewStringUTF(env, family); |
| |
| return familyName; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getFontNameNative |
| * Signature: (J)Ljava/lang/String; |
| * Returns face name of the XftFont object. |
| */ |
| JNIEXPORT jstring JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getFontNameNative(JNIEnv *env, jclass obj, jlong fnt){ |
| |
| // !! at the moment only EN locale font names used |
| jstring faceName = NULL; |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| const int BUF_SIZE = 64; |
| char name[BUF_SIZE]; |
| |
| if(!xftFnt){ |
| return 0; |
| } |
| face = XftLockFace(xftFnt); |
| |
| if(!face) |
| return 0; |
| |
| snprintf(name, BUF_SIZE, "%s %s", face->family_name, face->style_name); |
| |
| #ifdef DEBUG |
| printf("Face name = %s\n", name); |
| #endif // DEBUG |
| |
| XftUnlockFace(xftFnt); |
| |
| |
| faceName = (*env)->NewStringUTF(env, name); |
| |
| return faceName; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getFontPSNameNative |
| * Signature: (J)Ljava/lang/String; |
| * Returns XftFont's postscript name. |
| * Returned value is the name of the font in system default locale or |
| * for english langid if there is no results for default locale settings. |
| */ |
| JNIEXPORT jstring JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getFontPSNameNative(JNIEnv *env, jclass obj, jlong fnt){ |
| |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| const char* name; |
| jstring psName; |
| |
| if(!xftFnt){ |
| return 0; |
| } |
| face = XftLockFace(xftFnt); |
| |
| if(!face) |
| return 0; |
| |
| name = FT_Get_Postscript_Name(face); |
| #ifdef DEBUG |
| printf("PostScript name = %s\n", name); |
| #endif /* DEBUG */ |
| |
| |
| psName = (*env)->NewStringUTF(env, name); |
| |
| XftUnlockFace(xftFnt); |
| |
| |
| return psName; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: pFontFree |
| * Signature: (JJ)V |
| * Disposes XftFont object. |
| */ |
| JNIEXPORT void JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_pFontFree(JNIEnv *env, jclass obj, jlong fnt, jlong display){ |
| |
| Display *dpy = (Display *)(long)display; |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| if(xftFnt){ |
| XftFontClose (dpy, xftFnt); |
| } |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getItalicAngleNative |
| * Signature: (JI)F |
| * Returns tangent of Italic angle of given Font. |
| * Returned value is null and NullPointerException is thrown if there is Xft error. |
| */ |
| JNIEXPORT jfloat JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getItalicAngleNative(JNIEnv *env, jclass obj, jlong fnt, int fontType){ |
| |
| jfloat italicAngle = 0.0; |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| #if HAS_FREETYPE_INTERNAL |
| TT_Face tt_face; |
| #endif |
| TT_HoriHeader* hh; |
| float rise; |
| float run; |
| PS_FontInfoRec afont_info; |
| FT_Error err; |
| double pi = 3.1415926535; |
| |
| if(!xftFnt){ |
| return 0; |
| } |
| face = XftLockFace(xftFnt); |
| |
| if(!face){ |
| return 0; |
| } |
| if (fontType == FONT_TYPE_TT){ |
| #if HAS_FREETYPE_INTERNAL |
| tt_face = (TT_Face)face; |
| hh = &(tt_face->horizontal); |
| #else |
| hh = (TT_HoriHeader*)FT_Get_Sfnt_Table(face, ft_sfnt_hhea); |
| #endif |
| rise = (float)hh->caret_Slope_Rise; |
| run = (float)hh->caret_Slope_Run; |
| italicAngle = run / rise ; |
| } else { |
| err = FT_Get_PS_Font_Info( face, &afont_info); |
| if (err){ |
| XftUnlockFace(xftFnt); |
| |
| return italicAngle; |
| } |
| italicAngle = tan(((double)afont_info.italic_angle * pi) / 180); |
| } |
| |
| #ifdef DEBUG |
| printf("Italic angle value = %f\n", italicAngle); |
| #endif /* DEBUG */ |
| |
| XftUnlockFace(xftFnt); |
| |
| |
| return italicAngle; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getFonts |
| * Signature: ()[Ljava/lang/String; |
| * Returns an array of available system fonts names. |
| * In case of errors NullPointerException is thrown. |
| */ |
| JNIEXPORT jobjectArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getFonts(JNIEnv *env, jclass obj){ |
| |
| jobjectArray fonts; |
| |
| XftObjectSet *os = 0; |
| XftPattern *xftPattern; |
| int len; |
| XftFontSet *fs; |
| int j, i; |
| int numFonts; |
| const int BUF_SIZE = 128; |
| FcChar8 font[BUF_SIZE]; |
| FcChar8 *family; |
| FcChar8 *style; |
| char** fontList; |
| char* fstr="%s-%s-%d"; // "family name"-"styleName"-"style" |
| int fontStyle; |
| int weight; |
| int slant; |
| jclass strClass; |
| jstring initStr; |
| |
| /* Create pattern */ |
| xftPattern = XftPatternCreate(); |
| |
| if (!XftPatternAddBool (xftPattern, XFT_OUTLINE, True)){ |
| throwNPException(env, "Outline value can't be added to XftPattern"); |
| } |
| |
| /* Just need to add which fields you want to list */ |
| os = XftObjectSetBuild (XFT_FAMILY, XFT_STYLE, XFT_SLANT, XFT_WEIGHT, (char *) 0); |
| |
| fs = FcFontList (0, xftPattern, os); |
| |
| XftObjectSetDestroy (os); |
| |
| if(xftPattern){ |
| XftPatternDestroy(xftPattern); |
| } |
| |
| if (!fs){ |
| throwNPException(env, "Font list can't be created"); |
| return NULL; |
| } else { |
| numFonts = fs->nfont; |
| fontList = (char** )malloc(numFonts * sizeof(char *)); |
| |
| for (j = 0; j < numFonts; j++){ |
| if (XftPatternGetString (fs->fonts[j], XFT_FAMILY, 0, &family) != XftResultMatch){ |
| throwNPException(env, "Couldn't get font family name"); |
| } |
| |
| #ifdef DEBUG |
| { |
| FcChar8* font = FcNameUnparse (fs->fonts[j]); |
| printf ("%s\n", font); |
| free(font); |
| } |
| #endif /* DEBUG */ |
| |
| if (XftPatternGetString (fs->fonts[j], XFT_STYLE, 0, &style) != XftResultMatch) { |
| throwNPException(env, "Couldn't get font style name"); |
| } |
| |
| if (XftPatternGetInteger (fs->fonts[j], XFT_SLANT, 0, &slant) != XftResultMatch) { |
| throwNPException(env, "Couldn't get font slant"); |
| } |
| |
| if (XftPatternGetInteger (fs->fonts[j], XFT_WEIGHT, 0, &weight) != XftResultMatch) { |
| throwNPException(env, "Couldn't get font weight"); |
| } |
| |
| if (weight <= XFT_WEIGHT_MEDIUM) { |
| fontStyle = FONT_PLAIN; |
| } else { |
| fontStyle = FONT_BOLD; |
| } |
| |
| if (slant != XFT_SLANT_ROMAN){ |
| fontStyle |= FONT_ITALIC; |
| } |
| |
| len = snprintf((char *)font, BUF_SIZE, fstr, family, style, fontStyle); |
| |
| if (len < 0){ |
| len = BUF_SIZE; |
| } |
| |
| fontList[j] = (char*)malloc(sizeof(char) * (len+1)); |
| strncpy(fontList[j], (char *)font, len); |
| fontList[j][len] = 0; |
| } |
| XftFontSetDestroy (fs); |
| } |
| |
| |
| strClass = (*env)->FindClass(env, "java/lang/String"); |
| initStr = (*env)->NewStringUTF(env, ""); |
| |
| fonts = (jobjectArray)(*env)->NewObjectArray(env, |
| numFonts, |
| strClass, |
| initStr); |
| |
| if (fonts == NULL){ |
| for (i = 0;i < numFonts;i++){ |
| free(fontList[i]); |
| } |
| free(fontList); |
| |
| throwNPException(env, "Not enough memory to create families list"); |
| return (jobjectArray)NULL; |
| } |
| |
| for (i = 0;i < numFonts;i++){ |
| (*env)->SetObjectArrayElement(env, fonts,i,(*env)->NewStringUTF(env, fontList[i])); // number of chars == length of string -1 |
| free(fontList[i]); |
| } |
| free(fontList); |
| |
| return fonts; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getNativeLineMetrics |
| * Signature: (JIZZI)[F |
| * Returns array of values of font metrics corresponding to the given XftFont |
| * font object. NullPointerException is thrown in case of errors. |
| */ |
| JNIEXPORT jfloatArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getNativeLineMetrics(JNIEnv *env, jclass obj, jlong fnt, jint fontHeight, jboolean isAntialiased, jboolean usesFractionalMetrics, jint fontType){ |
| jfloatArray metrics; |
| jfloat values[17]; |
| |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| TT_OS2* os2; |
| #if HAS_FREETYPE_INTERNAL |
| TT_Face tt_face; |
| #endif |
| int units_per_EM; |
| FT_Size_Metrics size_metrics; |
| FT_Size size; |
| float mltpl; |
| |
| if (!xftFnt){ |
| return NULL; |
| } |
| #ifdef DEBUG |
| printf("XFT Ascent = %d\n", xftFnt->ascent); |
| printf("XFT Descent = %d\n", xftFnt->descent); |
| printf("XFT Height = %d\n", xftFnt->height); |
| #endif /* DEBUG */ |
| |
| face = XftLockFace(xftFnt); |
| |
| if(!face){ |
| return NULL; |
| } |
| units_per_EM = face->units_per_EM; |
| if (units_per_EM == 0){ |
| // throwNPException(env, "Units per EM value is equals to zero"); |
| XftUnlockFace(xftFnt); |
| |
| |
| return NULL; |
| } |
| values[16] = units_per_EM; |
| mltpl = (float)fontHeight / units_per_EM; |
| values[0] = (float)(face->ascender) * mltpl; // Ascent value |
| values[1] = (float)(face->descender) * mltpl; // -Descent value |
| values[2] = (float)(face->height) * mltpl - values[0] + values[1]; // External Leading value |
| values[3] = (float)(face->underline_thickness) * mltpl; // Underline size value |
| values[4] = (float)(face->underline_position) * mltpl; // Underline position value |
| |
| if (fontType == FONT_TYPE_TT){ |
| #if HAS_FREETYPE_INTERNAL |
| tt_face = (TT_Face)face; |
| os2 = &(tt_face->os2); |
| #else |
| os2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
| #endif |
| values[5] = (float)(os2->yStrikeoutSize) * mltpl; // Strikeout size value |
| values[6] = (float)(os2->yStrikeoutPosition) * mltpl; // Strikeout position value |
| } else { |
| values[5] = values[3]; |
| // !!Workaround: for Type1 fonts strikethrough position = (-ascent+descent)/2 |
| values[6] = (-values[0] - values[1])/2; |
| } |
| |
| values[7] = (float)(face->bbox.xMax - face->bbox.xMin)* mltpl; // Max char width |
| |
| size = face->size; |
| size_metrics = size->metrics; |
| values[8] = (int)size_metrics.ascender >> 6; // Ascent value |
| values[9] = (int)size_metrics.descender >> 6; // Descent value |
| values[10] = (int)(size_metrics.height >> 6) - values[8] + values[9]; // External Leading value |
| values[11] = (int)values[3]; // Underline size value |
| values[12] = (int)values[4]; // Underline position value |
| |
| values[13] = (int)values[5]; // Strikeout size value |
| values[14] = (int)values[6]; // Strikeout sposition value |
| |
| values[15] = (int)values[7]; // Max char width |
| |
| #ifdef DEBUG |
| printf("Ascent = %f\n", values[0]); |
| printf("Descent = %f\n", values[1]); |
| printf("External Leading = %f\n", values[2]); |
| printf("Underline size = %f\n", values[3]); |
| printf("Underline position = %f\n", values[4]); |
| printf("Strikeout size = %f\n", values[5]); |
| printf("Strikeout position = %f\n", values[6]); |
| printf("Max char width = %f\n", values[7]); |
| |
| printf("Pixel Ascent = %f\n", values[8]); |
| printf("Pixel Descent = %f\n", values[9]); |
| printf("Pixel External Leading = %f\n", values[10]); |
| printf("Pixel Underline size = %f\n", values[11]); |
| printf("Pixel Underline position = %f\n", values[12]); |
| printf("Pixel Strikeout size = %f\n", values[13]); |
| printf("Pixel Strikeout position = %f\n", values[14]); |
| printf("Pixel Max char width = %f\n", values[15]); |
| |
| #endif /* DEBUG */ |
| |
| XftUnlockFace(xftFnt); |
| |
| |
| metrics = (*env)->NewFloatArray(env, 17); |
| (*env)->SetFloatArrayRegion(env, metrics, 0, 17, values); |
| |
| return metrics; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getGlyphInfoNative |
| * Signature: (JCI)[F |
| * Returns array of glyph metrics values for the specified character |
| * null is returned and NullPointerException is thrown in case of FreeType |
| * errors. |
| */ |
| JNIEXPORT jfloatArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getGlyphInfoNative(JNIEnv *env, jclass obj, jlong fnt, jchar chr, jint fontHeight){ |
| |
| jfloatArray results = 0; |
| jfloat values[11]; |
| |
| XftFont *font = (XftFont *)(long)fnt; |
| const float CONST_96_DIV_76 = (float)96 / 72; |
| float mltpl; |
| FT_Face face; |
| FT_GlyphSlot glyphslot; |
| FT_Glyph_Metrics metrics; |
| |
| FT_Pos width; /* glyph width */ |
| FT_Pos height; /* glyph height */ |
| |
| FT_Pos horiBearingX; /* left side bearing in horizontal layouts */ |
| FT_Pos horiBearingY; /* top side bearing in horizontal layouts */ |
| FT_Pos horiAdvance; /* advance width for horizontal layout */ |
| |
| FT_Pos vertBearingX; /* left side bearing in vertical layouts */ |
| FT_Pos vertBearingY; /* top side bearing in vertical layouts */ |
| FT_Pos vertAdvance; /* advance height for vertical layout */ |
| int units_per_EM; |
| FT_Error error; |
| |
| if (!font){ |
| return results; |
| } |
| face = XftLockFace(font); |
| |
| if(!face){ |
| return results; |
| } |
| units_per_EM = face->units_per_EM; |
| |
| error = FT_Load_Char(face, (FT_ULong)chr, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO); |
| |
| if(error){ |
| // throwNPException(env, "FT_Load_char : FreeType error"); |
| XftUnlockFace(font); |
| |
| return NULL; |
| } |
| |
| glyphslot = face->glyph; |
| metrics = glyphslot->metrics; |
| |
| width = metrics.width; /* glyph width */ |
| height = metrics.height; /* glyph height */ |
| |
| horiBearingX = metrics.horiBearingX; /* left side bearing in horizontal layouts */ |
| horiBearingY = metrics.horiBearingY; /* top side bearing in horizontal layouts */ |
| horiAdvance = metrics.horiAdvance; /* advance width for horizontal layout */ |
| |
| vertBearingX = metrics.vertBearingX; /* left side bearing in vertical layouts */ |
| vertBearingY = metrics.vertBearingY; /* top side bearing in vertical layouts */ |
| vertAdvance = metrics.vertAdvance; /* advance height for vertical layout */ |
| |
| /* Multyplier to obtain proper values in pixels of the metrics */ |
| mltpl = CONST_96_DIV_76 / units_per_EM; |
| |
| #ifdef DEBUG |
| |
| printf("\n glyph metrics char = %d: : \n", chr); |
| printf("width = %d : height = %d \n", (int)width >> 6, (int)height >> 6); |
| printf("ghoriBearingX = %d : ghoriBearingY = %d \n", horiBearingX >> 6, horiBearingY>> 6); |
| printf("gvertBearingX = %d : gvertBearingY = %d \n", vertBearingX>> 6, vertBearingY>> 6); |
| printf("ghoriAdvance = %d : gvertAdvance = %d \n", horiAdvance>> 6, vertAdvance>> 6); |
| #endif /* DEBUG*/ |
| |
| XftUnlockFace(font); |
| |
| values[0] = (horiBearingX >> 6) + (horiBearingX & 0x3F)/64; // Glyph Precise Bounds : X |
| values[1] = (horiBearingY >> 6) + (horiBearingY & 0x3F)/64;// Glyph Precise Bounds : Y |
| values[2] = (horiAdvance >> 6) + (horiAdvance & 0x3F)/64; // Precise AdvanceX |
| values[3] = 0;//(vertAdvance >> 6) + (vertAdvance & 0x3F)/64; // Precise AdvanceY ?= Ascent+Descent |
| values[4] = (width >> 6) + (width & 0x3F)/64; // Glyph Precise Bounds : width |
| values[5] = (height >> 6) + (height & 0x3F)/64; // Glyph Precise Bounds : height |
| |
| results = (*env)->NewFloatArray(env, 6); |
| (*env)->SetFloatArrayRegion(env, results, 0, 6, values); |
| |
| return results; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getGlyphPxlInfoNative |
| * Signature: (JJC)[I |
| * Returns array of glyph metrics values in pixels for the specified character |
| * null is returned and NullPointerException is thrown in case of FreeType errors. |
| */ |
| JNIEXPORT jintArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getGlyphPxlInfoNative(JNIEnv *env, jclass obj, jlong display, jlong fnt, jchar chr){ |
| |
| Display * dpy = (Display *)(long)display; |
| jintArray metricsArr = NULL; |
| jint values[6]; |
| XftFont *font = (XftFont *)(long)fnt; |
| XGlyphInfo extents; |
| FT_Face face; |
| FT_BBox acbox; |
| FT_Glyph glyph; |
| FT_Error error; |
| |
| if (!font){ |
| return metricsArr; |
| } |
| face = XftLockFace(font); |
| |
| if (!face){ |
| return metricsArr; |
| } |
| error = FT_Load_Char(face, (FT_ULong)chr, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO); |
| |
| if(error){ |
| XftUnlockFace(font); |
| |
| return metricsArr; |
| } |
| |
| error = FT_Get_Glyph( face->glyph, &glyph ); |
| |
| if(error){ |
| throwNPException(env, "getGlyphPxlInfoNative 1 : FreeType error"); |
| XftUnlockFace(font); |
| |
| return metricsArr; |
| } |
| |
| FT_Glyph_Get_CBox(glyph, |
| 2, //FT_GLYPH_BBOX_PIXELS |
| &acbox); |
| FT_Done_Glyph(glyph); |
| XftUnlockFace(font); |
| |
| |
| XftTextExtents16 (dpy, |
| font, |
| &chr, |
| 1, |
| &extents); |
| #ifdef DEBUG |
| |
| printf("char = %d; y = %d; x = %d; height = %d; width = %d; advX = %d; advY = %d \n", |
| chr, extents.y, extents.x, extents.height, extents.width, extents.xOff, extents.yOff); |
| #endif // DEBUG |
| |
| values[0] = - extents.x ; // Glyph Pixels Bounds : X |
| values[1] = extents.y ; // Glyph Pixels Bounds : Y |
| values[2] = extents.xOff; // Pixels AdvanceX |
| values[3] = extents.yOff; // Pixels AdvanceY ?= Ascent+Descent |
| values[4] = acbox.xMax-acbox.xMin; // Glyph Pixels Bounds : width |
| values[5] = acbox.yMax-acbox.yMin; // Glyph Pixels Bounds : height |
| |
| metricsArr = (*env)->NewIntArray(env, 6); |
| (*env)->SetIntArrayRegion(env, metricsArr, 0, 6, values); |
| |
| return metricsArr; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getGlyphCodesNative |
| * Signature: (JLjava/lang/String;I)[I |
| * Returns glyphs code corresponding to the characters in String specified, null |
| * is returned if failure. NullPointerException is thrown in case of Display |
| * is null. |
| */ |
| JNIEXPORT jintArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getGlyphCodesNative(JNIEnv *env, jclass obj, jlong fnt, jstring str, jint len){ |
| |
| jintArray glyphsCodes = NULL; |
| |
| // TODO: implement method |
| |
| return glyphsCodes; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getGlyphCodeNative |
| * Signature: (JCJ)I |
| * Returns glyph code corresponding to the specified character, null is |
| * returned if failure. NullPointerException is thrown in case of Display is null. |
| */ |
| JNIEXPORT jint JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getGlyphCodeNative(JNIEnv *env, jclass obj, jlong fnt, jchar chr, jlong display){ |
| |
| jint code = 0xFFFF; |
| Display *dpy = (Display *)(long)display; |
| XftFont *font = (XftFont *)(long)fnt; |
| |
| if (!font){ |
| return 0xFFFF; |
| } |
| |
| code = XftCharIndex (dpy, font, chr); |
| |
| return (code == 0) ? 0xFFFF : code; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: RemoveFontResource |
| * Signature: (Ljava/lang/String;)I |
| * Description: Re-cache ~/.fonts directory, after temporary font-file is deleted. |
| */ |
| JNIEXPORT jint JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_RemoveFontResource(JNIEnv *env, jclass obj, jstring fName){ |
| |
| FcChar8* dirName; |
| jboolean iscopy; |
| FcConfig *config; |
| FcFontSet *set; |
| FcStrSet *subdirs; |
| FcStrList *list; |
| jboolean result = TRUE; |
| |
| /* get current congif */ |
| config = FcConfigGetCurrent(); |
| |
| if (!config){ |
| return FALSE; |
| } |
| |
| dirName = (FcChar8*)((*env)->GetStringUTFChars(env, fName, &iscopy)); |
| |
| list = FcConfigGetConfigDirs (config); |
| set = FcFontSetCreate (); |
| subdirs = FcStrSetCreate (); |
| |
| /* scan dir for changes */ |
| result = result && FcDirScan (set, subdirs, 0, FcConfigGetBlanks (config), dirName, FcFalse); |
| |
| /* save changes to the config */ |
| result = result && FcDirSave (set, subdirs, dirName); |
| |
| /* rebuild fonts list */ |
| FcConfigBuildFonts(config); |
| |
| FcFontSetDestroy (set); |
| FcStrSetDestroy (subdirs); |
| FcStrListDone (list); |
| |
| (*env)->ReleaseStringUTFChars(env, fName, (char *)dirName); |
| |
| return result; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: NativeInitGlyphBitmap |
| * Signature: (JC)J |
| * Returns pointer to FreeType FT_Bitmap that represents bitmap |
| * of the character specified or 0 if failures in native code. |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_NativeInitGlyphBitmap(JNIEnv *env, jclass jobj, jlong fnt, jchar chr){ |
| |
| XftFont *font = (XftFont *)(long)fnt; |
| FT_Glyph glyph; |
| FT_BitmapGlyph glyph_bitmap; |
| int size; |
| |
| FT_Error error; |
| FT_Face face; |
| FT_Bitmap ft_bitmap; |
| |
| if (!font){ |
| return 0; |
| } |
| face = XftLockFace(font); |
| |
| if (!face){ |
| return 0; |
| } |
| |
| error = FT_Load_Char(face, (FT_ULong)chr, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO); |
| |
| if(error){ |
| throwNPException(env, "NativeInitGlyphBitmap : FreeType error"); |
| |
| XftUnlockFace(font); |
| |
| return (jlong)(IDATA)NULL; |
| } |
| |
| error = FT_Get_Glyph( face->glyph, &glyph ); |
| |
| if(error){ |
| // throwNPException(env, "NativeInitGlyphBitmap 1 : FreeType error"); |
| XftUnlockFace(font); |
| |
| return (jlong)(IDATA)NULL; |
| } |
| // convert to a bitmap (default render mode + destroy old) |
| if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { |
| error = FT_Glyph_To_Bitmap( &glyph, (FT_LOAD_RENDER | FT_LOAD_TARGET_MONO), |
| 0, 1 ); |
| if ( error ){ |
| // glyph unchanged |
| FT_Done_Glyph( glyph ); |
| XftUnlockFace(font); |
| return (jlong)(IDATA)NULL; |
| } |
| } |
| |
| glyph_bitmap = (FT_BitmapGlyph)(glyph); |
| ft_bitmap = glyph_bitmap->bitmap; |
| |
| |
| GlyphBitmap *gbmp = (GlyphBitmap *)malloc(sizeof(GlyphBitmap)); |
| gbmp->left = glyph_bitmap->left; |
| gbmp->top = glyph_bitmap->top; |
| gbmp->bitmap.rows = ft_bitmap.rows; |
| gbmp->bitmap.width = ft_bitmap.width; |
| gbmp->bitmap.pitch = ft_bitmap.pitch; |
| gbmp->bitmap.buffer = malloc(ft_bitmap.rows * ft_bitmap.pitch); |
| size= ft_bitmap.rows * ft_bitmap.pitch; |
| memcpy(gbmp->bitmap.buffer, ft_bitmap.buffer, size); |
| |
| FT_Done_Glyph(glyph); |
| XftUnlockFace(font); |
| return (long)gbmp; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: NativeFreeGlyphBitmap |
| * Signature: (J)V |
| * Disposes GlyphBitmap memory block. |
| */ |
| JNIEXPORT void JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_NativeFreeGlyphBitmap(JNIEnv *env, jclass jobj, |
| jlong bitmap){ |
| GlyphBitmap *gbmp = (GlyphBitmap *)(long)bitmap; |
| free(gbmp->bitmap.buffer); |
| free(gbmp); |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: drawStringNative |
| * Signature: (JJJJII[CIJ)V |
| * Draws text on XftDraw with specified parameters. |
| */ |
| JNIEXPORT void |
| JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_drawStringNative |
| (JNIEnv *env, jclass jobj, jlong xftDraw, jlong display, |
| jlong colormap, jlong font, jint x, jint y, jcharArray str, jint len, jlong color){ |
| |
| jboolean iscopy; |
| |
| XftDraw *draw = (XftDraw *)(long)xftDraw; |
| Display *dpy = (Display *)(long)display; |
| Colormap cmap = (Colormap)colormap; |
| XftFont *fnt = (XftFont *)(long)font; |
| XftColor xftColor; |
| XRenderColor renderColor; |
| XftChar16 *string; |
| XColor *xcolor = (XColor *)(long)color; |
| |
| XftDrawSetSubwindowMode(draw, IncludeInferiors/*mode*/); |
| |
| string = (XftChar16 *)(*env)->GetCharArrayElements(env, str, &iscopy); |
| |
| /* Creating XRenderColor structure */ |
| renderColor.red = xcolor->red; |
| renderColor.green = xcolor->green; |
| renderColor.blue = xcolor->blue; |
| renderColor.alpha = 0xFFFF; |
| |
| /* Creating XftColor structure */ |
| if (XAllocColor (dpy, cmap, xcolor)){ |
| xftColor.pixel = xcolor->pixel; |
| } |
| xftColor.color.red = renderColor.red; |
| xftColor.color.green = renderColor.green; |
| xftColor.color.blue = renderColor.blue; |
| xftColor.color.alpha = renderColor.alpha; |
| |
| XftDrawString16 (draw, |
| &xftColor, |
| fnt, |
| x, |
| y, |
| string, |
| len); |
| |
| (*env)->ReleaseCharArrayElements(env, str, string, iscopy); |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: createXftDrawNative |
| * Signature: (JJJ)J |
| * Returns XftDraw handle created from specified parameters. |
| */ |
| JNIEXPORT jlong JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_createXftDrawNative |
| (JNIEnv *env, jclass jobj, jlong display, jlong drawable, jlong visual){ |
| |
| XftDraw *draw; |
| Display *dpy = (Display *)(long)display; |
| Drawable drwbl = (Drawable)drawable; |
| |
| /* Creating xftDraw structure */ |
| draw = XftDrawCreate (dpy, drwbl, (Visual *)(long)visual, 0); |
| |
| return (long)draw; |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: xftDrawSetSubwindowModeNative |
| * Signature: (JI)V |
| * Set new subwindow mode to XftDraw object. |
| */ |
| JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_xftDrawSetSubwindowModeNative |
| (JNIEnv *env, jclass jobj, jlong xftDraw, jint mode){ |
| |
| XftDraw *draw = (XftDraw *)(long)xftDraw; |
| |
| XftDrawSetSubwindowMode(draw, mode); |
| |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: XftDrawSetClipRectangles |
| * Signature: (JIIJI)Z |
| * Sets clipping rectangles in Xft drawable to the specified clipping rectangles. |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_XftDrawSetClipRectangles |
| (JNIEnv *env, jclass jobj, jlong xftDraw, jint xOrigin, jint yOrigin, jlong rects, jint n){ |
| |
| XftDraw *draw = (XftDraw *)(long)xftDraw; |
| XRectangle *xrects = (XRectangle *)(long)rects; |
| |
| return XftDrawSetClipRectangles (draw, xOrigin, yOrigin, xrects, n); |
| |
| } |
| |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: freeXftDrawNative |
| * Signature: (J)V |
| * Destroys XftDraw object. |
| */ |
| JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_freeXftDrawNative |
| (JNIEnv *env, jclass jobj, jlong xftDraw){ |
| |
| XftDraw *draw = (XftDraw *)(long)xftDraw; |
| |
| XftDrawDestroy(draw); |
| } |
| |
| /* Initializes FreeType FT_Outline structure with the source FT_Outline data. */ |
| int createOutline(FT_Outline *outline, FT_Outline *srcOutline){ |
| int size; |
| outline->flags = srcOutline->flags | FT_OUTLINE_OWNER; |
| outline->n_points = srcOutline->n_points; |
| outline->n_contours = srcOutline->n_contours; |
| |
| size = srcOutline->n_points * sizeof(FT_Vector); |
| outline->points = (FT_Vector *)malloc(size); |
| if (!outline->points){ |
| return 0; |
| } |
| memcpy(outline->points, srcOutline->points, size); |
| |
| size = srcOutline->n_points * sizeof(char); |
| outline->tags = (char *)malloc(size); |
| if (!outline->tags){ |
| free(outline->points); |
| return 0; |
| } |
| memcpy(outline->tags, srcOutline->tags, size); |
| |
| size = srcOutline->n_contours * sizeof(short); |
| outline->contours = (short *)malloc(size); |
| if (!outline->contours){ |
| free(outline->points); |
| free(outline->tags); |
| return 0; |
| } |
| memcpy(outline->contours, srcOutline->contours, size); |
| |
| return 1; |
| } |
| |
| /* Disposes FreeType FT_Outline structure. */ |
| void freeOutline(FT_Outline *outline){ |
| free(outline->points); |
| free(outline->tags); |
| free(outline->contours); |
| |
| free(outline); |
| } |
| |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: getGlyphOutline |
| * Signature: (JC)J |
| * Returns pointer to the FreeType FT_Outline structure. |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getGlyphOutline(JNIEnv *env, jclass obj, jlong fnt, jchar chr){ |
| |
| XftFont *font = (XftFont *)(long)fnt; |
| FT_Face face; |
| FT_Error error; |
| FT_Outline *outline = NULL; |
| |
| if (!font){ |
| return 0; |
| } |
| face = XftLockFace(font); |
| |
| if(!face){ |
| return 0; |
| } |
| error = FT_Load_Char(face, (FT_ULong)chr, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO); |
| |
| if(error){ |
| throwNPException(env, "getGlyphOutline : FreeType error"); |
| XftUnlockFace(font); |
| |
| return (jlong)(IDATA)NULL; |
| } |
| |
| if ((face->glyph->format & ft_glyph_format_outline) != 0){ |
| outline = (FT_Outline *)malloc(sizeof(FT_Outline)); |
| if (!createOutline(outline, &face->glyph->outline)){ |
| free(outline); |
| } |
| } |
| |
| XftUnlockFace(font); |
| |
| return (long)outline; |
| } |
| |
| /* |
| * Class: org_apache_harmony_awt_gl_font_LinuxNativeFont |
| * Method: freeGlyphOutline |
| * Signature: (JC)J |
| * Disposes FT_Outline memory block. |
| */ |
| JNIEXPORT void JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_freeGlyphOutline(JNIEnv *env, jclass obj, jlong j_outline){ |
| FT_Outline *outline = (FT_Outline *)(long)j_outline; |
| |
| freeOutline(outline); |
| } |
| |
| /* |
| * Returns desierd tag index from the list. |
| */ |
| int getTagIndex(Tag* tagList, int count, Tag value){ |
| int result = -1; |
| int i; |
| |
| for (i = 0; i < count; i++){ |
| if (* (DWORD *)tagList[i] == * (DWORD *)value){ |
| return result = i; |
| } |
| } |
| return result; |
| |
| } |
| |
| /* |
| * Returns an array of pairs of coordinates [x1, y1, x2, y2...] from |
| * FreeType FT_Vector structure. |
| */ |
| JNIEXPORT jfloatArray JNICALL Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getPointsFromFTVector |
| (JNIEnv *env, jclass obj, jlong points, jint size){ |
| |
| jfloatArray flArray; |
| float * fpPoints = (float *)malloc(sizeof(float) * size * 2); |
| int i; |
| FT_Vector *ft_points = (FT_Vector *)(long)points; |
| for(i = 0; i < size; i++){ |
| fpPoints[i*2] = (float)((int)ft_points[i].x + 32)/64; |
| fpPoints[i*2 + 1] = (float)(-(int)ft_points[i].y + 32)/64; |
| } |
| |
| flArray=(*env)->NewFloatArray(env, size*2); |
| (*env)->SetFloatArrayRegion(env, flArray, 0, size*2, fpPoints); |
| free(fpPoints); |
| return flArray; |
| } |
| |
| /* Returns an array of extrametrics of the font. */ |
| JNIEXPORT jfloatArray JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getExtraMetricsNative(JNIEnv *env, jclass obj, jlong fnt, jint fontHeight, jint fontType) { |
| |
| jfloatArray metrics; |
| jfloat values[9]; |
| |
| XftFont *xftFnt = (XftFont *)(long)fnt; |
| FT_Face face; |
| TT_OS2* os2; |
| #if HAS_FREETYPE_INTERNAL |
| TT_Face tt_face; |
| #endif |
| int units_per_EM; |
| float mltpl; |
| |
| if (!xftFnt){ |
| return NULL; |
| } |
| |
| face = XftLockFace(xftFnt); |
| |
| if(!face){ |
| return NULL; |
| } |
| units_per_EM = face->units_per_EM; |
| if (units_per_EM == 0){ |
| // throwNPException(env, "Units per EM value is equals to zero"); |
| XftUnlockFace(xftFnt); |
| |
| return NULL; |
| } |
| mltpl = (float)fontHeight / units_per_EM; |
| |
| if (fontType == FONT_TYPE_TT){ |
| #if HAS_FREETYPE_INTERNAL |
| tt_face = (TT_Face)face; |
| os2 = &(tt_face->os2); |
| #else |
| os2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
| #endif |
| |
| values[0] = (float)(os2->xAvgCharWidth) * mltpl; // the average width of characters in the font |
| values[1] = (float)(os2->ySubscriptXSize) * mltpl; // horizontal size for subscripts |
| values[2] = (float)(os2->ySubscriptYSize) * mltpl; // vertical size for subscripts |
| values[3] = (float)(os2->ySubscriptXOffset) * mltpl; // horizontal offset for subscripts |
| values[4] = (float)(os2->ySubscriptYOffset) * mltpl; // vertical offset value for subscripts |
| values[5] = (float)(os2->ySuperscriptXSize) * mltpl; // horizontal size for superscripts |
| values[6] = (float)(os2->ySuperscriptYSize) * mltpl; // vertical size for superscripts |
| values[7] = (float)(os2->ySuperscriptXOffset) * mltpl; // horizontal offset for superscripts |
| values[8] = (float)(os2->ySuperscriptYOffset) * mltpl; // vertical offset for superscripts |
| } else { |
| values[0] = 0.0f; // the average width of characters in the font |
| values[1] = 0.7f * fontHeight; // horizontal size for subscripts |
| values[2] = 0.65f * fontHeight;; // vertical size for subscripts |
| values[3] = 0.0f; // horizontal offset for subscripts |
| values[4] = 0.15f * fontHeight; // vertical offset value for subscripts |
| values[5] = 0.7f * fontHeight; // horizontal size for superscripts |
| values[6] = 0.65f * fontHeight; // vertical size for superscripts |
| values[7] = 0.0f; // horizontal offset for superscripts |
| values[8] = 0.45 * fontHeight; // vertical offset for superscripts |
| } |
| XftUnlockFace(xftFnt); |
| |
| metrics = (*env)->NewFloatArray(env, 9); |
| (*env)->SetFloatArrayRegion(env, metrics, 0, 9, values); |
| |
| return metrics; |
| |
| } |
| |
| /* |
| * Getting antialiased font from existing font |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_org_apache_harmony_awt_gl_font_LinuxNativeFont_getAntialiasedFont( |
| JNIEnv *env, jclass jobj, jlong font, jlong display, jboolean isAntialiasing){ |
| |
| XftFont *fnt = (XftFont *)(long)font; |
| Display *dpy = (Display *)(long)display; |
| |
| XftResult result; |
| XftPattern *mpattern = XftFontMatch(dpy, DefaultScreen(dpy),fnt->pattern,&result); |
| |
| XftPatternDel(mpattern, XFT_ANTIALIAS); |
| if (isAntialiasing) { |
| if (!XftPatternAddBool(mpattern, XFT_ANTIALIAS, True)) { |
| throwNPException(env, |
| "Error during adding font antialias set to true to XFTPattern structure"); |
| } |
| } |
| else { |
| if (!XftPatternAddBool(mpattern, XFT_ANTIALIAS, False)) { |
| throwNPException(env, |
| "Error during adding font antialias set to false to XFTPattern structure"); |
| } |
| } |
| |
| XftFont *aaFnt = XftFontOpenPattern(dpy, mpattern); |
| return (long)aaFnt; |
| } |