Started the rework of the font system so the system works better.

This commit is contained in:
Speiger 2024-07-26 17:36:08 +02:00
parent 62b91f0f1d
commit 7fdbe645e4
9 changed files with 143 additions and 68 deletions

View File

@ -14,8 +14,8 @@ 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.UnbakedGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.GlythBaker; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.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;
@ -99,7 +99,7 @@ public class NewInputTest {
else if(T.key() == GLFW.GLFW_KEY_Z) { else if(T.key() == GLFW.GLFW_KEY_Z) {
T.cancel(); T.cancel();
texture.bind(); texture.bind();
GlythData data = provider.glythData("C".codePointAt(0), 0); UnbakedGlyth data = provider.glythData("C".codePointAt(0), 0);
data.bake(new GlythBaker() { data.bake(new GlythBaker() {
@Override @Override
public Glyth bake(IGlythSheetInfo info) { public Glyth bake(IGlythSheetInfo info) {
@ -108,8 +108,7 @@ public class NewInputTest {
info.upload(half - (width >> 2), half - (height >> 2)); info.upload(half - (width >> 2), half - (height >> 2));
return null; return null;
} }
}); }, 1F, 1F);
System.out.println("Testing: "+data.advance()+", "+bit.getCharacter("C".codePointAt(0), false).getXAdvance());
} }
}); });

View File

@ -0,0 +1,56 @@
package speiger.src.coreengine.rendering.gui.font;
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
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.UnbakedGlyth.GlythBaker;
public class Font {
FontGroup fonts;
GlythBaker baker;
float size;
float oversample;
GlythCache[] styledCache = new GlythCache[] {new GlythCache(0), new GlythCache(1), new GlythCache(2), new GlythCache(3)};
private Font(FontGroup fonts, GlythBaker baker, float size, float oversample) {
this.fonts = fonts;
this.baker = baker;
this.size = size;
this.oversample = oversample;
}
public GlythData data(int codepoint, int style) {
return styledCache[style & 0x3].data(codepoint);
}
public Glyth glyth(int codepoint, int style) {
return styledCache[style & 0x3].glyth(codepoint);
}
private class GlythCache {
final int style;
Int2ObjectMap<GlythData> data = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<Glyth> glyth = new Int2ObjectOpenHashMap<>();
public GlythCache(int style) {
this.style = style;
}
public GlythData data(int codepoint) {
return data.computeIfAbsent(codepoint, this::compute);
}
public Glyth glyth(int codepoint) {
return glyth.computeIfAbsent(codepoint, this::bake);
}
private GlythData compute(int codepoint) {
return new GlythData(fonts.data(codepoint, style), size);
}
private Glyth bake(int codepoint) {
return fonts.data(codepoint, style).bake(baker, size, oversample);
}
}
}

View File

