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