12047
|
1 |
/*
|
|
2 |
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation. Oracle designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Oracle in the LICENSE file that accompanied this code.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
22 |
* or visit www.oracle.com if you need additional information or have any
|
|
23 |
* questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
package sun.font;
|
|
27 |
|
|
28 |
import java.awt.*;
|
|
29 |
import java.io.File;
|
|
30 |
import java.util.ArrayList;
|
|
31 |
import java.util.HashMap;
|
|
32 |
import java.util.Hashtable;
|
|
33 |
import java.util.Locale;
|
|
34 |
import java.util.TreeMap;
|
|
35 |
import java.util.Vector;
|
|
36 |
|
|
37 |
import javax.swing.plaf.FontUIResource;
|
|
38 |
|
|
39 |
import sun.awt.FontConfiguration;
|
|
40 |
import sun.lwawt.macosx.*;
|
|
41 |
|
|
42 |
public class CFontManager extends SunFontManager {
|
|
43 |
private FontConfigManager fcManager = null;
|
|
44 |
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
|
|
45 |
|
|
46 |
@Override
|
|
47 |
protected FontConfiguration createFontConfiguration() {
|
|
48 |
FontConfiguration fc = new CFontConfiguration(this);
|
|
49 |
fc.init();
|
|
50 |
return fc;
|
|
51 |
}
|
|
52 |
|
|
53 |
@Override
|
|
54 |
public FontConfiguration createFontConfiguration(boolean preferLocaleFonts,
|
|
55 |
boolean preferPropFonts)
|
|
56 |
{
|
|
57 |
return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts);
|
|
58 |
}
|
|
59 |
|
|
60 |
private static String[] defaultPlatformFont = null;
|
|
61 |
|
|
62 |
/*
|
|
63 |
* Returns an array of two strings. The first element is the
|
|
64 |
* name of the font. The second element is the file name.
|
|
65 |
*/
|
|
66 |
@Override
|
|
67 |
public synchronized String[] getDefaultPlatformFont() {
|
|
68 |
if (defaultPlatformFont == null) {
|
|
69 |
defaultPlatformFont = new String[2];
|
|
70 |
defaultPlatformFont[0] = "Lucida Grande";
|
|
71 |
defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc";
|
|
72 |
}
|
|
73 |
return defaultPlatformFont;
|
|
74 |
}
|
|
75 |
|
|
76 |
// This is a way to register any kind of Font2D, not just files and composites.
|
|
77 |
public static Font2D[] getGenericFonts() {
|
|
78 |
return (Font2D[])genericFonts.values().toArray(new Font2D[0]);
|
|
79 |
}
|
|
80 |
|
|
81 |
public Font2D registerGenericFont(Font2D f)
|
|
82 |
{
|
|
83 |
return registerGenericFont(f, false);
|
|
84 |
}
|
|
85 |
public Font2D registerGenericFont(Font2D f, boolean logicalFont)
|
|
86 |
{
|
|
87 |
int rank = 4;
|
|
88 |
|
|
89 |
String fontName = f.fullName;
|
|
90 |
String familyName = f.familyName;
|
|
91 |
|
|
92 |
if (fontName == null || "".equals(fontName)) {
|
|
93 |
return null;
|
|
94 |
}
|
|
95 |
|
|
96 |
// logical fonts always need to be added to the family
|
|
97 |
// plus they never need to be added to the generic font list
|
|
98 |
// or the fullNameToFont table since they are covers for
|
|
99 |
// already existing fonts in this list
|
|
100 |
if (logicalFont || !genericFonts.containsKey(fontName)) {
|
|
101 |
if (FontUtilities.debugFonts()) {
|
|
102 |
FontUtilities.getLogger().info("Add to Family "+familyName +
|
|
103 |
", Font " + fontName + " rank="+rank);
|
|
104 |
}
|
|
105 |
FontFamily family = FontFamily.getFamily(familyName);
|
|
106 |
if (family == null) {
|
|
107 |
family = new FontFamily(familyName, false, rank);
|
|
108 |
family.setFont(f, f.style);
|
|
109 |
} else if (family.getRank() >= rank) {
|
|
110 |
family.setFont(f, f.style);
|
|
111 |
}
|
|
112 |
if (!logicalFont)
|
|
113 |
{
|
|
114 |
genericFonts.put(fontName, f);
|
|
115 |
fullNameToFont.put(fontName.toLowerCase(Locale.ENGLISH), f);
|
|
116 |
}
|
|
117 |
return f;
|
|
118 |
} else {
|
|
119 |
return (Font2D)genericFonts.get(fontName);
|
|
120 |
}
|
|
121 |
}
|
|
122 |
|
|
123 |
@Override
|
|
124 |
public Font2D[] getRegisteredFonts() {
|
|
125 |
Font2D[] regFonts = super.getRegisteredFonts();
|
|
126 |
|
|
127 |
// Add in the Mac OS X native fonts
|
|
128 |
Font2D[] genericFonts = getGenericFonts();
|
|
129 |
Font2D[] allFonts = new Font2D[regFonts.length+genericFonts.length];
|
|
130 |
System.arraycopy(regFonts, 0, allFonts, 0, regFonts.length);
|
|
131 |
System.arraycopy(genericFonts, 0, allFonts, regFonts.length, genericFonts.length);
|
|
132 |
|
|
133 |
return allFonts;
|
|
134 |
}
|
|
135 |
|
|
136 |
@Override
|
|
137 |
protected void addNativeFontFamilyNames(TreeMap<String, String> familyNames, Locale requestedLocale) {
|
|
138 |
Font2D[] genericfonts = getGenericFonts();
|
|
139 |
for (int i=0; i < genericfonts.length; i++) {
|
|
140 |
if (!(genericfonts[i] instanceof NativeFont)) {
|
|
141 |
String name = genericfonts[i].getFamilyName(requestedLocale);
|
|
142 |
familyNames.put(name.toLowerCase(requestedLocale), name);
|
|
143 |
}
|
|
144 |
}
|
|
145 |
}
|
|
146 |
|
|
147 |
@Override
|
|
148 |
public Font2D createFont2D(File fontFile, int fontFormat, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException {
|
|
149 |
|
|
150 |
String fontFilePath = fontFile.getPath();
|
|
151 |
Font2D font2D = null;
|
|
152 |
final File fFile = fontFile;
|
|
153 |
final CreatedFontTracker _tracker = tracker;
|
|
154 |
try {
|
|
155 |
switch (fontFormat) {
|
|
156 |
case Font.TRUETYPE_FONT:
|
|
157 |
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
|
|
158 |
break;
|
|
159 |
case Font.TYPE1_FONT:
|
|
160 |
font2D = new Type1Font(fontFilePath, null, isCopy);
|
|
161 |
break;
|
|
162 |
default:
|
|
163 |
throw new FontFormatException("Unrecognised Font Format");
|
|
164 |
}
|
|
165 |
} catch (FontFormatException e) {
|
|
166 |
if (isCopy) {
|
|
167 |
java.security.AccessController.doPrivileged(
|
|
168 |
new java.security.PrivilegedAction<Object>() {
|
|
169 |
public Object run() {
|
|
170 |
if (_tracker != null) {
|
|
171 |
_tracker.subBytes((int)fFile.length());
|
|
172 |
}
|
|
173 |
fFile.delete();
|
|
174 |
return null;
|
|
175 |
}
|
|
176 |
});
|
|
177 |
}
|
|
178 |
throw(e);
|
|
179 |
}
|
|
180 |
if (isCopy) {
|
|
181 |
FileFont.setFileToRemove(font2D, fontFile, tracker);
|
|
182 |
synchronized (FontManager.class) {
|
|
183 |
|
|
184 |
if (tmpFontFiles == null) {
|
|
185 |
tmpFontFiles = new Vector<File>();
|
|
186 |
}
|
|
187 |
tmpFontFiles.add(fontFile);
|
|
188 |
|
|
189 |
if (fileCloser == null) {
|
|
190 |
final Runnable fileCloserRunnable = new Runnable() {
|
|
191 |
public void run() {
|
|
192 |
java.security.AccessController.doPrivileged(
|
|
193 |
new java.security.PrivilegedAction<Object>() {
|
|
194 |
public Object run() {
|
|
195 |
|
|
196 |
for (int i=0;i<CHANNELPOOLSIZE;i++) {
|
|
197 |
if (fontFileCache[i] != null) {
|
|
198 |
try {
|
|
199 |
fontFileCache[i].close();
|
|
200 |
} catch (Exception e) {}
|
|
201 |
}
|
|
202 |
}
|
|
203 |
if (tmpFontFiles != null) {
|
|
204 |
File[] files = new File[tmpFontFiles.size()];
|
|
205 |
files = tmpFontFiles.toArray(files);
|
|
206 |
for (int f=0; f<files.length;f++) {
|
|
207 |
try {
|
|
208 |
files[f].delete();
|
|
209 |
} catch (Exception e) {}
|
|
210 |
}
|
|
211 |
}
|
|
212 |
return null;
|
|
213 |
}
|
|
214 |
});
|
|
215 |
}
|
|
216 |
};
|
|
217 |
java.security.AccessController.doPrivileged(
|
|
218 |
new java.security.PrivilegedAction<Object>() {
|
|
219 |
public Object run() {
|
|
220 |
/* The thread must be a member of a thread group
|
|
221 |
* which will not get GCed before VM exit.
|
|
222 |
* Make its parent the top-level thread group.
|
|
223 |
*/
|
|
224 |
ThreadGroup tg =
|
|
225 |
Thread.currentThread().getThreadGroup();
|
|
226 |
for (ThreadGroup tgn = tg;
|
|
227 |
tgn != null;
|
|
228 |
tg = tgn, tgn = tg.getParent());
|
|
229 |
fileCloser = new Thread(tg, fileCloserRunnable);
|
|
230 |
fileCloser.setContextClassLoader(null);
|
|
231 |
Runtime.getRuntime().addShutdownHook(fileCloser);
|
|
232 |
return null;
|
|
233 |
}
|
|
234 |
});
|
|
235 |
}
|
|
236 |
}
|
|
237 |
}
|
|
238 |
return font2D;
|
|
239 |
}
|
|
240 |
|
|
241 |
/*
|
|
242 |
public synchronized FontConfigManager getFontConfigManager() {
|
|
243 |
if (fcManager == null) {
|
|
244 |
fcManager = new FontConfigManager();
|
|
245 |
}
|
|
246 |
return fcManager;
|
|
247 |
}
|
|
248 |
*/
|
|
249 |
|
|
250 |
protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
|
|
251 |
loadNativeDirFonts(dirName);
|
|
252 |
super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);
|
|
253 |
}
|
|
254 |
|
|
255 |
private native void loadNativeDirFonts(String dirName);
|
|
256 |
private native void loadNativeFonts();
|
|
257 |
|
|
258 |
void registerFont(String fontName, String fontFamilyName) {
|
|
259 |
final CFont font = new CFont(fontName, fontFamilyName);
|
|
260 |
|
|
261 |
registerGenericFont(font);
|
|
262 |
|
|
263 |
if ((font.getStyle() & Font.ITALIC) == 0) {
|
|
264 |
registerGenericFont(font.createItalicVariant(), true);
|
|
265 |
}
|
|
266 |
}
|
|
267 |
|
|
268 |
Object waitForFontsToBeLoaded = new Object();
|
|
269 |
public void loadFonts()
|
|
270 |
{
|
|
271 |
synchronized(waitForFontsToBeLoaded)
|
|
272 |
{
|
|
273 |
super.loadFonts();
|
|
274 |
java.security.AccessController.doPrivileged(
|
|
275 |
new java.security.PrivilegedAction<Object>() {
|
|
276 |
public Object run() {
|
|
277 |
loadNativeFonts();
|
|
278 |
return null;
|
|
279 |
}
|
|
280 |
}
|
|
281 |
);
|
|
282 |
|
|
283 |
String defaultFont = "Lucida Grande";
|
|
284 |
String defaultFallback = "Lucida Sans";
|
|
285 |
|
|
286 |
setupLogicalFonts("Dialog", defaultFont, defaultFallback);
|
|
287 |
setupLogicalFonts("Serif", "Times", "Lucida Bright");
|
|
288 |
setupLogicalFonts("SansSerif", defaultFont, defaultFallback);
|
|
289 |
setupLogicalFonts("Monospaced", "Menlo", "Lucida Sans Typewriter");
|
|
290 |
setupLogicalFonts("DialogInput", defaultFont, defaultFallback);
|
|
291 |
}
|
|
292 |
}
|
|
293 |
|
|
294 |
protected void setupLogicalFonts(String logicalName, String realName, String fallbackName) {
|
|
295 |
FontFamily realFamily = getFontFamilyWithExtraTry(logicalName, realName, fallbackName);
|
|
296 |
|
|
297 |
cloneStyledFont(realFamily, logicalName, Font.PLAIN);
|
|
298 |
cloneStyledFont(realFamily, logicalName, Font.BOLD);
|
|
299 |
cloneStyledFont(realFamily, logicalName, Font.ITALIC);
|
|
300 |
cloneStyledFont(realFamily, logicalName, Font.BOLD | Font.ITALIC);
|
|
301 |
}
|
|
302 |
|
|
303 |
protected FontFamily getFontFamilyWithExtraTry(String logicalName, String realName, String fallbackName){
|
|
304 |
FontFamily family = getFontFamily(realName, fallbackName);
|
|
305 |
if (family != null) return family;
|
|
306 |
|
|
307 |
// at this point, we recognize that we probably needed a fallback font
|
|
308 |
super.loadFonts();
|
|
309 |
|
|
310 |
family = getFontFamily(realName, fallbackName);
|
|
311 |
if (family != null) return family;
|
|
312 |
|
|
313 |
System.err.println("Warning: the fonts \"" + realName + "\" and \"" + fallbackName + "\" are not available for the Java logical font \"" + logicalName + "\", which may have unexpected appearance or behavior. Re-enable the \""+ realName +"\" font to remove this warning.");
|
|
314 |
return null;
|
|
315 |
}
|
|
316 |
|
|
317 |
protected FontFamily getFontFamily(String realName, String fallbackName){
|
|
318 |
FontFamily family = FontFamily.getFamily(realName);
|
|
319 |
if (family != null) return family;
|
|
320 |
|
|
321 |
family = FontFamily.getFamily(fallbackName);
|
|
322 |
if (family != null){
|
|
323 |
System.err.println("Warning: the font \"" + realName + "\" is not available, so \"" + fallbackName + "\" has been substituted, but may have unexpected appearance or behavor. Re-enable the \""+ realName +"\" font to remove this warning.");
|
|
324 |
return family;
|
|
325 |
}
|
|
326 |
|
|
327 |
return null;
|
|
328 |
}
|
|
329 |
|
|
330 |
protected boolean cloneStyledFont(FontFamily realFamily, String logicalFamilyName, int style) {
|
|
331 |
if (realFamily == null) return false;
|
|
332 |
|
|
333 |
Font2D realFont = realFamily.getFontWithExactStyleMatch(style);
|
|
334 |
if (realFont == null || !(realFont instanceof CFont)) return false;
|
|
335 |
|
|
336 |
CFont newFont = new CFont((CFont)realFont, logicalFamilyName);
|
|
337 |
registerGenericFont(newFont, true);
|
|
338 |
|
|
339 |
return true;
|
|
340 |
}
|
|
341 |
|
|
342 |
@Override
|
|
343 |
public String getFontPath(boolean noType1Fonts) {
|
|
344 |
// In the case of the Cocoa toolkit, since we go through NSFont, we dont need to register /Library/Fonts
|
|
345 |
if (Toolkit.getDefaultToolkit() instanceof LWCToolkit) {
|
|
346 |
return "";
|
|
347 |
}
|
|
348 |
// X11 case
|
|
349 |
return "/Library/Fonts";
|
|
350 |
}
|
|
351 |
|
|
352 |
@Override
|
|
353 |
protected FontUIResource getFontConfigFUIR(
|
|
354 |
String family, int style, int size)
|
|
355 |
{
|
|
356 |
String mappedName = FontUtilities.mapFcName(family);
|
|
357 |
if (mappedName == null) {
|
|
358 |
mappedName = "sansserif";
|
|
359 |
}
|
|
360 |
return new FontUIResource(mappedName, style, size);
|
|
361 |
}
|
|
362 |
|
|
363 |
// Only implemented on Windows
|
|
364 |
@Override
|
|
365 |
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
|
|
366 |
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
|
|
367 |
}
|