From 4115bd3641daa2c1755fe3f73ea4a1eb4026121f Mon Sep 17 00:00:00 2001 From: prr Date: Fri, 21 Jan 2011 08:04:04 -0800 Subject: [PATCH] 6892138: Windows GDI platform font lookup apis affect start-up for small UI apps Reviewed-by: igor, jgodinez --- .../classes/sun/font/SunFontManager.java | 222 +++++++++++++++++- .../classes/sun/awt/Win32FontManager.java | 75 ++++++ .../awt/font/FontNames/LocaleFamilyNames.java | 67 ++++++ 3 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 test/java/awt/font/FontNames/LocaleFamilyNames.java diff --git a/src/share/classes/sun/font/SunFontManager.java b/src/share/classes/sun/font/SunFontManager.java index 7bd2864db..e9b3bf171 100644 --- a/src/share/classes/sun/font/SunFontManager.java +++ b/src/share/classes/sun/font/SunFontManager.java @@ -1595,6 +1595,207 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { } } + /* 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 platformFontMap; + + /** + * default implementation does nothing. + */ + public HashMap populateHardcodedFileNameMap() { + return new HashMap(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() { + public Boolean run() { + for (int i=0; i 0 && style != font.style) { + style |= font.style; + font = fontFamily.getFont(style); + if (font == null) { + font = fontFamily.getClosestStyle(style); + } + } + } + + return font; + } private synchronized HashMap getFullNameToFileMap() { if (fontToFileMap == null) { @@ -1998,6 +2199,17 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { } if (FontUtilities.isWindows) { + + font = findFontFromPlatformMap(lowerCaseName, style); + if (FontUtilities.isLogging()) { + FontUtilities.getLogger() + .info("findFontFromPlatformMap returned " + font); + } + if (font != null) { + fontNameCache.put(mapName, font); + return font; + } + /* Don't want Windows to return a Lucida Sans font from * C:\Windows\Fonts */ @@ -2934,7 +3146,14 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { } } + protected String[] getPlatformFontDirs(boolean noType1Fonts) { + + /* First check if we already initialised path dirs */ + if (pathDirs != null) { + return pathDirs; + } + String path = getPlatformFontPath(noType1Fonts); StringTokenizer parser = new StringTokenizer(path, File.pathSeparator); @@ -2945,7 +3164,8 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { } } catch (NoSuchElementException e) { } - return pathList.toArray(new String[0]); + pathDirs = pathList.toArray(new String[0]); + return pathDirs; } /** diff --git a/src/windows/classes/sun/awt/Win32FontManager.java b/src/windows/classes/sun/awt/Win32FontManager.java index b308fa089..b2dd894e4 100644 --- a/src/windows/classes/sun/awt/Win32FontManager.java +++ b/src/windows/classes/sun/awt/Win32FontManager.java @@ -282,4 +282,79 @@ public class Win32FontManager extends SunFontManager { protected static native void deRegisterFontWithPlatform(String fontName); + /** + * populate the map with the most common windows fonts. + */ + @Override + public HashMap populateHardcodedFileNameMap() { + HashMap platformFontMap + = new HashMap(); + FamilyDescription fd; + + /* Segoe UI is the default UI font for Vista and later, and + * is used by the Win L&F which is used by FX too. + * Tahoma is used for the Win L&F on XP. + * Verdana is used in some FX UI controls. + */ + fd = new FamilyDescription(); + fd.familyName = "Segoe UI"; + fd.plainFullName = "Segoe UI"; + fd.plainFileName = "segoeui.ttf"; + fd.boldFullName = "Segoe UI Bold"; + fd.boldFileName = "segoeuib.ttf"; + fd.italicFullName = "Segoe UI Italic"; + fd.italicFileName = "segoeuii.ttf"; + fd.boldItalicFullName = "Segoe UI Bold Italic"; + fd.boldItalicFileName = "segoeuiz.ttf"; + platformFontMap.put("segoe", fd); + + fd = new FamilyDescription(); + fd.familyName = "Tahoma"; + fd.plainFullName = "Tahoma"; + fd.plainFileName = "tahoma.ttf"; + fd.boldFullName = "Tahoma Bold"; + fd.boldFileName = "tahomabd.ttf"; + platformFontMap.put("tahoma", fd); + + fd = new FamilyDescription(); + fd.familyName = "Verdana"; + fd.plainFullName = "Verdana"; + fd.plainFileName = "verdana.TTF"; + fd.boldFullName = "Verdana Bold"; + fd.boldFileName = "verdanab.TTF"; + fd.italicFullName = "Verdana Italic"; + fd.italicFileName = "verdanai.TTF"; + fd.boldItalicFullName = "Verdana Bold Italic"; + fd.boldItalicFileName = "verdanaz.TTF"; + platformFontMap.put("verdana", fd); + + /* The following are important because they are the core + * members of the default "Dialog" font. + */ + fd = new FamilyDescription(); + fd.familyName = "Arial"; + fd.plainFullName = "Arial"; + fd.plainFileName = "ARIAL.TTF"; + fd.boldFullName = "Arial Bold"; + fd.boldFileName = "ARIALBD.TTF"; + fd.italicFullName = "Arial Italic"; + fd.italicFileName = "ARIALI.TTF"; + fd.boldItalicFullName = "Arial Bold Italic"; + fd.boldItalicFileName = "ARIALBI.TTF"; + platformFontMap.put("arial", fd); + + fd = new FamilyDescription(); + fd.familyName = "Symbol"; + fd.plainFullName = "Symbol"; + fd.plainFileName = "Symbol.TTF"; + platformFontMap.put("symbol", fd); + + fd = new FamilyDescription(); + fd.familyName = "WingDings"; + fd.plainFullName = "WingDings"; + fd.plainFileName = "WINGDING.TTF"; + platformFontMap.put("wingdings", fd); + + return platformFontMap; + } } diff --git a/test/java/awt/font/FontNames/LocaleFamilyNames.java b/test/java/awt/font/FontNames/LocaleFamilyNames.java new file mode 100644 index 000000000..e6d71feb8 --- /dev/null +++ b/test/java/awt/font/FontNames/LocaleFamilyNames.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4935798 6521210 6901159 + * @summary Tests that all family names that are reported in all locales + * correspond to some font returned from getAllFonts(). + * @run main LocaleFamilyNames + */ +import java.awt.*; +import java.util.*; + +public class LocaleFamilyNames { + public static void main(String[] args) throws Exception { + + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + + Font[] all_fonts = ge.getAllFonts(); + + Locale[] all_locales = Locale.getAvailableLocales(); + + HashSet all_families = new HashSet(); + for (int i=0; i