3912 lines · 165.2 KB · Java
RawDownload
        haveCheckedUnreferencedFontFiles = true;        if (!FontUtilities.isWindows) {            return;        }        /* getFontFilesFromPath() returns all lower case names.         * To compare we also need lower case         * versions of the names from the registry.         */        ArrayList<String> registryFiles = new ArrayList<String>();        for (String regFile : fontToFileMap.values()) {            registryFiles.add(regFile.toLowerCase());        }         /* To avoid any issues with concurrent modification, create         * copies of the existing maps, add the new fonts into these         * and then replace the references to the old ones with the         * new maps. ConcurrentHashmap is another option but its a lot         * more changes and with this exception, these maps are intended         * to be static.         */        HashMap<String,String> fontToFileMap2 = null;        HashMap<String,String> fontToFamilyNameMap2 = null;        HashMap<String,ArrayList<String>> familyToFontListMap2 = null;;         for (String pathFile : getFontFilesFromPath(false)) {            if (!registryFiles.contains(pathFile)) {                if (FontUtilities.isLogging()) {                    FontUtilities.getLogger()                                 .info("Found non-registry file : " + pathFile);                }                PhysicalFont f = registerFontFile(getPathName(pathFile));                if (f == null) {                    continue;                }                if (fontToFileMap2 == null) {                    fontToFileMap2 = new HashMap<String,String>(fontToFileMap);                    fontToFamilyNameMap2 =                        new HashMap<String,String>(fontToFamilyNameMap);                    familyToFontListMap2 = new                        HashMap<String,ArrayList<String>>(familyToFontListMap);                }                String fontName = f.getFontName(null);                String family = f.getFamilyName(null);                String familyLC = family.toLowerCase();                fontToFamilyNameMap2.put(fontName, family);                fontToFileMap2.put(fontName, pathFile);                ArrayList<String> fonts = familyToFontListMap2.get(familyLC);                if (fonts == null) {                    fonts = new ArrayList<String>();                } else {                    fonts = new ArrayList<String>(fonts);                }                fonts.add(fontName);                familyToFontListMap2.put(familyLC, fonts);            }        }        if (fontToFileMap2 != null) {            fontToFileMap = fontToFileMap2;            familyToFontListMap = familyToFontListMap2;            fontToFamilyNameMap = fontToFamilyNameMap2;        }    }     private void resolveFontFiles(HashSet<String> unmappedFiles,                                  ArrayList<String> unmappedFonts) {         Locale l = SunToolkit.getStartupLocale();         for (String file : unmappedFiles) {            try {                int fn = 0;                TrueTypeFont ttf;                String fullPath = getPathName(file);                if (FontUtilities.isLogging()) {                    FontUtilities.getLogger()                                   .info("Trying to resolve file " + fullPath);                }                do {                    ttf = new TrueTypeFont(fullPath, null, fn++, false);                    //  prefer the font's locale name.                    String fontName = ttf.getFontName(l).toLowerCase();                    if (unmappedFonts.contains(fontName)) {                        fontToFileMap.put(fontName, file);                        unmappedFonts.remove(fontName);                        if (FontUtilities.isLogging()) {                            FontUtilities.getLogger()                                  .info("Resolved absent registry entry for " +                                        fontName + " located in " + fullPath);                        }                    }                }                while (fn < ttf.getFontCount());            } catch (Exception e) {            }        }    }     /* Hardwire the English names and expected file names of fonts     * commonly used at start up. Avoiding until later even the small     * cost of calling platform APIs to locate these can help.     * The code that registers these fonts needs to "bail" if any     * of the files do not exist, so it will verify the existence of     * all non-null file names first.     * They are added in to a map with nominally the first     * word in the name of the family as the key. In all the cases     * we are using the the family name is a single word, and as is     * more or less required the family name is the initial sequence     * in a full name. So lookup first finds the matching description,     * then registers the whole family, returning the right font.     */    public static class FamilyDescription {        public String familyName;        public String plainFullName;        public String boldFullName;        public String italicFullName;        public String boldItalicFullName;        public String plainFileName;        public String boldFileName;        public String italicFileName;        public String boldItalicFileName;    }     static HashMap<String, FamilyDescription> platformFontMap;     /**     * default implementation does nothing.     */    public HashMap<String, FamilyDescription> populateHardcodedFileNameMap() {        return new HashMap<String, FamilyDescription>(0);    }     Font2D findFontFromPlatformMap(String lcName, int style) {        if (platformFontMap == null) {            platformFontMap = populateHardcodedFileNameMap();        }         if (platformFontMap == null || platformFontMap.size() == 0) {            return null;        }         int spaceIndex = lcName.indexOf(' ');        String firstWord = lcName;        if (spaceIndex > 0) {            firstWord = lcName.substring(0, spaceIndex);        }         FamilyDescription fd = platformFontMap.get(firstWord);        if (fd == null) {            return null;        }        /* Once we've established that its at least the first word,         * we need to dig deeper to make sure its a match for either         * a full name, or the family name, to make sure its not         * a request for some other font that just happens to start         * with the same first word.         */        int styleIndex = -1;        if (lcName.equalsIgnoreCase(fd.plainFullName)) {            styleIndex = 0;        } else if (lcName.equalsIgnoreCase(fd.boldFullName)) {            styleIndex = 1;        } else if (lcName.equalsIgnoreCase(fd.italicFullName)) {            styleIndex = 2;        } else if (lcName.equalsIgnoreCase(fd.boldItalicFullName)) {            styleIndex = 3;        }        if (styleIndex == -1 && !lcName.equalsIgnoreCase(fd.familyName)) {            return null;        }         String plainFile = null, boldFile = null,            italicFile = null, boldItalicFile = null;         boolean failure = false;        /* In a terminal server config, its possible that getPathName()         * will return null, if the file doesn't exist, hence the null         * checks on return. But in the normal client config we need to         * follow this up with a check to see if all the files really         * exist for the non-null paths.         */         getPlatformFontDirs(noType1Font);         if (fd.plainFileName != null) {            plainFile = getPathName(fd.plainFileName);            if (plainFile == null) {                failure = true;            }        }         if (fd.boldFileName != null) {            boldFile = getPathName(fd.boldFileName);            if (boldFile == null) {                failure = true;            }        }         if (fd.italicFileName != null) {            italicFile = getPathName(fd.italicFileName);            if (italicFile == null) {                failure = true;            }        }         if (fd.boldItalicFileName != null) {            boldItalicFile = getPathName(fd.boldItalicFileName);            if (boldItalicFile == null) {                failure = true;            }        }         if (failure) {            if (FontUtilities.isLogging()) {                FontUtilities.getLogger().                    info("Hardcoded file missing looking for " + lcName);            }            platformFontMap.remove(firstWord);            return null;        }         /* Some of these may be null,as not all styles have to exist */        final String[] files = {            plainFile, boldFile, italicFile, boldItalicFile } ;         failure = java.security.AccessController.doPrivileged(                 new java.security.PrivilegedAction<Boolean>() {                     public Boolean run() {                         for (int i=0; i<files.length; i++) {                             if (files[i] == null) {                                 continue;                             }                             File f = new File(files[i]);                             if (!f.exists()) {                                 return Boolean.TRUE;                             }                         }                         return Boolean.FALSE;                     }                 });         if (failure) {            if (FontUtilities.isLogging()) {                FontUtilities.getLogger().                    info("Hardcoded file missing looking for " + lcName);            }            platformFontMap.remove(firstWord);            return null;        }         /* If we reach here we know that we have all the files we         * expect, so all should be fine so long as the contents         * are what we'd expect. Now on to registering the fonts.         * Currently this code only looks for TrueType fonts, so format         * and rank can be specified without looking at the filename.         */        Font2D font = null;        for (int f=0;f<files.length;f++) {            if (files[f] == null) {                continue;            }            PhysicalFont pf =                registerFontFile(files[f], null,                                 FONTFORMAT_TRUETYPE, false, Font2D.TTF_RANK);            if (f == styleIndex) {                font = pf;            }        }          /* Two general cases need a bit more work here.         * 1) If font is null, then it was perhaps a request for a         * non-existent font, such as "Tahoma Italic", or a family name -         * where family and full name of the plain font differ.         * Fall back to finding the closest one in the family.         * This could still fail if a client specified "Segoe" instead of         * "Segoe UI".         * 2) The request is of the form "MyFont Bold", style=Font.ITALIC,         * and so we want to see if there's a Bold Italic font, or         * "MyFamily", style=Font.BOLD, and we may have matched the plain,         * but now need to revise that to the BOLD font.         */        FontFamily fontFamily = FontFamily.getFamily(fd.familyName);        if (fontFamily != null) {            if (font == null) {                font = fontFamily.getFont(style);                if (font == null) {                    font = fontFamily.getClosestStyle(style);                }            } else if (style > 0 && style != font.style) {                style |= font.style;                font = fontFamily.getFont(style);                if (font == null) {                    font = fontFamily.getClosestStyle(style);                }            }        }         return font;    }    private synchronized HashMap<String,String> getFullNameToFileMap() {        if (fontToFileMap == null) {             pathDirs = getPlatformFontDirs(noType1Font);             fontToFileMap = new HashMap<String,String>(100);            fontToFamilyNameMap = new HashMap<String,String>(100);            familyToFontListMap = new HashMap<String,ArrayList<String>>(50);            populateFontFileNameMap(fontToFileMap,                                    fontToFamilyNameMap,                                    familyToFontListMap,                                    Locale.ENGLISH);            if (FontUtilities.isWindows) {                resolveWindowsFonts();            }            if (FontUtilities.isLogging()) {                logPlatformFontInfo();            }        }        return fontToFileMap;    }     private void logPlatformFontInfo() {        PlatformLogger logger = FontUtilities.getLogger();        for (int i=0; i< pathDirs.length;i++) {            logger.info("fontdir="+pathDirs[i]);        }        for (String keyName : fontToFileMap.keySet()) {            logger.info("font="+keyName+" file="+ fontToFileMap.get(keyName));        }        for (String keyName : fontToFamilyNameMap.keySet()) {            logger.info("font="+keyName+" family="+                        fontToFamilyNameMap.get(keyName));        }        for (String keyName : familyToFontListMap.keySet()) {            logger.info("family="+keyName+ " fonts="+                        familyToFontListMap.get(keyName));        }    }     /* Note this return list excludes logical fonts and JRE fonts */    protected String[] getFontNamesFromPlatform() {        if (getFullNameToFileMap().size() == 0) {            return null;        }        checkForUnreferencedFontFiles();        /* This odd code with TreeMap is used to preserve a historical         * behaviour wrt the sorting order .. */        ArrayList<String> fontNames = new ArrayList<String>();        for (ArrayList<String> a : familyToFontListMap.values()) {            for (String s : a) {                fontNames.add(s);            }        }        return fontNames.toArray(STR_ARRAY);    }     public boolean gotFontsFromPlatform() {        return getFullNameToFileMap().size() != 0;    }     public String getFileNameForFontName(String fontName) {        String fontNameLC = fontName.toLowerCase(Locale.ENGLISH);        return fontToFileMap.get(fontNameLC);    }     private PhysicalFont registerFontFile(String file) {        if (new File(file).isAbsolute() &&            !registeredFonts.contains(file)) {            int fontFormat = FONTFORMAT_NONE;            int fontRank = Font2D.UNKNOWN_RANK;            if (ttFilter.accept(null, file)) {                fontFormat = FONTFORMAT_TRUETYPE;                fontRank = Font2D.TTF_RANK;            } else if                (t1Filter.accept(null, file)) {                fontFormat = FONTFORMAT_TYPE1;                fontRank = Font2D.TYPE1_RANK;            }            if (fontFormat == FONTFORMAT_NONE) {                return null;            }            return registerFontFile(file, null, fontFormat, false, fontRank);        }        return null;    }     /* Used to register any font files that are found by platform APIs     * that weren't previously found in the standard font locations.     * the isAbsolute() check is needed since that's whats stored in the     * set, and on windows, the fonts in the system font directory that     * are in the fontToFileMap are just basenames. We don't want to try     * to register those again, but we do want to register other registry     * installed fonts.     */    protected void registerOtherFontFiles(HashSet registeredFontFiles) {        if (getFullNameToFileMap().size() == 0) {            return;        }        for (String file : fontToFileMap.values()) {            registerFontFile(file);        }    }     public boolean        getFamilyNamesFromPlatform(TreeMap<String,String> familyNames,                                   Locale requestedLocale) {        if (getFullNameToFileMap().size() == 0) {            return false;        }        checkForUnreferencedFontFiles();        for (String name : fontToFamilyNameMap.values()) {            familyNames.put(name.toLowerCase(requestedLocale), name);        }        return true;    }     /* Path may be absolute or a base file name relative to one of     * the platform font directories     */    private String getPathName(final String s) {        File f = new File(s);        if (f.isAbsolute()) {            return s;        } else if (pathDirs.length==1) {            return pathDirs[0] + File.separator + s;        } else {            String path = java.security.AccessController.doPrivileged(                 new java.security.PrivilegedAction<String>() {                     public String run() {                         for (int p=0; p<pathDirs.length; p++) {                             File f = new File(pathDirs[p] +File.separator+ s);                             if (f.exists()) {                                 return f.getAbsolutePath();                             }                         }                         return null;                     }                });            if (path != null) {                return path;            }        }        return s; // shouldn't happen, but harmless    }     /* lcName is required to be lower case for use as a key.     * lcName may be a full name, or a family name, and style may     * be specified in addition to either of these. So be sure to     * get the right one. Since an app *could* ask for "Foo Regular"     * and later ask for "Foo Italic", if we don't register all the     * styles, then logic in findFont2D may try to style the original     * so we register the entire family if we get a match here.     * This is still a big win because this code is invoked where     * otherwise we would register all fonts.     * It's also useful for the case where "Foo Bold" was specified with     * style Font.ITALIC, as we would want in that case to try to return     * "Foo Bold Italic" if it exists, and it is only by locating "Foo Bold"     * and opening it that we really "know" it's Bold, and can look for     * a font that supports that and the italic style.     * The code in here is not overtly windows-specific but in fact it     * is unlikely to be useful as is on other platforms. It is maintained     * in this shared source file to be close to its sole client and     * because so much of the logic is intertwined with the logic in     * findFont2D.     */    private Font2D findFontFromPlatform(String lcName, int style) {        if (getFullNameToFileMap().size() == 0) {            return null;        }         ArrayList<String> family = null;        String fontFile = null;        String familyName = fontToFamilyNameMap.get(lcName);        if (familyName != null) {            fontFile = fontToFileMap.get(lcName);            family = familyToFontListMap.get                (familyName.toLowerCase(Locale.ENGLISH));        } else {            family = familyToFontListMap.get(lcName); // is lcName is a family?            if (family != null && family.size() > 0) {                String lcFontName = family.get(0).toLowerCase(Locale.ENGLISH);                if (lcFontName != null) {                    familyName = fontToFamilyNameMap.get(lcFontName);                }            }        }        if (family == null || familyName == null) {            return null;        }        String [] fontList = (String[])family.toArray(STR_ARRAY);        if (fontList.length == 0) {            return null;        }         /* first check that for every font in this family we can find         * a font file. The specific reason for doing this is that         * in at least one case on Windows a font has the face name "David"         * but the registry entry is "David Regular". That is the "unique"         * name of the font but in other cases the registry contains the         * "full" name. See the specifications of name ids 3 and 4 in the         * TrueType 'name' table.

Lines 1501–2000 of 3912. Previous lines