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.BLACK); g.drawString(String.valueOf(c), 0, metrics.getAscent()); g.dispose(); return image; } public void delete() { texture.delete(); } }