214 lines
6.1 KiB
Java
214 lines
6.1 KiB
Java
package io.github.hydos.ginger.engine.font;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
import io.github.hydos.ginger.engine.io.Window;
|
|
|
|
/**
|
|
* Provides functionality for getting the values from a font file.
|
|
*
|
|
*
|
|
*/
|
|
public class MetaFile {
|
|
|
|
private static final int PAD_TOP = 0;
|
|
private static final int PAD_LEFT = 1;
|
|
private static final int PAD_BOTTOM = 2;
|
|
private static final int PAD_RIGHT = 3;
|
|
|
|
private static final int DESIRED_PADDING = 8;
|
|
|
|
private static final String SPLITTER = " ";
|
|
private static final String NUMBER_SEPARATOR = ",";
|
|
|
|
private double aspectRatio;
|
|
|
|
private double verticalPerPixelSize;
|
|
private double horizontalPerPixelSize;
|
|
private double spaceWidth;
|
|
private int[] padding;
|
|
private int paddingWidth;
|
|
private int paddingHeight;
|
|
|
|
private Map<Integer, Character> metaData = new HashMap<Integer, Character>();
|
|
|
|
private BufferedReader reader;
|
|
private Map<String, String> values = new HashMap<String, String>();
|
|
|
|
/**
|
|
* Opens a font file in preparation for reading.
|
|
*
|
|
* @param file
|
|
* - the font file.
|
|
*/
|
|
protected MetaFile(String file) {
|
|
this.aspectRatio = (double) Window.width / (double) Window.height;
|
|
openFile(file);
|
|
loadPaddingData();
|
|
loadLineSizes();
|
|
int imageWidth = getValueOfVariable("scaleW");
|
|
loadCharacterData(imageWidth);
|
|
close();
|
|
}
|
|
|
|
protected double getSpaceWidth() {
|
|
return spaceWidth;
|
|
}
|
|
|
|
protected Character getCharacter(int ascii) {
|
|
return metaData.get(ascii);
|
|
}
|
|
|
|
/**
|
|
* Read in the next line and store the variable values.
|
|
*
|
|
* @return {@code true} if the end of the file hasn't been reached.
|
|
*/
|
|
private boolean processNextLine() {
|
|
values.clear();
|
|
String line = null;
|
|
try {
|
|
line = reader.readLine();
|
|
} catch (IOException e1) {
|
|
}
|
|
if (line == null) {
|
|
return false;
|
|
}
|
|
for (String part : line.split(SPLITTER)) {
|
|
String[] valuePairs = part.split("=");
|
|
if (valuePairs.length == 2) {
|
|
values.put(valuePairs[0], valuePairs[1]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Gets the {@code int} value of the variable with a certain name on the
|
|
* current line.
|
|
*
|
|
* @param variable
|
|
* - the name of the variable.
|
|
* @return The value of the variable.
|
|
*/
|
|
private int getValueOfVariable(String variable) {
|
|
return Integer.parseInt(values.get(variable));
|
|
}
|
|
|
|
/**
|
|
* Gets the array of ints associated with a variable on the current line.
|
|
*
|
|
* @param variable
|
|
* - the name of the variable.
|
|
* @return The int array of values associated with the variable.
|
|
*/
|
|
private int[] getValuesOfVariable(String variable) {
|
|
String[] numbers = values.get(variable).split(NUMBER_SEPARATOR);
|
|
int[] actualValues = new int[numbers.length];
|
|
for (int i = 0; i < actualValues.length; i++) {
|
|
actualValues[i] = Integer.parseInt(numbers[i]);
|
|
}
|
|
return actualValues;
|
|
}
|
|
|
|
/**
|
|
* Closes the font file after finishing reading.
|
|
*/
|
|
private void close() {
|
|
try {
|
|
reader.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Opens the font file, ready for reading.
|
|
*
|
|
* @param file
|
|
* - the font file.
|
|
*/
|
|
private void openFile(String file) {
|
|
try {
|
|
reader = new BufferedReader(new InputStreamReader(Class.class.getResourceAsStream("/fonts/" + file)));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
System.err.println("Couldn't read font meta file!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads the data about how much padding is used around each character in
|
|
* the texture atlas.
|
|
*/
|
|
private void loadPaddingData() {
|
|
processNextLine();
|
|
this.padding = getValuesOfVariable("padding");
|
|
this.paddingWidth = padding[PAD_LEFT] + padding[PAD_RIGHT];
|
|
this.paddingHeight = padding[PAD_TOP] + padding[PAD_BOTTOM];
|
|
}
|
|
|
|
/**
|
|
* Loads information about the line height for this font in pixels, and uses
|
|
* this as a way to find the conversion rate between pixels in the texture
|
|
* atlas and screen-space.
|
|
*/
|
|
private void loadLineSizes() {
|
|
processNextLine();
|
|
int lineHeightPixels = getValueOfVariable("lineHeight") - paddingHeight;
|
|
verticalPerPixelSize = TextMeshCreator.LINE_HEIGHT / (double) lineHeightPixels;
|
|
horizontalPerPixelSize = verticalPerPixelSize / aspectRatio;
|
|
}
|
|
|
|
/**
|
|
* Loads in data about each character and stores the data in the
|
|
* {@link Character} class.
|
|
*
|
|
* @param imageWidth
|
|
* - the width of the texture atlas in pixels.
|
|
*/
|
|
private void loadCharacterData(int imageWidth) {
|
|
processNextLine();
|
|
processNextLine();
|
|
while (processNextLine()) {
|
|
Character c = loadCharacter(imageWidth);
|
|
if (c != null) {
|
|
metaData.put(c.getId(), c);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads all the data about one character in the texture atlas and converts
|
|
* it all from 'pixels' to 'screen-space' before storing. The effects of
|
|
* padding are also removed from the data.
|
|
*
|
|
* @param imageSize
|
|
* - the size of the texture atlas in pixels.
|
|
* @return The data about the character.
|
|
*/
|
|
private Character loadCharacter(int imageSize) {
|
|
int id = getValueOfVariable("id");
|
|
if (id == TextMeshCreator.SPACE_ASCII) {
|
|
this.spaceWidth = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
|
|
return null;
|
|
}
|
|
double xTex = ((double) getValueOfVariable("x") + (padding[PAD_LEFT] - DESIRED_PADDING)) / imageSize;
|
|
double yTex = ((double) getValueOfVariable("y") + (padding[PAD_TOP] - DESIRED_PADDING)) / imageSize;
|
|
int width = getValueOfVariable("width") - (paddingWidth - (2 * DESIRED_PADDING));
|
|
int height = getValueOfVariable("height") - ((paddingHeight) - (2 * DESIRED_PADDING));
|
|
double quadWidth = width * horizontalPerPixelSize;
|
|
double quadHeight = height * verticalPerPixelSize;
|
|
double xTexSize = (double) width / imageSize;
|
|
double yTexSize = (double) height / imageSize;
|
|
double xOff = (getValueOfVariable("xoffset") + padding[PAD_LEFT] - DESIRED_PADDING) * horizontalPerPixelSize;
|
|
double yOff = (getValueOfVariable("yoffset") + (padding[PAD_TOP] - DESIRED_PADDING)) * verticalPerPixelSize;
|
|
double xAdvance = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
|
|
return new Character(id, xTex, yTex, xTexSize, yTexSize, xOff, yOff, quadWidth, quadHeight, xAdvance);
|
|
}
|
|
}
|