Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/macosx/native/sun/font/AWTFont.m
83405 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 <JavaNativeFoundation/JavaNativeFoundation.h>2627#import "java_awt_Font.h"28#import "sun_awt_PlatformFont.h"29#import "sun_awt_FontDescriptor.h"30#import "sun_font_CFont.h"31#import "sun_font_CFontManager.h"3233#import "AWTFont.h"34#import "AWTStrike.h"35#import "CoreTextSupport.h"3637@implementation AWTFont3839- (id) initWithFont:(NSFont *)font {40self = [super init];41if (self) {42fFont = [font retain];43fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);44layoutTableCache = NULL;45}46return self;47}4849static TTLayoutTableCache* newCFontLayoutTableCache() {50TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));51if (ltc) {52int i;53for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {54ltc->entries[i].len = -1;55}56}57return ltc;58}5960static void freeCFontLayoutTableCache(TTLayoutTableCache* ltc) {61if (ltc) {62int i;63for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {64if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);65}66if (ltc->kernPairs) free(ltc->kernPairs);67free(ltc);68}69}7071- (void) dealloc {72[fFont release];73fFont = nil;7475if (fNativeCGFont) {76CGFontRelease(fNativeCGFont);77fNativeCGFont = NULL;78if (layoutTableCache != NULL) {79freeCFontLayoutTableCache(layoutTableCache);80layoutTableCache = NULL;81}82}8384[super dealloc];85}8687- (void) finalize {88if (fNativeCGFont) {89CGFontRelease(fNativeCGFont);90fNativeCGFont = NULL;91}92if (layoutTableCache != NULL) {93freeCFontLayoutTableCache(layoutTableCache);94layoutTableCache = NULL;95}96[super finalize];97}9899static NSString* uiName = nil;100static NSString* uiBoldName = nil;101102+ (AWTFont *) awtFontForName:(NSString *)name103style:(int)style104{105// create font with family & size106NSFont *nsFont = nil;107108if ((uiName != nil && [name isEqualTo:uiName]) ||109(uiBoldName != nil && [name isEqualTo:uiBoldName])) {110if (style & java_awt_Font_BOLD) {111nsFont = [NSFont boldSystemFontOfSize:1.0];112} else {113nsFont = [NSFont systemFontOfSize:1.0];114}115#ifdef DEBUG116NSLog(@"nsFont-name is : %@", nsFont.familyName);117NSLog(@"nsFont-family is : %@", nsFont.fontName);118NSLog(@"nsFont-desc-name is : %@", nsFont.fontDescriptor.postscriptName);119#endif120121122} else {123nsFont = [NSFont fontWithName:name size:1.0];124}125126if (nsFont == nil) {127// if can't get font of that name, substitute system default font128nsFont = [NSFont fontWithName:@"Lucida Grande" size:1.0];129#ifdef DEBUG130NSLog(@"needed to substitute Lucida Grande for: %@", name);131#endif132}133134// create an italic style (if one is installed)135if (style & java_awt_Font_ITALIC) {136nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSItalicFontMask];137}138139// create a bold style (if one is installed)140if (style & java_awt_Font_BOLD) {141nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSBoldFontMask];142}143144return [[[AWTFont alloc] initWithFont:nsFont] autorelease];145}146147+ (NSFont *) nsFontForJavaFont:(jobject)javaFont env:(JNIEnv *)env {148if (javaFont == NULL) {149#ifdef DEBUG150NSLog(@"nil font");151#endif152return nil;153}154155static JNF_CLASS_CACHE(jc_Font, "java/awt/Font");156157// obtain the Font2D158static JNF_MEMBER_CACHE(jm_Font_getFont2D, jc_Font, "getFont2D", "()Lsun/font/Font2D;");159jobject font2d = JNFCallObjectMethod(env, javaFont, jm_Font_getFont2D);160if (font2d == NULL) {161#ifdef DEBUG162NSLog(@"nil font2d");163#endif164return nil;165}166167// if it's not a CFont, it's likely one of TTF or OTF fonts168// from the Sun rendering loops169static JNF_CLASS_CACHE(jc_CFont, "sun/font/CFont");170if (!JNFIsInstanceOf(env, font2d, &jc_CFont)) {171#ifdef DEBUG172NSLog(@"font2d !instanceof CFont");173#endif174return nil;175}176177static JNF_MEMBER_CACHE(jm_CFont_getFontStrike, jc_CFont, "getStrike", "(Ljava/awt/Font;)Lsun/font/FontStrike;");178jobject fontStrike = JNFCallObjectMethod(env, font2d, jm_CFont_getFontStrike, javaFont);179180static JNF_CLASS_CACHE(jc_CStrike, "sun/font/CStrike");181if (!JNFIsInstanceOf(env, fontStrike, &jc_CStrike)) {182#ifdef DEBUG183NSLog(@"fontStrike !instanceof CStrike");184#endif185return nil;186}187188static JNF_MEMBER_CACHE(jm_CStrike_nativeStrikePtr, jc_CStrike, "getNativeStrikePtr", "()J");189jlong awtStrikePtr = JNFCallLongMethod(env, fontStrike, jm_CStrike_nativeStrikePtr);190if (awtStrikePtr == 0L) {191#ifdef DEBUG192NSLog(@"nil nativeFontPtr from CFont");193#endif194return nil;195}196197AWTStrike *strike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);198199return [NSFont fontWithName:[strike->fAWTFont->fFont fontName] matrix:(CGFloat *)(&(strike->fAltTx))];200}201202@end203204205#pragma mark --- Font Discovery and Loading ---206207static NSArray* sFilteredFonts = nil;208static NSDictionary* sFontFamilyTable = nil;209210static NSString*211GetFamilyNameForFontName(NSString* fontname)212{213return [sFontFamilyTable objectForKey:fontname];214}215216static void addFont(CTFontUIFontType uiType,217NSMutableArray *allFonts,218NSMutableDictionary* fontFamilyTable) {219220CTFontRef font = CTFontCreateUIFontForLanguage(uiType, 0.0, NULL);221if (font == NULL) {222return;223}224CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);225if (desc == NULL) {226CFRelease(font);227return;228}229CFStringRef family = CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute);230if (family == NULL) {231CFRelease(desc);232CFRelease(font);233return;234}235CFStringRef name = CTFontDescriptorCopyAttribute(desc, kCTFontNameAttribute);236if (name == NULL) {237CFRelease(family);238CFRelease(desc);239CFRelease(font);240return;241}242if (uiType == kCTFontUIFontSystem) {243uiName = (NSString*)name;244}245if (uiType == kCTFontUIFontEmphasizedSystem) {246uiBoldName = (NSString*)name;247}248[allFonts addObject:name];249[fontFamilyTable setObject:family forKey:name];250#ifdef DEBUG251NSLog(@"name is : %@", (NSString*)name);252NSLog(@"family is : %@", (NSString*)family);253#endif254CFRelease(family);255CFRelease(name);256CFRelease(desc);257CFRelease(font);258}259260static NSArray*261GetFilteredFonts()262{263if (sFilteredFonts == nil) {264NSFontManager *fontManager = [NSFontManager sharedFontManager];265NSUInteger fontCount = [[fontManager availableFonts] count];266267NSMutableArray *allFonts = [[NSMutableArray alloc] initWithCapacity:fontCount];268NSMutableDictionary* fontFamilyTable = [[NSMutableDictionary alloc] initWithCapacity:fontCount];269NSArray *allFamilies = [fontManager availableFontFamilies];270271NSUInteger familyCount = [allFamilies count];272273NSUInteger familyIndex;274for (familyIndex = 0; familyIndex < familyCount; familyIndex++) {275NSString *family = [allFamilies objectAtIndex:familyIndex];276277if ((family == nil) || [family characterAtIndex:0] == '.') {278continue;279}280281NSArray *fontFaces = [fontManager availableMembersOfFontFamily:family];282NSUInteger faceCount = [fontFaces count];283284NSUInteger faceIndex;285for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {286NSString* face = [[fontFaces objectAtIndex:faceIndex] objectAtIndex:0];287if (face != nil) {288[allFonts addObject:face];289[fontFamilyTable setObject:family forKey:face];290}291}292}293294/*295* JavaFX registers these fonts and so JDK needs to do so as well.296* If this isn't done we will have mis-matched rendering, since297* although these may include fonts that are enumerated normally298* they also demonstrably includes fonts that are not.299*/300addFont(kCTFontUIFontSystem, allFonts, fontFamilyTable);301addFont(kCTFontUIFontEmphasizedSystem, allFonts, fontFamilyTable);302303sFilteredFonts = allFonts;304sFontFamilyTable = fontFamilyTable;305}306307return sFilteredFonts;308}309310#pragma mark --- sun.font.CFontManager JNI ---311312static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath)313{314return FSPathMakeRef((UInt8 *)[inPath fileSystemRepresentation],315myFSRefPtr, NULL);316}317318// /*319// * Class: sun_font_CFontManager320// * Method: loadFileFont321// * Signature: (Ljava/lang/String;)Lsun/font/Font2D;322// */323// JNIEXPORT /* sun.font.CFont */ jobject JNICALL324// Java_sun_font_CFontManager_loadFileFont325// (JNIEnv *env, jclass obj, jstring fontpath)326// {327// jobject result = NULL;328//329// JNF_COCOA_ENTER(env);330//331// NSString *nsFilePath = JNFJavaToNSString(env, fontpath);332// jstring javaFontName = NULL;333//334// //335// // Note: This API uses ATS and can therefore return Carbon error codes.336// // These codes can be found at:337// // http://developer.apple.com/techpubs/macosx/Carbon/Files/FileManager/File_Manager/ResultCodes/ResultCodes.html338// //339//340// FSRef iFile;341// OSStatus status = CreateFSRef(&iFile, nsFilePath);342//343// if (status == noErr) {344// ATSFontContainerRef oContainer;345// status = ATSFontActivateFromFileReference(&iFile, kATSFontContextLocal,346// kATSFontFormatUnspecified,347// NULL,348// kATSOptionFlagsUseDataFork,349// &oContainer);350// if (status == noErr) {351// ATSFontRef ioArray[1];352// ItemCount oCount;353// status = ATSFontFindFromContainer(oContainer,354// kATSOptionFlagsUseDataFork,355// 1, ioArray, &oCount);356//357// if (status == noErr) {358// CFStringRef oName;359// status = ATSFontGetPostScriptName(ioArray[0],360// kATSOptionFlagsUseDataFork,361// &oName);362// if (status == noErr) {363// javaFontName = JNFNSToJavaString(env, (NSString *)oName);364// CFRelease(oName);365// }366// }367// }368// }369//370// if (javaFontName != NULL) {371// // create the CFont!372// static JNF_CLASS_CACHE(sjc_CFont, "sun/font/CFont");373// static JNF_CTOR_CACHE(sjf_CFont_ctor,374// sjc_CFont, "(Ljava/lang/String;)V");375// result = JNFNewObject(env, sjf_CFont_ctor, javaFontName);376// }377//378// JNF_COCOA_EXIT(env);379//380// return result;381// }382383/*384* Class: sun_font_CFontManager385* Method: loadNativeFonts386* Signature: ()V387*/388JNIEXPORT void JNICALL389Java_sun_font_CFontManager_loadNativeFonts390(JNIEnv *env, jobject jthis)391{392static JNF_CLASS_CACHE(jc_CFontManager,393"sun/font/CFontManager");394static JNF_MEMBER_CACHE(jm_registerFont, jc_CFontManager,395"registerFont",396"(Ljava/lang/String;Ljava/lang/String;)V");397398jint num = 0;399400JNF_COCOA_ENTER(env);401402NSArray *filteredFonts = GetFilteredFonts();403num = (jint)[filteredFonts count];404405jint i;406for (i = 0; i < num; i++) {407NSString *fontname = [filteredFonts objectAtIndex:i];408jobject jFontName = JNFNSToJavaString(env, fontname);409jobject jFontFamilyName =410JNFNSToJavaString(env, GetFamilyNameForFontName(fontname));411412JNFCallVoidMethod(env, jthis,413jm_registerFont, jFontName, jFontFamilyName);414}415416JNF_COCOA_EXIT(env);417}418419/*420* Class: Java_sun_font_CFontManager_loadNativeDirFonts421* Method: loadNativeDirFonts422* Signature: (Ljava/lang/String;)V;423*/424JNIEXPORT void JNICALL425Java_sun_font_CFontManager_loadNativeDirFonts426(JNIEnv *env, jclass clz, jstring filename)427{428JNF_COCOA_ENTER(env);429430NSString *nsFilePath = JNFJavaToNSString(env, filename);431432FSRef iFile;433OSStatus status = CreateFSRef(&iFile, nsFilePath);434435if (status == noErr) {436ATSFontContainerRef oContainer;437status = ATSFontActivateFromFileReference(&iFile, kATSFontContextLocal,438kATSFontFormatUnspecified,439NULL, kNilOptions,440&oContainer);441}442443JNF_COCOA_EXIT(env);444}445446#pragma mark --- sun.font.CFont JNI ---447448/*449* Class: sun_font_CFont450* Method: getPlatformFontPtrNative451* Signature: (JI)[B452*/453JNIEXPORT jlong JNICALL454Java_sun_font_CFont_getCGFontPtrNative455(JNIEnv *env, jclass clazz,456jlong awtFontPtr)457{458AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);459return (jlong)(awtFont->fNativeCGFont);460}461462/*463* Class: sun_font_CFont464* Method: getLayoutTableCacheNative465* Signature: (J)J466*/467JNIEXPORT jlong JNICALL468Java_sun_font_CFont_getLayoutTableCacheNative469(JNIEnv *env, jclass clazz,470jlong awtFontPtr)471{472AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);473if (awtFont->layoutTableCache == NULL) {474awtFont->layoutTableCache = newCFontLayoutTableCache();475}476return (jlong)(awtFont->layoutTableCache);477}478479/*480* Class: sun_font_CFont481* Method: getTableBytesNative482* Signature: (JI)[B483*/484JNIEXPORT jbyteArray JNICALL485Java_sun_font_CFont_getTableBytesNative486(JNIEnv *env, jclass clazz,487jlong awtFontPtr, jint jtag)488{489jbyteArray jbytes = NULL;490JNF_COCOA_ENTER(env);491492CTFontTableTag tag = (CTFontTableTag)jtag;493int i, found = 0;494AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);495NSFont* nsFont = awtFont->fFont;496CTFontRef ctfont = (CTFontRef)nsFont;497CFArrayRef tagsArray =498CTFontCopyAvailableTables(ctfont, kCTFontTableOptionNoOptions);499CFIndex numTags = CFArrayGetCount(tagsArray);500for (i=0; i<numTags; i++) {501if (tag ==502(CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tagsArray, i)) {503found = 1;504break;505}506}507CFRelease(tagsArray);508if (!found) {509return NULL;510}511CFDataRef table = CTFontCopyTable(ctfont, tag, kCTFontTableOptionNoOptions);512if (table == NULL) {513return NULL;514}515516char *tableBytes = (char*)(CFDataGetBytePtr(table));517size_t tableLength = CFDataGetLength(table);518if (tableBytes == NULL || tableLength == 0) {519CFRelease(table);520return NULL;521}522523jbytes = (*env)->NewByteArray(env, (jsize)tableLength);524if (jbytes == NULL) {525return NULL;526}527(*env)->SetByteArrayRegion(env, jbytes, 0,528(jsize)tableLength,529(jbyte*)tableBytes);530CFRelease(table);531532JNF_COCOA_EXIT(env);533534return jbytes;535}536537/*538* Class: sun_font_CFont539* Method: initNativeFont540* Signature: (Ljava/lang/String;I)J541*/542JNIEXPORT jlong JNICALL543Java_sun_font_CFont_createNativeFont544(JNIEnv *env, jclass clazz,545jstring nativeFontName, jint style)546{547AWTFont *awtFont = nil;548549JNF_COCOA_ENTER(env);550551awtFont =552[AWTFont awtFontForName:JNFJavaToNSString(env, nativeFontName)553style:style]; // autoreleased554555if (awtFont) {556CFRetain(awtFont); // GC557}558559JNF_COCOA_EXIT(env);560561return ptr_to_jlong(awtFont);562}563564/*565* Class: sun_font_CFont566* Method: getWidthNative567* Signature: (J)F568*/569JNIEXPORT jfloat JNICALL570Java_sun_font_CFont_getWidthNative571(JNIEnv *env, jobject cfont, jlong awtFontPtr)572{573float widthVal;574JNF_COCOA_ENTER(env);575576AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);577NSFont* nsFont = awtFont->fFont;578NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;579NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];580NSNumber *width = [fontTraits objectForKey : NSFontWidthTrait];581widthVal = (float)[width floatValue];582583JNF_COCOA_EXIT(env);584return (jfloat)widthVal;585}586587/*588* Class: sun_font_CFont589* Method: getWeightNative590* Signature: (J)F591*/592JNIEXPORT jfloat JNICALL593Java_sun_font_CFont_getWeightNative594(JNIEnv *env, jobject cfont, jlong awtFontPtr)595{596float weightVal;597JNF_COCOA_ENTER(env);598599AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);600NSFont* nsFont = awtFont->fFont;601NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;602NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];603NSNumber *weight = [fontTraits objectForKey : NSFontWeightTrait];604weightVal = (float)[weight floatValue];605606JNF_COCOA_EXIT(env);607return (jfloat)weightVal;608}609610/*611* Class: sun_font_CFont612* Method: disposeNativeFont613* Signature: (J)V614*/615JNIEXPORT void JNICALL616Java_sun_font_CFont_disposeNativeFont617(JNIEnv *env, jclass clazz, jlong awtFontPtr)618{619JNF_COCOA_ENTER(env);620621if (awtFontPtr) {622CFRelease((AWTFont *)jlong_to_ptr(awtFontPtr)); // GC623}624625JNF_COCOA_EXIT(env);626}627628629#pragma mark --- Miscellaneous JNI ---630631#ifndef HEADLESS632/*633* Class: sun_awt_PlatformFont634* Method: initIDs635* Signature: ()V636*/637JNIEXPORT void JNICALL638Java_sun_awt_PlatformFont_initIDs639(JNIEnv *env, jclass cls)640{641}642643/*644* Class: sun_awt_FontDescriptor645* Method: initIDs646* Signature: ()V647*/648JNIEXPORT void JNICALL649Java_sun_awt_FontDescriptor_initIDs650(JNIEnv *env, jclass cls)651{652}653#endif654655/*656* Class: sun_awt_FontDescriptor657* Method: initIDs658* Signature: ()V659*/660JNIEXPORT void JNICALL661Java_sun_font_CFont_getCascadeList662(JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)663{664jclass alc = (*env)->FindClass(env, "java/util/ArrayList");665if (alc == NULL) return;666jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");667if (addMID == NULL) return;668669CFIndex i;670AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);671NSFont* nsFont = awtFont->fFont;672CTFontRef font = (CTFontRef)nsFont;673CFStringRef base = CTFontCopyFullName(font);674CFArrayRef codes = CFLocaleCopyISOLanguageCodes();675676#ifdef DEBUG677NSLog(@"BaseFont is : %@", (NSString*)base);678#endif679CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);680CFIndex cnt = CFArrayGetCount(fds);681for (i=0; i<cnt; i++) {682CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);683CFStringRef fontname =684CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);685#ifdef DEBUG686NSLog(@"Font is : %@", (NSString*)fontname);687#endif688jstring jFontName = (jstring)JNFNSToJavaString(env, fontname);689(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);690(*env)->DeleteLocalRef(env, jFontName);691}692}693694695