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