src/share/classes/sun/font/SunFontManager.java

Print this page


   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;