src/windows/native/sun/font/fontpath.c

Print this page




 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)->CallBooleanMethod(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 {


 225     JNIEnv *env = fmi->env;
 226     jstring fullname, fullnameLC;
 227 
 228     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 229     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 230         return 1;
 231     }
 232 
 233     /* Windows has font aliases and so may enumerate fonts from
 234      * the aliased family if any actual font of that family is installed.
 235      * To protect against it ignore fonts which aren't enumerated under
 236      * their true family.
 237      */
 238     if (DifferentFamily(lpelfe->elfLogFont.lfFaceName,
 239                         lpelfe->elfFullName))  {
 240       return 1;
 241     }
 242 
 243     fullname = (*env)->NewString(env, lpelfe->elfFullName,
 244                                  (jsize)wcslen((LPWSTR)lpelfe->elfFullName));




 245     fullnameLC = (*env)->CallObjectMethod(env, fullname,
 246                                           fmi->toLowerCaseMID, fmi->locale);
 247     (*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
 248     (*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
 249                              fmi->putMID, fullnameLC, fmi->family);
 250     return 1;
 251 }
 252 
 253 /* Callback for EnumFontFamiliesEx in populateFontFileNameMap.
 254  * Expects to be called for every charset of every font family.
 255  * If this is the first time we have been called for this family,
 256  * add a new mapping to the familyToFontListMap from this family to a
 257  * list of its members. To populate that list, further enumerate all faces
 258  * in this family for the matched charset. This assumes that all fonts
 259  * in a family support the same charset, which is a fairly safe assumption
 260  * and saves time as the call we make here to EnumFontFamiliesEx will
 261  * enumerate the members of this family just once each.
 262  * Because we set fmi->list to be the newly created list the call back
 263  * can safely add to that list without a search.
 264  */


 270 {
 271     GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
 272     JNIEnv *env = fmi->env;
 273     jstring familyLC;
 274     LOGFONTA lfa;
 275 
 276     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 277     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 278         return 1;
 279     }
 280 
 281     /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
 282      * Once using their normal name, and again preceded by '@'. These appear
 283      * in font lists in some windows apps, such as wordpad. We don't want
 284      * these so we skip any font where the first character is '@'
 285      */
 286     if (lpelfe->elfLogFont.lfFaceName[0] == '@') {
 287         return 1;
 288     }
 289     fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName);




 290     familyLC = (*env)->CallObjectMethod(env, fmi->family,
 291                                         fmi->toLowerCaseMID, fmi->locale);
 292     /* check if already seen this family with a different charset */
 293     if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
 294                                   fmi->containsKeyMID, familyLC)) {
 295         return 1;
 296     }
 297     fmi->list = (*env)->NewObject(env,
 298                                   fmi->arrayListClass, fmi->arrayListCtr, 4);
 299 



 300     (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
 301                              fmi->putMID, familyLC, fmi->list);
 302 
 303 /*  printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */
 304 
 305     memset(&lfa, 0, sizeof(lfa));
 306     strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName);
 307     lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet;
 308     EnumFontFamiliesExA(screenDC, &lfa,
 309                         (FONTENUMPROCA)EnumFontFacesInFamilyProcA,
 310                         lParam, 0L);
 311     return 1;
 312 }
 313 
 314 static int CALLBACK EnumFamilyNamesW(
 315   ENUMLOGFONTEXW *lpelfe,    /* pointer to logical-font data */
 316   NEWTEXTMETRICEX *lpntme,  /* pointer to physical-font data */
 317   int FontType,             /* type of font */
 318   LPARAM lParam )           /* application-defined data */
 319 {


 326     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 327     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 328         return 1;
 329     }
 330 /*     wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */
 331 /*          lpelfe->elfLogFont.lfFaceName, */
 332 /*          lpelfe->elfLogFont.lfCharSet, */
 333 /*          lpelfe->elfFullName); */
 334 /*     fflush(stdout); */
 335 
 336     /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
 337      * Once using their normal name, and again preceded by '@'. These appear
 338      * in font lists in some windows apps, such as wordpad. We don't want
 339      * these so we skip any font where the first character is '@'
 340      */
 341     if (lpelfe->elfLogFont.lfFaceName[0] == L'@') {
 342             return 1;
 343     }
 344     slen = wcslen(lpelfe->elfLogFont.lfFaceName);
 345     fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen);




 346     familyLC = (*env)->CallObjectMethod(env, fmi->family,
 347                                         fmi->toLowerCaseMID, fmi->locale);
 348     /* check if already seen this family with a different charset */
 349     if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
 350                                   fmi->containsKeyMID, familyLC)) {
 351         return 1;
 352     }
 353     fmi->list = (*env)->NewObject(env,
 354                                   fmi->arrayListClass, fmi->arrayListCtr, 4);
 355 



 356     (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
 357                              fmi->putMID, familyLC, fmi->list);
 358 
 359     memset(&lfw, 0, sizeof(lfw));
 360     wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName);
 361     lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet;
 362     EnumFontFamiliesExW(screenDC, &lfw,
 363                         (FONTENUMPROCW)EnumFontFacesInFamilyProcW,
 364                         lParam, 0L);
 365     return 1;
 366 }
 367 
 368 
 369 /* It looks like TrueType fonts have " (TrueType)" tacked on the end of their
 370  * name, so we can try to use that to distinguish TT from other fonts.
 371  * However if a program "installed" a font in the registry the key may
 372  * not include that. We could also try to "pass" fonts which have no "(..)"
 373  * at the end. But that turns out to pass a few .FON files that MS supply.
 374  * If there's no parenthesized type string, we could next try to infer
 375  * the file type from the file name extension. Since the MS entries that


 430     }
 431     if (len <= TTSLEN) {
 432         return FALSE;
 433     }
 434     /* suffix length is the same for truetype and opentype fonts */
 435     suffix = name + (len - TTSLEN);
 436     if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) {
 437         suffix[0] = L'\0'; /* truncate name */
 438         return TRUE;
 439     }
 440     return FALSE;
 441 }
 442 
 443 static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,
 444                           LPCSTR name, LPCSTR data) {
 445     LPSTR ptr1, ptr2;
 446     jstring fontStr;
 447     JNIEnv *env = fmi->env;
 448     size_t dslen = strlen(data);
 449     jstring fileStr = JNU_NewStringPlatform(env, data);




 450 
 451     /* TTC or ttc means it may be a collection. Need to parse out
 452      * multiple font face names separated by " & "
 453      * By only doing this for fonts which look like collections based on
 454      * file name we are adhering to MS recommendations for font file names
 455      * so it seems that we can be sure that this identifies precisely
 456      * the MS-supplied truetype collections.
 457      * This avoids any potential issues if a TTF file happens to have
 458      * a & in the font name (I can't find anything which prohibits this)
 459      * and also means we only parse the key in cases we know to be
 460      * worthwhile.
 461      */
 462     if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') &&
 463         (ptr1 = strstr(name, " & ")) != NULL) {
 464         ptr1+=3;
 465         while (ptr1 >= name) { /* marginally safer than while (true) */
 466             while ((ptr2 = strstr(ptr1, " & ")) != NULL) {
 467                     ptr1 = ptr2+3;
 468             }
 469             fontStr = JNU_NewStringPlatform(env, ptr1);




 470             fontStr = (*env)->CallObjectMethod(env, fontStr,
 471                                                fmi->toLowerCaseMID,
 472                                                fmi->locale);
 473             (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 474                                      fontStr, fileStr);
 475             if (ptr1 == name) {
 476                 break;
 477             } else {
 478                 *(ptr1-3) ='\0';
 479                 ptr1 = (LPSTR)name;
 480             }
 481         }
 482     } else {
 483         fontStr = JNU_NewStringPlatform(env, name);




 484         fontStr = (*env)->CallObjectMethod(env, fontStr,
 485                                            fmi->toLowerCaseMID, fmi->locale);
 486         (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 487                                  fontStr, fileStr);
 488     }
 489 }
 490 
 491 static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
 492                           LPWSTR name, LPWSTR data) {
 493 
 494     wchar_t *ptr1, *ptr2;
 495     jstring fontStr;
 496     JNIEnv *env = fmi->env;
 497     size_t dslen = wcslen(data);
 498     jstring fileStr = (*env)->NewString(env, data, (jsize)dslen);




 499 
 500     /* TTC or ttc means it may be a collection. Need to parse out
 501      * multiple font face names separated by " & "
 502      * By only doing this for fonts which look like collections based on
 503      * file name we are adhering to MS recommendations for font file names
 504      * so it seems that we can be sure that this identifies precisely
 505      * the MS-supplied truetype collections.
 506      * This avoids any potential issues if a TTF file happens to have
 507      * a & in the font name (I can't find anything which prohibits this)
 508      * and also means we only parse the key in cases we know to be
 509      * worthwhile.
 510      */
 511 
 512     if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') &&
 513         (ptr1 = wcsstr(name, L" & ")) != NULL) {
 514         ptr1+=3;
 515         while (ptr1 >= name) { /* marginally safer than while (true) */
 516             while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) {
 517                 ptr1 = ptr2+3;
 518             }
 519             fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1));




 520             fontStr = (*env)->CallObjectMethod(env, fontStr,
 521                                                fmi->toLowerCaseMID,
 522                                                fmi->locale);
 523             (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 524                                      fontStr, fileStr);
 525             if (ptr1 == name) {
 526                 break;
 527             } else {
 528                 *(ptr1-3) = L'\0';
 529                 ptr1 = name;
 530             }
 531         }
 532     } else {
 533         fontStr = (*env)->NewString(env, name, (jsize)wcslen(name));




 534         fontStr = (*env)->CallObjectMethod(env, fontStr,
 535                                            fmi->toLowerCaseMID, fmi->locale);
 536         (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 537                                  fontStr, fileStr);
 538     }
 539 }
 540 
 541 /* Obtain all the fontname -> filename mappings.
 542  * This is called once and the results returned to Java code which can
 543  * use it for lookups to reduce or avoid the need to search font files.
 544  */
 545 JNIEXPORT void JNICALL
 546 Java_sun_awt_Win32FontManager_populateFontFileNameMap0
 547 (JNIEnv *env, jclass obj, jobject fontToFileMap,
 548  jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
 549 {
 550 #define MAX_BUFFER (FILENAME_MAX+1)
 551     const wchar_t wname[MAX_BUFFER];
 552     const char cname[MAX_BUFFER];
 553     const char data[MAX_BUFFER];




 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     if (fullname == NULL) {
 156         (*env)->ExceptionClear(env);
 157         return 1;
 158     }
 159     fullnameLC = (*env)->CallObjectMethod(env, fullname,
 160                                           fmi->toLowerCaseMID, fmi->locale);
 161     (*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
 162     (*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
 163                              fmi->putMID, fullnameLC, fmi->family);
 164     return 1;
 165 }
 166 
 167 typedef struct CheckFamilyInfo {
 168   wchar_t *family;
 169   wchar_t* fullName;
 170   int isDifferent;
 171 } CheckFamilyInfo;
 172 
 173 static int CALLBACK CheckFontFamilyProcW(
 174   ENUMLOGFONTEXW *lpelfe,
 175   NEWTEXTMETRICEX *lpntme,
 176   int FontType,
 177   LPARAM lParam)
 178 {


 229     JNIEnv *env = fmi->env;
 230     jstring fullname, fullnameLC;
 231 
 232     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 233     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 234         return 1;
 235     }
 236 
 237     /* Windows has font aliases and so may enumerate fonts from
 238      * the aliased family if any actual font of that family is installed.
 239      * To protect against it ignore fonts which aren't enumerated under
 240      * their true family.
 241      */
 242     if (DifferentFamily(lpelfe->elfLogFont.lfFaceName,
 243                         lpelfe->elfFullName))  {
 244       return 1;
 245     }
 246 
 247     fullname = (*env)->NewString(env, lpelfe->elfFullName,
 248                                  (jsize)wcslen((LPWSTR)lpelfe->elfFullName));
 249     if (fullname == NULL) {
 250         (*env)->ExceptionClear(env);
 251         return 1;
 252     }
 253     fullnameLC = (*env)->CallObjectMethod(env, fullname,
 254                                           fmi->toLowerCaseMID, fmi->locale);
 255     (*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
 256     (*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
 257                              fmi->putMID, fullnameLC, fmi->family);
 258     return 1;
 259 }
 260 
 261 /* Callback for EnumFontFamiliesEx in populateFontFileNameMap.
 262  * Expects to be called for every charset of every font family.
 263  * If this is the first time we have been called for this family,
 264  * add a new mapping to the familyToFontListMap from this family to a
 265  * list of its members. To populate that list, further enumerate all faces
 266  * in this family for the matched charset. This assumes that all fonts
 267  * in a family support the same charset, which is a fairly safe assumption
 268  * and saves time as the call we make here to EnumFontFamiliesEx will
 269  * enumerate the members of this family just once each.
 270  * Because we set fmi->list to be the newly created list the call back
 271  * can safely add to that list without a search.
 272  */


 278 {
 279     GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
 280     JNIEnv *env = fmi->env;
 281     jstring familyLC;
 282     LOGFONTA lfa;
 283 
 284     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 285     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 286         return 1;
 287     }
 288 
 289     /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
 290      * Once using their normal name, and again preceded by '@'. These appear
 291      * in font lists in some windows apps, such as wordpad. We don't want
 292      * these so we skip any font where the first character is '@'
 293      */
 294     if (lpelfe->elfLogFont.lfFaceName[0] == '@') {
 295         return 1;
 296     }
 297     fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName);
 298     if (fmi->family == NULL) {
 299         (*env)->ExceptionClear(env);
 300         return 1;
 301     }
 302     familyLC = (*env)->CallObjectMethod(env, fmi->family,
 303                                         fmi->toLowerCaseMID, fmi->locale);
 304     /* check if already seen this family with a different charset */
 305     if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
 306                                   fmi->containsKeyMID, familyLC)) {
 307         return 1;
 308     }
 309     fmi->list = (*env)->NewObject(env,
 310                                   fmi->arrayListClass, fmi->arrayListCtr, 4);
 311     if (fmi->list == NULL) {
 312         (*env)->ExceptionClear(env);
 313         return 1;
 314     }
 315     (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
 316                              fmi->putMID, familyLC, fmi->list);
 317 
 318 /*  printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */
 319 
 320     memset(&lfa, 0, sizeof(lfa));
 321     strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName);
 322     lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet;
 323     EnumFontFamiliesExA(screenDC, &lfa,
 324                         (FONTENUMPROCA)EnumFontFacesInFamilyProcA,
 325                         lParam, 0L);
 326     return 1;
 327 }
 328 
 329 static int CALLBACK EnumFamilyNamesW(
 330   ENUMLOGFONTEXW *lpelfe,    /* pointer to logical-font data */
 331   NEWTEXTMETRICEX *lpntme,  /* pointer to physical-font data */
 332   int FontType,             /* type of font */
 333   LPARAM lParam )           /* application-defined data */
 334 {


 341     /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
 342     if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
 343         return 1;
 344     }
 345 /*     wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */
 346 /*          lpelfe->elfLogFont.lfFaceName, */
 347 /*          lpelfe->elfLogFont.lfCharSet, */
 348 /*          lpelfe->elfFullName); */
 349 /*     fflush(stdout); */
 350 
 351     /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
 352      * Once using their normal name, and again preceded by '@'. These appear
 353      * in font lists in some windows apps, such as wordpad. We don't want
 354      * these so we skip any font where the first character is '@'
 355      */
 356     if (lpelfe->elfLogFont.lfFaceName[0] == L'@') {
 357             return 1;
 358     }
 359     slen = wcslen(lpelfe->elfLogFont.lfFaceName);
 360     fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen);
 361     if (fmi->family == NULL) {
 362         (*env)->ExceptionClear(env);
 363         return 1;
 364     }
 365     familyLC = (*env)->CallObjectMethod(env, fmi->family,
 366                                         fmi->toLowerCaseMID, fmi->locale);
 367     /* check if already seen this family with a different charset */
 368     if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
 369                                   fmi->containsKeyMID, familyLC)) {
 370         return 1;
 371     }
 372     fmi->list = (*env)->NewObject(env,
 373                                   fmi->arrayListClass, fmi->arrayListCtr, 4);
 374     if (fmi->list == NULL) {
 375         (*env)->ExceptionClear(env);
 376         return 1;
 377     }
 378     (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
 379                              fmi->putMID, familyLC, fmi->list);
 380 
 381     memset(&lfw, 0, sizeof(lfw));
 382     wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName);
 383     lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet;
 384     EnumFontFamiliesExW(screenDC, &lfw,
 385                         (FONTENUMPROCW)EnumFontFacesInFamilyProcW,
 386                         lParam, 0L);
 387     return 1;
 388 }
 389 
 390 
 391 /* It looks like TrueType fonts have " (TrueType)" tacked on the end of their
 392  * name, so we can try to use that to distinguish TT from other fonts.
 393  * However if a program "installed" a font in the registry the key may
 394  * not include that. We could also try to "pass" fonts which have no "(..)"
 395  * at the end. But that turns out to pass a few .FON files that MS supply.
 396  * If there's no parenthesized type string, we could next try to infer
 397  * the file type from the file name extension. Since the MS entries that


 452     }
 453     if (len <= TTSLEN) {
 454         return FALSE;
 455     }
 456     /* suffix length is the same for truetype and opentype fonts */
 457     suffix = name + (len - TTSLEN);
 458     if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) {
 459         suffix[0] = L'\0'; /* truncate name */
 460         return TRUE;
 461     }
 462     return FALSE;
 463 }
 464 
 465 static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,
 466                           LPCSTR name, LPCSTR data) {
 467     LPSTR ptr1, ptr2;
 468     jstring fontStr;
 469     JNIEnv *env = fmi->env;
 470     size_t dslen = strlen(data);
 471     jstring fileStr = JNU_NewStringPlatform(env, data);
 472     if (fileStr == NULL) {
 473         (*env)->ExceptionClear(env);
 474         return;
 475     }
 476 
 477     /* TTC or ttc means it may be a collection. Need to parse out
 478      * multiple font face names separated by " & "
 479      * By only doing this for fonts which look like collections based on
 480      * file name we are adhering to MS recommendations for font file names
 481      * so it seems that we can be sure that this identifies precisely
 482      * the MS-supplied truetype collections.
 483      * This avoids any potential issues if a TTF file happens to have
 484      * a & in the font name (I can't find anything which prohibits this)
 485      * and also means we only parse the key in cases we know to be
 486      * worthwhile.
 487      */
 488     if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') &&
 489         (ptr1 = strstr(name, " & ")) != NULL) {
 490         ptr1+=3;
 491         while (ptr1 >= name) { /* marginally safer than while (true) */
 492             while ((ptr2 = strstr(ptr1, " & ")) != NULL) {
 493                     ptr1 = ptr2+3;
 494             }
 495             fontStr = JNU_NewStringPlatform(env, ptr1);
 496             if (fontStr == NULL) {
 497                 (*env)->ExceptionClear(env);
 498                 return;
 499             }
 500             fontStr = (*env)->CallObjectMethod(env, fontStr,
 501                                                fmi->toLowerCaseMID,
 502                                                fmi->locale);
 503             (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 504                                      fontStr, fileStr);
 505             if (ptr1 == name) {
 506                 break;
 507             } else {
 508                 *(ptr1-3) ='\0';
 509                 ptr1 = (LPSTR)name;
 510             }
 511         }
 512     } else {
 513         fontStr = JNU_NewStringPlatform(env, name);
 514         if (fontStr == NULL) {
 515             (*env)->ExceptionClear(env);
 516             return;
 517         }
 518         fontStr = (*env)->CallObjectMethod(env, fontStr,
 519                                            fmi->toLowerCaseMID, fmi->locale);
 520         (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 521                                  fontStr, fileStr);
 522     }
 523 }
 524 
 525 static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
 526                           LPWSTR name, LPWSTR data) {
 527 
 528     wchar_t *ptr1, *ptr2;
 529     jstring fontStr;
 530     JNIEnv *env = fmi->env;
 531     size_t dslen = wcslen(data);
 532     jstring fileStr = (*env)->NewString(env, data, (jsize)dslen);
 533     if (fileStr == NULL) {
 534         (*env)->ExceptionClear(env);
 535         return;
 536     }
 537 
 538     /* TTC or ttc means it may be a collection. Need to parse out
 539      * multiple font face names separated by " & "
 540      * By only doing this for fonts which look like collections based on
 541      * file name we are adhering to MS recommendations for font file names
 542      * so it seems that we can be sure that this identifies precisely
 543      * the MS-supplied truetype collections.
 544      * This avoids any potential issues if a TTF file happens to have
 545      * a & in the font name (I can't find anything which prohibits this)
 546      * and also means we only parse the key in cases we know to be
 547      * worthwhile.
 548      */
 549 
 550     if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') &&
 551         (ptr1 = wcsstr(name, L" & ")) != NULL) {
 552         ptr1+=3;
 553         while (ptr1 >= name) { /* marginally safer than while (true) */
 554             while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) {
 555                 ptr1 = ptr2+3;
 556             }
 557             fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1));
 558             if (fontStr == NULL) {
 559                 (*env)->ExceptionClear(env);
 560                 return;
 561             }
 562             fontStr = (*env)->CallObjectMethod(env, fontStr,
 563                                                fmi->toLowerCaseMID,
 564                                                fmi->locale);
 565             (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 566                                      fontStr, fileStr);
 567             if (ptr1 == name) {
 568                 break;
 569             } else {
 570                 *(ptr1-3) = L'\0';
 571                 ptr1 = name;
 572             }
 573         }
 574     } else {
 575         fontStr = (*env)->NewString(env, name, (jsize)wcslen(name));
 576         if (fontStr == NULL) {
 577             (*env)->ExceptionClear(env);
 578             return;
 579         }
 580         fontStr = (*env)->CallObjectMethod(env, fontStr,
 581                                            fmi->toLowerCaseMID, fmi->locale);
 582         (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
 583                                  fontStr, fileStr);
 584     }
 585 }
 586 
 587 /* Obtain all the fontname -> filename mappings.
 588  * This is called once and the results returned to Java code which can
 589  * use it for lookups to reduce or avoid the need to search font files.
 590  */
 591 JNIEXPORT void JNICALL
 592 Java_sun_awt_Win32FontManager_populateFontFileNameMap0
 593 (JNIEnv *env, jclass obj, jobject fontToFileMap,
 594  jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
 595 {
 596 #define MAX_BUFFER (FILENAME_MAX+1)
 597     const wchar_t wname[MAX_BUFFER];
 598     const char cname[MAX_BUFFER];
 599     const char data[MAX_BUFFER];