More work on the font system

This commit is contained in:
Speiger 2024-07-25 20:39:38 +02:00
parent 0139086858
commit 62b91f0f1d
15 changed files with 2148 additions and 1940 deletions

View File

@ -6,15 +6,20 @@ import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.google.gson.JsonObject;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.GlythBaker; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.GlythBaker;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider; import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider;
import speiger.src.coreengine.rendering.gui.font.providers.STBTrueTypeProvider; import speiger.src.coreengine.rendering.gui.font.providers.STBTrueTypeProvider;
import speiger.src.coreengine.rendering.guiOld.renderer.provider.BitmapFontProvider;
import speiger.src.coreengine.rendering.input.devices.FileDrop; import speiger.src.coreengine.rendering.input.devices.FileDrop;
import speiger.src.coreengine.rendering.input.devices.Joystick; import speiger.src.coreengine.rendering.input.devices.Joystick;
import speiger.src.coreengine.rendering.input.devices.Keyboard; import speiger.src.coreengine.rendering.input.devices.Keyboard;
@ -62,18 +67,23 @@ public class NewInputTest {
shaderTest.register(); shaderTest.register();
assets.addListener(GLStateTracker.instance().shaders); assets.addListener(GLStateTracker.instance().shaders);
assets.addListener(GLStateTracker.TEXTURE_TRACKER); assets.addListener(GLStateTracker.TEXTURE_TRACKER);
assets.reload(Runnable::run, Runnable::run); assets.reload();
System.out.println("Testing: "+GL.getCapabilities().OpenGL46); System.out.println("Testing: "+GL.getCapabilities().OpenGL46);
System.out.println("Testing: "+Integer.divideUnsigned(-1, 255));
IFontProvider provider = STBTrueTypeProvider.create(AssetLocation.of("font/Roboto-Medium.ttf"), assets); IFontProvider provider = STBTrueTypeProvider.create(AssetLocation.of("font/roboto/font.json"), assets);
BitmapFontProvider bit = loadProvider(AssetLocation.of("font/roboto.json"), 18.5F);
DynamicTexture texture = new DynamicTexture(512, 512, DynamicTexture.DEFAULT_PARAMETERS); int size = 512;
texture.fill(0, 0, 512, 512, -1); int half = size >> 1;
texture.fill(0, 0, 256, 256, 255, 0, 0, 255);
texture.fill(256, 0, 256, 256, 0, 255, 0, 255); DynamicTexture texture = new DynamicTexture(size, size, DynamicTexture.DEFAULT_PARAMETERS);
texture.fill(256, 256, 256, 256, 255, 0, 0, 255); texture.fill(0, 0, size, size, -1);
texture.fill(0, 256, 256, 256, 0, 0, 255, 255); texture.fill(0, 0, half, half, 255, 0, 0, 255);
texture.fill(half, 0, half, half, 0, 255, 0, 255);
texture.fill(half, half, half, half, 255, 0, 0, 255);
texture.fill(0, half, half, half, 0, 0, 255, 255);
texture.process(true); texture.process(true);
window.visible(true); window.visible(true);
@ -81,23 +91,25 @@ public class NewInputTest {
if(T.key() == GLFW.GLFW_KEY_T) { if(T.key() == GLFW.GLFW_KEY_T) {
T.cancel(); T.cancel();
texture.bind(); texture.bind();
Drawable drawable = new Drawable(GLTextureFormat.RGBA, 256, 256); Drawable drawable = new Drawable(GLTextureFormat.RGBA, half, half);
drawable.fill(0, 0, 256, 256, 255, 255, 0, 255); drawable.fill(0, 0, half, half, 255, 255, 0, 255);
drawable.upload(192, 192, 64, 64, 128, 128); drawable.upload(192, 192, 64, 64, 128, 128);
drawable.close(); drawable.close();
} }
else if(T.key() == GLFW.GLFW_KEY_Z) { else if(T.key() == GLFW.GLFW_KEY_Z) {
T.cancel(); T.cancel();
texture.bind(); texture.bind();
provider.glythData("C".codePointAt(0), false).bake(new GlythBaker() { GlythData data = provider.glythData("C".codePointAt(0), 0);
data.bake(new GlythBaker() {
@Override @Override
public Glyth bake(IGlythSheetInfo info) { public Glyth bake(IGlythSheetInfo info) {
int width = info.width(); int width = info.width();
int height = info.height(); int height = info.height();
info.upload(256 - (width >> 2), 256 - (height >> 2)); info.upload(half - (width >> 2), half - (height >> 2));
return null; return null;
} }
}); });
System.out.println("Testing: "+data.advance()+", "+bit.getCharacter("C".codePointAt(0), false).getXAdvance());
} }
}); });
@ -132,6 +144,17 @@ public class NewInputTest {
manager.destroy(); manager.destroy();
} }
private BitmapFontProvider loadProvider(AssetLocation location, float desiredSize)
{
try(IAsset asset = assets.getAsset(location))
{
JsonObject obj = asset.json();
return BitmapFontProvider.load(obj, desiredSize, null);
}
catch(Exception e) { e.printStackTrace(); }
return null;
}
public static class TestShader extends SimpleShader { public static class TestShader extends SimpleShader {
public TextureUniform texture = uniforms.addTexture("texture", 0); public TextureUniform texture = uniforms.addTexture("texture", 0);
public TestShader(IAssetProvider provider) { public TestShader(IAssetProvider provider) {

View File

@ -42,10 +42,18 @@ public class AssetManager implements ICloseableAssetProvider
return reloadAssets(packages).reloadSelective(offthread, syncer, listeners); return reloadAssets(packages).reloadSelective(offthread, syncer, listeners);
} }
public AssetManager reload() {
return reload(Runnable::run, Runnable::run);
}
public AssetManager reload(Executor offthread, Executor syncer) { public AssetManager reload(Executor offthread, Executor syncer) {
return reloadSelective(offthread, syncer, listeners); return reloadSelective(offthread, syncer, listeners);
} }
public AssetManager reloadSelective(List<IReloadableAsset> listeners) {
return reloadSelective(Runnable::run, Runnable::run, listeners);
}
public AssetManager reloadSelective(Executor offthread, Executor syncer, List<IReloadableAsset> listeners) { public AssetManager reloadSelective(Executor offthread, Executor syncer, List<IReloadableAsset> listeners) {
PackReloadingTask.reload(provider, listeners, offthread, syncer).join(); PackReloadingTask.reload(provider, listeners, offthread, syncer).join();
return this; return this;

View File

@ -4,63 +4,68 @@ import java.util.List;
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap; import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.GlythBaker;
import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider; import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider;
public class FontGroup { public class FontGroup {
private static final int BOLD_FLAG = 1<<31;
private static final int TEXTURE_SIZE = 2048;
AssetLocation locations; AssetLocation locations;
List<IFontProvider> providers; List<IFontProvider> providers;
Int2ObjectMap<Glyth> bakedGlyths = new Int2ObjectOpenHashMap<>(); GlythBaker baker;
Int2ObjectMap<GlythData> dataGlyths = new Int2ObjectOpenHashMap<>(); StyledFont[] cache = new StyledFont[] {new StyledFont(0), new StyledFont(1), new StyledFont(2), new StyledFont(3)};
List<FontTexture> textures = new ObjectArrayList<>();
public FontGroup(AssetLocation locations, List<IFontProvider> providers) { public FontGroup(AssetLocation locations, List<IFontProvider> providers, GlythBaker baker) {
this.locations = locations; this.locations = locations;
this.providers = providers; this.providers = providers;
this.baker = baker;
} }
public GlythData data(int codepoint, boolean bold) { public GlythData data(int codepoint, int style) {
return dataGlyths.computeIfAbsent(codepoint | (bold ? 0 : BOLD_FLAG), this::compute); return cache[style & 0x3].data(codepoint);
} }
public Glyth glyth(int codepoint, boolean bold) { public Glyth glyth(int codepoint, int style) {
return bakedGlyths.computeIfAbsent(codepoint | (bold ? 0 : BOLD_FLAG), this::bake); return cache[style & 0x3].glyth(codepoint);
} }
private GlythData compute(int codepoint) { public void close() {
boolean bold = (codepoint & BOLD_FLAG) != 0; providers.forEach(IFontProvider::close);
codepoint &= ~BOLD_FLAG; providers.clear();
for(int i = 0,m=providers.size();i<m;i++) { }
GlythData data = providers.get(i).glythData(codepoint, bold);
if(data != null) return data; private class StyledFont {
final int style;
Int2ObjectMap<Glyth> bakedGlyths = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<GlythData> dataGlyths = new Int2ObjectOpenHashMap<>();
public StyledFont(int style) {
this.style = style;
} }
return null;
} public GlythData data(int codepoint) {
return dataGlyths.computeIfAbsent(codepoint, this::compute);
private Glyth bake(int codepoint) {
boolean bold = (codepoint & BOLD_FLAG) != 0;
codepoint &= ~BOLD_FLAG;
for(int i = 0,m=providers.size();i<m;i++) {
GlythData data = providers.get(i).glythData(codepoint, bold);
if(data != null) return data.bake(this::stitch);
} }
return null;
} public Glyth glyth(int codepoint) {
return bakedGlyths.computeIfAbsent(codepoint, this::bake);
private Glyth stitch(IGlythSheetInfo info) { }
for(int i = 0,m=textures.size();i<m;i++) {
Glyth glyth = textures.get(i).build(info); private GlythData compute(int codepoint) {
if(glyth != null) return glyth; for(int i = 0,m=providers.size();i<m;i++) {
GlythData data = providers.get(i).glythData(codepoint, style);
if(data != null) return data;
}
return null;
}
private Glyth bake(int codepoint) {
for(int i = 0,m=providers.size();i<m;i++) {
GlythData data = providers.get(i).glythData(codepoint, style);
if(data != null) return data.bake(baker);
}
return null;
} }
FontTexture texture = new FontTexture(TEXTURE_SIZE, info.isColored());
textures.add(texture);
Glyth glyth = texture.build(info);
return glyth;
} }
} }

View File

@ -1,5 +1,49 @@
package speiger.src.coreengine.rendering.gui.font; package speiger.src.coreengine.rendering.gui.font;
public class FontManager { import java.util.List;
import java.util.Map;
import com.google.gson.JsonObject;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.base.SteppedReloadableAsset;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, List<JsonObject>>> {
private static final int TEXTURE_SIZE = 2048;
List<FontTexture> textures = new ObjectArrayList<>();
@Override
public String getName() { return null; }
@Override
public void destroy() {
}
@Override
protected Map<AssetLocation, List<JsonObject>> prepare(IAssetProvider provider) {
return null;
}
@Override
protected void apply(Map<AssetLocation, List<JsonObject>> value, IAssetProvider provider) {
}
private Glyth stitch(IGlythSheetInfo info) {
for(int i = 0,m=textures.size();i<m;i++) {
Glyth glyth = textures.get(i).build(info);
if(glyth != null) return glyth;
}
FontTexture texture = new FontTexture(TEXTURE_SIZE, info.isColored());
textures.add(texture);
Glyth glyth = texture.build(info);
return glyth;
}
} }

View File

@ -1,3 +1,6 @@
package speiger.src.coreengine.rendering.gui.font.glyth; package speiger.src.coreengine.rendering.gui.font.glyth;
public record Glyth(int texture, float minU, float minV, float maxU, float maxV) {} public record Glyth(int texture, float minU, float minV, float maxU, float maxV) {
public static final Glyth EMPTY = new Glyth(-1, 0, 0, 0, 0);
}

View File

@ -2,8 +2,15 @@ package speiger.src.coreengine.rendering.gui.font.glyth;
public interface GlythData { public interface GlythData {
public float advance(); public float advance();
public default float shadowOffset() { return 1F; }
public Glyth bake(GlythBaker baker); public Glyth bake(GlythBaker baker);
public static record EmptyGlythData(float advance) implements GlythData {
@Override
public Glyth bake(GlythBaker baker) { return Glyth.EMPTY; }
}
public static interface GlythBaker { public static interface GlythBaker {
Glyth bake(IGlythSheetInfo info); Glyth bake(IGlythSheetInfo info);
} }

View File

@ -0,0 +1,38 @@
package speiger.src.coreengine.rendering.gui.font.providers;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData;
public class BitmapProivder implements IFontProvider {
@Override
public GlythData glythData(int codepoint, int style) {
return null;
}
@Override
public void close() {
}
private static class BitmapGlyth implements GlythData {
int minX;
int minY;
int maxX;
int maxY;
int glyth;
@Override
public float advance() {
return 0;
}
@Override
public Glyth bake(GlythBaker baker) {
return null;
}
}
}

View File

@ -3,7 +3,13 @@ package speiger.src.coreengine.rendering.gui.font.providers;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData;
public interface IFontProvider extends AutoCloseable { public interface IFontProvider extends AutoCloseable {
public GlythData glythData(int codepoint, boolean bold); public static final int REGULAR = 0;
public static final int BOLD = 1;
public static final int ITALIC = 2;
public static final int ITALIC_BOLD = 3;
public GlythData glythData(int codepoint, int style);
@Override @Override
void close(); void close();
} }

View File

@ -8,6 +8,8 @@ import org.lwjgl.stb.STBTruetype;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.google.gson.JsonObject;
import speiger.src.collections.ints.sets.IntOpenHashSet; import speiger.src.collections.ints.sets.IntOpenHashSet;
import speiger.src.collections.ints.sets.IntSet; import speiger.src.collections.ints.sets.IntSet;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
@ -17,33 +19,51 @@ import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.gui.font.FontTexture; import speiger.src.coreengine.rendering.gui.font.FontTexture;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.EmptyGlythData;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.textures.custom.Drawable; import speiger.src.coreengine.rendering.textures.custom.Drawable;
import speiger.src.coreengine.utils.helpers.JsonUtil;
public class STBTrueTypeProvider implements IFontProvider { public class STBTrueTypeProvider implements IFontProvider {
long data; TrueTypeInstance[] instances;
STBTTFontinfo info;
IntSet skip = new IntOpenHashSet();
float oversample;
float xOff;
float yOff;
float pointScale;
float ascent;
public STBTrueTypeProvider(long data, STBTTFontinfo info, float size, float oversample, float xOff, float yOff, String skip) { public STBTrueTypeProvider(TrueTypeInstance[] instances) {
this.data = data; this.instances = instances;
this.info = info;
skip.codePoints().forEach(this.skip::add);
this.oversample = oversample;
this.xOff = xOff;
this.yOff = yOff;
pointScale = STBTruetype.stbtt_ScaleForPixelHeight(info, size * oversample);
int[] ascent = new int[1];
STBTruetype.stbtt_GetFontVMetrics(info, ascent, new int[1], new int[1]);
this.ascent = pointScale * ascent[0];
} }
public static IFontProvider create(AssetLocation location, IAssetProvider provider) { public static IFontProvider create(AssetLocation location, IAssetProvider provider) {
try(IAsset asset = provider.getAsset(location)) {
return create(asset.json(), provider);
}
catch(Exception e) { e.printStackTrace(); }
return null;
}
public static IFontProvider create(JsonObject data, IAssetProvider provider) {
TrueTypeInstance[] instances = new TrueTypeInstance[4];
instances[0] = create(0, data.getAsJsonObject("regular"), provider);
if(instances[0] == null) return null;
instances[1] = create(1, data.getAsJsonObject("bold"), provider);
instances[2] = create(2, data.getAsJsonObject("italic"), provider);
instances[3] = create(3, data.getAsJsonObject("bold_italic"), provider);
return new STBTrueTypeProvider(instances);
}
private static TrueTypeInstance create(int style, JsonObject obj, IAssetProvider provider) {
if(obj == null || !obj.has("file")) return null;
AssetLocation location = AssetLocation.of(obj.get("file").getAsString());
float size = JsonUtil.getOrDefault(obj, "size", 24F);
float oversample = JsonUtil.getOrDefault(obj, "oversample", 1F);
float shadowOffset = JsonUtil.getOrDefault(obj, "shadowOffset", 1F);
float xOff = 0;
float yOff = 0;
StringBuilder builder = new StringBuilder();
JsonObject shift = obj.getAsJsonObject("offset");
if(shift != null) {
xOff = JsonUtil.getOrDefault(shift, "x", 0);
yOff = JsonUtil.getOrDefault(shift, "y", 0);
}
JsonUtil.iterateValues(obj.get("skip"), T -> builder.append(T.getAsString()));
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE); ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
STBTTFontinfo info = STBTTFontinfo.create(); STBTTFontinfo info = STBTTFontinfo.create();
@ -53,7 +73,7 @@ public class STBTrueTypeProvider implements IFontProvider {
info.free(); info.free();
return null; return null;
} }
return new STBTrueTypeProvider(MemoryUtil.memAddress(buffer), info, 10.2F, 24F, 0, 0, ""); return new TrueTypeInstance(style, MemoryUtil.memAddress(buffer), info, size, oversample, xOff, yOff, shadowOffset, builder.toString());
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -61,61 +81,103 @@ public class STBTrueTypeProvider implements IFontProvider {
return null; return null;
} }
@Override public static class TrueTypeInstance {
public GlythData glythData(int codepoint, boolean bold) { final int style;
if(skip.contains(codepoint)) return null; long data;
int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint); final STBTTFontinfo info;
if(glyth == 0) return null; IntSet skip = new IntOpenHashSet();
try(MemoryStack stack = MemoryStack.stackPush()) { final float oversample;
IntBuffer left = stack.mallocInt(1); final float xOff;
IntBuffer bottom = stack.mallocInt(1); final float yOff;
IntBuffer right = stack.mallocInt(1); final float shadowOffset;
IntBuffer top = stack.mallocInt(1); final float pointScale;
IntBuffer advance = stack.mallocInt(1); final float ascent;
IntBuffer leftSideBearing = stack.mallocInt(1);
STBTruetype.stbtt_GetGlyphHMetrics(info, glyth, advance, leftSideBearing); public TrueTypeInstance(int style, long data, STBTTFontinfo info, float size, float oversample, float xOff, float yOff, float shadowOffset, String skip) {
STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(info, glyth, pointScale, pointScale, xOff, yOff, left, bottom, right, top); this.style = style;
int minX = left.get(0); this.data = data;
int minY = -top.get(0); this.info = info;
int maxX = right.get(0); skip.codePoints().forEach(this.skip::add);
int maxY = -bottom.get(0); this.oversample = oversample;
if(maxX - minX <= 0 || maxY - minY <= 0) return null; this.xOff = xOff;
return new STBGlyth(this, minX, minY, maxX, maxY, advance.get(0) * pointScale, leftSideBearing.get(0) * pointScale, glyth); this.yOff = yOff;
this.shadowOffset = shadowOffset;
pointScale = STBTruetype.stbtt_ScaleForPixelHeight(info, size * oversample);
int[] ascent = new int[1];
STBTruetype.stbtt_GetFontVMetrics(info, ascent, new int[1], new int[1]);
this.ascent = pointScale * ascent[0];
} }
public void free() {
if(data == 0L) return;
info.free();
MemoryUtil.nmemFree(data);
data = 0L;
}
public GlythData glythData(int codepoint) {
if(skip.contains(codepoint)) return null;
int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint);
if(glyth == 0) return null;
try(MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer left = stack.mallocInt(1);
IntBuffer bottom = stack.mallocInt(1);
IntBuffer right = stack.mallocInt(1);
IntBuffer top = stack.mallocInt(1);
IntBuffer advance = stack.mallocInt(1);
IntBuffer leftSideBearing = stack.mallocInt(1);
STBTruetype.stbtt_GetGlyphHMetrics(info, glyth, advance, leftSideBearing);
STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(info, glyth, pointScale, pointScale, xOff, yOff, left, bottom, right, top);
int minX = left.get(0);
int minY = -top.get(0);
int maxX = right.get(0);
int maxY = -bottom.get(0);
if(maxX - minX <= 0 || maxY - minY <= 0) return new EmptyGlythData(advance.get(0) * pointScale / oversample);
return new STBGlyth(this, minX, minY, maxX, maxY, advance.get(0) * pointScale, leftSideBearing.get(0) * pointScale, glyth);
}
catch(Throwable exception) {
exception.printStackTrace();
return null;
}
}
}
@Override
public GlythData glythData(int codepoint, int style) {
TrueTypeInstance instance = instances[style & 0x3];
return instance == null ? null : instance.glythData(codepoint);
} }
@Override @Override
public void close() { public void close() {
if(data == 0L) return; if(instances == null) return;
info.free(); for(int i = 0;i<4;i++) {
MemoryUtil.nmemFree(data); if(instances[i] == null) continue;
data = 0L; instances[i].free();
}
instances = null;
} }
private static class STBGlyth implements GlythData { private static class STBGlyth implements GlythData {
final STBTrueTypeProvider owner; final TrueTypeInstance owner;
final int width; final int width;
final int height; final int height;
// final float xOff;
// final float yOff;
final float advance; final float advance;
final int glyth; final int glyth;
public STBGlyth(STBTrueTypeProvider owner, int minX, int minY, int maxX, int maxY, float advance, float leftPadding, int glyth) { public STBGlyth(TrueTypeInstance owner, int minX, int minY, int maxX, int maxY, float advance, float leftPadding, int glyth) {
this.owner = owner; this.owner = owner;
this.width = maxX - minX; this.width = maxX - minX;
this.height = maxY - minY; this.height = maxY - minY;
this.advance = advance / owner.oversample; this.advance = advance / owner.oversample;
// this.xOff = (leftPadding + minX + owner.xOff) / owner.oversample;
// this.yOff = (owner.ascent + maxY + owner.yOff) / owner.oversample;
this.glyth = glyth; this.glyth = glyth;
} }
@Override @Override
public float advance() { public float advance() { return advance; }
return advance; @Override
} public float shadowOffset() { return owner.shadowOffset; }
@Override @Override
public Glyth bake(GlythBaker baker) { public Glyth bake(GlythBaker baker) {
return baker.bake(new IGlythSheetInfo() { return baker.bake(new IGlythSheetInfo() {

View File

@ -90,7 +90,7 @@ public class BitmapFontProvider implements IFontProvider
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static IFontProvider load(JsonObject object, float desiredSize, AssetManager manager) public static BitmapFontProvider load(JsonObject object, float desiredSize, AssetManager manager)
{ {
FontInfo info = new FontInfo(object.getAsJsonObject("info")); FontInfo info = new FontInfo(object.getAsJsonObject("info"));
float multiplier = info.setDesiredHeight(desiredSize); float multiplier = info.setDesiredHeight(desiredSize);

View File

@ -25,7 +25,7 @@ public class STBTexture extends AbstractTexture
public STBTexture(AssetLocation location) public STBTexture(AssetLocation location)
{ {
this.location = location; this.location = location;
loadTexture(); // loadTexture();
} }
private void loadTexture() private void loadTexture()

View File

@ -70,6 +70,7 @@ public class JsonUtil {
} }
public static void iterateValues(JsonElement element, Consumer<JsonPrimitive> result) { public static void iterateValues(JsonElement element, Consumer<JsonPrimitive> result) {
if(element == null) return;
if(element.isJsonPrimitive()) result.accept(element.getAsJsonPrimitive()); if(element.isJsonPrimitive()) result.accept(element.getAsJsonPrimitive());
else if(element.isJsonArray()) { else if(element.isJsonArray()) {
JsonArray array = element.getAsJsonArray(); JsonArray array = element.getAsJsonArray();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
{
"type": "stb-ttf",
"regular": {
"file": "font/roboto/Roboto-Medium.ttf",
"size": 18.5,
"oversample": 2,
"shadowOffset": 1,
"skip": "",
"offset": { "x": 0, "y": 0 }
}
}