Skip to content

Commit

Permalink
fix: Thread safety and better resource management for fontloader
Browse files Browse the repository at this point in the history
  • Loading branch information
cvs0 committed Jul 7, 2024
1 parent d71ab89 commit cde8fdb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 73 deletions.
110 changes: 39 additions & 71 deletions src/main/java/net/aoba/gui/font/FontManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.lwjgl.PointerBuffer;
import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.system.MemoryStack;
Expand All @@ -54,11 +57,11 @@ public class FontManager {
private MinecraftClient MC;
private TextRenderer currentFontRenderer;

public HashMap<String, TextRenderer> fontRenderers;
public ConcurrentHashMap<String, TextRenderer> fontRenderers;
public StringSetting fontSetting;

public FontManager() {
fontRenderers = new HashMap<String, TextRenderer>();
fontRenderers = new ConcurrentHashMap<>();
MC = MinecraftClient.getInstance();

fontSetting = new StringSetting("font", "The font that Aoba will use.", "minecraft");
Expand All @@ -72,38 +75,31 @@ public FontManager() {

public void Initialize() {
fontRenderers.put("minecraft", MC.textRenderer);

File fontDirectory = new File(MC.runDirectory + "\\aoba\\fonts\\");
if (fontDirectory.isDirectory()) {
File[] files = fontDirectory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".ttf");
}
});

for (File file : files) {
List<Font.FontFilterPair> list = new ArrayList<Font.FontFilterPair>();
File fontDirectory = new File(MC.runDirectory + File.separator + "aoba" + File.separator + "fonts");
if (fontDirectory.exists() && fontDirectory.isDirectory()) {
File[] files = fontDirectory.listFiles((dir, name) -> name.endsWith(".ttf"));

try {
Font font = LoadTTFFont(file, 12.5f, 2, new TrueTypeFontLoader.Shift(-1, 0), "");
list.add(new Font.FontFilterPair(font, FilterMap.NO_FILTER));
} catch (Exception e) {
e.printStackTrace();
}
if (files != null) {
for (File file : files) {
try {
Font font = LoadTTFFont(file, 12.5f, 2, new TrueTypeFontLoader.Shift(-1, 0), "");
List<Font.FontFilterPair> list = new ArrayList<>();
list.add(new Font.FontFilterPair(font, FilterMap.NO_FILTER));

try (FontStorage storage = new FontStorage(MC.getTextureManager(), Identifier.of("aoba:" + file.getName()))) {
storage.setFonts(list, Set.of());
fontRenderers.put(file.getName().replace(".ttf", ""), new TextRenderer(id -> storage, true));
try (FontStorage storage = new FontStorage(MC.getTextureManager(), Identifier.of("aoba:" + file.getName()))) {
storage.setFonts(list, Set.of());
fontRenderers.put(file.getName().replace(".ttf", ""), new TextRenderer(id -> storage, true));
}
} catch (Exception e) {
System.err.println("Failed to load font: " + file.getName());
e.printStackTrace();
}
}
}
}

Iterator<TextRenderer> newFonts = fontRenderers.values().iterator();
if(newFonts.hasNext()) {
currentFontRenderer = newFonts.next();
}

currentFontRenderer = fontRenderers.values().iterator().next();
}

public TextRenderer GetRenderer() {
Expand All @@ -116,51 +112,23 @@ public void SetRenderer(TextRenderer renderer) {
}

private static Font LoadTTFFont(File location, float size, float oversample, Shift shift, String skip) throws IOException {
TrueTypeFont trueTypeFont = null;
STBTTFontinfo sTBTTFontinfo = null;
ByteBuffer byteBuffer = null;

InputStream inputStream = new FileInputStream(location);
try {
sTBTTFontinfo = STBTTFontinfo.malloc();
byte[] test = inputStream.readAllBytes();
byteBuffer = ByteBuffer.allocateDirect(test.length);
byteBuffer.put(test, 0, test.length);
byteBuffer.flip();

MemoryStack memoryStack = MemoryStack.stackPush();
PointerBuffer pointerBuffer = memoryStack.mallocPointer(1);
FreeTypeUtil.checkFatalError(FreeType.FT_New_Memory_Face(FreeTypeUtil.initialize(), byteBuffer, 0L, pointerBuffer), "Initializing font face");
FT_Face fT_Face = FT_Face.create(pointerBuffer.get());

String string = FreeType.FT_Get_Font_Format(fT_Face);
if (!"TrueType".equals(string)) {
throw new IOException("Font is not in TTF format, was " + string);
}
FreeTypeUtil.checkFatalError(FreeType.FT_Select_Charmap(fT_Face, FreeType.FT_ENCODING_UNICODE), "Find unicode charmap");
trueTypeFont = new TrueTypeFont(byteBuffer, fT_Face, size, oversample, shift.x(),
shift.y(), skip);

} catch (Throwable throwable) {
try {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
}
throw throwable;
} catch (Exception exception) {
if (sTBTTFontinfo != null) {
sTBTTFontinfo.free();
}
MemoryUtil.memFree(byteBuffer);
throw exception;
ByteBuffer byteBuffer = MemoryUtil.memAlloc(Files.readAllBytes(location.toPath()).length);
byteBuffer.put(Files.readAllBytes(location.toPath())).flip();

try (MemoryStack memoryStack = MemoryStack.stackPush()) {
PointerBuffer pointerBuffer = memoryStack.mallocPointer(1);
FreeTypeUtil.checkFatalError(FreeType.FT_New_Memory_Face(FreeTypeUtil.initialize(), byteBuffer, 0L, pointerBuffer), "Initializing font face");
FT_Face fT_Face = FT_Face.create(pointerBuffer.get());

String string = FreeType.FT_Get_Font_Format(fT_Face);
if (!"TrueType".equals(string)) {
throw new IOException("Font is not in TTF format, was " + string);
}
}
inputStream.close();
FreeTypeUtil.checkFatalError(FreeType.FT_Select_Charmap(fT_Face, FreeType.FT_ENCODING_UNICODE), "Find unicode charmap");

return trueTypeFont;
return new TrueTypeFont(byteBuffer, fT_Face, size, oversample, shift.x(), shift.y(), skip);
} finally {
MemoryUtil.memFree(byteBuffer);
}
}
}
3 changes: 2 additions & 1 deletion src/main/java/net/aoba/gui/tabs/HudOptionsTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import net.aoba.Aoba;
import net.aoba.gui.GuiManager;
Expand All @@ -41,7 +42,7 @@ public HudOptionsTab() {
stackPanel.setTop(30);

List<String> fontNames = new ArrayList<String>();
HashMap<String, TextRenderer> fontRenderers = Aoba.getInstance().fontManager.fontRenderers;
ConcurrentHashMap<String, TextRenderer> fontRenderers = Aoba.getInstance().fontManager.fontRenderers;
Set<String> set = fontRenderers.keySet();

for (String s : set) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/aoba/gui/tabs/HudsTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import net.aoba.Aoba;
import net.aoba.gui.GuiManager;
Expand All @@ -45,7 +46,7 @@ public HudsTab(AbstractHud[] abstractHuds) {
List<String> test = new ArrayList<String>();


HashMap<String, TextRenderer> fontRenderers = Aoba.getInstance().fontManager.fontRenderers;
ConcurrentHashMap<String, TextRenderer> fontRenderers = Aoba.getInstance().fontManager.fontRenderers;
Set<String> set = fontRenderers.keySet();

for (String s : set) {
Expand Down

0 comments on commit cde8fdb

Please sign in to comment.