LiteCraft/src/main/java/io/github/hydos/ginger/engine/font/MetaFile.java

198 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 com.github.halotroop.litecraft.LiteCraftMain;
/** 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) LiteCraftMain.width / (double) LiteCraftMain.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 / 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);
}
}