@ -5,31 +5,23 @@ 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.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.UnbakedGlyth;
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.providers.IFontProvider; import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider;
public class FontGroup { public class FontGroup {
AssetLocation locations; AssetLocation locations;
List<IFontProvider> providers; List<IFontProvider> providers;
GlythBaker baker;
StyledFont[] cache = new StyledFont[] {new StyledFont(0), new StyledFont(1), new StyledFont(2), new StyledFont(3)}; StyledFont[] cache = new StyledFont[] {new StyledFont(0), new StyledFont(1), new StyledFont(2), new StyledFont(3)};
public FontGroup(AssetLocation locations, List<IFontProvider> providers, GlythBaker baker) { public FontGroup(AssetLocation locations, List<IFontProvider> providers) {
this.locations = locations; this.locations = locations;
this.providers = providers; this.providers = providers;
this.baker = baker;
} }
public GlythData data(int codepoint, int style) { public UnbakedGlyth data(int codepoint, int style) {
return cache[style & 0x3].data(codepoint); return cache[style & 0x3].data(codepoint);
} }
public Glyth glyth(int codepoint, int style) {
return cache[style & 0x3].glyth(codepoint);
}
public void close() { public void close() {
providers.forEach(IFontProvider::close); providers.forEach(IFontProvider::close);
providers.clear(); providers.clear();
@ -37,35 +29,22 @@ public class FontGroup {
private class StyledFont { private class StyledFont {
final int style; final int style;
Int2ObjectMap<Glyth> bakedGlyths = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<UnbakedGlyth> dataGlyths = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<GlythData> dataGlyths = new Int2ObjectOpenHashMap<>();
public StyledFont(int style) { public StyledFont(int style) {
this.style = style; this.style = style;
} }
public GlythData data(int codepoint) { public UnbakedGlyth data(int codepoint) {
return dataGlyths.computeIfAbsent(codepoint, this::compute); return dataGlyths.computeIfAbsent(codepoint, this::compute);
} }
public Glyth glyth(int codepoint) { private UnbakedGlyth compute(int codepoint) {
return bakedGlyths.computeIfAbsent(codepoint, this::bake);
}
private GlythData compute(int codepoint) {
for(int i = 0,m=providers.size();i<m;i++) { for(int i = 0,m=providers.size();i<m;i++) {
GlythData data = providers.get(i).glythData(codepoint, style); UnbakedGlyth data = providers.get(i).glythData(codepoint, style);
if(data != null) return data; if(data != null) return data;
} }
return null; 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;
}
} }
} }

View File

@ -1,6 +1,13 @@
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, int left, int right, int top, int bottom) {
public static final Glyth EMPTY = new Glyth(-1, 0, 0, 0, 0); public static final Glyth EMPTY = new Glyth();
private Glyth() {
this(-1, 0F, 0F, 0F, 0F, 0, 0, 0, 0);
}
public Glyth(int texture, float minU, float minV, float maxU, float maxV) {
this(texture, minU, minV, maxU, maxV, 0, 0, 0, 0);
}
} }

View File

@ -1,17 +1,26 @@
package speiger.src.coreengine.rendering.gui.font.glyth; package speiger.src.coreengine.rendering.gui.font.glyth;
public interface GlythData { import speiger.src.collections.ints.functions.function.Int2FloatFunction;
public float advance(); import speiger.src.collections.ints.maps.impl.hash.Int2FloatOpenHashMap;
public default float shadowOffset() { return 1F; } import speiger.src.collections.ints.maps.interfaces.Int2FloatMap;
public Glyth bake(GlythBaker baker);
public class GlythData {
float advance;
float shadowOffset;
Int2FloatMap kernlings = new Int2FloatOpenHashMap();
Int2FloatFunction kernling;
public static record EmptyGlythData(float advance) implements GlythData { public GlythData(float advance, float shadowOffset, Int2FloatFunction kernling) {
@Override this.advance = advance;
public Glyth bake(GlythBaker baker) { return Glyth.EMPTY; } this.shadowOffset = shadowOffset;
this.kernling = kernling;
} }
public static interface GlythBaker { public GlythData(UnbakedGlyth glyth, float size) {
Glyth bake(IGlythSheetInfo info); this(glyth.advance(size), glyth.shadowOffset(), glyth::kernling);
} }
public float advance() { return advance; }
public float shadowOffset() { return shadowOffset; }
public float kernling(int codepoint) { return kernlings.computeFloatIfAbsent(codepoint, kernling); }
} }

View File

@ -0,0 +1,22 @@
package speiger.src.coreengine.rendering.gui.font.glyth;
public interface UnbakedGlyth {
public float advance(float size);
public float kernling(int codepoint);
public default float shadowOffset() { return 1F; }
public Glyth bake(GlythBaker baker, float size, float oversample);
public static record EmptyGlythData(float advance) implements UnbakedGlyth {
@Override
public Glyth bake(GlythBaker baker, float size, float oversample) { return Glyth.EMPTY; }
@Override
public float advance(float size) { return advance; }
@Override
public float kernling(int codepoint) { return 0F; }
}
public static interface GlythBaker {
Glyth bake(IGlythSheetInfo info);
}
}

View File

@ -1,13 +1,13 @@
package speiger.src.coreengine.rendering.gui.font.providers; 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.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth;
public class BitmapProivder implements IFontProvider { public class BitmapProivder implements IFontProvider {
@Override @Override
public GlythData glythData(int codepoint, int style) { public UnbakedGlyth glythData(int codepoint, int style) {
return null; return null;
} }
@ -16,23 +16,26 @@ public class BitmapProivder implements IFontProvider {
} }
private static class BitmapGlyth implements GlythData { private static class BitmapGlyth implements UnbakedGlyth {
int minX; int minX;
int minY; int minY;
int maxX; int maxX;
int maxY; int maxY;
int glyth; int glyth;
@Override
public Glyth bake(GlythBaker baker, float size, float oversample) {
return null;
}
@Override @Override
public float advance() { public float advance(float size) {
return 0; return 0;
} }
@Override @Override
public Glyth bake(GlythBaker baker) { public float kernling(int codepoint) {
return null; return 0;
} }
} }
} }

View File

@ -1,6 +1,6 @@
package speiger.src.coreengine.rendering.gui.font.providers; 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.UnbakedGlyth;
public interface IFontProvider extends AutoCloseable { public interface IFontProvider extends AutoCloseable {
public static final int REGULAR = 0; public static final int REGULAR = 0;
@ -9,7 +9,7 @@ public interface IFontProvider extends AutoCloseable {
public static final int ITALIC_BOLD = 3; public static final int ITALIC_BOLD = 3;
public GlythData glythData(int codepoint, int style); public UnbakedGlyth glythData(int codepoint, int style);
@Override @Override
void close(); void close();
} }

View File

@ -18,8 +18,8 @@ import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser; 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.UnbakedGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.GlythData.EmptyGlythData; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.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; import speiger.src.coreengine.utils.helpers.JsonUtil;
@ -115,7 +115,7 @@ public class STBTrueTypeProvider implements IFontProvider {
data = 0L; data = 0L;
} }
public GlythData glythData(int codepoint) { public UnbakedGlyth glythData(int codepoint) {
if(skip.contains(codepoint)) return null; if(skip.contains(codepoint)) return null;
int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint); int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint);
if(glyth == 0) return null; if(glyth == 0) return null;
@ -143,7 +143,7 @@ public class STBTrueTypeProvider implements IFontProvider {
} }
@Override @Override
public GlythData glythData(int codepoint, int style) { public UnbakedGlyth glythData(int codepoint, int style) {
TrueTypeInstance instance = instances[style & 0x3]; TrueTypeInstance instance = instances[style & 0x3];
return instance == null ? null : instance.glythData(codepoint); return instance == null ? null : instance.glythData(codepoint);
} }
@ -158,7 +158,7 @@ public class STBTrueTypeProvider implements IFontProvider {
instances = null; instances = null;
} }
private static class STBGlyth implements GlythData { private static class STBGlyth implements UnbakedGlyth {
final TrueTypeInstance owner; final TrueTypeInstance owner;
final int width; final int width;
final int height; final int height;
@ -174,12 +174,13 @@ public class STBTrueTypeProvider implements IFontProvider {
} }
@Override @Override
public float advance() { return advance; } public float advance(float size) { return advance; }
@Override @Override
public float shadowOffset() { return owner.shadowOffset; } public float shadowOffset() { return owner.shadowOffset; }
@Override @Override
public Glyth bake(GlythBaker baker) { public float kernling(int codepoint) { return STBTruetype.stbtt_GetCodepointKernAdvance(owner.info, codepoint, glyth); }
@Override
public Glyth bake(GlythBaker baker, float size, float oversample) {
return baker.bake(new IGlythSheetInfo() { return baker.bake(new IGlythSheetInfo() {
@Override @Override
public int width() { return width; } public int width() { return width; }
@ -196,6 +197,5 @@ public class STBTrueTypeProvider implements IFontProvider {
} }
}); });
} }
} }
} }