public PhysicalFont getSlotFont(int slot) { /* This is essentially the runtime overhead for deferred font * initialisation: a boolean test on obtaining a slot font, * which will happen per slot, on initialisation of a strike * (as that is the only frequent call site of this method. */ if (deferredInitialisation[slot]) { doDeferredInitialisation(slot); } SunFontManager fm = SunFontManager.getInstance(); try { PhysicalFont font = components[slot]; if (font == null) { try { font = (PhysicalFont) fm.findFont2D(componentNames[slot], style, FontManager.PHYSICAL_FALLBACK); components[slot] = font; } catch (ClassCastException cce) { font = fm.getDefaultPhysicalFont(); } } return font; } catch (Exception e) { return fm.getDefaultPhysicalFont(); } }
/* This is used for deferred initialisation, so that the components of * a logical font are initialised only when the font is used. * This can have a positive impact on start-up of most UI applications. * Note that this technique cannot be used with a TTC font as it * doesn't know which font in the collection is needed. The solution to * this is that the initialisation checks if the returned font is * really the one it wants by comparing the name against the name that * was passed in (if none was passed in then you aren't using a TTC * as you would have to specify the name in such a case). * Assuming there's only two or three fonts in a collection then it * may be sufficient to verify the returned name is the expected one. * But half the time it won't be. However since initialisation of the * TTC will initialise all its components then just do a findFont2D call * to locate the right one. * This code allows for initialisation of each slot on demand. * There are two issues with this. * 1) All metrics slots probably may be initialised anyway as many * apps will query the overall font metrics. However this is not an * absolute requirement * 2) Some font configuration files on Solaris reference two versions * of a TT font: a Latin-1 version, then a Pan-European version. * One from /usr/openwin/lib/X11/fonts/TrueType, the other from * a euro_fonts directory which is symlinked from numerous locations. * This is difficult to avoid because the two do not share XLFDs so * both will be consequently mapped by separate XLFDs needed by AWT. * The difficulty this presents for lazy initialisation is that if * all the components are not mapped at once, the smaller version may * have been used only to be replaced later, and what is the consequence * for a client that displayed the contents of this font already. * After some thought I think this will not be a problem because when * client tries to display a glyph only in the Euro font, the composite * will ask all components of this font for that glyph and will get * the euro one. Subsequent uses will all come from the 100% compatible * euro one. */ private void doDeferredInitialisation(int slot) { if (deferredInitialisation[slot] == false) { return; } /* Synchronize on FontManager so that is the global lock * to update its static set of deferred fonts. * This global lock is rarely likely to be an issue as there * are only going to be a few calls into this code. */ SunFontManager fm = SunFontManager.getInstance(); synchronized (fm) { if (componentNames == null) { componentNames = new String[numSlots]; } if (components[slot] == null) { /* Warning: it is possible that the returned component is * not derived from the file name argument, this can happen if: * - the file can't be found * - the file has a bad font * - the font in the file is superseded by a more complete one * This should not be a problem for composite font as it will * make no further use of this file, but code debuggers/ * maintainers need to be conscious of this possibility. */ if (componentFileNames != null && componentFileNames[slot] != null) { components[slot] = fm.initialiseDeferredFont(componentFileNames[slot]); } if (components[slot] == null) { components[slot] = fm.getDefaultPhysicalFont(); } String name = components[slot].getFontName(null); if (componentNames[slot] == null) { componentNames[slot] = name; } else if (!componentNames[slot].equalsIgnoreCase(name)) { /* If a component specifies the file with a bad font, * the corresponding slot will be initialized by * default physical font. In such case findFont2D may * return composite font which cannot be casted to * physical font. */ try { components[slot] = (PhysicalFont) fm.findFont2D(componentNames[slot], style, FontManager.PHYSICAL_FALLBACK); } catch (ClassCastException cce) { /* Assign default physical font to the slot */ components[slot] = fm.getDefaultPhysicalFont(); } } } deferredInitialisation[slot] = false; } }