1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  27 
  28 #import "java_awt_Font.h"
  29 #import "sun_awt_PlatformFont.h"
  30 #import "sun_awt_FontDescriptor.h"
  31 #import "sun_font_CFont.h"
  32 #import "sun_font_CFontManager.h"
  33 
  34 #import "AWTFont.h"
  35 #import "AWTStrike.h"
  36 #import "CoreTextSupport.h"
  37 
  38 @implementation AWTFont
  39 
  40 - (id) initWithFont:(NSFont *)font {
  41     self = [super init];
  42     if (self) {
  43         fFont = [font retain];
  44         fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);
  45     }
  46     return self;
  47 }
  48 
  49 - (void) dealloc {
  50     [fFont release];
  51     fFont = nil;
  52 
  53     if (fNativeCGFont) {
  54         CGFontRelease(fNativeCGFont);
  55     fNativeCGFont = NULL;
  56     }
  57 
  58     [super dealloc];
  59 }
  60 
  61 - (void) finalize {
  62     if (fNativeCGFont) {
  63         CGFontRelease(fNativeCGFont);
  64     fNativeCGFont = NULL;
  65     }
  66     [super finalize];
  67 }
  68 
  69 static NSString* uiName = nil;
  70 static NSString* uiBoldName = nil;
  71 
  72 + (AWTFont *) awtFontForName:(NSString *)name
  73                        style:(int)style
  74 {
  75     // create font with family & size
  76     NSFont *nsFont = nil;
  77 
  78     if ((uiName != nil && [name isEqualTo:uiName]) ||
  79         (uiBoldName != nil && [name isEqualTo:uiBoldName])) {
  80         if (style & java_awt_Font_BOLD) {
  81             nsFont = [NSFont boldSystemFontOfSize:1.0];
  82         } else {
  83             nsFont = [NSFont systemFontOfSize:1.0];
  84         }
  85 #ifdef DEBUG
  86         NSLog(@"nsFont-name is : %@", nsFont.familyName);
  87         NSLog(@"nsFont-family is : %@", nsFont.fontName);
  88         NSLog(@"nsFont-desc-name is : %@", nsFont.fontDescriptor.postscriptName);
  89 #endif
  90 
  91 
  92     } else {
  93            nsFont = [NSFont fontWithName:name size:1.0];
  94     }
  95 
  96     if (nsFont == nil) {
  97         // if can't get font of that name, substitute system default font
  98         nsFont = [NSFont fontWithName:@"Lucida Grande" size:1.0];
  99 #ifdef DEBUG
 100         NSLog(@"needed to substitute Lucida Grande for: %@", name);
 101 #endif
 102     }
 103 
 104     // create an italic style (if one is installed)
 105     if (style & java_awt_Font_ITALIC) {
 106         nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSItalicFontMask];
 107     }
 108 
 109     // create a bold style (if one is installed)
 110     if (style & java_awt_Font_BOLD) {
 111         nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSBoldFontMask];
 112     }
 113 
 114     return [[[AWTFont alloc] initWithFont:nsFont] autorelease];
 115 }
 116 
 117 + (NSFont *) nsFontForJavaFont:(jobject)javaFont env:(JNIEnv *)env {
 118     if (javaFont == NULL) {
 119 #ifdef DEBUG
 120         NSLog(@"nil font");
 121 #endif
 122         return nil;
 123     }
 124 
 125     static JNF_CLASS_CACHE(jc_Font, "java/awt/Font");
 126 
 127     // obtain the Font2D
 128     static JNF_MEMBER_CACHE(jm_Font_getFont2D, jc_Font, "getFont2D", "()Lsun/font/Font2D;");
 129     jobject font2d = JNFCallObjectMethod(env, javaFont, jm_Font_getFont2D);
 130     if (font2d == NULL) {
 131 #ifdef DEBUG
 132         NSLog(@"nil font2d");
 133 #endif
 134         return nil;
 135     }
 136 
 137     // if it's not a CFont, it's likely one of TTF or OTF fonts
 138     // from the Sun rendering loops
 139     static JNF_CLASS_CACHE(jc_CFont, "sun/font/CFont");
 140     if (!JNFIsInstanceOf(env, font2d, &jc_CFont)) {
 141 #ifdef DEBUG
 142         NSLog(@"font2d !instanceof CFont");
 143 #endif
 144         return nil;
 145     }
 146 
 147     static JNF_MEMBER_CACHE(jm_CFont_getFontStrike, jc_CFont, "getStrike", "(Ljava/awt/Font;)Lsun/font/FontStrike;");
 148     jobject fontStrike = JNFCallObjectMethod(env, font2d, jm_CFont_getFontStrike, javaFont);
 149 
 150     static JNF_CLASS_CACHE(jc_CStrike, "sun/font/CStrike");
 151     if (!JNFIsInstanceOf(env, fontStrike, &jc_CStrike)) {
 152 #ifdef DEBUG
 153         NSLog(@"fontStrike !instanceof CStrike");
 154 #endif
 155         return nil;
 156     }
 157 
 158     static JNF_MEMBER_CACHE(jm_CStrike_nativeStrikePtr, jc_CStrike, "getNativeStrikePtr", "()J");
 159     jlong awtStrikePtr = JNFCallLongMethod(env, fontStrike, jm_CStrike_nativeStrikePtr);
 160     if (awtStrikePtr == 0L) {
 161 #ifdef DEBUG
 162         NSLog(@"nil nativeFontPtr from CFont");
 163 #endif
 164         return nil;
 165     }
 166 
 167     AWTStrike *strike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 168 
 169     return [NSFont fontWithName:[strike->fAWTFont->fFont fontName] matrix:(CGFloat *)(&(strike->fAltTx))];
 170 }
 171 
 172 @end
 173 
 174 
 175 #pragma mark --- Font Discovery and Loading ---
 176 
 177 static NSArray* sFilteredFonts = nil;
 178 static NSDictionary* sFontFamilyTable = nil;
 179 
 180 static NSString*
 181 GetFamilyNameForFontName(NSString* fontname)
 182 {
 183     return [sFontFamilyTable objectForKey:fontname];
 184 }
 185 
 186 static void addFont(CTFontUIFontType uiType,
 187                     NSMutableArray *allFonts,
 188                     NSMutableDictionary* fontFamilyTable) {
 189 
 190         CTFontRef font = CTFontCreateUIFontForLanguage(uiType, 0.0, NULL);
 191         if (font == NULL) {
 192             return;
 193         }
 194         CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);
 195         if (desc == NULL) {
 196             CFRelease(font);
 197             return;
 198         }
 199         CFStringRef family = CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute);
 200         if (family == NULL) {
 201             CFRelease(desc);
 202             CFRelease(font);
 203             return;
 204         }
 205         CFStringRef name = CTFontDescriptorCopyAttribute(desc, kCTFontNameAttribute);
 206         if (name == NULL) {
 207             CFRelease(family);
 208             CFRelease(desc);
 209             CFRelease(font);
 210             return;
 211         }
 212         if (uiType == kCTFontUIFontSystem) {
 213             uiName = (NSString*)name;
 214         }
 215         if (uiType == kCTFontUIFontEmphasizedSystem) {
 216             uiBoldName = (NSString*)name;
 217         }
 218         [allFonts addObject:name];
 219         [fontFamilyTable setObject:family forKey:name];
 220 #ifdef DEBUG
 221         NSLog(@"name is : %@", (NSString*)name);
 222         NSLog(@"family is : %@", (NSString*)family);
 223 #endif
 224         CFRelease(family);
 225         CFRelease(name);
 226         CFRelease(desc);
 227         CFRelease(font);
 228 }
 229 
 230 static NSArray*
 231 GetFilteredFonts()
 232 {
 233     if (sFilteredFonts == nil) {
 234         NSFontManager *fontManager = [NSFontManager sharedFontManager];
 235         NSUInteger fontCount = [[fontManager availableFonts] count];
 236 
 237         NSMutableArray *allFonts = [[NSMutableArray alloc] initWithCapacity:fontCount];
 238         NSMutableDictionary* fontFamilyTable = [[NSMutableDictionary alloc] initWithCapacity:fontCount];
 239         NSArray *allFamilies = [fontManager availableFontFamilies];
 240 
 241         NSUInteger familyCount = [allFamilies count];
 242 
 243         NSUInteger familyIndex;
 244         for (familyIndex = 0; familyIndex < familyCount; familyIndex++) {
 245             NSString *family = [allFamilies objectAtIndex:familyIndex];
 246 
 247             if ((family == nil) || [family characterAtIndex:0] == '.') {
 248                 continue;
 249             }
 250 
 251             NSArray *fontFaces = [fontManager availableMembersOfFontFamily:family];
 252             NSUInteger faceCount = [fontFaces count];
 253 
 254             NSUInteger faceIndex;
 255             for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
 256                 NSString* face = [[fontFaces objectAtIndex:faceIndex] objectAtIndex:0];
 257                 if (face != nil) {
 258                     [allFonts addObject:face];
 259                     [fontFamilyTable setObject:family forKey:face];
 260                 }
 261             }
 262         }
 263 
 264         /*
 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, since
 267          * although these may include fonts that are enumerated normally
 268          * they also demonstrably includes fonts that are not.
 269          */
 270         addFont(kCTFontUIFontSystem, allFonts, fontFamilyTable);
 271         addFont(kCTFontUIFontEmphasizedSystem, allFonts, fontFamilyTable);
 272 
 273         sFilteredFonts = allFonts;
 274         sFontFamilyTable = fontFamilyTable;
 275     }
 276 
 277     return sFilteredFonts;
 278 }
 279 
 280 #pragma mark --- sun.font.CFontManager JNI ---
 281 
 282 static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath)
 283 {
 284     return FSPathMakeRef((UInt8 *)[inPath fileSystemRepresentation],
 285                          myFSRefPtr, NULL);
 286 }
 287 
 288 // /*
 289 //  * Class:     sun_font_CFontManager
 290 //  * Method:    loadFileFont
 291 //  * Signature: (Ljava/lang/String;)Lsun/font/Font2D;
 292 //  */
 293 // JNIEXPORT /* sun.font.CFont */ jobject JNICALL
 294 // Java_sun_font_CFontManager_loadFileFont
 295 //     (JNIEnv *env, jclass obj, jstring fontpath)
 296 // {
 297 //     jobject result = NULL;
 298 //
 299 // JNF_COCOA_ENTER(env);
 300 //
 301 //     NSString *nsFilePath = JNFJavaToNSString(env, fontpath);
 302 //     jstring javaFontName = NULL;
 303 //
 304 //     //
 305 //     // Note: This API uses ATS and can therefore return Carbon error codes.
 306 //     // These codes can be found at:
 307 //     // http://developer.apple.com/techpubs/macosx/Carbon/Files/FileManager/File_Manager/ResultCodes/ResultCodes.html
 308 //     //
 309 //
 310 //     FSRef iFile;
 311 //     OSStatus status = CreateFSRef(&iFile, nsFilePath);
 312 //
 313 //     if (status == noErr) {
 314 //         ATSFontContainerRef oContainer;
 315 //         status = ATSFontActivateFromFileReference(&iFile, kATSFontContextLocal,
 316 //                                                   kATSFontFormatUnspecified,
 317 //                                                   NULL,
 318 //                                                   kATSOptionFlagsUseDataFork,
 319 //                                                   &oContainer);
 320 //         if (status == noErr) {
 321 //             ATSFontRef ioArray[1];
 322 //             ItemCount oCount;
 323 //             status = ATSFontFindFromContainer(oContainer,
 324 //                                               kATSOptionFlagsUseDataFork,
 325 //                                               1, ioArray, &oCount);
 326 //
 327 //             if (status == noErr) {
 328 //                 CFStringRef oName;
 329 //                 status = ATSFontGetPostScriptName(ioArray[0],
 330 //                                                   kATSOptionFlagsUseDataFork,
 331 //                                                   &oName);
 332 //                 if (status == noErr) {
 333 //                     javaFontName = JNFNSToJavaString(env, (NSString *)oName);
 334 //                     CFRelease(oName);
 335 //                 }
 336 //             }
 337 //         }
 338 //     }
 339 //
 340 //     if (javaFontName != NULL) {
 341 //         // create the CFont!
 342 //         static JNF_CLASS_CACHE(sjc_CFont, "sun/font/CFont");
 343 //         static JNF_CTOR_CACHE(sjf_CFont_ctor,
 344 //                               sjc_CFont, "(Ljava/lang/String;)V");
 345 //         result = JNFNewObject(env, sjf_CFont_ctor, javaFontName);
 346 //     }
 347 //
 348 // JNF_COCOA_EXIT(env);
 349 //
 350 //     return result;
 351 // }
 352 
 353 /*
 354  * Class:     sun_font_CFontManager
 355  * Method:    loadNativeFonts
 356  * Signature: ()V
 357  */
 358 JNIEXPORT void JNICALL
 359 Java_sun_font_CFontManager_loadNativeFonts
 360     (JNIEnv *env, jobject jthis)
 361 {
 362     static JNF_CLASS_CACHE(jc_CFontManager,
 363                            "sun/font/CFontManager");
 364     static JNF_MEMBER_CACHE(jm_registerFont, jc_CFontManager,
 365                             "registerFont",
 366                             "(Ljava/lang/String;Ljava/lang/String;)V");
 367 
 368     jint num = 0;
 369 
 370 JNF_COCOA_ENTER(env);
 371 
 372     NSArray *filteredFonts = GetFilteredFonts();
 373     num = (jint)[filteredFonts count];
 374 
 375     jint i;
 376     for (i = 0; i < num; i++) {
 377         NSString *fontname = [filteredFonts objectAtIndex:i];
 378         jobject jFontName = JNFNSToJavaString(env, fontname);
 379         jobject jFontFamilyName =
 380             JNFNSToJavaString(env, GetFamilyNameForFontName(fontname));
 381 
 382         JNFCallVoidMethod(env, jthis,
 383                           jm_registerFont, jFontName, jFontFamilyName);
 384         (*env)->DeleteLocalRef(env, jFontName);
 385         (*env)->DeleteLocalRef(env, jFontFamilyName);
 386     }
 387 
 388 JNF_COCOA_EXIT(env);
 389 }
 390 
 391 /*
 392  * Class:     Java_sun_font_CFontManager_loadNativeDirFonts
 393  * Method:    loadNativeDirFonts
 394  * Signature: (Ljava/lang/String;)V;
 395  */
 396 JNIEXPORT void JNICALL
 397 Java_sun_font_CFontManager_loadNativeDirFonts
 398 (JNIEnv *env, jclass clz, jstring filename)
 399 {
 400 JNF_COCOA_ENTER(env);
 401 
 402     NSString *path = JNFJavaToNSString(env, filename);
 403     NSURL *url = [NSURL fileURLWithPath:(NSString *)path];
 404     bool res = CTFontManagerRegisterFontsForURL((CFURLRef)url, kCTFontManagerScopeProcess, nil);
 405 #ifdef DEBUG
 406     NSLog(@"path is : %@", (NSString*)path);
 407     NSLog(@"url is : %@", (NSString*)url);
 408     printf("res is %d\n", res);
 409 #endif
 410 JNF_COCOA_EXIT(env);
 411 }
 412 
 413 #pragma mark --- sun.font.CFont JNI ---
 414 
 415 /*
 416  * Class:     sun_font_CFont
 417  * Method:    getPlatformFontPtrNative
 418  * Signature: (JI)[B
 419  */
 420 JNIEXPORT jlong JNICALL
 421 Java_sun_font_CFont_getCGFontPtrNative
 422     (JNIEnv *env, jclass clazz,
 423      jlong awtFontPtr)
 424 {
 425     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
 426     return (jlong)(awtFont->fNativeCGFont);
 427 }
 428 
 429 /*
 430  * Class:     sun_font_CFont
 431  * Method:    getTableBytesNative
 432  * Signature: (JI)[B
 433  */
 434 JNIEXPORT jbyteArray JNICALL
 435 Java_sun_font_CFont_getTableBytesNative
 436     (JNIEnv *env, jclass clazz,
 437      jlong awtFontPtr, jint jtag)
 438 {
 439     jbyteArray jbytes = NULL;
 440 JNF_COCOA_ENTER(env);
 441 
 442     CTFontTableTag tag = (CTFontTableTag)jtag;
 443     int i, found = 0;
 444     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
 445     NSFont* nsFont = awtFont->fFont;
 446     CTFontRef ctfont = (CTFontRef)nsFont;
 447     CFArrayRef tagsArray =
 448         CTFontCopyAvailableTables(ctfont, kCTFontTableOptionNoOptions);
 449     CFIndex numTags = CFArrayGetCount(tagsArray);
 450     for (i=0; i<numTags; i++) {
 451         if (tag ==
 452             (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tagsArray, i)) {
 453             found = 1;
 454             break;
 455         }
 456     }
 457     CFRelease(tagsArray);
 458     if (!found) {
 459         return NULL;
 460     }
 461     CFDataRef table = CTFontCopyTable(ctfont, tag, kCTFontTableOptionNoOptions);
 462     if (table == NULL) {
 463         return NULL;
 464     }
 465 
 466     char *tableBytes = (char*)(CFDataGetBytePtr(table));
 467     size_t tableLength = CFDataGetLength(table);
 468     if (tableBytes == NULL || tableLength == 0) {
 469         CFRelease(table);
 470         return NULL;
 471     }
 472 
 473     jbytes = (*env)->NewByteArray(env, (jsize)tableLength);
 474     if (jbytes == NULL) {
 475         return NULL;
 476     }
 477     (*env)->SetByteArrayRegion(env, jbytes, 0,
 478                                (jsize)tableLength,
 479                                (jbyte*)tableBytes);
 480     CFRelease(table);
 481 
 482 JNF_COCOA_EXIT(env);
 483 
 484     return jbytes;
 485 }
 486 
 487 /*
 488  * Class:     sun_font_CFont
 489  * Method:    initNativeFont
 490  * Signature: (Ljava/lang/String;I)J
 491  */
 492 JNIEXPORT jlong JNICALL
 493 Java_sun_font_CFont_createNativeFont
 494     (JNIEnv *env, jclass clazz,
 495      jstring nativeFontName, jint style)
 496 {
 497     AWTFont *awtFont = nil;
 498 
 499 JNF_COCOA_ENTER(env);
 500 
 501     awtFont =
 502         [AWTFont awtFontForName:JNFJavaToNSString(env, nativeFontName)
 503          style:style]; // autoreleased
 504 
 505     if (awtFont) {
 506         CFRetain(awtFont); // GC
 507     }
 508 
 509 JNF_COCOA_EXIT(env);
 510 
 511     return ptr_to_jlong(awtFont);
 512 }
 513 
 514 /*
 515  * Class:     sun_font_CFont
 516  * Method:    getWidthNative
 517  * Signature: (J)F
 518  */
 519 JNIEXPORT jfloat JNICALL
 520 Java_sun_font_CFont_getWidthNative
 521     (JNIEnv *env, jobject cfont, jlong awtFontPtr)
 522 {
 523     float widthVal;
 524 JNF_COCOA_ENTER(env);
 525 
 526     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
 527     NSFont* nsFont = awtFont->fFont;
 528     NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;
 529     NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];
 530     NSNumber *width = [fontTraits objectForKey : NSFontWidthTrait];
 531     widthVal = (float)[width floatValue];
 532 
 533 JNF_COCOA_EXIT(env);
 534    return (jfloat)widthVal;
 535 }
 536 
 537 /*
 538  * Class:     sun_font_CFont
 539  * Method:    getWeightNative
 540  * Signature: (J)F
 541  */
 542 JNIEXPORT jfloat JNICALL
 543 Java_sun_font_CFont_getWeightNative
 544     (JNIEnv *env, jobject cfont, jlong awtFontPtr)
 545 {
 546     float weightVal;
 547 JNF_COCOA_ENTER(env);
 548 
 549     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
 550     NSFont* nsFont = awtFont->fFont;
 551     NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;
 552     NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];
 553     NSNumber *weight = [fontTraits objectForKey : NSFontWeightTrait];
 554     weightVal = (float)[weight floatValue];
 555 
 556 JNF_COCOA_EXIT(env);
 557    return (jfloat)weightVal;
 558 }
 559 
 560 /*
 561  * Class:     sun_font_CFont
 562  * Method:    disposeNativeFont
 563  * Signature: (J)V
 564  */
 565 JNIEXPORT void JNICALL
 566 Java_sun_font_CFont_disposeNativeFont
 567     (JNIEnv *env, jclass clazz, jlong awtFontPtr)
 568 {
 569 JNF_COCOA_ENTER(env);
 570 
 571     if (awtFontPtr) {
 572         CFRelease((AWTFont *)jlong_to_ptr(awtFontPtr)); // GC
 573     }
 574 
 575 JNF_COCOA_EXIT(env);
 576 }
 577 
 578 
 579 #pragma mark --- Miscellaneous JNI ---
 580 
 581 #ifndef HEADLESS
 582 /*
 583  * Class:     sun_awt_PlatformFont
 584  * Method:    initIDs
 585  * Signature: ()V
 586  */
 587 JNIEXPORT void JNICALL
 588 Java_sun_awt_PlatformFont_initIDs
 589     (JNIEnv *env, jclass cls)
 590 {
 591 }
 592 
 593 /*
 594  * Class:     sun_awt_FontDescriptor
 595  * Method:    initIDs
 596  * Signature: ()V
 597  */
 598 JNIEXPORT void JNICALL
 599 Java_sun_awt_FontDescriptor_initIDs
 600     (JNIEnv *env, jclass cls)
 601 {
 602 }
 603 #endif
 604 
 605 /*
 606  * Class:     sun_awt_FontDescriptor
 607  * Method:    initIDs
 608  * Signature: ()V
 609  */
 610 JNIEXPORT void JNICALL
 611 Java_sun_font_CFont_getCascadeList
 612     (JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)
 613 {
 614     jclass alc = (*env)->FindClass(env, "java/util/ArrayList");
 615     if (alc == NULL) return;
 616     jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");
 617     if (addMID == NULL) return;
 618 
 619     CFIndex i;
 620     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
 621     NSFont* nsFont = awtFont->fFont;
 622     CTFontRef font = (CTFontRef)nsFont;
 623     CFStringRef base = CTFontCopyFullName(font);
 624     CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
 625 
 626 #ifdef DEBUG
 627     NSLog(@"BaseFont is : %@", (NSString*)base);
 628 #endif
 629     CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
 630     CFIndex cnt = CFArrayGetCount(fds);
 631     for (i=0; i<cnt; i++) {
 632         CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
 633         CFStringRef fontname =
 634             CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);
 635 #ifdef DEBUG
 636         NSLog(@"Font is : %@", (NSString*)fontname);
 637 #endif
 638         jstring jFontName = (jstring)JNFNSToJavaString(env, fontname);
 639         (*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
 640         (*env)->DeleteLocalRef(env, jFontName);
 641     }
 642 }