2362N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 0N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 2362N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A * or visit www.oracle.com if you need additional information or have any 0N/A * The base implementation of the {@link FontManager} interface. It implements 0N/A * the platform independent, shared parts of OpenJDK's FontManager 0N/A * implementations. The platform specific parts are declared as abstract 0N/A * methods that have to be implemented by specific implementations. 0N/A /* all conveniently have the same suffix length */ 0N/A if (
offset <=
0) {
/* must be at least A.ttf */ 0N/A /* all conveniently have the same suffix length */ 0N/A if (
offset <=
0) {
/* must be at least A.pfa */ 0N/A /* all conveniently have the same suffix length */ 0N/A if (
offset <=
0) {
/* must be at least A.ttf or A.pfa */ 0N/A /* Pool of 20 font file channels chosen because some UTF-8 locale 0N/A * composite fonts can use up to 16 platform fonts (including the 0N/A * Lucida fall back). This should prevent channel thrashing when 0N/A * dealing with one of these fonts. 0N/A * The pool array stores the fonts, rather than directly referencing 0N/A * the channels, as the font needs to do the open/close work. 0N/A // MACOSX begin -- need to access these in subclass 0N/A /* Need to implement a simple linked list scheme for fast 0N/A * traversal and lookup. 0N/A * Also want to "fast path" dialog so there's minimal overhead. 0N/A /* There are at exactly 20 composite fonts: 5 faces (but some are not 0N/A * usually different), in 4 styles. The array may be auto-expanded 0N/A * later if more are needed, eg for user-defined composites or locale 0N/A /* given a full name find the Font. Remind: there's duplication 0N/A * here in that this contains the content of compositeFonts + 0N/A // MACOSX begin -- need to access this in subclass 0N/A /* TrueType fonts have localised names. Support searching all 0N/A * of these before giving up on a name. 0N/A /* fontPath is the location of all fonts on the system, excluding the 0N/A * JRE's own font directory but including any path specified using the 0N/A * sun.java2d.fontpath property. Together with that property, it is 0N/A * initialised by the getPlatformFontPath() method 0N/A * This call must be followed by a call to registerFontDirs(fontPath) 0N/A * once any extra debugging path has been appended. 0N/A /* discoveredAllFonts is set to true when all fonts on the font path are 0N/A * discovered. This usually also implies opening, validating and 0N/A * registering, but an implementation may be optimized to avold this. 0N/A * So see also "loadedAllFontFiles" 0N/A /* No need to keep consing up new instances - reuse a singleton. 0N/A * The trade-off is that these objects don't get GC'd. 0N/A /* Used to indicate required return type from toArray(..); */ 0N/A * Deprecated, unsupported hack - actually invokes a bug! 0N/A * Left in for a customer, don't remove. 0N/A * Returns the global SunFontManager instance. This is similar to 0N/A * {@link FontManagerFactory#getInstance()} but it returns a 0N/A * SunFontManager instance instead. This is only used in internal classes 0N/A * where we can safely assume that a SunFontManager is to be used. 0N/A * @return the global SunFontManager instance 0N/A /* Key is familyname+style value as an int. 0N/A * Value is filename containing the font. 0N/A * If no mapping exists, it means there is no font file for the style 0N/A * If the mapping exists but the file doesn't exist in the deferred 0N/A * list then it means its not installed. 0N/A * This looks like a lot of code and strings but if it saves even 0N/A * a single file being opened at JRE start-up there's a big payoff. 0N/A * Lucida Sans is probably the only important case as the others 0N/A * are rarely used. Consider removing the other mappings if there's 0N/A * no evidence they are useful in practice. 0N/A /* Lucida Sans Family */ 0N/A /* Lucida Sans full names (map Bold and DemiBold to same file) */ 0N/A /* Lucida Sans Typewriter Family */ 0N/A "LucidaTypewriterRegular.ttf");
0N/A /* Typewriter full names (map Bold and DemiBold to same file) */ 0N/A "LucidaTypewriter.ttf");
0N/A "LucidaTypewriterBold.ttf");
0N/A "LucidaTypewriterBold.ttf");
0N/A "LucidaTypewriterBold.ttf");
0N/A /* Lucida Bright Family */ 0N/A /* Lucida Bright full names (map Bold and DemiBold to same file) */ 0N/A "LucidaBrightDemiItalic.ttf");
0N/A "LucidaBrightDemiItalic.ttf");
0N/A // so there's no need to do anything explicit here. 0N/A // Overridden in Windows. 0N/A /* Initialise ptrs used by JNI methods */ 0N/A * them so they are always available and preferred over 0N/A * other fonts. This needs to be registered before the 0N/A * composite fonts as otherwise some native font that 0N/A * corresponds may be found as we don't have a way to 0N/A * handle two fonts of the same name, so the JRE one 0N/A * must be the first one registered. Pass "true" to 0N/A * registerFonts method as on-screen these JRE fonts 0N/A * always go through the T2K rasteriser. 0N/A /* Linux font configuration uses these fonts */ 0N/A /* Create the font configuration and get any font path 0N/A * that might be specified. 0N/A /* In prior releases the debugging font path replaced 0N/A * all normally located font directories except for the 0N/A * JRE fonts dir. This directory is still always located 0N/A * and placed at the head of the path but as an 0N/A * augmentation to the previous behaviour the 0N/A * changes below allow you to additionally append to 0N/A * the font path by starting with append: or prepend by 0N/A * starting with a prepend: sign. Eg: to append 0N/A * If there is an appendedfontpath it in the font 0N/A * configuration it is used instead of searching the 0N/A * The behaviour of append and prepend is then similar 0N/A * to the normal case. ie it goes after what 0N/A * you prepend and * before what you append. If the 0N/A * neither the append or prepend syntaxes is used then 0N/A * as except for the JRE dir the path is replaced and it 0N/A * is up to you to make sure that all the right 0N/A * directories are located. This is platform and * locale-specific so its almost impossible to get * right, so it should be used with caution. /* In debugging mode we register all the paths * Caution: this is a very expensive call on Solaris:- /* If the font configuration contains an * "appendedfontpath" entry, it is interpreted as a * set of locations that should always be registered. * It may be additional to locations normally found * for that place, or it may be locations that need * to have all their paths registered to locate all * the needed platform names. * This is typically when the same .TTF file is * referenced from multiple font.dir files and all * of these must be read to find all the native * (XLFD) names for the font, so that X11 font APIs * can be used for as many code points as possible. /* On Solaris, we need to register the Japanese TrueType * directory so that we can find the corresponding * bitmap fonts. This could be done by listing the * directory in the font configuration file, but we * don't want to confuse users with this quirk. There * are no bitmap fonts for other writing systems that * correspond to TrueType fonts and have matching XLFDs. * We need to register the bitmap fonts only in * environments where they're on the X font path, i.e., * in the Japanese locale. Note that if the X Toolkit * is in use the font path isn't set up by JDK, but * users of a JA locale should have it * set up already by their login environment. System.
out.
println(
"Enabling platform font metrics for win32. This is an unsupported option.");
System.
out.
println(
"This yields incorrect composite font metrics as reported by 1.1.x releases.");
System.
out.
println(
"It is appropriate only for use by applications which do not use any Java 2");
System.
out.
println(
"functionality. This property will be removed in a later release.");
* This method is provided for internal and exclusive use by Swing. * @param font representing a physical font. * @return true if the underlying font is a TrueType or OpenType font * that claims to support the Microsoft Windows encoding corresponding to * the default file.encoding property of this JRE instance. * This narrow value is useful for Swing to decide if the font is useful * for the the Windows Look and Feel, or, if a composite font should be * The information used to make the decision is obtained from * the ulCodePageRange fields in the font. * A caller can use isLogicalFont(Font) in this class before calling * this method and would not need to call this method if that // static boolean fontSupportsDefaultEncoding(Font font) { // (String) java.security.AccessController.doPrivileged( // new sun.security.action.GetPropertyAction("file.encoding")); // if (encoding == null || font == null) { // encoding = encoding.toLowerCase(Locale.ENGLISH); // return FontManager.fontSupportsEncoding(font, encoding); /* This variant is used only when the application specifies * a variant of composite fonts which prefers locale specific or /* if the cache has an existing composite for this case, make * its handle point to this new font. * This ensures that when the altNameCache that is passed in * is the global mapNameCache - ie we are running as an application - * that any statically created java.awt.Font instances which already * have a Font2D instance will have that re-directed to the new Font * on subsequent uses. This is particularly important for "the" * default font instance, or similar cases where a UI toolkit (eg * Swing) has cached a java.awt.Font. Note that if Swing is using * a custom composite APIs which update the standard composites have * no effect - this is typically the case only when using the Windows * L&F where these APIs would conflict with that L&F anyway. * Systems may have fonts with the same name. * We want to register only one of such fonts (at least until * such time as there might be APIs which can accommodate > 1). * Rank is 1) font configuration fonts, 2) JRE fonts, 3) OT/TT fonts, * 4) Type1 fonts, 5) native fonts. * If the new font has the same name as the old font, the higher * ranked font gets added, replacing the lower ranked one. * If the fonts are of equal rank, then make a special case of * font configuration rank fonts, which are on closer inspection, * OT/TT fonts such that the larger font is registered. This is * a heuristic since a font may be "larger" in the sense of more * code points, or be a larger "file" because it has more bitmaps. * So it is possible that using filesize may lead to less glyphs, and * using glyphs may lead to lower quality display. Probably number * of glyphs is the ideal, but filesize is information we already * have and is good enough for the known cases. * Also don't want to register fonts that match JRE font families * but are coming from a source other than the JRE. * This will ensure that we will algorithmically style the JRE * plain font and get the same set of glyphs for all styles. * Note that this method returns a value * if it returns the same object as its argument that means this * font was newly registered. * If it returns a different object it means this font already exists, * and you should use that one. * If it returns null means this font was not registered and none * in that name is registered. The caller must find a substitute // MACOSX begin -- need to access this in subclass /* Don't register any font that has the same name as a composite */ /* If the new font is of an equal or higher rank, it is a * candidate to replace the current one, subject to further tests. /* All fonts initialise their mapper when first * used. If the mapper is non-null then this font * has been accessed at least once. In that case * do not replace it. This may be overly stringent, * but its probably better not to replace a font that * someone is already using without a compelling reason. * Additionally the primary case where it is known * this behaviour is important is in certain composite * fonts, and since all the components of a given * composite are usually initialised together this * is unlikely. For this to be a problem, there would * have to be a case where two different composites used * different versions of the same-named font, and they * were initialised and used at separate times. * In that case we continue on and allow the new font to * be installed, but replaceFont will continue to allow * the original font to be used in Composite fonts. /* Normally we require a higher rank to replace a font, * but as a special case, if the two fonts are the same rank, * and are instances of TrueTypeFont we want the * more complete (larger) one. /* Don't replace ever JRE fonts. * This test is in case a font configuration references * a Lucida font, which has been mapped to a Lucida * from the host O/S. The assumption here is that any * such font configuration file is probably incorrect, or * the host O/S version is for the use of AWT. * In other words if we reach here, there's a possible * problem with our choice of font configuration fonts. .
warning(
"Unexpected attempt to replace a JRE " +
/* The class FontRegistrationInfo is used when a client says not * to register a font immediately. This mechanism is used to defer * initialisation of all the components of composite fonts at JRE * start-up. The CompositeFont class is "aware" of this and when it * is first used it asks for the registration of its components. * Also in the event that any physical font is requested the * deferred fonts are initialised before triggering a search of the * Two maps are used. One to track the deferred fonts. The * other to track the fonts that have been initialised through this /* Remind: possibly enhance initialiseDeferredFonts() to be * optionally given a name and a style and it could stop when it * finds that font - but this would be a problem if two of the * fonts reference the same font face name (cf the Solaris /* We keep a map of the files which contain the Lucida fonts so we * don't need to search for them. * But since we know what fonts these files contain, we can also avoid * opening them to look for a font name we don't recognise - see * For typical cases where the font isn't a JRE one the overhead is * this method call, HashMap.get() and null reference test, then * a boolean test of noOtherJREFontFiles. /* Iterate over the deferred font files looking for any in the * jre directory that we didn't recognise, open each of these. * In almost all installations this will quickly fall through * because only the Lucidas will be present and jreOtherFontFiles * noOtherJREFontFiles is used so we can skip this block as soon * as its determined that its not needed - almost always after the * very first time through. /* skip names which aren't absolute, aren't in the JRE * directory, or are known Lucida fonts. /* This skips JRE installed fonts. */ /* Store the handle, so that if a font is bad, we * retrieve the substituted font. /* Probably shouldn't happen, but just in case */ /* Note that the return value from this method is not always * derived from this file, and may be null. See addToFontList for * some explanation of this. * This is the Physical font used when some other font on the system * can't be located. There has to be at least one font or the font * system is not useful and the graphics environment cannot sustain /* findFont2D will load all fonts before giving up the search. * If the JRE Lucida isn't found (eg because the JRE fonts * directory is missing), it could find another version of Lucida * from the host system. This is OK because at that point we are * misconfiguration and this is probably a reasonable substitution. /* Because of the findFont2D call above, if we reach here, we * know all fonts have already been loaded, just accept any * match at this point. If this fails we are in real trouble * and I don't know how to recover from there being absolutely * no fonts anywhere on the system. throw new Error(
"Probable fatal error:No fonts found.");
* return String representation of style prepended with "." * This is useful for performance to avoid unnecessary string operations. /* This is implemented only on windows and is called from code that * executes only on windows. This isn't pretty but its not a precedent * in this file. This very probably should be cleaned up at some point. /* Obtained from Platform APIs (windows only) * Map from lower-case font full name to basename of font file. * Eg "arial bold" -> ARIALBD.TTF. * For TTC files, there is a mapping for each font in the file. /* Obtained from Platform APIs (windows only) * Map from lower-case font full name to the name of its font family * Eg "arial bold" -> "Arial" /* Obtained from Platform APIs (windows only) * Map from a lower-case family name to a list of full names of * "arial" -> ["Arial", "Arial Bold", "Arial Italic","Arial Bold Italic"] /* The directories which contain platform fonts */ /* This is needed since some windows registry names don't match * - UPC styled font names have a double space, but the * registry entry mapping to a file doesn't. * - Marlett is in a hidden file not listed in the registry * - The registry advertises that the file david.ttf contains a * font with the full name "David Regular" when in fact its * Directly fix up these known cases as this is faster. * If a font which doesn't match these known cases has no file, * it may be a font that has been temporarily added to the known set * or it may be an installed font with a missing registry entry. * Installed fonts are those in the windows font directories. * Make a best effort attempt to locate these. * We obtain the list of TrueType fonts in these directories and * filter out all the font files we already know about from the registry. * What remains may be "bad" fonts, duplicate fonts, or perhaps the * missing font(s) we are looking for. * Open each of these files to find out. /* If this name exists and isn't for a valid name * replace the mapping to the file with this font /* Every font key in fontToFileMap ought to correspond to a * font key in fontToFamilyNameMap. Entries that don't seem * to correspond are likely fonts that were named differently * by GDI than in the registry. One known cause of this is when * Windows has had its regional settings changed so that from * GDI we get a localised (eg Chinese or Japanese) name for the * font, but the registry retains the English version of the name * that corresponded to the "install" locale for windows. * Since we are in this code block because there are unmapped * font names, we can look to find unused font->file mappings * and then open the files to read the names. We don't generally * want to open font files, as its a performance hit, but this * occurs only for a small number of fonts on specific system * configs - ie is believed that a "true" Japanese windows would * have JA names in the registry too. * Clone fontToFileMap and remove from the clone all keys which * match a fontToFamilyNameMap key. What remains maps to the * files we want to open to find the fonts GDI returned. * A font in such a file is added to the fontToFileMap after * checking its one of the unmappedFontNames we are looking for. * The original name that didn't map is removed from fontToFileMap * so essentially this "fixes up" fontToFileMap to use the same * Also note that typically the fonts for which this occurs in * CJK locales are TTC fonts and not all fonts in a TTC may have * localised names. Eg MSGOTHIC.TTC contains 3 fonts and one of * them "MS UI Gothic" has no JA name whereas the other two do. * So not every font in these files is unmapped or new. /* If there are still unmapped font names, this means there's * something that wasn't in the registry. We need to get all * the font files directly and look at the ones that weren't /* getFontFilesFromPath() returns all lower case names. * To compare we also need lower case * versions of the names from the registry. /* We don't look for Type1 files here as windows will * not enumerate these, so aren't useful in reconciling * GDI's unmapped files. We do find these later when * we enumerate all fonts. /* remove from the set of names that will be returned to the * user any fonts that can't be mapped to files. for (
int i=
0; i<
sz; i++) {
* In some cases windows may have fonts in the fonts folder that * don't show up in the registry or in the GDI calls to enumerate fonts. * The only way to find these is to list the directory. We invoke this * font that is satisfied by the GDI/registry calls don't take the * additional hit of listing the directory. This hit is small enough * that its not significant in these 'enumerate all the fonts' cases. * The basic approach is to cross-reference the files windows found * with the ones in the directory listing approach, and for each * in the latter list that is missing from the former list, register it. /* getFontFilesFromPath() returns all lower case names. * To compare we also need lower case * versions of the names from the registry. /* To avoid any issues with concurrent modification, create * copies of the existing maps, add the new fonts into these * and then replace the references to the old ones with the * new maps. ConcurrentHashmap is another option but its a lot * more changes and with this exception, these maps are intended // prefer the font's locale name. .
info(
"Resolved absent registry entry for " +
/* Hardwire the English names and expected file names of fonts * commonly used at start up. Avoiding until later even the small * cost of calling platform APIs to locate these can help. * The code that registers these fonts needs to "bail" if any * of the files do not exist, so it will verify the existence of * all non-null file names first. * They are added in to a map with nominally the first * word in the name of the family as the key. In all the cases * we are using the the family name is a single word, and as is * more or less required the family name is the initial sequence * in a full name. So lookup first finds the matching description, * then registers the whole family, returning the right font. * default implementation does nothing. /* Once we've established that its at least the first word, * we need to dig deeper to make sure its a match for either * a full name, or the family name, to make sure its not * a request for some other font that just happens to start * with the same first word. /* In a terminal server config, its possible that getPathName() * will return null, if the file doesn't exist, hence the null * checks on return. But in the normal client config we need to * follow this up with a check to see if all the files really * exist for the non-null paths. info(
"Hardcoded file missing looking for " +
lcName);
/* Some of these may be null,as not all styles have to exist */ info(
"Hardcoded file missing looking for " +
lcName);
/* If we reach here we know that we have all the files we * expect, so all should be fine so long as the contents * are what we'd expect. Now on to registering the fonts. * Currently this code only looks for TrueType fonts, so format * and rank can be specified without looking at the filename. /* Two general cases need a bit more work here. * 1) If font is null, then it was perhaps a request for a * non-existent font, such as "Tahoma Italic", or a family name - * where family and full name of the plain font differ. * Fall back to finding the closest one in the family. * This could still fail if a client specified "Segoe" instead of * 2) The request is of the form "MyFont Bold", style=Font.ITALIC, * and so we want to see if there's a Bold Italic font, or * "MyFamily", style=Font.BOLD, and we may have matched the plain, * but now need to revise that to the BOLD font. /* Note this return list excludes logical fonts and JRE fonts */ /* This odd code with TreeMap is used to preserve a historical * behaviour wrt the sorting order .. */ /* Used to register any font files that are found by platform APIs * that weren't previously found in the standard font locations. * the isAbsolute() check is needed since that's whats stored in the * set, and on windows, the fonts in the system font directory that * are in the fontToFileMap are just basenames. We don't want to try * to register those again, but we do want to register other registry /* Path may be absolute or a base file name relative to one of * the platform font directories return s;
// shouldn't happen, but harmless /* lcName is required to be lower case for use as a key. * lcName may be a full name, or a family name, and style may * be specified in addition to either of these. So be sure to * get the right one. Since an app *could* ask for "Foo Regular" * and later ask for "Foo Italic", if we don't register all the * styles, then logic in findFont2D may try to style the original * so we register the entire family if we get a match here. * This is still a big win because this code is invoked where * otherwise we would register all fonts. * It's also useful for the case where "Foo Bold" was specified with * style Font.ITALIC, as we would want in that case to try to return * "Foo Bold Italic" if it exists, and it is only by locating "Foo Bold" * and opening it that we really "know" it's Bold, and can look for * a font that supports that and the italic style. * The code in here is not overtly windows-specific but in fact it * is unlikely to be useful as is on other platforms. It is maintained * in this shared source file to be close to its sole client and * because so much of the logic is intertwined with the logic in /* first check that for every font in this family we can find * a font file. The specific reason for doing this is that * in at least one case on Windows a font has the face name "David" * but the registry entry is "David Regular". That is the "unique" * name of the font but in other cases the registry contains the * "full" name. See the specifications of name ids 3 and 4 in the * In general this could cause a problem that we fail to register * if we all members of a family that we may end up mapping to * the wrong font member: eg return Bold when Plain is needed. .
info(
"Platform lookup : No file for font " +
/* Currently this code only looks for TrueType fonts, so format * and rank can be specified without looking at the filename. /* Register all fonts in this family. */ /* Currently this code only looks for TrueType fonts, so format * and rank can be specified without looking at the filename. /* Handle case where request "MyFont Bold", style=Font.ITALIC */ * The client supplies a name and a style. * The name could be a family name, or a full name. * A font may exist with the specified style, or it may * exist only in some other style. For non-native fonts the scaler * may be able to emulate the required style. /* If preferLocaleFonts() or preferProportionalFonts() has been * called we may be using an alternate set of composite fonts in this * app context. The presence of a pre-built name map indicates whether * this is so, and gives access to the alternate composite for the // The check below is just so that the bitmap fonts being set by // AWT and Swing thru the desktop properties do not trigger the // the load fonts case. The two bitmap fonts are now mapped to // appropriate equivalents for serif and sansserif. // Note that the cost of this comparison is only for the first // call until the map is filled. /* This isn't intended to support a client passing in the * string default, but if a client passes in null for the name * the java.awt.Font class internally substitutes this name. * So we need to recognise it here to prevent a loadFonts * on the unrecognised name. The only potential problem with * this is it would hide any real font called "default"! * But that seems like a potential problem we can ignore for now. /* First see if its a family name. */ /* If it wasn't a family name, it should be a full name of * either a composite, or a physical font /* Check that the requested style matches the matched font's style. * But also match style automatically if the requested style is * "plain". This because the existing behaviour is that the fonts * listed via getAllFonts etc always list their style as PLAIN. * This does lead to non-commutative behaviours where you might * start with "Lucida Sans Regular" and ask for a BOLD version * and get "Lucida Sans DemiBold" but if you ask for the PLAIN * style of "Lucida Sans DemiBold" you get "Lucida Sans DemiBold". * This consistent however with what happens if you have a bold * version of a font and no plain version exists - alg. styling * doesn't "unbolden" the font. /* If it was a full name like "Lucida Sans Regular", but * the style requested is "bold", then we want to see if * there's the appropriate match against another font in * that family before trying to load all fonts, or applying a /* We exactly matched the requested style, use it! */ /* This next call is designed to support the case * where bold italic is requested, and if we must * style, then base it on either bold or italic - /* The next check is perhaps one * that shouldn't be done. ie if we get this * far we have probably as close a match as we * are going to get. We could load all fonts to * see if somehow some parts of the family are * loaded but not all of it. .
info(
"findFontFromPlatformMap returned " +
font);
/* Don't want Windows to return a Lucida Sans font from .
info(
"Found font via platform API for request:\"" +
/* If reach here and no match has been located, then if there are * uninitialised deferred fonts, load as many of those as needed * to find the deferred font. If none is found through that * There is possibly a minor issue when more than one * deferred font implements the same font face. Since deferred * fonts are only those in font configuration files, this is a * controlled situation, the known case being Solaris euro_fonts * versions of Arial, Times New Roman, Courier New. However * the larger font will transparently replace the smaller one * - see addToFontList() - when it is needed by the composite font. /* Some apps use deprecated 1.0 names such as helvetica and courier. On * If running on Solaris will register all the fonts in this * May as well register the whole directory without actually testing * the font name is one of the deprecated names as the next step would * load all fonts which are in this directory anyway. * In the event that this lookup is successful it potentially "hides" * TrueType versions of such fonts that are elsewhere but since they * do not exist on Solaris this is not a problem. * Set a flag to indicate we've done this registration to avoid * repetition and more seriously, to avoid recursion. /* "timesroman" is a special case since that's not the * name of any known font on Solaris or elsewhere. /* We check for application registered fonts before * explicitly loading all fonts as if necessary the registration * code will have done so anyway. And we don't want to needlessly * load the actual files for all fonts. * Just as for installed fonts we check for family before fullname. * We do not add these fonts to fontNameCache for the * app context case which eliminates the overhead of a per context /* If reach here and no match has been located, then if all fonts * are not yet loaded, do so, and then recurse. .
info(
"Load fonts looking for:" +
name);
.
info(
"Load font files looking for:" +
name);
/* The primary name is the locale default - ie not US/English but * whatever is the default in this locale. This is the way it always * has been but may be surprising to some developers if "Arial Regular" * were hard-coded in their app and yet "Arial Regular" was not the * default name. Fortunately for them, as a consequence of the JDK * supporting returning names and family names for arbitrary locales, * we also need to support searching all localised names for a match. * But because this case of the name used to reference a font is not * the same as the default for this locale is rare, it makes sense to * search a much shorter list of default locale names and only go to * a longer list of names in the event that no match was found. * So add here code which searches localised names too. * As in 1.4.x this happens only after loading all fonts, which * is probably the right order. /* Perhaps its a "compatibility" name - timesroman, helvetica, * or courier, which 1.0 apps used for logical fonts. * We look for these "late" after a loadFonts as we must not * hide real fonts of these names. * Map these appropriately: * On windows this means according to the rules specified by the * FontConfiguration : do it only for encoding==Cp1252 * REMIND: this is something we plan to remove. * Workaround for apps which are dependent on a font metrics bug * in JDK 1.1. This is an unsupported win32 private setting. * Left in for a customer - do not remove. // MACOSX begin -- need to access this in subclass /* The thread must be a member of a thread group * which will not get GCed before VM exit. * Make its parent the top-level thread group. /* remind: used in X11GraphicsEnvironment and called often enough * that we ought to obsolete this code * This is called when font is determined to be invalid/bad. * It designed to be called (for example) by the font scaler * when in processing a font file it is discovered to be incorrect. * This is different than the case where fonts are discovered to * be incorrect during initial verification, as such fonts are * Handles to this font held are re-directed to a default font. * This default may not be an ideal substitute buts it better than * crashing This code assumes a PhysicalFont parameter as it doesn't * make sense for a Composite to be "bad". /* We should never reach here, but just in case */ * This encapsulates all the work that needs to be done when a * Font2D is replaced by a different Font2D. /* If we try to replace the font with itself, that won't work, * so pick any alternative physical font .
severe(
"This is bad. No good physicalFonts found.");
/* eliminate references to this font, so it won't be located * by future callers, and will be eligible for GC when all /* Should I be replacing these, or just I just remove * the names from the map? /* some maps don't support this operation. * In this case just give up and remove the entry. /* Deferred initialization of composites shouldn't be * a problem for this case, since a font must have been * initialised to be discovered to be bad. * Some JRE composites on Solaris use two versions of the same * font. The replaced font isn't bad, just "smaller" so there's * no need to make the slot point to the new font. * Since composites have a direct reference to the Font2D (not * via a handle) making this substitution is not safe and could * cause an additional problem and so this substitution is * warranted only when a font is truly "bad" and could cause * a crash. So we now replace it only if its being substituted * with some font other than a fontconfig rank font * Since in practice a substitution will have the same rank * this may never happen, but the code is safer even if its * The only obvious "glitch" from this stems from the current * implementation that when asked for the number of glyphs in a * composite it lies and returns the number in slot 0 because * composite glyphs aren't contiguous. Since we live with that * we can live with the glitch that depending on how it was * initialised a composite may return different values for this. * Fixing the issues with composite glyph ids is tricky as * there are exclusion ranges and unlike other fonts even the * true "numGlyphs" isn't a contiguous range. Likely the only * solution is an API that returns an array of glyph ranges * which takes precedence over the existing API. That might * also need to address excluding ranges which represent a * code point supported by an earlier component. /* This replicate the core logic of findFont2D but operates on * all the locale names. This hasn't been merged into findFont2D to * keep the logic simpler and reduce overhead, since this case is * almost never used. The main case in which it is called is when * a bogus font name is used and we need to check all possible names * before returning the default case. .
info(
"Searching localised font names for:" +
name);
/* If reach here and no match has been located, then if we have * not yet built the map of localeFullNamesToFont for TT fonts, do so * now. This method must be called after all fonts have been loaded. /* First see if its a family name. */ /* If it wasn't a family name, it should be a full name. */ /* We exactly matched the requested style, use it! */ /* The next check is perhaps one * that shouldn't be done. ie if we get this * far we have probably as close a match as we * are going to get. We could load all fonts to * see if somehow some parts of the family are * loaded but not all of it. * This check is commented out for now. /* Supporting "alternate" composite fonts on 2D graphics objects * is accessed by the application by calling methods on the local * GraphicsEnvironment. The overall implementation is described * in one place, here, since otherwise the implementation is spread * around it may be difficult to track. * The methods below call into SunGraphicsEnvironment which creates a * new FontConfiguration instance. The FontConfiguration class, * and its platform sub-classes are updated to take parameters requesting * these behaviours. This is then used to create new composite font * instances. Since this calls the initCompositeFont method in * SunGraphicsEnvironment it performs the same initialization as is * performed normally. There may be some duplication of effort, but * that code is already written to be able to perform properly if called * to duplicate work. The main difference is that if we detect we are * are not placed in the "default" maps but into an AppContext instance. * The font lookup mechanism in java.awt.Font.getFont2D() is also updated * so that look-up for composite fonts will in that case always * do a lookup rather than returning a cached result. * This is inefficient but necessary else singleton java.awt.Font * instances would not retrieve the correct Font2D for the appcontext. * sun.font.FontManager.findFont2D is also updated to that it uses * a name map cache specific to that appcontext. * Getting an AppContext is expensive, so there is a global variable * that records whether these methods have ever been called and can * avoid the expense for almost all applications. Once the correct * CompositeFont is associated with the Font, everything should work * through existing mechanisms. * A special case is that GraphicsEnvironment.getAllFonts() must * return an AppContext specific list. * Calling the methods below is "heavyweight" but it is expected that * these methods will be called very rarely. * If _usingPerAppContextComposites is true, we are in "applet" * (eg browser) enviroment and at least one context has selected * an alternate composite font behaviour. * If _usingAlternateComposites is true, we are not in an "applet" * environment and the (single) application has selected * an alternate composite font behaviour. * - Printing: The implementation delegates logical fonts to an AWT * mechanism which cannot use these alternate configurations. * We can detect that alternate fonts are in use and back-off to 2D, but * that uses outlines. Much of this can be fixed with additional work * but that may have to wait. The results should be correct, just not /* These values are used only if we are running as a standalone * application, as determined by maybeMultiAppContext(); /* This method doesn't check if alternates are selected in this app * context. Its used by the FontMetrics caching code which in such * a case cannot retrieve a cached metrics solely on the basis of * the Font.equals() method since it needs to also check if the Font2D * We also use non-standard composites for Swing native L&F fonts on * Windows. In that case the policy is that the metrics reported are * based solely on the physical font in the first slot which is the * visible java.awt.Font. So in that case the metrics cache which tests * the Font does what we want. In the near future when we expand the GTK * logical font definitions we may need to revisit this if GTK reports * combined metrics instead. For now though this test can be simple. /* Modifies the behaviour of a subsequent call to preferLocaleFonts() * to use Mincho instead of Gothic for dialoginput in JA locales * on windows. Not needed on other platforms. .
info(
"Entered useAlternateFontforJALocales().");
/* Test if re-ordering will have any effect */ /* If there is an existing hashtable, we can drop it. */ .
info(
"Entered preferProportionalFonts().");
/* If no proportional fonts are configured, there's no need /* If there is an existing hashtable, we can drop it. */ /* Keys are used to lookup per-AppContext Hashtables */ /* This method should not be called with "null". * It is the caller's responsibility to ensure that. /* Initialise these objects only once we start to use this API */ /* We want to ensure that this font cannot override existing * installed fonts. Check these conditions : * - family name is not that of an installed font * - full name is not that of an installed font * - family name is not the same as the full name of an installed font * - full name is not the same as the family name of an installed font * The last two of these may initially look odd but the reason is * that (unfortunately) Font constructors do not distinuguish these. * An extreme example of such a problem would be a font which has * family name "Dialog.Plain" and full name of "Dialog". * The one arguably overly stringent restriction here is that if an * application wants to supply a new member of an existing family * It will get rejected. But since the JRE can perform synthetic * styling in many cases its not necessary. * We don't apply the same logic to registered fonts. If apps want * to do this lets assume they have a reason. It won't cause problems /* Checks passed, now register the font */ /* Create the FontFamily and add font to the tables */ /* Remove name cache entries if not using app contexts. * To accommodate a case where code may have registered first a plain * family member and then used it and is now registering a bold family * member, we need to remove all members of the family, so that the * new style can get picked up rather than continuing to synthesise. /* Remove from the name cache all references to the Font2D */ // It may look odd to use TreeMap but its more convenient to the caller. /* First check if we already initialised path dirs */ * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. // Begin: Refactored from SunGraphicsEnviroment. * helper function for registerFonts // REMIND: case compare depends on platform continue;
// skip this font file. * Returns a file name for the physical font represented by this platform * font name. The default implementation tries to obtain the file name * from the font configuration. * Subclasses may override to provide information from other sources. * Return the default font configuration. /* A call to this method should be followed by a call to /* Use lock specific to the font system */ .
info(
"SunGraphicsEnvironment.loadFonts() called");
// this will find all fonts including those already // registered. But we have checks in place to prevent /* Called to register fall back fonts */ // MACOSX begin -- need to access this in subclass * Returns file name for default font, either absolute * or relative as needed by registerFontFile. * Whether registerFontFile expects absolute or relative * Creates this environment's FontConfiguration. * Returns face name for default font, or null if * no face names are used for CompositeFontDescriptors /* Use lock specific to the font system */ // this will find all fonts including those already // registered. But we have checks in place to prevent * This method asks the font configuration API for all platform names * looking up their corresponding file name and registers these fonts. * It also ensures that the fonts are accessible via platform APIs. * The composites themselves are then registered. .
info(
"Initialising composite fonts");
/* No file located, so register using the platform name, /* If platform APIs also need to access the font, add it * to a set to be registered with the platform too. * This may be used to add the parent directory to the X11 * font path if its not already there. See the docs for the * subclass implementation. * This is now mainly for the benefit of X11-based AWT * But for historical reasons, 2D initialisation code * If the fontconfiguration file is properly set up * so that all fonts are mapped to files and all their * appropriate directories are specified, then this * method will be low cost as it will return after * a test that finds a null lookup map. /* Uncomment these two lines to "generate" the XLFD->filename * mappings needed to speed start-up on Solaris. * Augment this with the appendedpathname and the mappings //String platName = platformFontName.replaceAll(" ", "_"); //System.out.println("filename."+platName+"="+fontFileName); /* This registers accumulated paths from the calls to * addFontToPlatformFontPath(..) and any specified by * the font configuration. Rather than registering * the fonts it puts them in a place and form suitable for * the Toolkit to pick up and use if a toolkit is initialised, * and if it uses X11 fonts. /* It would be better eventually to handle this in the * FontConfiguration code which should also remove duplicate slots /* FontConfiguration needs to convey how many fonts it has added * as fallback component fonts which should not affect metrics. * The core component count will be the number of metrics slots. * This does not preclude other mechanisms for adding * fall back component fonts to the composite. * Notifies graphics environment that the logical font configuration * uses the given platform font name. The graphics environment may * use this for platform specific initialization. // REMIND: case compare depends on platform * A GE may verify whether a font file used in a fontconfiguration * exists. If it doesn't then either we may substitute the default * font, or perhaps elide it altogether from the composite font. * This makes some sense on windows where the font file is only * likely to be in one place. But on other OSes, eg Linux, the file * can move around depending. So there we probably don't want to assume * its missing and so won't add it to this list. * If this list - missingFontFiles - is non-null then the composite * font initialisation logic tests to see if a font file is in that * Only one thread should be able to add to this set so we don't * This is for use only within getAllFonts(). * Fonts listed in the fontconfig files for windows were all * on the "deferred" initialisation list. They were registered * either in the course of the application, or in the call to * loadFonts() within getAllFonts(). The fontconfig file specifies * the names of the fonts using the English names. If there's a * different name in the execution locale, then the platform will * report that, and we will construct the font with both names, and * thereby enumerate it twice. This happens for Japanese fonts listed * in the windows fontconfig, when run in the JA locale. The solution * is to rely (in this case) on the platform's font->file mapping to * determine that this name corresponds to a file we already registered. * - we know when we get here all deferred fonts are already initialised * - when we register a font file, we register all fonts in it. * - we know the fontconfig fonts are all in the windows registry * This invocation is not in a privileged block because * all privileged operations (reading files and properties) * was conducted on the creation of the GE * Returns all fonts installed in this environment. /* warning: the number of composite fonts could change dynamically * if applications are allowed to create them. "allfonts" could * Get a list of installed fonts in the requested {@link Locale}. * The list contains the fonts Family Names. * If Locale is null, the default locale is used. * @param requestedLocale, if null the default locale is used. * @return list of installed fonts in the system. // these names are always there and aren't localised /* Platform APIs may be used to get the set of available family * names for the current default locale so long as it is the same * as the start-up system locale, rather than loading all fonts. /* Augment platform names with JRE font family names */ // Add any native font family names here // Provides an aperture to add native font family names to the map /* Really we need only the JRE fonts family names, but there's little * overhead in doing this the easy way by adding all the currently * Default locale can be changed but we need to know the initial locale * as that is what is used by native code. Changing Java default locale * Returns the locale in use when using native code to communicate * with platform APIs. On windows this is known as the "system" locale, * and it is usually the same as the platform locale, but not always, * so this method also checks an implementation property used only * on windows and uses that if set. /* On windows the system locale may be different than the * user locale. This is an unsupported configuration, but * in that case we want to return a dummy locale that will * never cause a match in the usage of this API. This is * important because Windows documents that the family * names of fonts are enumerated using the language of * the system locale. BY returning a dummy locale in that * case we do not use the platform API which would not * return us the names we want. /* Avoid duplicate entries in the pool, and don't close() it, * since this method is called only from within open(). * Seeing a duplicate is most likely to happen if the thread * was interrupted during a read, forcing perhaps repeated * close and open calls and it eventually it ends up pointing /* replace with new font. */ /* lastPoolIndex is updated so that the least recently opened * file will be closed next. /* Need to close the font file outside of the synchronized block, * since its possible some other thread is in an open() call on * this font file, and could be holding its lock and the pool lock. * Releasing the pool lock allows that thread to continue, so it can * then release the lock on this font, allowing the close() call * Also, calling close() is safe because any other thread using * the font we are closing() synchronizes all reading, so we * will not close the file while its in use.