/* * Copyright (c) 2011, 2026, 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.*; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Locale; import java.util.Map; import java.util.TreeMap; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import javax.swing.plaf.FontUIResource; import sun.awt.FontConfiguration; import sun.awt.HeadlessToolkit; import sun.awt.util.ThreadGroupUtils; import sun.lwawt.macosx.*; public final class CFontManager extends SunFontManager { private static Hashtable genericFonts = new Hashtable(); private final Map fallbackFonts = new ConcurrentHashMap<>(); @Override protected FontConfiguration createFontConfiguration() { FontConfiguration fc = new CFontConfiguration(this); fc.init(); return fc; } @Override public FontConfiguration createFontConfiguration(boolean preferLocaleFonts, boolean preferPropFonts) { return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts); } /* * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. */ @Override protected String[] getDefaultPlatformFont() { return new String[]{"Lucida Grande", "/System/Library/Fonts/LucidaGrande.ttc"}; } // This is a way to register any kind of Font2D, not just files and composites. public static Font2D[] getGenericFonts() { return genericFonts.values().toArray(new Font2D[0]); } public Font2D registerGenericFont(Font2D f) { return registerGenericFont(f, false); } public Font2D registerGenericFont(Font2D f, boolean logicalFont) { int rank = 4; String fontName = f.fullName; String familyName = f.familyName; if (fontName == null || fontName.isEmpty()) { return null; } // logical fonts always need to be added to the family // plus they never need to be added to the generic font list // or the fullNameToFont table since they are covers for // already existing fonts in this list if (logicalFont || !genericFonts.containsKey(fontName)) { if (FontUtilities.debugFonts()) { FontUtilities.logInfo("Add to Family " + familyName + ", Font " + fontName + " rank=" + rank); } FontFamily family = FontFamily.getFamily(familyName); if (family == null) { family = new FontFamily(familyName, false, rank); family.setFont(f, f.style); } else if (family.getRank() >= rank) { family.setFont(f, f.style); } if (!logicalFont) { genericFonts.put(fontName, f); fullNameToFont.put(fontName.toLowerCase(Locale.ENGLISH), f); } return f; } else { return genericFonts.get(fontName); } } @Override public Font2D[] getRegisteredFonts() { Font2D[] regFonts = super.getRegisteredFonts(); // Add in the Mac OS X native fonts Font2D[] genericFonts = getGenericFonts(); Font2D[] allFonts = new Font2D[regFonts.length+genericFonts.length]; System.arraycopy(regFonts, 0, allFonts, 0, regFonts.length); System.arraycopy(genericFonts, 0, allFonts, regFonts.length, genericFonts.length); return allFonts; } @Override protected void addNativeFontFamilyNames(TreeMap familyNames, Locale requestedLocale) { Font2D[] genericfonts = getGenericFonts(); for (int i=0; i < genericfonts.length; i++) { if (!(genericfonts[i] instanceof NativeFont)) { String name = genericfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } @Override protected void registerFontsInDir(final String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) { String[] files = new File(dirName).list(getTrueTypeFilter()); if (files == null) { return; } else { for (String f : files) { loadNativeDirFonts(dirName+File.separator+f); } } super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks); } private native void loadNativeDirFonts(String fontPath); private native void loadNativeFonts(); void registerFont(String fontName, String fontFamilyName) { final CFont font = new CFont(fontName, fontFamilyName); registerGenericFont(font); } void registerItalicDerived() { FontFamily[] famArr = FontFamily.getAllFontFamilies(); for (int i=0; i fontToFileMap, HashMap fontToFamilyNameMap, HashMap> familyToFontListMap, Locale locale) {} Font2D getOrCreateFallbackFont(String fontName) { Font2D font2D = findFont2D(fontName, Font.PLAIN, FontManager.NO_FALLBACK); if (font2D != null || fontName.startsWith(".")) { return font2D; } else { // macOS doesn't list some system fonts in [NSFontManager availableFontFamilies] output, // so they are not registered in font manager as part of 'loadNativeFonts'. // These fonts are present in [NSFontManager availableFonts] output though, // and can be accessed in the same way as other system fonts. return fallbackFonts.computeIfAbsent(fontName, name -> new CFont(name, null)); } } }