Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m
41152 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import "java_awt_Font.h"26#import "sun_awt_PlatformFont.h"27#import "sun_awt_FontDescriptor.h"28#import "sun_font_CFont.h"29#import "sun_font_CFontManager.h"3031#import "AWTFont.h"32#import "AWTStrike.h"33#import "CoreTextSupport.h"34#import "JNIUtilities.h"3536@implementation AWTFont3738- (id) initWithFont:(NSFont *)font {39self = [super init];40if (self) {41fFont = [font retain];42fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);43}44return self;45}4647- (void) dealloc {48[fFont release];49fFont = nil;5051if (fNativeCGFont) {52CGFontRelease(fNativeCGFont);53fNativeCGFont = NULL;54}5556[super dealloc];57}5859- (void) finalize {60if (fNativeCGFont) {61CGFontRelease(fNativeCGFont);62fNativeCGFont = NULL;63}64[super finalize];65}6667static NSString* uiName = nil;68static NSString* uiBoldName = nil;6970+ (AWTFont *) awtFontForName:(NSString *)name71style:(int)style72{73// create font with family & size74NSFont *nsFont = nil;7576if ((uiName != nil && [name isEqualTo:uiName]) ||77(uiBoldName != nil && [name isEqualTo:uiBoldName])) {78if (style & java_awt_Font_BOLD) {79nsFont = [NSFont boldSystemFontOfSize:1.0];80} else {81nsFont = [NSFont systemFontOfSize:1.0];82}83#ifdef DEBUG84NSLog(@"nsFont-name is : %@", nsFont.familyName);85NSLog(@"nsFont-family is : %@", nsFont.fontName);86NSLog(@"nsFont-desc-name is : %@", nsFont.fontDescriptor.postscriptName);87#endif888990} else {91nsFont = [NSFont fontWithName:name size:1.0];92}9394if (nsFont == nil) {95// if can't get font of that name, substitute system default font96nsFont = [NSFont fontWithName:@"Lucida Grande" size:1.0];97#ifdef DEBUG98NSLog(@"needed to substitute Lucida Grande for: %@", name);99#endif100}101102// create an italic style (if one is installed)103if (style & java_awt_Font_ITALIC) {104nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSItalicFontMask];105}106107// create a bold style (if one is installed)108if (style & java_awt_Font_BOLD) {109nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSBoldFontMask];110}111112return [[[AWTFont alloc] initWithFont:nsFont] autorelease];113}114115+ (NSFont *) nsFontForJavaFont:(jobject)javaFont env:(JNIEnv *)env {116if (javaFont == NULL) {117#ifdef DEBUG118NSLog(@"nil font");119#endif120return nil;121}122123DECLARE_CLASS_RETURN(jc_Font, "java/awt/Font", nil);124125// obtain the Font2D126DECLARE_METHOD_RETURN(jm_Font_getFont2D, jc_Font, "getFont2D", "()Lsun/font/Font2D;", nil);127jobject font2d = (*env)->CallObjectMethod(env, javaFont, jm_Font_getFont2D);128CHECK_EXCEPTION();129if (font2d == NULL) {130#ifdef DEBUG131NSLog(@"nil font2d");132#endif133return nil;134}135136// if it's not a CFont, it's likely one of TTF or OTF fonts137// from the Sun rendering loops138DECLARE_CLASS_RETURN(jc_CFont, "sun/font/CFont", nil);139if (!(*env)->IsInstanceOf(env, font2d, jc_CFont)) {140#ifdef DEBUG141NSLog(@"font2d !instanceof CFont");142#endif143return nil;144}145146DECLARE_METHOD_RETURN(jm_CFont_getFontStrike, jc_CFont, "getStrike", "(Ljava/awt/Font;)Lsun/font/FontStrike;", nil);147jobject fontStrike = (*env)->CallObjectMethod(env, font2d, jm_CFont_getFontStrike, javaFont);148CHECK_EXCEPTION();149DECLARE_CLASS_RETURN(jc_CStrike, "sun/font/CStrike", nil);150if (!(*env)->IsInstanceOf(env, fontStrike, jc_CStrike)) {151#ifdef DEBUG152NSLog(@"fontStrike !instanceof CStrike");153#endif154return nil;155}156157DECLARE_METHOD_RETURN(jm_CStrike_nativeStrikePtr, jc_CStrike, "getNativeStrikePtr", "()J", nil);158jlong awtStrikePtr = (*env)->CallLongMethod(env, fontStrike, jm_CStrike_nativeStrikePtr);159CHECK_EXCEPTION();160if (awtStrikePtr == 0L) {161#ifdef DEBUG162NSLog(@"nil nativeFontPtr from CFont");163#endif164return nil;165}166167AWTStrike *strike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);168169return [NSFont fontWithName:[strike->fAWTFont->fFont fontName] matrix:(CGFloat *)(&(strike->fAltTx))];170}171172@end173174175#pragma mark --- Font Discovery and Loading ---176177static NSArray* sFilteredFonts = nil;178static NSDictionary* sFontFamilyTable = nil;179180static NSString*181GetFamilyNameForFontName(NSString* fontname)182{183return [sFontFamilyTable objectForKey:fontname];184}185186static void addFont(CTFontUIFontType uiType,187NSMutableArray *allFonts,188NSMutableDictionary* fontFamilyTable) {189190CTFontRef font = CTFontCreateUIFontForLanguage(uiType, 0.0, NULL);191if (font == NULL) {192return;193}194CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);195if (desc == NULL) {196CFRelease(font);197return;198}199CFStringRef family = CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute);200if (family == NULL) {201CFRelease(desc);202CFRelease(font);203return;204}205CFStringRef name = CTFontDescriptorCopyAttribute(desc, kCTFontNameAttribute);206if (name == NULL) {207CFRelease(family);208CFRelease(desc);209CFRelease(font);210return;211}212if (uiType == kCTFontUIFontSystem) {213uiName = (NSString*)name;214}215if (uiType == kCTFontUIFontEmphasizedSystem) {216uiBoldName = (NSString*)name;217}218[allFonts addObject:name];219[fontFamilyTable setObject:family forKey:name];220#ifdef DEBUG221NSLog(@"name is : %@", (NSString*)name);222NSLog(@"family is : %@", (NSString*)family);223#endif224CFRelease(family);225CFRelease(name);226CFRelease(desc);227CFRelease(font);228}229230static NSArray*231GetFilteredFonts()232{233if (sFilteredFonts == nil) {234NSFontManager *fontManager = [NSFontManager sharedFontManager];235NSUInteger fontCount = [[fontManager availableFonts] count];236237NSMutableArray *allFonts = [[NSMutableArray alloc] initWithCapacity:fontCount];238NSMutableDictionary* fontFamilyTable = [[NSMutableDictionary alloc] initWithCapacity:fontCount];239NSArray *allFamilies = [fontManager availableFontFamilies];240241NSUInteger familyCount = [allFamilies count];242243NSUInteger familyIndex;244for (familyIndex = 0; familyIndex < familyCount; familyIndex++) {245NSString *family = [allFamilies objectAtIndex:familyIndex];246247if ((family == nil) || [family characterAtIndex:0] == '.') {248continue;249}250251NSArray *fontFaces = [fontManager availableMembersOfFontFamily:family];252NSUInteger faceCount = [fontFaces count];253254NSUInteger faceIndex;255for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {256NSString* face = [[fontFaces objectAtIndex:faceIndex] objectAtIndex:0];257if (face != nil) {258[allFonts addObject:face];259[fontFamilyTable setObject:family forKey:face];260}261}262}263264/*265* JavaFX registers these fonts and so JDK needs to do so as well.266* If this isn't done we will have mis-matched rendering, since267* although these may include fonts that are enumerated normally268* they also demonstrably includes fonts that are not.269*/270addFont(kCTFontUIFontSystem, allFonts, fontFamilyTable);271addFont(kCTFontUIFontEmphasizedSystem, allFonts, fontFamilyTable);272273sFilteredFonts = allFonts;274sFontFamilyTable = fontFamilyTable;275}276277return sFilteredFonts;278}279280#pragma mark --- sun.font.CFontManager JNI ---281282static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath)283{284return FSPathMakeRef((UInt8 *)[inPath fileSystemRepresentation],285myFSRefPtr, NULL);286}287288/*289* Class: sun_font_CFontManager290* Method: loadNativeFonts291* Signature: ()V292*/293JNIEXPORT void JNICALL294Java_sun_font_CFontManager_loadNativeFonts295(JNIEnv *env, jobject jthis)296{297DECLARE_CLASS(jc_CFontManager, "sun/font/CFontManager");298DECLARE_METHOD(jm_registerFont, jc_CFontManager, "registerFont", "(Ljava/lang/String;Ljava/lang/String;)V");299300jint num = 0;301302JNI_COCOA_ENTER(env);303304NSArray *filteredFonts = GetFilteredFonts();305num = (jint)[filteredFonts count];306307jint i;308for (i = 0; i < num; i++) {309NSString *fontname = [filteredFonts objectAtIndex:i];310jobject jFontName = NSStringToJavaString(env, fontname);311jobject jFontFamilyName =312NSStringToJavaString(env, GetFamilyNameForFontName(fontname));313314(*env)->CallVoidMethod(env, jthis, jm_registerFont, jFontName, jFontFamilyName);315CHECK_EXCEPTION();316(*env)->DeleteLocalRef(env, jFontName);317(*env)->DeleteLocalRef(env, jFontFamilyName);318}319320JNI_COCOA_EXIT(env);321}322323/*324* Class: Java_sun_font_CFontManager_loadNativeDirFonts325* Method: loadNativeDirFonts326* Signature: (Ljava/lang/String;)V;327*/328JNIEXPORT void JNICALL329Java_sun_font_CFontManager_loadNativeDirFonts330(JNIEnv *env, jclass clz, jstring filename)331{332JNI_COCOA_ENTER(env);333334NSString *path = JavaStringToNSString(env, filename);335NSURL *url = [NSURL fileURLWithPath:(NSString *)path];336bool res = CTFontManagerRegisterFontsForURL((CFURLRef)url, kCTFontManagerScopeProcess, nil);337#ifdef DEBUG338NSLog(@"path is : %@", (NSString*)path);339NSLog(@"url is : %@", (NSString*)url);340printf("res is %d\n", res);341#endif342JNI_COCOA_EXIT(env);343}344345#pragma mark --- sun.font.CFont JNI ---346347/*348* Class: sun_font_CFont349* Method: getPlatformFontPtrNative350* Signature: (JI)[B351*/352JNIEXPORT jlong JNICALL353Java_sun_font_CFont_getCGFontPtrNative354(JNIEnv *env, jclass clazz,355jlong awtFontPtr)356{357AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);358return (jlong)(awtFont->fNativeCGFont);359}360361/*362* Class: sun_font_CFont363* Method: getTableBytesNative364* Signature: (JI)[B365*/366JNIEXPORT jbyteArray JNICALL367Java_sun_font_CFont_getTableBytesNative368(JNIEnv *env, jclass clazz,369jlong awtFontPtr, jint jtag)370{371jbyteArray jbytes = NULL;372JNI_COCOA_ENTER(env);373374CTFontTableTag tag = (CTFontTableTag)jtag;375int i, found = 0;376AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);377NSFont* nsFont = awtFont->fFont;378CTFontRef ctfont = (CTFontRef)nsFont;379CFArrayRef tagsArray =380CTFontCopyAvailableTables(ctfont, kCTFontTableOptionNoOptions);381CFIndex numTags = CFArrayGetCount(tagsArray);382for (i=0; i<numTags; i++) {383if (tag ==384(CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tagsArray, i)) {385found = 1;386break;387}388}389CFRelease(tagsArray);390if (!found) {391return NULL;392}393CFDataRef table = CTFontCopyTable(ctfont, tag, kCTFontTableOptionNoOptions);394if (table == NULL) {395return NULL;396}397398char *tableBytes = (char*)(CFDataGetBytePtr(table));399size_t tableLength = CFDataGetLength(table);400if (tableBytes == NULL || tableLength == 0) {401CFRelease(table);402return NULL;403}404405jbytes = (*env)->NewByteArray(env, (jsize)tableLength);406if (jbytes == NULL) {407return NULL;408}409(*env)->SetByteArrayRegion(env, jbytes, 0,410(jsize)tableLength,411(jbyte*)tableBytes);412CFRelease(table);413414JNI_COCOA_EXIT(env);415416return jbytes;417}418419/*420* Class: sun_font_CFont421* Method: initNativeFont422* Signature: (Ljava/lang/String;I)J423*/424JNIEXPORT jlong JNICALL425Java_sun_font_CFont_createNativeFont426(JNIEnv *env, jclass clazz,427jstring nativeFontName, jint style)428{429AWTFont *awtFont = nil;430431JNI_COCOA_ENTER(env);432433awtFont =434[AWTFont awtFontForName:JavaStringToNSString(env, nativeFontName)435style:style]; // autoreleased436437if (awtFont) {438CFRetain(awtFont); // GC439}440441JNI_COCOA_EXIT(env);442443return ptr_to_jlong(awtFont);444}445446/*447* Class: sun_font_CFont448* Method: getWidthNative449* Signature: (J)F450*/451JNIEXPORT jfloat JNICALL452Java_sun_font_CFont_getWidthNative453(JNIEnv *env, jobject cfont, jlong awtFontPtr)454{455float widthVal;456JNI_COCOA_ENTER(env);457458AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);459NSFont* nsFont = awtFont->fFont;460NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;461NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];462NSNumber *width = [fontTraits objectForKey : NSFontWidthTrait];463widthVal = (float)[width floatValue];464465JNI_COCOA_EXIT(env);466return (jfloat)widthVal;467}468469/*470* Class: sun_font_CFont471* Method: getWeightNative472* Signature: (J)F473*/474JNIEXPORT jfloat JNICALL475Java_sun_font_CFont_getWeightNative476(JNIEnv *env, jobject cfont, jlong awtFontPtr)477{478float weightVal;479JNI_COCOA_ENTER(env);480481AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);482NSFont* nsFont = awtFont->fFont;483NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;484NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];485NSNumber *weight = [fontTraits objectForKey : NSFontWeightTrait];486weightVal = (float)[weight floatValue];487488JNI_COCOA_EXIT(env);489return (jfloat)weightVal;490}491492/*493* Class: sun_font_CFont494* Method: disposeNativeFont495* Signature: (J)V496*/497JNIEXPORT void JNICALL498Java_sun_font_CFont_disposeNativeFont499(JNIEnv *env, jclass clazz, jlong awtFontPtr)500{501JNI_COCOA_ENTER(env);502503if (awtFontPtr) {504CFRelease((AWTFont *)jlong_to_ptr(awtFontPtr)); // GC505}506507JNI_COCOA_EXIT(env);508}509510511#pragma mark --- Miscellaneous JNI ---512513#ifndef HEADLESS514/*515* Class: sun_awt_PlatformFont516* Method: initIDs517* Signature: ()V518*/519JNIEXPORT void JNICALL520Java_sun_awt_PlatformFont_initIDs521(JNIEnv *env, jclass cls)522{523}524525/*526* Class: sun_awt_FontDescriptor527* Method: initIDs528* Signature: ()V529*/530JNIEXPORT void JNICALL531Java_sun_awt_FontDescriptor_initIDs532(JNIEnv *env, jclass cls)533{534}535#endif536537/*538* Class: sun_awt_FontDescriptor539* Method: initIDs540* Signature: ()V541*/542JNIEXPORT void JNICALL543Java_sun_font_CFont_getCascadeList544(JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)545{546JNI_COCOA_ENTER(env);547jclass alc = (*env)->FindClass(env, "java/util/ArrayList");548if (alc == NULL) return;549jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");550if (addMID == NULL) return;551552CFIndex i;553AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);554NSFont* nsFont = awtFont->fFont;555CTFontRef font = (CTFontRef)nsFont;556CFArrayRef codes = CFLocaleCopyISOLanguageCodes();557558#ifdef DEBUG559CFStringRef base = CTFontCopyFullName(font);560NSLog(@"BaseFont is : %@", (NSString*)base);561CFRelease(base);562#endif563CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);564CFRelease(codes);565CFIndex cnt = CFArrayGetCount(fds);566for (i=0; i<cnt; i++) {567CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);568CFStringRef fontname =569CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);570#ifdef DEBUG571NSLog(@"Font is : %@", (NSString*)fontname);572#endif573jstring jFontName = (jstring)NSStringToJavaString(env, fontname);574CFRelease(fontname);575(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);576if ((*env)->ExceptionOccurred(env)) {577CFRelease(fds);578return;579}580(*env)->DeleteLocalRef(env, jFontName);581}582CFRelease(fds);583JNI_COCOA_EXIT(env);584}585586static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");587588bool IsEmojiFont(CTFontRef font)589{590CFStringRef name = CTFontCopyFullName(font);591if (name == NULL) return false;592bool isFixedColor = CFStringCompare(name, EMOJI_FONT_NAME, 0) == kCFCompareEqualTo;593CFRelease(name);594return isFixedColor;595}596597598