aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/sun/font/FontManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/classes/sun/font/FontManager.java')
-rw-r--r--src/share/classes/sun/font/FontManager.java157
1 files changed, 112 insertions, 45 deletions
diff --git a/src/share/classes/sun/font/FontManager.java b/src/share/classes/sun/font/FontManager.java
index d3e770f14..d217be16d 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]);