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