3912 lines · 165.2 KB · Java
RawDownload
/* * Copyright (c) 2008, 2011, 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 sun.font; import java.awt.Font;import java.awt.FontFormatException;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FilenameFilter;import java.io.IOException;import java.io.InputStreamReader;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;import java.util.Locale;import java.util.Map;import java.util.NoSuchElementException;import java.util.StringTokenizer;import java.util.TreeMap;import java.util.Vector;import java.util.concurrent.ConcurrentHashMap; import javax.swing.plaf.FontUIResource;import sun.awt.AppContext;import sun.awt.FontConfiguration;import sun.awt.SunToolkit;import sun.java2d.FontSupport;import sun.util.logging.PlatformLogger; /** * The base implementation of the {@link FontManager} interface. It implements * the platform independent, shared parts of OpenJDK's FontManager * implementations. The platform specific parts are declared as abstract * methods that have to be implemented by specific implementations. */public abstract class SunFontManager implements FontSupport, FontManagerForSGE {     private static class TTFilter implements FilenameFilter {        public boolean accept(File dir,String name) {            /* all conveniently have the same suffix length */            int offset = name.length()-4;            if (offset <= 0) { /* must be at least A.ttf */                return false;            } else {                return(name.startsWith(".ttf", offset) ||                       name.startsWith(".TTF", offset) ||                       name.startsWith(".ttc", offset) ||                       name.startsWith(".TTC", offset) ||                       name.startsWith(".otf", offset) ||                       name.startsWith(".OTF", offset));            }        }    }     private static class T1Filter implements FilenameFilter {        public boolean accept(File dir,String name) {            if (noType1Font) {                return false;            }            /* all conveniently have the same suffix length */            int offset = name.length()-4;            if (offset <= 0) { /* must be at least A.pfa */                return false;            } else {                return(name.startsWith(".pfa", offset) ||                       name.startsWith(".pfb", offset) ||                       name.startsWith(".PFA", offset) ||                       name.startsWith(".PFB", offset));            }        }    }      private static class TTorT1Filter implements FilenameFilter {        public boolean accept(File dir, String name) {             /* all conveniently have the same suffix length */            int offset = name.length()-4;            if (offset <= 0) { /* must be at least A.ttf or A.pfa */                return false;            } else {                boolean isTT =                    name.startsWith(".ttf", offset) ||                    name.startsWith(".TTF", offset) ||                    name.startsWith(".ttc", offset) ||                    name.startsWith(".TTC", offset) ||                    name.startsWith(".otf", offset) ||                    name.startsWith(".OTF", offset);                if (isTT) {                    return true;                } else if (noType1Font) {                    return false;                } else {                    return(name.startsWith(".pfa", offset) ||                           name.startsWith(".pfb", offset) ||                           name.startsWith(".PFA", offset) ||                           name.startsWith(".PFB", offset));                }            }        }    }      public static final int FONTFORMAT_NONE = -1;     public static final int FONTFORMAT_TRUETYPE = 0;     public static final int FONTFORMAT_TYPE1 = 1;     public static final int FONTFORMAT_T2K = 2;     public static final int FONTFORMAT_TTC = 3;     public static final int FONTFORMAT_COMPOSITE = 4;     public static final int FONTFORMAT_NATIVE = 5;      /* Pool of 20 font file channels chosen because some UTF-8 locale      * composite fonts can use up to 16 platform fonts (including the      * Lucida fall back). This should prevent channel thrashing when      * dealing with one of these fonts.      * The pool array stores the fonts, rather than directly referencing      * the channels, as the font needs to do the open/close work.      */     private static final int CHANNELPOOLSIZE = 20;     private int lastPoolIndex = 0;     private FileFont fontFileCache[] = new FileFont[CHANNELPOOLSIZE];     /* Need to implement a simple linked list scheme for fast     * traversal and lookup.     * Also want to "fast path" dialog so there's minimal overhead.     */    /* There are at exactly 20 composite fonts: 5 faces (but some are not     * usually different), in 4 styles. The array may be auto-expanded     * later if more are needed, eg for user-defined composites or locale     * variants.     */    private int maxCompFont = 0;    private CompositeFont [] compFonts = new CompositeFont[20];    private ConcurrentHashMap<String, CompositeFont>        compositeFonts = new ConcurrentHashMap<String, CompositeFont>();    private ConcurrentHashMap<String, PhysicalFont>        physicalFonts = new ConcurrentHashMap<String, PhysicalFont>();    private ConcurrentHashMap<String, PhysicalFont>        registeredFonts = new ConcurrentHashMap<String, PhysicalFont>();     /* given a full name find the Font. Remind: there's duplication     * here in that this contains the content of compositeFonts +     * physicalFonts.     */    private ConcurrentHashMap<String, Font2D>        fullNameToFont = new ConcurrentHashMap<String, Font2D>();     /* TrueType fonts have localised names. Support searching all     * of these before giving up on a name.     */    private HashMap<String, TrueTypeFont> localeFullNamesToFont;     private PhysicalFont defaultPhysicalFont;     static boolean longAddresses;    private boolean loaded1dot0Fonts = false;    boolean loadedAllFonts = false;    boolean loadedAllFontFiles = false;    HashMap<String,String> jreFontMap;    HashSet<String> jreLucidaFontFiles;    String[] jreOtherFontFiles;    boolean noOtherJREFontFiles = false; // initial assumption.     public static final String lucidaFontName = "Lucida Sans Regular";    public static String jreLibDirName;    public static String jreFontDirName;    private static HashSet<String> missingFontFiles = null;    private String defaultFontName;    private String defaultFontFileName;    protected HashSet registeredFontFiles = new HashSet();     private ArrayList badFonts;    /* fontPath is the location of all fonts on the system, excluding the     * JRE's own font directory but including any path specified using the     * sun.java2d.fontpath property. Together with that property,  it is     * initialised by the getPlatformFontPath() method     * This call must be followed by a call to registerFontDirs(fontPath)     * once any extra debugging path has been appended.     */    protected String fontPath;    private FontConfiguration fontConfig;    /* discoveredAllFonts is set to true when all fonts on the font path are     * discovered. This usually also implies opening, validating and     * registering, but an implementation may be optimized to avold this.     * So see also "loadedAllFontFiles"     */    private boolean discoveredAllFonts = false;     /* No need to keep consing up new instances - reuse a singleton.     * The trade-off is that these objects don't get GC'd.     */    private static final FilenameFilter ttFilter = new TTFilter();    private static final FilenameFilter t1Filter = new T1Filter();     private Font[] allFonts;    private String[] allFamilies; // cache for default locale only    private Locale lastDefaultLocale;     public static boolean noType1Font;     /* Used to indicate required return type from toArray(..); */    private static String[] STR_ARRAY = new String[0];     /**     * Deprecated, unsupported hack - actually invokes a bug!     * Left in for a customer, don't remove.     */    private boolean usePlatformFontMetrics = false;     /**     * Returns the global SunFontManager instance. This is similar to     * {@link FontManagerFactory#getInstance()} but it returns a     * SunFontManager instance instead. This is only used in internal classes     * where we can safely assume that a SunFontManager is to be used.     *     * @return the global SunFontManager instance     */    public static SunFontManager getInstance() {        FontManager fm = FontManagerFactory.getInstance();        return (SunFontManager) fm;    }     public FilenameFilter getTrueTypeFilter() {        return ttFilter;    }     public FilenameFilter getType1Filter() {        return t1Filter;    }     @Override    public boolean usingPerAppContextComposites() {        return _usingPerAppContextComposites;    }     private void initJREFontMap() {         /* Key is familyname+style value as an int.         * Value is filename containing the font.         * If no mapping exists, it means there is no font file for the style         * If the mapping exists but the file doesn't exist in the deferred         * list then it means its not installed.         * This looks like a lot of code and strings but if it saves even         * a single file being opened at JRE start-up there's a big payoff.         * Lucida Sans is probably the only important case as the others         * are rarely used. Consider removing the other mappings if there's         * no evidence they are useful in practice.         */        jreFontMap = new HashMap<String,String>();        jreLucidaFontFiles = new HashSet<String>();        if (isOpenJDK()) {            return;        }        /* Lucida Sans Family */        jreFontMap.put("lucida sans0",   "LucidaSansRegular.ttf");        jreFontMap.put("lucida sans1",   "LucidaSansDemiBold.ttf");        /* Lucida Sans full names (map Bold and DemiBold to same file) */        jreFontMap.put("lucida sans regular0", "LucidaSansRegular.ttf");        jreFontMap.put("lucida sans regular1", "LucidaSansDemiBold.ttf");        jreFontMap.put("lucida sans bold1", "LucidaSansDemiBold.ttf");        jreFontMap.put("lucida sans demibold1", "LucidaSansDemiBold.ttf");         /* Lucida Sans Typewriter Family */        jreFontMap.put("lucida sans typewriter0",                       "LucidaTypewriterRegular.ttf");        jreFontMap.put("lucida sans typewriter1", "LucidaTypewriterBold.ttf");        /* Typewriter full names (map Bold and DemiBold to same file) */        jreFontMap.put("lucida sans typewriter regular0",                       "LucidaTypewriter.ttf");        jreFontMap.put("lucida sans typewriter regular1",                       "LucidaTypewriterBold.ttf");        jreFontMap.put("lucida sans typewriter bold1",                       "LucidaTypewriterBold.ttf");        jreFontMap.put("lucida sans typewriter demibold1",                       "LucidaTypewriterBold.ttf");         /* Lucida Bright Family */        jreFontMap.put("lucida bright0", "LucidaBrightRegular.ttf");        jreFontMap.put("lucida bright1", "LucidaBrightDemiBold.ttf");        jreFontMap.put("lucida bright2", "LucidaBrightItalic.ttf");        jreFontMap.put("lucida bright3", "LucidaBrightDemiItalic.ttf");        /* Lucida Bright full names (map Bold and DemiBold to same file) */        jreFontMap.put("lucida bright regular0", "LucidaBrightRegular.ttf");        jreFontMap.put("lucida bright regular1", "LucidaBrightDemiBold.ttf");        jreFontMap.put("lucida bright regular2", "LucidaBrightItalic.ttf");        jreFontMap.put("lucida bright regular3", "LucidaBrightDemiItalic.ttf");        jreFontMap.put("lucida bright bold1", "LucidaBrightDemiBold.ttf");        jreFontMap.put("lucida bright bold3", "LucidaBrightDemiItalic.ttf");        jreFontMap.put("lucida bright demibold1", "LucidaBrightDemiBold.ttf");        jreFontMap.put("lucida bright demibold3","LucidaBrightDemiItalic.ttf");        jreFontMap.put("lucida bright italic2", "LucidaBrightItalic.ttf");        jreFontMap.put("lucida bright italic3", "LucidaBrightDemiItalic.ttf");        jreFontMap.put("lucida bright bold italic3",                       "LucidaBrightDemiItalic.ttf");        jreFontMap.put("lucida bright demibold italic3",                       "LucidaBrightDemiItalic.ttf");        for (String ffile : jreFontMap.values()) {            jreLucidaFontFiles.add(ffile);        }    }     static {         java.security.AccessController.doPrivileged(                                    new java.security.PrivilegedAction() {            public Object run() {               FontManagerNativeLibrary.load();                // JNI throws an exception if a class/method/field is not found,               // so there's no need to do anything explicit here.               initIDs();                switch (StrikeCache.nativeAddressSize) {               case 8: longAddresses = true; break;               case 4: longAddresses = false; break;               default: throw new RuntimeException("Unexpected address size");               }                noType1Font =                   "true".equals(System.getProperty("sun.java2d.noType1Font"));               jreLibDirName =                   System.getProperty("java.home","") + File.separator + "lib";               jreFontDirName = jreLibDirName + File.separator + "fonts";               File lucidaFile =                   new File(jreFontDirName + File.separator + FontUtilities.LUCIDA_FILE_NAME);                return null;           }        });    }     public TrueTypeFont getEUDCFont() {        // Overridden in Windows.        return null;    }     /* Initialise ptrs used by JNI methods */    private static native void initIDs();     @SuppressWarnings("unchecked")    protected SunFontManager() {         initJREFontMap();        java.security.AccessController.doPrivileged(                new java.security.PrivilegedAction() {                    public Object run() {                        File badFontFile =                            new File(jreFontDirName + File.separator +                                     "badfonts.txt");                        if (badFontFile.exists()) {                            FileInputStream fis = null;                            try {                                badFonts = new ArrayList();                                fis = new FileInputStream(badFontFile);                                InputStreamReader isr = new InputStreamReader(fis);                                BufferedReader br = new BufferedReader(isr);                                while (true) {                                    String name = br.readLine();                                    if (name == null) {                                        break;                                    } else {                                        if (FontUtilities.debugFonts()) {                                            FontUtilities.getLogger().warning("read bad font: " +                                                           name);                                        }                                        badFonts.add(name);                                    }                                }                            } catch (IOException e) {                                try {                                    if (fis != null) {                                        fis.close();                                    }                                } catch (IOException ioe) {                                }                            }                        }                         /* Here we get the fonts in jre/lib/fonts and register                         * them so they are always available and preferred over                         * other fonts. This needs to be registered before the                         * composite fonts as otherwise some native font that                         * corresponds may be found as we don't have a way to                         * handle two fonts of the same name, so the JRE one                         * must be the first one registered. Pass "true" to                         * registerFonts method as on-screen these JRE fonts                         * always go through the T2K rasteriser.                         */                        if (FontUtilities.isLinux) {                            /* Linux font configuration uses these fonts */                            registerFontDir(jreFontDirName);                        }                        registerFontsInDir(jreFontDirName, true, Font2D.JRE_RANK,                                           true, false);                         /* Create the font configuration and get any font path                         * that might be specified.                         */                        fontConfig = createFontConfiguration();                        if (isOpenJDK()) {                            String[] fontInfo = getDefaultPlatformFont();                            defaultFontName = fontInfo[0];                            defaultFontFileName = fontInfo[1];                        }                         String extraFontPath = fontConfig.getExtraFontPath();                         /* In prior releases the debugging font path replaced                         * all normally located font directories except for the                         * JRE fonts dir. This directory is still always located                         * and placed at the head of the path but as an                         * augmentation to the previous behaviour the                         * changes below allow you to additionally append to                         * the font path by starting with append: or prepend by                         * starting with a prepend: sign. Eg: to append                         * -Dsun.java2d.fontpath=append:/usr/local/myfonts                         * and to prepend                         * -Dsun.java2d.fontpath=prepend:/usr/local/myfonts Disp                         *                         * If there is an appendedfontpath it in the font                         * configuration it is used instead of searching the                         * system for dirs.                         * The behaviour of append and prepend is then similar                         * to the normal case. ie it goes after what                         * you prepend and * before what you append. If the                         * sun.java2d.fontpath property is used, but it                         * neither the append or prepend syntaxes is used then                         * as except for the JRE dir the path is replaced and it                         * is up to you to make sure that all the right                         * directories are located. This is platform and                         * locale-specific so its almost impossible to get                         * right, so it should be used with caution.                         */                        boolean prependToPath = false;                        boolean appendToPath = false;                        String dbgFontPath =                            System.getProperty("sun.java2d.fontpath");                         if (dbgFontPath != null) {                            if (dbgFontPath.startsWith("prepend:")) {                                prependToPath = true;                                dbgFontPath =                                    dbgFontPath.substring("prepend:".length());                            } else if (dbgFontPath.startsWith("append:")) {                                appendToPath = true;                                dbgFontPath =                                    dbgFontPath.substring("append:".length());                            }                        }                         if (FontUtilities.debugFonts()) {                            PlatformLogger logger = FontUtilities.getLogger();                            logger.info("JRE font directory: " + jreFontDirName);                            logger.info("Extra font path: " + extraFontPath);                            logger.info("Debug font path: " + dbgFontPath);                        }                         if (dbgFontPath != null) {                            /* In debugging mode we register all the paths                             * Caution: this is a very expensive call on Solaris:-                             */                            fontPath = getPlatformFontPath(noType1Font);                             if (extraFontPath != null) {                                fontPath =                                    extraFontPath + File.pathSeparator + fontPath;                            }                            if (appendToPath) {                                fontPath =                                    fontPath + File.pathSeparator + dbgFontPath;                            } else if (prependToPath) {                                fontPath =                                    dbgFontPath + File.pathSeparator + fontPath;

Lines 1–500 of 3912.