added FontTTF

This commit is contained in:
DaniTheSkunk 2022-09-21 03:10:12 +02:00
parent fd42674cee
commit febe5786b9
12 changed files with 151 additions and 6 deletions

View File

@ -8,9 +8,10 @@ public class Test {
var tex2 = window.loadTexture("C:\\art\\pixel stuff.png"); var tex2 = window.loadTexture("C:\\art\\pixel stuff.png");
var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16)); var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16));
var font = window.loadFontTileset("EGA8x14.png"); var font = window.loadFontTileset("EGA8x14.png");
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16*8.f);
//img.drawImage(img2, Vec2i.ZERO); //img.drawImage(img2, Vec2i.ZERO);
var tex = window.loadTexture(img); var tex = window.loadTexture(img);
window.setDebug(false); window.setDebug(true);
while(!window.shouldClose()) { while(!window.shouldClose()) {
window.tick(); window.tick();
@ -30,6 +31,7 @@ public class Test {
); );
renderContext.drawString(new Vec2i(100, 100), "hello world mew", font); renderContext.drawString(new Vec2i(100, 100), "hello world mew", font);
renderContext.drawString(new Vec2i(710, 140), "hello world mew", font2);
window.renderFinish(renderContext); window.renderFinish(renderContext);
} }
} }

View File

@ -17,8 +17,9 @@ abstract class BaseRenderContext implements IRenderContext {
for(int i = 0; i < string.length(); ++i) { for(int i = 0; i < string.length(); ++i) {
int ch = buf.get(i); int ch = buf.get(i);
var tex = font.getTexture(ch); var tex = font.getTexture(ch);
drawTextureRectangle(new Recti(new Vec2i(x, y), tex.getSize()), tex); var off = font.getOffset(ch);
x += font.getCharWidth(ch); drawTextureRectangle(new Recti(Vec2i.add(new Vec2i(x, y), off), tex.getSize()), tex);
x += font.getXAdvance(ch);
} }
} }
} }

View File

@ -1,5 +1,8 @@
package com.danitheskunk.skunkworks; package com.danitheskunk.skunkworks;
import org.lwjgl.stb.STBTTFontinfo;
import static org.lwjgl.stb.STBTruetype.*;
abstract class BaseWindow implements IWindow { abstract class BaseWindow implements IWindow {
protected final Engine engine; protected final Engine engine;
@ -7,6 +10,12 @@ abstract class BaseWindow implements IWindow {
this.engine = engine; this.engine = engine;
} }
@Override
public Engine getEngine() {
return engine;
}
@Override
public IFont loadFontTileset(String path) { public IFont loadFontTileset(String path) {
var img = engine.loadImage(path); var img = engine.loadImage(path);
var charSize = Vec2i.div(img.getSize(), 16); var charSize = Vec2i.div(img.getSize(), 16);
@ -14,4 +23,12 @@ abstract class BaseWindow implements IWindow {
assert tex.size() == 256; assert tex.size() == 256;
return new FontTileset(tex); return new FontTileset(tex);
} }
@Override
public IFont loadFontTTF(String path, float size) {
var bytes = engine.loadBytes(path);
return new FontTTF(bytes, size, this);
}
} }

View File

