1 /*
2  * Copyright (c) 2000, 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 sun.awt.FontConfiguration;
29 import sun.awt.X11FontManager;
30 import sun.font.FontUtilities;
31 import sun.font.SunFontManager;
32 import sun.util.logging.PlatformLogger;
33 
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.nio.charset.Charset;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.Properties;
40 import java.util.Scanner;
41 
42 public class MFontConfiguration extends FontConfiguration {
43 
44     private static FontConfiguration fontConfig = null;
45     private static PlatformLogger logger;
46 
MFontConfiguration(SunFontManager fm)47     public MFontConfiguration(SunFontManager fm) {
48         super(fm);
49         if (FontUtilities.debugFonts()) {
50             logger = PlatformLogger.getLogger("sun.awt.FontConfiguration");
51         }
52         initTables();
53     }
54 
55 
MFontConfiguration(SunFontManager fm, boolean preferLocaleFonts, boolean preferPropFonts)56     public MFontConfiguration(SunFontManager fm,
57                               boolean preferLocaleFonts,
58                               boolean preferPropFonts) {
59         super(fm, preferLocaleFonts, preferPropFonts);
60         if (FontUtilities.debugFonts()) {
61             logger = PlatformLogger.getLogger("sun.awt.FontConfiguration");
62         }
63         initTables();
64     }
65 
66     /* Needs to be kept in sync with updates in the languages used in
67      * the fontconfig files.
68      */
initReorderMap()69     protected void initReorderMap() {
70         reorderMap = new HashMap<>();
71         if (osName == null) {  /* null means SunOS */
72             initReorderMapForSolaris();
73         } else {
74             initReorderMapForLinux();
75         }
76     }
77 
initReorderMapForSolaris()78     private void initReorderMapForSolaris() {
79         /* Don't create a no-op entry, so we can optimize this case
80          * i.e. we don't need to do anything so can avoid slower paths in
81          * the code.
82          */
83 //      reorderMap.put("UTF-8", "latin-1");
84         reorderMap.put("UTF-8.hi", "devanagari"); // NB is in Lucida.
85         reorderMap.put("UTF-8.ja",
86                        split("japanese-x0201,japanese-x0208,japanese-x0212"));
87         reorderMap.put("UTF-8.ko", "korean-johab");
88         reorderMap.put("UTF-8.th", "thai");
89         reorderMap.put("UTF-8.zh.TW", "chinese-big5");
90         reorderMap.put("UTF-8.zh.HK", split("chinese-big5,chinese-hkscs"));
91         reorderMap.put("UTF-8.zh.CN",
92                        split("chinese-gb18030-0,chinese-gb18030-1"));
93         reorderMap.put("UTF-8.zh",
94                        split("chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1"));
95         reorderMap.put("Big5", "chinese-big5");
96         reorderMap.put("Big5-HKSCS", split("chinese-big5,chinese-hkscs"));
97         reorderMap.put("GB2312", split("chinese-gbk,chinese-gb2312"));
98         reorderMap.put("x-EUC-TW",
99             split("chinese-cns11643-1,chinese-cns11643-2,chinese-cns11643-3"));
100         reorderMap.put("GBK", "chinese-gbk");
101         reorderMap.put("GB18030",split("chinese-gb18030-0,chinese-gb18030-1"));
102 
103         reorderMap.put("TIS-620", "thai");
104         reorderMap.put("x-PCK",
105                        split("japanese-x0201,japanese-x0208,japanese-x0212"));
106         reorderMap.put("x-eucJP-Open",
107                        split("japanese-x0201,japanese-x0208,japanese-x0212"));
108         reorderMap.put("EUC-KR", "korean");
109         /* Don't create a no-op entry, so we can optimize this case */
110 //      reorderMap.put("ISO-8859-1", "latin-1");
111         reorderMap.put("ISO-8859-2", "latin-2");
112         reorderMap.put("ISO-8859-5", "cyrillic-iso8859-5");
113         reorderMap.put("windows-1251", "cyrillic-cp1251");
114         reorderMap.put("KOI8-R", "cyrillic-koi8-r");
115         reorderMap.put("ISO-8859-6", "arabic");
116         reorderMap.put("ISO-8859-7", "greek");
117         reorderMap.put("ISO-8859-8", "hebrew");
118         reorderMap.put("ISO-8859-9", "latin-5");
119         reorderMap.put("ISO-8859-13", "latin-7");
120         reorderMap.put("ISO-8859-15", "latin-9");
121     }
122 
initReorderMapForLinux()123     private void initReorderMapForLinux() {
124         reorderMap.put("UTF-8.ja.JP", "japanese-iso10646");
125         reorderMap.put("UTF-8.ko.KR", "korean-iso10646");
126         reorderMap.put("UTF-8.zh.TW", "chinese-tw-iso10646");
127         reorderMap.put("UTF-8.zh.HK", "chinese-tw-iso10646");
128         reorderMap.put("UTF-8.zh.CN", "chinese-cn-iso10646");
129         reorderMap.put("x-euc-jp-linux",
130                         split("japanese-x0201,japanese-x0208"));
131         reorderMap.put("GB2312", "chinese-gb18030");
132         reorderMap.put("Big5", "chinese-big5");
133         reorderMap.put("EUC-KR", "korean");
134         if (osName.equals("Sun")){
135             reorderMap.put("GB18030", "chinese-cn-iso10646");
136         }
137         else {
138             reorderMap.put("GB18030", "chinese-gb18030");
139         }
140     }
141 
142     /**
143      * Sets the OS name and version from environment information.
144      */
setOsNameAndVersion()145     protected void setOsNameAndVersion(){
146         super.setOsNameAndVersion();
147 
148         if (osName.equals("SunOS")) {
149             //don't care os name on Solaris
150             osName = null;
151         } else if (osName.equals("Linux")) {
152             try {
153                 File f;
154                 if ((f = new File("/etc/fedora-release")).canRead()) {
155                     osName = "Fedora";
156                     osVersion = getVersionString(f);
157                 } else if ((f = new File("/etc/redhat-release")).canRead()) {
158                     osName = "RedHat";
159                     osVersion = getVersionString(f);
160                 } else if ((f = new File("/etc/turbolinux-release")).canRead()) {
161                     osName = "Turbo";
162                     osVersion = getVersionString(f);
163                 } else if ((f = new File("/etc/SuSE-release")).canRead()) {
164                     osName = "SuSE";
165                     osVersion = getVersionString(f);
166                 } else if ((f = new File("/etc/lsb-release")).canRead()) {
167                     /* Ubuntu and (perhaps others) use only lsb-release.
168                      * Syntax and encoding is compatible with java properties.
169                      * For Ubuntu the ID is "Ubuntu".
170                      */
171                     Properties props = new Properties();
172                     props.load(new FileInputStream(f));
173                     osName = props.getProperty("DISTRIB_ID");
174                     osVersion =  props.getProperty("DISTRIB_RELEASE");
175                 }
176             } catch (Exception e) {
177             }
178         }
179         return;
180     }
181 
182     /**
183      * Gets the OS version string from a Linux release-specific file.
184      */
getVersionString(File f)185     private String getVersionString(File f){
186         try {
187             Scanner sc  = new Scanner(f);
188             return sc.findInLine("(\\d)+((\\.)(\\d)+)*");
189         }
190         catch (Exception e){
191         }
192         return null;
193     }
194 
195     private static final String fontsDirPrefix = "$JRE_LIB_FONTS";
196 
mapFileName(String fileName)197     protected String mapFileName(String fileName) {
198         if (fileName != null && fileName.startsWith(fontsDirPrefix)) {
199             return SunFontManager.jreFontDirName
200                     + fileName.substring(fontsDirPrefix.length());
201         }
202         return fileName;
203     }
204 
205     // overrides FontConfiguration.getFallbackFamilyName
getFallbackFamilyName(String fontName, String defaultFallback)206     public String getFallbackFamilyName(String fontName, String defaultFallback) {
207         // maintain compatibility with old font.properties files, which
208         // either had aliases for TimesRoman & Co. or defined mappings for them.
209         String compatibilityName = getCompatibilityFamilyName(fontName);
210         if (compatibilityName != null) {
211             return compatibilityName;
212         }
213         return defaultFallback;
214     }
215 
getEncoding(String awtFontName, String characterSubsetName)216     protected String getEncoding(String awtFontName,
217             String characterSubsetName) {
218         // extract encoding field from XLFD
219         int beginIndex = 0;
220         int fieldNum = 13; // charset registry field
221         while (fieldNum-- > 0 && beginIndex >= 0) {
222             beginIndex = awtFontName.indexOf("-", beginIndex) + 1;
223         }
224         if (beginIndex == -1) {
225             return "default";
226         }
227         String xlfdEncoding = awtFontName.substring(beginIndex);
228         if (xlfdEncoding.indexOf("fontspecific") > 0) {
229             if (awtFontName.indexOf("dingbats") > 0) {
230                 return "sun.font.X11Dingbats";
231             } else if (awtFontName.indexOf("symbol") > 0) {
232                 return "sun.awt.Symbol";
233             }
234         }
235         String encoding = encodingMap.get(xlfdEncoding);
236         if (encoding == null) {
237             encoding = "default";
238         }
239         return encoding;
240     }
241 
getDefaultFontCharset(String fontName)242     protected Charset getDefaultFontCharset(String fontName) {
243         return Charset.forName("ISO8859_1");
244     }
245 
getFaceNameFromComponentFontName(String componentFontName)246     protected String getFaceNameFromComponentFontName(String componentFontName) {
247         return null;
248     }
249 
getFileNameFromComponentFontName(String componentFontName)250     protected String getFileNameFromComponentFontName(String componentFontName) {
251         // for X11, component font name is XLFD
252         // if we have a file name already, just use it; otherwise let's see
253         // what the graphics environment can provide
254         String fileName = getFileNameFromPlatformName(componentFontName);
255         if (fileName != null && fileName.charAt(0) == '/' &&
256             !needToSearchForFile(fileName)) {
257             return fileName;
258         }
259         return ((X11FontManager) fontManager).getFileNameFromXLFD(componentFontName);
260     }
261 
getAWTFontPathSet()262     public HashSet<String> getAWTFontPathSet() {
263         HashSet<String> fontDirs = new HashSet<String>();
264         short[] scripts = getCoreScripts(0);
265         for (int i = 0; i< scripts.length; i++) {
266             String path = getString(table_awtfontpaths[scripts[i]]);
267             if (path != null) {
268                 int start = 0;
269                 int colon = path.indexOf(':');
270                 while (colon >= 0) {
271                     fontDirs.add(path.substring(start, colon));
272                     start = colon + 1;
273                     colon = path.indexOf(':', start);
274                 }
275                 fontDirs.add((start == 0) ? path : path.substring(start));
276             }
277         }
278         return fontDirs;
279     }
280 
281     /* methods for table setup ***********************************************/
282 
283     private static HashMap<String, String> encodingMap = new HashMap<>();
284 
initTables()285     private void initTables() {
286         // encodingMap maps XLFD encoding component to
287         // name of corresponding java.nio charset
288         encodingMap.put("iso8859-1", "ISO-8859-1");
289         encodingMap.put("iso8859-2", "ISO-8859-2");
290         encodingMap.put("iso8859-4", "ISO-8859-4");
291         encodingMap.put("iso8859-5", "ISO-8859-5");
292         encodingMap.put("iso8859-6", "ISO-8859-6");
293         encodingMap.put("iso8859-7", "ISO-8859-7");
294         encodingMap.put("iso8859-8", "ISO-8859-8");
295         encodingMap.put("iso8859-9", "ISO-8859-9");
296         encodingMap.put("iso8859-13", "ISO-8859-13");
297         encodingMap.put("iso8859-15", "ISO-8859-15");
298         encodingMap.put("gb2312.1980-0", "sun.font.X11GB2312");
299         if (osName == null) {
300             // use standard converter on Solaris
301             encodingMap.put("gbk-0", "GBK");
302         } else {
303             encodingMap.put("gbk-0", "sun.font.X11GBK");
304         }
305         encodingMap.put("gb18030.2000-0", "sun.font.X11GB18030_0");
306         encodingMap.put("gb18030.2000-1", "sun.font.X11GB18030_1");
307         encodingMap.put("cns11643-1", "sun.font.X11CNS11643P1");
308         encodingMap.put("cns11643-2", "sun.font.X11CNS11643P2");
309         encodingMap.put("cns11643-3", "sun.font.X11CNS11643P3");
310         encodingMap.put("big5-1", "Big5");
311         encodingMap.put("big5-0", "Big5");
312         encodingMap.put("hkscs-1", "Big5-HKSCS");
313         encodingMap.put("ansi-1251", "windows-1251");
314         encodingMap.put("koi8-r", "KOI8-R");
315         encodingMap.put("jisx0201.1976-0", "JIS0201");
316         encodingMap.put("jisx0208.1983-0", "JIS0208");
317         encodingMap.put("jisx0212.1990-0", "JIS0212");
318         encodingMap.put("ksc5601.1987-0", "sun.font.X11KSC5601");
319         encodingMap.put("ksc5601.1992-3", "sun.font.X11Johab");
320         encodingMap.put("tis620.2533-0", "TIS-620");
321         encodingMap.put("iso10646-1", "UTF-16BE");
322     }
323 
324 }
325