diff options
author | prr <none@none> | 2008-06-12 13:17:33 -0700 |
---|---|---|
committer | prr <none@none> | 2008-06-12 13:17:33 -0700 |
commit | 952999dcaf5ba7639a2c55b725ae18b33cace22a (patch) | |
tree | 95d1c79aa7f0346c12e06d67a5ba85d7c5c1324b | |
parent | 633a1fda50c5260a9ae5643ade9bd5e0a2ddd613 (diff) |
6378099: RFE: Use libfontconfig to create/synthesise a fontconfig.properties
Reviewed-by: tdv, igor
-rw-r--r-- | make/sun/headless/mapfile-vers | 1 | ||||
-rw-r--r-- | make/sun/xawt/mapfile-vers | 1 | ||||
-rw-r--r-- | src/share/classes/sun/awt/FontConfiguration.java | 80 | ||||
-rw-r--r-- | src/share/classes/sun/font/FontManager.java | 157 | ||||
-rw-r--r-- | src/share/classes/sun/java2d/SunGraphicsEnvironment.java | 31 | ||||
-rw-r--r-- | src/solaris/classes/sun/awt/X11GraphicsEnvironment.java | 50 | ||||
-rw-r--r-- | src/solaris/classes/sun/font/FcFontConfiguration.java | 517 | ||||
-rw-r--r-- | src/solaris/native/sun/awt/fontconfig.h | 482 | ||||
-rw-r--r-- | src/solaris/native/sun/awt/fontpath.c | 313 | ||||
-rw-r--r-- | src/windows/classes/sun/awt/Win32GraphicsEnvironment.java | 4 |
10 files changed, 1361 insertions, 275 deletions
diff --git a/make/sun/headless/mapfile-vers b/make/sun/headless/mapfile-vers index f27f007d7..d3107ecee 100644 --- a/make/sun/headless/mapfile-vers +++ b/make/sun/headless/mapfile-vers @@ -60,6 +60,7 @@ SUNWprivate_1.1 { X11SurfaceData_GetOps; Java_java_awt_Font_initIDs; Java_sun_font_FontManager_getFontConfig; + Java_sun_font_FontManager_getFontConfigVersion; Java_sun_font_FontManager_getFontConfigAASettings; Java_sun_font_FontManager_getFontPath; Java_sun_font_FontManager_setNativeFontPath; diff --git a/make/sun/xawt/mapfile-vers b/make/sun/xawt/mapfile-vers index 7828481bd..aee563e2d 100644 --- a/make/sun/xawt/mapfile-vers +++ b/make/sun/xawt/mapfile-vers @@ -177,6 +177,7 @@ SUNWprivate_1.1 { Java_java_awt_TextField_initIDs; Java_java_awt_TrayIcon_initIDs; Java_sun_font_FontManager_getFontConfig; + Java_sun_font_FontManager_getFontConfigVersion; Java_sun_font_FontManager_getFontConfigAASettings; Java_sun_font_FontManager_getFontPath; Java_sun_font_FontManager_setNativeFontPath; diff --git a/src/share/classes/sun/awt/FontConfiguration.java b/src/share/classes/sun/awt/FontConfiguration.java index a6b94870b..d3d6ed819 100644 --- a/src/share/classes/sun/awt/FontConfiguration.java +++ b/src/share/classes/sun/awt/FontConfiguration.java @@ -72,6 +72,11 @@ public abstract class FontConfiguration { protected boolean preferLocaleFonts; protected boolean preferPropFonts; + private File fontConfigFile; + private boolean foundOsSpecificFile; + private boolean inited; + private String javaLib; + /* A default FontConfiguration must be created before an alternate * one to ensure proper static initialisation takes place. */ @@ -80,14 +85,25 @@ public abstract class FontConfiguration { logger = Logger.getLogger("sun.awt.FontConfiguration"); } this.environment = environment; - this.preferLocaleFonts = false; - this.preferPropFonts = false; setOsNameAndVersion(); /* static initialization */ setEncoding(); /* static initialization */ - fontConfig = this; /* static initialization */ + /* Separating out the file location from the rest of the + * initialisation, so the caller has the option of doing + * something else if a suitable file isn't found. + */ + findFontConfigFile(); + } - readFontConfigFile(); - initFontConfig(); + public synchronized boolean init() { + if (!inited) { + this.preferLocaleFonts = false; + this.preferPropFonts = false; + fontConfig = this; /* static initialization */ + readFontConfigFile(fontConfigFile); + initFontConfig(); + inited = true; + } + return true; } public FontConfiguration(SunGraphicsEnvironment environment, @@ -121,21 +137,51 @@ public abstract class FontConfiguration { ///////////////////////////////////////////////////////////////////// // methods for loading the FontConfig file // ///////////////////////////////////////////////////////////////////// - private void readFontConfigFile() { - // Find fontconfig file - File f = null; + + public boolean foundOsSpecificFile() { + return foundOsSpecificFile; + } + + /* Smoke test to see if we can trust this configuration by testing if + * the first slot of a composite font maps to an installed file. + */ + public boolean fontFilesArePresent() { + init(); + short fontNameID = compFontNameIDs[0][0][0]; + short fileNameID = getComponentFileID(fontNameID); + final String fileName = mapFileName(getComponentFileName(fileNameID)); + Boolean exists = (Boolean)java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + try { + File f = new File(fileName); + return Boolean.valueOf(f.exists()); + } + catch (Exception e) { + return false; + } + } + }); + return exists.booleanValue(); + } + + private void findFontConfigFile() { + + foundOsSpecificFile = true; // default assumption. String javaHome = System.getProperty("java.home"); if (javaHome == null) { throw new Error("java.home property not set"); } - String javaLib = javaHome + File.separator + "lib"; + javaLib = javaHome + File.separator + "lib"; String userConfigFile = System.getProperty("sun.awt.fontconfig"); if (userConfigFile != null) { - f = new File(userConfigFile); + fontConfigFile = new File(userConfigFile); } else { - f = findFontConfigFile(javaLib); + fontConfigFile = findFontConfigFile(javaLib); } + } + private void readFontConfigFile(File f) { /* This is invoked here as readFontConfigFile is only invoked * once per VM, and always in a privileged context, thus the * directory containing installed fall back fonts is accessed @@ -167,7 +213,7 @@ public abstract class FontConfiguration { } } - private void getInstalledFallbackFonts(String javaLib) { + protected void getInstalledFallbackFonts(String javaLib) { String fallbackDirName = javaLib + File.separator + "fonts" + File.separator + "fallback"; @@ -229,6 +275,8 @@ public abstract class FontConfiguration { return configFile; } } + foundOsSpecificFile = false; + configFile = findImpl(baseName); if (configFile != null) { return configFile; @@ -506,12 +554,12 @@ public abstract class FontConfiguration { ///////////////////////////////////////////////////////////////////// protected static final int NUM_FONTS = 5; protected static final int NUM_STYLES = 4; - private static final String[] fontNames + protected static final String[] fontNames = {"serif", "sansserif", "monospaced", "dialog", "dialoginput"}; - private static final String[] publicFontNames + protected static final String[] publicFontNames = {Font.SERIF, Font.SANS_SERIF, Font.MONOSPACED, Font.DIALOG, Font.DIALOG_INPUT}; - private static final String[] styleNames + protected static final String[] styleNames = {"plain", "bold", "italic", "bolditalic"}; /** @@ -656,7 +704,7 @@ public abstract class FontConfiguration { return null; } - private static String[] installedFallbackFontFiles = null; + protected static String[] installedFallbackFontFiles = null; /** * Maps a file name given in the font configuration file diff --git a/src/share/classes/sun/font/FontManager.java b/src/share/classes/sun/font/FontManager.java index 09f181f12..a9a7257e4 100644 --- a/src/share/classes/sun/font/FontManager.java +++ b/src/share/classes/sun/font/FontManager.java @@ -148,6 +148,7 @@ public final class FontManager { static HashSet<String> jreLucidaFontFiles; static String[] jreOtherFontFiles; static boolean noOtherJREFontFiles = false; // initial assumption. + static boolean fontConfigFailed = false; /* Used to indicate required return type from toArray(..); */ private static String[] STR_ARRAY = new String[0]; @@ -3100,19 +3101,30 @@ public final class FontManager { "monospace:bold:italic", }; - /* This class is just a data structure. + /* These next three classes are just data structures. */ - private static class FontConfigInfo { + static class FontConfigFont { + String familyName; // eg Bitstream Vera Sans + String styleStr; // eg Bold + String fullName; // eg Bitstream Vera Sans Bold + String fontFile; // eg /usr/X11/lib/fonts/foo.ttf + } + + static class FcCompFont { String fcName; // eg sans String fcFamily; // eg sans String jdkName; // eg sansserif int style; // eg 0=PLAIN - String familyName; // eg Bitstream Vera Sans - String fontFile; // eg /usr/X11/lib/fonts/foo.ttf + FontConfigFont firstFont; + FontConfigFont[] allFonts; //boolean preferBitmaps; // if embedded bitmaps preferred over AA CompositeFont compFont; // null if not yet created/known. } + static class FontConfigInfo { + int fcVersion; + String[] cacheDirs = new String[4]; + } private static String getFCLocaleStr() { Locale l = SunToolkit.getStartupLocale(); @@ -3124,6 +3136,12 @@ public final class FontManager { return localeStr; } + /* This does cause the native libfontconfig to be loaded and unloaded, + * but it does not incur the overhead of initialisation of its + * data structures, so shouldn't have a measurable impact. + */ + public static native int getFontConfigVersion(); + private static native int getFontConfigAASettings(String locale, String fcFamily); @@ -3157,17 +3175,35 @@ public final class FontManager { return getFontConfigAAHint("sans"); } + /* This is populated by native */ + private static final FontConfigInfo fcInfo = new FontConfigInfo(); + /* This array has the array elements created in Java code and is * passed down to native to be filled in. */ - private static FontConfigInfo[] fontConfigFonts; + private static FcCompFont[] fontConfigFonts; - /* Return an array of FontConfigInfo structs describing the primary + /* Return an array of FcCompFont structs describing the primary * font located for each of fontconfig/GTK/Pango's logical font names. */ private static native void getFontConfig(String locale, - FontConfigInfo[] fonts); + FontConfigInfo fcInfo, + FcCompFont[] fonts, + boolean includeFallbacks); + static void populateFontConfig(FcCompFont[] fcInfo) { + fontConfigFonts = fcInfo; + } + + static FcCompFont[] loadFontConfig() { + initFontConfigFonts(true); + return fontConfigFonts; + } + + static FontConfigInfo getFontConfigInfo() { + initFontConfigFonts(true); + return fcInfo; + } /* This can be made public if it's needed to force a re-read * rather than using the cached values. The re-read would be needed @@ -3175,54 +3211,80 @@ public final class FontManager { * In that event this method would need to return directly the array * to be used by the caller in case it subsequently changed. */ - private static void initFontConfigFonts() { + private static synchronized void + initFontConfigFonts(boolean includeFallbacks) { if (fontConfigFonts != null) { - return; + if (!includeFallbacks || (fontConfigFonts[0].allFonts != null)) { + return; + } } - if (isWindows) { + if (isWindows || fontConfigFailed) { return; } long t0 = 0; if (logging) { - t0 = System.currentTimeMillis(); + t0 = System.nanoTime(); } - FontConfigInfo[] fontArr = new FontConfigInfo[fontConfigNames.length]; + FcCompFont[] fontArr = new FcCompFont[fontConfigNames.length]; for (int i = 0; i< fontArr.length; i++) { - fontArr[i] = new FontConfigInfo(); + fontArr[i] = new FcCompFont(); fontArr[i].fcName = fontConfigNames[i]; int colonPos = fontArr[i].fcName.indexOf(':'); fontArr[i].fcFamily = fontArr[i].fcName.substring(0, colonPos); fontArr[i].jdkName = mapFcName(fontArr[i].fcFamily); fontArr[i].style = i % 4; // depends on array order. } - getFontConfig(getFCLocaleStr(), fontArr); + getFontConfig(getFCLocaleStr(), fcInfo, fontArr, includeFallbacks); + /* If don't find anything (eg no libfontconfig), then just return */ + for (int i = 0; i< fontArr.length; i++) { + FcCompFont fci = fontArr[i]; + if (fci.firstFont == null) { + if (logging) { + logger.info("Fontconfig returned no fonts."); + } + fontConfigFailed = true; + return; + } + } fontConfigFonts = fontArr; if (logging) { - long t1 = System.currentTimeMillis(); - logger.info("Time spent accessing fontconfig="+(t1-t0)+"ms."); + long t1 = System.nanoTime(); + logger.info("Time spent accessing fontconfig="+ + (t1-t0)/1000000+"ms."); for (int i = 0; i< fontConfigFonts.length; i++) { - FontConfigInfo fci = fontConfigFonts[i]; + FcCompFont fci = fontConfigFonts[i]; logger.info("FC font " + fci.fcName+" maps to family " + - fci.familyName + " in file " + fci.fontFile); + fci.firstFont.familyName + + " in file " + fci.firstFont.fontFile); + if (fci.allFonts != null) { + for (int f=0;f<fci.allFonts.length;f++) { + FontConfigFont fcf = fci.allFonts[f]; + logger.info("Family=" + fcf.familyName + + " Style="+ fcf.styleStr + + " Fullname="+fcf.fullName + + " File="+fcf.fontFile); + } + } } } } - private static PhysicalFont registerFromFcInfo(FontConfigInfo fcInfo) { + private static PhysicalFont registerFromFcInfo(FcCompFont fcInfo) { /* If it's a TTC file we need to know that as we will need to * make sure we return the right font */ - int offset = fcInfo.fontFile.length()-4; + String fontFile = fcInfo.firstFont.fontFile; + int offset = fontFile.length()-4; if (offset <= 0) { return null; } - String ext = fcInfo.fontFile.substring(offset).toLowerCase(); + String ext = fontFile.substring(offset).toLowerCase(); boolean isTTC = ext.equals(".ttc"); /* If this file is already registered, can just return its font. @@ -3230,10 +3292,10 @@ public final class FontManager { * a specific font, so rather than directly returning it, let * findFont2D resolve that. */ - PhysicalFont physFont = registeredFontFiles.get(fcInfo.fontFile); + PhysicalFont physFont = registeredFontFiles.get(fontFile); if (physFont != null) { if (isTTC) { - Font2D f2d = findFont2D(fcInfo.familyName, + Font2D f2d = findFont2D(fcInfo.firstFont.familyName, fcInfo.style, NO_FALLBACK); if (f2d instanceof PhysicalFont) { /* paranoia */ return (PhysicalFont)f2d; @@ -3249,18 +3311,20 @@ public final class FontManager { * Lucida Sans), we want to use the JRE version, so make it * point to the JRE font. */ - physFont = findJREDeferredFont(fcInfo.familyName, fcInfo.style); + physFont = findJREDeferredFont(fcInfo.firstFont.familyName, + fcInfo.style); /* It is also possible the font file is on the "deferred" list, * in which case we can just initialise it now. */ if (physFont == null && - deferredFontFiles.get(fcInfo.fontFile) != null) { - physFont = initialiseDeferredFont(fcInfo.fontFile); + deferredFontFiles.get(fontFile) != null) + { + physFont = initialiseDeferredFont(fcInfo.firstFont.fontFile); /* use findFont2D to get the right font from TTC's */ if (physFont != null) { if (isTTC) { - Font2D f2d = findFont2D(fcInfo.familyName, + Font2D f2d = findFont2D(fcInfo.firstFont.familyName, fcInfo.style, NO_FALLBACK); if (f2d instanceof PhysicalFont) { /* paranoia */ return (PhysicalFont)f2d; @@ -3287,7 +3351,7 @@ public final class FontManager { fontFormat = FONTFORMAT_TYPE1; fontRank = Font2D.TYPE1_RANK; } - physFont = registerFontFile(fcInfo.fontFile, null, + physFont = registerFontFile(fcInfo.firstFont.fontFile, null, fontFormat, true, fontRank); } return physFont; @@ -3345,12 +3409,12 @@ public final class FontManager { } info[1] = info[1] + File.separator + "arial.ttf"; } else { - initFontConfigFonts(); + initFontConfigFonts(false); for (int i=0; i<fontConfigFonts.length; i++) { if ("sans".equals(fontConfigFonts[i].fcFamily) && 0 == fontConfigFonts[i].style) { - info[0] = fontConfigFonts[i].familyName; - info[1] = fontConfigFonts[i].fontFile; + info[0] = fontConfigFonts[i].firstFont.familyName; + info[1] = fontConfigFonts[i].firstFont.fontFile; break; } } @@ -3360,9 +3424,9 @@ public final class FontManager { */ if (info[0] == null) { if (fontConfigFonts.length > 0 && - fontConfigFonts[0].fontFile != null) { - info[0] = fontConfigFonts[0].familyName; - info[1] = fontConfigFonts[0].fontFile; + fontConfigFonts[0].firstFont.fontFile != null) { + info[0] = fontConfigFonts[0].firstFont.familyName; + info[1] = fontConfigFonts[0].firstFont.fontFile; } else { info[0] = "Dialog"; info[1] = "/dialog.ttf"; @@ -3373,8 +3437,8 @@ public final class FontManager { return defaultPlatformFont; } - private FontConfigInfo getFontConfigInfo() { - initFontConfigFonts(); + private FcCompFont getFcCompFont() { + initFontConfigFonts(false); for (int i=0; i<fontConfigFonts.length; i++) { if ("sans".equals(fontConfigFonts[i].fcFamily) && 0 == fontConfigFonts[i].style) { @@ -3391,9 +3455,9 @@ public final class FontManager { name = name.toLowerCase(); - initFontConfigFonts(); + initFontConfigFonts(false); - FontConfigInfo fcInfo = null; + FcCompFont fcInfo = null; for (int i=0; i<fontConfigFonts.length; i++) { if (name.equals(fontConfigFonts[i].fcFamily) && style == fontConfigFonts[i].style) { @@ -3407,7 +3471,8 @@ public final class FontManager { if (logging) { logger.info("FC name=" + name + " style=" + style + " uses " + - fcInfo.familyName + " in file: " + fcInfo.fontFile); + fcInfo.firstFont.familyName + + " in file: " + fcInfo.firstFont.fontFile); } if (fcInfo.compFont != null) { @@ -3420,7 +3485,8 @@ public final class FontManager { CompositeFont jdkFont = (CompositeFont) findFont2D(fcInfo.jdkName, style, LOGICAL_FALLBACK); - if (fcInfo.familyName == null || fcInfo.fontFile == null) { + if (fcInfo.firstFont.familyName == null || + fcInfo.firstFont.fontFile == null) { return (fcInfo.compFont = jdkFont); } @@ -3432,7 +3498,7 @@ public final class FontManager { * will fall through this code, but the regisration code will * find that file already registered and return its font. */ - FontFamily family = FontFamily.getFamily(fcInfo.familyName); + FontFamily family = FontFamily.getFamily(fcInfo.firstFont.familyName); PhysicalFont physFont = null; if (family != null) { Font2D f2D = family.getFontWithExactStyleMatch(fcInfo.style); @@ -3441,7 +3507,8 @@ public final class FontManager { } } - if (physFont == null || !fcInfo.fontFile.equals(physFont.platName)) { + if (physFont == null || + !fcInfo.firstFont.fontFile.equals(physFont.platName)) { physFont = registerFromFcInfo(fcInfo); if (physFont == null) { return (fcInfo.compFont = jdkFont); @@ -3459,10 +3526,10 @@ public final class FontManager { * together to prevent synthetic styling. */ for (int i=0; i<fontConfigFonts.length; i++) { - FontConfigInfo fc = fontConfigFonts[i]; + FcCompFont fc = fontConfigFonts[i]; if (fc != fcInfo && - physFont.getFamilyName(null).equals(fc.familyName) && - !fc.fontFile.equals(physFont.platName) && + physFont.getFamilyName(null).equals(fc.firstFont.familyName) && + !fc.firstFont.fontFile.equals(physFont.platName) && family.getFontWithExactStyleMatch(fc.style) == null) { registerFromFcInfo(fontConfigFonts[i]); diff --git a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java index 63b942bf4..d4f9424ef 100644 --- a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -78,6 +78,7 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment public static boolean isLinux; public static boolean isSolaris; + public static boolean isOpenSolaris; public static boolean isWindows; public static boolean noType1Font; private static Font defaultFont; @@ -167,6 +168,23 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment isLinux = true; } else if ("SunOS".equals(osName)) { isSolaris = true; + String version = System.getProperty("os.version", "0.0"); + try { + float ver = Float.parseFloat(version); + if (ver > 5.10f) { + File f = new File("/etc/release"); + FileInputStream fis = new FileInputStream(f); + InputStreamReader isr + = new InputStreamReader(fis, "ISO-8859-1"); + BufferedReader br = new BufferedReader(isr); + String line = br.readLine(); + if (line.indexOf("OpenSolaris") >= 0) { + isOpenSolaris = true; + } + fis.close(); + } + } catch (Exception e) { + } } else if ("Windows".equals(osName)) { isWindows = true; } @@ -174,11 +192,7 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment noType1Font = "true". equals(System.getProperty("sun.java2d.noType1Font")); - if (isOpenJDK()) { - String[] fontInfo = FontManager.getDefaultPlatformFont(); - defaultFontName = fontInfo[0]; - defaultFontFileName = fontInfo[1]; - } else { + if (!isOpenJDK()) { defaultFontName = lucidaFontName; if (useAbsoluteFontFileNames()) { defaultFontFileName = @@ -244,6 +258,11 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment * that might be specified. */ fontConfig = createFontConfiguration(); + if (isOpenJDK()) { + String[] fontInfo = FontManager.getDefaultPlatformFont(); + defaultFontName = fontInfo[0]; + defaultFontFileName = fontInfo[1]; + } getPlatformFontPathFromFontConfig(); String extraFontPath = fontConfig.getExtraFontPath(); @@ -1069,7 +1088,7 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment String fontFileName = getFileNameFromPlatformName(platformFontName); String[] nativeNames = null; - if (fontFileName == null) { + if (fontFileName == null || fontFileName.equals(platformFontName)){ /* No file located, so register using the platform name, * i.e. as a native font. */ diff --git a/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java index b531fa739..4c52788f8 100644 --- a/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java +++ b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java @@ -44,6 +44,7 @@ import java.util.*; import java.util.logging.*; import sun.awt.motif.MFontConfiguration; +import sun.font.FcFontConfiguration; import sun.font.Font2D; import sun.font.FontManager; import sun.font.NativeFont; @@ -350,6 +351,14 @@ public class X11GraphicsEnvironment * only to get called for these fonts. */ public String getFileNameFromPlatformName(String platName) { + + /* If the FontConfig file doesn't use xlfds, or its + * FcFontConfiguration, this may be already a file name. + */ + if (platName.startsWith("/")) { + return platName; + } + String fileName = null; String fontID = specificFontIDForName(platName); @@ -905,12 +914,50 @@ public class X11GraphicsEnvironment // Implements SunGraphicsEnvironment.createFontConfiguration. protected FontConfiguration createFontConfiguration() { - return new MFontConfiguration(this); + + /* The logic here decides whether to use a preconfigured + * fontconfig.properties file, or synthesise one using platform APIs. + * On Solaris (as opposed to OpenSolaris) we try to use the + * pre-configured ones, but if the files it specifies are missing + * we fail-safe to synthesising one. This might happen if Solaris + * changes its fonts. + * For OpenSolaris I don't expect us to ever create fontconfig files, + * so it will always synthesise. Note that if we misidentify + * OpenSolaris as Solaris, then the test for the presence of + * Solaris-only font files will correct this. + * For Linux we require an exact match of distro and version to + * use the preconfigured file, and also that it points to + * existent fonts. + * If synthesising fails, we fall back to any preconfigured file + * and do the best we can. For the commercial JDK this will be + * fine as it includes the Lucida fonts. OpenJDK should not hit + * this as the synthesis should always work on its platforms. + */ + FontConfiguration mFontConfig = new MFontConfiguration(this); + if (isOpenSolaris || + (isLinux && + (!mFontConfig.foundOsSpecificFile() || + !mFontConfig.fontFilesArePresent()) || + (isSolaris && !mFontConfig.fontFilesArePresent()))) { + FcFontConfiguration fcFontConfig = + new FcFontConfiguration(this); + if (fcFontConfig.init()) { + return fcFontConfig; + } + } + mFontConfig.init(); + return mFontConfig; } public FontConfiguration createFontConfiguration(boolean preferLocaleFonts, boolean preferPropFonts) { + FontConfiguration config = getFontConfiguration(); + if (config instanceof FcFontConfiguration) { + // Doesn't need to implement the alternate support. + return config; + } + return new MFontConfiguration(this, preferLocaleFonts, preferPropFonts); } @@ -921,6 +968,7 @@ public class X11GraphicsEnvironment * for this platform. */ public String getDefaultFontFaceName() { + return null; } diff --git a/src/solaris/classes/sun/font/FcFontConfiguration.java b/src/solaris/classes/sun/font/FcFontConfiguration.java new file mode 100644 index 000000000..fe2e5dbf8 --- /dev/null +++ b/src/solaris/classes/sun/font/FcFontConfiguration.java @@ -0,0 +1,517 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.font; + +import java.awt.Font; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.HashSet; +import java.util.logging.Logger; +import java.util.Properties; +import java.util.Scanner; +import sun.awt.FontConfiguration; +import sun.awt.FontDescriptor; +import sun.awt.SunToolkit; +import sun.font.CompositeFontDescriptor; +import sun.font.FontManager; +import sun.font.FontManager.FontConfigInfo; +import sun.font.FontManager.FcCompFont; +import sun.font.FontManager.FontConfigFont; +import sun.java2d.SunGraphicsEnvironment; + +public class FcFontConfiguration extends FontConfiguration { + + /** Version of the cache file format understood by this code. + * Its part of the file name so that we can rev this at + * any time, even in a minor JDK update. + * It is stored as the value of the "version" property. + * This is distinct from the version of "libfontconfig" that generated + * the cached results, and which is the "fcversion" property in the file. + * {@code FontConfiguration.getVersion()} also returns a version string, + * and has meant the version of the fontconfiguration.properties file + * that was read. Since this class doesn't use such files, then what + * that really means is whether the methods on this class return + * values that are compatible with the classes that do directly read + * from such files. It is a compatible subset of version "1". + */ + private static final String fileVersion = "1"; + private String fcInfoFileName = null; + + private FcCompFont[] fcCompFonts = null; + + public FcFontConfiguration(SunGraphicsEnvironment environment) { + super(environment); + init(); + } + + /* This isn't called but is needed to satisfy super-class contract. */ + public FcFontConfiguration(SunGraphicsEnvironment environment, + boolean preferLocaleFonts, + boolean preferPropFonts) { + super(environment, preferLocaleFonts, preferPropFonts); + init(); + } + + @Override + public synchronized boolean init() { + if (fcCompFonts != null) { + return true; + } + + readFcInfo(); + if (fcCompFonts == null) { + fcCompFonts = FontManager.loadFontConfig(); + if (fcCompFonts != null) { + try { + writeFcInfo(); + } catch (Exception e) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = + Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("Exception writing fcInfo " + e); + } + } + } else if (SunGraphicsEnvironment.debugFonts) { + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("Failed to get info from libfontconfig"); + } + } else { + FontManager.populateFontConfig(fcCompFonts); + } + + if (fcCompFonts == null) { + return false; // couldn't load fontconfig. + } + + // NB already in a privileged block from SGE + String javaHome = System.getProperty("java.home"); + if (javaHome == null) { + throw new Error("java.home property not set"); + } + String javaLib = javaHome + File.separator + "lib"; + getInstalledFallbackFonts(javaLib); + + return true; + } + + @Override + public String getFallbackFamilyName(String fontName, + String defaultFallback) { + // maintain compatibility with old font.properties files, which either + // had aliases for TimesRoman & Co. or defined mappings for them. + String compatibilityName = getCompatibilityFamilyName(fontName); + if (compatibilityName != null) { + return compatibilityName; + } + return defaultFallback; + } + + @Override + protected String + getFaceNameFromComponentFontName(String componentFontName) { + return null; + } + + @Override + protected String + getFileNameFromComponentFontName(String componentFontName) { + return null; + } + + @Override + public String getFileNameFromPlatformName(String platformName) { + /* Platform name is the file name, but rather than returning + * the arg, return null*/ + return null; + } + + @Override + protected Charset getDefaultFontCharset(String fontName) { + return Charset.forName("ISO8859_1"); + } + + @Override + protected String getEncoding(String awtFontName, + String characterSubsetName) { + return "default"; + } + + @Override + protected void initReorderMap() { + reorderMap = new HashMap(); + } + + @Override + public FontDescriptor[] getFontDescriptors(String fontName, int style) { + throw new InternalError("Not implemented"); + } + + @Override + public int getNumberCoreFonts() { + return 1; + } + + @Override + public String[] getPlatformFontNames() { + HashSet<String> nameSet = new HashSet<String>(); + FcCompFont[] fcCompFonts = FontManager.loadFontConfig(); + for (int i=0; i<fcCompFonts.length; i++) { + for (int j=0; j<fcCompFonts[i].allFonts.length; j++) { + nameSet.add(fcCompFonts[i].allFonts[j].fontFile); + } + } + return nameSet.toArray(new String[0]); + } + + @Override + public String getExtraFontPath() { + return null; + } + + @Override + public boolean needToSearchForFile(String fileName) { + return false; + } + + private FontConfigFont[] getFcFontList(FcCompFont[] fcFonts, + String fontname, int style) { + + if (fontname.equals("dialog")) { + fontname = "sansserif"; + } else if (fontname.equals("dialoginput")) { + fontname = "monospaced"; + } + for (int i=0; i<fcFonts.length; i++) { + if (fontname.equals(fcFonts[i].jdkName) && + style == fcFonts[i].style) { + return fcFonts[i].allFonts; + } + } + return fcFonts[0].allFonts; + } + + @Override + public CompositeFontDescriptor[] get2DCompositeFontInfo() { + + FcCompFont[] fcCompFonts = FontManager.loadFontConfig(); + + CompositeFontDescriptor[] result = + new CompositeFontDescriptor[NUM_FONTS * NUM_STYLES]; + + for (int fontIndex = 0; fontIndex < NUM_FONTS; fontIndex++) { + String fontName = publicFontNames[fontIndex]; + + for (int styleIndex = 0; styleIndex < NUM_STYLES; styleIndex++) { + + String faceName = fontName + "." + styleNames[styleIndex]; + FontConfigFont[] fcFonts = + getFcFontList(fcCompFonts, + fontNames[fontIndex], styleIndex); + + int numFonts = fcFonts.length; + // fall back fonts listed in the lib/fonts/fallback directory + if (installedFallbackFontFiles != null) { + numFonts += installedFallbackFontFiles.length; + } + + String[] fileNames = new String[numFonts]; + + int index; + for (index = 0; index < fcFonts.length; index++) { + fileNames[index] = fcFonts[index].fontFile; + } + + if (installedFallbackFontFiles != null) { + System.arraycopy(fileNames, index, + installedFallbackFontFiles, + 0, installedFallbackFontFiles.length); + } + + result[fontIndex * NUM_STYLES + styleIndex] + = new CompositeFontDescriptor( + faceName, + 1, + null, + fileNames, + null, null); + } + } + return result; + } + + /** + * Gets the OS version string from a Linux release-specific file. + */ + private String getVersionString(File f){ + try { + Scanner sc = new Scanner(f); + return sc.findInLine("(\\d)+((\\.)(\\d)+)*"); + } + catch (Exception e){ + } + return null; + } + + /** + * Sets the OS name and version from environment information. + */ + @Override + protected void setOsNameAndVersion() { + + super.setOsNameAndVersion(); + + if (!osName.equals("Linux")) { + return; + } + try { + File f; + if ((f = new File("/etc/lsb-release")).canRead()) { + /* Ubuntu and (perhaps others) use only lsb-release. + * Syntax and encoding is compatible with java properties. + * For Ubuntu the ID is "Ubuntu". + */ + Properties props = new Properties(); + props.load(new FileInputStream(f)); + osName = props.getProperty("DISTRIB_ID"); + osVersion = props.getProperty("DISTRIB_RELEASE"); + } else if ((f = new File("/etc/redhat-release")).canRead()) { + osName = "RedHat"; + osVersion = getVersionString(f); + } else if ((f = new File("/etc/SuSE-release")).canRead()) { + osName = "SuSE"; + osVersion = getVersionString(f); + } else if ((f = new File("/etc/turbolinux-release")).canRead()) { + osName = "Turbo"; + osVersion = getVersionString(f); + } else if ((f = new File("/etc/fedora-release")).canRead()) { + osName = "Fedora"; + osVersion = getVersionString(f); + } else if ((f = new File("/etc/sun-release")).canRead()) { + osName = "Sun"; + osVersion = getVersionString(f); + } + } catch (Exception e) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("Exception identifying Linux distro."); + } + } + } + + private File getFcInfoFile() { + if (fcInfoFileName == null) { + // NB need security permissions to get true IP address, and + // we should have those as the whole initialisation is in a + // doPrivileged block. But in this case no exception is thrown, + // and it returns the loop back address, and so we end up with + // "localhost" + String hostname; + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + hostname = "localhost"; + } + String userDir = System.getProperty("user.home"); + String version = System.getProperty("java.version"); + String fs = File.separator; + String dir = userDir+fs+".java"+fs+"fonts"+fs+version; + String lang = SunToolkit.getStartupLocale().getLanguage(); + String name = "fcinfo-"+fileVersion+"-"+hostname+"-"+ + osName+"-"+osVersion+"-"+lang+".properties"; + fcInfoFileName = dir+fs+name; + } + return new File(fcInfoFileName); + } + + private void writeFcInfo() { + Properties props = new Properties(); + props.setProperty("version", fileVersion); + FontConfigInfo fcInfo = FontManager.getFontConfigInfo(); + props.setProperty("fcversion", Integer.toString(fcInfo.fcVersion)); + if (fcInfo.cacheDirs != null) { + for (int i=0;i<fcInfo.cacheDirs.length;i++) { + if (fcInfo.cacheDirs[i] != null) { + props.setProperty("cachedir."+i, fcInfo.cacheDirs[i]); + } + } + } + for (int i=0; i<fcCompFonts.length; i++) { + FcCompFont fci = fcCompFonts[i]; + String styleKey = fci.jdkName+"."+fci.style; + props.setProperty(styleKey+".length", + Integer.toString(fci.allFonts.length)); + for (int j=0; j<fci.allFonts.length; j++) { + props.setProperty(styleKey+"."+j+".family", + fci.allFonts[j].familyName); + props.setProperty(styleKey+"."+j+".file", + fci.allFonts[j].fontFile); + } + } + try { + /* This writes into a temp file then renames when done. + * Since the rename is an atomic action within the same + * directory no client will ever see a partially written file. + */ + File fcInfoFile = getFcInfoFile(); + File dir = fcInfoFile.getParentFile(); + dir.mkdirs(); + File tempFile = File.createTempFile("fcinfo", null, dir); + FileOutputStream fos = new FileOutputStream(tempFile); + props.store(fos, + "JDK Font Configuration Generated File: *Do Not Edit*"); + fos.close(); + boolean renamed = tempFile.renameTo(fcInfoFile); + if (!renamed && SunGraphicsEnvironment.debugFonts) { + System.out.println("rename failed"); + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("Failed renaming file to "+ getFcInfoFile()); + } + } catch (Exception e) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("IOException writing to "+ getFcInfoFile()); + } + } + } + + /* We want to be able to use this cache instead of invoking + * fontconfig except when we can detect the system cache has changed. + * But there doesn't seem to be a way to find the location of + * the system cache. + */ + private void readFcInfo() { + File fcFile = getFcInfoFile(); + if (!fcFile.exists()) { + return; + } + Properties props = new Properties(); + try { + FileInputStream fis = new FileInputStream(fcFile); + props.load(fis); + fis.close(); + } catch (IOException e) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("IOException reading from "+fcFile.toString()); + } + return; + } + String version = (String)props.get("version"); + if (version == null || !version.equals(fileVersion)) { + return; + } + + // If there's a new, different fontconfig installed on the + // system, we invalidate our fontconfig file. + String fcVersionStr = (String)props.get("fcversion"); + if (fcVersionStr != null) { + int fcVersion; + try { + fcVersion = Integer.parseInt(fcVersionStr); + if (fcVersion != 0 && + fcVersion != FontManager.getFontConfigVersion()) { + return; + } + } catch (Exception e) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = + Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning("Exception parsing version " + + fcVersionStr); + } + return; + } + } + + // If we can locate the fontconfig cache dirs, then compare the + // time stamp of those with our properties file. If we are out + // of date then re-generate. + long lastModified = fcFile.lastModified(); + int cacheDirIndex = 0; + while (cacheDirIndex<4) { // should never be more than 2 anyway. + String dir = (String)props.get("cachedir."+cacheDirIndex); + if (dir == null) { + break; + } + File dirFile = new File(dir); + if (dirFile.exists() && dirFile.lastModified() > lastModified) { + return; + } + cacheDirIndex++; + } + + String[] names = { "sansserif", "serif", "monospaced" }; + String[] fcnames = { "sans", "serif", "monospace" }; + int namesLen = names.length; + int numStyles = 4; + FcCompFont[] fci = new FcCompFont[namesLen*numStyles]; + + try { + for (int i=0; i<namesLen; i++) { + for (int s=0; s<numStyles; s++) { + int index = i*numStyles+s; + fci[index] = new FcCompFont(); + String key = names[i]+"."+s; + fci[index].jdkName = names[i]; + fci[index].fcFamily = fcnames[i]; + fci[index].style = s; + String lenStr = (String)props.get(key+".length"); + int nfonts = Integer.parseInt(lenStr); + if (nfonts <= 0) { + return; // bad file + } + fci[index].allFonts = new FontConfigFont[nfonts]; + for (int f=0; f<nfonts; f++) { + fci[index].allFonts[f] = new FontConfigFont(); + String fkey = key+"."+f+".family"; + String family = (String)props.get(fkey); + fci[index].allFonts[f].familyName = family; + fkey = key+"."+f+".file"; + String file = (String)props.get(fkey); + if (file == null) { + return; // bad file + } + fci[index].allFonts[f].fontFile = file; + } + fci[index].firstFont = fci[index].allFonts[0]; + + } + } + fcCompFonts = fci; + } catch (Throwable t) { + if (SunGraphicsEnvironment.debugFonts) { + Logger logger = Logger.getLogger("sun.awt.FontConfiguration"); + logger.warning(t.toString()); + } + } + } +} diff --git a/src/solaris/native/sun/awt/fontconfig.h b/src/solaris/native/sun/awt/fontconfig.h index fe84abef2..d6e49d88b 100644 --- a/src/solaris/native/sun/awt/fontconfig.h +++ b/src/solaris/native/sun/awt/fontconfig.h @@ -1,11 +1,7 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* * $RCSId: xc/lib/fontconfig/fontconfig/fontconfig.h,v 1.30 2002/09/26 00:17:27 keithp Exp $ * - * Copyright © 2001 Keith Packard + * Copyright © 2001 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -29,8 +25,21 @@ #ifndef _FONTCONFIG_H_ #define _FONTCONFIG_H_ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <stdarg.h> +#if defined(__GNUC__) && (__GNUC__ >= 4) +#define FC_ATTRIBUTE_SENTINEL(x) __attribute__((__sentinel__(0))) +#else +#define FC_ATTRIBUTE_SENTINEL(x) +#endif + +#ifndef FcPublic +#define FcPublic +#endif + typedef unsigned char FcChar8; typedef unsigned short FcChar16; typedef unsigned int FcChar32; @@ -43,7 +52,7 @@ typedef int FcBool; */ #define FC_MAJOR 2 -#define FC_MINOR 2 +#define FC_MINOR 5 #define FC_REVISION 0 #define FC_VERSION ((FC_MAJOR * 10000) + (FC_MINOR * 100) + (FC_REVISION)) @@ -58,7 +67,7 @@ typedef int FcBool; * it means multiple copies of the font information. */ -#define FC_CACHE_VERSION "1" +#define FC_CACHE_VERSION "2" #define FcTrue 1 #define FcFalse 0 @@ -74,6 +83,7 @@ typedef int FcBool; #define FC_FOUNDRY "foundry" /* String */ #define FC_ANTIALIAS "antialias" /* Bool (depends) */ #define FC_HINTING "hinting" /* Bool (true) */ +#define FC_HINT_STYLE "hintstyle" /* Int */ #define FC_VERTICAL_LAYOUT "verticallayout" /* Bool (false) */ #define FC_AUTOHINT "autohint" /* Bool (false) */ #define FC_GLOBAL_ADVANCE "globaladvance" /* Bool (true) */ @@ -88,11 +98,21 @@ typedef int FcBool; #define FC_DPI "dpi" /* double */ #define FC_RGBA "rgba" /* Int */ #define FC_MINSPACE "minspace" /* Bool use minimum line spacing */ -#define FC_SOURCE "source" /* String (X11, freetype) */ +#define FC_SOURCE "source" /* String (deprecated) */ #define FC_CHARSET "charset" /* CharSet */ #define FC_LANG "lang" /* String RFC 3066 langs */ #define FC_FONTVERSION "fontversion" /* Int from 'head' table */ - +#define FC_FULLNAME "fullname" /* String */ +#define FC_FAMILYLANG "familylang" /* String RFC 3066 langs */ +#define FC_STYLELANG "stylelang" /* String RFC 3066 langs */ +#define FC_FULLNAMELANG "fullnamelang" /* String RFC 3066 langs */ +#define FC_CAPABILITY "capability" /* String */ +#define FC_FONTFORMAT "fontformat" /* String */ +#define FC_EMBOLDEN "embolden" /* Bool - true if emboldening needed*/ +#define FC_EMBEDDED_BITMAP "embeddedbitmap" /* Bool - true to enable embedded bitmaps */ +#define FC_DECORATIVE "decorative" /* Bool - true if style is a decorative variant */ + +#define FC_CACHE_SUFFIX ".cache-"FC_CACHE_VERSION #define FC_DIR_CACHE_FILE "fonts.cache-"FC_CACHE_VERSION #define FC_USER_CACHE_FILE ".fonts.cache-"FC_CACHE_VERSION @@ -105,6 +125,7 @@ typedef int FcBool; #define FC_WEIGHT_EXTRALIGHT 40 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT #define FC_WEIGHT_LIGHT 50 +#define FC_WEIGHT_BOOK 75 #define FC_WEIGHT_REGULAR 80 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR #define FC_WEIGHT_MEDIUM 100 @@ -115,6 +136,8 @@ typedef int FcBool; #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD #define FC_WEIGHT_BLACK 210 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK +#define FC_WEIGHT_EXTRABLACK 215 +#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_EXTRABLACK #define FC_SLANT_ROMAN 0 #define FC_SLANT_ITALIC 100 @@ -131,6 +154,7 @@ typedef int FcBool; #define FC_WIDTH_ULTRAEXPANDED 200 #define FC_PROPORTIONAL 0 +#define FC_DUAL 90 #define FC_MONO 100 #define FC_CHARCELL 110 @@ -142,6 +166,12 @@ typedef int FcBool; #define FC_RGBA_VBGR 4 #define FC_RGBA_NONE 5 +/* hinting style */ +#define FC_HINT_NONE 0 +#define FC_HINT_SLIGHT 1 +#define FC_HINT_MEDIUM 2 +#define FC_HINT_FULL 3 + typedef enum _FcType { FcTypeVoid, FcTypeInteger, @@ -180,7 +210,8 @@ typedef struct _FcConstant { } FcConstant; typedef enum _FcResult { - FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId + FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId, + FcResultOutOfMemory } FcResult; typedef struct _FcPattern FcPattern; @@ -197,7 +228,6 @@ typedef struct _FcValue { const FcMatrix *m; const FcCharSet *c; void *f; - const FcPattern *p; const FcLangSet *l; } u; } FcValue; @@ -215,11 +245,14 @@ typedef struct _FcObjectSet { } FcObjectSet; typedef enum _FcMatchKind { - FcMatchPattern, FcMatchFont + FcMatchPattern, FcMatchFont, FcMatchScan } FcMatchKind; typedef enum _FcLangResult { - FcLangEqual, FcLangDifferentCountry, FcLangDifferentLang + FcLangEqual = 0, + FcLangDifferentCountry = 1, + FcLangDifferentTerritory = 1, + FcLangDifferentLang = 2 } FcLangResult; typedef enum _FcSetName { @@ -249,169 +282,207 @@ typedef struct _FcStrList FcStrList; typedef struct _FcStrSet FcStrSet; -_FCFUNCPROTOBEGIN +typedef struct _FcCache FcCache; -FcBool -FcDirCacheValid (const FcChar8 *cache_file); +_FCFUNCPROTOBEGIN /* fcblanks.c */ -FcBlanks * +FcPublic FcBlanks * FcBlanksCreate (void); -void +FcPublic void FcBlanksDestroy (FcBlanks *b); -FcBool +FcPublic FcBool FcBlanksAdd (FcBlanks *b, FcChar32 ucs4); -FcBool +FcPublic FcBool FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4); +/* fccache.c */ + +FcPublic const FcChar8 * +FcCacheDir(const FcCache *c); + +FcPublic FcFontSet * +FcCacheCopySet(const FcCache *c); + +FcPublic const FcChar8 * +FcCacheSubdir (const FcCache *c, int i); + +FcPublic int +FcCacheNumSubdir (const FcCache *c); + +FcPublic int +FcCacheNumFont (const FcCache *c); + +FcPublic FcBool +FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config); + +FcPublic FcBool +FcDirCacheValid (const FcChar8 *cache_file); + /* fccfg.c */ -FcChar8 * +FcPublic FcChar8 * FcConfigHome (void); -FcBool +FcPublic FcBool FcConfigEnableHome (FcBool enable); -FcChar8 * +FcPublic FcChar8 * FcConfigFilename (const FcChar8 *url); -FcConfig * +FcPublic FcConfig * FcConfigCreate (void); -void +FcPublic void FcConfigDestroy (FcConfig *config); -FcBool +FcPublic FcBool FcConfigSetCurrent (FcConfig *config); -FcConfig * +FcPublic FcConfig * FcConfigGetCurrent (void); -FcBool +FcPublic FcBool FcConfigUptoDate (FcConfig *config); -FcBool +FcPublic FcBool FcConfigBuildFonts (FcConfig *config); -FcStrList * +FcPublic FcStrList * FcConfigGetFontDirs (FcConfig *config); -FcStrList * +FcPublic FcStrList * FcConfigGetConfigDirs (FcConfig *config); -FcStrList * +FcPublic FcStrList * FcConfigGetConfigFiles (FcConfig *config); -FcChar8 * +FcPublic FcChar8 * FcConfigGetCache (FcConfig *config); -FcBlanks * +FcPublic FcBlanks * FcConfigGetBlanks (FcConfig *config); -int -FcConfigGetRescanInverval (FcConfig *config); +FcPublic FcStrList * +FcConfigGetCacheDirs (FcConfig *config); + +FcPublic int +FcConfigGetRescanInterval (FcConfig *config); -FcBool -FcConfigSetRescanInverval (FcConfig *config, int rescanInterval); +FcPublic FcBool +FcConfigSetRescanInterval (FcConfig *config, int rescanInterval); -FcFontSet * +FcPublic FcFontSet * FcConfigGetFonts (FcConfig *config, FcSetName set); -FcBool +FcPublic FcBool FcConfigAppFontAddFile (FcConfig *config, const FcChar8 *file); -FcBool +FcPublic FcBool FcConfigAppFontAddDir (FcConfig *config, const FcChar8 *dir); -void +FcPublic void FcConfigAppFontClear (FcConfig *config); -FcBool +FcPublic FcBool FcConfigSubstituteWithPat (FcConfig *config, FcPattern *p, FcPattern *p_pat, FcMatchKind kind); -FcBool +FcPublic FcBool FcConfigSubstitute (FcConfig *config, FcPattern *p, FcMatchKind kind); /* fccharset.c */ -FcCharSet * +FcPublic FcCharSet* FcCharSetCreate (void); -void +/* deprecated alias for FcCharSetCreate */ +FcPublic FcCharSet * +FcCharSetNew (void); + +FcPublic void FcCharSetDestroy (FcCharSet *fcs); -FcBool +FcPublic FcBool FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4); -FcCharSet * +FcPublic FcCharSet* FcCharSetCopy (FcCharSet *src); -FcBool +FcPublic FcBool FcCharSetEqual (const FcCharSet *a, const FcCharSet *b); -FcCharSet * +FcPublic FcCharSet* FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b); -FcCharSet * +FcPublic FcCharSet* FcCharSetUnion (const FcCharSet *a, const FcCharSet *b); -FcCharSet * +FcPublic FcCharSet* FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b); -FcBool +FcPublic FcBool FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4); -FcChar32 +FcPublic FcChar32 FcCharSetCount (const FcCharSet *a); -FcChar32 +FcPublic FcChar32 FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b); -FcChar32 +FcPublic FcChar32 FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b); -FcBool +FcPublic FcBool FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b); #define FC_CHARSET_MAP_SIZE (256/32) #define FC_CHARSET_DONE ((FcChar32) -1) -FcChar32 +FcPublic FcChar32 FcCharSetFirstPage (const FcCharSet *a, FcChar32 map[FC_CHARSET_MAP_SIZE], FcChar32 *next); -FcChar32 +FcPublic FcChar32 FcCharSetNextPage (const FcCharSet *a, FcChar32 map[FC_CHARSET_MAP_SIZE], FcChar32 *next); +/* + * old coverage API, rather hard to use correctly + */ + +FcPublic FcChar32 +FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result); /* fcdbg.c */ -void +FcPublic void FcValuePrint (const FcValue v); -void +FcPublic void FcPatternPrint (const FcPattern *p); -void +FcPublic void FcFontSetPrint (const FcFontSet *s); /* fcdefault.c */ -void +FcPublic void FcDefaultSubstitute (FcPattern *pattern); /* fcdir.c */ -FcBool +FcPublic FcBool +FcFileIsDir (const FcChar8 *file); + +FcPublic FcBool FcFileScan (FcFontSet *set, FcStrSet *dirs, FcFileCache *cache, @@ -419,7 +490,7 @@ FcFileScan (FcFontSet *set, const FcChar8 *file, FcBool force); -FcBool +FcPublic FcBool FcDirScan (FcFontSet *set, FcStrSet *dirs, FcFileCache *cache, @@ -427,144 +498,165 @@ FcDirScan (FcFontSet *set, const FcChar8 *dir, FcBool force); -FcBool +FcPublic FcBool FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir); +FcPublic FcCache * +FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file); + +FcPublic FcCache * +FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config); + +FcPublic FcCache * +FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat); + +FcPublic void +FcDirCacheUnload (FcCache *cache); + /* fcfreetype.c */ -FcPattern * +FcPublic FcPattern * FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count); /* fcfs.c */ -FcFontSet * +FcPublic FcFontSet * FcFontSetCreate (void); -void +FcPublic void FcFontSetDestroy (FcFontSet *s); -FcBool +FcPublic FcBool FcFontSetAdd (FcFontSet *s, FcPattern *font); /* fcinit.c */ -FcConfig * +FcPublic FcConfig * FcInitLoadConfig (void); -FcConfig * +FcPublic FcConfig * FcInitLoadConfigAndFonts (void); -FcBool +FcPublic FcBool FcInit (void); -int +FcPublic void +FcFini (void); + +FcPublic int FcGetVersion (void); -FcBool +FcPublic FcBool FcInitReinitialize (void); -FcBool +FcPublic FcBool FcInitBringUptoDate (void); /* fclang.c */ -FcLangSet * +FcPublic FcStrSet * +FcGetLangs (void); + +FcPublic const FcCharSet * +FcLangGetCharSet (const FcChar8 *lang); + +FcPublic FcLangSet* FcLangSetCreate (void); -void +FcPublic void FcLangSetDestroy (FcLangSet *ls); -FcLangSet * +FcPublic FcLangSet* FcLangSetCopy (const FcLangSet *ls); -FcBool +FcPublic FcBool FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang); -FcLangResult +FcPublic FcLangResult FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang); -FcLangResult +FcPublic FcLangResult FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb); -FcBool +FcPublic FcBool FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb); -FcBool +FcPublic FcBool FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb); -FcChar32 +FcPublic FcChar32 FcLangSetHash (const FcLangSet *ls); /* fclist.c */ -FcObjectSet * +FcPublic FcObjectSet * FcObjectSetCreate (void); -FcBool +FcPublic FcBool FcObjectSetAdd (FcObjectSet *os, const char *object); -void +FcPublic void FcObjectSetDestroy (FcObjectSet *os); -FcObjectSet * +FcPublic FcObjectSet * FcObjectSetVaBuild (const char *first, va_list va); -FcObjectSet * -FcObjectSetBuild (const char *first, ...); +FcPublic FcObjectSet * +FcObjectSetBuild (const char *first, ...) FC_ATTRIBUTE_SENTINEL(0); -FcFontSet * +FcPublic FcFontSet * FcFontSetList (FcConfig *config, FcFontSet **sets, int nsets, FcPattern *p, FcObjectSet *os); -FcFontSet * +FcPublic FcFontSet * FcFontList (FcConfig *config, FcPattern *p, FcObjectSet *os); /* fcatomic.c */ -FcAtomic * +FcPublic FcAtomic * FcAtomicCreate (const FcChar8 *file); -FcBool +FcPublic FcBool FcAtomicLock (FcAtomic *atomic); -FcChar8 * +FcPublic FcChar8 * FcAtomicNewFile (FcAtomic *atomic); -FcChar8 * +FcPublic FcChar8 * FcAtomicOrigFile (FcAtomic *atomic); -FcBool +FcPublic FcBool FcAtomicReplaceOrig (FcAtomic *atomic); -void +FcPublic void FcAtomicDeleteNew (FcAtomic *atomic); -void +FcPublic void FcAtomicUnlock (FcAtomic *atomic); -void +FcPublic void FcAtomicDestroy (FcAtomic *atomic); /* fcmatch.c */ -FcPattern * +FcPublic FcPattern * FcFontSetMatch (FcConfig *config, FcFontSet **sets, int nsets, FcPattern *p, FcResult *result); -FcPattern * +FcPublic FcPattern * FcFontMatch (FcConfig *config, FcPattern *p, FcResult *result); -FcPattern * +FcPublic FcPattern * FcFontRenderPrepare (FcConfig *config, FcPattern *pat, FcPattern *font); -FcFontSet * +FcPublic FcFontSet * FcFontSetSort (FcConfig *config, FcFontSet **sets, int nsets, @@ -573,179 +665,198 @@ FcFontSetSort (FcConfig *config, FcCharSet **csp, FcResult *result); -FcFontSet * +FcPublic FcFontSet * FcFontSort (FcConfig *config, FcPattern *p, FcBool trim, FcCharSet **csp, FcResult *result); -void +FcPublic void FcFontSetSortDestroy (FcFontSet *fs); /* fcmatrix.c */ -FcMatrix * +FcPublic FcMatrix * FcMatrixCopy (const FcMatrix *mat); -FcBool +FcPublic FcBool FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2); -void +FcPublic void FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b); -void +FcPublic void FcMatrixRotate (FcMatrix *m, double c, double s); -void +FcPublic void FcMatrixScale (FcMatrix *m, double sx, double sy); -void +FcPublic void FcMatrixShear (FcMatrix *m, double sh, double sv); /* fcname.c */ -FcBool +FcPublic FcBool FcNameRegisterObjectTypes (const FcObjectType *types, int ntype); -FcBool +FcPublic FcBool FcNameUnregisterObjectTypes (const FcObjectType *types, int ntype); -const FcObjectType * +FcPublic const FcObjectType * FcNameGetObjectType (const char *object); -FcBool +FcPublic FcBool FcNameRegisterConstants (const FcConstant *consts, int nconsts); -FcBool +FcPublic FcBool FcNameUnregisterConstants (const FcConstant *consts, int nconsts); -const FcConstant * +FcPublic const FcConstant * FcNameGetConstant (FcChar8 *string); -FcBool +FcPublic FcBool FcNameConstant (FcChar8 *string, int *result); -FcPattern * +FcPublic FcPattern * FcNameParse (const FcChar8 *name); -FcChar8 * +FcPublic FcChar8 * FcNameUnparse (FcPattern *pat); /* fcpat.c */ -FcPattern * +FcPublic FcPattern * FcPatternCreate (void); -FcPattern * +FcPublic FcPattern * FcPatternDuplicate (const FcPattern *p); -void +FcPublic void FcPatternReference (FcPattern *p); -void +FcPublic void FcValueDestroy (FcValue v); -FcBool +FcPublic FcBool FcValueEqual (FcValue va, FcValue vb); -FcValue +FcPublic FcValue FcValueSave (FcValue v); -void +FcPublic void FcPatternDestroy (FcPattern *p); -FcBool +FcPublic FcBool FcPatternEqual (const FcPattern *pa, const FcPattern *pb); -FcBool +FcPublic FcBool FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os); -FcChar32 +FcPublic FcChar32 FcPatternHash (const FcPattern *p); -FcBool +FcPublic FcBool FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append); -FcBool +FcPublic FcBool FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append); -FcResult +FcPublic FcResult FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v); -FcBool +FcPublic FcBool FcPatternDel (FcPattern *p, const char *object); -FcBool +FcPublic FcBool +FcPatternRemove (FcPattern *p, const char *object, int id); + +FcPublic FcBool FcPatternAddInteger (FcPattern *p, const char *object, int i); -FcBool +FcPublic FcBool FcPatternAddDouble (FcPattern *p, const char *object, double d); -FcBool +FcPublic FcBool FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s); -FcBool +FcPublic FcBool FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s); -FcBool +FcPublic FcBool FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c); -FcBool +FcPublic FcBool FcPatternAddBool (FcPattern *p, const char *object, FcBool b); -FcBool +FcPublic FcBool FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls); -FcResult +FcPublic FcResult FcPatternGetInteger (const FcPattern *p, const char *object, int n, int *i); -FcResult +FcPublic FcResult FcPatternGetDouble (const FcPattern *p, const char *object, int n, double *d); -FcResult +FcPublic FcResult FcPatternGetString (const FcPattern *p, const char *object, int n, FcChar8 ** s); -FcResult +FcPublic FcResult FcPatternGetMatrix (const FcPattern *p, const char *object, int n, FcMatrix **s); -FcResult +FcPublic FcResult FcPatternGetCharSet (const FcPattern *p, const char *object, int n, FcCharSet **c); -FcResult +FcPublic FcResult FcPatternGetBool (const FcPattern *p, const char *object, int n, FcBool *b); -FcResult +FcPublic FcResult FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **ls); -FcPattern * +FcPublic FcPattern * FcPatternVaBuild (FcPattern *orig, va_list va); -FcPattern * -FcPatternBuild (FcPattern *orig, ...); +FcPublic FcPattern * +FcPatternBuild (FcPattern *orig, ...) FC_ATTRIBUTE_SENTINEL(0); /* fcstr.c */ -FcChar8 * +FcPublic FcChar8 * FcStrCopy (const FcChar8 *s); -FcChar8 * +FcPublic FcChar8 * FcStrCopyFilename (const FcChar8 *s); -#define FcIsUpper(c) (('A' <= (c) && (c) <= 'Z')) -#define FcIsLower(c) (('a' <= (c) && (c) <= 'z')) -#define FcToLower(c) (FcIsUpper(c) ? (c) - 'A' + 'a' : (c)) +FcPublic FcChar8 * +FcStrPlus (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic void +FcStrFree (FcChar8 *s); + +/* These are ASCII only, suitable only for pattern element names */ +#define FcIsUpper(c) ((0101 <= (c) && (c) <= 0132)) +#define FcIsLower(c) ((0141 <= (c) && (c) <= 0172)) +#define FcToLower(c) (FcIsUpper(c) ? (c) - 0101 + 0141 : (c)) -int +FcPublic FcChar8 * +FcStrDowncase (const FcChar8 *s); + +FcPublic int FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2); -int +FcPublic int FcStrCmp (const FcChar8 *s1, const FcChar8 *s2); -int +FcPublic const FcChar8 * +FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic const FcChar8 * +FcStrStr (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic int FcUtf8ToUcs4 (const FcChar8 *src_orig, FcChar32 *dst, int len); -FcBool +FcPublic FcBool FcUtf8Len (const FcChar8 *string, int len, int *nchar, @@ -753,63 +864,78 @@ FcUtf8Len (const FcChar8 *string, #define FC_UTF8_MAX_LEN 6 -int +FcPublic int FcUcs4ToUtf8 (FcChar32 ucs4, FcChar8 dest[FC_UTF8_MAX_LEN]); -int +FcPublic int FcUtf16ToUcs4 (const FcChar8 *src_orig, FcEndian endian, FcChar32 *dst, int len); /* in bytes */ -FcBool +FcPublic FcBool FcUtf16Len (const FcChar8 *string, FcEndian endian, int len, /* in bytes */ int *nchar, int *wchar); -FcChar8 * +FcPublic FcChar8 * FcStrDirname (const FcChar8 *file); -FcChar8 * +FcPublic FcChar8 * FcStrBasename (const FcChar8 *file); -FcStrSet * +FcPublic FcStrSet * FcStrSetCreate (void); -FcBool +FcPublic FcBool FcStrSetMember (FcStrSet *set, const FcChar8 *s); -FcBool +FcPublic FcBool FcStrSetEqual (FcStrSet *sa, FcStrSet *sb); -FcBool +FcPublic FcBool FcStrSetAdd (FcStrSet *set, const FcChar8 *s); -FcBool +FcPublic FcBool FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s); -FcBool +FcPublic FcBool FcStrSetDel (FcStrSet *set, const FcChar8 *s); -void +FcPublic void FcStrSetDestroy (FcStrSet *set); -FcStrList * +FcPublic FcStrList * FcStrListCreate (FcStrSet *set); -FcChar8 * +FcPublic FcChar8 * FcStrListNext (FcStrList *list); -void +FcPublic void FcStrListDone (FcStrList *list); /* fcxml.c */ -FcBool +FcPublic FcBool FcConfigParseAndLoad (FcConfig *config, const FcChar8 *file, FcBool complain); _FCFUNCPROTOEND +#undef FC_ATTRIBUTE_SENTINEL + + +#ifndef _FCINT_H_ + +/* + * Deprecated functions are placed here to help users fix their code without + * digging through documentation + */ + +#define FcConfigGetRescanInverval FcConfigGetRescanInverval_REPLACE_BY_FcConfigGetRescanInterval +#define FcConfigSetRescanInverval FcConfigSetRescanInverval_REPLACE_BY_FcConfigSetRescanInterval + +#endif + #endif /* _FONTCONFIG_H_ */ diff --git a/src/solaris/native/sun/awt/fontpath.c b/src/solaris/native/sun/awt/fontpath.c index d863d265b..8f9f3d9a8 100644 --- a/src/solaris/native/sun/awt/fontpath.c +++ b/src/solaris/native/sun/awt/fontpath.c @@ -735,6 +735,25 @@ typedef FcPattern* (*FcFontMatchFuncType)(FcConfig *config, typedef FcFontSet* (*FcFontSetCreateFuncType)(); typedef FcBool (*FcFontSetAddFuncType)(FcFontSet *s, FcPattern *font); +typedef FcResult (*FcPatternGetCharSetFuncType)(FcPattern *p, + const char *object, + int n, + FcCharSet **c); +typedef FcFontSet* (*FcFontSortFuncType)(FcConfig *config, + FcPattern *p, + FcBool trim, + FcCharSet **csp, + FcResult *result); +typedef FcCharSet* (*FcCharSetUnionFuncType)(const FcCharSet *a, + const FcCharSet *b); +typedef FcChar32 (*FcCharSetSubtractCountFuncType)(const FcCharSet *a, + const FcCharSet *b); + +typedef int (*FcGetVersionFuncType)(); + +typedef FcStrList* (*FcConfigGetCacheDirsFuncType)(FcConfig *config); +typedef FcChar8* (*FcStrListNextFuncType)(FcStrList *list); +typedef FcChar8* (*FcStrListDoneFuncType)(FcStrList *list); static char **getFontConfigLocations() { @@ -955,10 +974,35 @@ Java_sun_font_FontManager_getFontConfigAASettings } } +JNIEXPORT jint JNICALL +Java_sun_font_FontManager_getFontConfigVersion + (JNIEnv *env, jclass obj) { + + void* libfontconfig; + FcGetVersionFuncType FcGetVersion; + int version = 0; + + if ((libfontconfig = openFontConfig()) == NULL) { + return 0; + } + + FcGetVersion = (FcGetVersionFuncType)dlsym(libfontconfig, "FcGetVersion"); + + if (FcGetVersion == NULL) { + closeFontConfig(libfontconfig, JNI_FALSE); + return 0; + } + version = (*FcGetVersion)(); + closeFontConfig(libfontconfig, JNI_FALSE); + + return version; +} + JNIEXPORT void JNICALL Java_sun_font_FontManager_getFontConfig -(JNIEnv *env, jclass obj, jstring localeStr, jobjectArray fontInfoArray) { +(JNIEnv *env, jclass obj, jstring localeStr, jobject fcInfoObj, + jobjectArray fcCompFontArray, jboolean includeFallbacks) { FcNameParseFuncType FcNameParse; FcPatternAddStringFuncType FcPatternAddString; @@ -967,33 +1011,70 @@ Java_sun_font_FontManager_getFontConfig FcFontMatchFuncType FcFontMatch; FcPatternGetStringFuncType FcPatternGetString; FcPatternDestroyFuncType FcPatternDestroy; + FcPatternGetCharSetFuncType FcPatternGetCharSet; + FcFontSortFuncType FcFontSort; + FcFontSetDestroyFuncType FcFontSetDestroy; + FcCharSetUnionFuncType FcCharSetUnion; + FcCharSetSubtractCountFuncType FcCharSetSubtractCount; + FcGetVersionFuncType FcGetVersion; + FcConfigGetCacheDirsFuncType FcConfigGetCacheDirs; + FcStrListNextFuncType FcStrListNext; + FcStrListDoneFuncType FcStrListDone; int i, arrlen; - jobject fontInfoObj; + jobject fcCompFontObj; jstring fcNameStr, jstr; const char *locale, *fcName; - FcPattern *pattern, *matchPattern; + FcPattern *pattern; FcResult result; void* libfontconfig; - jfieldID fcNameID, familyNameID, fontFileID; + jfieldID fcNameID, fcFirstFontID, fcAllFontsID, fcVersionID, fcCacheDirsID; + jfieldID familyNameID, styleNameID, fullNameID, fontFileID; + jmethodID fcFontCons; + char* debugMinGlyphsStr = getenv("J2D_DEBUG_MIN_GLYPHS"); - jclass fontInfoArrayClass = - (*env)->FindClass(env, "[Lsun/font/FontManager$FontConfigInfo;"); - jclass fontInfoClass = + jclass fcInfoClass = (*env)->FindClass(env, "sun/font/FontManager$FontConfigInfo"); + jclass fcCompFontClass = + (*env)->FindClass(env, "sun/font/FontManager$FcCompFont"); + jclass fcFontClass = + (*env)->FindClass(env, "sun/font/FontManager$FontConfigFont"); - if (fontInfoArray == NULL || fontInfoClass == NULL) { + if (fcInfoObj == NULL || fcCompFontArray == NULL || fcInfoClass == NULL || + fcCompFontClass == NULL || fcFontClass == NULL) { return; } - fcNameID = (*env)->GetFieldID(env, fontInfoClass, + fcVersionID = (*env)->GetFieldID(env, fcInfoClass, "fcVersion", "I"); + + fcCacheDirsID = (*env)->GetFieldID(env, fcInfoClass, "cacheDirs", + "[Ljava/lang/String;"); + + fcNameID = (*env)->GetFieldID(env, fcCompFontClass, "fcName", "Ljava/lang/String;"); - familyNameID = (*env)->GetFieldID(env, fontInfoClass, + fcFirstFontID = + (*env)->GetFieldID(env, fcCompFontClass, "firstFont", + "Lsun/font/FontManager$FontConfigFont;"); + + fcAllFontsID = + (*env)->GetFieldID(env, fcCompFontClass, "allFonts", + "[Lsun/font/FontManager$FontConfigFont;"); + + fcFontCons = (*env)->GetMethodID(env, fcFontClass, "<init>", "()V"); + + familyNameID = (*env)->GetFieldID(env, fcFontClass, "familyName", "Ljava/lang/String;"); - fontFileID = (*env)->GetFieldID(env, fontInfoClass, + styleNameID = (*env)->GetFieldID(env, fcFontClass, + "styleStr", "Ljava/lang/String;"); + fullNameID = (*env)->GetFieldID(env, fcFontClass, + "fullName", "Ljava/lang/String;"); + fontFileID = (*env)->GetFieldID(env, fcFontClass, "fontFile", "Ljava/lang/String;"); - if (fcNameID == NULL || familyNameID == NULL || fontFileID == NULL) { + if (fcVersionID == NULL || fcCacheDirsID == NULL || fcNameID == NULL || + fcFirstFontID == NULL || fcAllFontsID == NULL || fcFontCons == NULL || + familyNameID == NULL || styleNameID == NULL || fullNameID == NULL || + fontFileID == NULL) { return; } @@ -1013,6 +1094,19 @@ Java_sun_font_FontManager_getFontConfig (FcPatternGetStringFuncType)dlsym(libfontconfig, "FcPatternGetString"); FcPatternDestroy = (FcPatternDestroyFuncType)dlsym(libfontconfig, "FcPatternDestroy"); + FcPatternGetCharSet = + (FcPatternGetCharSetFuncType)dlsym(libfontconfig, + "FcPatternGetCharSet"); + FcFontSort = + (FcFontSortFuncType)dlsym(libfontconfig, "FcFontSort"); + FcFontSetDestroy = + (FcFontSetDestroyFuncType)dlsym(libfontconfig, "FcFontSetDestroy"); + FcCharSetUnion = + (FcCharSetUnionFuncType)dlsym(libfontconfig, "FcCharSetUnion"); + FcCharSetSubtractCount = + (FcCharSetSubtractCountFuncType)dlsym(libfontconfig, + "FcCharSetSubtractCount"); + FcGetVersion = (FcGetVersionFuncType)dlsym(libfontconfig, "FcGetVersion"); if (FcNameParse == NULL || FcPatternAddString == NULL || @@ -1020,23 +1114,77 @@ Java_sun_font_FontManager_getFontConfig FcDefaultSubstitute == NULL || FcFontMatch == NULL || FcPatternGetString == NULL || - FcPatternDestroy == NULL) { /* problem with the library: return. */ + FcPatternDestroy == NULL || + FcPatternGetCharSet == NULL || + FcFontSetDestroy == NULL || + FcCharSetUnion == NULL || + FcGetVersion == NULL || + FcCharSetSubtractCount == NULL) {/* problem with the library: return.*/ closeFontConfig(libfontconfig, JNI_FALSE); return; } + (*env)->SetIntField(env, fcInfoObj, fcVersionID, (*FcGetVersion)()); + + /* Optionally get the cache dir locations. This isn't + * available until v 2.4.x, but this is OK since on those later versions + * we can check the time stamps on the cache dirs to see if we + * are out of date. There are a couple of assumptions here. First + * that the time stamp on the directory changes when the contents are + * updated. Secondly that the locations don't change. The latter is + * most likely if a new version of fontconfig is installed, but we also + * invalidate the cache if we detect that. Arguably even that is "rare", + * and most likely is tied to an OS upgrade which gets a new file anyway. + */ + FcConfigGetCacheDirs = + (FcConfigGetCacheDirsFuncType)dlsym(libfontconfig, + "FcConfigGetCacheDirs"); + FcStrListNext = + (FcStrListNextFuncType)dlsym(libfontconfig, "FcStrListNext"); + FcStrListDone = + (FcStrListDoneFuncType)dlsym(libfontconfig, "FcStrListDone"); + if (FcStrListNext != NULL && FcStrListDone != NULL && + FcConfigGetCacheDirs != NULL) { + + FcStrList* cacheDirs; + FcChar8* cacheDir; + int cnt = 0; + jobject cacheDirArray = + (*env)->GetObjectField(env, fcInfoObj, fcCacheDirsID); + int max = (*env)->GetArrayLength(env, cacheDirArray); + + cacheDirs = (*FcConfigGetCacheDirs)(NULL); + if (cacheDirs != NULL) { + while ((cnt < max) && (cacheDir = (*FcStrListNext)(cacheDirs))) { + jstr = (*env)->NewStringUTF(env, (const char*)cacheDir); + (*env)->SetObjectArrayElement(env, cacheDirArray, cnt++, jstr); + } + (*FcStrListDone)(cacheDirs); + } + } + locale = (*env)->GetStringUTFChars(env, localeStr, 0); - arrlen = (*env)->GetArrayLength(env, fontInfoArray); + arrlen = (*env)->GetArrayLength(env, fcCompFontArray); for (i=0; i<arrlen; i++) { - fontInfoObj = (*env)->GetObjectArrayElement(env, fontInfoArray, i); + FcFontSet* fontset; + int fn, j, fontCount, nfonts, minGlyphs; + FcChar8 **family, **styleStr, **fullname, **file; + jarray fcFontArr; + + fcCompFontObj = (*env)->GetObjectArrayElement(env, fcCompFontArray, i); fcNameStr = - (jstring)((*env)->GetObjectField(env, fontInfoObj, fcNameID)); + (jstring)((*env)->GetObjectField(env, fcCompFontObj, fcNameID)); fcName = (*env)->GetStringUTFChars(env, fcNameStr, 0); if (fcName == NULL) { continue; } pattern = (*FcNameParse)((FcChar8 *)fcName); + if (pattern == NULL) { + closeFontConfig(libfontconfig, JNI_FALSE); + return; + } + /* locale may not usually be necessary as fontconfig appears to apply * this anyway based on the user's environment. However we want * to use the value of the JDK startup locale so this should take @@ -1047,25 +1195,134 @@ Java_sun_font_FontManager_getFontConfig } (*FcConfigSubstitute)(NULL, pattern, FcMatchPattern); (*FcDefaultSubstitute)(pattern); - matchPattern = (*FcFontMatch)(NULL, pattern, &result); - if (matchPattern) { - FcChar8 *file, *family; + fontset = (*FcFontSort)(NULL, pattern, FcTrue, NULL, &result); + if (fontset == NULL) { + closeFontConfig(libfontconfig, JNI_FALSE); + return; + } - (*FcPatternGetString)(matchPattern, FC_FILE, 0, &file); - (*FcPatternGetString)(matchPattern, FC_FAMILY, 0, &family); + /* fontconfig returned us "nfonts". If we are just getting the + * first font, we set nfont to zero. Otherwise we use "nfonts". + * Next create separate C arrrays of length nfonts for family file etc. + * Inspect the returned fonts and the ones we like (adds enough glyphs) + * are added to the arrays and we increment 'fontCount'. + */ + if (includeFallbacks) { + nfonts = fontset->nfont; + } else { + nfonts = 1; + } + family = (FcChar8**)calloc(nfonts, sizeof(FcChar8*)); + styleStr = (FcChar8**)calloc(nfonts, sizeof(FcChar8*)); + fullname = (FcChar8**)calloc(nfonts, sizeof(FcChar8*)); + file = (FcChar8**)calloc(nfonts, sizeof(FcChar8*)); + if (family == NULL || styleStr == NULL || + fullname == NULL || file == NULL) { + closeFontConfig(libfontconfig, JNI_FALSE); + return; + } + fontCount = 0; + minGlyphs = 20; + if (debugMinGlyphsStr != NULL) { + int val = minGlyphs; + sscanf(debugMinGlyphsStr, "%5d", &val); + if (val >= 0 && val <= 65536) { + minGlyphs = val; + } + } + for (j=0; j<nfonts; j++) { + FcPattern *fontPattern = fontset->fonts[j]; + FcChar8 *fontformat; + FcCharSet *unionCharset, *charset; + + fontformat = NULL; + (*FcPatternGetString)(fontPattern, FC_FONTFORMAT, 0, &fontformat); + if (fontformat != NULL && strcmp((char*)fontformat, "TrueType") + != 0) { + continue; + } + result = (*FcPatternGetCharSet)(fontPattern, + FC_CHARSET, 0, &charset); + if (result != FcResultMatch) { + closeFontConfig(libfontconfig, JNI_FALSE); + return; + } - if (file != NULL) { - jstr = (*env)->NewStringUTF(env, (const char*)file); - ((*env)->SetObjectField(env, fontInfoObj, fontFileID, jstr)); + /* We don't want 20 or 30 fonts, so once we hit 10 fonts, + * then require that they really be adding value. Too many + * adversely affects load time for minimal value-add. + * This is still likely far more than we've had in the past. + */ + if (nfonts==10) { + minGlyphs = 50; + } + if (j == 0) { + unionCharset = charset; + } else { + if ((*FcCharSetSubtractCount)(charset, unionCharset) + > minGlyphs) { + unionCharset = (* FcCharSetUnion)(unionCharset, charset); + } else { + continue; + } } - if (family != NULL) { - jstr = (*env)->NewStringUTF(env, (const char*)family); - ((*env)->SetObjectField(env, fontInfoObj, familyNameID, jstr)); + + fontCount++; // found a font we will use. + (*FcPatternGetString)(fontPattern, FC_FILE, 0, &file[j]); + (*FcPatternGetString)(fontPattern, FC_FAMILY, 0, &family[j]); + (*FcPatternGetString)(fontPattern, FC_STYLE, 0, &styleStr[j]); + (*FcPatternGetString)(fontPattern, FC_FULLNAME, 0, &fullname[j]); + } + + /* Once we get here 'fontCount' is the number of returned fonts + * we actually want to use, so we create 'fcFontArr' of that length. + * The non-null entries of "family[]" etc are those fonts. + * Then loop again over all nfonts adding just those non-null ones + * to 'fcFontArr'. If its null (we didn't want the font) + * then we don't enter the main body. + * So we should never get more than 'fontCount' entries. + */ + if (includeFallbacks) { + fcFontArr = + (*env)->NewObjectArray(env, fontCount, fcFontClass, NULL); + (*env)->SetObjectField(env,fcCompFontObj, fcAllFontsID, fcFontArr); + } + fn=0; + + for (j=0;j<nfonts;j++) { + if (family[j] != NULL) { + jobject fcFont = + (*env)->NewObject(env, fcFontClass, fcFontCons); + jstr = (*env)->NewStringUTF(env, (const char*)family[j]); + (*env)->SetObjectField(env, fcFont, familyNameID, jstr); + if (file[j] != NULL) { + jstr = (*env)->NewStringUTF(env, (const char*)file[j]); + (*env)->SetObjectField(env, fcFont, fontFileID, jstr); + } + if (styleStr[j] != NULL) { + jstr = (*env)->NewStringUTF(env, (const char*)styleStr[j]); + (*env)->SetObjectField(env, fcFont, styleNameID, jstr); + } + if (fullname[j] != NULL) { + jstr = (*env)->NewStringUTF(env, (const char*)fullname[j]); + (*env)->SetObjectField(env, fcFont, fullNameID, jstr); + } + if (fn==0) { + (*env)->SetObjectField(env, fcCompFontObj, + fcFirstFontID, fcFont); + } + if (includeFallbacks) { + (*env)->SetObjectArrayElement(env, fcFontArr, fn++,fcFont); + } } - (*FcPatternDestroy)(matchPattern); } (*env)->ReleaseStringUTFChars (env, fcNameStr, (const char*)fcName); + (*FcFontSetDestroy)(fontset); (*FcPatternDestroy)(pattern); + free(family); + free(styleStr); + free(fullname); + free(file); } /* release resources and close the ".so" */ diff --git a/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java b/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java index c3820c22a..8828b2f08 100644 --- a/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java +++ b/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java @@ -338,7 +338,9 @@ public class Win32GraphicsEnvironment // Implements SunGraphicsEnvironment.createFontConfiguration. protected FontConfiguration createFontConfiguration() { - return new WFontConfiguration(this); + FontConfiguration fc = new WFontConfiguration(this); + fc.init(); + return fc; } public FontConfiguration createFontConfiguration(boolean preferLocaleFonts, |