addFontToPlatformFontPath(platformFontName); } nativeNames = getNativeNames(fontFileName, platformFontName); } /* Uncomment these two lines to "generate" the XLFD->filename * mappings needed to speed start-up on Solaris. * Augment this with the appendedpathname and the mappings * for native (F3) fonts */ //String platName = platformFontName.replaceAll(" ", "_"); //System.out.println("filename."+platName+"="+fontFileName); registerFontFile(fontFileName, nativeNames, Font2D.FONT_CONFIG_RANK, true); } /* This registers accumulated paths from the calls to * addFontToPlatformFontPath(..) and any specified by * the font configuration. Rather than registering * the fonts it puts them in a place and form suitable for * the Toolkit to pick up and use if a toolkit is initialised, * and if it uses X11 fonts. */ registerPlatformFontsUsedByFontConfiguration(); CompositeFontDescriptor[] compositeFontInfo = fontConfig.get2DCompositeFontInfo(); for (int i = 0; i < compositeFontInfo.length; i++) { CompositeFontDescriptor descriptor = compositeFontInfo[i]; String[] componentFileNames = descriptor.getComponentFileNames(); String[] componentFaceNames = descriptor.getComponentFaceNames(); /* It would be better eventually to handle this in the * FontConfiguration code which should also remove duplicate slots */ if (missingFontFiles != null) { for (int ii=0; ii<componentFileNames.length; ii++) { if (missingFontFiles.contains(componentFileNames[ii])) { componentFileNames[ii] = getDefaultFontFile(); componentFaceNames[ii] = getDefaultFontFaceName(); } } } /* FontConfiguration needs to convey how many fonts it has added * as fallback component fonts which should not affect metrics. * The core component count will be the number of metrics slots. * This does not preclude other mechanisms for adding * fall back component fonts to the composite. */ if (altNameCache != null) { SunFontManager.registerCompositeFont( descriptor.getFaceName(), componentFileNames, componentFaceNames, descriptor.getCoreComponentCount(), descriptor.getExclusionRanges(), descriptor.getExclusionRangeLimits(), true, altNameCache); } else { registerCompositeFont(descriptor.getFaceName(), componentFileNames, componentFaceNames, descriptor.getCoreComponentCount(), descriptor.getExclusionRanges(), descriptor.getExclusionRangeLimits(), true); } if (FontUtilities.debugFonts()) { FontUtilities.getLogger() .info("registered " + descriptor.getFaceName()); } } } /** * Notifies graphics environment that the logical font configuration * uses the given platform font name. The graphics environment may * use this for platform specific initialization. */ protected void addFontToPlatformFontPath(String platformFontName) { } protected void registerFontFile(String fontFileName, String[] nativeNames, int fontRank, boolean defer) {// REMIND: case compare depends on platform if (registeredFontFiles.contains(fontFileName)) { return; } int fontFormat; if (ttFilter.accept(null, fontFileName)) { fontFormat = FONTFORMAT_TRUETYPE; } else if (t1Filter.accept(null, fontFileName)) { fontFormat = FONTFORMAT_TYPE1; } else { fontFormat = FONTFORMAT_NATIVE; } registeredFontFiles.add(fontFileName); if (defer) { registerDeferredFont(fontFileName, fontFileName, nativeNames, fontFormat, false, fontRank); } else { registerFontFile(fontFileName, nativeNames, fontFormat, false, fontRank); } } protected void registerPlatformFontsUsedByFontConfiguration() { } /* * A GE may verify whether a font file used in a fontconfiguration * exists. If it doesn't then either we may substitute the default * font, or perhaps elide it altogether from the composite font. * This makes some sense on windows where the font file is only * likely to be in one place. But on other OSes, eg Linux, the file * can move around depending. So there we probably don't want to assume * its missing and so won't add it to this list. * If this list - missingFontFiles - is non-null then the composite * font initialisation logic tests to see if a font file is in that * set. * Only one thread should be able to add to this set so we don't * synchronize. */ protected void addToMissingFontFileList(String fileName) { if (missingFontFiles == null) { missingFontFiles = new HashSet<String>(); } missingFontFiles.add(fileName); } /* * This is for use only within getAllFonts(). * Fonts listed in the fontconfig files for windows were all * on the "deferred" initialisation list. They were registered * either in the course of the application, or in the call to * loadFonts() within getAllFonts(). The fontconfig file specifies * the names of the fonts using the English names. If there's a * different name in the execution locale, then the platform will * report that, and we will construct the font with both names, and * thereby enumerate it twice. This happens for Japanese fonts listed * in the windows fontconfig, when run in the JA locale. The solution * is to rely (in this case) on the platform's font->file mapping to * determine that this name corresponds to a file we already registered. * This works because * - we know when we get here all deferred fonts are already initialised * - when we register a font file, we register all fonts in it. * - we know the fontconfig fonts are all in the windows registry */ private boolean isNameForRegisteredFile(String fontName) { String fileName = getFileNameForFontName(fontName); if (fileName == null) { return false; } return registeredFontFiles.contains(fileName); } /* * This invocation is not in a privileged block because * all privileged operations (reading files and properties) * was conducted on the creation of the GE */ public void createCompositeFonts(ConcurrentHashMap<String, Font2D> altNameCache, boolean preferLocale, boolean preferProportional) { FontConfiguration fontConfig = createFontConfiguration(preferLocale, preferProportional); initCompositeFonts(fontConfig, altNameCache); } /** * Returns all fonts installed in this environment. */ public Font[] getAllInstalledFonts() { if (allFonts == null) { loadFonts(); TreeMap fontMapNames = new TreeMap(); /* warning: the number of composite fonts could change dynamically * if applications are allowed to create them. "allfonts" could * then be stale. */ Font2D[] allfonts = getRegisteredFonts(); for (int i=0; i < allfonts.length; i++) { if (!(allfonts[i] instanceof NativeFont)) { fontMapNames.put(allfonts[i].getFontName(null), allfonts[i]); } } String[] platformNames = getFontNamesFromPlatform(); if (platformNames != null) { for (int i=0; i<platformNames.length; i++) { if (!isNameForRegisteredFile(platformNames[i])) { fontMapNames.put(platformNames[i], null); } } } String[] fontNames = null; if (fontMapNames.size() > 0) { fontNames = new String[fontMapNames.size()]; Object [] keyNames = fontMapNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { fontNames[i] = (String)keyNames[i]; } } Font[] fonts = new Font[fontNames.length]; for (int i=0; i < fontNames.length; i++) { fonts[i] = new Font(fontNames[i], Font.PLAIN, 1); Font2D f2d = (Font2D)fontMapNames.get(fontNames[i]); if (f2d != null) { FontAccess.getFontAccess().setFont2D(fonts[i], f2d.handle); } } allFonts = fonts; } Font []copyFonts = new Font[allFonts.length]; System.arraycopy(allFonts, 0, copyFonts, 0, allFonts.length); return copyFonts; } /** * Get a list of installed fonts in the requested {@link Locale}. * The list contains the fonts Family Names. * If Locale is null, the default locale is used. * * @param requestedLocale, if null the default locale is used. * @return list of installed fonts in the system. */ public String[] getInstalledFontFamilyNames(Locale requestedLocale) { if (requestedLocale == null) { requestedLocale = Locale.getDefault(); } if (allFamilies != null && lastDefaultLocale != null && requestedLocale.equals(lastDefaultLocale)) { String[] copyFamilies = new String[allFamilies.length]; System.arraycopy(allFamilies, 0, copyFamilies, 0, allFamilies.length); return copyFamilies; } TreeMap<String,String> familyNames = new TreeMap<String,String>(); // these names are always there and aren't localised String str; str = Font.SERIF; familyNames.put(str.toLowerCase(), str); str = Font.SANS_SERIF; familyNames.put(str.toLowerCase(), str); str = Font.MONOSPACED; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG_INPUT; familyNames.put(str.toLowerCase(), str); /* Platform APIs may be used to get the set of available family * names for the current default locale so long as it is the same * as the start-up system locale, rather than loading all fonts. */ if (requestedLocale.equals(getSystemStartupLocale()) && getFamilyNamesFromPlatform(familyNames, requestedLocale)) { /* Augment platform names with JRE font family names */ getJREFontFamilyNames(familyNames, requestedLocale); } else { loadFontFiles(); Font2D[] physicalfonts = getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } String[] retval = new String[familyNames.size()]; Object [] keyNames = familyNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { retval[i] = (String)familyNames.get(keyNames[i]); } if (requestedLocale.equals(Locale.getDefault())) { lastDefaultLocale = requestedLocale; allFamilies = new String[retval.length]; System.arraycopy(retval, 0, allFamilies, 0, allFamilies.length); } return retval; } public void register1dot0Fonts() { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { String type1Dir = "/usr/openwin/lib/X11/fonts/Type1"; registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK, false, false); return null; } }); } /* Really we need only the JRE fonts family names, but there's little * overhead in doing this the easy way by adding all the currently * known fonts. */ protected void getJREFontFamilyNames(TreeMap<String,String> familyNames, Locale requestedLocale) { registerDeferredJREFonts(jreFontDirName); Font2D[] physicalfonts = getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } /** * Default locale can be changed but we need to know the initial locale * as that is what is used by native code. Changing Java default locale * doesn't affect that. * Returns the locale in use when using native code to communicate * with platform APIs. On windows this is known as the "system" locale, * and it is usually the same as the platform locale, but not always, * so this method also checks an implementation property used only * on windows and uses that if set. */ private static Locale systemLocale = null; private static Locale getSystemStartupLocale() { if (systemLocale == null) { systemLocale = (Locale) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { /* On windows the system locale may be different than the * user locale. This is an unsupported configuration, but * in that case we want to return a dummy locale that will * never cause a match in the usage of this API. This is * important because Windows documents that the family * names of fonts are enumerated using the language of * the system locale. BY returning a dummy locale in that * case we do not use the platform API which would not * return us the names we want. */ String fileEncoding = System.getProperty("file.encoding", ""); String sysEncoding = System.getProperty("sun.jnu.encoding"); if (sysEncoding != null && !sysEncoding.equals(fileEncoding)) { return Locale.ROOT; } String language = System.getProperty("user.language", "en"); String country = System.getProperty("user.country",""); String variant = System.getProperty("user.variant",""); return new Locale(language, country, variant); } }); } return systemLocale; } void addToPool(FileFont font) { FileFont fontFileToClose = null; int freeSlot = -1; synchronized (fontFileCache) { /* Avoid duplicate entries in the pool, and don't close() it, * since this method is called only from within open(). * Seeing a duplicate is most likely to happen if the thread * was interrupted during a read, forcing perhaps repeated * close and open calls and it eventually it ends up pointing * at the same slot. */ for (int i=0;i<CHANNELPOOLSIZE;i++) { if (fontFileCache[i] == font) { return; } if (fontFileCache[i] == null && freeSlot < 0) { freeSlot = i; } } if (freeSlot >= 0) { fontFileCache[freeSlot] = font; return; } else { /* replace with new font. */ fontFileToClose = fontFileCache[lastPoolIndex]; fontFileCache[lastPoolIndex] = font; /* lastPoolIndex is updated so that the least recently opened * file will be closed next. */ lastPoolIndex = (lastPoolIndex+1) % CHANNELPOOLSIZE; } } /* Need to close the font file outside of the synchronized block, * since its possible some other thread is in an open() call on * this font file, and could be holding its lock and the pool lock. * Releasing the pool lock allows that thread to continue, so it can * then release the lock on this font, allowing the close() call * below to proceed. * Also, calling close() is safe because any other thread using * the font we are closing() synchronizes all reading, so we * will not close the file while its in use. */ if (fontFileToClose != null) { fontFileToClose.close(); } } protected FontUIResource getFontConfigFUIR(String family, int style, int size) { return new FontUIResource(family, style, size); }}Lines 3501–3912 of 3912. Previous lines
addFontToPlatformFontPath(platformFontName); } nativeNames = getNativeNames(fontFileName, platformFontName); } /* Uncomment these two lines to "generate" the XLFD->filename * mappings needed to speed start-up on Solaris. * Augment this with the appendedpathname and the mappings * for native (F3) fonts */ //String platName = platformFontName.replaceAll(" ", "_"); //System.out.println("filename."+platName+"="+fontFileName); registerFontFile(fontFileName, nativeNames, Font2D.FONT_CONFIG_RANK, true); } /* This registers accumulated paths from the calls to * addFontToPlatformFontPath(..) and any specified by * the font configuration. Rather than registering * the fonts it puts them in a place and form suitable for * the Toolkit to pick up and use if a toolkit is initialised, * and if it uses X11 fonts. */ registerPlatformFontsUsedByFontConfiguration(); CompositeFontDescriptor[] compositeFontInfo = fontConfig.get2DCompositeFontInfo(); for (int i = 0; i < compositeFontInfo.length; i++) { CompositeFontDescriptor descriptor = compositeFontInfo[i]; String[] componentFileNames = descriptor.getComponentFileNames(); String[] componentFaceNames = descriptor.getComponentFaceNames(); /* It would be better eventually to handle this in the * FontConfiguration code which should also remove duplicate slots */ if (missingFontFiles != null) { for (int ii=0; ii<componentFileNames.length; ii++) { if (missingFontFiles.contains(componentFileNames[ii])) { componentFileNames[ii] = getDefaultFontFile(); componentFaceNames[ii] = getDefaultFontFaceName(); } } } /* FontConfiguration needs to convey how many fonts it has added * as fallback component fonts which should not affect metrics. * The core component count will be the number of metrics slots. * This does not preclude other mechanisms for adding * fall back component fonts to the composite. */ if (altNameCache != null) { SunFontManager.registerCompositeFont( descriptor.getFaceName(), componentFileNames, componentFaceNames, descriptor.getCoreComponentCount(), descriptor.getExclusionRanges(), descriptor.getExclusionRangeLimits(), true, altNameCache); } else { registerCompositeFont(descriptor.getFaceName(), componentFileNames, componentFaceNames, descriptor.getCoreComponentCount(), descriptor.getExclusionRanges(), descriptor.getExclusionRangeLimits(), true); } if (FontUtilities.debugFonts()) { FontUtilities.getLogger() .info("registered " + descriptor.getFaceName()); } } } /** * Notifies graphics environment that the logical font configuration * uses the given platform font name. The graphics environment may * use this for platform specific initialization. */ protected void addFontToPlatformFontPath(String platformFontName) { } protected void registerFontFile(String fontFileName, String[] nativeNames, int fontRank, boolean defer) { // REMIND: case compare depends on platform if (registeredFontFiles.contains(fontFileName)) { return; } int fontFormat; if (ttFilter.accept(null, fontFileName)) { fontFormat = FONTFORMAT_TRUETYPE; } else if (t1Filter.accept(null, fontFileName)) { fontFormat = FONTFORMAT_TYPE1; } else { fontFormat = FONTFORMAT_NATIVE; } registeredFontFiles.add(fontFileName); if (defer) { registerDeferredFont(fontFileName, fontFileName, nativeNames, fontFormat, false, fontRank); } else { registerFontFile(fontFileName, nativeNames, fontFormat, false, fontRank); } } protected void registerPlatformFontsUsedByFontConfiguration() { } /* * A GE may verify whether a font file used in a fontconfiguration * exists. If it doesn't then either we may substitute the default * font, or perhaps elide it altogether from the composite font. * This makes some sense on windows where the font file is only * likely to be in one place. But on other OSes, eg Linux, the file * can move around depending. So there we probably don't want to assume * its missing and so won't add it to this list. * If this list - missingFontFiles - is non-null then the composite * font initialisation logic tests to see if a font file is in that * set. * Only one thread should be able to add to this set so we don't * synchronize. */ protected void addToMissingFontFileList(String fileName) { if (missingFontFiles == null) { missingFontFiles = new HashSet<String>(); } missingFontFiles.add(fileName); } /* * This is for use only within getAllFonts(). * Fonts listed in the fontconfig files for windows were all * on the "deferred" initialisation list. They were registered * either in the course of the application, or in the call to * loadFonts() within getAllFonts(). The fontconfig file specifies * the names of the fonts using the English names. If there's a * different name in the execution locale, then the platform will * report that, and we will construct the font with both names, and * thereby enumerate it twice. This happens for Japanese fonts listed * in the windows fontconfig, when run in the JA locale. The solution * is to rely (in this case) on the platform's font->file mapping to * determine that this name corresponds to a file we already registered. * This works because * - we know when we get here all deferred fonts are already initialised * - when we register a font file, we register all fonts in it. * - we know the fontconfig fonts are all in the windows registry */ private boolean isNameForRegisteredFile(String fontName) { String fileName = getFileNameForFontName(fontName); if (fileName == null) { return false; } return registeredFontFiles.contains(fileName); } /* * This invocation is not in a privileged block because * all privileged operations (reading files and properties) * was conducted on the creation of the GE */ public void createCompositeFonts(ConcurrentHashMap<String, Font2D> altNameCache, boolean preferLocale, boolean preferProportional) { FontConfiguration fontConfig = createFontConfiguration(preferLocale, preferProportional); initCompositeFonts(fontConfig, altNameCache); } /** * Returns all fonts installed in this environment. */ public Font[] getAllInstalledFonts() { if (allFonts == null) { loadFonts(); TreeMap fontMapNames = new TreeMap(); /* warning: the number of composite fonts could change dynamically * if applications are allowed to create them. "allfonts" could * then be stale. */ Font2D[] allfonts = getRegisteredFonts(); for (int i=0; i < allfonts.length; i++) { if (!(allfonts[i] instanceof NativeFont)) { fontMapNames.put(allfonts[i].getFontName(null), allfonts[i]); } } String[] platformNames = getFontNamesFromPlatform(); if (platformNames != null) { for (int i=0; i<platformNames.length; i++) { if (!isNameForRegisteredFile(platformNames[i])) { fontMapNames.put(platformNames[i], null); } } } String[] fontNames = null; if (fontMapNames.size() > 0) { fontNames = new String[fontMapNames.size()]; Object [] keyNames = fontMapNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { fontNames[i] = (String)keyNames[i]; } } Font[] fonts = new Font[fontNames.length]; for (int i=0; i < fontNames.length; i++) { fonts[i] = new Font(fontNames[i], Font.PLAIN, 1); Font2D f2d = (Font2D)fontMapNames.get(fontNames[i]); if (f2d != null) { FontAccess.getFontAccess().setFont2D(fonts[i], f2d.handle); } } allFonts = fonts; } Font []copyFonts = new Font[allFonts.length]; System.arraycopy(allFonts, 0, copyFonts, 0, allFonts.length); return copyFonts; } /** * Get a list of installed fonts in the requested {@link Locale}. * The list contains the fonts Family Names. * If Locale is null, the default locale is used. * * @param requestedLocale, if null the default locale is used. * @return list of installed fonts in the system. */ public String[] getInstalledFontFamilyNames(Locale requestedLocale) { if (requestedLocale == null) { requestedLocale = Locale.getDefault(); } if (allFamilies != null && lastDefaultLocale != null && requestedLocale.equals(lastDefaultLocale)) { String[] copyFamilies = new String[allFamilies.length]; System.arraycopy(allFamilies, 0, copyFamilies, 0, allFamilies.length); return copyFamilies; } TreeMap<String,String> familyNames = new TreeMap<String,String>(); // these names are always there and aren't localised String str; str = Font.SERIF; familyNames.put(str.toLowerCase(), str); str = Font.SANS_SERIF; familyNames.put(str.toLowerCase(), str); str = Font.MONOSPACED; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG_INPUT; familyNames.put(str.toLowerCase(), str); /* Platform APIs may be used to get the set of available family * names for the current default locale so long as it is the same * as the start-up system locale, rather than loading all fonts. */ if (requestedLocale.equals(getSystemStartupLocale()) && getFamilyNamesFromPlatform(familyNames, requestedLocale)) { /* Augment platform names with JRE font family names */ getJREFontFamilyNames(familyNames, requestedLocale); } else { loadFontFiles(); Font2D[] physicalfonts = getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } String[] retval = new String[familyNames.size()]; Object [] keyNames = familyNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { retval[i] = (String)familyNames.get(keyNames[i]); } if (requestedLocale.equals(Locale.getDefault())) { lastDefaultLocale = requestedLocale; allFamilies = new String[retval.length]; System.arraycopy(retval, 0, allFamilies, 0, allFamilies.length); } return retval; } public void register1dot0Fonts() { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { String type1Dir = "/usr/openwin/lib/X11/fonts/Type1"; registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK, false, false); return null; } }); } /* Really we need only the JRE fonts family names, but there's little * overhead in doing this the easy way by adding all the currently * known fonts. */ protected void getJREFontFamilyNames(TreeMap<String,String> familyNames, Locale requestedLocale) { registerDeferredJREFonts(jreFontDirName); Font2D[] physicalfonts = getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } /** * Default locale can be changed but we need to know the initial locale * as that is what is used by native code. Changing Java default locale * doesn't affect that. * Returns the locale in use when using native code to communicate * with platform APIs. On windows this is known as the "system" locale, * and it is usually the same as the platform locale, but not always, * so this method also checks an implementation property used only * on windows and uses that if set. */ private static Locale systemLocale = null; private static Locale getSystemStartupLocale() { if (systemLocale == null) { systemLocale = (Locale) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { /* On windows the system locale may be different than the * user locale. This is an unsupported configuration, but * in that case we want to return a dummy locale that will * never cause a match in the usage of this API. This is * important because Windows documents that the family * names of fonts are enumerated using the language of * the system locale. BY returning a dummy locale in that * case we do not use the platform API which would not * return us the names we want. */ String fileEncoding = System.getProperty("file.encoding", ""); String sysEncoding = System.getProperty("sun.jnu.encoding"); if (sysEncoding != null && !sysEncoding.equals(fileEncoding)) { return Locale.ROOT; } String language = System.getProperty("user.language", "en"); String country = System.getProperty("user.country",""); String variant = System.getProperty("user.variant",""); return new Locale(language, country, variant); } }); } return systemLocale; } void addToPool(FileFont font) { FileFont fontFileToClose = null; int freeSlot = -1; synchronized (fontFileCache) { /* Avoid duplicate entries in the pool, and don't close() it, * since this method is called only from within open(). * Seeing a duplicate is most likely to happen if the thread * was interrupted during a read, forcing perhaps repeated * close and open calls and it eventually it ends up pointing * at the same slot. */ for (int i=0;i<CHANNELPOOLSIZE;i++) { if (fontFileCache[i] == font) { return; } if (fontFileCache[i] == null && freeSlot < 0) { freeSlot = i; } } if (freeSlot >= 0) { fontFileCache[freeSlot] = font; return; } else { /* replace with new font. */ fontFileToClose = fontFileCache[lastPoolIndex]; fontFileCache[lastPoolIndex] = font; /* lastPoolIndex is updated so that the least recently opened * file will be closed next. */ lastPoolIndex = (lastPoolIndex+1) % CHANNELPOOLSIZE; } } /* Need to close the font file outside of the synchronized block, * since its possible some other thread is in an open() call on * this font file, and could be holding its lock and the pool lock. * Releasing the pool lock allows that thread to continue, so it can * then release the lock on this font, allowing the close() call * below to proceed. * Also, calling close() is safe because any other thread using * the font we are closing() synchronizes all reading, so we * will not close the file while its in use. */ if (fontFileToClose != null) { fontFileToClose.close(); } } protected FontUIResource getFontConfigFUIR(String family, int style, int size) { return new FontUIResource(family, style, size); } }