
com.sun.javafx.font.FontConfigManager Maven / Gradle / Ivy
The newest version!
/* * Copyright (c) 2012, 2024, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 * 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. */ package com.sun.javafx.font; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.Properties; public class FontConfigManager { static boolean debugFonts = false; static boolean useFontConfig = true; static boolean fontConfigFailed = false; static boolean useEmbeddedFontSupport = false; static { String dbg = System.getProperty("prism.debugfonts", ""); debugFonts = "true".equals(dbg); String ufc = System.getProperty("prism.useFontConfig", "true"); useFontConfig = "true".equals(ufc); String emb = System.getProperty("prism.embeddedfonts", ""); useEmbeddedFontSupport = "true".equals(emb); } /* These next three classes are just data structures. */ public static class FontConfigFont { public String familyName; // eg Bitstream Vera Sans public String styleStr; // eg Bold public String fullName; // eg Bitstream Vera Sans Bold public String fontFile; // eg /usr/X11/lib/fonts/foo.ttf } public static class FcCompFont { public String fcName; // eg sans public String fcFamily; // eg sans //public String fxName; // eg sans serif public int style; // eg 0=PLAIN public FontConfigFont firstFont; public FontConfigFont[] allFonts; //public CompositeFont compFont; // null if not yet created/known. } /* fontconfig recognises slants roman, italic, as well as oblique, * and a slew of weights, where the ones that matter here are * regular and bold. * To fully qualify what we want, we can for example ask for (eg) * Font.PLAIN : "serif:regular:roman" * Font.BOLD : "serif:bold:roman" * Font.ITALIC : "serif:regular:italic" * Font.BOLD|Font.ITALIC : "serif:bold:italic" */ private static final String[] fontConfigNames = { "sans:regular:roman", "sans:bold:roman", "sans:regular:italic", "sans:bold:italic", "serif:regular:roman", "serif:bold:roman", "serif:regular:italic", "serif:bold:italic", "monospace:regular:roman", "monospace:bold:roman", "monospace:regular:italic", "monospace:bold:italic", }; /* This array has the array elements created in Java code and is * passed down to native to be filled in. */ private static FcCompFont[] fontConfigFonts; private FontConfigManager() { } private static String[] getFontConfigNames() { return fontConfigNames; } private static String getFCLocaleStr() { Locale l = Locale.getDefault(); String localeStr = l.getLanguage(); String country = l.getCountry(); if (!country.equals("")) { localeStr = localeStr + "-" + country; } return localeStr; } /* Return an array of FcCompFont structs describing the primary * font located for each of fontconfig/GTK/Pango's logical font names. */ private static native boolean getFontConfig(String locale, FcCompFont[] fonts, boolean includeFallbacks); private static synchronized void initFontConfigLogFonts() { if (fontConfigFonts != null || fontConfigFailed) { return; } long t0 = 0; if (debugFonts) { t0 = System.nanoTime(); } String[] fontConfigNames = FontConfigManager.getFontConfigNames(); FcCompFont[] fontArr = new FcCompFont[fontConfigNames.length]; for (int i = 0; i< fontArr.length; i++) { 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].style = i % 4; // depends on array order. } boolean foundFontConfig = false; if (useFontConfig) { foundFontConfig = getFontConfig(getFCLocaleStr(), fontArr, true); } else { if (debugFonts) { System.err.println("Not using FontConfig"); } } if (useEmbeddedFontSupport || !foundFontConfig) { EmbeddedFontSupport.initLogicalFonts(fontArr); } FontConfigFont anyFont = null; /* 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 (debugFonts) { System.err.println("Fontconfig returned no font for " + fontArr[i].fcName); } fontConfigFailed = true; } else if (anyFont == null) { anyFont = fci.firstFont; defaultFontFile = anyFont.fontFile; } } if (anyFont == null) { fontConfigFailed = true; System.err.println("Error: JavaFX detected no fonts! " + "Please refer to release notes for proper font configuration"); return; } else if (fontConfigFailed) { for (int i = 0; i< fontArr.length; i++) { if (fontArr[i].firstFont == null) { fontArr[i].firstFont = anyFont; } } } fontConfigFonts = fontArr; if (debugFonts) { long t1 = System.nanoTime(); System.err.println("Time spent accessing fontconfig=" + ((t1 - t0) / 1000000) + "ms."); for (int i = 0; i
*/ static void initLogicalFonts(FcCompFont[] fonts) { Properties props = new Properties(); try { File f = new File(fontDir,"logicalfonts.properties"); if (f.exists()) { FileInputStream fis = new FileInputStream(f); props.load(fis); fis.close(); } else if (fontDirFromJRE) { // Our fontDir is in the JRE (at least relative to our Jar) // we have no logicalfonts.properties, but we can see // if we can intuit one.... this is checked next. for(int i=0; i < jreFontsProperties.length; i += 2) { props.setProperty(jreFontsProperties[i],jreFontsProperties[i+1]); } if (debugFonts) { System.err.println("Using fallback implied logicalfonts.properties"); } } } catch (IOException ioe) { if (debugFonts) { System.err.println(ioe); return; } } for (int f=0; fgetFileNames(FcCompFont font, boolean fallBacksOnly) { ArrayList fileList = new ArrayList (); if (font.allFonts != null) { int start = (fallBacksOnly) ? 1 : 0; for (int i=start; i getFontNames(FcCompFont font, boolean fallBacksOnly) { ArrayList fontList = new ArrayList (); if (font.allFonts != null) { int start = (fallBacksOnly) ? 1 : 0; for (int i=start; i populateMaps() allFonts = new ArrayList<>(); int i=0; while (true) { String file = props.getProperty(key+i+".file"); String font = props.getProperty(key+i+".font"); i++; if (file == null) { break; } File ff = new File(fontDir, file); if (!exists(ff)) { if (debugFonts) { System.out.println("Failed to find logical font file "+ff); } continue; } FontConfigFont fcFont = new FontConfigFont(); fcFont.fontFile = ff.getPath(); // required. fcFont.fullName = font; // optional. fcFont.familyName = null; // not used. fcFont.styleStr = null; // not used. if (fonts[f].firstFont == null) { fonts[f].firstFont = fcFont; } allFonts.add(fcFont); } if (allFonts.size() > 0) { fonts[f].allFonts = new FontConfigFont[allFonts.size()]; allFonts.toArray(fonts[f].allFonts); } } } /* * To speed lookup of fonts, check for a file called * allfonts.properties. Only fonts in that file will be enumerated. * If this file isn't present we'll open all the files. * The file name must be a simple basename, and is mandatory. * But you are encouraged to name the font and family too. * If this file doesn't say the name or family of a font, * we'll still open the file. The names must be the actual * font names. No promises to fix it if you spell it wrongly. * We look for "maxFont" and if that's a valid property * we'll look from 0 .. maxFont, else we stop at the first * index for which no file exists. Eg file : * maxFont=1 * family.0=Arial * font.0=Arial Regular * file.0=arial.ttf * family.1=Times New Roman * font.1=Times New Roman Regular * file.1=times.ttf * * NOTE: if you are testing embedded on desktop, and are using * the 2D pipeline, you will want to use /home/ /.fonts as * the font directory, else Java 2D won't know where to find * the fonts. If this turns out to be a major impediment, we * can arrange to register them with Java 2D. */ static void populateMaps (HashMap fontToFileMap, HashMap fontToFamilyNameMap, HashMap > familyToFontListMap, Locale locale) { final Properties props = new Properties(); try { String lFile = fontDir+"/allfonts.properties"; FileInputStream fis = new FileInputStream(lFile); props.load(fis); fis.close(); } catch (IOException ioe) { props.clear(); if (debugFonts) { System.err.println(ioe); System.err.println("Fall back to opening the files"); } } if (!props.isEmpty()) { int maxFont = Integer.MAX_VALUE; try { maxFont = Integer.parseInt(props.getProperty("maxFont","")); } catch (NumberFormatException e) { } if (maxFont <= 0) { maxFont = Integer.MAX_VALUE; } for (int f=0; f familyArr = familyToFontListMap.get(familyLC); if (familyArr == null) { familyArr = new ArrayList<>(4); familyToFontListMap.put(familyLC, familyArr); } familyArr.add(font); } } } } }
© 2015 - 2025 Weber Informatics LLC | Privacy Policy