mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Optimize font loading to happen on startup without blocking UI thread any more than necessary
This commit is contained in:
@@ -79,7 +79,10 @@ public class Forge implements ApplicationListener {
|
||||
public void run() {
|
||||
FModel.initialize(splashScreen.getProgressBar());
|
||||
|
||||
splashScreen.getProgressBar().setDescription("Finishing startup...");
|
||||
splashScreen.getProgressBar().setDescription("Loading fonts");
|
||||
FSkinFont.preloadAll();
|
||||
|
||||
splashScreen.getProgressBar().setDescription("Finishing startup");
|
||||
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -46,7 +46,6 @@ import forge.sound.IAudioClip;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.ThreadUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.WaitRunnable;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
@@ -79,7 +78,7 @@ public class GuiMobile implements IGuiBase {
|
||||
|
||||
@Override
|
||||
public boolean isGuiThread() {
|
||||
return !ThreadUtil.isGameThread();
|
||||
return Thread.currentThread().getName().startsWith("LWJGL");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,21 +8,22 @@ import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.BitmapFontData;
|
||||
import com.badlogic.gdx.graphics.g2d.PixmapPacker;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.util.Utils;
|
||||
|
||||
public class FSkinFont {
|
||||
public static final int MIN_FONT_SIZE = Math.round(8 / Utils.MAX_RATIO);
|
||||
public static final int MAX_FONT_SIZE = Math.round(72 / Utils.MAX_RATIO);
|
||||
|
||||
private static final String TTF_FILE = "font1.ttf";
|
||||
private static final Map<Integer, FSkinFont> fonts = new HashMap<Integer, FSkinFont>();
|
||||
private static final int FONT_PAGE_SIZE = 256;
|
||||
private static final int MAX_FONT_SIZE = 72; //don't generate fonts larger than this, use scaling instead
|
||||
|
||||
public static FSkinFont get(final int size0) {
|
||||
FSkinFont skinFont = fonts.get(size0);
|
||||
@@ -43,6 +44,13 @@ public class FSkinFont {
|
||||
}
|
||||
}
|
||||
|
||||
//pre-load all supported font sizes
|
||||
public static void preloadAll() {
|
||||
for (int size = MIN_FONT_SIZE; size <= MAX_FONT_SIZE; size++) {
|
||||
get(size);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateAll() {
|
||||
for (FSkinFont skinFont : fonts.values()) {
|
||||
skinFont.updateFont();
|
||||
@@ -66,70 +74,76 @@ public class FSkinFont {
|
||||
}
|
||||
|
||||
private void updateFont() {
|
||||
float scale = 1;
|
||||
int fontSize = (int)Utils.scaleMax(size);
|
||||
try {
|
||||
if (fontSize > MAX_FONT_SIZE) { //scale if larger than max font size
|
||||
scale = (float)fontSize / (float)MAX_FONT_SIZE;
|
||||
fontSize = MAX_FONT_SIZE;
|
||||
}
|
||||
String fontName = "f" + fontSize;
|
||||
FileHandle fontFile = Gdx.files.absolute(FSkin.getFontDir() + fontName + ".fnt");
|
||||
if (fontFile.exists()) {
|
||||
font = new BitmapFont(fontFile);
|
||||
}
|
||||
else {
|
||||
FileHandle ttfFile = Gdx.files.absolute(FSkin.getDir() + TTF_FILE);
|
||||
font = generateFont(ttfFile, fontName, fontSize);
|
||||
}
|
||||
String fontName = "f" + fontSize;
|
||||
FileHandle fontFile = Gdx.files.absolute(FSkin.getFontDir() + fontName + ".fnt");
|
||||
if (fontFile.exists()) {
|
||||
final BitmapFontData data = new BitmapFontData(fontFile, false);
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() { //font must be initialized on UI thread
|
||||
font = new BitmapFont(data, (TextureRegion)null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (font == null) {
|
||||
font = new BitmapFont(); //use scaled default font as fallback
|
||||
scale = (float)fontSize / 15; //default font has size 15
|
||||
}
|
||||
font.setUseIntegerPositions(true); //prevent parts of text getting cut off at times
|
||||
if (scale != 1) {
|
||||
font.setScale(scale);
|
||||
else {
|
||||
FileHandle ttfFile = Gdx.files.absolute(FSkin.getDir() + TTF_FILE);
|
||||
generateFont(ttfFile, fontName, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
private BitmapFont generateFont(FileHandle ttfFile, String fontName, int fontSize) {
|
||||
if (!ttfFile.exists()) { return null; }
|
||||
private void generateFont(final FileHandle ttfFile, final String fontName, final int fontSize) {
|
||||
if (!ttfFile.exists()) { return; }
|
||||
|
||||
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(ttfFile);
|
||||
final FreeTypeFontGenerator generator = new FreeTypeFontGenerator(ttfFile);
|
||||
|
||||
PixmapPacker packer = new PixmapPacker(FONT_PAGE_SIZE, FONT_PAGE_SIZE, Pixmap.Format.RGBA8888, 2, false);
|
||||
FreeTypeFontGenerator.FreeTypeBitmapFontData fontData = generator.generateData(fontSize, FreeTypeFontGenerator.DEFAULT_CHARS, false, packer);
|
||||
Array<PixmapPacker.Page> pages = packer.getPages();
|
||||
TextureRegion[] texRegions = new TextureRegion[pages.size];
|
||||
for (int i=0; i<pages.size; i++) {
|
||||
PixmapPacker.Page p = pages.get(i);
|
||||
Texture texture = new Texture(new PixmapTextureData(p.getPixmap(), p.getPixmap().getFormat(), false, false)) {
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
getTextureData().consumePixmap().dispose();
|
||||
}
|
||||
};
|
||||
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||
texRegions[i] = new TextureRegion(texture);
|
||||
//approximate optimal page size
|
||||
int pageSize;
|
||||
if (fontSize >= 28) {
|
||||
pageSize = 256;
|
||||
}
|
||||
else {
|
||||
pageSize = 128;
|
||||
}
|
||||
|
||||
BitmapFont font = new BitmapFont(fontData, texRegions, false);
|
||||
//only generate images for characters that could be used by Forge
|
||||
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\"!?'.,;:()[]{}<>|/@\\^$-%+=#_&*";
|
||||
|
||||
//create .fnt and .png files for font
|
||||
FileHandle fontFile = Gdx.files.absolute(FSkin.getFontDir() + fontName + ".fnt");
|
||||
FileHandle pixmapDir = Gdx.files.absolute(FSkin.getFontDir());
|
||||
BitmapFontWriter.setOutputFormat(BitmapFontWriter.OutputFormat.Text);
|
||||
final PixmapPacker packer = new PixmapPacker(pageSize, pageSize, Pixmap.Format.RGBA8888, 2, false);
|
||||
final FreeTypeFontGenerator.FreeTypeBitmapFontData fontData = generator.generateData(fontSize, chars, false, packer);
|
||||
final Array<PixmapPacker.Page> pages = packer.getPages();
|
||||
|
||||
String[] pageRefs = BitmapFontWriter.writePixmaps(packer.getPages(), pixmapDir, fontName);
|
||||
BitmapFontWriter.writeFont(font.getData(), pageRefs, fontFile, new BitmapFontWriter.FontInfo(fontName, fontSize), 1, 1);
|
||||
//finish generating font on UI thread
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TextureRegion[] textureRegions = new TextureRegion[pages.size];
|
||||
for (int i = 0; i < pages.size; i++) {
|
||||
PixmapPacker.Page p = pages.get(i);
|
||||
Texture texture = new Texture(new PixmapTextureData(p.getPixmap(), p.getPixmap().getFormat(), false, false)) {
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
getTextureData().consumePixmap().dispose();
|
||||
}
|
||||
};
|
||||
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||
textureRegions[i] = new TextureRegion(texture);
|
||||
}
|
||||
|
||||
generator.dispose();
|
||||
packer.dispose();
|
||||
return font;
|
||||
font = new BitmapFont(fontData, textureRegions, true);
|
||||
|
||||
//create .fnt and .png files for font
|
||||
FileHandle fontFile = Gdx.files.absolute(FSkin.getFontDir() + fontName + ".fnt");
|
||||
FileHandle pixmapDir = Gdx.files.absolute(FSkin.getFontDir());
|
||||
BitmapFontWriter.setOutputFormat(BitmapFontWriter.OutputFormat.Text);
|
||||
|
||||
String[] pageRefs = BitmapFontWriter.writePixmaps(packer.getPages(), pixmapDir, fontName);
|
||||
BitmapFontWriter.writeFont(font.getData(), pageRefs, fontFile, new BitmapFontWriter.FontInfo(fontName, fontSize), 1, 1);
|
||||
|
||||
generator.dispose();
|
||||
packer.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user