More Progress on the font system
This commit is contained in:
parent
7fdbe645e4
commit
2dae61adbf
|
@ -77,6 +77,7 @@ public class NewInputTest {
|
||||||
|
|
||||||
int size = 512;
|
int size = 512;
|
||||||
int half = size >> 1;
|
int half = size >> 1;
|
||||||
|
int base = size >> 3;
|
||||||
|
|
||||||
DynamicTexture texture = new DynamicTexture(size, size, DynamicTexture.DEFAULT_PARAMETERS);
|
DynamicTexture texture = new DynamicTexture(size, size, DynamicTexture.DEFAULT_PARAMETERS);
|
||||||
texture.fill(0, 0, size, size, -1);
|
texture.fill(0, 0, size, size, -1);
|
||||||
|
@ -86,18 +87,20 @@ public class NewInputTest {
|
||||||
texture.fill(0, half, half, half, 0, 0, 255, 255);
|
texture.fill(0, half, half, half, 0, 0, 255, 255);
|
||||||
texture.process(true);
|
texture.process(true);
|
||||||
window.visible(true);
|
window.visible(true);
|
||||||
|
var instance = bit.getCharacter("C".codePointAt(0), false);
|
||||||
|
System.out.println("Testing: "+instance.getWidth()+","+instance.getHeight());
|
||||||
bus.register(KeyEvent.Key.class, T -> {
|
bus.register(KeyEvent.Key.class, T -> {
|
||||||
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, half, half);
|
Drawable drawable = new Drawable(GLTextureFormat.RGBA, half, half);
|
||||||
drawable.fill(0, 0, half, half, 255, 255, 0, 255);
|
drawable.fill(0, 0, half, half, 255, 255, 0, 255);
|
||||||
drawable.upload(192, 192, 64, 64, 128, 128);
|
drawable.upload(base * 3, base * 3, base, base, base * 2, base * 2);
|
||||||
drawable.close();
|
drawable.close();
|
||||||
}
|
}
|
||||||
else if(T.key() == GLFW.GLFW_KEY_Z) {
|
else if(T.key() == GLFW.GLFW_KEY_Z) {
|
||||||
T.cancel();
|
T.cancel();
|
||||||
|
System.out.println("Testing");
|
||||||
texture.bind();
|
texture.bind();
|
||||||
UnbakedGlyth data = provider.glythData("C".codePointAt(0), 0);
|
UnbakedGlyth data = provider.glythData("C".codePointAt(0), 0);
|
||||||
data.bake(new GlythBaker() {
|
data.bake(new GlythBaker() {
|
||||||
|
@ -105,7 +108,8 @@ public class NewInputTest {
|
||||||
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(half - (width >> 2), half - (height >> 2));
|
info.upload(half - (width >> 1), half - (height >> 1));
|
||||||
|
System.out.println("Test2: "+width+", "+height);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, 1F, 1F);
|
}, 1F, 1F);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package speiger.src.coreengine.assets;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import speiger.src.coreengine.assets.base.IAsset;
|
||||||
|
import speiger.src.coreengine.assets.base.IAssetProvider;
|
||||||
|
import speiger.src.coreengine.assets.base.MultiAsset;
|
||||||
|
|
||||||
|
public record AssetFilter(String prefix, String extension) {
|
||||||
|
public static AssetFilter json(String prefix) {
|
||||||
|
return new AssetFilter(prefix, ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetLocation id(AssetLocation file) {
|
||||||
|
String location = file.location();
|
||||||
|
return AssetLocation.of(file.domain(), location.substring(prefix().length()+1, location.length()-extension().length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetLocation file(AssetLocation id) {
|
||||||
|
return AssetLocation.of(id.domain(), prefix()+"/"+id.location()+extension());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<AssetLocation, IAsset> list(IAssetProvider provider) {
|
||||||
|
return provider.listAssets(prefix, T -> T.endsWith(extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<AssetLocation, IAsset> listRoot(IAssetProvider provider) {
|
||||||
|
return provider.listAssets(prefix, T -> T.endsWith(extension) && !T.isInFolder(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<AssetLocation, MultiAsset> multi(IAssetProvider provider) {
|
||||||
|
return provider.listAllAssets(prefix, T -> T.endsWith(extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ public final class AssetLocation implements Comparable<AssetLocation> {
|
||||||
public String location() { return location; }
|
public String location() { return location; }
|
||||||
public String actualLocation() { return "assets/"+domain+"/"+location; }
|
public String actualLocation() { return "assets/"+domain+"/"+location; }
|
||||||
public boolean endsWith(String suffix) { return location.endsWith(suffix); }
|
public boolean endsWith(String suffix) { return location.endsWith(suffix); }
|
||||||
|
public boolean isInFolder() { return location.contains("/"); }
|
||||||
|
public boolean isInFolder(String prefix) { return location.indexOf("/", prefix.length()+1) >= 0; }
|
||||||
|
|
||||||
public AssetLocation subAsset(String subPath) {
|
public AssetLocation subAsset(String subPath) {
|
||||||
return of(domain+":"+location+"/"+subPath);
|
return of(domain+":"+location+"/"+subPath);
|
||||||
|
|
|
@ -1,56 +1,35 @@
|
||||||
package speiger.src.coreengine.rendering.gui.font;
|
package speiger.src.coreengine.rendering.gui.font;
|
||||||
|
|
||||||
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
import java.util.Map;
|
||||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
|
||||||
|
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.UnbakedGlyth.GlythBaker;
|
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.GlythBaker;
|
||||||
|
|
||||||
public class Font {
|
public class Font {
|
||||||
FontGroup fonts;
|
Map<AssetLocation, FontGroup> fonts;
|
||||||
GlythBaker baker;
|
GlythBaker baker;
|
||||||
float size;
|
float size;
|
||||||
float oversample;
|
float oversample;
|
||||||
GlythCache[] styledCache = new GlythCache[] {new GlythCache(0), new GlythCache(1), new GlythCache(2), new GlythCache(3)};
|
GlythCache[] styledCache = new GlythCache[] {new GlythCache(this, 0), new GlythCache(this, 1), new GlythCache(this, 2), new GlythCache(this, 3)};
|
||||||
|
|
||||||
private Font(FontGroup fonts, GlythBaker baker, float size, float oversample) {
|
protected Font(Map<AssetLocation, FontGroup> fonts, GlythBaker baker, float size, float oversample) {
|
||||||
this.fonts = fonts;
|
this.fonts = fonts;
|
||||||
this.baker = baker;
|
this.baker = baker;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.oversample = oversample;
|
this.oversample = oversample;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlythData data(int codepoint, int style) {
|
public GlythData data(AssetLocation font, int codepoint, int style) {
|
||||||
return styledCache[style & 0x3].data(codepoint);
|
return styledCache[style & 0x3].data(font, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Glyth glyth(int codepoint, int style) {
|
public Glyth glyth(AssetLocation font, int codepoint, int style) {
|
||||||
return styledCache[style & 0x3].glyth(codepoint);
|
return styledCache[style & 0x3].glyth(font, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GlythCache {
|
protected FontGroup font(AssetLocation font) {
|
||||||
final int style;
|
return fonts.get(font);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ public class FontGroup {
|
||||||
this.providers = providers;
|
this.providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnbakedGlyth data(int codepoint, int style) {
|
public UnbakedGlyth unbaked(int codepoint, int style) {
|
||||||
return cache[style & 0x3].data(codepoint);
|
return cache[style & 0x3].unbaked(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -35,7 +35,7 @@ public class FontGroup {
|
||||||
this.style = style;
|
this.style = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnbakedGlyth data(int codepoint) {
|
public UnbakedGlyth unbaked(int codepoint) {
|
||||||
return dataGlyths.computeIfAbsent(codepoint, this::compute);
|
return dataGlyths.computeIfAbsent(codepoint, this::compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,17 @@ import java.util.Map;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||||
|
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
|
||||||
import speiger.src.coreengine.assets.AssetLocation;
|
import speiger.src.coreengine.assets.AssetLocation;
|
||||||
import speiger.src.coreengine.assets.base.IAssetProvider;
|
import speiger.src.coreengine.assets.base.IAssetProvider;
|
||||||
import speiger.src.coreengine.assets.base.SteppedReloadableAsset;
|
import speiger.src.coreengine.assets.base.SteppedReloadableAsset;
|
||||||
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.IGlythSheetInfo;
|
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
|
||||||
|
import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider;
|
||||||
|
|
||||||
public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, List<JsonObject>>> {
|
public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, List<IFontProvider>>> {
|
||||||
private static final int TEXTURE_SIZE = 2048;
|
private static final int TEXTURE_SIZE = 2048;
|
||||||
|
Map<AssetLocation, FontGroup> fonts = Object2ObjectMap.builder().linkedMap();
|
||||||
List<FontTexture> textures = new ObjectArrayList<>();
|
List<FontTexture> textures = new ObjectArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,16 +28,23 @@ public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, List<
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<AssetLocation, List<JsonObject>> prepare(IAssetProvider provider) {
|
protected Map<AssetLocation, List<IFontProvider>> prepare(IAssetProvider provider) {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void apply(Map<AssetLocation, List<JsonObject>> value, IAssetProvider provider) {
|
protected void apply(Map<AssetLocation, List<IFontProvider>> value, IAssetProvider provider) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Font createFont(float size) {
|
||||||
|
return createFont(size, 1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Font createFont(float size, float oversample) {
|
||||||
|
return new Font(fonts, this::stitch, size, oversample);
|
||||||
|
}
|
||||||
|
|
||||||
private Glyth stitch(IGlythSheetInfo info) {
|
private Glyth stitch(IGlythSheetInfo info) {
|
||||||
for(int i = 0,m=textures.size();i<m;i++) {
|
for(int i = 0,m=textures.size();i<m;i++) {
|
||||||
Glyth glyth = textures.get(i).build(info);
|
Glyth glyth = textures.get(i).build(info);
|
||||||
|
@ -45,5 +55,4 @@ public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, List<
|
||||||
Glyth glyth = texture.build(info);
|
Glyth glyth = texture.build(info);
|
||||||
return glyth;
|
return glyth;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package speiger.src.coreengine.rendering.gui.font;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
||||||
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||||
|
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.GlythData;
|
||||||
|
|
||||||
|
public class GlythCache {
|
||||||
|
private Font font;
|
||||||
|
final int style;
|
||||||
|
Map<AssetLocation, FontCache> cache = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public GlythCache(Font font, int style) {
|
||||||
|
this.font = font;
|
||||||
|
this.style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FontCache cache(AssetLocation font) {
|
||||||
|
return cache.computeIfAbsent(font, FontCache::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlythData data(AssetLocation fontId, int codepoint) {
|
||||||
|
return cache(fontId).data(codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Glyth glyth(AssetLocation fontId, int codepoint) {
|
||||||
|
return cache(fontId).glyth(codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FontCache {
|
||||||
|
Int2ObjectMap<GlythData> data = new Int2ObjectOpenHashMap<>();
|
||||||
|
Int2ObjectMap<Glyth> glyth = new Int2ObjectOpenHashMap<>();
|
||||||
|
AssetLocation fontId;
|
||||||
|
|
||||||
|
public FontCache(AssetLocation fontId) {
|
||||||
|
this.fontId = fontId;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(font.font(fontId).unbaked(codepoint, style), font.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Glyth bake(int codepoint) {
|
||||||
|
return font.font(fontId).unbaked(codepoint, style).bake(font.baker, font.size, font.oversample);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth;
|
||||||
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.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.rendering.utils.values.textures.GLTextureFormat;
|
||||||
import speiger.src.coreengine.utils.helpers.JsonUtil;
|
import speiger.src.coreengine.utils.helpers.JsonUtil;
|
||||||
|
|
||||||
public class STBTrueTypeProvider implements IFontProvider {
|
public class STBTrueTypeProvider implements IFontProvider {
|
||||||
|
@ -192,7 +193,14 @@ public class STBTrueTypeProvider implements IFontProvider {
|
||||||
public void upload(int x, int y) {
|
public void upload(int x, int y) {
|
||||||
Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height);
|
Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height);
|
||||||
drawable.drawFont(owner.info, glyth, owner.xOff, owner.yOff, 0, 0, width, height, owner.pointScale, owner.pointScale);
|
drawable.drawFont(owner.info, glyth, owner.xOff, owner.yOff, 0, 0, width, height, owner.pointScale, owner.pointScale);
|
||||||
drawable.upload(x, y, 0, 0, width, height);
|
Drawable upload = new Drawable(GLTextureFormat.RGBA, width, height);
|
||||||
|
int pattern = Integer.divideUnsigned(-1, 255);
|
||||||
|
for(int i = 0,m=width*height;i<m;i++) {
|
||||||
|
upload.set(i, drawable.getR(i) * pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
upload.upload(x, y, 0, 0, width, height);
|
||||||
|
upload.close();
|
||||||
drawable.close();
|
drawable.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"regular": {
|
"regular": {
|
||||||
"file": "font/roboto/Roboto-Medium.ttf",
|
"file": "font/roboto/Roboto-Medium.ttf",
|
||||||
"size": 18.5,
|
"size": 18.5,
|
||||||
"oversample": 2,
|
"oversample": 3,
|
||||||
"shadowOffset": 1,
|
"shadowOffset": 1,
|
||||||
"skip": "",
|
"skip": "",
|
||||||
"offset": { "x": 0, "y": 0 }
|
"offset": { "x": 0, "y": 0 }
|
||||||
|
|
Loading…
Reference in New Issue