author | lana |
Thu, 26 Dec 2013 12:04:16 -0800 | |
changeset 23010 | 6dadb192ad81 |
parent 21278 | ef8a3a2a72f2 |
child 23674 | 47a4a6183907 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
21278
diff
changeset
|
2 |
* Copyright (c) 1998, 2013, 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 |
||
35 |
||
3928 | 36 |
JNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1) |
2 | 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 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
147 |
/* 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
|
148 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 149 |
return 1; |
150 |
} |
|
151 |
||
152 |
/* printf("FULL=%s\n",lpelfe->elfFullName);fflush(stdout); */ |
|
153 |
||
154 |
fullname = JNU_NewStringPlatform(env, lpelfe->elfFullName); |
|
155 |
fullnameLC = (*env)->CallObjectMethod(env, fullname, |
|
156 |
fmi->toLowerCaseMID, fmi->locale); |
|
5752 | 157 |
(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname); |
2 | 158 |
(*env)->CallObjectMethod(env, fmi->fontToFamilyMap, |
159 |
fmi->putMID, fullnameLC, fmi->family); |
|
160 |
return 1; |
|
161 |
} |
|
162 |
||
163 |
typedef struct CheckFamilyInfo { |
|
164 |
wchar_t *family; |
|
165 |
wchar_t* fullName; |
|
166 |
int isDifferent; |
|
167 |
} CheckFamilyInfo; |
|
168 |
||
169 |
static int CALLBACK CheckFontFamilyProcW( |
|
170 |
ENUMLOGFONTEXW *lpelfe, |
|
171 |
NEWTEXTMETRICEX *lpntme, |
|
172 |
int FontType, |
|
173 |
LPARAM lParam) |
|
174 |
{ |
|
175 |
CheckFamilyInfo *info = (CheckFamilyInfo*)lParam; |
|
176 |
info->isDifferent = wcscmp(lpelfe->elfLogFont.lfFaceName, info->family); |
|
177 |
||
178 |
/* if (!info->isDifferent) { */ |
|
179 |
/* wprintf(LFor font %s expected family=%s instead got %s\n", */ |
|
180 |
/* lpelfe->elfFullName, */ |
|
181 |
/* info->family, */ |
|
182 |
/* lpelfe->elfLogFont.lfFaceName); */ |
|
183 |
/* fflush(stdout); */ |
|
184 |
/* } */ |
|
185 |
return 0; |
|
186 |
} |
|
187 |
||
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
188 |
/* 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
|
189 |
* 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
|
190 |
* create many DCs. |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
191 |
*/ |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
192 |
static HDC screenDC = NULL; |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
193 |
|
2 | 194 |
static int DifferentFamily(wchar_t *family, wchar_t* fullName) { |
195 |
LOGFONTW lfw; |
|
196 |
CheckFamilyInfo info; |
|
197 |
||
198 |
/* If fullName can't be stored in the struct, assume correct family */ |
|
199 |
if (wcslen((LPWSTR)fullName) >= LF_FACESIZE) { |
|
200 |
return 0; |
|
201 |
} |
|
202 |
||
203 |
memset(&info, 0, sizeof(CheckFamilyInfo)); |
|
204 |
info.family = family; |
|
205 |
info.fullName = fullName; |
|
206 |
info.isDifferent = 0; |
|
207 |
||
208 |
memset(&lfw, 0, sizeof(lfw)); |
|
209 |
wcscpy(lfw.lfFaceName, fullName); |
|
210 |
lfw.lfCharSet = DEFAULT_CHARSET; |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
211 |
EnumFontFamiliesExW(screenDC, &lfw, |
2 | 212 |
(FONTENUMPROCW)CheckFontFamilyProcW, |
213 |
(LPARAM)(&info), 0L); |
|
214 |
||
215 |
return info.isDifferent; |
|
216 |
} |
|
217 |
||
218 |
static int CALLBACK EnumFontFacesInFamilyProcW( |
|
219 |
ENUMLOGFONTEXW *lpelfe, |
|
220 |
NEWTEXTMETRICEX *lpntme, |
|
221 |
int FontType, |
|
222 |
LPARAM lParam) |
|
223 |
{ |
|
224 |
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; |
|
225 |
JNIEnv *env = fmi->env; |
|
226 |
jstring fullname, fullnameLC; |
|
227 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
228 |
/* 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
|
229 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 230 |
return 1; |
231 |
} |
|
232 |
||
233 |
/* Windows has font aliases and so may enumerate fonts from |
|
234 |
* the aliased family if any actual font of that family is installed. |
|
235 |
* To protect against it ignore fonts which aren't enumerated under |
|
236 |
* their true family. |
|
237 |
*/ |
|
238 |
if (DifferentFamily(lpelfe->elfLogFont.lfFaceName, |
|
239 |
lpelfe->elfFullName)) { |
|
240 |
return 1; |
|
241 |
} |
|
242 |
||
243 |
fullname = (*env)->NewString(env, lpelfe->elfFullName, |
|
9460 | 244 |
(jsize)wcslen((LPWSTR)lpelfe->elfFullName)); |
2 | 245 |
fullnameLC = (*env)->CallObjectMethod(env, fullname, |
246 |
fmi->toLowerCaseMID, fmi->locale); |
|
5752 | 247 |
(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname); |
2 | 248 |
(*env)->CallObjectMethod(env, fmi->fontToFamilyMap, |
249 |
fmi->putMID, fullnameLC, fmi->family); |
|
250 |
return 1; |
|
251 |
} |
|
252 |
||
253 |
/* Callback for EnumFontFamiliesEx in populateFontFileNameMap. |
|
254 |
* Expects to be called for every charset of every font family. |
|
255 |
* If this is the first time we have been called for this family, |
|
256 |
* add a new mapping to the familyToFontListMap from this family to a |
|
257 |
* list of its members. To populate that list, further enumerate all faces |
|
258 |
* in this family for the matched charset. This assumes that all fonts |
|
259 |
* in a family support the same charset, which is a fairly safe assumption |
|
260 |
* and saves time as the call we make here to EnumFontFamiliesEx will |
|
261 |
* enumerate the members of this family just once each. |
|
262 |
* Because we set fmi->list to be the newly created list the call back |
|
263 |
* can safely add to that list without a search. |
|
264 |
*/ |
|
265 |
static int CALLBACK EnumFamilyNamesA( |
|
266 |
ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */ |
|
267 |
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */ |
|
268 |
int FontType, /* type of font */ |
|
269 |
LPARAM lParam) /* application-defined data */ |
|
270 |
{ |
|
271 |
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; |
|
272 |
JNIEnv *env = fmi->env; |
|
273 |
jstring familyLC; |
|
274 |
LOGFONTA lfa; |
|
275 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
276 |
/* 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
|
277 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 278 |
return 1; |
279 |
} |
|
280 |
||
281 |
/* Windows lists fonts which have a vmtx (vertical metrics) table twice. |
|
282 |
* Once using their normal name, and again preceded by '@'. These appear |
|
283 |
* in font lists in some windows apps, such as wordpad. We don't want |
|
284 |
* these so we skip any font where the first character is '@' |
|
285 |
*/ |
|
286 |
if (lpelfe->elfLogFont.lfFaceName[0] == '@') { |
|
287 |
return 1; |
|
288 |
} |
|
289 |
fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName); |
|
290 |
familyLC = (*env)->CallObjectMethod(env, fmi->family, |
|
291 |
fmi->toLowerCaseMID, fmi->locale); |
|
292 |
/* check if already seen this family with a different charset */ |
|
293 |
if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap, |
|
294 |
fmi->containsKeyMID, familyLC)) { |
|
295 |
return 1; |
|
296 |
} |
|
297 |
fmi->list = (*env)->NewObject(env, |
|
298 |
fmi->arrayListClass, fmi->arrayListCtr, 4); |
|
299 |
||
300 |
(*env)->CallObjectMethod(env, fmi->familyToFontListMap, |
|
301 |
fmi->putMID, familyLC, fmi->list); |
|
302 |
||
303 |
/* printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */ |
|
304 |
||
305 |
memset(&lfa, 0, sizeof(lfa)); |
|
306 |
strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName); |
|
307 |
lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet; |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
308 |
EnumFontFamiliesExA(screenDC, &lfa, |
2 | 309 |
(FONTENUMPROCA)EnumFontFacesInFamilyProcA, |
310 |
lParam, 0L); |
|
311 |
return 1; |
|
312 |
} |
|
313 |
||
314 |
static int CALLBACK EnumFamilyNamesW( |
|
315 |
ENUMLOGFONTEXW *lpelfe, /* pointer to logical-font data */ |
|
316 |
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */ |
|
317 |
int FontType, /* type of font */ |
|
318 |
LPARAM lParam ) /* application-defined data */ |
|
319 |
{ |
|
320 |
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam; |
|
321 |
JNIEnv *env = fmi->env; |
|
322 |
jstring familyLC; |
|
9460 | 323 |
size_t slen; |
2 | 324 |
LOGFONTW lfw; |
325 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
326 |
/* 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
|
327 |
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) { |
2 | 328 |
return 1; |
329 |
} |
|
330 |
/* wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */ |
|
331 |
/* lpelfe->elfLogFont.lfFaceName, */ |
|
332 |
/* lpelfe->elfLogFont.lfCharSet, */ |
|
333 |
/* lpelfe->elfFullName); */ |
|
334 |
/* fflush(stdout); */ |
|
335 |
||
336 |
/* Windows lists fonts which have a vmtx (vertical metrics) table twice. |
|
337 |
* Once using their normal name, and again preceded by '@'. These appear |
|
338 |
* in font lists in some windows apps, such as wordpad. We don't want |
|
339 |
* these so we skip any font where the first character is '@' |
|
340 |
*/ |
|
341 |
if (lpelfe->elfLogFont.lfFaceName[0] == L'@') { |
|
342 |
return 1; |
|
343 |
} |
|
344 |
slen = wcslen(lpelfe->elfLogFont.lfFaceName); |
|
9460 | 345 |
fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen); |
2 | 346 |
familyLC = (*env)->CallObjectMethod(env, fmi->family, |
347 |
fmi->toLowerCaseMID, fmi->locale); |
|
348 |
/* check if already seen this family with a different charset */ |
|
349 |
if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap, |
|
350 |
fmi->containsKeyMID, familyLC)) { |
|
351 |
return 1; |
|
352 |
} |
|
353 |
fmi->list = (*env)->NewObject(env, |
|
354 |
fmi->arrayListClass, fmi->arrayListCtr, 4); |
|
355 |
||
356 |
(*env)->CallObjectMethod(env, fmi->familyToFontListMap, |
|
357 |
fmi->putMID, familyLC, fmi->list); |
|
358 |
||
359 |
memset(&lfw, 0, sizeof(lfw)); |
|
360 |
wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName); |
|
361 |
lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet; |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
362 |
EnumFontFamiliesExW(screenDC, &lfw, |
2 | 363 |
(FONTENUMPROCW)EnumFontFacesInFamilyProcW, |
364 |
lParam, 0L); |
|
365 |
return 1; |
|
366 |
} |
|
367 |
||
368 |
||
369 |
/* It looks like TrueType fonts have " (TrueType)" tacked on the end of their |
|
370 |
* name, so we can try to use that to distinguish TT from other fonts. |
|
371 |
* However if a program "installed" a font in the registry the key may |
|
372 |
* not include that. We could also try to "pass" fonts which have no "(..)" |
|
373 |
* at the end. But that turns out to pass a few .FON files that MS supply. |
|
21278 | 374 |
* If there's no parenthesized type string, we could next try to infer |
2 | 375 |
* the file type from the file name extension. Since the MS entries that |
376 |
* have no type string are very few, and have odd names like "MS-DOS CP 437" |
|
377 |
* and would never return a Java Font anyway its currently OK to put these |
|
378 |
* in the font map, although clearly the returned names must never percolate |
|
379 |
* up into a list of available fonts returned to the application. |
|
380 |
* Additionally for TTC font files the key looks like |
|
381 |
* Font 1 & Font 2 (TrueType) |
|
382 |
* or sometimes even : |
|
383 |
* Font 1 & Font 2 & Font 3 (TrueType) |
|
384 |
* Also if a Font has a name for this locale that name also |
|
385 |
* exists in the registry using the appropriate platform encoding. |
|
386 |
* What do we do then? |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
387 |
* |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
388 |
* 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
|
389 |
* but " (OpenType)" on XP. |
2 | 390 |
*/ |
391 |
||
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
392 |
static BOOL RegistryToBaseTTNameA(LPSTR name) { |
2 | 393 |
static const char TTSUFFIX[] = " (TrueType)"; |
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
394 |
static const char OTSUFFIX[] = " (OpenType)"; |
9460 | 395 |
size_t TTSLEN = strlen(TTSUFFIX); |
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
396 |
char *suffix; |
2 | 397 |
|
9460 | 398 |
size_t len = strlen(name); |
2 | 399 |
if (len == 0) { |
400 |
return FALSE; |
|
401 |
} |
|
402 |
if (name[len-1] != ')') { |
|
403 |
return FALSE; |
|
404 |
} |
|
405 |
if (len <= TTSLEN) { |
|
406 |
return FALSE; |
|
407 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
408 |
|
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
409 |
/* 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
|
410 |
suffix = name + len - TTSLEN; |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
411 |
if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) { |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
412 |
suffix[0] = '\0'; /* truncate name */ |
2 | 413 |
return TRUE; |
414 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
415 |
return FALSE; |
2 | 416 |
} |
417 |
||
418 |
static BOOL RegistryToBaseTTNameW(LPWSTR name) { |
|
419 |
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
|
420 |
static const wchar_t OTSUFFIX[] = L" (OpenType)"; |
9460 | 421 |
size_t TTSLEN = wcslen(TTSUFFIX); |
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
422 |
wchar_t *suffix; |
2 | 423 |
|
9460 | 424 |
size_t len = wcslen(name); |
2 | 425 |
if (len == 0) { |
426 |
return FALSE; |
|
427 |
} |
|
428 |
if (name[len-1] != L')') { |
|
429 |
return FALSE; |
|
430 |
} |
|
431 |
if (len <= TTSLEN) { |
|
432 |
return FALSE; |
|
433 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
434 |
/* 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
|
435 |
suffix = name + (len - TTSLEN); |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
436 |
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
|
437 |
suffix[0] = L'\0'; /* truncate name */ |
2 | 438 |
return TRUE; |
439 |
} |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
440 |
return FALSE; |
2 | 441 |
} |
442 |
||
443 |
static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap, |
|
444 |
LPCSTR name, LPCSTR data) { |
|
445 |
LPSTR ptr1, ptr2; |
|
446 |
jstring fontStr; |
|
447 |
JNIEnv *env = fmi->env; |
|
9460 | 448 |
size_t dslen = strlen(data); |
2 | 449 |
jstring fileStr = JNU_NewStringPlatform(env, data); |
450 |
||
451 |
/* TTC or ttc means it may be a collection. Need to parse out |
|
452 |
* multiple font face names separated by " & " |
|
453 |
* By only doing this for fonts which look like collections based on |
|
454 |
* file name we are adhering to MS recommendations for font file names |
|
455 |
* so it seems that we can be sure that this identifies precisely |
|
456 |
* the MS-supplied truetype collections. |
|
457 |
* This avoids any potential issues if a TTF file happens to have |
|
458 |
* a & in the font name (I can't find anything which prohibits this) |
|
459 |
* and also means we only parse the key in cases we know to be |
|
460 |
* worthwhile. |
|
461 |
*/ |
|
462 |
if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') && |
|
463 |
(ptr1 = strstr(name, " & ")) != NULL) { |
|
464 |
ptr1+=3; |
|
465 |
while (ptr1 >= name) { /* marginally safer than while (true) */ |
|
466 |
while ((ptr2 = strstr(ptr1, " & ")) != NULL) { |
|
467 |
ptr1 = ptr2+3; |
|
468 |
} |
|
469 |
fontStr = JNU_NewStringPlatform(env, ptr1); |
|
470 |
fontStr = (*env)->CallObjectMethod(env, fontStr, |
|
471 |
fmi->toLowerCaseMID, |
|
472 |
fmi->locale); |
|
473 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
|
474 |
fontStr, fileStr); |
|
475 |
if (ptr1 == name) { |
|
476 |
break; |
|
477 |
} else { |
|
478 |
*(ptr1-3) ='\0'; |
|
479 |
ptr1 = (LPSTR)name; |
|
480 |
} |
|
481 |
} |
|
482 |
} else { |
|
483 |
fontStr = JNU_NewStringPlatform(env, name); |
|
484 |
fontStr = (*env)->CallObjectMethod(env, fontStr, |
|
485 |
fmi->toLowerCaseMID, fmi->locale); |
|
486 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
|
487 |
fontStr, fileStr); |
|
488 |
} |
|
489 |
} |
|
490 |
||
491 |
static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap, |
|
492 |
LPWSTR name, LPWSTR data) { |
|
493 |
||
494 |
wchar_t *ptr1, *ptr2; |
|
495 |
jstring fontStr; |
|
496 |
JNIEnv *env = fmi->env; |
|
9460 | 497 |
size_t dslen = wcslen(data); |
498 |
jstring fileStr = (*env)->NewString(env, data, (jsize)dslen); |
|
2 | 499 |
|
500 |
/* TTC or ttc means it may be a collection. Need to parse out |
|
501 |
* multiple font face names separated by " & " |
|
502 |
* By only doing this for fonts which look like collections based on |
|
503 |
* file name we are adhering to MS recommendations for font file names |
|
504 |
* so it seems that we can be sure that this identifies precisely |
|
505 |
* the MS-supplied truetype collections. |
|
506 |
* This avoids any potential issues if a TTF file happens to have |
|
507 |
* a & in the font name (I can't find anything which prohibits this) |
|
508 |
* and also means we only parse the key in cases we know to be |
|
509 |
* worthwhile. |
|
510 |
*/ |
|
511 |
||
512 |
if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') && |
|
513 |
(ptr1 = wcsstr(name, L" & ")) != NULL) { |
|
514 |
ptr1+=3; |
|
515 |
while (ptr1 >= name) { /* marginally safer than while (true) */ |
|
516 |
while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) { |
|
517 |
ptr1 = ptr2+3; |
|
518 |
} |
|
9460 | 519 |
fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1)); |
2 | 520 |
fontStr = (*env)->CallObjectMethod(env, fontStr, |
521 |
fmi->toLowerCaseMID, |
|
522 |
fmi->locale); |
|
523 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
|
524 |
fontStr, fileStr); |
|
525 |
if (ptr1 == name) { |
|
526 |
break; |
|
527 |
} else { |
|
528 |
*(ptr1-3) = L'\0'; |
|
529 |
ptr1 = name; |
|
530 |
} |
|
531 |
} |
|
532 |
} else { |
|
9460 | 533 |
fontStr = (*env)->NewString(env, name, (jsize)wcslen(name)); |
2 | 534 |
fontStr = (*env)->CallObjectMethod(env, fontStr, |
535 |
fmi->toLowerCaseMID, fmi->locale); |
|
536 |
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID, |
|
537 |
fontStr, fileStr); |
|
538 |
} |
|
539 |
} |
|
540 |
||
541 |
/* Obtain all the fontname -> filename mappings. |
|
542 |
* This is called once and the results returned to Java code which can |
|
543 |
* use it for lookups to reduce or avoid the need to search font files. |
|
544 |
*/ |
|
545 |
JNIEXPORT void JNICALL |
|
3928 | 546 |
Java_sun_awt_Win32FontManager_populateFontFileNameMap0 |
2 | 547 |
(JNIEnv *env, jclass obj, jobject fontToFileMap, |
548 |
jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale) |
|
549 |
{ |
|
550 |
#define MAX_BUFFER (FILENAME_MAX+1) |
|
551 |
const wchar_t wname[MAX_BUFFER]; |
|
552 |
const char cname[MAX_BUFFER]; |
|
553 |
const char data[MAX_BUFFER]; |
|
554 |
||
555 |
DWORD type; |
|
556 |
LONG ret; |
|
557 |
HKEY hkeyFonts; |
|
558 |
DWORD dwNameSize; |
|
559 |
DWORD dwDataValueSize; |
|
560 |
DWORD nval; |
|
561 |
LPCSTR fontKeyName; |
|
562 |
DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen; |
|
563 |
DWORD numValues = 0; |
|
564 |
jclass classID; |
|
565 |
jmethodID putMID; |
|
566 |
GdiFontMapInfo fmi; |
|
567 |
||
568 |
/* Check we were passed all the maps we need, and do lookup of |
|
569 |
* methods for JNI up-calls |
|
570 |
*/ |
|
571 |
if (fontToFileMap == NULL || |
|
572 |
fontToFamilyMap == NULL || |
|
573 |
familyToFontListMap == NULL) { |
|
574 |
return; |
|
575 |
} |
|
576 |
classID = (*env)->FindClass(env, "java/util/HashMap"); |
|
577 |
if (classID == NULL) { |
|
578 |
return; |
|
579 |
} |
|
580 |
putMID = (*env)->GetMethodID(env, classID, "put", |
|
581 |
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); |
|
582 |
if (putMID == NULL) { |
|
583 |
return; |
|
584 |
} |
|
585 |
||
586 |
fmi.env = env; |
|
587 |
fmi.fontToFamilyMap = fontToFamilyMap; |
|
588 |
fmi.familyToFontListMap = familyToFontListMap; |
|
589 |
fmi.putMID = putMID; |
|
590 |
fmi.locale = locale; |
|
591 |
fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey", |
|
592 |
"(Ljava/lang/Object;)Z"); |
|
593 |
if (fmi.containsKeyMID == NULL) { |
|
594 |
return; |
|
595 |
} |
|
596 |
||
597 |
fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); |
|
598 |
if (fmi.arrayListClass == NULL) { |
|
599 |
return; |
|
600 |
} |
|
601 |
fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass, |
|
602 |
"<init>", "(I)V"); |
|
603 |
if (fmi.arrayListCtr == NULL) { |
|
604 |
return; |
|
605 |
} |
|
606 |
fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass, |
|
607 |
"add", "(Ljava/lang/Object;)Z"); |
|
608 |
if (fmi.addMID == NULL) { |
|
609 |
return; |
|
610 |
} |
|
611 |
classID = (*env)->FindClass(env, "java/lang/String"); |
|
612 |
if (classID == NULL) { |
|
613 |
return; |
|
614 |
} |
|
615 |
fmi.toLowerCaseMID = |
|
616 |
(*env)->GetMethodID(env, classID, "toLowerCase", |
|
617 |
"(Ljava/util/Locale;)Ljava/lang/String;"); |
|
618 |
if (fmi.toLowerCaseMID == NULL) { |
|
619 |
return; |
|
620 |
} |
|
621 |
||
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
622 |
screenDC = GetDC(NULL); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
623 |
if (screenDC == NULL) { |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
624 |
return; |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
625 |
} |
2 | 626 |
/* Enumerate fonts via GDI to build maps of fonts and families */ |
627 |
if (IS_NT) { |
|
628 |
LOGFONTW lfw; |
|
629 |
memset(&lfw, 0, sizeof(lfw)); |
|
630 |
lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */ |
|
631 |
wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */ |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
632 |
EnumFontFamiliesExW(screenDC, &lfw, |
2 | 633 |
(FONTENUMPROCW)EnumFamilyNamesW, |
634 |
(LPARAM)(&fmi), 0L); |
|
635 |
} else { |
|
636 |
LOGFONT lfa; |
|
637 |
memset(&lfa, 0, sizeof(lfa)); |
|
638 |
lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */ |
|
639 |
strcpy(lfa.lfFaceName, ""); /* one face per family */ |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
640 |
ret = EnumFontFamiliesExA(screenDC, &lfa, |
2 | 641 |
(FONTENUMPROCA)EnumFamilyNamesA, |
642 |
(LPARAM)(&fmi), 0L); |
|
643 |
} |
|
644 |
||
645 |
/* Use the windows registry to map font names to files */ |
|
646 |
fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN; |
|
647 |
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
|
648 |
fontKeyName, 0L, KEY_READ, &hkeyFonts); |
|
649 |
if (ret != ERROR_SUCCESS) { |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
650 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
651 |
screenDC = NULL; |
2 | 652 |
return; |
653 |
} |
|
654 |
||
655 |
if (IS_NT) { |
|
656 |
ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL, |
|
657 |
&dwNumValues, &dwMaxValueNameLen, |
|
658 |
&dwMaxValueDataLen, NULL, NULL); |
|
659 |
} else { |
|
660 |
ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL, |
|
661 |
&dwNumValues, &dwMaxValueNameLen, |
|
662 |
&dwMaxValueDataLen, NULL, NULL); |
|
663 |
} |
|
664 |
if (ret != ERROR_SUCCESS || |
|
665 |
dwMaxValueNameLen >= MAX_BUFFER || |
|
666 |
dwMaxValueDataLen >= MAX_BUFFER) { |
|
667 |
RegCloseKey(hkeyFonts); |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
668 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
669 |
screenDC = NULL; |
2 | 670 |
return; |
671 |
} |
|
672 |
for (nval = 0; nval < dwNumValues; nval++ ) { |
|
673 |
dwNameSize = MAX_BUFFER; |
|
674 |
dwDataValueSize = MAX_BUFFER; |
|
675 |
if (IS_NT) { |
|
676 |
ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize, |
|
677 |
NULL, &type, (LPBYTE)data, &dwDataValueSize); |
|
678 |
} else { |
|
679 |
ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize, |
|
680 |
NULL, &type, (LPBYTE)data, &dwDataValueSize); |
|
681 |
} |
|
682 |
if (ret != ERROR_SUCCESS) { |
|
683 |
break; |
|
684 |
} |
|
685 |
if (type != REG_SZ) { /* REG_SZ means a null-terminated string */ |
|
686 |
continue; |
|
687 |
} |
|
688 |
if (IS_NT) { |
|
689 |
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) { |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
690 |
/* If the filename ends with ".ttf" or ".otf" also accept it. |
2 | 691 |
* Not expecting to need to do this for .ttc files. |
692 |
* Also note this code is not mirrored in the "A" (win9x) path. |
|
693 |
*/ |
|
694 |
LPWSTR dot = wcsrchr((LPWSTR)data, L'.'); |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
695 |
if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0) |
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
696 |
&& (wcsicmp(dot, L".otf") != 0))) { |
2 | 697 |
continue; /* not a TT font... */ |
698 |
} |
|
699 |
} |
|
700 |
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data); |
|
701 |
} else { |
|
1716
461122becab9
4356282: RFE: T2K should be used to rasterize CID/CFF fonts
igor
parents:
2
diff
changeset
|
702 |
if (!RegistryToBaseTTNameA((LPSTR)cname)) { |
2 | 703 |
continue; /* not a TT font... */ |
704 |
} |
|
705 |
registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data); |
|
706 |
} |
|
707 |
} |
|
708 |
RegCloseKey(hkeyFonts); |
|
11653
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
709 |
ReleaseDC(NULL, screenDC); |
65d57ea9c30a
7131153: GetDC called way too many times - causes bad performance.
prr
parents:
9460
diff
changeset
|
710 |
screenDC = NULL; |
2 | 711 |
} |