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 Load more
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.