Implemented Dynamic sized fonts that adjust based on your need.

This commit is contained in:
Speiger 2024-12-28 09:59:44 +01:00
parent a1453f0a6c
commit 9ba9e81686
6 changed files with 70 additions and 36 deletions

View File

@ -80,7 +80,7 @@ public class NewInputTest {
assets.addListener(fonts); assets.addListener(fonts);
assets.reload(); assets.reload();
System.out.println("Testing: "+GL.getCapabilities().OpenGL46); System.out.println("Testing: "+GL.getCapabilities().OpenGL41);
System.out.println("Testing: "+Integer.divideUnsigned(-1, 255)); System.out.println("Testing: "+Integer.divideUnsigned(-1, 255));
IFontProvider provider = STBTrueTypeProvider.create(AssetLocation.of("font/roboto/font.json"), assets); IFontProvider provider = STBTrueTypeProvider.create(AssetLocation.of("font/roboto/font.json"), assets);
@ -150,16 +150,24 @@ public class NewInputTest {
builder.pos(-0.5F, 0.5F, 0).tex(0F, 0F).rgba(-1).endVertex(); builder.pos(-0.5F, 0.5F, 0).tex(0F, 0F).rgba(-1).endVertex();
builder.pos(-0.5F, -0.5F, 0).tex(0F, 1F).rgba(-1).endVertex(); builder.pos(-0.5F, -0.5F, 0).tex(0F, 1F).rgba(-1).endVertex();
Font font = fonts.createFont(18F, 1F); Font font = fonts.createFont(1F);
TestModel model = new TestModel(builder.getBytes()); TestModel model = new TestModel(builder.getBytes());
TestModel[] guiModel = new TestModel[1]; TestModel[] guiModel = new TestModel[1];
List<GLDraw> draws = new ObjectArrayList<>(); List<GLDraw> draws = new ObjectArrayList<>();
font.drawText("The Quick brown fox Jumps over the Lazy dog", 50, 50, -1, new TexturedBuffer((K, V) -> { TexturedBuffer buffer = new TexturedBuffer((K, V) -> {
draws.addAll(K); draws.addAll(K);
guiModel[0] = new TestModel(V); guiModel[0] = new TestModel(V);
System.out.println("Testing: "+V.length+" bytes, "+K.size()); System.out.println("Testing: "+V.length+" bytes, "+K.size());
})); });
// String s = "The Quick brown fox Jumps over the Lazy dog";
float offset = font.drawText("The Quick ", 50, 50, -1, buffer, false);
offset += font.drawText(Font.DEFAULT.with(25F), "Brown ", 50+offset, 50, -1, buffer, false);
offset += font.drawText(Font.DEFAULT, "Fox ", 50+offset, 50, -1, buffer, false);
offset += font.drawText(Font.DEFAULT.with(10F), "Jumps ", 50+offset, 50, -1, buffer, false);
offset += font.drawText(Font.DEFAULT, "over the Lazy dog", 50+offset, 50, -1, buffer, true);
// font.drawText(s, 50, 50, -1, buffer, true);
GLStateTracker tracker = GLStateTracker.instance(); GLStateTracker tracker = GLStateTracker.instance();
GL11.glClearColor(0.2F, 0.55F, 0.66F, 1F); GL11.glClearColor(0.2F, 0.55F, 0.66F, 1F);

View File

@ -6,28 +6,21 @@ import java.util.function.Consumer;
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.MissingGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.GlythBaker; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.GlythBaker;
import speiger.src.coreengine.rendering.tesselation.buffer.IVertexBuilder; import speiger.src.coreengine.rendering.tesselation.buffer.IVertexBuilder;
public class Font { public class Font {
private static final AssetLocation DEFAULT = AssetLocation.of("default"); public static final FontStyle DEFAULT = new FontStyle(AssetLocation.of("default"), 18);
Map<AssetLocation, FontGroup> fonts; Map<AssetLocation, FontGroup> fonts;
GlythBaker baker; GlythBaker baker;
float size;
float oversample; float oversample;
GlythCache[] styledCache = new GlythCache[] {new GlythCache(this, 0), new GlythCache(this, 1), new GlythCache(this, 2), new GlythCache(this, 3)}; GlythCache[] styledCache = new GlythCache[] {new GlythCache(this, 0), new GlythCache(this, 1), new GlythCache(this, 2), new GlythCache(this, 3)};
MissingGlyth missingGlyth;
GlythData missingData;
protected Font(Map<AssetLocation, FontGroup> fonts, GlythBaker baker, float size, float oversample, Consumer<Runnable> clearing) { protected Font(Map<AssetLocation, FontGroup> fonts, GlythBaker baker, float oversample, Consumer<Runnable> clearing) {
this.fonts = fonts; this.fonts = fonts;
this.baker = baker; this.baker = baker;
this.size = size;
this.oversample = oversample; this.oversample = oversample;
this.missingGlyth = new MissingGlyth(size, oversample * 2F);
missingData = new GlythData(missingGlyth);
clearing.accept(this::reset); clearing.accept(this::reset);
} }
@ -35,15 +28,13 @@ public class Font {
for(int i = 0;i<4;i++) { for(int i = 0;i<4;i++) {
styledCache[i].reset(); styledCache[i].reset();
} }
missingGlyth.cleanCache();
missingData.cleanCache();
} }
public GlythData data(AssetLocation font, int codepoint, int style) { public GlythData data(FontStyle font, int codepoint, int style) {
return styledCache[style & 0x3].data(font, codepoint); return styledCache[style & 0x3].data(font, codepoint);
} }
public Glyth glyth(AssetLocation font, int codepoint, int style) { public Glyth glyth(FontStyle font, int codepoint, int style) {
return styledCache[style & 0x3].glyth(font, codepoint); return styledCache[style & 0x3].glyth(font, codepoint);
} }
@ -51,15 +42,20 @@ public class Font {
return fonts.get(font); return fonts.get(font);
} }
public void drawText(String text, float x, float y, int color, TexturedBuffer buffer) { public float drawText(String text, float x, float y, int color, TexturedBuffer buffer, boolean end) {
return drawText(DEFAULT, text, x, y, color, buffer, end);
}
public float drawText(FontStyle style, String text, float x, float y, int color, TexturedBuffer buffer, boolean end) {
float xStart = x;
int previousCodepoint = -1; int previousCodepoint = -1;
for(int i = 0,m=text.length();i<m;) { for(int i = 0,m=text.length();i<m;) {
int codepoint = text.codePointAt(i); int codepoint = text.codePointAt(i);
GlythData data = data(DEFAULT, codepoint, 0); GlythData data = data(style, codepoint, 0);
if(previousCodepoint != -1) { if(previousCodepoint != -1) {
x -= data.kerning(previousCodepoint); x -= data.kerning(previousCodepoint);
} }
Glyth glyth = glyth(DEFAULT, codepoint, 0); Glyth glyth = glyth(style, codepoint, 0);
if(glyth.isValid()) { if(glyth.isValid()) {
float minX = glyth.left() + x; float minX = glyth.left() + x;
float minY = glyth.top() + y; float minY = glyth.top() + y;
@ -78,7 +74,8 @@ public class Font {
i += Character.charCount(codepoint); i += Character.charCount(codepoint);
previousCodepoint = codepoint; previousCodepoint = codepoint;
} }
buffer.end(); if(end) buffer.end();
return x - xStart;
} }
public static interface TexturedBuffer { public static interface TexturedBuffer {

View File

@ -82,12 +82,12 @@ public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, Objec
fonts.clear(); fonts.clear();
} }
public Font createFont(float size) { public Font createFont() {
return createFont(size, 1F); return createFont(1F);
} }
public Font createFont(float size, float oversample) { public Font createFont(float oversample) {
return new Font(fonts, this::stitch, size, oversample, listeners::add); return new Font(fonts, this::stitch, oversample, listeners::add);
} }
private Glyth stitch(IGlythSheetInfo info) { private Glyth stitch(IGlythSheetInfo info) {

View File

@ -0,0 +1,18 @@
package speiger.src.coreengine.rendering.gui.font;
import speiger.src.coreengine.assets.AssetLocation;
public record FontStyle(AssetLocation font, float size) {
public FontStyle with(AssetLocation font, float size) {
return new FontStyle(font, size);
}
public FontStyle with(AssetLocation font) {
return new FontStyle(font, size);
}
public FontStyle with(float size) {
return new FontStyle(font, size);
}
}

View File

@ -5,15 +5,15 @@ import java.util.Map;
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.maps.impl.hash.Object2ObjectOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
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.MissingGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth;
public class GlythCache { public class GlythCache {
private Font font; private Font font;
final int style; final int style;
Map<AssetLocation, FontCache> cache = new Object2ObjectOpenHashMap<>(); Map<FontStyle, FontCache> cache = new Object2ObjectOpenHashMap<>();
public GlythCache(Font font, int style) { public GlythCache(Font font, int style) {
this.font = font; this.font = font;
@ -21,28 +21,39 @@ public class GlythCache {
} }
public void reset() { public void reset() {
cache.values().forEach(FontCache::reset);
cache.clear(); cache.clear();
} }
private FontCache cache(AssetLocation font) { private FontCache cache(FontStyle font) {
return cache.computeIfAbsent(font, FontCache::new); return cache.computeIfAbsent(font, FontCache::new);
} }
public GlythData data(AssetLocation fontId, int codepoint) { public GlythData data(FontStyle fontId, int codepoint) {
return cache(fontId).data(codepoint); return cache(fontId).data(codepoint);
} }
public Glyth glyth(AssetLocation fontId, int codepoint) { public Glyth glyth(FontStyle fontId, int codepoint) {
return cache(fontId).glyth(codepoint); return cache(fontId).glyth(codepoint);
} }
public class FontCache { public class FontCache {
Int2ObjectMap<GlythData> data = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<GlythData> data = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<Glyth> glyth = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<Glyth> glyth = new Int2ObjectOpenHashMap<>();
AssetLocation fontId; FontStyle fontStyle;
MissingGlyth missingGlyth;
GlythData missingData;
public FontCache(AssetLocation fontId) {
this.fontId = fontId; public FontCache(FontStyle fontStyle) {
this.fontStyle = fontStyle;
this.missingGlyth = new MissingGlyth(fontStyle.size(), font.oversample * 2F);
missingData = new GlythData(missingGlyth);
}
private void reset() {
missingGlyth.cleanCache();
missingData.cleanCache();
} }
public GlythData data(int codepoint) { public GlythData data(int codepoint) {
@ -54,8 +65,8 @@ public class GlythCache {
} }
private GlythData compute(int codepoint) { private GlythData compute(int codepoint) {
UnbakedGlyth data = font.font(fontId).data(codepoint, style, font.size, font.oversample); UnbakedGlyth data = font.font(fontStyle.font()).data(codepoint, style, fontStyle.size(), font.oversample);
return data == null ? font.missingData : new GlythData(data); return data == null ? missingData : new GlythData(data);
} }
private Glyth bake(int codepoint) { private Glyth bake(int codepoint) {

View File

@ -4,7 +4,7 @@
"file": "font/roboto/Roboto-Medium.ttf", "file": "font/roboto/Roboto-Medium.ttf",
"oversample": 3, "oversample": 3,
"shadowOffset": 1, "shadowOffset": 1,
"skip": "s", "skip": "",
"offset": { "x": 0, "y": 0 } "offset": { "x": 0, "y": 0 }
} }
} }