package gameEngine.views;
import org.lwjgl.BufferUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
public class Font {
/**
* Contains the glyphs for each char.
*/
private final Map<Character, Glyph> glyphs;
private Texture texture;
private int fontHeight;
public Map<Character, Glyph> getGlyphs(){
return glyphs;
}
public Texture getTexture() {
return texture;
}
public int getFontHeight(){
return fontHeight;
}
/**
* Creates a font from an AWT Font.
*
* @param font The AWT Font
* @param antiAlias Wheter the font should be antialiased or not
*/
public Font(java.awt.Font font, boolean antiAlias) {
glyphs = new HashMap<>();
createFontTexture(font, antiAlias);
}
private void createFontTexture(java.awt.Font font, boolean antiAlias) {
texture = new Texture();
/* Loop through the characters to get charWidth and charHeight */
int imageWidth = 0;
int imageHeight = 0;
/* Start at char #32, because ASCII 0 to 31 are just control codes */
for (int i = 32; i < 256; i++) {
if (i == 127) {
/* ASCII 127 is the DEL control code, so we can skip it */
continue;
}
char c = (char) i;
BufferedImage ch = createCharImage(font, c, antiAlias);
if (ch == null) {
/* If char image is null that font does not contain the char */
continue;
}
imageWidth += ch.getWidth();
imageHeight = Math.max(imageHeight, ch.getHeight());
}
fontHeight = imageHeight;
/* Image for the texture */
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
int x = 0;
/* Create image for the standard chars, again we omit ASCII 0 to 31
* because they are just control codes */
for (int i = 32; i < 256; i++) {
if (i == 127) {
/* ASCII 127 is the DEL control code, so we can skip it */
continue;
}
char c = (char) i;
BufferedImage charImage = createCharImage(font, c, antiAlias);
if (charImage == null) {
/* If char image is null that font does not contain the char */
continue;
}
int charWidth = charImage.getWidth();
int charHeight = charImage.getHeight();
/* Create glyph and draw char on image */
Glyph ch = new Glyph(charWidth, charHeight, x, image.getHeight() - charHeight, 0f);
g.drawImage(charImage, x, 0, null);
x += ch.width;
glyphs.put(c, ch);
}
/* Flip image Horizontal to get the origin to bottom left */
/*AffineTransform transform = AffineTransform.getScaleInstance(1f, -1f);
transform.translate(0, -image.getHeight());
AffineTransformOp operation = new AffineTransformOp(transform,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
image = operation.filter(image, null);*/
/* Get charWidth and charHeight of image */
int width = image.getWidth();
int height = image.getHeight();
/* Get pixel data of image */
int[] pixelsRaw = new int[width * height];
image.getRGB(0, 0, width, height, pixelsRaw, 0, width);
/* Put pixel data into a ByteBuffer */
ByteBuffer pixels = BufferUtils.createByteBuffer(width * height * 4);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
/* Pixel as RGBA: 0xAARRGGBB */
int pixel = pixelsRaw[i * width + j];
/* Red component 0xAARRGGBB >> 16 = 0x0000AARR */
pixels.put((byte) ((pixel >> 16) & 0xFF));
/* Green component 0xAARRGGBB >> 8 = 0x00AARRGG */
pixels.put((byte) ((pixel >> 8) & 0xFF));
/* Blue component 0xAARRGGBB >> 0 = 0xAARRGGBB */
pixels.put((byte) (pixel & 0xFF));
/* Alpha component 0xAARRGGBB >> 24 = 0x000000AA */
pixels.put((byte) ((pixel >> 24) & 0xFF));
}
}
/* Do not forget to flip the buffer! */
pixels.flip();
texture.setTextureData(width, height, pixels);
texture.init();
}
/**
* Creates a char image from specified AWT font and char.
*
* @param font The AWT font
* @param c The char
* @param antiAlias Wheter the char should be antialiased or not
* @return Char image
*/
private BufferedImage createCharImage(java.awt.Font font, char c, boolean antiAlias) {
/* Creating temporary image to extract character size */
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
if (antiAlias) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
g.dispose();
/* Get char charWidth and charHeight */
int charWidth = metrics.charWidth(c);
int charHeight = metrics.getHeight();
/* Check if charWidth is 0 */
if (charWidth == 0) {
return null;
}
/* Create image for holding the char */
image = new BufferedImage(charWidth, charHeight, BufferedImage.TYPE_INT_ARGB);
g = image.createGraphics();
if (antiAlias) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.setFont(font);
g.setPaint(Color.RED); //色指定部分
g.drawString(String.valueOf(c), 0, metrics.getAscent());
g.dispose();
return image;
}
public void delete() {
texture.delete();
}
}