1 /*
   2  * Copyright (c) 2001, 2020, 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.awt.windows;
  27 
  28 import java.util.HashMap;
  29 import java.util.Hashtable;
  30 import sun.awt.FontDescriptor;
  31 import sun.awt.FontConfiguration;
  32 import sun.font.SunFontManager;
  33 import java.nio.charset.*;
  34 
  35 public final class WFontConfiguration extends FontConfiguration {
  36 
  37     // whether compatibility fallbacks for TimesRoman and Co. are used
  38     private boolean useCompatibilityFallbacks;
  39 
  40     public WFontConfiguration(SunFontManager fm) {
  41         super(fm);
  42         useCompatibilityFallbacks = "windows-1252".equals(encoding);
  43         initTables(encoding);
  44     }
  45 
  46     public WFontConfiguration(SunFontManager fm,
  47                               boolean preferLocaleFonts,
  48                               boolean preferPropFonts) {
  49         super(fm, preferLocaleFonts, preferPropFonts);
  50         useCompatibilityFallbacks = "windows-1252".equals(encoding);
  51     }
  52 
  53     @Override
  54     protected void initReorderMap() {
  55         if (encoding.equalsIgnoreCase("windows-31j")) {
  56             localeMap = new Hashtable<>();
  57             /* Substitute Mincho for Gothic in this one case.
  58              * Note the windows fontconfig files already contain the mapping:
  59              * filename.MS_Mincho=MSMINCHO.TTC
  60              * which isn't essential to this usage but avoids a call
  61              * to loadfonts in the event MSMINCHO.TTC has not otherwise
  62              * been opened and its fonts loaded.
  63              * Also note this usage is only enabled if a private flag is set.
  64              */
  65             localeMap.put("dialoginput.plain.japanese", "MS Mincho");
  66             localeMap.put("dialoginput.bold.japanese", "MS Mincho");
  67             localeMap.put("dialoginput.italic.japanese", "MS Mincho");
  68             localeMap.put("dialoginput.bolditalic.japanese", "MS Mincho");
  69         }
  70         reorderMap = new HashMap<>();
  71         reorderMap.put("UTF-8.hi", "devanagari");
  72         reorderMap.put("windows-1255", "hebrew");
  73         reorderMap.put("x-windows-874", "thai");
  74         reorderMap.put("windows-31j", "japanese");
  75         reorderMap.put("x-windows-949", "korean");
  76         reorderMap.put("GBK", "chinese-ms936");
  77         reorderMap.put("GB18030", "chinese-gb18030");
  78         reorderMap.put("x-windows-950", "chinese-ms950");
  79         reorderMap.put("x-MS950-HKSCS", split("chinese-ms950,chinese-hkscs"));
  80 //      reorderMap.put("windows-1252", "alphabetic");
  81     }
  82 
  83     @Override
  84     protected void setOsNameAndVersion(){
  85         super.setOsNameAndVersion();
  86         if (osName.startsWith("Windows")){
  87             int p, q;
  88             p = osName.indexOf(' ');
  89             if (p == -1){
  90                 osName = null;
  91             }
  92             else{
  93                 q = osName.indexOf(' ', p + 1);
  94                 if (q == -1){
  95                     osName = osName.substring(p + 1);
  96                 }
  97                 else{
  98                     osName = osName.substring(p + 1, q);
  99                 }
 100             }
 101             osVersion = null;
 102         }
 103     }
 104 
 105     // overrides FontConfiguration.getFallbackFamilyName
 106     @Override
 107     public String getFallbackFamilyName(String fontName, String defaultFallback) {
 108         // maintain compatibility with old font.properties files, where
 109         // default file had aliases for timesroman & Co, while others didn't.
 110         if (useCompatibilityFallbacks) {
 111             String compatibilityName = getCompatibilityFamilyName(fontName);
 112             if (compatibilityName != null) {
 113                 return compatibilityName;
 114             }
 115         }
 116         return defaultFallback;
 117     }
 118 
 119     @Override
 120     protected String makeAWTFontName(String platformFontName, String characterSubsetName) {
 121         String windowsCharset = subsetCharsetMap.get(characterSubsetName);
 122         if (windowsCharset == null) {
 123             windowsCharset = "DEFAULT_CHARSET";
 124         }
 125         return platformFontName + "," + windowsCharset;
 126     }
 127 
 128     @Override
 129     protected String getEncoding(String awtFontName, String characterSubsetName) {
 130         String encoding = subsetEncodingMap.get(characterSubsetName);
 131         if (encoding == null) {
 132             encoding = "default";
 133         }
 134         return encoding;
 135     }
 136 
 137     @Override
 138     protected Charset getDefaultFontCharset(String fontName) {
 139         return new WDefaultFontCharset(fontName);
 140     }
 141 
 142     @Override
 143     public String getFaceNameFromComponentFontName(String componentFontName) {
 144         // for Windows, the platform name is the face name
 145         return componentFontName;
 146     }
 147 
 148     @Override
 149     protected String getFileNameFromComponentFontName(String componentFontName) {
 150         return getFileNameFromPlatformName(componentFontName);
 151     }
 152 
 153     /**
 154      * Returns the component font name (face name plus charset) of the
 155      * font that should be used for AWT text components.
 156      */
 157     public String getTextComponentFontName(String familyName, int style) {
 158         FontDescriptor[] fontDescriptors = getFontDescriptors(familyName, style);
 159         String fontName = findFontWithCharset(fontDescriptors, textInputCharset);
 160         if ((fontName == null) && !textInputCharset.equals("DEFAULT_CHARSET")) {
 161             fontName = findFontWithCharset(fontDescriptors, "DEFAULT_CHARSET");
 162         }
 163         if (fontName == null) {
 164             fontName = (fontDescriptors.length > 0) ? fontDescriptors[0].getNativeName()
 165                                                     : "Arial.ANSI_CHARSET";
 166         }
 167         return fontName;
 168     }
 169 
 170     private String findFontWithCharset(FontDescriptor[] fontDescriptors, String charset) {
 171         String fontName = null;
 172         for (int i = 0; i < fontDescriptors.length; i++) {
 173             String componentFontName = fontDescriptors[i].getNativeName();
 174             if (componentFontName.endsWith(charset)) {
 175                 fontName = componentFontName;
 176             }
 177         }
 178         return fontName;
 179     }
 180 
 181     private static HashMap<String, String> subsetCharsetMap = new HashMap<>();
 182     private static HashMap<String, String> subsetEncodingMap = new HashMap<>();
 183     private static String textInputCharset;
 184 
 185     private void initTables(String defaultEncoding) {
 186         subsetCharsetMap.put("alphabetic", "ANSI_CHARSET");
 187         subsetCharsetMap.put("alphabetic/1252", "ANSI_CHARSET");
 188         subsetCharsetMap.put("alphabetic/default", "DEFAULT_CHARSET");
 189         subsetCharsetMap.put("arabic", "ARABIC_CHARSET");
 190         subsetCharsetMap.put("chinese-ms936", "GB2312_CHARSET");
 191         subsetCharsetMap.put("chinese-gb18030", "GB2312_CHARSET");
 192         subsetCharsetMap.put("chinese-ms950", "CHINESEBIG5_CHARSET");
 193         subsetCharsetMap.put("chinese-hkscs", "CHINESEBIG5_CHARSET");
 194         subsetCharsetMap.put("cyrillic", "RUSSIAN_CHARSET");
 195         subsetCharsetMap.put("devanagari", "DEFAULT_CHARSET");
 196         subsetCharsetMap.put("dingbats", "SYMBOL_CHARSET");
 197         subsetCharsetMap.put("greek", "GREEK_CHARSET");
 198         subsetCharsetMap.put("hebrew", "HEBREW_CHARSET");
 199         subsetCharsetMap.put("japanese", "SHIFTJIS_CHARSET");
 200         subsetCharsetMap.put("korean", "HANGEUL_CHARSET");
 201         subsetCharsetMap.put("latin", "ANSI_CHARSET");
 202         subsetCharsetMap.put("symbol", "SYMBOL_CHARSET");
 203         subsetCharsetMap.put("thai", "THAI_CHARSET");
 204 
 205         subsetEncodingMap.put("alphabetic", "default");
 206         subsetEncodingMap.put("alphabetic/1252", "windows-1252");
 207         subsetEncodingMap.put("alphabetic/default", defaultEncoding);
 208         subsetEncodingMap.put("arabic", "windows-1256");
 209         subsetEncodingMap.put("chinese-ms936", "GBK");
 210         subsetEncodingMap.put("chinese-gb18030", "GB18030");
 211         if ("x-MS950-HKSCS".equals(defaultEncoding)) {
 212             subsetEncodingMap.put("chinese-ms950", "x-MS950-HKSCS");
 213         } else {
 214             subsetEncodingMap.put("chinese-ms950", "x-windows-950"); //MS950
 215         }
 216         subsetEncodingMap.put("chinese-hkscs", "sun.awt.HKSCS");
 217         subsetEncodingMap.put("cyrillic", "windows-1251");
 218         subsetEncodingMap.put("devanagari", "UTF-16LE");
 219         subsetEncodingMap.put("dingbats", "sun.awt.windows.WingDings");
 220         subsetEncodingMap.put("greek", "windows-1253");
 221         subsetEncodingMap.put("hebrew", "windows-1255");
 222         subsetEncodingMap.put("japanese", "windows-31j");
 223         subsetEncodingMap.put("korean", "x-windows-949");
 224         subsetEncodingMap.put("latin", "windows-1252");
 225         subsetEncodingMap.put("symbol", "sun.awt.Symbol");
 226         subsetEncodingMap.put("thai", "x-windows-874");
 227 
 228         if ("windows-1256".equals(defaultEncoding)) {
 229             textInputCharset = "ARABIC_CHARSET";
 230         } else if ("GBK".equals(defaultEncoding)) {
 231             textInputCharset = "GB2312_CHARSET";
 232         } else if ("GB18030".equals(defaultEncoding)) {
 233             textInputCharset = "GB2312_CHARSET";
 234         } else if ("x-windows-950".equals(defaultEncoding)) {
 235             textInputCharset = "CHINESEBIG5_CHARSET";
 236         } else if ("x-MS950-HKSCS".equals(defaultEncoding)) {
 237             textInputCharset = "CHINESEBIG5_CHARSET";
 238         } else if ("windows-1251".equals(defaultEncoding)) {
 239             textInputCharset = "RUSSIAN_CHARSET";
 240         } else if ("UTF-8".equals(defaultEncoding)) {
 241             textInputCharset = "DEFAULT_CHARSET";
 242         } else if ("windows-1253".equals(defaultEncoding)) {
 243             textInputCharset = "GREEK_CHARSET";
 244         } else if ("windows-1255".equals(defaultEncoding)) {
 245             textInputCharset = "HEBREW_CHARSET";
 246         } else if ("windows-31j".equals(defaultEncoding)) {
 247             textInputCharset = "SHIFTJIS_CHARSET";
 248         } else if ("x-windows-949".equals(defaultEncoding)) {
 249             textInputCharset = "HANGEUL_CHARSET";
 250         } else if ("x-windows-874".equals(defaultEncoding)) {
 251             textInputCharset = "THAI_CHARSET";
 252         } else {
 253             textInputCharset = "DEFAULT_CHARSET";
 254         }
 255     }
 256 }