package net.wurstclient.font; import static org.lwjgl.opengl.GL11.*; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import net.minecraft.client.renderer.texture.TextureUtil; public class WurstFont { public int IMAGE_WIDTH = 1024; public int IMAGE_HEIGHT = 1024; private int texID; private final IntObject[] chars = new IntObject[2048]; private final Font font; private boolean antiAlias; private int fontHeight = -1; private int charOffset = 8; public WurstFont(final Font font, final boolean antiAlias, final int charOffset) { this.font = font; this.antiAlias = antiAlias; this.charOffset = charOffset; setupTexture(antiAlias); } public WurstFont(final Font font, final boolean antiAlias) { this.font = font; this.antiAlias = antiAlias; charOffset = 8; setupTexture(antiAlias); } private void setupTexture(final boolean antiAlias) { if(font.getSize() <= 15) { IMAGE_WIDTH = 256; IMAGE_HEIGHT = 256; } if(font.getSize() <= 43) { IMAGE_WIDTH = 512; IMAGE_HEIGHT = 512; }else if(font.getSize() <= 91) { IMAGE_WIDTH = 1024; IMAGE_HEIGHT = 1024; }else { IMAGE_WIDTH = 2048; IMAGE_HEIGHT = 2048; } final BufferedImage img = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB); final Graphics2D g = (Graphics2D)img.getGraphics(); g.setFont(font); g.setColor(new Color(255, 255, 255, 0)); g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); g.setColor(Color.white); int rowHeight = 0; int positionX = 0; int positionY = 0; for(int i = 0; i < 2048; i++) { final char ch = (char)i; final BufferedImage fontImage = getFontImage(ch, antiAlias); final IntObject newIntObject = new IntObject(); newIntObject.width = fontImage.getWidth(); newIntObject.height = fontImage.getHeight(); if(positionX + newIntObject.width >= IMAGE_WIDTH) { positionX = 0; positionY += rowHeight; rowHeight = 0; } newIntObject.storedX = positionX; newIntObject.storedY = positionY; if(newIntObject.height > fontHeight) fontHeight = newIntObject.height; if(newIntObject.height > rowHeight) rowHeight = newIntObject.height; chars[i] = newIntObject; g.drawImage(fontImage, positionX, positionY, null); positionX += newIntObject.width; } try { texID = TextureUtil.uploadTextureImageAllocate( TextureUtil.glGenTextures(), img, true, true); }catch(final NullPointerException e) { e.printStackTrace(); } } private BufferedImage getFontImage(final char ch, final boolean antiAlias) { final BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); final Graphics2D g = (Graphics2D)tempfontImage.getGraphics(); if(antiAlias) g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); else g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g.setFont(font); final FontMetrics fontMetrics = g.getFontMetrics(); int charwidth = fontMetrics.charWidth(ch) + 8; if(charwidth <= 0) charwidth = 7; int charheight = fontMetrics.getHeight() + 3; if(charheight <= 0) charheight = font.getSize(); final BufferedImage fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB); final Graphics2D gt = (Graphics2D)fontImage.getGraphics(); if(antiAlias) gt.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); else gt.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); gt.setFont(font); gt.setColor(Color.WHITE); final int charx = 3; final int chary = 1; gt.drawString(String.valueOf(ch), charx, chary + fontMetrics.getAscent()); return fontImage; } public void drawChar(final char c, final float x, final float y) throws ArrayIndexOutOfBoundsException { try { drawQuad(x, y, chars[c].width, chars[c].height, chars[c].storedX, chars[c].storedY, chars[c].width, chars[c].height); }catch(final Exception e) { e.printStackTrace(); } } private void drawQuad(final float x, final float y, final float width, final float height, final float srcX, final float srcY, final float srcWidth, final float srcHeight) { final float renderSRCX = srcX / IMAGE_WIDTH, renderSRCY = srcY / IMAGE_HEIGHT, renderSRCWidth = srcWidth / IMAGE_WIDTH, renderSRCHeight = srcHeight / IMAGE_HEIGHT; glBegin(GL_TRIANGLES); glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); glVertex2d(x + width, y); glTexCoord2f(renderSRCX, renderSRCY); glVertex2d(x, y); glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); glVertex2d(x, y + height); glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); glVertex2d(x, y + height); glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY + renderSRCHeight); glVertex2d(x + width, y + height); glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); glVertex2d(x + width, y); glEnd(); } public void drawString(final String text, double x, double y, final Color color, final boolean shadow) { x *= 2; y = y * 2 - 2; glPushMatrix(); // glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_NICEST); glScaled(0.25D, 0.25D, 0.25D); // glColor4f(1.0F, 1.0F, 1.0F, 1.0F); TextureUtil.bindTexture(texID); glColor(shadow ? new Color(0.05F, 0.05F, 0.05F, color.getAlpha() / 255F) : color); final int size = text.length(); for(int indexInString = 0; indexInString < size; indexInString++) { final char character = text.charAt(indexInString); if(character < chars.length && character >= 0) { drawChar(character, (float)x, (float)y); x += chars[character].width - charOffset; } } glPopMatrix(); } public void glColor(final Color color) { final float red = color.getRed() / 255F, green = color.getGreen() / 255F, blue = color.getBlue() / 255F, alpha = color.getAlpha() / 255F; glColor4f(red, green, blue, alpha); } public int getStringHeight(final String text) { int lines = 1; for(char c : text.toCharArray()) if(c == '\n') lines++; return (fontHeight - charOffset) / 2 * lines; } public int getHeight() { return (fontHeight - charOffset) / 2; } public int getStringWidth(final String text) { int width = 0; for(final char c : text.toCharArray()) if(c < chars.length && c >= 0) width += chars[c].width - charOffset; return width / 2; } public boolean isAntiAlias() { return antiAlias; } public void setAntiAlias(final boolean antiAlias) { if(this.antiAlias != antiAlias) { this.antiAlias = antiAlias; setupTexture(antiAlias); } } public Font getFont() { return font; } private class IntObject { public int width; public int height; public int storedX; public int storedY; } }