1 /*
2  * Copyright (c) 2008, 2015, 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 
27 package sun.awt;
28 
29 import java.awt.FontFormatException;
30 import java.awt.GraphicsEnvironment;
31 import java.io.File;
32 import java.security.AccessController;
33 import java.security.PrivilegedAction;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.Locale;
37 import java.util.NoSuchElementException;
38 import java.util.StringTokenizer;
39 
40 import sun.awt.windows.WFontConfiguration;
41 import sun.font.FontManager;
42 import sun.font.SunFontManager;
43 import sun.font.TrueTypeFont;
44 
45 /**
46  * The X11 implementation of {@link FontManager}.
47  */
48 public final class Win32FontManager extends SunFontManager {
49 
50     private static TrueTypeFont eudcFont;
51 
52     static {
53 
AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { String eudcFile = getEUDCFontFile(); if (eudcFile != null) { try { eudcFont = new TrueTypeFont(eudcFile, null, 0, true, false); } catch (FontFormatException e) { } } return null; } })54         AccessController.doPrivileged(new PrivilegedAction<Object>() {
55 
56                 public Object run() {
57                     String eudcFile = getEUDCFontFile();
58                     if (eudcFile != null) {
59                         try {
60                             /* Must use Java rasteriser since GDI doesn't
61                              * enumerate (allow direct use) of EUDC fonts.
62                              */
63                             eudcFont = new TrueTypeFont(eudcFile, null, 0,
64                                                         true, false);
65                         } catch (FontFormatException e) {
66                         }
67                     }
68                     return null;
69                 }
70 
71             });
72     }
73 
74     /* Used on Windows to obtain from the windows registry the name
75      * of a file containing the system EUFC font. If running in one of
76      * the locales for which this applies, and one is defined, the font
77      * defined by this file is appended to all composite fonts as a
78      * fallback component.
79      */
getEUDCFontFile()80     private static native String getEUDCFontFile();
81 
getEUDCFont()82     public TrueTypeFont getEUDCFont() {
83         return eudcFont;
84     }
85 
Win32FontManager()86     public Win32FontManager() {
87         super();
88         AccessController.doPrivileged(new PrivilegedAction<Object>() {
89                 public Object run() {
90 
91                     /* Register the JRE fonts so that the native platform can
92                      * access them. This is used only on Windows so that when
93                      * printing the printer driver can access the fonts.
94                      */
95                     registerJREFontsWithPlatform(jreFontDirName);
96                     return null;
97                 }
98             });
99     }
100 
101     /**
102      * Whether registerFontFile expects absolute or relative
103      * font file names.
104      */
useAbsoluteFontFileNames()105     protected boolean useAbsoluteFontFileNames() {
106         return false;
107     }
108 
109     /* Unlike the shared code version, this expects a base file name -
110      * not a full path name.
111      * The font configuration file has base file names and the FontConfiguration
112      * class reports these back to the GraphicsEnvironment, so these
113      * are the componentFileNames of CompositeFonts.
114      */
registerFontFile(String fontFileName, String[] nativeNames, int fontRank, boolean defer)115     protected void registerFontFile(String fontFileName, String[] nativeNames,
116                                     int fontRank, boolean defer) {
117 
118         // REMIND: case compare depends on platform
119         if (registeredFontFiles.contains(fontFileName)) {
120             return;
121         }
122         registeredFontFiles.add(fontFileName);
123 
124         int fontFormat;
125         if (getTrueTypeFilter().accept(null, fontFileName)) {
126             fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
127         } else if (getType1Filter().accept(null, fontFileName)) {
128             fontFormat = SunFontManager.FONTFORMAT_TYPE1;
129         } else {
130             /* on windows we don't use/register native fonts */
131             return;
132         }
133 
134         if (fontPath == null) {
135             fontPath = getPlatformFontPath(noType1Font);
136         }
137 
138         /* Look in the JRE font directory first.
139          * This is playing it safe as we would want to find fonts in the
140          * JRE font directory ahead of those in the system directory
141          */
142         String tmpFontPath = jreFontDirName+File.pathSeparator+fontPath;
143         StringTokenizer parser = new StringTokenizer(tmpFontPath,
144                                                      File.pathSeparator);
145 
146         boolean found = false;
147         try {
148             while (!found && parser.hasMoreTokens()) {
149                 String newPath = parser.nextToken();
150                 boolean isJREFont = newPath.equals(jreFontDirName);
151                 File theFile = new File(newPath, fontFileName);
152                 if (theFile.canRead()) {
153                     found = true;
154                     String path = theFile.getAbsolutePath();
155                     if (defer) {
156                         registerDeferredFont(fontFileName, path,
157                                              nativeNames,
158                                              fontFormat, isJREFont,
159                                              fontRank);
160                     } else {
161                         registerFontFile(path, nativeNames,
162                                          fontFormat, isJREFont,
163                                          fontRank);
164                     }
165                     break;
166                 }
167             }
168         } catch (NoSuchElementException e) {
169             System.err.println(e);
170         }
171         if (!found) {
172             addToMissingFontFileList(fontFileName);
173         }
174     }
175 
176     @Override
createFontConfiguration()177     protected FontConfiguration createFontConfiguration() {
178 
179        FontConfiguration fc = new WFontConfiguration(this);
180        fc.init();
181        return fc;
182     }
183 
184     @Override
createFontConfiguration(boolean preferLocaleFonts, boolean preferPropFonts)185     public FontConfiguration createFontConfiguration(boolean preferLocaleFonts,
186             boolean preferPropFonts) {
187 
188         return new WFontConfiguration(this,
189                                       preferLocaleFonts,preferPropFonts);
190     }
191 
192     protected void
populateFontFileNameMap(HashMap<String,String> fontToFileMap, HashMap<String,String> fontToFamilyNameMap, HashMap<String,ArrayList<String>> familyToFontListMap, Locale locale)193         populateFontFileNameMap(HashMap<String,String> fontToFileMap,
194                                 HashMap<String,String> fontToFamilyNameMap,
195                                 HashMap<String,ArrayList<String>>
196                                 familyToFontListMap,
197                                 Locale locale) {
198 
199         populateFontFileNameMap0(fontToFileMap, fontToFamilyNameMap,
200                                  familyToFontListMap, locale);
201 
202     }
203 
204     private static native void
populateFontFileNameMap0(HashMap<String,String> fontToFileMap, HashMap<String,String> fontToFamilyNameMap, HashMap<String,ArrayList<String>> familyToFontListMap, Locale locale)205         populateFontFileNameMap0(HashMap<String,String> fontToFileMap,
206                                  HashMap<String,String> fontToFamilyNameMap,
207                                  HashMap<String,ArrayList<String>>
208                                      familyToFontListMap,
209                                  Locale locale);
210 
getFontPath(boolean noType1Fonts)211     protected synchronized native String getFontPath(boolean noType1Fonts);
212 
213     @Override
getDefaultPlatformFont()214     protected String[] getDefaultPlatformFont() {
215         String[] info = new String[2];
216         info[0] = "Arial";
217         info[1] = "c:\\windows\\fonts";
218         final String[] dirs = getPlatformFontDirs(true);
219         if (dirs.length > 1) {
220             String dir = (String)
221                 AccessController.doPrivileged(new PrivilegedAction<Object>() {
222                         public Object run() {
223                             for (int i=0; i<dirs.length; i++) {
224                                 String path =
225                                     dirs[i] + File.separator + "arial.ttf";
226                                 File file = new File(path);
227                                 if (file.exists()) {
228                                     return dirs[i];
229                                 }
230                             }
231                             return null;
232                         }
233                     });
234             if (dir != null) {
235                 info[1] = dir;
236             }
237         } else {
238             info[1] = dirs[0];
239         }
240         info[1] = info[1] + File.separator + "arial.ttf";
241         return info;
242     }
243 
244     /* register only TrueType/OpenType fonts
245      * Because these need to be registed just for use when printing,
246      * we defer the actual registration and the static initialiser
247      * for the printing class makes the call to registerJREFontsForPrinting()
248      */
249     static String fontsForPrinting = null;
registerJREFontsWithPlatform(String pathName)250     protected void registerJREFontsWithPlatform(String pathName) {
251         fontsForPrinting = pathName;
252     }
253 
registerJREFontsForPrinting()254     public static void registerJREFontsForPrinting() {
255         final String pathName;
256         synchronized (Win32GraphicsEnvironment.class) {
257             GraphicsEnvironment.getLocalGraphicsEnvironment();
258             if (fontsForPrinting == null) {
259                 return;
260             }
261             pathName = fontsForPrinting;
262             fontsForPrinting = null;
263         }
264         java.security.AccessController.doPrivileged(
265             new java.security.PrivilegedAction<Object>() {
266                 public Object run() {
267                     File f1 = new File(pathName);
268                     String[] ls = f1.list(SunFontManager.getInstance().
269                             getTrueTypeFilter());
270                     if (ls == null) {
271                         return null;
272                     }
273                     for (int i=0; i <ls.length; i++ ) {
274                         File fontFile = new File(f1, ls[i]);
275                         registerFontWithPlatform(fontFile.getAbsolutePath());
276                     }
277                     return null;
278                 }
279          });
280     }
281 
registerFontWithPlatform(String fontName)282     private static native void registerFontWithPlatform(String fontName);
283 
deRegisterFontWithPlatform(String fontName)284     private static native void deRegisterFontWithPlatform(String fontName);
285 
286     /**
287      * populate the map with the most common windows fonts.
288      */
289     @Override
populateHardcodedFileNameMap()290     public HashMap<String, FamilyDescription> populateHardcodedFileNameMap() {
291         HashMap<String, FamilyDescription> platformFontMap
292             = new HashMap<String, FamilyDescription>();
293         FamilyDescription fd;
294 
295         /* Segoe UI is the default UI font for Vista and later, and
296          * is used by the Win L&F which is used by FX too.
297          * Tahoma is used for the Win L&F on XP.
298          * Verdana is used in some FX UI controls.
299          */
300         fd = new FamilyDescription();
301         fd.familyName = "Segoe UI";
302         fd.plainFullName = "Segoe UI";
303         fd.plainFileName = "segoeui.ttf";
304         fd.boldFullName = "Segoe UI Bold";
305         fd.boldFileName = "segoeuib.ttf";
306         fd.italicFullName = "Segoe UI Italic";
307         fd.italicFileName = "segoeuii.ttf";
308         fd.boldItalicFullName = "Segoe UI Bold Italic";
309         fd.boldItalicFileName = "segoeuiz.ttf";
310         platformFontMap.put("segoe", fd);
311 
312         fd = new FamilyDescription();
313         fd.familyName = "Tahoma";
314         fd.plainFullName = "Tahoma";
315         fd.plainFileName = "tahoma.ttf";
316         fd.boldFullName = "Tahoma Bold";
317         fd.boldFileName = "tahomabd.ttf";
318         platformFontMap.put("tahoma", fd);
319 
320         fd = new FamilyDescription();
321         fd.familyName = "Verdana";
322         fd.plainFullName = "Verdana";
323         fd.plainFileName = "verdana.TTF";
324         fd.boldFullName = "Verdana Bold";
325         fd.boldFileName = "verdanab.TTF";
326         fd.italicFullName = "Verdana Italic";
327         fd.italicFileName = "verdanai.TTF";
328         fd.boldItalicFullName = "Verdana Bold Italic";
329         fd.boldItalicFileName = "verdanaz.TTF";
330         platformFontMap.put("verdana", fd);
331 
332         /* The following are important because they are the core
333          * members of the default "Dialog" font.
334          */
335         fd = new FamilyDescription();
336         fd.familyName = "Arial";
337         fd.plainFullName = "Arial";
338         fd.plainFileName = "ARIAL.TTF";
339         fd.boldFullName = "Arial Bold";
340         fd.boldFileName = "ARIALBD.TTF";
341         fd.italicFullName = "Arial Italic";
342         fd.italicFileName = "ARIALI.TTF";
343         fd.boldItalicFullName = "Arial Bold Italic";
344         fd.boldItalicFileName = "ARIALBI.TTF";
345         platformFontMap.put("arial", fd);
346 
347         fd = new FamilyDescription();
348         fd.familyName = "Symbol";
349         fd.plainFullName = "Symbol";
350         fd.plainFileName = "Symbol.TTF";
351         platformFontMap.put("symbol", fd);
352 
353         fd = new FamilyDescription();
354         fd.familyName = "WingDings";
355         fd.plainFullName = "WingDings";
356         fd.plainFileName = "WINGDING.TTF";
357         platformFontMap.put("wingdings", fd);
358 
359         return platformFontMap;
360     }
361 }
362