author | erikj |
Tue, 12 Sep 2017 19:03:39 +0200 | |
changeset 47216 | 71c04702a3d5 |
parent 40423 | jdk/src/java.desktop/windows/native/libfontmanager/fontpath.c@6b56a2890514 |
child 54243 | 0b9fb3cfb6f2 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
39864 | 2 |
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
#include <windows.h> |
|
27 |
#include <stdio.h> |
|
28 |
||
29 |
#include <jni.h> |
|
30 |
#include <jni_util.h> |
|
3928 | 31 |
#include <sun_awt_Win32FontManager.h> |
2 | 32 |
|
33 |
#define BSIZE (max(512, MAX_PATH+1)) |
|
34 |
||
39864 | 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) |
|
2 | 49 |
|
3928 | 50 |
JNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1) |
2 | 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 |
||
39864 | 105 |
/* Registry entry for fonts */ |
2 | 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 |
||
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
134 |
/* This HDC is initialised and released in the populate family map |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
135 |
* JNI entry point, and used within the call which would otherwise |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
136 |
* create many DCs. |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
137 |
*/ |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
138 |
static HDC screenDC = NULL; |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
139 |
|
2 | 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; |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
157 |
EnumFontFamiliesExW(screenDC, &lfw, |
2 | 158 |
(FONTENUMPROCW)CheckFontFamilyProcW, |
159 |
(LPARAM)(&info), 0L); |
|
160 |
||
161 |
return info.isDifferent; |
|
162 |
} |
|
163 |
||
39864 | 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 |
*/ |
|
2 | 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 |
||
39864 | 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 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
195 |
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
196 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 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, |
|
9460 | 211 |
(jsize)wcslen((LPWSTR)lpelfe->elfFullName)); |
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
212 |
if (fullname == NULL) { |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
213 |
(*env)->ExceptionClear(env); |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
214 |
return 1; |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
215 |
} |
39864 | 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 |
||
2 | 224 |
fullnameLC = (*env)->CallObjectMethod(env, fullname, |
225 |
fmi->toLowerCaseMID, fmi->locale); |
|
39864 | 226 |
/* Delete the created reference after its usage */ |
227 |
DeleteLocalReference(env, fullname); |
|
228 |
if ((*env)->ExceptionCheck(env)) { |
|
229 |
return 0; |
|
230 |
} |
|
231 |
||
2 | 232 |
(*env)->CallObjectMethod(env, fmi->fontToFamilyMap, |
233 |
fmi->putMID, fullnameLC, fmi->family); |
|
39864 | 234 |
/* Delete the created reference after its usage */ |
235 |
DeleteLocalReference(env, fullnameLC); |
|
236 |
if ((*env)->ExceptionCheck(env)) { |
|
237 |
return 0; |
|
238 |
} |
|
239 |
||
2 | 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; |
|
9460 | 264 |
size_t slen; |
2 | 265 |
LOGFONTW lfw; |
40423
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
266 |
jboolean mapHasKey; |
2 | 267 |
|
39864 | 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 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
281 |
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */ |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
282 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 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); |
|
9460 | 300 |
fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen); |
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
301 |
if (fmi->family == NULL) { |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
302 |
(*env)->ExceptionClear(env); |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
303 |
return 1; |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
304 |
} |
39864 | 305 |
|
2 | 306 |
familyLC = (*env)->CallObjectMethod(env, fmi->family, |
307 |
fmi->toLowerCaseMID, fmi->locale); |
|
39864 | 308 |
/* Delete the created reference after its usage */ |
309 |
if ((*env)->ExceptionCheck(env)) { |
|
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
310 |
DeleteLocalReference(env, fmi->family); |
39864 | 311 |
return 0; |
312 |
} |
|
313 |
||
2 | 314 |
/* check if already seen this family with a different charset */ |
40423
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
315 |
mapHasKey = (*env)->CallBooleanMethod(env, |
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
316 |
fmi->familyToFontListMap, |
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
317 |
fmi->containsKeyMID, |
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
318 |
familyLC); |
39864 | 319 |
if ((*env)->ExceptionCheck(env)) { |
320 |
/* Delete the created references before return */ |
|
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
321 |
DeleteLocalReference(env, fmi->family); |
39864 | 322 |
DeleteLocalReference(env, familyLC); |
323 |
return 0; |
|
324 |
} else if (mapHasKey) { |
|
325 |
/* Delete the created references before return */ |
|
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
326 |
DeleteLocalReference(env, fmi->family); |
39864 | 327 |
DeleteLocalReference(env, familyLC); |
2 | 328 |
return 1; |
329 |
} |
|
39864 | 330 |
|
2 | 331 |
fmi->list = (*env)->NewObject(env, |
332 |
fmi->arrayListClass, fmi->arrayListCtr, 4); |
|
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
333 |
if (fmi->list == NULL) { |
39864 | 334 |
/* Delete the created references before return */ |
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
335 |
DeleteLocalReference(env, fmi->family); |
39864 | 336 |
DeleteLocalReference(env, familyLC); |
337 |
return 0; |
|
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
338 |
} |
39864 | 339 |
|
2 | 340 |
(*env)->CallObjectMethod(env, fmi->familyToFontListMap, |
341 |
fmi->putMID, familyLC, fmi->list); |
|
39864 | 342 |
/* Delete the created reference after its usage */ |
343 |
DeleteLocalReference(env, familyLC); |
|
344 |
if ((*env)->ExceptionCheck(env)) { |
|
345 |
/* Delete the created reference before return */ |
|
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
346 |
DeleteLocalReference(env, fmi->family); |
39864 | 347 |
DeleteLocalReference(env, fmi->list); |
348 |
return 0; |
|
349 |
} |
|
2 | 350 |
|
351 |
memset(&lfw, 0, sizeof(lfw)); |
|
352 |
wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName); |
|
353 |
lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet; |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
354 |
EnumFontFamiliesExW(screenDC, &lfw, |
2 | 355 |
(FONTENUMPROCW)EnumFontFacesInFamilyProcW, |
356 |
lParam, 0L); |
|
39864 | 357 |
|
358 |
/* Delete the created reference after its usage in the enum function */ |
|
39874
bf85c2b8f0e0
8162097: [PIT] A series of closed tests about SunFontManager throw NPE on Windows
prr
parents:
39864
diff
changeset
|
359 |
DeleteLocalReference(env, fmi->family); |
39864 | 360 |
DeleteLocalReference(env, fmi->list); |
2 | 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. |
|
21278 | 369 |
* If there's no parenthesized type string, we could next try to infer |
2 | 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? |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
382 |
* |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
383 |
* Note: OpenType fonts seems to have " (TrueType)" suffix on Vista |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
384 |
* but " (OpenType)" on XP. |
2 | 385 |
*/ |
386 |
static BOOL RegistryToBaseTTNameW(LPWSTR name) { |
|
387 |
static const wchar_t TTSUFFIX[] = L" (TrueType)"; |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
388 |
static const wchar_t OTSUFFIX[] = L" (OpenType)"; |
9460 | 389 |
size_t TTSLEN = wcslen(TTSUFFIX); |
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
390 |
wchar_t *suffix; |
2 | 391 |
|
9460 | 392 |
size_t len = wcslen(name); |
2 | 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 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
402 |
/* suffix length is the same for truetype and opentype fonts */ |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
403 |
suffix = name + (len - TTSLEN); |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
404 |
if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) { |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
405 |
suffix[0] = L'\0'; /* truncate name */ |
2 | 406 |
return TRUE; |
407 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
408 |
return FALSE; |
2 | 409 |
} |
410 |
||
411 |
static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap, |
|
412 |
LPWSTR name, LPWSTR data) { |
|
413 |
||
414 |
wchar_t *ptr1, *ptr2; |
|
415 |
jstring fontStr; |
|
39864 | 416 |
jstring fontStrLC; |
2 | 417 |
JNIEnv *env = fmi->env; |
9460 | 418 |
size_t dslen = wcslen(data); |
419 |
jstring fileStr = (*env)->NewString(env, data, (jsize)dslen); |
|
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
420 |
if (fileStr == NULL) { |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
421 |
(*env)->ExceptionClear(env); |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
422 |
return; |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
423 |
} |
2 | 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 |
} |
|
9460 | 444 |
fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1)); |
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
445 |
if (fontStr == NULL) { |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
446 |
(*env)->ExceptionClear(env); |
39864 | 447 |
/* Delete the created reference before return */ |
448 |
DeleteLocalReference(env, fileStr); |
|
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
449 |
return; |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
450 |
} |
39864 | 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 |
||
2 | 463 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
39864 | 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 |
||
2 | 473 |
if (ptr1 == name) { |
474 |
break; |
|
475 |
} else { |
|
476 |
*(ptr1-3) = L'\0'; |
|
477 |
ptr1 = name; |
|
478 |
} |
|
479 |
} |
|
480 |
} else { |
|
9460 | 481 |
fontStr = (*env)->NewString(env, name, (jsize)wcslen(name)); |
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
482 |
if (fontStr == NULL) { |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
483 |
(*env)->ExceptionClear(env); |
39864 | 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); |
|
23674
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
496 |
return; |
47a4a6183907
8035630: [parfait] JNI exception pending in jdk/src/windows/native/sun/font/fontpath.c
prr
parents:
23010
diff
changeset
|
497 |
} |
39864 | 498 |
|
2 | 499 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
39864 | 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 |
} |
|
2 | 508 |
} |
39864 | 509 |
|
510 |
/* Delete the created reference after its usage */ |
|
511 |
DeleteLocalReference(env, fileStr); |
|
2 | 512 |
} |
513 |
||
514 |
/* Obtain all the fontname -> filename mappings. |
|
515 |
* This is called once and the results returned to Java code which can |
|
516 |
* use it for lookups to reduce or avoid the need to search font files. |
|
517 |
*/ |
|
518 |
JNIEXPORT void JNICALL |
|
3928 | 519 |
Java_sun_awt_Win32FontManager_populateFontFileNameMap0 |
2 | 520 |
(JNIEnv *env, jclass obj, jobject fontToFileMap, |
521 |
jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale) |
|
522 |
{ |
|
523 |
#define MAX_BUFFER (FILENAME_MAX+1) |
|
524 |
const wchar_t wname[MAX_BUFFER]; |
|
525 |
const char data[MAX_BUFFER]; |
|
526 |
||
527 |
DWORD type; |
|
528 |
LONG ret; |
|
529 |
HKEY hkeyFonts; |
|
530 |
DWORD dwNameSize; |
|
531 |
DWORD dwDataValueSize; |
|
532 |
DWORD nval; |
|
533 |
DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen; |
|
534 |
DWORD numValues = 0; |
|
39864 | 535 |
jclass classIDHashMap; |
536 |
jclass classIDString; |
|
2 | 537 |
jmethodID putMID; |
538 |
GdiFontMapInfo fmi; |
|
40423
6b56a2890514
8163177: Fix for 8152971 breaks builds with VS2010
clanger
parents:
39874
diff
changeset
|
539 |
LOGFONTW lfw; |
2 | 540 |
|
541 |
/* Check we were passed all the maps we need, and do lookup of |
|
542 |
* methods for JNI up-calls |
|
543 |
*/ |
|
544 |
if (fontToFileMap == NULL || |
|
545 |
fontToFamilyMap == NULL || |
|
546 |
familyToFontListMap == NULL) { |
|
547 |
return; |
|
548 |
} |
|
39864 | 549 |
classIDHashMap = (*env)->FindClass(env, "java/util/HashMap"); |
550 |
if (classIDHashMap == NULL) { |
|
2 | 551 |
return; |
552 |
} |
|
39864 | 553 |
putMID = (*env)->GetMethodID(env, classIDHashMap, "put", |
2 | 554 |
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); |
555 |
if (putMID == NULL) { |
|
556 |
return; |
|
557 |
} |
|
558 |
||
559 |
fmi.env = env; |
|
560 |
fmi.fontToFamilyMap = fontToFamilyMap; |
|
561 |
fmi.familyToFontListMap = familyToFontListMap; |
|
562 |
fmi.putMID = putMID; |
|
563 |
fmi.locale = locale; |
|
39864 | 564 |
fmi.containsKeyMID = (*env)->GetMethodID(env, classIDHashMap, |
565 |
"containsKey", |
|
2 | 566 |
"(Ljava/lang/Object;)Z"); |
567 |
if (fmi.containsKeyMID == NULL) { |
|
568 |
return; |
|
569 |
} |
|
570 |
||
571 |
fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); |
|
572 |
if (fmi.arrayListClass == NULL) { |
|
573 |
return; |
|
574 |
} |
|
575 |
fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass, |
|
576 |
"<init>", "(I)V"); |
|
577 |
if (fmi.arrayListCtr == NULL) { |
|
578 |
return; |
|
579 |
} |
|
580 |
fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass, |
|
581 |
"add", "(Ljava/lang/Object;)Z"); |
|
582 |
if (fmi.addMID == NULL) { |
|
583 |
return; |
|
584 |
} |
|
39864 | 585 |
|
586 |
classIDString = (*env)->FindClass(env, "java/lang/String"); |
|
587 |
if (classIDString == NULL) { |
|
2 | 588 |
return; |
589 |
} |
|
590 |
fmi.toLowerCaseMID = |
|
39864 | 591 |
(*env)->GetMethodID(env, classIDString, "toLowerCase", |
2 | 592 |
"(Ljava/util/Locale;)Ljava/lang/String;"); |
593 |
if (fmi.toLowerCaseMID == NULL) { |
|
594 |
return; |
|
595 |
} |
|
596 |
||
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
597 |
screenDC = GetDC(NULL); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
598 |
if (screenDC == NULL) { |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
599 |
return; |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
600 |
} |
39864 | 601 |
|
2 | 602 |
/* Enumerate fonts via GDI to build maps of fonts and families */ |
39864 | 603 |
memset(&lfw, 0, sizeof(lfw)); |
604 |
lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */ |
|
605 |
wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */ |
|
606 |
EnumFontFamiliesExW(screenDC, &lfw, |
|
607 |
(FONTENUMPROCW)EnumFamilyNamesW, |
|
608 |
(LPARAM)(&fmi), 0L); |
|
2 | 609 |
|
610 |
/* Use the windows registry to map font names to files */ |
|
611 |
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
|
39864 | 612 |
FONTKEY_NT, 0L, KEY_READ, &hkeyFonts); |
2 | 613 |
if (ret != ERROR_SUCCESS) { |
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
614 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
615 |
screenDC = NULL; |
2 | 616 |
return; |
617 |
} |
|
618 |
||
39864 | 619 |
ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL, |
620 |
&dwNumValues, &dwMaxValueNameLen, |
|
621 |
&dwMaxValueDataLen, NULL, NULL); |
|
622 |
||
2 | 623 |
if (ret != ERROR_SUCCESS || |
624 |
dwMaxValueNameLen >= MAX_BUFFER || |
|
625 |
dwMaxValueDataLen >= MAX_BUFFER) { |
|
626 |
RegCloseKey(hkeyFonts); |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
627 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
628 |
screenDC = NULL; |
2 | 629 |
return; |
630 |
} |
|
631 |
for (nval = 0; nval < dwNumValues; nval++ ) { |
|
632 |
dwNameSize = MAX_BUFFER; |
|
633 |
dwDataValueSize = MAX_BUFFER; |
|
39864 | 634 |
ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize, |
635 |
NULL, &type, (LPBYTE)data, &dwDataValueSize); |
|
636 |
||
2 | 637 |
if (ret != ERROR_SUCCESS) { |
638 |
break; |
|
639 |
} |
|
640 |
if (type != REG_SZ) { /* REG_SZ means a null-terminated string */ |
|
641 |
continue; |
|
642 |
} |
|
39864 | 643 |
|
644 |
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) { |
|
645 |
/* If the filename ends with ".ttf" or ".otf" also accept it. |
|
646 |
* Not expecting to need to do this for .ttc files. |
|
647 |
* Also note this code is not mirrored in the "A" (win9x) path. |
|
648 |
*/ |
|
649 |
LPWSTR dot = wcsrchr((LPWSTR)data, L'.'); |
|
650 |
if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0) |
|
651 |
&& (wcsicmp(dot, L".otf") != 0))) { |
|
652 |
continue; /* not a TT font... */ |
|
2 | 653 |
} |
654 |
} |
|
39864 | 655 |
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data); |
2 | 656 |
} |
39864 | 657 |
|
2 | 658 |
RegCloseKey(hkeyFonts); |
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
659 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
660 |
screenDC = NULL; |
2 | 661 |
} |