Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>virtual-cardboard</groupId>
<artifactId>nengen</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
Expand Down Expand Up @@ -200,6 +200,11 @@
<artifactId>lwjgl-stb</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-freetype</artifactId>
<version>3.3.6</version>
</dependency>
</dependencies>

<build>
Expand Down
73 changes: 68 additions & 5 deletions src/main/java/common/NengenFileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,29 @@
import static org.lwjgl.stb.STBImage.stbi_failure_reason;
import static org.lwjgl.stb.STBImage.stbi_load;
import static org.lwjgl.stb.STBImage.stbi_set_flip_vertically_on_load;
import static org.lwjgl.util.freetype.FreeType.FT_New_Face;
import static visuals.rendering.text.GameFont.getFontIndex;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.PointerBuffer;
import org.lwjgl.freetype.FT_Bitmap;
import org.lwjgl.freetype.FT_Face;
import org.lwjgl.freetype.FT_GlyphSlot;
import org.lwjgl.freetype.FreeType;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.freetype.FT_Bitmap;
import org.lwjgl.util.freetype.FT_Face;
import org.lwjgl.util.freetype.FT_GlyphSlot;
import org.lwjgl.util.freetype.FreeType;

import javafx.scene.image.Image;
import visuals.lwjgl.render.Texture;
import visuals.rendering.text.CharacterData;
import visuals.rendering.text.GameFont;
import visuals.rendering.texture.Image;

