added FontTTF
This commit is contained in:
parent
fd42674cee
commit
febe5786b9
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
Loading…
Reference in New Issue