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(); } }
PhysicalFont getDelegateFont() { if (delegateFont == null) { SunFontManager fm = SunFontManager.getInstance(); delegateFont = fm.getDefaultPhysicalFont(); } return delegateFont; }
public CharToGlyphMapper getMapper() { if (mapper == null) { if (isBitmapDelegate) { /* we are a delegate */ mapper = new NativeGlyphMapper(this); } else { /* we need to delegate */ SunFontManager fm = SunFontManager.getInstance(); delegateFont = fm.getDefaultPhysicalFont(); mapper = delegateFont.getMapper(); } } return mapper; }
FontStrike createStrike(FontStrikeDesc desc) { if (isBitmapDelegate) { return new NativeStrike(this, desc); } else { if (delegateFont == null) { SunFontManager fm = SunFontManager.getInstance(); delegateFont = fm.getDefaultPhysicalFont(); } /* If no FileFont's are found, delegate font may be * a NativeFont, so we need to avoid recursing here. */ if (delegateFont instanceof NativeFont) { return new NativeStrike((NativeFont) delegateFont, desc); } FontStrike delegate = delegateFont.createStrike(desc); return new DelegateStrike(this, desc, delegate); } }
/* 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; } }
public CompositeFont( String name, String[] compFileNames, String[] compNames, int metricsSlotCnt, int[] exclRanges, int[] maxIndexes, boolean defer, SunFontManager fm) { handle = new Font2DHandle(this); fullName = name; componentFileNames = compFileNames; componentNames = compNames; if (compNames == null) { numSlots = componentFileNames.length; } else { numSlots = componentNames.length; } /* We will limit the number of slots to 254. * We store the slot for a glyph id in a byte and we may use one slot * for an EUDC font, and we may also create a composite * using this composite as a backup for a physical font. * So we want to leave space for the two additional slots. */ numSlots = (numSlots <= 254) ? numSlots : 254; /* Only the first "numMetricsSlots" slots are used for font metrics. * the rest are considered "fallback" slots". */ numMetricsSlots = metricsSlotCnt; exclusionRanges = exclRanges; maxIndices = maxIndexes; /* * See if this is a windows locale which has a system EUDC font. * If so add it as the final fallback component of the composite. * The caller could be responsible for this, but for now it seems * better that it is handled internally to the CompositeFont class. */ if (fm.getEUDCFont() != null) { numSlots++; if (componentNames != null) { componentNames = new String[numSlots]; System.arraycopy(compNames, 0, componentNames, 0, numSlots - 1); componentNames[numSlots - 1] = fm.getEUDCFont().getFontName(null); } if (componentFileNames != null) { componentFileNames = new String[numSlots]; System.arraycopy(compFileNames, 0, componentFileNames, 0, numSlots - 1); } components = new PhysicalFont[numSlots]; components[numSlots - 1] = fm.getEUDCFont(); deferredInitialisation = new boolean[numSlots]; if (defer) { for (int i = 0; i < numSlots - 1; i++) { deferredInitialisation[i] = true; } } } else { components = new PhysicalFont[numSlots]; deferredInitialisation = new boolean[numSlots]; if (defer) { for (int i = 0; i < numSlots; i++) { deferredInitialisation[i] = true; } } } fontRank = Font2D.FONT_CONFIG_RANK; int index = fullName.indexOf('.'); if (index > 0) { familyName = fullName.substring(0, index); /* composites don't call setStyle() as parsing the style * takes place at the same time as parsing the family name. * Do I really have to parse the style from the name? * Need to look into having the caller provide this. */ if (index + 1 < fullName.length()) { String styleStr = fullName.substring(index + 1); if ("plain".equals(styleStr)) { style = Font.PLAIN; } else if ("bold".equals(styleStr)) { style = Font.BOLD; } else if ("italic".equals(styleStr)) { style = Font.ITALIC; } else if ("bolditalic".equals(styleStr)) { style = Font.BOLD | Font.ITALIC; } } } else { familyName = fullName; } }