public class NengenFileUtil {

Expand Down Expand Up @@ -94,7 +105,7 @@ public static GameFont loadFont(File font, Texture texture) {
DEBUG("Characters: " + numCharacters);
DEBUG("Kernings: " + kernings);

GameFont gameFont = new GameFont(name, fontSize, texture);
GameFont gameFont = new GameFont(name, fontSize, texture, getFontIndex());

// Read characters
CharacterData[] characters = gameFont.getCharacterDatas();
Expand All @@ -111,7 +122,8 @@ public static GameFont loadFont(File font, Texture texture) {
short page = (short) fis.read();
CharacterData charData = new CharacterData(x, y, width, height, xOffset, yOffset, xAdvance, page);
DEBUG("=====================");
DEBUG(c + " " + x + " " + y + " " + width + " " + height + " " + xOffset + " " + yOffset + " " + xAdvance + " " + page);
DEBUG(c + " " + x + " " + y + " " + width + " " + height + " " + xOffset + " " + yOffset + " "
+ xAdvance + " " + page);
DEBUG("Character: " + (char) c);
DEBUG("X: " + x);
DEBUG("Y: " + y);
Expand All @@ -124,14 +136,65 @@ public static GameFont loadFont(File font, Texture texture) {
characters[c] = charData;
}
CharacterData space = characters[' '];
characters['\t'] = new CharacterData(space.x(), space.y(), space.width(), space.height(), space.xOffset(), space.yOffset(), (short) (space.xAdvance() * 4), space.getPage());
characters['\t'] = new CharacterData(space.x(), space.y(), space.width(), space.height(), space.xOffset(),
space.yOffset(), (short) (space.xAdvance() * 4), space.getPage());

return gameFont;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static GameFont loadTTF(String ttfFile, int fontSize) {
PointerBuffer ftLibrary = PointerBuffer.allocateDirect(10000);
FT_Init_FreeType(ftLibrary);

PointerBuffer ftFaceBuffer = PointerBuffer.allocateDirect(1);
ByteBuffer ftFaceByteBuffer = ftFaceBuffer.getByteBuffer(0, 8);
FT_Face ftFace = new FT_Face(ftFaceByteBuffer);
FT_New_Face(ftLibrary.address(), ttfFile, getFontIndex(), ftFaceBuffer);

if (false) {
throw new RuntimeException("Failed to initialize FreeType library");
}

FreeType.FT_Set_Pixel_Sizes(ftFace, 0, fontSize);

GameFont gameFont = new GameFont(ttfFile, fontSize, new CharacterData[0], getFontIndex());
CharacterData[] characters = gameFont.getCharacterDatas();

for (int c = 0; c < 128; c++) {
if (FreeType.FT_Load_Char(ftFace, c, FreeType.FT_LOAD_RENDER) != 0) {
System.err.println("Failed to load Glyph for character: " + (char) c);
continue;
}

FT_GlyphSlot glyph = ftFace.glyph();
FT_Bitmap bitmap = glyph.bitmap();

Texture texture = new Texture().dimensions(bitmap.width(), bitmap.rows())
.image(new Image().data(bitmap.buffer(100))).load();

CharacterData charData = new CharacterData(
(short) glyph.bitmap_left(),
(short) glyph.bitmap_top(),
(short) bitmap.width(),
(short) bitmap.rows(),
(short) glyph.bitmap_left(),
(short) glyph.bitmap_top(),
(short) glyph.advance().x(),
texture);
characters[c] = charData;
}

gameFont.characterDatas(characters);

FreeType.FT_Done_Face(ftFace);
FreeType.FT_Done_FreeType(ftLibrary.address());

return gameFont;
}

private static short readShort(FileInputStream fis) throws IOException {
byte b1 = (byte) fis.read();
byte b2 = (byte) fis.read();
Expand Down
41 changes: 36 additions & 5 deletions src/main/java/visuals/rendering/text/CharacterData.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package visuals.rendering.text;

import visuals.lwjgl.render.Texture;

/**
* Information about a character in a bitmap font. The fields are all in pixels, except for {@link CharacterData#page}.
* Information about a character in a bitmap font. The fields are all in pixels,
* except for {@link CharacterData#page}.
*
* @author Jay
*/
Expand All @@ -24,12 +27,14 @@ public final class CharacterData {
*/
private final int height;
/**
* The horizontal offset of the character when it is displayed. This is usually a small number.
* The horizontal offset of the character when it is displayed. This is usually
* a small number.
*/
private final int xOffset;
/**
* The vertical offset of the character when it is displayed.
* For example, the letter 'g' has a larger yOffset than 'l' because it is offset downwards.
* For example, the letter 'g' has a larger yOffset than 'l' because it is
* offset downwards.
*/
private final int yOffset;
/**
Expand All @@ -39,8 +44,18 @@ public final class CharacterData {
private final int xAdvance;
/**
* The index of the bitmap image that this character is on. This is usually 0.
* <br>
* <br>
* Mutually exclusive with {@link CharacterData#texture}.
*/
private int page;
/**
* The texture that this character is on.
* <br>
* <br>
* Mutually exclusive with {@link CharacterData#page}.
*/
private final int page;
private Texture texture;

public CharacterData(int x, int y, int width, int height, int xOffset, int yOffset, int xAdvance, int page) {
this.x = x;
Expand All @@ -53,10 +68,26 @@ public CharacterData(int x, int y, int width, int height, int xOffset, int yOffs
this.page = page;
}

public CharacterData(short x, short y, short width, short height, short xOffset, short yOffset, short xAdvance, short page) {
public CharacterData(int x, int y, int width, int height, int xOffset, int yOffset, int xAdvance, Texture texture) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.xOffset = xOffset;
this.yOffset = yOffset;
this.xAdvance = xAdvance;
this.texture = texture;
}

public CharacterData(short x, short y, short width, short height, short xOffset, short yOffset, short xAdvance,
short page) {
this(x, y, width, height, xOffset, yOffset, xAdvance, (int) page);
}

public CharacterData(int x, int y, int width, int height, int xOffset, int yOffset, int xAdvance) {
this(x, y, width, height, xOffset, yOffset, xAdvance, 0);
}

public int x() {
return x;
}
Expand Down
39 changes: 36 additions & 3 deletions src/main/java/visuals/rendering/text/GameFont.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,39 @@

public final class GameFont {

public static long FONT_INDEX = 0;

/**
* The global index of the font.
*/
private final long fontIndex;

private final String name;
private final int fontSize;
private final CharacterData[] characterDatas;
private CharacterData[] characterDatas;
private final Texture texture;

public GameFont(String name, int fontSize, Texture texture) {
public GameFont(String name, int fontSize, Texture texture, long fontIndex) {
this.name = name;
this.fontSize = fontSize;
characterDatas = new CharacterData[128];
this.texture = texture;
this.fontIndex = fontIndex;
}

public GameFont(String name, int fontSize, CharacterData[] characterDatas, long fontIndex) {
this.name = name;
this.fontSize = fontSize;
this.characterDatas = characterDatas;
this.texture = null;
this.fontIndex = fontIndex;
}

public GameFont(String name, int fontSize, CharacterData[] characterDatas) {
this.name = name;
this.fontSize = fontSize;
this.characterDatas = characterDatas;
this.texture = null;
}

public String getName() {
Expand All @@ -28,12 +51,22 @@ public CharacterData[] getCharacterDatas() {
return characterDatas;
}

public void characterDatas(CharacterData[] characterDatas) {
this.characterDatas = characterDatas;
}

public Texture texture() {
return texture;
}

public void delete() {
texture.delete();
if (texture != null) {
texture.delete();
}
}

public static long getFontIndex() {
return FONT_INDEX++;
}

}
Loading