4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage sun.font;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.io.File;
4632N/Aimport java.util.ArrayList;
4632N/Aimport java.util.HashMap;
4632N/Aimport java.util.Hashtable;
4632N/Aimport java.util.Locale;
4632N/Aimport java.util.TreeMap;
4632N/Aimport java.util.Vector;
4632N/A
4632N/Aimport javax.swing.plaf.FontUIResource;
4632N/A
4632N/Aimport sun.awt.FontConfiguration;
5331N/Aimport sun.awt.HeadlessToolkit;
4632N/Aimport sun.lwawt.macosx.*;
4632N/A
4632N/Apublic class CFontManager extends SunFontManager {
4632N/A private FontConfigManager fcManager = null;
4632N/A private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
4632N/A
4632N/A @Override
4632N/A protected FontConfiguration createFontConfiguration() {
4632N/A FontConfiguration fc = new CFontConfiguration(this);
4632N/A fc.init();
4632N/A return fc;
4632N/A }
4632N/A
4632N/A @Override
4632N/A public FontConfiguration createFontConfiguration(boolean preferLocaleFonts,
4632N/A boolean preferPropFonts)
4632N/A {
4632N/A return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts);
4632N/A }
4632N/A
4632N/A private static String[] defaultPlatformFont = null;
4632N/A
4632N/A /*
4632N/A * Returns an array of two strings. The first element is the
4632N/A * name of the font. The second element is the file name.
4632N/A */
4632N/A @Override
4632N/A public synchronized String[] getDefaultPlatformFont() {
4632N/A if (defaultPlatformFont == null) {
4632N/A defaultPlatformFont = new String[2];
4632N/A defaultPlatformFont[0] = "Lucida Grande";
4632N/A defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc";
4632N/A }
4632N/A return defaultPlatformFont;
4632N/A }
4632N/A
4632N/A // This is a way to register any kind of Font2D, not just files and composites.
4632N/A public static Font2D[] getGenericFonts() {
4632N/A return (Font2D[])genericFonts.values().toArray(new Font2D[0]);
4632N/A }
4632N/A
4632N/A public Font2D registerGenericFont(Font2D f)
4632N/A {
4632N/A return registerGenericFont(f, false);
4632N/A }
4632N/A public Font2D registerGenericFont(Font2D f, boolean logicalFont)
4632N/A {
4632N/A int rank = 4;
4632N/A
4632N/A String fontName = f.fullName;
4632N/A String familyName = f.familyName;
4632N/A
4632N/A if (fontName == null || "".equals(fontName)) {
4632N/A return null;
4632N/A }
4632N/A
4632N/A // logical fonts always need to be added to the family
4632N/A // plus they never need to be added to the generic font list
4632N/A // or the fullNameToFont table since they are covers for
4632N/A // already existing fonts in this list
4632N/A if (logicalFont || !genericFonts.containsKey(fontName)) {
4632N/A if (FontUtilities.debugFonts()) {
4632N/A FontUtilities.getLogger().info("Add to Family "+familyName +
4632N/A ", Font " + fontName + " rank="+rank);
4632N/A }
4632N/A FontFamily family = FontFamily.getFamily(familyName);
4632N/A if (family == null) {
4632N/A family = new FontFamily(familyName, false, rank);
4632N/A family.setFont(f, f.style);
4632N/A } else if (family.getRank() >= rank) {
4632N/A family.setFont(f, f.style);
4632N/A }
4632N/A if (!logicalFont)
4632N/A {
4632N/A genericFonts.put(fontName, f);
4632N/A fullNameToFont.put(fontName.toLowerCase(Locale.ENGLISH), f);
4632N/A }
4632N/A return f;
4632N/A } else {
4632N/A return (Font2D)genericFonts.get(fontName);
4632N/A }
4632N/A }
4632N/A
4632N/A @Override
4632N/A public Font2D[] getRegisteredFonts() {
4632N/A Font2D[] regFonts = super.getRegisteredFonts();
4632N/A
4632N/A // Add in the Mac OS X native fonts
4632N/A Font2D[] genericFonts = getGenericFonts();
4632N/A Font2D[] allFonts = new Font2D[regFonts.length+genericFonts.length];
4632N/A System.arraycopy(regFonts, 0, allFonts, 0, regFonts.length);
4632N/A System.arraycopy(genericFonts, 0, allFonts, regFonts.length, genericFonts.length);
4632N/A
4632N/A return allFonts;
4632N/A }
4632N/A
4632N/A @Override
4632N/A protected void addNativeFontFamilyNames(TreeMap<String, String> familyNames, Locale requestedLocale) {
4632N/A Font2D[] genericfonts = getGenericFonts();
4632N/A for (int i=0; i < genericfonts.length; i++) {
4632N/A if (!(genericfonts[i] instanceof NativeFont)) {
4632N/A String name = genericfonts[i].getFamilyName(requestedLocale);
4632N/A familyNames.put(name.toLowerCase(requestedLocale), name);
4632N/A }
4632N/A }
4632N/A }
4632N/A
4632N/A @Override
4632N/A public Font2D createFont2D(File fontFile, int fontFormat, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException {
4632N/A
4632N/A String fontFilePath = fontFile.getPath();
4632N/A Font2D font2D = null;
4632N/A final File fFile = fontFile;
4632N/A final CreatedFontTracker _tracker = tracker;
4632N/A try {
4632N/A switch (fontFormat) {
4632N/A case Font.TRUETYPE_FONT:
4632N/A font2D = new TrueTypeFont(fontFilePath, null, 0, true);
4632N/A break;
4632N/A case Font.TYPE1_FONT:
4632N/A font2D = new Type1Font(fontFilePath, null, isCopy);
4632N/A break;
4632N/A default:
4632N/A throw new FontFormatException("Unrecognised Font Format");
4632N/A }
4632N/A } catch (FontFormatException e) {
4632N/A if (isCopy) {
4632N/A java.security.AccessController.doPrivileged(
4632N/A new java.security.PrivilegedAction<Object>() {
4632N/A public Object run() {
4632N/A if (_tracker != null) {
4632N/A _tracker.subBytes((int)fFile.length());
4632N/A }
4632N/A fFile.delete();
4632N/A return null;
4632N/A }
4632N/A });
4632N/A }
4632N/A throw(e);
4632N/A }
4632N/A if (isCopy) {
4632N/A FileFont.setFileToRemove(font2D, fontFile, tracker);
4632N/A synchronized (FontManager.class) {
4632N/A
4632N/A if (tmpFontFiles == null) {
4632N/A tmpFontFiles = new Vector<File>();
4632N/A }
4632N/A tmpFontFiles.add(fontFile);
4632N/A
4632N/A if (fileCloser == null) {
4632N/A final Runnable fileCloserRunnable = new Runnable() {
4632N/A public void run() {
4632N/A java.security.AccessController.doPrivileged(
4632N/A new java.security.PrivilegedAction<Object>() {
4632N/A public Object run() {
4632N/A
4632N/A for (int i=0;i<CHANNELPOOLSIZE;i++) {
4632N/A if (fontFileCache[i] != null) {
4632N/A try {
4632N/A fontFileCache[i].close();
4632N/A } catch (Exception e) {}
4632N/A }
4632N/A }
4632N/A if (tmpFontFiles != null) {
4632N/A File[] files = new File[tmpFontFiles.size()];
4632N/A files = tmpFontFiles.toArray(files);
4632N/A for (int f=0; f<files.length;f++) {
4632N/A try {
4632N/A files[f].delete();
4632N/A } catch (Exception e) {}
4632N/A }
4632N/A }
4632N/A return null;
4632N/A }
4632N/A });
4632N/A }
4632N/A };
4632N/A java.security.AccessController.doPrivileged(
4632N/A new java.security.PrivilegedAction<Object>() {
4632N/A public Object run() {
4632N/A /* The thread must be a member of a thread group
4632N/A * which will not get GCed before VM exit.
4632N/A * Make its parent the top-level thread group.
4632N/A */
4632N/A ThreadGroup tg =
4632N/A Thread.currentThread().getThreadGroup();
4632N/A for (ThreadGroup tgn = tg;
4632N/A tgn != null;
4632N/A tg = tgn, tgn = tg.getParent());
4632N/A fileCloser = new Thread(tg, fileCloserRunnable);
4632N/A fileCloser.setContextClassLoader(null);
4632N/A Runtime.getRuntime().addShutdownHook(fileCloser);
4632N/A return null;
4632N/A }
4632N/A });
4632N/A }
4632N/A }
4632N/A }
4632N/A return font2D;
4632N/A }
4632N/A
4632N/A /*
4632N/A public synchronized FontConfigManager getFontConfigManager() {
4632N/A if (fcManager == null) {
4632N/A fcManager = new FontConfigManager();
4632N/A }
4632N/A return fcManager;
4632N/A }
4632N/A */
4632N/A
4632N/A protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
4632N/A loadNativeDirFonts(dirName);
4632N/A super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);
4632N/A }
4632N/A
4632N/A private native void loadNativeDirFonts(String dirName);
4632N/A private native void loadNativeFonts();
4632N/A
4632N/A void registerFont(String fontName, String fontFamilyName) {
4632N/A final CFont font = new CFont(fontName, fontFamilyName);
4632N/A
4632N/A registerGenericFont(font);
4632N/A
4632N/A if ((font.getStyle() & Font.ITALIC) == 0) {
4632N/A registerGenericFont(font.createItalicVariant(), true);
4632N/A }
4632N/A }
4632N/A
4632N/A Object waitForFontsToBeLoaded = new Object();
4632N/A public void loadFonts()
4632N/A {
4632N/A synchronized(waitForFontsToBeLoaded)
4632N/A {
4632N/A super.loadFonts();
4632N/A java.security.AccessController.doPrivileged(
4632N/A new java.security.PrivilegedAction<Object>() {
4632N/A public Object run() {
4632N/A loadNativeFonts();
4632N/A return null;
4632N/A }
4632N/A }
4632N/A );
4632N/A
4632N/A String defaultFont = "Lucida Grande";
4632N/A String defaultFallback = "Lucida Sans";
4632N/A
4632N/A setupLogicalFonts("Dialog", defaultFont, defaultFallback);
4632N/A setupLogicalFonts("Serif", "Times", "Lucida Bright");
4632N/A setupLogicalFonts("SansSerif", defaultFont, defaultFallback);
4632N/A setupLogicalFonts("Monospaced", "Menlo", "Lucida Sans Typewriter");
4632N/A setupLogicalFonts("DialogInput", defaultFont, defaultFallback);
4632N/A }
4632N/A }
4632N/A
4632N/A protected void setupLogicalFonts(String logicalName, String realName, String fallbackName) {
4632N/A FontFamily realFamily = getFontFamilyWithExtraTry(logicalName, realName, fallbackName);
4632N/A
4632N/A cloneStyledFont(realFamily, logicalName, Font.PLAIN);
4632N/A cloneStyledFont(realFamily, logicalName, Font.BOLD);
4632N/A cloneStyledFont(realFamily, logicalName, Font.ITALIC);
4632N/A cloneStyledFont(realFamily, logicalName, Font.BOLD | Font.ITALIC);
4632N/A }
4632N/A
4632N/A protected FontFamily getFontFamilyWithExtraTry(String logicalName, String realName, String fallbackName){
4632N/A FontFamily family = getFontFamily(realName, fallbackName);
4632N/A if (family != null) return family;
4632N/A
4632N/A // at this point, we recognize that we probably needed a fallback font
4632N/A super.loadFonts();
4632N/A
4632N/A family = getFontFamily(realName, fallbackName);
4632N/A if (family != null) return family;
4632N/A
4632N/A System.err.println("Warning: the fonts \"" + realName + "\" and \"" + fallbackName + "\" are not available for the Java logical font \"" + logicalName + "\", which may have unexpected appearance or behavior. Re-enable the \""+ realName +"\" font to remove this warning.");
4632N/A return null;
4632N/A }
4632N/A
4632N/A protected FontFamily getFontFamily(String realName, String fallbackName){
4632N/A FontFamily family = FontFamily.getFamily(realName);
4632N/A if (family != null) return family;
4632N/A
4632N/A family = FontFamily.getFamily(fallbackName);
4632N/A if (family != null){
4632N/A System.err.println("Warning: the font \"" + realName + "\" is not available, so \"" + fallbackName + "\" has been substituted, but may have unexpected appearance or behavor. Re-enable the \""+ realName +"\" font to remove this warning.");
4632N/A return family;
4632N/A }
4632N/A
4632N/A return null;
4632N/A }
4632N/A
4632N/A protected boolean cloneStyledFont(FontFamily realFamily, String logicalFamilyName, int style) {
4632N/A if (realFamily == null) return false;
4632N/A
4632N/A Font2D realFont = realFamily.getFontWithExactStyleMatch(style);
4632N/A if (realFont == null || !(realFont instanceof CFont)) return false;
4632N/A
4632N/A CFont newFont = new CFont((CFont)realFont, logicalFamilyName);
4632N/A registerGenericFont(newFont, true);
4632N/A
4632N/A return true;
4632N/A }
4632N/A
4632N/A @Override
4632N/A public String getFontPath(boolean noType1Fonts) {
4632N/A // In the case of the Cocoa toolkit, since we go through NSFont, we dont need to register /Library/Fonts
5331N/A Toolkit tk = Toolkit.getDefaultToolkit();
5331N/A if (tk instanceof HeadlessToolkit) {
5331N/A tk = ((HeadlessToolkit)tk).getUnderlyingToolkit();
5331N/A }
5331N/A if (tk instanceof LWCToolkit) {
4632N/A return "";
4632N/A }
5331N/A
4632N/A // X11 case
4632N/A return "/Library/Fonts";
4632N/A }
4632N/A
4632N/A @Override
4632N/A protected FontUIResource getFontConfigFUIR(
4632N/A String family, int style, int size)
4632N/A {
4632N/A String mappedName = FontUtilities.mapFcName(family);
4632N/A if (mappedName == null) {
4632N/A mappedName = "sansserif";
4632N/A }
4632N/A return new FontUIResource(mappedName, style, size);
4632N/A }
4632N/A
4632N/A // Only implemented on Windows
4632N/A @Override
4632N/A protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
4632N/A HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
4632N/A}