@ -0,0 +1,111 @@
package com.danitheskunk.skunkworks;
import org.lwjgl.BufferUtils;
import org.lwjgl.stb.STBTTFontinfo;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import static org.lwjgl.stb.STBTruetype.*;
import static org.lwjgl.stb.STBTruetype.stbtt_ScaleForPixelHeight;
public class FontTTF implements IFont {
HashMap<Integer, Char> chars;
int lineHeight;
float size;
float unscaled_size;
STBTTFontinfo info;
IWindow window;
FontTTF(ByteBuffer buffer, float size, IWindow window) {
int[] ascent = {0};
int[] descent = {0};
int[] lineGap = {0};
this.window = window;
this.chars = new HashMap<>();
this.info = STBTTFontinfo.create();
if(!stbtt_InitFont(info, buffer)) {
throw new IllegalStateException("Failed to initialize font information.");
}
//todo: save these
stbtt_GetFontVMetrics(info, ascent, descent, lineGap);
lineHeight = lineGap[0];
this.unscaled_size = size;
this.size = stbtt_ScaleForPixelHeight(info, size);
//precache ascii characters
for(int i = 32; i < 128; ++i)
cacheChar(i);
}
void cacheChar(int ch) {
if(chars.containsKey(ch))
return;
int[] width = {0};
int[] height = {0};
int[] xoff = {0};
int[] yoff = {0};
int[] advanceWidth = {0};
int[] leftSideBearing = {0};
ITexture tex;
var bufmono = stbtt_GetCodepointBitmap(info, size, size, ch, width, height, xoff, yoff);
if(bufmono != null) {
var buf = ByteBuffer.allocate(bufmono.remaining() * 4);
while(bufmono.hasRemaining()) {
var b = bufmono.get();
buf.put((byte) 0xff);
buf.put((byte) 0xff);
buf.put((byte) 0xff);
buf.put(b);
}
buf.flip();
tex = window.loadTexture(new Image(buf, new Vec2i(width[0], height[0])));
} else {
tex = window.loadTexture(new Image(Vec2i.ZERO));
}
stbtt_GetCodepointHMetrics(info, ch, advanceWidth, leftSideBearing);
var c = new Char(tex, (int)(advanceWidth[0] * size), new Vec2i(xoff[0], yoff[0]));
chars.put(ch, c);
}
@Override
public int getXAdvance(int ch) {
cacheChar(ch);
return chars.get(ch).advance;
}
@Override
public int getLineHeight(int ch) {
cacheChar(ch);
return lineHeight;
}
@Override
public Vec2i getOffset(int ch) {
cacheChar(ch);
return chars.get(ch).off;
}
@Override
public ITexture getTexture(int ch) {
cacheChar(ch);
return chars.get(ch).tex;
}
private class Char {
ITexture tex;
int advance;
Vec2i off;
Char(ITexture tex, int advance, Vec2i off) {
this.tex = tex;
this.advance = advance;
this.off = off;
}
}
}

View File

@ -12,7 +12,7 @@ class FontTileset implements IFont {
} }
@Override @Override
public int getCharWidth(int ch) { public int getXAdvance(int ch) {
return charSize.getX(); return charSize.getX();
} }
@ -21,6 +21,11 @@ class FontTileset implements IFont {
return charSize.getY(); return charSize.getY();
} }
@Override
public Vec2i getOffset(int ch) {
return Vec2i.ZERO;
}
@Override @Override
public ITexture getTexture(int ch) { public ITexture getTexture(int ch) {
if(ch >= 256 || ch < 0) { if(ch >= 256 || ch < 0) {

View File

@ -1,7 +1,8 @@
package com.danitheskunk.skunkworks; package com.danitheskunk.skunkworks;
public interface IFont { public interface IFont {
int getCharWidth(int ch);
int getLineHeight(int ch); int getLineHeight(int ch);
Vec2i getOffset(int ch);
ITexture getTexture(int ch); ITexture getTexture(int ch);
int getXAdvance(int ch);
} }

View File

@ -3,7 +3,9 @@ package com.danitheskunk.skunkworks;
import java.util.List; import java.util.List;
public interface IWindow { public interface IWindow {
Engine getEngine();
IFont loadFontTileset(String path); IFont loadFontTileset(String path);
IFont loadFontTTF(String path, float size);
ITexture loadTexture(Image image); ITexture loadTexture(Image image);
ITexture loadTexture(String path); ITexture loadTexture(String path);
List<ITexture> loadTextureArray(Image image, Vec2i tileSize); List<ITexture> loadTextureArray(Image image, Vec2i tileSize);

View File

@ -9,7 +9,7 @@ public class Image {
private final Vec2i size; private final Vec2i size;
//constructors //constructors
Image(ByteBuffer buffer) { Image(ByteBuffer buffer) { //png or similar
//todo: resource system //todo: resource system
int[] x = {0}, y = {0}, n = {0}; int[] x = {0}, y = {0}, n = {0};
var img = STBImage.stbi_load_from_memory(buffer, x, y, n, 4); var img = STBImage.stbi_load_from_memory(buffer, x, y, n, 4);
@ -24,6 +24,12 @@ public class Image {
data = new byte[size.getX() * size.getY() * 4]; data = new byte[size.getX() * size.getY() * 4];
} }
Image(ByteBuffer buffer, Vec2i size) {
data = new byte[buffer.remaining()];
buffer.get(data);
this.size = size;
}
//getters //getters
public byte[] getData() { public byte[] getData() {
return data; return data;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.