0N/A/*
3261N/A * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <windows.h>
0N/A#include <stdio.h>
0N/A
0N/A#include <jni.h>
0N/A#include <jni_util.h>
1686N/A#include <sun_awt_Win32FontManager.h>
0N/A
0N/A#define BSIZE (max(512, MAX_PATH+1))
0N/A
0N/A
1686N/AJNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1)
0N/A{
0N/A char windir[BSIZE];
0N/A char sysdir[BSIZE];
0N/A char fontpath[BSIZE*2];
0N/A char *end;
0N/A
0N/A /* Locate fonts directories relative to the Windows System directory.
0N/A * If Windows System location is different than the user's window
0N/A * directory location, as in a shared Windows installation,
0N/A * return both locations as potential font directories
0N/A */
0N/A GetSystemDirectory(sysdir, BSIZE);
0N/A end = strrchr(sysdir,'\\');
0N/A if (end && (stricmp(end,"\\System") || stricmp(end,"\\System32"))) {
0N/A *end = 0;
0N/A strcat(sysdir, "\\Fonts");
0N/A }
0N/A
0N/A GetWindowsDirectory(windir, BSIZE);
0N/A if (strlen(windir) > BSIZE-7) {
0N/A *windir = 0;
0N/A } else {
0N/A strcat(windir, "\\Fonts");
0N/A }
0N/A
0N/A strcpy(fontpath,sysdir);
0N/A if (stricmp(sysdir,windir)) {
0N/A strcat(fontpath,";");
0N/A strcat(fontpath,windir);
0N/A }
0N/A
0N/A return JNU_NewStringPlatform(env, fontpath);
0N/A}
0N/A
0N/A/* The code below is used to obtain information from the windows font APIS
0N/A * and registry on which fonts are available and what font files hold those
0N/A * fonts. The results are used to speed font lookup.
0N/A */
0N/A
0N/Atypedef struct GdiFontMapInfo {
0N/A JNIEnv *env;
0N/A jstring family;
0N/A jobject fontToFamilyMap;
0N/A jobject familyToFontListMap;
0N/A jobject list;
0N/A jmethodID putMID;
0N/A jmethodID containsKeyMID;
0N/A jclass arrayListClass;
0N/A jmethodID arrayListCtr;
0N/A jmethodID addMID;
0N/A jmethodID toLowerCaseMID;
0N/A jobject locale;
0N/A} GdiFontMapInfo;
0N/A
0N/A/* IS_NT means NT or later OSes which support Unicode.
0N/A * We have to painfully deal with the ASCII and non-ASCII case we
0N/A * we really want to get the font names as unicode wherever possible.
0N/A * UNICODE_OS is 0 to mean uninitialised, 1 to mean not a unicode OS,
0N/A * 2 to mean a unicode OS.
0N/A */
0N/A
0N/A#define UC_UNKNOWN 0
0N/A#define UC_NO 1
0N/A#define UC_YES 2
0N/Astatic int UNICODE_OS = UC_UNKNOWN;
0N/Astatic int GetOSVersion () {
0N/A OSVERSIONINFO vinfo;
0N/A vinfo.dwOSVersionInfoSize = sizeof(vinfo);
0N/A GetVersionEx(&vinfo);
0N/A if ((int)vinfo.dwMajorVersion > 4) {
0N/A UNICODE_OS = UC_YES;
0N/A } else if ((int)vinfo.dwMajorVersion < 4) {
0N/A UNICODE_OS = UC_NO;
0N/A } else {
0N/A if ((int)vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
0N/A UNICODE_OS = UC_NO;
0N/A } else {
0N/A UNICODE_OS = UC_YES;
0N/A }
0N/A }
0N/A return UNICODE_OS;
0N/A}
0N/A
0N/A#define IS_NT ((UNICODE_OS == UC_UNKNOWN) \
0N/A ? (GetOSVersion() == UC_YES) : (UNICODE_OS == UC_YES))
0N/A
0N/A/* NT is W2K & XP. WIN is Win9x */
0N/Astatic const char FONTKEY_NT[] =
0N/A "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
0N/Astatic const char FONTKEY_WIN[] =
0N/A "Software\\Microsoft\\Windows\\CurrentVersion\\Fonts";
0N/A
0N/A/* Callback for call to EnumFontFamiliesEx in the EnumFamilyNames function.
0N/A * Expects to be called once for each face name in the family specified
0N/A * in the call. We extract the full name for the font which is expected
0N/A * to be in the "system encoding" and create canonical and lower case
0N/A * Java strings for the name which are added to the maps. The lower case
0N/A * name is used as key to the family name value in the font to family map,
0N/A * the canonical name is one of the"list" of members of the family.
0N/A */
0N/Astatic int CALLBACK EnumFontFacesInFamilyProcA(
0N/A ENUMLOGFONTEXA *lpelfe,
0N/A NEWTEXTMETRICEX *lpntme,
0N/A int FontType,
0N/A LPARAM lParam )
0N/A{
0N/A GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
0N/A JNIEnv *env = fmi->env;
0N/A jstring fullname, fullnameLC;
0N/A
752N/A /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
752N/A if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
0N/A return 1;
0N/A }
0N/A
0N/A /* printf("FULL=%s\n",lpelfe->elfFullName);fflush(stdout); */
0N/A
0N/A fullname = JNU_NewStringPlatform(env, lpelfe->elfFullName);
0N/A fullnameLC = (*env)->CallObjectMethod(env, fullname,
0N/A fmi->toLowerCaseMID, fmi->locale);
2439N/A (*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
0N/A (*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
0N/A fmi->putMID, fullnameLC, fmi->family);
0N/A return 1;
0N/A}
0N/A
0N/Atypedef struct CheckFamilyInfo {
0N/A wchar_t *family;
0N/A wchar_t* fullName;
0N/A int isDifferent;
0N/A} CheckFamilyInfo;
0N/A
0N/Astatic int CALLBACK CheckFontFamilyProcW(
0N/A ENUMLOGFONTEXW *lpelfe,
0N/A NEWTEXTMETRICEX *lpntme,
0N/A int FontType,
0N/A LPARAM lParam)
0N/A{
0N/A CheckFamilyInfo *info = (CheckFamilyInfo*)lParam;
0N/A info->isDifferent = wcscmp(lpelfe->elfLogFont.lfFaceName, info->family);
0N/A
0N/A/* if (!info->isDifferent) { */
0N/A/* wprintf(LFor font %s expected family=%s instead got %s\n", */
0N/A/* lpelfe->elfFullName, */
0N/A/* info->family, */
0N/A/* lpelfe->elfLogFont.lfFaceName); */
0N/A/* fflush(stdout); */
0N/A/* } */
0N/A return 0;
0N/A}
0N/A
0N/Astatic int DifferentFamily(wchar_t *family, wchar_t* fullName) {
0N/A LOGFONTW lfw;
0N/A CheckFamilyInfo info;
0N/A
0N/A /* If fullName can't be stored in the struct, assume correct family */
0N/A if (wcslen((LPWSTR)fullName) >= LF_FACESIZE) {
0N/A return 0;
0N/A }
0N/A
0N/A memset(&info, 0, sizeof(CheckFamilyInfo));
0N/A info.family = family;
0N/A info.fullName = fullName;
0N/A info.isDifferent = 0;
0N/A
0N/A memset(&lfw, 0, sizeof(lfw));
0N/A wcscpy(lfw.lfFaceName, fullName);
0N/A lfw.lfCharSet = DEFAULT_CHARSET;
0N/A EnumFontFamiliesExW(GetDC(NULL), &lfw,
0N/A (FONTENUMPROCW)CheckFontFamilyProcW,
0N/A (LPARAM)(&info), 0L);
0N/A
0N/A return info.isDifferent;
0N/A}
0N/A
0N/Astatic int CALLBACK EnumFontFacesInFamilyProcW(
0N/A ENUMLOGFONTEXW *lpelfe,
0N/A NEWTEXTMETRICEX *lpntme,
0N/A int FontType,
0N/A LPARAM lParam)
0N/A{
0N/A GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
0N/A JNIEnv *env = fmi->env;
0N/A jstring fullname, fullnameLC;
0N/A
752N/A /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
752N/A if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
0N/A return 1;
0N/A }
0N/A
0N/A /* Windows has font aliases and so may enumerate fonts from
0N/A * the aliased family if any actual font of that family is installed.
0N/A * To protect against it ignore fonts which aren't enumerated under
0N/A * their true family.
0N/A */
0N/A if (DifferentFamily(lpelfe->elfLogFont.lfFaceName,
0N/A lpelfe->elfFullName)) {
0N/A return 1;
0N/A }
0N/A
0N/A fullname = (*env)->NewString(env, lpelfe->elfFullName,
4063N/A (jsize)wcslen((LPWSTR)lpelfe->elfFullName));
0N/A fullnameLC = (*env)->CallObjectMethod(env, fullname,
0N/A fmi->toLowerCaseMID, fmi->locale);
2439N/A (*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
0N/A (*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
0N/A fmi->putMID, fullnameLC, fmi->family);
0N/A return 1;
0N/A}
0N/A
0N/A/* Callback for EnumFontFamiliesEx in populateFontFileNameMap.
0N/A * Expects to be called for every charset of every font family.
0N/A * If this is the first time we have been called for this family,
0N/A * add a new mapping to the familyToFontListMap from this family to a
0N/A * list of its members. To populate that list, further enumerate all faces
0N/A * in this family for the matched charset. This assumes that all fonts
0N/A * in a family support the same charset, which is a fairly safe assumption
0N/A * and saves time as the call we make here to EnumFontFamiliesEx will
0N/A * enumerate the members of this family just once each.
0N/A * Because we set fmi->list to be the newly created list the call back
0N/A * can safely add to that list without a search.
0N/A */
0N/Astatic int CALLBACK EnumFamilyNamesA(
0N/A ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */
0N/A NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
0N/A int FontType, /* type of font */
0N/A LPARAM lParam) /* application-defined data */
0N/A{
0N/A GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
0N/A JNIEnv *env = fmi->env;
0N/A jstring familyLC;
0N/A LOGFONTA lfa;
0N/A
752N/A /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
752N/A if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
0N/A return 1;
0N/A }
0N/A
0N/A /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
0N/A * Once using their normal name, and again preceded by '@'. These appear
0N/A * in font lists in some windows apps, such as wordpad. We don't want
0N/A * these so we skip any font where the first character is '@'
0N/A */
0N/A if (lpelfe->elfLogFont.lfFaceName[0] == '@') {
0N/A return 1;
0N/A }
0N/A fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName);
0N/A familyLC = (*env)->CallObjectMethod(env, fmi->family,
0N/A fmi->toLowerCaseMID, fmi->locale);
0N/A /* check if already seen this family with a different charset */
0N/A if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
0N/A fmi->containsKeyMID, familyLC)) {
0N/A return 1;
0N/A }
0N/A fmi->list = (*env)->NewObject(env,
0N/A fmi->arrayListClass, fmi->arrayListCtr, 4);
0N/A
0N/A (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
0N/A fmi->putMID, familyLC, fmi->list);
0N/A
0N/A/* printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */
0N/A
0N/A memset(&lfa, 0, sizeof(lfa));
0N/A strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName);
0N/A lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet;
0N/A EnumFontFamiliesExA(GetDC(NULL), &lfa,
0N/A (FONTENUMPROCA)EnumFontFacesInFamilyProcA,
0N/A lParam, 0L);
0N/A return 1;
0N/A}
0N/A
0N/Astatic int CALLBACK EnumFamilyNamesW(
0N/A ENUMLOGFONTEXW *lpelfe, /* pointer to logical-font data */
0N/A NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
0N/A int FontType, /* type of font */
0N/A LPARAM lParam ) /* application-defined data */
0N/A{
0N/A GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
0N/A JNIEnv *env = fmi->env;
0N/A jstring familyLC;
4063N/A size_t slen;
0N/A LOGFONTW lfw;
0N/A
752N/A /* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
752N/A if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
0N/A return 1;
0N/A }
0N/A/* wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */
0N/A/* lpelfe->elfLogFont.lfFaceName, */
0N/A/* lpelfe->elfLogFont.lfCharSet, */
0N/A/* lpelfe->elfFullName); */
0N/A/* fflush(stdout); */
0N/A
0N/A /* Windows lists fonts which have a vmtx (vertical metrics) table twice.
0N/A * Once using their normal name, and again preceded by '@'. These appear
0N/A * in font lists in some windows apps, such as wordpad. We don't want
0N/A * these so we skip any font where the first character is '@'
0N/A */
0N/A if (lpelfe->elfLogFont.lfFaceName[0] == L'@') {
0N/A return 1;
0N/A }
0N/A slen = wcslen(lpelfe->elfLogFont.lfFaceName);
4063N/A fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen);
0N/A familyLC = (*env)->CallObjectMethod(env, fmi->family,
0N/A fmi->toLowerCaseMID, fmi->locale);
0N/A /* check if already seen this family with a different charset */
0N/A if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
0N/A fmi->containsKeyMID, familyLC)) {
0N/A return 1;
0N/A }
0N/A fmi->list = (*env)->NewObject(env,
0N/A fmi->arrayListClass, fmi->arrayListCtr, 4);
0N/A
0N/A (*env)->CallObjectMethod(env, fmi->familyToFontListMap,
0N/A fmi->putMID, familyLC, fmi->list);
0N/A
0N/A memset(&lfw, 0, sizeof(lfw));
0N/A wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName);
0N/A lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet;
0N/A EnumFontFamiliesExW(GetDC(NULL), &lfw,
0N/A (FONTENUMPROCW)EnumFontFacesInFamilyProcW,
0N/A lParam, 0L);
0N/A return 1;
0N/A}
0N/A
0N/A
0N/A/* It looks like TrueType fonts have " (TrueType)" tacked on the end of their
0N/A * name, so we can try to use that to distinguish TT from other fonts.
0N/A * However if a program "installed" a font in the registry the key may
0N/A * not include that. We could also try to "pass" fonts which have no "(..)"
0N/A * at the end. But that turns out to pass a few .FON files that MS supply.
0N/A * If there's no parenthesised type string, we could next try to infer
0N/A * the file type from the file name extension. Since the MS entries that
0N/A * have no type string are very few, and have odd names like "MS-DOS CP 437"
0N/A * and would never return a Java Font anyway its currently OK to put these
0N/A * in the font map, although clearly the returned names must never percolate
0N/A * up into a list of available fonts returned to the application.
0N/A * Additionally for TTC font files the key looks like
0N/A * Font 1 & Font 2 (TrueType)
0N/A * or sometimes even :
0N/A * Font 1 & Font 2 & Font 3 (TrueType)
0N/A * Also if a Font has a name for this locale that name also
0N/A * exists in the registry using the appropriate platform encoding.
0N/A * What do we do then?
752N/A *
752N/A * Note: OpenType fonts seems to have " (TrueType)" suffix on Vista
752N/A * but " (OpenType)" on XP.
0N/A */
0N/A
752N/Astatic BOOL RegistryToBaseTTNameA(LPSTR name) {
0N/A static const char TTSUFFIX[] = " (TrueType)";
752N/A static const char OTSUFFIX[] = " (OpenType)";
4063N/A size_t TTSLEN = strlen(TTSUFFIX);
752N/A char *suffix;
0N/A
4063N/A size_t len = strlen(name);
0N/A if (len == 0) {
0N/A return FALSE;
0N/A }
0N/A if (name[len-1] != ')') {
0N/A return FALSE;
0N/A }
0N/A if (len <= TTSLEN) {
0N/A return FALSE;
0N/A }
752N/A
752N/A /* suffix length is the same for truetype and opentype fonts */
752N/A suffix = name + len - TTSLEN;
752N/A if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) {
752N/A suffix[0] = '\0'; /* truncate name */
0N/A return TRUE;
0N/A }
752N/A return FALSE;
0N/A}
0N/A
0N/Astatic BOOL RegistryToBaseTTNameW(LPWSTR name) {
0N/A static const wchar_t TTSUFFIX[] = L" (TrueType)";
752N/A static const wchar_t OTSUFFIX[] = L" (OpenType)";
4063N/A size_t TTSLEN = wcslen(TTSUFFIX);
752N/A wchar_t *suffix;
0N/A
4063N/A size_t len = wcslen(name);
0N/A if (len == 0) {
0N/A return FALSE;
0N/A }
0N/A if (name[len-1] != L')') {
0N/A return FALSE;
0N/A }
0N/A if (len <= TTSLEN) {
0N/A return FALSE;
0N/A }
752N/A /* suffix length is the same for truetype and opentype fonts */
752N/A suffix = name + (len - TTSLEN);
752N/A if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) {
752N/A suffix[0] = L'\0'; /* truncate name */
0N/A return TRUE;
0N/A }
752N/A return FALSE;
0N/A}
0N/A
0N/Astatic void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,
0N/A LPCSTR name, LPCSTR data) {
0N/A LPSTR ptr1, ptr2;
0N/A jstring fontStr;
0N/A JNIEnv *env = fmi->env;
4063N/A size_t dslen = strlen(data);
0N/A jstring fileStr = JNU_NewStringPlatform(env, data);
0N/A
0N/A /* TTC or ttc means it may be a collection. Need to parse out
0N/A * multiple font face names separated by " & "
0N/A * By only doing this for fonts which look like collections based on
0N/A * file name we are adhering to MS recommendations for font file names
0N/A * so it seems that we can be sure that this identifies precisely
0N/A * the MS-supplied truetype collections.
0N/A * This avoids any potential issues if a TTF file happens to have
0N/A * a & in the font name (I can't find anything which prohibits this)
0N/A * and also means we only parse the key in cases we know to be
0N/A * worthwhile.
0N/A */
0N/A if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') &&
0N/A (ptr1 = strstr(name, " & ")) != NULL) {
0N/A ptr1+=3;
0N/A while (ptr1 >= name) { /* marginally safer than while (true) */
0N/A while ((ptr2 = strstr(ptr1, " & ")) != NULL) {
0N/A ptr1 = ptr2+3;
0N/A }
0N/A fontStr = JNU_NewStringPlatform(env, ptr1);
0N/A fontStr = (*env)->CallObjectMethod(env, fontStr,
0N/A fmi->toLowerCaseMID,
0N/A fmi->locale);
0N/A (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
0N/A fontStr, fileStr);
0N/A if (ptr1 == name) {
0N/A break;
0N/A } else {
0N/A *(ptr1-3) ='\0';
0N/A ptr1 = (LPSTR)name;
0N/A }
0N/A }
0N/A } else {
0N/A fontStr = JNU_NewStringPlatform(env, name);
0N/A fontStr = (*env)->CallObjectMethod(env, fontStr,
0N/A fmi->toLowerCaseMID, fmi->locale);
0N/A (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
0N/A fontStr, fileStr);
0N/A }
0N/A}
0N/A
0N/Astatic void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
0N/A LPWSTR name, LPWSTR data) {
0N/A
0N/A wchar_t *ptr1, *ptr2;
0N/A jstring fontStr;
0N/A JNIEnv *env = fmi->env;
4063N/A size_t dslen = wcslen(data);
4063N/A jstring fileStr = (*env)->NewString(env, data, (jsize)dslen);
0N/A
0N/A /* TTC or ttc means it may be a collection. Need to parse out
0N/A * multiple font face names separated by " & "
0N/A * By only doing this for fonts which look like collections based on
0N/A * file name we are adhering to MS recommendations for font file names
0N/A * so it seems that we can be sure that this identifies precisely
0N/A * the MS-supplied truetype collections.
0N/A * This avoids any potential issues if a TTF file happens to have
0N/A * a & in the font name (I can't find anything which prohibits this)
0N/A * and also means we only parse the key in cases we know to be
0N/A * worthwhile.
0N/A */
0N/A
0N/A if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') &&
0N/A (ptr1 = wcsstr(name, L" & ")) != NULL) {
0N/A ptr1+=3;
0N/A while (ptr1 >= name) { /* marginally safer than while (true) */
0N/A while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) {
0N/A ptr1 = ptr2+3;
0N/A }
4063N/A fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1));
0N/A fontStr = (*env)->CallObjectMethod(env, fontStr,
0N/A fmi->toLowerCaseMID,
0N/A fmi->locale);
0N/A (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
0N/A fontStr, fileStr);
0N/A if (ptr1 == name) {
0N/A break;
0N/A } else {
0N/A *(ptr1-3) = L'\0';
0N/A ptr1 = name;
0N/A }
0N/A }
0N/A } else {
4063N/A fontStr = (*env)->NewString(env, name, (jsize)wcslen(name));
0N/A fontStr = (*env)->CallObjectMethod(env, fontStr,
0N/A fmi->toLowerCaseMID, fmi->locale);
0N/A (*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
0N/A fontStr, fileStr);
0N/A }
0N/A}
0N/A
0N/A/* Obtain all the fontname -> filename mappings.
0N/A * This is called once and the results returned to Java code which can
0N/A * use it for lookups to reduce or avoid the need to search font files.
0N/A */
0N/AJNIEXPORT void JNICALL
1686N/AJava_sun_awt_Win32FontManager_populateFontFileNameMap0
0N/A(JNIEnv *env, jclass obj, jobject fontToFileMap,
0N/A jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
0N/A{
0N/A#define MAX_BUFFER (FILENAME_MAX+1)
0N/A const wchar_t wname[MAX_BUFFER];
0N/A const char cname[MAX_BUFFER];
0N/A const char data[MAX_BUFFER];
0N/A
0N/A DWORD type;
0N/A LONG ret;
0N/A HKEY hkeyFonts;
0N/A DWORD dwNameSize;
0N/A DWORD dwDataValueSize;
0N/A DWORD nval;
0N/A LPCSTR fontKeyName;
0N/A DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen;
0N/A DWORD numValues = 0;
0N/A jclass classID;
0N/A jmethodID putMID;
0N/A GdiFontMapInfo fmi;
0N/A
0N/A /* Check we were passed all the maps we need, and do lookup of
0N/A * methods for JNI up-calls
0N/A */
0N/A if (fontToFileMap == NULL ||
0N/A fontToFamilyMap == NULL ||
0N/A familyToFontListMap == NULL) {
0N/A return;
0N/A }
0N/A classID = (*env)->FindClass(env, "java/util/HashMap");
0N/A if (classID == NULL) {
0N/A return;
0N/A }
0N/A putMID = (*env)->GetMethodID(env, classID, "put",
0N/A "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
0N/A if (putMID == NULL) {
0N/A return;
0N/A }
0N/A
0N/A fmi.env = env;
0N/A fmi.fontToFamilyMap = fontToFamilyMap;
0N/A fmi.familyToFontListMap = familyToFontListMap;
0N/A fmi.putMID = putMID;
0N/A fmi.locale = locale;
0N/A fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey",
0N/A "(Ljava/lang/Object;)Z");
0N/A if (fmi.containsKeyMID == NULL) {
0N/A return;
0N/A }
0N/A
0N/A fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList");
0N/A if (fmi.arrayListClass == NULL) {
0N/A return;
0N/A }
0N/A fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass,
0N/A "<init>", "(I)V");
0N/A if (fmi.arrayListCtr == NULL) {
0N/A return;
0N/A }
0N/A fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass,
0N/A "add", "(Ljava/lang/Object;)Z");
0N/A if (fmi.addMID == NULL) {
0N/A return;
0N/A }
0N/A classID = (*env)->FindClass(env, "java/lang/String");
0N/A if (classID == NULL) {
0N/A return;
0N/A }
0N/A fmi.toLowerCaseMID =
0N/A (*env)->GetMethodID(env, classID, "toLowerCase",
0N/A "(Ljava/util/Locale;)Ljava/lang/String;");
0N/A if (fmi.toLowerCaseMID == NULL) {
0N/A return;
0N/A }
0N/A
0N/A /* Enumerate fonts via GDI to build maps of fonts and families */
0N/A if (IS_NT) {
0N/A LOGFONTW lfw;
0N/A memset(&lfw, 0, sizeof(lfw));
0N/A lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */
0N/A wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */
0N/A EnumFontFamiliesExW(GetDC(NULL), &lfw,
0N/A (FONTENUMPROCW)EnumFamilyNamesW,
0N/A (LPARAM)(&fmi), 0L);
0N/A } else {
0N/A LOGFONT lfa;
0N/A memset(&lfa, 0, sizeof(lfa));
0N/A lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */
0N/A strcpy(lfa.lfFaceName, ""); /* one face per family */
0N/A ret = EnumFontFamiliesExA(GetDC(NULL), &lfa,
0N/A (FONTENUMPROCA)EnumFamilyNamesA,
0N/A (LPARAM)(&fmi), 0L);
0N/A }
0N/A
0N/A /* Use the windows registry to map font names to files */
0N/A fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN;
0N/A ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
0N/A fontKeyName, 0L, KEY_READ, &hkeyFonts);
0N/A if (ret != ERROR_SUCCESS) {
0N/A return;
0N/A }
0N/A
0N/A if (IS_NT) {
0N/A ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
0N/A &dwNumValues, &dwMaxValueNameLen,
0N/A &dwMaxValueDataLen, NULL, NULL);
0N/A } else {
0N/A ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
0N/A &dwNumValues, &dwMaxValueNameLen,
0N/A &dwMaxValueDataLen, NULL, NULL);
0N/A }
0N/A if (ret != ERROR_SUCCESS ||
0N/A dwMaxValueNameLen >= MAX_BUFFER ||
0N/A dwMaxValueDataLen >= MAX_BUFFER) {
0N/A RegCloseKey(hkeyFonts);
0N/A return;
0N/A }
0N/A for (nval = 0; nval < dwNumValues; nval++ ) {
0N/A dwNameSize = MAX_BUFFER;
0N/A dwDataValueSize = MAX_BUFFER;
0N/A if (IS_NT) {
0N/A ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
0N/A NULL, &type, (LPBYTE)data, &dwDataValueSize);
0N/A } else {
0N/A ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize,
0N/A NULL, &type, (LPBYTE)data, &dwDataValueSize);
0N/A }
0N/A if (ret != ERROR_SUCCESS) {
0N/A break;
0N/A }
0N/A if (type != REG_SZ) { /* REG_SZ means a null-terminated string */
0N/A continue;
0N/A }
0N/A if (IS_NT) {
0N/A if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
752N/A /* If the filename ends with ".ttf" or ".otf" also accept it.
0N/A * Not expecting to need to do this for .ttc files.
0N/A * Also note this code is not mirrored in the "A" (win9x) path.
0N/A */
0N/A LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
752N/A if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
752N/A && (wcsicmp(dot, L".otf") != 0))) {
0N/A continue; /* not a TT font... */
0N/A }
0N/A }
0N/A registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
0N/A } else {
752N/A if (!RegistryToBaseTTNameA((LPSTR)cname)) {
0N/A continue; /* not a TT font... */
0N/A }
0N/A registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data);
0N/A }
0N/A }
0N/A RegCloseKey(hkeyFonts);
0N/A}