src/share/classes/sun/awt/FontConfiguration.java

Print this page
rev 1297 : [mq]: fontmanager.patch


  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package sun.awt;
  27 
  28 import java.awt.Font;
  29 import java.io.DataInputStream;
  30 import java.io.DataOutputStream;
  31 import java.io.File;
  32 import java.io.FileInputStream;
  33 import java.io.FileOutputStream;
  34 import java.io.InputStream;
  35 import java.io.IOException;
  36 import java.io.OutputStream;
  37 import java.nio.charset.Charset;
  38 import java.nio.charset.CharsetEncoder;
  39 import java.security.AccessController;
  40 import java.security.PrivilegedAction;
  41 import java.util.logging.Logger;
  42 import java.util.HashMap;
  43 import java.util.HashSet;
  44 import java.util.Hashtable;
  45 import java.util.Iterator;
  46 import java.util.Locale;
  47 import java.util.Map.Entry;
  48 import java.util.Properties;
  49 import java.util.Set;
  50 import java.util.Vector;
  51 import sun.font.CompositeFontDescriptor;
  52 import sun.java2d.SunGraphicsEnvironment;


  53 
  54 /**
  55  * Provides the definitions of the five logical fonts: Serif, SansSerif,
  56  * Monospaced, Dialog, and DialogInput. The necessary information
  57  * is obtained from fontconfig files.
  58  */
  59 public abstract class FontConfiguration {
  60 
  61     //static global runtime env
  62     protected static String osVersion;
  63     protected static String osName;
  64     protected static String encoding; // canonical name of default nio charset
  65     protected static Locale startupLocale = null;
  66     protected static Hashtable localeMap = null;
  67     private static FontConfiguration fontConfig;
  68     private static Logger logger;
  69     protected static boolean isProperties = true;
  70 
  71     protected SunGraphicsEnvironment environment;
  72     protected boolean preferLocaleFonts;
  73     protected boolean preferPropFonts;
  74 
  75     private File fontConfigFile;
  76     private boolean foundOsSpecificFile;
  77     private boolean inited;
  78     private String javaLib;
  79 
  80     /* A default FontConfiguration must be created before an alternate
  81      * one to ensure proper static initialisation takes place.
  82      */
  83     public FontConfiguration(SunGraphicsEnvironment environment) {
  84         if (SunGraphicsEnvironment.debugFonts && logger == null) {
  85             logger = Logger.getLogger("sun.awt.FontConfiguration");
  86         }
  87         this.environment = environment;
  88         setOsNameAndVersion();  /* static initialization */
  89         setEncoding();          /* static initialization */
  90         /* Separating out the file location from the rest of the
  91          * initialisation, so the caller has the option of doing
  92          * something else if a suitable file isn't found.
  93          */
  94         findFontConfigFile();
  95     }
  96 
  97     public synchronized boolean init() {
  98         if (!inited) {
  99             this.preferLocaleFonts = false;
 100             this.preferPropFonts = false;
 101             setFontConfiguration();
 102             readFontConfigFile(fontConfigFile);
 103             initFontConfig();
 104             inited = true;
 105         }
 106         return true;
 107     }
 108 
 109     public FontConfiguration(SunGraphicsEnvironment environment,
 110                              boolean preferLocaleFonts,
 111                              boolean preferPropFonts) {
 112         this.environment = environment;
 113         this.preferLocaleFonts = preferLocaleFonts;
 114         this.preferPropFonts = preferPropFonts;
 115         /* fontConfig should be initialised by default constructor, and
 116          * its data tables can be shared, since readFontConfigFile doesn't
 117          * update any other state. Also avoid a doPrivileged block.
 118          */
 119         initFontConfig();
 120     }
 121 
 122     /**
 123      * Fills in this instance's osVersion and osName members. By
 124      * default uses the system properties os.name and os.version;
 125      * subclasses may override.
 126      */
 127     protected void setOsNameAndVersion() {
 128         osName = System.getProperty("os.name");
 129         osVersion = System.getProperty("os.version");
 130     }
 131 
 132     private void setEncoding() {


 181         }
 182     }
 183 
 184     private void readFontConfigFile(File f) {
 185         /* This is invoked here as readFontConfigFile is only invoked
 186          * once per VM, and always in a privileged context, thus the
 187          * directory containing installed fall back fonts is accessed
 188          * from this context
 189          */
 190         getInstalledFallbackFonts(javaLib);
 191 
 192         if (f != null) {
 193             try {
 194                 FileInputStream in = new FileInputStream(f.getPath());
 195                 if (isProperties) {
 196                     loadProperties(in);
 197                 } else {
 198                     loadBinary(in);
 199                 }
 200                 in.close();
 201                 if (SunGraphicsEnvironment.debugFonts) {
 202                     logger.config("Read logical font configuration from " + f);
 203                 }
 204             } catch (IOException e) {
 205                 if (SunGraphicsEnvironment.debugFonts) {
 206                     logger.config("Failed to read logical font configuration from " + f);
 207                 }
 208             }
 209         }
 210         String version = getVersion();
 211         if (!"1".equals(version) && SunGraphicsEnvironment.debugFonts) {
 212             logger.config("Unsupported fontconfig version: " + version);
 213         }
 214     }
 215 
 216     protected void getInstalledFallbackFonts(String javaLib) {
 217         String fallbackDirName = javaLib + File.separator +
 218             "fonts" + File.separator + "fallback";
 219 
 220         File fallbackDir = new File(fallbackDirName);
 221         if (fallbackDir.exists() && fallbackDir.isDirectory()) {
 222             String[] ttfs = fallbackDir.list(SunGraphicsEnvironment.ttFilter);
 223             String[] t1s = fallbackDir.list(SunGraphicsEnvironment.t1Filter);
 224             int numTTFs = (ttfs == null) ? 0 : ttfs.length;
 225             int numT1s = (t1s == null) ? 0 : t1s.length;
 226             int len = numTTFs + numT1s;
 227             if (numTTFs + numT1s == 0) {
 228                 return;
 229             }
 230             installedFallbackFontFiles = new String[len];
 231             for (int i=0; i<numTTFs; i++) {
 232                 installedFallbackFontFiles[i] =
 233                     fallbackDir + File.separator + ttfs[i];
 234             }
 235             for (int i=0; i<numT1s; i++) {
 236                 installedFallbackFontFiles[i+numTTFs] =
 237                     fallbackDir + File.separator + t1s[i];
 238             }
 239             environment.registerFontsInDir(fallbackDirName);
 240         }
 241     }
 242 
 243     private File findImpl(String fname) {
 244         File f = new File(fname + ".properties");
 245         if (f.canRead()) {
 246             isProperties = true;
 247             return f;
 248         }
 249         f = new File(fname + ".bfc");
 250         if (f.canRead()) {
 251             isProperties = false;
 252             return f;
 253         }
 254         return null;
 255     }
 256 
 257     private File findFontConfigFile(String javaLib) {
 258         String baseName = javaLib + File.separator + "fontconfig";
 259         File configFile;


 448             System.out.println("coreScriptID=" + table_sequences[initELC * 5 + fontIndex]);
 449             for (int i = 0; i < coreScripts.length; i++) {
 450             System.out.println("  " + i + " :" + getString(table_scriptIDs[coreScripts[i]]));
 451             }
 452             */
 453             //init exclusionRanges
 454             int[][] exclusions = new int[coreScripts.length][];
 455             for (int i = 0; i < coreScripts.length; i++) {
 456                 exclusions[i] = getExclusionRanges(coreScripts[i]);
 457             }
 458             compExclusions[fontIndex] = exclusions;
 459             //init componentFontNames
 460             for (int styleIndex = 0; styleIndex < NUM_STYLES; styleIndex++) {
 461                 int index;
 462                 short[] nameIDs = new short[coreScripts.length + fallbackScripts.length];
 463                 //core
 464                 for (index = 0; index < coreScripts.length; index++) {
 465                     nameIDs[index] = getComponentFontID(coreScripts[index],
 466                                                fontIndex, styleIndex);
 467                     if (preferLocaleFonts && localeMap != null &&
 468                         sun.font.FontManager.usingAlternateFontforJALocales()) {
 469                         nameIDs[index] = remapLocaleMap(fontIndex, styleIndex,
 470                                                         coreScripts[index], nameIDs[index]);
 471                     }
 472                     if (preferPropFonts) {
 473                         nameIDs[index] = remapProportional(fontIndex, nameIDs[index]);
 474                     }
 475                     //System.out.println("nameid=" + nameIDs[index]);
 476                     coreFontNameIDs.add(nameIDs[index]);
 477                 }
 478                 //fallback
 479                 for (int i = 0; i < fallbackScripts.length; i++) {
 480                     short id = getComponentFontID(fallbackScripts[i],
 481                                                fontIndex, styleIndex);
 482                     if (preferLocaleFonts && localeMap != null &&
 483                         sun.font.FontManager.usingAlternateFontforJALocales()) {
 484                         id = remapLocaleMap(fontIndex, styleIndex, fallbackScripts[i], id);
 485                     }
 486                     if (preferPropFonts) {
 487                         id = remapProportional(fontIndex, id);
 488                     }
 489                     if (contains(nameIDs, id, index)) {
 490                         continue;
 491                     }
 492                     /*
 493                       System.out.println("fontIndex=" + fontIndex + ", styleIndex=" + styleIndex
 494                            + ", fbIndex=" + i + ",fbS=" + fallbackScripts[i] + ", id=" + id);
 495                     */
 496                     fallbackFontNameIDs.add(id);
 497                     nameIDs[index++] = id;
 498                 }
 499                 if (index < nameIDs.length) {
 500                     short[] newNameIDs = new short[index];
 501                     System.arraycopy(nameIDs, 0, newNameIDs, 0, index);
 502                     nameIDs = newNameIDs;
 503                 }


 956      * returns null, its expected that X11 platforms may return
 957      * non-null.
 958      */
 959     public HashSet<String> getAWTFontPathSet() {
 960         return null;
 961     }
 962 
 963     ////////////////////////////////////////////////////////////////////////
 964     // methods for extracting information from the fontconfig data for 2D //
 965     ////////////////////////////////////////////////////////////////////////
 966 
 967     /**
 968      * Returns an array of composite font descriptors for all logical font
 969      * faces.
 970      * If the font configuration file doesn't specify Lucida Sans Regular
 971      * or the given fallback font as component fonts, they are added here.
 972      */
 973     public CompositeFontDescriptor[] get2DCompositeFontInfo() {
 974         CompositeFontDescriptor[] result =
 975                 new CompositeFontDescriptor[NUM_FONTS * NUM_STYLES];
 976         String defaultFontFile = environment.getDefaultFontFile();
 977         String defaultFontFaceName = environment.getDefaultFontFaceName();
 978 
 979         for (int fontIndex = 0; fontIndex < NUM_FONTS; fontIndex++) {
 980             String fontName = publicFontNames[fontIndex];
 981 
 982             // determine exclusion ranges for font
 983             // AWT uses separate exclusion range array per component font.
 984             // 2D packs all range boundaries into one array.
 985             // Both use separate entries for lower and upper boundary.
 986             int[][] exclusions = compExclusions[fontIndex];
 987             int numExclusionRanges = 0;
 988             for (int i = 0; i < exclusions.length; i++) {
 989                 numExclusionRanges += exclusions[i].length;
 990             }
 991             int[] exclusionRanges = new int[numExclusionRanges];
 992             int[] exclusionRangeLimits = new int[exclusions.length];
 993             int exclusionRangeIndex = 0;
 994             int exclusionRangeLimitIndex = 0;
 995             for (int i = 0; i < exclusions.length; i++) {
 996                 int[] componentRanges = exclusions[i];
 997                 for (int j = 0; j < componentRanges.length; ) {


1104     }
1105 
1106     protected abstract String getFaceNameFromComponentFontName(String componentFontName);
1107     protected abstract String getFileNameFromComponentFontName(String componentFontName);
1108 
1109     /*
1110     public class 2dFont {
1111         public String platformName;
1112         public String fontfileName;
1113     }
1114     private 2dFont [] componentFonts = null;
1115     */
1116 
1117     /* Used on Linux to test if a file referenced in a font configuration
1118      * file exists in the location that is expected. If it does, no need
1119      * to search for it. If it doesn't then unless its a fallback font,
1120      * return that expensive code should be invoked to search for the font.
1121      */
1122     HashMap<String, Boolean> existsMap;
1123     public boolean needToSearchForFile(String fileName) {
1124         if (!environment.isLinux) {
1125             return false;
1126         } else if (existsMap == null) {
1127            existsMap = new HashMap<String, Boolean>();
1128         }
1129         Boolean exists = existsMap.get(fileName);
1130         if (exists == null) {
1131             /* call getNumberCoreFonts() to ensure these are initialised, and
1132              * if this file isn't for a core component, ie, is a for a fallback
1133              * font which very typically isn't available, then can't afford
1134              * to take the start-up penalty to search for it.
1135              */
1136             getNumberCoreFonts();
1137             if (!coreFontFileNames.contains(fileName)) {
1138                 exists = Boolean.TRUE;
1139             } else {
1140                 exists = Boolean.valueOf((new File(fileName)).exists());
1141                 existsMap.put(fileName, exists);
1142                 if (SunGraphicsEnvironment.debugFonts &&
1143                     exists == Boolean.FALSE) {
1144                     logger.warning("Couldn't locate font file " + fileName);
1145                 }
1146             }
1147         }
1148         return exists == Boolean.FALSE;
1149     }
1150 
1151     private int numCoreFonts = -1;
1152     private String[] componentFonts = null;
1153     HashMap <String, String> filenamesMap = new HashMap<String, String>();
1154     HashSet <String> coreFontFileNames = new HashSet<String>();
1155 
1156     /* Return the number of core fonts. Note this isn't thread safe but
1157      * a calling thread can call this and getPlatformFontNames() in either
1158      * order.
1159      */
1160     public int getNumberCoreFonts() {
1161         if (numCoreFonts == -1) {
1162             numCoreFonts = coreFontNameIDs.size();


2050                     lower = exclusions.substring(pos, newPos);
2051                     pos = newPos + 1;
2052                     newPos = exclusions.indexOf(',', pos);
2053                     if (newPos == -1) {
2054                         newPos = exclusions.length();
2055                     }
2056                     upper = exclusions.substring(pos, newPos);
2057                     pos = newPos + 1;
2058                     int lowerLength = lower.length();
2059                     int upperLength = upper.length();
2060                     if (lowerLength != 4 && lowerLength != 6
2061                         || upperLength != 4 && upperLength != 6) {
2062                         throw new Exception();
2063                     }
2064                     lo = Integer.parseInt(lower, 16);
2065                     up = Integer.parseInt(upper, 16);
2066                     if (lo > up) {
2067                         throw new Exception();
2068                     }
2069                 } catch (Exception e) {
2070                     if (SunGraphicsEnvironment.debugFonts && logger != null) {

2071                         logger.config("Failed parsing " + key +
2072                                   " property of font configuration.");
2073 
2074                     }
2075                     return EMPTY_INT_ARRAY;
2076                 }
2077                 exclusionRanges[j++] = lo;
2078                 exclusionRanges[j++] = up;
2079             }
2080             return exclusionRanges;
2081         }
2082 
2083         private Short getID(HashMap<String, Short> map, String key) {
2084             Short ret = map.get(key);
2085             if ( ret == null) {
2086                 map.put(key, (short)map.size());
2087                 return map.get(key);
2088             }
2089             return ret;
2090         }




  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package sun.awt;
  27 
  28 import java.awt.Font;
  29 import java.io.DataInputStream;
  30 import java.io.DataOutputStream;
  31 import java.io.File;
  32 import java.io.FileInputStream;

  33 import java.io.InputStream;
  34 import java.io.IOException;
  35 import java.io.OutputStream;
  36 import java.nio.charset.Charset;
  37 import java.nio.charset.CharsetEncoder;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 import java.util.logging.Logger;
  41 import java.util.HashMap;
  42 import java.util.HashSet;
  43 import java.util.Hashtable;
  44 import java.util.Iterator;
  45 import java.util.Locale;
  46 import java.util.Map.Entry;
  47 import java.util.Properties;
  48 import java.util.Set;
  49 import java.util.Vector;
  50 import sun.font.CompositeFontDescriptor;
  51 import sun.font.SunFontManager;
  52 import sun.font.FontManagerFactory;
  53 import sun.font.FontUtilities;
  54 
  55 /**
  56  * Provides the definitions of the five logical fonts: Serif, SansSerif,
  57  * Monospaced, Dialog, and DialogInput. The necessary information
  58  * is obtained from fontconfig files.
  59  */
  60 public abstract class FontConfiguration {
  61 
  62     //static global runtime env
  63     protected static String osVersion;
  64     protected static String osName;
  65     protected static String encoding; // canonical name of default nio charset
  66     protected static Locale startupLocale = null;
  67     protected static Hashtable localeMap = null;
  68     private static FontConfiguration fontConfig;
  69     private static Logger logger;
  70     protected static boolean isProperties = true;
  71 
  72     protected SunFontManager fontManager;
  73     protected boolean preferLocaleFonts;
  74     protected boolean preferPropFonts;
  75 
  76     private File fontConfigFile;
  77     private boolean foundOsSpecificFile;
  78     private boolean inited;
  79     private String javaLib;
  80 
  81     /* A default FontConfiguration must be created before an alternate
  82      * one to ensure proper static initialisation takes place.
  83      */
  84     public FontConfiguration(SunFontManager fm) {
  85         if (FontUtilities.debugFonts() && logger == null) {
  86             logger = Logger.getLogger("sun.awt.FontConfiguration");
  87         }
  88         fontManager = fm;
  89         setOsNameAndVersion();  /* static initialization */
  90         setEncoding();          /* static initialization */
  91         /* Separating out the file location from the rest of the
  92          * initialisation, so the caller has the option of doing
  93          * something else if a suitable file isn't found.
  94          */
  95         findFontConfigFile();
  96     }
  97 
  98     public synchronized boolean init() {
  99         if (!inited) {
 100             this.preferLocaleFonts = false;
 101             this.preferPropFonts = false;
 102             setFontConfiguration();
 103             readFontConfigFile(fontConfigFile);
 104             initFontConfig();
 105             inited = true;
 106         }
 107         return true;
 108     }
 109 
 110     public FontConfiguration(SunFontManager fm,
 111                              boolean preferLocaleFonts,
 112                              boolean preferPropFonts) {
 113         fontManager = fm;
 114         this.preferLocaleFonts = preferLocaleFonts;
 115         this.preferPropFonts = preferPropFonts;
 116         /* fontConfig should be initialised by default constructor, and
 117          * its data tables can be shared, since readFontConfigFile doesn't
 118          * update any other state. Also avoid a doPrivileged block.
 119          */
 120         initFontConfig();
 121     }
 122 
 123     /**
 124      * Fills in this instance's osVersion and osName members. By
 125      * default uses the system properties os.name and os.version;
 126      * subclasses may override.
 127      */
 128     protected void setOsNameAndVersion() {
 129         osName = System.getProperty("os.name");
 130         osVersion = System.getProperty("os.version");
 131     }
 132 
 133     private void setEncoding() {


 182         }
 183     }
 184 
 185     private void readFontConfigFile(File f) {
 186         /* This is invoked here as readFontConfigFile is only invoked
 187          * once per VM, and always in a privileged context, thus the
 188          * directory containing installed fall back fonts is accessed
 189          * from this context
 190          */
 191         getInstalledFallbackFonts(javaLib);
 192 
 193         if (f != null) {
 194             try {
 195                 FileInputStream in = new FileInputStream(f.getPath());
 196                 if (isProperties) {
 197                     loadProperties(in);
 198                 } else {
 199                     loadBinary(in);
 200                 }
 201                 in.close();
 202                 if (FontUtilities.debugFonts()) {
 203                     logger.config("Read logical font configuration from " + f);
 204                 }
 205             } catch (IOException e) {
 206                 if (FontUtilities.debugFonts()) {
 207                     logger.config("Failed to read logical font configuration from " + f);
 208                 }
 209             }
 210         }
 211         String version = getVersion();
 212         if (!"1".equals(version) && FontUtilities.debugFonts()) {
 213             logger.config("Unsupported fontconfig version: " + version);
 214         }
 215     }
 216 
 217     protected void getInstalledFallbackFonts(String javaLib) {
 218         String fallbackDirName = javaLib + File.separator +
 219             "fonts" + File.separator + "fallback";
 220 
 221         File fallbackDir = new File(fallbackDirName);
 222         if (fallbackDir.exists() && fallbackDir.isDirectory()) {
 223             String[] ttfs = fallbackDir.list(fontManager.getTrueTypeFilter());
 224             String[] t1s = fallbackDir.list(fontManager.getType1Filter());
 225             int numTTFs = (ttfs == null) ? 0 : ttfs.length;
 226             int numT1s = (t1s == null) ? 0 : t1s.length;
 227             int len = numTTFs + numT1s;
 228             if (numTTFs + numT1s == 0) {
 229                 return;
 230             }
 231             installedFallbackFontFiles = new String[len];
 232             for (int i=0; i<numTTFs; i++) {
 233                 installedFallbackFontFiles[i] =
 234                     fallbackDir + File.separator + ttfs[i];
 235             }
 236             for (int i=0; i<numT1s; i++) {
 237                 installedFallbackFontFiles[i+numTTFs] =
 238                     fallbackDir + File.separator + t1s[i];
 239             }
 240             fontManager.registerFontsInDir(fallbackDirName);
 241         }
 242     }
 243 
 244     private File findImpl(String fname) {
 245         File f = new File(fname + ".properties");
 246         if (f.canRead()) {
 247             isProperties = true;
 248             return f;
 249         }
 250         f = new File(fname + ".bfc");
 251         if (f.canRead()) {
 252             isProperties = false;
 253             return f;
 254         }
 255         return null;
 256     }
 257 
 258     private File findFontConfigFile(String javaLib) {
 259         String baseName = javaLib + File.separator + "fontconfig";
 260         File configFile;


 449             System.out.println("coreScriptID=" + table_sequences[initELC * 5 + fontIndex]);
 450             for (int i = 0; i < coreScripts.length; i++) {
 451             System.out.println("  " + i + " :" + getString(table_scriptIDs[coreScripts[i]]));
 452             }
 453             */
 454             //init exclusionRanges
 455             int[][] exclusions = new int[coreScripts.length][];
 456             for (int i = 0; i < coreScripts.length; i++) {
 457                 exclusions[i] = getExclusionRanges(coreScripts[i]);
 458             }
 459             compExclusions[fontIndex] = exclusions;
 460             //init componentFontNames
 461             for (int styleIndex = 0; styleIndex < NUM_STYLES; styleIndex++) {
 462                 int index;
 463                 short[] nameIDs = new short[coreScripts.length + fallbackScripts.length];
 464                 //core
 465                 for (index = 0; index < coreScripts.length; index++) {
 466                     nameIDs[index] = getComponentFontID(coreScripts[index],
 467                                                fontIndex, styleIndex);
 468                     if (preferLocaleFonts && localeMap != null &&
 469                             fontManager.usingAlternateFontforJALocales()) {
 470                         nameIDs[index] = remapLocaleMap(fontIndex, styleIndex,
 471                                                         coreScripts[index], nameIDs[index]);
 472                     }
 473                     if (preferPropFonts) {
 474                         nameIDs[index] = remapProportional(fontIndex, nameIDs[index]);
 475                     }
 476                     //System.out.println("nameid=" + nameIDs[index]);
 477                     coreFontNameIDs.add(nameIDs[index]);
 478                 }
 479                 //fallback
 480                 for (int i = 0; i < fallbackScripts.length; i++) {
 481                     short id = getComponentFontID(fallbackScripts[i],
 482                                                fontIndex, styleIndex);
 483                     if (preferLocaleFonts && localeMap != null &&
 484                             fontManager.usingAlternateFontforJALocales()) {
 485                         id = remapLocaleMap(fontIndex, styleIndex, fallbackScripts[i], id);
 486                     }
 487                     if (preferPropFonts) {
 488                         id = remapProportional(fontIndex, id);
 489                     }
 490                     if (contains(nameIDs, id, index)) {
 491                         continue;
 492                     }
 493                     /*
 494                       System.out.println("fontIndex=" + fontIndex + ", styleIndex=" + styleIndex
 495                            + ", fbIndex=" + i + ",fbS=" + fallbackScripts[i] + ", id=" + id);
 496                     */
 497                     fallbackFontNameIDs.add(id);
 498                     nameIDs[index++] = id;
 499                 }
 500                 if (index < nameIDs.length) {
 501                     short[] newNameIDs = new short[index];
 502                     System.arraycopy(nameIDs, 0, newNameIDs, 0, index);
 503                     nameIDs = newNameIDs;
 504                 }


 957      * returns null, its expected that X11 platforms may return
 958      * non-null.
 959      */
 960     public HashSet<String> getAWTFontPathSet() {
 961         return null;
 962     }
 963 
 964     ////////////////////////////////////////////////////////////////////////
 965     // methods for extracting information from the fontconfig data for 2D //
 966     ////////////////////////////////////////////////////////////////////////
 967 
 968     /**
 969      * Returns an array of composite font descriptors for all logical font
 970      * faces.
 971      * If the font configuration file doesn't specify Lucida Sans Regular
 972      * or the given fallback font as component fonts, they are added here.
 973      */
 974     public CompositeFontDescriptor[] get2DCompositeFontInfo() {
 975         CompositeFontDescriptor[] result =
 976                 new CompositeFontDescriptor[NUM_FONTS * NUM_STYLES];
 977         String defaultFontFile = fontManager.getDefaultFontFile();
 978         String defaultFontFaceName = fontManager.getDefaultFontFaceName();
 979 
 980         for (int fontIndex = 0; fontIndex < NUM_FONTS; fontIndex++) {
 981             String fontName = publicFontNames[fontIndex];
 982 
 983             // determine exclusion ranges for font
 984             // AWT uses separate exclusion range array per component font.
 985             // 2D packs all range boundaries into one array.
 986             // Both use separate entries for lower and upper boundary.
 987             int[][] exclusions = compExclusions[fontIndex];
 988             int numExclusionRanges = 0;
 989             for (int i = 0; i < exclusions.length; i++) {
 990                 numExclusionRanges += exclusions[i].length;
 991             }
 992             int[] exclusionRanges = new int[numExclusionRanges];
 993             int[] exclusionRangeLimits = new int[exclusions.length];
 994             int exclusionRangeIndex = 0;
 995             int exclusionRangeLimitIndex = 0;
 996             for (int i = 0; i < exclusions.length; i++) {
 997                 int[] componentRanges = exclusions[i];
 998                 for (int j = 0; j < componentRanges.length; ) {


1105     }
1106 
1107     protected abstract String getFaceNameFromComponentFontName(String componentFontName);
1108     protected abstract String getFileNameFromComponentFontName(String componentFontName);
1109 
1110     /*
1111     public class 2dFont {
1112         public String platformName;
1113         public String fontfileName;
1114     }
1115     private 2dFont [] componentFonts = null;
1116     */
1117 
1118     /* Used on Linux to test if a file referenced in a font configuration
1119      * file exists in the location that is expected. If it does, no need
1120      * to search for it. If it doesn't then unless its a fallback font,
1121      * return that expensive code should be invoked to search for the font.
1122      */
1123     HashMap<String, Boolean> existsMap;
1124     public boolean needToSearchForFile(String fileName) {
1125         if (!FontUtilities.isLinux) {
1126             return false;
1127         } else if (existsMap == null) {
1128            existsMap = new HashMap<String, Boolean>();
1129         }
1130         Boolean exists = existsMap.get(fileName);
1131         if (exists == null) {
1132             /* call getNumberCoreFonts() to ensure these are initialised, and
1133              * if this file isn't for a core component, ie, is a for a fallback
1134              * font which very typically isn't available, then can't afford
1135              * to take the start-up penalty to search for it.
1136              */
1137             getNumberCoreFonts();
1138             if (!coreFontFileNames.contains(fileName)) {
1139                 exists = Boolean.TRUE;
1140             } else {
1141                 exists = Boolean.valueOf((new File(fileName)).exists());
1142                 existsMap.put(fileName, exists);
1143                 if (FontUtilities.debugFonts() &&
1144                     exists == Boolean.FALSE) {
1145                     logger.warning("Couldn't locate font file " + fileName);
1146                 }
1147             }
1148         }
1149         return exists == Boolean.FALSE;
1150     }
1151 
1152     private int numCoreFonts = -1;
1153     private String[] componentFonts = null;
1154     HashMap <String, String> filenamesMap = new HashMap<String, String>();
1155     HashSet <String> coreFontFileNames = new HashSet<String>();
1156 
1157     /* Return the number of core fonts. Note this isn't thread safe but
1158      * a calling thread can call this and getPlatformFontNames() in either
1159      * order.
1160      */
1161     public int getNumberCoreFonts() {
1162         if (numCoreFonts == -1) {
1163             numCoreFonts = coreFontNameIDs.size();


2051                     lower = exclusions.substring(pos, newPos);
2052                     pos = newPos + 1;
2053                     newPos = exclusions.indexOf(',', pos);
2054                     if (newPos == -1) {
2055                         newPos = exclusions.length();
2056                     }
2057                     upper = exclusions.substring(pos, newPos);
2058                     pos = newPos + 1;
2059                     int lowerLength = lower.length();
2060                     int upperLength = upper.length();
2061                     if (lowerLength != 4 && lowerLength != 6
2062                         || upperLength != 4 && upperLength != 6) {
2063                         throw new Exception();
2064                     }
2065                     lo = Integer.parseInt(lower, 16);
2066                     up = Integer.parseInt(upper, 16);
2067                     if (lo > up) {
2068                         throw new Exception();
2069                     }
2070                 } catch (Exception e) {
2071                     if (FontUtilities.debugFonts() && 
2072                         logger != null) {
2073                         logger.config("Failed parsing " + key +
2074                                   " property of font configuration.");
2075 
2076                     }
2077                     return EMPTY_INT_ARRAY;
2078                 }
2079                 exclusionRanges[j++] = lo;
2080                 exclusionRanges[j++] = up;
2081             }
2082             return exclusionRanges;
2083         }
2084 
2085         private Short getID(HashMap<String, Short> map, String key) {
2086             Short ret = map.get(key);
2087             if ( ret == null) {
2088                 map.put(key, (short)map.size());
2089                 return map.get(key);
2090             }
2091             return ret;
2092         }