faster font family loading & lazy font family population

1. NSFont.familyName is faster than loading allFamilyNames
2. Prebuilt list of system fonts
3. Cleanup San Francisco family loading
4. Avoid calling expensive native getWidth on font when creating font family, load styles only when they would be used.
This commit is contained in:
Dennis Ushakov
2019-08-07 12:13:57 +03:00
committed by alexey.ushakov@jetbrains.com
parent 43b37499de
commit d9eba7b0b6
5 changed files with 80 additions and 61 deletions

View File

@@ -36,7 +36,7 @@ import java.awt.geom.Rectangle2D;
// For some reason the JNI IsInstanceOf was not working correctly
// so we are checking the class specifically. If we subclass this
// we need to modify the native code in CFontWrapper.m
public final class CFont extends PhysicalFont implements FontSubstitution {
public final class CFont extends PhysicalFont implements FontSubstitution, FontWithDerivedItalic {
/* CFontStrike doesn't call these methods so they are unimplemented.
* They are here to meet the requirements of PhysicalFont, needed
@@ -266,4 +266,8 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
", familyName: " + familyName + ", style: " + style +
" } aka: " + super.toString();
}
public Font2D createItalic() {
return this.createItalicVariant(true);
}
}

View File

@@ -185,37 +185,6 @@ public final class CFontManager extends SunFontManager {
registerGenericFont(font);
}
void registerItalicDerived() {
FontFamily[] famArr = FontFamily.getAllFontFamilies();
for (int i=0; i<famArr.length; i++) {
FontFamily family = famArr[i];
Font2D f2dPlain = family.getFont(Font.PLAIN);
if (f2dPlain != null && !(f2dPlain instanceof CFont)) continue;
Font2D f2dBold = family.getFont(Font.BOLD);
if (f2dBold != null && !(f2dBold instanceof CFont)) continue;
Font2D f2dItalic = family.getFont(Font.ITALIC);
if (f2dItalic != null && !(f2dItalic instanceof CFont)) continue;
Font2D f2dBoldItalic = family.getFont(Font.BOLD|Font.ITALIC);
if (f2dBoldItalic != null && !(f2dBoldItalic instanceof CFont)) continue;
CFont plain = (CFont)f2dPlain;
CFont bold = (CFont)f2dBold;
CFont italic = (CFont)f2dItalic;
CFont boldItalic = (CFont)f2dBoldItalic;
if (bold == null) bold = plain;
if (plain == null && bold == null) continue;
if (italic != null && boldItalic != null) continue;
if (plain != null && italic == null) {
registerGenericFont(plain.createItalicVariant(true), true);
}
if (bold != null && boldItalic == null) {
registerGenericFont(bold.createItalicVariant(true), true);
}
}
}
Object waitForFontsToBeLoaded = new Object();
private boolean loadedAllFonts = false;
@@ -230,7 +199,6 @@ public final class CFontManager extends SunFontManager {
public Object run() {
if (!loadedAllFonts) {
loadNativeFonts();
registerItalicDerived();
loadedAllFonts = true;
}
return null;

View File

@@ -1284,35 +1284,29 @@ GetFilteredFonts()
{
if (sFilteredFonts == nil) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSUInteger fontCount = [[fontManager availableFonts] count];
NSMutableArray *allFonts = [[NSMutableArray alloc] initWithCapacity:fontCount];
NSArray<NSString *> *availableFonts= [fontManager availableFonts];
NSUInteger fontCount = [availableFonts count];
NSMutableArray* allFonts = [NSMutableArray arrayWithCapacity:fontCount];
NSMutableDictionary* fontFamilyTable = [[NSMutableDictionary alloc] initWithCapacity:fontCount];
NSArray *allFamilies = [fontManager availableFontFamilies];
NSUInteger familyCount = [allFamilies count];
NSUInteger familyIndex;
for (familyIndex = 0; familyIndex < familyCount; familyIndex++) {
NSString *family = [allFamilies objectAtIndex:familyIndex];
if ((family == nil) || [family characterAtIndex:0] == '.') {
continue;
}
NSArray *fontFaces = [fontManager availableMembersOfFontFamily:family];
NSUInteger faceCount = [fontFaces count];
NSUInteger faceIndex;
for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
NSString* face = [[fontFaces objectAtIndex:faceIndex] objectAtIndex:0];
if (face != nil) {
[allFonts addObject:face];
[fontFamilyTable setObject:family forKey:face];
NSMutableDictionary* fontTable = [[NSMutableDictionary alloc] initWithCapacity:fontCount];
NSDictionary* prebuilt = prebuiltFamilyNames();
for (NSString *face in availableFonts) {
NSString* familyName = [prebuilt objectForKey:face];
if (!familyName) {
NSFont* font = [NSFont fontWithName:face size:NSFont.systemFontSize];
if(font && font.familyName) {
familyName = font.familyName;
// NSLog(@"@\"%@\" : @\"%@\",", face, familyName);
}
}
if (!isVisibleFamily(familyName)) {
continue;
}
[allFonts addObject:face];
[fontFamilyTable setObject:familyName forKey:face];
}
/*
* JavaFX registers these fonts and so JDK needs to do so as well.
* If this isn't done we will have mis-matched rendering, since

View File

@@ -28,7 +28,9 @@ package sun.font;
import java.io.File;
import java.awt.Font;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Locale;
@@ -44,6 +46,8 @@ public class FontFamily {
protected Font2D bold;
protected Font2D italic;
protected Font2D bolditalic;
private final List<FontAndStyle> fontSequence = new ArrayList<FontAndStyle>();
private boolean initialized = false;
protected boolean logicalFont = false;
protected int familyRank;
@@ -66,6 +70,7 @@ public class FontFamily {
if (family == null) {
return;
}
family.ensureFontsLoaded();
if (family.plain == font2D) {
family.plain = null;
}
@@ -244,6 +249,38 @@ public class FontFamily {
}
FontUtilities.logInfo(msg);
}
synchronized (fontSequence) {
if (initialized) {
doSetFont(font, style);
return;
}
fontSequence.add(new FontAndStyle(font, style));
}
}
private void ensureFontsLoaded() {
synchronized (fontSequence) {
if (initialized) {
return;
}
for (FontAndStyle fontAndStyle : fontSequence) {
doSetFont(fontAndStyle.font, fontAndStyle.style);
}
if (italic == null && plain instanceof FontWithDerivedItalic) {
italic = ((FontWithDerivedItalic)plain).createItalic();
}
if (bolditalic == null) {
Font2D boldItalicPrototype = bold != null ? bold : plain;
if (boldItalicPrototype instanceof FontWithDerivedItalic) {
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalic();
}
}
fontSequence.clear();
initialized = true;
}
}
private void doSetFont(Font2D font, int style) {
/* Allow a lower-rank font only if its a file font
* from the exact same source as any previous font.
*/
@@ -289,7 +326,7 @@ public class FontFamily {
}
public Font2D getFontWithExactStyleMatch(int style) {
ensureFontsLoaded();
switch (style) {
case Font.PLAIN:
@@ -318,7 +355,7 @@ public class FontFamily {
* same location.
*/
public Font2D getFont(int style) {
ensureFontsLoaded();
switch (style) {
case Font.PLAIN:
@@ -366,7 +403,7 @@ public class FontFamily {
* it might as well be from the same family.
*/
Font2D getClosestStyle(int style) {
ensureFontsLoaded();
switch (style) {
/* if you ask for a plain font try to return a non-italic one,
* then a italic one, finally a bold italic one */
@@ -443,8 +480,19 @@ public class FontFamily {
" plain="+plain+
" bold=" + bold +
" italic=" + italic +
" bolditalic=" + bolditalic;
" bolditalic=" + bolditalic +
" initialized=" + initialized;
}
private static class FontAndStyle {
private final Font2D font;
private final int style;
private FontAndStyle(Font2D inFont, int inStyle) {
font = inFont;
style = inStyle;
}
}
}

View File

@@ -0,0 +1,5 @@
package sun.font;
interface FontWithDerivedItalic {
Font2D createItalic();
}