1 /* 2 * Copyright 1998-2007 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 #include <windows.h> 27 #include <stdio.h> 28 29 #include <jni.h> 30 #include <jni_util.h> 31 #include <sun_awt_Win32FontManager.h> 32 33 #define BSIZE (max(512, MAX_PATH+1)) 34 35 36 JNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1) 37 { 38 char windir[BSIZE]; 39 char sysdir[BSIZE]; 40 char fontpath[BSIZE*2]; 41 char *end; 42 43 /* Locate fonts directories relative to the Windows System directory. 44 * If Windows System location is different than the user's window 45 * directory location, as in a shared Windows installation, 46 * return both locations as potential font directories 47 */ 48 GetSystemDirectory(sysdir, BSIZE); 49 end = strrchr(sysdir,'\\'); 50 if (end && (stricmp(end,"\\System") || stricmp(end,"\\System32"))) { 51 *end = 0; 52 strcat(sysdir, "\\Fonts"); 53 } 54 55 GetWindowsDirectory(windir, BSIZE); 56 if (strlen(windir) > BSIZE-7) { 57 *windir = 0; 58 } else { 59 strcat(windir, "\\Fonts"); 60 } 61 62 strcpy(fontpath,sysdir); 63 if (stricmp(sysdir,windir)) { 64 strcat(fontpath,";"); 65 strcat(fontpath,windir); 66 } 67 68 return JNU_NewStringPlatform(env, fontpath); 69 } 70 71 /* The code below is used to obtain information from the windows font APIS 72 * and registry on which fonts are available and what font files hold those 73 * fonts. The results are used to speed font lookup. 74 */ 75 76 typedef struct GdiFontMapInfo { 77 JNIEnv *env; 78 jstring family; 79 jobject fontToFamilyMap; 80 jobject familyToFontListMap; 81 jobject list; 82 jmethodID putMID; 83 jmethodID containsKeyMID; 84 jclass arrayListClass; 85 jmethodID arrayListCtr; 86 jmethodID addMID; 87 jmethodID toLowerCaseMID; 88 jobject locale; 89 } GdiFontMapInfo; 90 91 /* IS_NT means NT or later OSes which support Unicode. 92 * We have to painfully deal with the ASCII and non-ASCII case we 93 * we really want to get the font names as unicode wherever possible. 94 * UNICODE_OS is 0 to mean uninitialised, 1 to mean not a unicode OS, 95 * 2 to mean a unicode OS. 96 */ 97 98 #define UC_UNKNOWN 0 99 #define UC_NO 1 100 #define UC_YES 2 101 static int UNICODE_OS = UC_UNKNOWN; 102 static int GetOSVersion () { 103 OSVERSIONINFO vinfo; 104 vinfo.dwOSVersionInfoSize = sizeof(vinfo); 105 GetVersionEx(&vinfo); 106 if ((int)vinfo.dwMajorVersion > 4) { 107 UNICODE_OS = UC_YES; 108 } else if ((int)vinfo.dwMajorVersion < 4) { 109 UNICODE_OS = UC_NO; 110 } else { 111 if ((int)vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { 112 UNICODE_OS = UC_NO; 113 } else { 114 UNICODE_OS = UC_YES; 115 } 116 } 117 return UNICODE_OS; 118 } 119 120 #define IS_NT ((UNICODE_OS == UC_UNKNOWN) \ 121 ? (GetOSVersion() == UC_YES) : (UNICODE_OS == UC_YES)) 122 123 /* NT is W2K & XP. WIN is Win9x */ 124 static const char FONTKEY_NT[] = 125 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"; 126 static const char FONTKEY_WIN[] = 127 "Software\\Microsoft\\Windows\\CurrentVersion\\Fonts"; 128 129 /* Callback for call to EnumFontFamiliesEx in the EnumFamilyNames function. 130 * Expects to be called once for each face name in the family specified 131 * in the call. We extract the full name for the font which is expected 132 * to be in the "system encoding" and create canonical and lower case 133 * Java strings for the name which are added to the maps. The lower case 134 * name is used as key to the family name value in the font to family map, 135 * the canonical name is one of the"list" of members of the family. 136 */ 137 static int CALLBACK EnumFontFacesInFamilyProcA( 138 ENUMLOGFONTEXA *lpelfe, 139 NEWTEXTMETRICEX *lpntme, 140 int FontType, 141 LPARAM lParam ) 142 { 143 GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; 144 JNIEnv *env = fmi->env; 145 jstring fullname, fullnameLC; 146 147 /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ 148 if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { 149 return 1; 150 } 151 152 /* printf("FULL=%s\n",lpelfe->elfFullName);fflush(stdout); */ 153 154 fullname = JNU_NewStringPlatform(env, lpelfe->elfFullName); 155 fullnameLC = (*env)->CallObjectMethod(env, fullname, 156 fmi->toLowerCaseMID, fmi->locale); 157 (*env)->CallObjectMethod(env, fmi->list, fmi->addMID, fullname); 158 (*env)->CallObjectMethod(env, fmi->fontToFamilyMap, 159 fmi->putMID, fullnameLC, fmi->family); 160 return 1; 161 } 162 163 typedef struct CheckFamilyInfo { 164 wchar_t *family; 165 wchar_t* fullName; 166 int isDifferent; 167 } CheckFamilyInfo; 168 169 static int CALLBACK CheckFontFamilyProcW( 170 ENUMLOGFONTEXW *lpelfe, 171 NEWTEXTMETRICEX *lpntme, 172 int FontType, 173 LPARAM lParam) 174 { 175 CheckFamilyInfo *info = (CheckFamilyInfo*)lParam; 176 info->isDifferent = wcscmp(lpelfe->elfLogFont.lfFaceName, info->family); 177 178 /* if (!info->isDifferent) { */ 179 /* wprintf(LFor font %s expected family=%s instead got %s\n", */ 180 /* lpelfe->elfFullName, */ 181 /* info->family, */ 182 /* lpelfe->elfLogFont.lfFaceName); */ 183 /* fflush(stdout); */ 184 /* } */ 185 return 0; 186 } 187 188 static int DifferentFamily(wchar_t *family, wchar_t* fullName) { 189 LOGFONTW lfw; 190 CheckFamilyInfo info; 191 192 /* If fullName can't be stored in the struct, assume correct family */ 193 if (wcslen((LPWSTR)fullName) >= LF_FACESIZE) { 194 return 0; 195 } 196 197 memset(&info, 0, sizeof(CheckFamilyInfo)); 198 info.family = family; 199 info.fullName = fullName; 200 info.isDifferent = 0; 201 202 memset(&lfw, 0, sizeof(lfw)); 203 wcscpy(lfw.lfFaceName, fullName); 204 lfw.lfCharSet = DEFAULT_CHARSET; 205 EnumFontFamiliesExW(GetDC(NULL), &lfw, 206 (FONTENUMPROCW)CheckFontFamilyProcW, 207 (LPARAM)(&info), 0L); 208 209 return info.isDifferent; 210 } 211 212 static int CALLBACK EnumFontFacesInFamilyProcW( 213 ENUMLOGFONTEXW *lpelfe, 214 NEWTEXTMETRICEX *lpntme, 215 int FontType, 216 LPARAM lParam) 217 { 218 GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; 219 JNIEnv *env = fmi->env; 220 jstring fullname, fullnameLC; 221 222 /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ 223 if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { 224 return 1; 225 } 226 227 /* Windows has font aliases and so may enumerate fonts from 228 * the aliased family if any actual font of that family is installed. 229 * To protect against it ignore fonts which aren't enumerated under 230 * their true family. 231 */ 232 if (DifferentFamily(lpelfe->elfLogFont.lfFaceName, 233 lpelfe->elfFullName)) { 234 return 1; 235 } 236 237 fullname = (*env)->NewString(env, lpelfe->elfFullName, 238 wcslen((LPWSTR)lpelfe->elfFullName)); 239 fullnameLC = (*env)->CallObjectMethod(env, fullname, 240 fmi->toLowerCaseMID, fmi->locale); 241 (*env)->CallObjectMethod(env, fmi->list, fmi->addMID, fullname); 242 (*env)->CallObjectMethod(env, fmi->fontToFamilyMap, 243 fmi->putMID, fullnameLC, fmi->family); 244 return 1; 245 } 246 247 /* Callback for EnumFontFamiliesEx in populateFontFileNameMap. 248 * Expects to be called for every charset of every font family. 249 * If this is the first time we have been called for this family, 250 * add a new mapping to the familyToFontListMap from this family to a 251 * list of its members. To populate that list, further enumerate all faces 252 * in this family for the matched charset. This assumes that all fonts 253 * in a family support the same charset, which is a fairly safe assumption 254 * and saves time as the call we make here to EnumFontFamiliesEx will 255 * enumerate the members of this family just once each. 256 * Because we set fmi->list to be the newly created list the call back 257 * can safely add to that list without a search. 258 */ 259 static int CALLBACK EnumFamilyNamesA( 260 ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */ 261 NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */ 262 int FontType, /* type of font */ 263 LPARAM lParam) /* application-defined data */ 264 { 265 GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; 266 JNIEnv *env = fmi->env; 267 jstring familyLC; 268 LOGFONTA lfa; 269 270 /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ 271 if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { 272 return 1; 273 } 274 275 /* Windows lists fonts which have a vmtx (vertical metrics) table twice. 276 * Once using their normal name, and again preceded by '@'. These appear 277 * in font lists in some windows apps, such as wordpad. We don't want 278 * these so we skip any font where the first character is '@' 279 */ 280 if (lpelfe->elfLogFont.lfFaceName[0] == '@') { 281 return 1; 282 } 283 fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName); 284 familyLC = (*env)->CallObjectMethod(env, fmi->family, 285 fmi->toLowerCaseMID, fmi->locale); 286 /* check if already seen this family with a different charset */ 287 if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap, 288 fmi->containsKeyMID, familyLC)) { 289 return 1; 290 } 291 fmi->list = (*env)->NewObject(env, 292 fmi->arrayListClass, fmi->arrayListCtr, 4); 293 294 (*env)->CallObjectMethod(env, fmi->familyToFontListMap, 295 fmi->putMID, familyLC, fmi->list); 296 297 /* printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */ 298 299 memset(&lfa, 0, sizeof(lfa)); 300 strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName); 301 lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet; 302 EnumFontFamiliesExA(GetDC(NULL), &lfa, 303 (FONTENUMPROCA)EnumFontFacesInFamilyProcA, 304 lParam, 0L); 305 return 1; 306 } 307 308 static int CALLBACK EnumFamilyNamesW( 309 ENUMLOGFONTEXW *lpelfe, /* pointer to logical-font data */ 310 NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */ 311 int FontType, /* type of font */ 312 LPARAM lParam ) /* application-defined data */ 313 { 314 GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; 315 JNIEnv *env = fmi->env; 316 jstring familyLC; 317 int slen; 318 LOGFONTW lfw; 319 320 /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ 321 if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { 322 return 1; 323 } 324 /* wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */ 325 /* lpelfe->elfLogFont.lfFaceName, */ 326 /* lpelfe->elfLogFont.lfCharSet, */ 327 /* lpelfe->elfFullName); */ 328 /* fflush(stdout); */ 329 330 /* Windows lists fonts which have a vmtx (vertical metrics) table twice. 331 * Once using their normal name, and again preceded by '@'. These appear 332 * in font lists in some windows apps, such as wordpad. We don't want 333 * these so we skip any font where the first character is '@' 334 */ 335 if (lpelfe->elfLogFont.lfFaceName[0] == L'@') { 336 return 1; 337 } 338 slen = wcslen(lpelfe->elfLogFont.lfFaceName); 339 fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, slen); 340 familyLC = (*env)->CallObjectMethod(env, fmi->family, 341 fmi->toLowerCaseMID, fmi->locale); 342 /* check if already seen this family with a different charset */ 343 if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap, 344 fmi->containsKeyMID, familyLC)) { 345 return 1; 346 } 347 fmi->list = (*env)->NewObject(env, 348 fmi->arrayListClass, fmi->arrayListCtr, 4); 349 350 (*env)->CallObjectMethod(env, fmi->familyToFontListMap, 351 fmi->putMID, familyLC, fmi->list); 352 353 memset(&lfw, 0, sizeof(lfw)); 354 wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName); 355 lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet; 356 EnumFontFamiliesExW(GetDC(NULL), &lfw, 357 (FONTENUMPROCW)EnumFontFacesInFamilyProcW, 358 lParam, 0L); 359 return 1; 360 } 361 362 363 /* It looks like TrueType fonts have " (TrueType)" tacked on the end of their 364 * name, so we can try to use that to distinguish TT from other fonts. 365 * However if a program "installed" a font in the registry the key may 366 * not include that. We could also try to "pass" fonts which have no "(..)" 367 * at the end. But that turns out to pass a few .FON files that MS supply. 368 * If there's no parenthesised type string, we could next try to infer 369 * the file type from the file name extension. Since the MS entries that 370 * have no type string are very few, and have odd names like "MS-DOS CP 437" 371 * and would never return a Java Font anyway its currently OK to put these 372 * in the font map, although clearly the returned names must never percolate 373 * up into a list of available fonts returned to the application. 374 * Additionally for TTC font files the key looks like 375 * Font 1 & Font 2 (TrueType) 376 * or sometimes even : 377 * Font 1 & Font 2 & Font 3 (TrueType) 378 * Also if a Font has a name for this locale that name also 379 * exists in the registry using the appropriate platform encoding. 380 * What do we do then? 381 * 382 * Note: OpenType fonts seems to have " (TrueType)" suffix on Vista 383 * but " (OpenType)" on XP. 384 */ 385 386 static BOOL RegistryToBaseTTNameA(LPSTR name) { 387 static const char TTSUFFIX[] = " (TrueType)"; 388 static const char OTSUFFIX[] = " (OpenType)"; 389 int TTSLEN = strlen(TTSUFFIX); 390 char *suffix; 391 392 int len = strlen(name); 393 if (len == 0) { 394 return FALSE; 395 } 396 if (name[len-1] != ')') { 397 return FALSE; 398 } 399 if (len <= TTSLEN) { 400 return FALSE; 401 } 402 403 /* suffix length is the same for truetype and opentype fonts */ 404 suffix = name + len - TTSLEN; 405 if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) { 406 suffix[0] = '\0'; /* truncate name */ 407 return TRUE; 408 } 409 return FALSE; 410 } 411 412 static BOOL RegistryToBaseTTNameW(LPWSTR name) { 413 static const wchar_t TTSUFFIX[] = L" (TrueType)"; 414 static const wchar_t OTSUFFIX[] = L" (OpenType)"; 415 int TTSLEN = wcslen(TTSUFFIX); 416 wchar_t *suffix; 417 418 int len = wcslen(name); 419 if (len == 0) { 420 return FALSE; 421 } 422 if (name[len-1] != L')') { 423 return FALSE; 424 } 425 if (len <= TTSLEN) { 426 return FALSE; 427 } 428 /* suffix length is the same for truetype and opentype fonts */ 429 suffix = name + (len - TTSLEN); 430 if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) { 431 suffix[0] = L'\0'; /* truncate name */ 432 return TRUE; 433 } 434 return FALSE; 435 } 436 437 static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap, 438 LPCSTR name, LPCSTR data) { 439 LPSTR ptr1, ptr2; 440 jstring fontStr; 441 JNIEnv *env = fmi->env; 442 int dslen = strlen(data); 443 jstring fileStr = JNU_NewStringPlatform(env, data); 444 445 /* TTC or ttc means it may be a collection. Need to parse out 446 * multiple font face names separated by " & " 447 * By only doing this for fonts which look like collections based on 448 * file name we are adhering to MS recommendations for font file names 449 * so it seems that we can be sure that this identifies precisely 450 * the MS-supplied truetype collections. 451 * This avoids any potential issues if a TTF file happens to have 452 * a & in the font name (I can't find anything which prohibits this) 453 * and also means we only parse the key in cases we know to be 454 * worthwhile. 455 */ 456 if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') && 457 (ptr1 = strstr(name, " & ")) != NULL) { 458 ptr1+=3; 459 while (ptr1 >= name) { /* marginally safer than while (true) */ 460 while ((ptr2 = strstr(ptr1, " & ")) != NULL) { 461 ptr1 = ptr2+3; 462 } 463 fontStr = JNU_NewStringPlatform(env, ptr1); 464 fontStr = (*env)->CallObjectMethod(env, fontStr, 465 fmi->toLowerCaseMID, 466 fmi->locale); 467 (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, 468 fontStr, fileStr); 469 if (ptr1 == name) { 470 break; 471 } else { 472 *(ptr1-3) ='\0'; 473 ptr1 = (LPSTR)name; 474 } 475 } 476 } else { 477 fontStr = JNU_NewStringPlatform(env, name); 478 fontStr = (*env)->CallObjectMethod(env, fontStr, 479 fmi->toLowerCaseMID, fmi->locale); 480 (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, 481 fontStr, fileStr); 482 } 483 } 484 485 static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap, 486 LPWSTR name, LPWSTR data) { 487 488 wchar_t *ptr1, *ptr2; 489 jstring fontStr; 490 JNIEnv *env = fmi->env; 491 int dslen = wcslen(data); 492 jstring fileStr = (*env)->NewString(env, data, dslen); 493 494 /* TTC or ttc means it may be a collection. Need to parse out 495 * multiple font face names separated by " & " 496 * By only doing this for fonts which look like collections based on 497 * file name we are adhering to MS recommendations for font file names 498 * so it seems that we can be sure that this identifies precisely 499 * the MS-supplied truetype collections. 500 * This avoids any potential issues if a TTF file happens to have 501 * a & in the font name (I can't find anything which prohibits this) 502 * and also means we only parse the key in cases we know to be 503 * worthwhile. 504 */ 505 506 if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') && 507 (ptr1 = wcsstr(name, L" & ")) != NULL) { 508 ptr1+=3; 509 while (ptr1 >= name) { /* marginally safer than while (true) */ 510 while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) { 511 ptr1 = ptr2+3; 512 } 513 fontStr = (*env)->NewString(env, ptr1, wcslen(ptr1)); 514 fontStr = (*env)->CallObjectMethod(env, fontStr, 515 fmi->toLowerCaseMID, 516 fmi->locale); 517 (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, 518 fontStr, fileStr); 519 if (ptr1 == name) { 520 break; 521 } else { 522 *(ptr1-3) = L'\0'; 523 ptr1 = name; 524 } 525 } 526 } else { 527 fontStr = (*env)->NewString(env, name, wcslen(name)); 528 fontStr = (*env)->CallObjectMethod(env, fontStr, 529 fmi->toLowerCaseMID, fmi->locale); 530 (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, 531 fontStr, fileStr); 532 } 533 } 534 535 /* Obtain all the fontname -> filename mappings. 536 * This is called once and the results returned to Java code which can 537 * use it for lookups to reduce or avoid the need to search font files. 538 */ 539 JNIEXPORT void JNICALL 540 Java_sun_awt_Win32FontManager_populateFontFileNameMap0 541 (JNIEnv *env, jclass obj, jobject fontToFileMap, 542 jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale) 543 { 544 #define MAX_BUFFER (FILENAME_MAX+1) 545 const wchar_t wname[MAX_BUFFER]; 546 const char cname[MAX_BUFFER]; 547 const char data[MAX_BUFFER]; 548 549 DWORD type; 550 LONG ret; 551 HKEY hkeyFonts; 552 DWORD dwNameSize; 553 DWORD dwDataValueSize; 554 DWORD nval; 555 LPCSTR fontKeyName; 556 DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen; 557 DWORD numValues = 0; 558 jclass classID; 559 jmethodID putMID; 560 GdiFontMapInfo fmi; 561 562 /* Check we were passed all the maps we need, and do lookup of 563 * methods for JNI up-calls 564 */ 565 if (fontToFileMap == NULL || 566 fontToFamilyMap == NULL || 567 familyToFontListMap == NULL) { 568 return; 569 } 570 classID = (*env)->FindClass(env, "java/util/HashMap"); 571 if (classID == NULL) { 572 return; 573 } 574 putMID = (*env)->GetMethodID(env, classID, "put", 575 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 576 if (putMID == NULL) { 577 return; 578 } 579 580 fmi.env = env; 581 fmi.fontToFamilyMap = fontToFamilyMap; 582 fmi.familyToFontListMap = familyToFontListMap; 583 fmi.putMID = putMID; 584 fmi.locale = locale; 585 fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey", 586 "(Ljava/lang/Object;)Z"); 587 if (fmi.containsKeyMID == NULL) { 588 return; 589 } 590 591 fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); 592 if (fmi.arrayListClass == NULL) { 593 return; 594 } 595 fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass, 596 "<init>", "(I)V"); 597 if (fmi.arrayListCtr == NULL) { 598 return; 599 } 600 fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass, 601 "add", "(Ljava/lang/Object;)Z"); 602 if (fmi.addMID == NULL) { 603 return; 604 } 605 classID = (*env)->FindClass(env, "java/lang/String"); 606 if (classID == NULL) { 607 return; 608 } 609 fmi.toLowerCaseMID = 610 (*env)->GetMethodID(env, classID, "toLowerCase", 611 "(Ljava/util/Locale;)Ljava/lang/String;"); 612 if (fmi.toLowerCaseMID == NULL) { 613 return; 614 } 615 616 /* Enumerate fonts via GDI to build maps of fonts and families */ 617 if (IS_NT) { 618 LOGFONTW lfw; 619 memset(&lfw, 0, sizeof(lfw)); 620 lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */ 621 wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */ 622 EnumFontFamiliesExW(GetDC(NULL), &lfw, 623 (FONTENUMPROCW)EnumFamilyNamesW, 624 (LPARAM)(&fmi), 0L); 625 } else { 626 LOGFONT lfa; 627 memset(&lfa, 0, sizeof(lfa)); 628 lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */ 629 strcpy(lfa.lfFaceName, ""); /* one face per family */ 630 ret = EnumFontFamiliesExA(GetDC(NULL), &lfa, 631 (FONTENUMPROCA)EnumFamilyNamesA, 632 (LPARAM)(&fmi), 0L); 633 } 634 635 /* Use the windows registry to map font names to files */ 636 fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN; 637 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 638 fontKeyName, 0L, KEY_READ, &hkeyFonts); 639 if (ret != ERROR_SUCCESS) { 640 return; 641 } 642 643 if (IS_NT) { 644 ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL, 645 &dwNumValues, &dwMaxValueNameLen, 646 &dwMaxValueDataLen, NULL, NULL); 647 } else { 648 ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL, 649 &dwNumValues, &dwMaxValueNameLen, 650 &dwMaxValueDataLen, NULL, NULL); 651 } 652 if (ret != ERROR_SUCCESS || 653 dwMaxValueNameLen >= MAX_BUFFER || 654 dwMaxValueDataLen >= MAX_BUFFER) { 655 RegCloseKey(hkeyFonts); 656 return; 657 } 658 for (nval = 0; nval < dwNumValues; nval++ ) { 659 dwNameSize = MAX_BUFFER; 660 dwDataValueSize = MAX_BUFFER; 661 if (IS_NT) { 662 ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize, 663 NULL, &type, (LPBYTE)data, &dwDataValueSize); 664 } else { 665 ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize, 666 NULL, &type, (LPBYTE)data, &dwDataValueSize); 667 } 668 if (ret != ERROR_SUCCESS) { 669 break; 670 } 671 if (type != REG_SZ) { /* REG_SZ means a null-terminated string */ 672 continue; 673 } 674 if (IS_NT) { 675 if (!RegistryToBaseTTNameW((LPWSTR)wname) ) { 676 /* If the filename ends with ".ttf" or ".otf" also accept it. 677 * Not expecting to need to do this for .ttc files. 678 * Also note this code is not mirrored in the "A" (win9x) path. 679 */ 680 LPWSTR dot = wcsrchr((LPWSTR)data, L'.'); 681 if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0) 682 && (wcsicmp(dot, L".otf") != 0))) { 683 continue; /* not a TT font... */ 684 } 685 } 686 registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data); 687 } else { 688 if (!RegistryToBaseTTNameA((LPSTR)cname)) { 689 continue; /* not a TT font... */ 690 } 691 registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data); 692 } 693 } 694 RegCloseKey(hkeyFonts); 695 }