1 /*
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
666 componentFileNames,
667 componentNames,
668 numMetricsSlots,
669 exclusionRanges,
670 exclusionMaxIndex, defer,
671 SunFontManager.getInstance());
672
673 /* if the cache has an existing composite for this case, make
674 * its handle point to this new font.
675 * This ensures that when the altNameCache that is passed in
676 * is the global mapNameCache - ie we are running as an application -
677 * that any statically created java.awt.Font instances which already
678 * have a Font2D instance will have that re-directed to the new Font
679 * on subsequent uses. This is particularly important for "the"
680 * default font instance, or similar cases where a UI toolkit (eg
681 * Swing) has cached a java.awt.Font. Note that if Swing is using
682 * a custom composite APIs which update the standard composites have
683 * no effect - this is typically the case only when using the Windows
684 * L&F where these APIs would conflict with that L&F anyway.
685 */
686 Font2D oldFont = (Font2D)
687 altNameCache.get(compositeName.toLowerCase(Locale.ENGLISH));
688 if (oldFont instanceof CompositeFont) {
689 oldFont.handle.font2D = cf;
690 }
691 altNameCache.put(compositeName.toLowerCase(Locale.ENGLISH), cf);
692 }
693
694 private void addCompositeToFontList(CompositeFont f, int rank) {
695
696 if (FontUtilities.isLogging()) {
697 FontUtilities.getLogger().info("Add to Family "+ f.familyName +
698 ", Font " + f.fullName + " rank="+rank);
699 }
700 f.setRank(rank);
701 compositeFonts.put(f.fullName, f);
702 fullNameToFont.put(f.fullName.toLowerCase(Locale.ENGLISH), f);
703
704 FontFamily family = FontFamily.getFamily(f.familyName);
705 if (family == null) {
706 family = new FontFamily(f.familyName, true, rank);
707 }
1975
1976 ArrayList<String> family = null;
1977 String fontFile = null;
1978 String familyName = fontToFamilyNameMap.get(lcName);
1979 if (familyName != null) {
1980 fontFile = fontToFileMap.get(lcName);
1981 family = familyToFontListMap.get
1982 (familyName.toLowerCase(Locale.ENGLISH));
1983 } else {
1984 family = familyToFontListMap.get(lcName); // is lcName is a family?
1985 if (family != null && family.size() > 0) {
1986 String lcFontName = family.get(0).toLowerCase(Locale.ENGLISH);
1987 if (lcFontName != null) {
1988 familyName = fontToFamilyNameMap.get(lcFontName);
1989 }
1990 }
1991 }
1992 if (family == null || familyName == null) {
1993 return null;
1994 }
1995 String [] fontList = (String[])family.toArray(STR_ARRAY);
1996 if (fontList.length == 0) {
1997 return null;
1998 }
1999
2000 /* first check that for every font in this family we can find
2001 * a font file. The specific reason for doing this is that
2002 * in at least one case on Windows a font has the face name "David"
2003 * but the registry entry is "David Regular". That is the "unique"
2004 * name of the font but in other cases the registry contains the
2005 * "full" name. See the specifications of name ids 3 and 4 in the
2006 * TrueType 'name' table.
2007 * In general this could cause a problem that we fail to register
2008 * if we all members of a family that we may end up mapping to
2009 * the wrong font member: eg return Bold when Plain is needed.
2010 */
2011 for (int f=0;f<fontList.length;f++) {
2012 String fontNameLC = fontList[f].toLowerCase(Locale.ENGLISH);
2013 String fileName = fontToFileMap.get(fontNameLC);
2014 if (fileName == null) {
2015 if (FontUtilities.isLogging()) {
2068 * A font may exist with the specified style, or it may
2069 * exist only in some other style. For non-native fonts the scaler
2070 * may be able to emulate the required style.
2071 */
2072 public Font2D findFont2D(String name, int style, int fallback) {
2073 String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
2074 String mapName = lowerCaseName + dotStyleStr(style);
2075 Font2D font;
2076
2077 /* If preferLocaleFonts() or preferProportionalFonts() has been
2078 * called we may be using an alternate set of composite fonts in this
2079 * app context. The presence of a pre-built name map indicates whether
2080 * this is so, and gives access to the alternate composite for the
2081 * name.
2082 */
2083 if (_usingPerAppContextComposites) {
2084 ConcurrentHashMap<String, Font2D> altNameCache =
2085 (ConcurrentHashMap<String, Font2D>)
2086 AppContext.getAppContext().get(CompositeFont.class);
2087 if (altNameCache != null) {
2088 font = (Font2D)altNameCache.get(mapName);
2089 } else {
2090 font = null;
2091 }
2092 } else {
2093 font = fontNameCache.get(mapName);
2094 }
2095 if (font != null) {
2096 return font;
2097 }
2098
2099 if (FontUtilities.isLogging()) {
2100 FontUtilities.getLogger().info("Search for font: " + name);
2101 }
2102
2103 // The check below is just so that the bitmap fonts being set by
2104 // AWT and Swing thru the desktop properties do not trigger the
2105 // the load fonts case. The two bitmap fonts are now mapped to
2106 // appropriate equivalents for serif and sansserif.
2107 // Note that the cost of this comparison is only for the first
2108 // call until the map is filled.
2611 }
2612 }
2613 if (oldFont == newFont) {
2614 if (FontUtilities.isLogging()) {
2615 FontUtilities.getLogger()
2616 .severe("This is bad. No good physicalFonts found.");
2617 }
2618 return;
2619 }
2620 }
2621
2622 /* eliminate references to this font, so it won't be located
2623 * by future callers, and will be eligible for GC when all
2624 * references are removed
2625 */
2626 oldFont.handle.font2D = newFont;
2627 physicalFonts.remove(oldFont.fullName);
2628 fullNameToFont.remove(oldFont.fullName.toLowerCase(Locale.ENGLISH));
2629 FontFamily.remove(oldFont);
2630 if (localeFullNamesToFont != null) {
2631 Map.Entry[] mapEntries =
2632 (Map.Entry[])localeFullNamesToFont.entrySet().
2633 toArray(new Map.Entry[0]);
2634 /* Should I be replacing these, or just I just remove
2635 * the names from the map?
2636 */
2637 for (int i=0; i<mapEntries.length;i++) {
2638 if (mapEntries[i].getValue() == oldFont) {
2639 try {
2640 mapEntries[i].setValue(newFont);
2641 } catch (Exception e) {
2642 /* some maps don't support this operation.
2643 * In this case just give up and remove the entry.
2644 */
2645 localeFullNamesToFont.remove(mapEntries[i].getKey());
2646 }
2647 }
2648 }
2649 }
2650
2651 for (int i=0; i<maxCompFont; i++) {
2652 /* Deferred initialization of composites shouldn't be
3083 * member, we need to remove all members of the family, so that the
3084 * new style can get picked up rather than continuing to synthesise.
3085 */
3086 if (fontsAreRegistered) {
3087 removeFromCache(family.getFont(Font.PLAIN));
3088 removeFromCache(family.getFont(Font.BOLD));
3089 removeFromCache(family.getFont(Font.ITALIC));
3090 removeFromCache(family.getFont(Font.BOLD|Font.ITALIC));
3091 removeFromCache(fullNameTable.get(fullName));
3092 }
3093 family.setFont(font2D, style);
3094 fullNameTable.put(fullName, font2D);
3095 return true;
3096 }
3097
3098 /* Remove from the name cache all references to the Font2D */
3099 private void removeFromCache(Font2D font) {
3100 if (font == null) {
3101 return;
3102 }
3103 String[] keys = (String[])(fontNameCache.keySet().toArray(STR_ARRAY));
3104 for (int k=0; k<keys.length;k++) {
3105 if (fontNameCache.get(keys[k]) == font) {
3106 fontNameCache.remove(keys[k]);
3107 }
3108 }
3109 }
3110
3111 // It may look odd to use TreeMap but its more convenient to the caller.
3112 public TreeMap<String, String> getCreatedFontFamilyNames() {
3113
3114 Hashtable<String,FontFamily> familyTable;
3115 if (fontsAreRegistered) {
3116 familyTable = createdByFamilyName;
3117 } else if (fontsAreRegisteredPerAppContext) {
3118 AppContext appContext = AppContext.getAppContext();
3119 familyTable =
3120 (Hashtable<String,FontFamily>)appContext.get(regFamilyKey);
3121 } else {
3122 return null;
3123 }
3768 /* Augment platform names with JRE font family names */
3769 getJREFontFamilyNames(familyNames, requestedLocale);
3770 } else {
3771 loadFontFiles();
3772 Font2D[] physicalfonts = getPhysicalFonts();
3773 for (int i=0; i < physicalfonts.length; i++) {
3774 if (!(physicalfonts[i] instanceof NativeFont)) {
3775 String name =
3776 physicalfonts[i].getFamilyName(requestedLocale);
3777 familyNames.put(name.toLowerCase(requestedLocale), name);
3778 }
3779 }
3780 }
3781
3782 // Add any native font family names here
3783 addNativeFontFamilyNames(familyNames, requestedLocale);
3784
3785 String[] retval = new String[familyNames.size()];
3786 Object [] keyNames = familyNames.keySet().toArray();
3787 for (int i=0; i < keyNames.length; i++) {
3788 retval[i] = (String)familyNames.get(keyNames[i]);
3789 }
3790 if (requestedLocale.equals(Locale.getDefault())) {
3791 lastDefaultLocale = requestedLocale;
3792 allFamilies = new String[retval.length];
3793 System.arraycopy(retval, 0, allFamilies, 0, allFamilies.length);
3794 }
3795 return retval;
3796 }
3797
3798 // Provides an aperture to add native font family names to the map
3799 protected void addNativeFontFamilyNames(TreeMap<String, String> familyNames, Locale requestedLocale) { }
3800
3801 public void register1dot0Fonts() {
3802 java.security.AccessController.doPrivileged(
3803 new java.security.PrivilegedAction() {
3804 public Object run() {
3805 String type1Dir = "/usr/openwin/lib/X11/fonts/Type1";
3806 registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK,
3807 false, false);
3808 return null;
|
1 /*
2 * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
666 componentFileNames,
667 componentNames,
668 numMetricsSlots,
669 exclusionRanges,
670 exclusionMaxIndex, defer,
671 SunFontManager.getInstance());
672
673 /* if the cache has an existing composite for this case, make
674 * its handle point to this new font.
675 * This ensures that when the altNameCache that is passed in
676 * is the global mapNameCache - ie we are running as an application -
677 * that any statically created java.awt.Font instances which already
678 * have a Font2D instance will have that re-directed to the new Font
679 * on subsequent uses. This is particularly important for "the"
680 * default font instance, or similar cases where a UI toolkit (eg
681 * Swing) has cached a java.awt.Font. Note that if Swing is using
682 * a custom composite APIs which update the standard composites have
683 * no effect - this is typically the case only when using the Windows
684 * L&F where these APIs would conflict with that L&F anyway.
685 */
686 Font2D oldFont =altNameCache.get(compositeName.toLowerCase(Locale.ENGLISH));
687 if (oldFont instanceof CompositeFont) {
688 oldFont.handle.font2D = cf;
689 }
690 altNameCache.put(compositeName.toLowerCase(Locale.ENGLISH), cf);
691 }
692
693 private void addCompositeToFontList(CompositeFont f, int rank) {
694
695 if (FontUtilities.isLogging()) {
696 FontUtilities.getLogger().info("Add to Family "+ f.familyName +
697 ", Font " + f.fullName + " rank="+rank);
698 }
699 f.setRank(rank);
700 compositeFonts.put(f.fullName, f);
701 fullNameToFont.put(f.fullName.toLowerCase(Locale.ENGLISH), f);
702
703 FontFamily family = FontFamily.getFamily(f.familyName);
704 if (family == null) {
705 family = new FontFamily(f.familyName, true, rank);
706 }
1974
1975 ArrayList<String> family = null;
1976 String fontFile = null;
1977 String familyName = fontToFamilyNameMap.get(lcName);
1978 if (familyName != null) {
1979 fontFile = fontToFileMap.get(lcName);
1980 family = familyToFontListMap.get
1981 (familyName.toLowerCase(Locale.ENGLISH));
1982 } else {
1983 family = familyToFontListMap.get(lcName); // is lcName is a family?
1984 if (family != null && family.size() > 0) {
1985 String lcFontName = family.get(0).toLowerCase(Locale.ENGLISH);
1986 if (lcFontName != null) {
1987 familyName = fontToFamilyNameMap.get(lcFontName);
1988 }
1989 }
1990 }
1991 if (family == null || familyName == null) {
1992 return null;
1993 }
1994 String [] fontList = family.toArray(STR_ARRAY);
1995 if (fontList.length == 0) {
1996 return null;
1997 }
1998
1999 /* first check that for every font in this family we can find
2000 * a font file. The specific reason for doing this is that
2001 * in at least one case on Windows a font has the face name "David"
2002 * but the registry entry is "David Regular". That is the "unique"
2003 * name of the font but in other cases the registry contains the
2004 * "full" name. See the specifications of name ids 3 and 4 in the
2005 * TrueType 'name' table.
2006 * In general this could cause a problem that we fail to register
2007 * if we all members of a family that we may end up mapping to
2008 * the wrong font member: eg return Bold when Plain is needed.
2009 */
2010 for (int f=0;f<fontList.length;f++) {
2011 String fontNameLC = fontList[f].toLowerCase(Locale.ENGLISH);
2012 String fileName = fontToFileMap.get(fontNameLC);
2013 if (fileName == null) {
2014 if (FontUtilities.isLogging()) {
2067 * A font may exist with the specified style, or it may
2068 * exist only in some other style. For non-native fonts the scaler
2069 * may be able to emulate the required style.
2070 */
2071 public Font2D findFont2D(String name, int style, int fallback) {
2072 String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
2073 String mapName = lowerCaseName + dotStyleStr(style);
2074 Font2D font;
2075
2076 /* If preferLocaleFonts() or preferProportionalFonts() has been
2077 * called we may be using an alternate set of composite fonts in this
2078 * app context. The presence of a pre-built name map indicates whether
2079 * this is so, and gives access to the alternate composite for the
2080 * name.
2081 */
2082 if (_usingPerAppContextComposites) {
2083 ConcurrentHashMap<String, Font2D> altNameCache =
2084 (ConcurrentHashMap<String, Font2D>)
2085 AppContext.getAppContext().get(CompositeFont.class);
2086 if (altNameCache != null) {
2087 font = altNameCache.get(mapName);
2088 } else {
2089 font = null;
2090 }
2091 } else {
2092 font = fontNameCache.get(mapName);
2093 }
2094 if (font != null) {
2095 return font;
2096 }
2097
2098 if (FontUtilities.isLogging()) {
2099 FontUtilities.getLogger().info("Search for font: " + name);
2100 }
2101
2102 // The check below is just so that the bitmap fonts being set by
2103 // AWT and Swing thru the desktop properties do not trigger the
2104 // the load fonts case. The two bitmap fonts are now mapped to
2105 // appropriate equivalents for serif and sansserif.
2106 // Note that the cost of this comparison is only for the first
2107 // call until the map is filled.
2610 }
2611 }
2612 if (oldFont == newFont) {
2613 if (FontUtilities.isLogging()) {
2614 FontUtilities.getLogger()
2615 .severe("This is bad. No good physicalFonts found.");
2616 }
2617 return;
2618 }
2619 }
2620
2621 /* eliminate references to this font, so it won't be located
2622 * by future callers, and will be eligible for GC when all
2623 * references are removed
2624 */
2625 oldFont.handle.font2D = newFont;
2626 physicalFonts.remove(oldFont.fullName);
2627 fullNameToFont.remove(oldFont.fullName.toLowerCase(Locale.ENGLISH));
2628 FontFamily.remove(oldFont);
2629 if (localeFullNamesToFont != null) {
2630 Map.Entry[] mapEntries = localeFullNamesToFont.entrySet().
2631 toArray(new Map.Entry[0]);
2632 /* Should I be replacing these, or just I just remove
2633 * the names from the map?
2634 */
2635 for (int i=0; i<mapEntries.length;i++) {
2636 if (mapEntries[i].getValue() == oldFont) {
2637 try {
2638 mapEntries[i].setValue(newFont);
2639 } catch (Exception e) {
2640 /* some maps don't support this operation.
2641 * In this case just give up and remove the entry.
2642 */
2643 localeFullNamesToFont.remove(mapEntries[i].getKey());
2644 }
2645 }
2646 }
2647 }
2648
2649 for (int i=0; i<maxCompFont; i++) {
2650 /* Deferred initialization of composites shouldn't be
3081 * member, we need to remove all members of the family, so that the
3082 * new style can get picked up rather than continuing to synthesise.
3083 */
3084 if (fontsAreRegistered) {
3085 removeFromCache(family.getFont(Font.PLAIN));
3086 removeFromCache(family.getFont(Font.BOLD));
3087 removeFromCache(family.getFont(Font.ITALIC));
3088 removeFromCache(family.getFont(Font.BOLD|Font.ITALIC));
3089 removeFromCache(fullNameTable.get(fullName));
3090 }
3091 family.setFont(font2D, style);
3092 fullNameTable.put(fullName, font2D);
3093 return true;
3094 }
3095
3096 /* Remove from the name cache all references to the Font2D */
3097 private void removeFromCache(Font2D font) {
3098 if (font == null) {
3099 return;
3100 }
3101 String[] keys = fontNameCache.keySet().toArray(STR_ARRAY);
3102 for (int k=0; k<keys.length;k++) {
3103 if (fontNameCache.get(keys[k]) == font) {
3104 fontNameCache.remove(keys[k]);
3105 }
3106 }
3107 }
3108
3109 // It may look odd to use TreeMap but its more convenient to the caller.
3110 public TreeMap<String, String> getCreatedFontFamilyNames() {
3111
3112 Hashtable<String,FontFamily> familyTable;
3113 if (fontsAreRegistered) {
3114 familyTable = createdByFamilyName;
3115 } else if (fontsAreRegisteredPerAppContext) {
3116 AppContext appContext = AppContext.getAppContext();
3117 familyTable =
3118 (Hashtable<String,FontFamily>)appContext.get(regFamilyKey);
3119 } else {
3120 return null;
3121 }
3766 /* Augment platform names with JRE font family names */
3767 getJREFontFamilyNames(familyNames, requestedLocale);
3768 } else {
3769 loadFontFiles();
3770 Font2D[] physicalfonts = getPhysicalFonts();
3771 for (int i=0; i < physicalfonts.length; i++) {
3772 if (!(physicalfonts[i] instanceof NativeFont)) {
3773 String name =
3774 physicalfonts[i].getFamilyName(requestedLocale);
3775 familyNames.put(name.toLowerCase(requestedLocale), name);
3776 }
3777 }
3778 }
3779
3780 // Add any native font family names here
3781 addNativeFontFamilyNames(familyNames, requestedLocale);
3782
3783 String[] retval = new String[familyNames.size()];
3784 Object [] keyNames = familyNames.keySet().toArray();
3785 for (int i=0; i < keyNames.length; i++) {
3786 retval[i] = familyNames.get(keyNames[i]);
3787 }
3788 if (requestedLocale.equals(Locale.getDefault())) {
3789 lastDefaultLocale = requestedLocale;
3790 allFamilies = new String[retval.length];
3791 System.arraycopy(retval, 0, allFamilies, 0, allFamilies.length);
3792 }
3793 return retval;
3794 }
3795
3796 // Provides an aperture to add native font family names to the map
3797 protected void addNativeFontFamilyNames(TreeMap<String, String> familyNames, Locale requestedLocale) { }
3798
3799 public void register1dot0Fonts() {
3800 java.security.AccessController.doPrivileged(
3801 new java.security.PrivilegedAction() {
3802 public Object run() {
3803 String type1Dir = "/usr/openwin/lib/X11/fonts/Type1";
3804 registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK,
3805 false, false);
3806 return null;
|