@NotNull public static FontInfo getFontAbleToDisplay( int codePoint, @JdkConstants.FontStyle int style, @NotNull FontPreferences preferences) { boolean tryDefaultFont = true; List<String> fontFamilies = preferences.getEffectiveFontFamilies(); FontInfo result; //noinspection ForLoopReplaceableByForEach for (int i = 0, len = fontFamilies.size(); i < len; ++i) { // avoid foreach, it instantiates ArrayList$Itr, this traversal happens very often final String fontFamily = fontFamilies.get(i); result = doGetFontAbleToDisplay(codePoint, preferences.getSize(fontFamily), style, fontFamily); if (result != null) { return result; } tryDefaultFont &= !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily); } int size = FontPreferences.DEFAULT_FONT_SIZE; if (!fontFamilies.isEmpty()) { size = preferences.getSize(fontFamilies.get(0)); } if (tryDefaultFont) { result = doGetFontAbleToDisplay(codePoint, size, style, FontPreferences.DEFAULT_FONT_NAME); if (result != null) { return result; } } result = doGetFontAbleToDisplay(codePoint, size, style); if (LOG.isDebugEnabled()) { LOG.debug("Fallback font: " + result.getFont().getFontName()); } return result; }
@Nullable private static FontInfo doGetFontAbleToDisplay( int codePoint, int size, @JdkConstants.FontStyle int originalStyle, @NotNull String defaultFontFamily) { synchronized (lock) { @JdkConstants.FontStyle int style = originalStyle; if (Patches.JDK_MAC_FONT_STYLE_DETECTION_WORKAROUND && style > 0 && style < 4) { Pair<String, Integer>[] replacement = ourStyledFontMap.get(defaultFontFamily); if (replacement != null) { defaultFontFamily = replacement[style].first; style = replacement[style].second; } } if (ourSharedKeyInstance.mySize == size && ourSharedKeyInstance.myStyle == style && ourSharedKeyInstance.myFamilyName != null && ourSharedKeyInstance.myFamilyName.equals(defaultFontFamily) && ourSharedDefaultFont != null && (codePoint < 128 || ourSharedDefaultFont.canDisplay(codePoint))) { return ourSharedDefaultFont; } ourSharedKeyInstance.myFamilyName = defaultFontFamily; ourSharedKeyInstance.mySize = size; ourSharedKeyInstance.myStyle = style; FontInfo defaultFont = ourUsedFonts.get(ourSharedKeyInstance); if (defaultFont == null) { defaultFont = new FontInfo(defaultFontFamily, size, style, originalStyle); ourUsedFonts.put(ourSharedKeyInstance, defaultFont); ourSharedKeyInstance = new FontKey("", 0, 0); } ourSharedDefaultFont = defaultFont; if (codePoint < 128 || defaultFont.canDisplay(codePoint)) { return defaultFont; } else { return null; } } }
@NotNull private static FontInfo doGetFontAbleToDisplay( int codePoint, int size, @JdkConstants.FontStyle int style) { synchronized (lock) { if (ourUndisplayableChars.contains(codePoint)) return ourSharedDefaultFont; final Collection<FontInfo> descriptors = ourUsedFonts.values(); for (FontInfo font : descriptors) { if (font.getSize() == size && font.getStyle() == style && font.canDisplay(codePoint)) { return font; } } for (int i = 0; i < ourFontNames.size(); i++) { String name = ourFontNames.get(i); FontInfo font = new FontInfo(name, size, style); if (font.canDisplay(codePoint)) { ourUsedFonts.put(new FontKey(name, size, style), font); ourFontNames.remove(i); return font; } } ourUndisplayableChars.add(codePoint); return ourSharedDefaultFont; } }
@Override public void drawChars( @NotNull Graphics g, @NotNull char[] data, int start, int end, int x, int y, Color color, FontInfo fontInfo) { g.setFont(fontInfo.getFont()); g.setColor(color); g.drawChars(data, start, end - start, x, y); }