Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/font/fontpath.c
32287 views
1
/*
2
* Copyright (c) 1998, 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
#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
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
{
179
CheckFamilyInfo *info = (CheckFamilyInfo*)lParam;
180
info->isDifferent = wcscmp(lpelfe->elfLogFont.lfFaceName, info->family);
181
182
/* if (!info->isDifferent) { */
183
/* wprintf(LFor font %s expected family=%s instead got %s\n", */
184
/* lpelfe->elfFullName, */
185
/* info->family, */
186
/* lpelfe->elfLogFont.lfFaceName); */
187
/* fflush(stdout); */
188
/* } */
189
return 0;
190
}
191
192
/* This HDC is initialised and released in the populate family map
193
* JNI entry point, and used within the call which would otherwise
194
* create many DCs.
195
*/
196
static HDC screenDC = NULL;
197
198
static int DifferentFamily(wchar_t *family, wchar_t* fullName) {
199
LOGFONTW lfw;
200
CheckFamilyInfo info;
201
202
/* If fullName can't be stored in the struct, assume correct family */
203
if (wcslen((LPWSTR)fullName) >= LF_FACESIZE) {
204
return 0;
205
}
206
207
memset(&info, 0, sizeof(CheckFamilyInfo));
208
info.family = family;
209
info.fullName = fullName;
210
info.isDifferent = 0;
211
212
memset(&lfw, 0, sizeof(lfw));
213
wcscpy(lfw.lfFaceName, fullName);
214
lfw.lfCharSet = DEFAULT_CHARSET;
215
EnumFontFamiliesExW(screenDC, &lfw,
216
(FONTENUMPROCW)CheckFontFamilyProcW,
217
(LPARAM)(&info), 0L);
218
219
return info.isDifferent;
220
}
221
222
static int CALLBACK EnumFontFacesInFamilyProcW(
223
ENUMLOGFONTEXW *lpelfe,
224
NEWTEXTMETRICEX *lpntme,
225
int FontType,
226
LPARAM lParam)
227
{
228
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
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
*/
273
static int CALLBACK EnumFamilyNamesA(
274
ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */
275
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
276
int FontType, /* type of font */
277
LPARAM lParam) /* application-defined data */
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
{
335
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
336
JNIEnv *env = fmi->env;
337
jstring familyLC;
338
size_t slen;
339
LOGFONTW lfw;
340
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
398
* have no type string are very few, and have odd names like "MS-DOS CP 437"
399
* and would never return a Java Font anyway its currently OK to put these
400
* in the font map, although clearly the returned names must never percolate
401
* up into a list of available fonts returned to the application.
402
* Additionally for TTC font files the key looks like
403
* Font 1 & Font 2 (TrueType)
404
* or sometimes even :
405
* Font 1 & Font 2 & Font 3 (TrueType)
406
* Also if a Font has a name for this locale that name also
407
* exists in the registry using the appropriate platform encoding.
408
* What do we do then?
409
*
410
* Note: OpenType fonts seems to have " (TrueType)" suffix on Vista
411
* but " (OpenType)" on XP.
412
*/
413
414
static BOOL RegistryToBaseTTNameA(LPSTR name) {
415
static const char TTSUFFIX[] = " (TrueType)";
416
static const char OTSUFFIX[] = " (OpenType)";
417
size_t TTSLEN = strlen(TTSUFFIX);
418
char *suffix;
419
420
size_t len = strlen(name);
421
if (len == 0) {
422
return FALSE;
423
}
424
if (name[len-1] != ')') {
425
return FALSE;
426
}
427
if (len <= TTSLEN) {
428
return FALSE;
429
}
430
431
/* suffix length is the same for truetype and opentype fonts */
432
suffix = name + len - TTSLEN;
433
if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) {
434
suffix[0] = '\0'; /* truncate name */
435
return TRUE;
436
}
437
return FALSE;
438
}
439
440
static BOOL RegistryToBaseTTNameW(LPWSTR name) {
441
static const wchar_t TTSUFFIX[] = L" (TrueType)";
442
static const wchar_t OTSUFFIX[] = L" (OpenType)";
443
size_t TTSLEN = wcslen(TTSUFFIX);
444
wchar_t *suffix;
445
446
size_t len = wcslen(name);
447
if (len == 0) {
448
return FALSE;
449
}
450
if (name[len-1] != L')') {
451
return FALSE;
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];
600
601
DWORD type;
602
LONG ret;
603
HKEY hkeyFonts;
604
DWORD dwNameSize;
605
DWORD dwDataValueSize;
606
DWORD nval;
607
LPCSTR fontKeyName;
608
DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen;
609
DWORD numValues = 0;
610
jclass classID;
611
jmethodID putMID;
612
GdiFontMapInfo fmi;
613
614
/* Check we were passed all the maps we need, and do lookup of
615
* methods for JNI up-calls
616
*/
617
if (fontToFileMap == NULL ||
618
fontToFamilyMap == NULL ||
619
familyToFontListMap == NULL) {
620
return;
621
}
622
classID = (*env)->FindClass(env, "java/util/HashMap");
623
if (classID == NULL) {
624
return;
625
}
626
putMID = (*env)->GetMethodID(env, classID, "put",
627
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
628
if (putMID == NULL) {
629
return;
630
}
631
632
fmi.env = env;
633
fmi.fontToFamilyMap = fontToFamilyMap;
634
fmi.familyToFontListMap = familyToFontListMap;
635
fmi.putMID = putMID;
636
fmi.locale = locale;
637
fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey",
638
"(Ljava/lang/Object;)Z");
639
if (fmi.containsKeyMID == NULL) {
640
return;
641
}
642
643
fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList");
644
if (fmi.arrayListClass == NULL) {
645
return;
646
}
647
fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass,
648
"<init>", "(I)V");
649
if (fmi.arrayListCtr == NULL) {
650
return;
651
}
652
fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass,
653
"add", "(Ljava/lang/Object;)Z");
654
if (fmi.addMID == NULL) {
655
return;
656
}
657
classID = (*env)->FindClass(env, "java/lang/String");
658
if (classID == NULL) {
659
return;
660
}
661
fmi.toLowerCaseMID =
662
(*env)->GetMethodID(env, classID, "toLowerCase",
663
"(Ljava/util/Locale;)Ljava/lang/String;");
664
if (fmi.toLowerCaseMID == NULL) {
665
return;
666
}
667
668
screenDC = GetDC(NULL);
669
if (screenDC == NULL) {
670
return;
671
}
672
/* Enumerate fonts via GDI to build maps of fonts and families */
673
if (IS_NT) {
674
LOGFONTW lfw;
675
memset(&lfw, 0, sizeof(lfw));
676
lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */
677
wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */
678
EnumFontFamiliesExW(screenDC, &lfw,
679
(FONTENUMPROCW)EnumFamilyNamesW,
680
(LPARAM)(&fmi), 0L);
681
} else {
682
LOGFONT lfa;
683
memset(&lfa, 0, sizeof(lfa));
684
lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */
685
strcpy(lfa.lfFaceName, ""); /* one face per family */
686
ret = EnumFontFamiliesExA(screenDC, &lfa,
687
(FONTENUMPROCA)EnumFamilyNamesA,
688
(LPARAM)(&fmi), 0L);
689
}
690
691
/* Use the windows registry to map font names to files */
692
fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN;
693
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
694
fontKeyName, 0L, KEY_READ, &hkeyFonts);
695
if (ret != ERROR_SUCCESS) {
696
ReleaseDC(NULL, screenDC);
697
screenDC = NULL;
698
return;
699
}
700
701
if (IS_NT) {
702
ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
703
&dwNumValues, &dwMaxValueNameLen,
704
&dwMaxValueDataLen, NULL, NULL);
705
} else {
706
ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
707
&dwNumValues, &dwMaxValueNameLen,
708
&dwMaxValueDataLen, NULL, NULL);
709
}
710
if (ret != ERROR_SUCCESS ||
711
dwMaxValueNameLen >= MAX_BUFFER ||
712
dwMaxValueDataLen >= MAX_BUFFER) {
713
RegCloseKey(hkeyFonts);
714
ReleaseDC(NULL, screenDC);
715
screenDC = NULL;
716
return;
717
}
718
for (nval = 0; nval < dwNumValues; nval++ ) {
719
dwNameSize = MAX_BUFFER;
720
dwDataValueSize = MAX_BUFFER;
721
if (IS_NT) {
722
ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
723
NULL, &type, (LPBYTE)data, &dwDataValueSize);
724
} else {
725
ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize,
726
NULL, &type, (LPBYTE)data, &dwDataValueSize);
727
}
728
if (ret != ERROR_SUCCESS) {
729
break;
730
}
731
if (type != REG_SZ) { /* REG_SZ means a null-terminated string */
732
continue;
733
}
734
if (IS_NT) {
735
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
736
/* If the filename ends with ".ttf" or ".otf" also accept it.
737
* Not expecting to need to do this for .ttc files.
738
* Also note this code is not mirrored in the "A" (win9x) path.
739
*/
740
LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
741
if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
742
&& (wcsicmp(dot, L".otf") != 0))) {
743
continue; /* not a TT font... */
744
}
745
}
746
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
747
} else {
748
if (!RegistryToBaseTTNameA((LPSTR)cname)) {
749
continue; /* not a TT font... */
750
}
751
registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data);
752
}
753
}
754
RegCloseKey(hkeyFonts);
755
ReleaseDC(NULL, screenDC);
756
screenDC = NULL;
757
}
758
759