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