Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.displee.render.font;
- import lombok.AllArgsConstructor;
- import org.lwjgl.BufferUtils;
- import org.lwjgl.opengl.GL11;
- import java.awt.*;
- import java.awt.image.BufferedImage;
- import java.awt.image.DataBuffer;
- import java.awt.image.DataBufferByte;
- import java.awt.image.DataBufferInt;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.IntBuffer;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * A TrueType font implementation originally for Slick, edited for Bobjob's Engine
- * @original author James Chambers (Jimmy)
- * @original author Jeremy Adams (elias4444)
- * @original author Kevin Glass (kevglass)
- * @original author Peter Korzuszek (genail)
- * @new version edited by David Aaron Muhar (bobjob)
- */
- public class TrueTypeFont {
- public final static int ALIGN_LEFT = 0, ALIGN_RIGHT = 1, ALIGN_CENTER = 2;
- /**
- * Array that holds necessary information about the font characters
- */
- private IntObject[] charArray = new IntObject[256];
- /**
- * Map of user defined font characters (Character <-> IntObject)
- */
- private Map customChars = new HashMap();
- /**
- * Boolean flag on whether AntiAliasing is enabled or not
- */
- private boolean antiAlias;
- /**
- * Font's size
- */
- private int fontSize = 0;
- /**
- * Font's height
- */
- private int fontHeight = 0;
- /**
- * Texture used to cache the font 0-255 characters
- */
- private int fontTextureID;
- /**
- * Default font texture width
- */
- private int textureWidth = 512;
- /**
- * Default font texture height
- */
- private int textureHeight = 512;
- /**
- * A reference to Java's AWT Font that we create our font texture from
- */
- private Font font;
- /**
- * The font metrics for our Java AWT font
- */
- private FontMetrics fontMetrics;
- private int correctL = 9, correctR = 8;
- private class IntObject {
- /**
- * Character's width
- */
- public int width;
- /**
- * Character's height
- */
- public int height;
- /**
- * Character's stored x position
- */
- public int storedX;
- /**
- * Character's stored y position
- */
- public int storedY;
- }
- public TrueTypeFont(Font font, boolean antiAlias, char[] additionalChars) {
- this.font = font;
- this.fontSize = font.getSize() + 3;
- this.antiAlias = antiAlias;
- createSet(additionalChars);
- fontHeight -= 1;
- if (fontHeight <= 0) {
- fontHeight = 1;
- }
- }
- public TrueTypeFont(Font font, boolean antiAlias) {
- this(font, antiAlias, null);
- }
- public void setCorrection(boolean on) {
- if (on) {
- correctL = 2;
- correctR = 1;
- } else {
- correctL = 0;
- correctR = 0;
- }
- }
- private BufferedImage getFontImage(char ch) {
- // Create a temporary image to extract the character's size
- BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = (Graphics2D) tempfontImage.getGraphics();
- if (antiAlias == true) {
- g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- }
- g.setFont(font);
- fontMetrics = g.getFontMetrics();
- int charwidth = fontMetrics.charWidth(ch) + 8;
- if (charwidth <= 0) {
- charwidth = 7;
- }
- int charheight = fontMetrics.getHeight() + 3;
- if (charheight <= 0) {
- charheight = fontSize;
- }
- // Create another image holding the character we are creating
- BufferedImage fontImage;
- fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
- Graphics2D gt = (Graphics2D) fontImage.getGraphics();
- if (antiAlias == true) {
- gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- }
- gt.setFont(font);
- gt.setColor(Color.WHITE);
- int charx = 3;
- int chary = 1;
- gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent());
- //fontImage = ImageUtils.flipVertically(fontImage);
- //fontImage = ImageUtils.flipHorizontally(fontImage);
- //fontImage = ImageUtils.flipHorizontallyAndVertically(fontImage);
- return fontImage;
- }
- private void createSet(char[] customCharsArray) {
- // If there are custom chars then I expand the font texture twice
- if (customCharsArray != null && customCharsArray.length > 0) {
- textureWidth *= 2;
- }
- // In any case this should be done in other way. Texture with size 512x512
- // can maintain only 256 characters with resolution of 32x32. The texture
- // size should be calculated dynamicaly by looking at character sizes.
- try {
- BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = (Graphics2D) imgTemp.getGraphics();
- g.setColor(new Color(0, 0, 0, 1));
- g.fillRect(0, 0, textureWidth, textureHeight);
- int rowHeight = 0;
- int positionX = 0;
- int positionY = 0;
- int customCharsLength = (customCharsArray != null) ? customCharsArray.length : 0;
- for (int i = 0; i < 256 + customCharsLength; i++) {
- // get 0-255 characters and then custom characters
- char ch = (i < 256) ? (char) i : customCharsArray[i - 256];
- BufferedImage fontImage = getFontImage(ch);
- IntObject newIntObject = new IntObject();
- newIntObject.width = fontImage.getWidth();
- newIntObject.height = fontImage.getHeight();
- if (positionX + newIntObject.width >= textureWidth) {
- 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;
- }
- // Draw it here
- g.drawImage(fontImage, positionX, positionY, null);
- positionX += newIntObject.width;
- if (i < 256) { // standard characters
- charArray[i] = newIntObject;
- } else { // custom characters
- customChars.put(new Character(ch), newIntObject);
- }
- fontImage = null;
- }
- fontTextureID = loadImage(imgTemp);
- //.getTexture(font.toString(), imgTemp);
- } catch (Exception e) {
- System.err.println("Failed to create font.");
- e.printStackTrace();
- }
- }
- private void drawQuad(float drawX, float drawY, float drawX2, float drawY2, float srcX, float srcY, float srcX2, float srcY2, float z) {
- float DrawWidth = drawX2 - drawX;
- float DrawHeight = drawY2 - drawY;
- float TextureSrcX = srcX / textureWidth;
- float TextureSrcY = srcY / textureHeight;
- float SrcWidth = srcX2 - srcX;
- float SrcHeight = srcY2 - srcY;
- float RenderWidth = (SrcWidth / textureWidth);
- float RenderHeight = (SrcHeight / textureHeight);
- GL11.glTexCoord2f(TextureSrcX, TextureSrcY);
- GL11.glVertex3f(drawX, drawY, z);
- GL11.glTexCoord2f(TextureSrcX, TextureSrcY + RenderHeight);
- GL11.glVertex3f(drawX, drawY + DrawHeight, z);
- GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight);
- GL11.glVertex3f(drawX + DrawWidth, drawY + DrawHeight, z);
- GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY);
- GL11.glVertex3f(drawX + DrawWidth, drawY, z);
- //GL11.glPopMatrix();
- }
- public int getWidth(String whatchars) {
- int totalwidth = 0;
- IntObject intObject = null;
- int currentChar = 0;
- for (int i = 0; i < whatchars.length(); i++) {
- currentChar = whatchars.charAt(i);
- if (currentChar < 256) {
- intObject = charArray[currentChar];
- } else {
- intObject = (IntObject) customChars.get(new Character((char) currentChar));
- }
- if (intObject != null) {
- totalwidth += intObject.width;
- }
- }
- return totalwidth;
- }
- public int getHeight() {
- return fontHeight;
- }
- public int getHeight(String HeightString) {
- return fontHeight;
- }
- public int getLineHeight() {
- return fontHeight;
- }
- public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY) {
- drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, ALIGN_LEFT);
- }
- public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY, int format) {
- drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, format);
- }
- public void drawString(float x, float y, float z, String whatchars, int startIndex, int endIndex, float scaleX, float scaleY, int format) {
- IntObject intObject = null;
- int charCurrent;
- int totalwidth = 0;
- int i = startIndex, d, c;
- float startY = 0;
- switch (format) {
- case ALIGN_RIGHT: {
- d = -1;
- c = correctR;
- while (i < endIndex) {
- if (whatchars.charAt(i) == 'n') {
- startY -= fontHeight;
- }
- i++;
- }
- break;
- }
- case ALIGN_CENTER: {
- for (int l = startIndex; l <= endIndex; l++) {
- charCurrent = whatchars.charAt(l);
- if (charCurrent == 'n') {
- break;
- }
- if (charCurrent < 256) {
- intObject = charArray[charCurrent];
- } else {
- intObject = (IntObject) customChars.get(new Character((char) charCurrent));
- }
- totalwidth += intObject.width - correctL;
- }
- totalwidth /= -2;
- }
- case ALIGN_LEFT:
- default: {
- d = 1;
- c = correctL;
- break;
- }
- }
- java.util.List<QuadObject> list = new ArrayList<>(endIndex - startIndex);
- while (i >= startIndex && i <= endIndex) {
- charCurrent = whatchars.charAt(i);
- if (charCurrent < 256) {
- intObject = charArray[charCurrent];
- } else {
- intObject = (IntObject) customChars.get(new Character((char) charCurrent));
- }
- if (intObject != null) {
- if (d < 0) {
- totalwidth += (intObject.width - c) * d;
- }
- if (charCurrent == 'n') {
- startY -= fontHeight * d;
- totalwidth = 0;
- if (format == ALIGN_CENTER) {
- for (int l = i + 1; l <= endIndex; l++) {
- charCurrent = whatchars.charAt(l);
- if (charCurrent == 'n') {
- break;
- }
- if (charCurrent < 256) {
- intObject = charArray[charCurrent];
- } else {
- intObject = (IntObject) customChars.get(new Character((char) charCurrent));
- }
- totalwidth += intObject.width - correctL;
- }
- totalwidth /= -2;
- }
- //if center get next lines total width/2;
- } else {
- QuadObject quad = new QuadObject((totalwidth + intObject.width) * scaleX + x, startY * scaleY + y, totalwidth * scaleX + x, (startY + intObject.height) * scaleY + y, intObject.storedX + intObject.width, intObject.storedY + intObject.height, intObject.storedX, intObject.storedY, z);
- list.add(quad);
- if (d > 0) {
- totalwidth += (intObject.width - c) * d;
- }
- }
- i += d;
- }
- }
- float centerX = 0;
- for(QuadObject quad : list) {
- centerX += quad.drawX + (quad.drawX2 - quad.drawX);
- }
- centerX /= 2.0f;
- float centerY = 0;
- for(QuadObject quad : list) {
- centerY += quad.drawY + (quad.drawY2 - quad.drawY);
- }
- centerY /= 2.0f;
- GL11.glTranslatef(centerX, centerY, z); // M1 - 2nd translation
- //GL11.glRotatef(ModelEditorConstants.rotation, 0.0f, 0.0f, 1.0f); // M2
- GL11.glTranslatef( -centerX, -centerY, -z);
- GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
- GL11.glBegin(GL11.GL_QUADS);
- for(QuadObject quad : list) {
- drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
- }
- GL11.glDisable(GL11.GL_TEXTURE_2D);
- GL11.glEnd();
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
- }
- public static int loadImage(BufferedImage bufferedImage) {
- try {
- short width = (short) bufferedImage.getWidth();
- short height = (short) bufferedImage.getHeight();
- //textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? (byte)32 : (byte)24;
- int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
- ByteBuffer byteBuffer;
- DataBuffer db = bufferedImage.getData().getDataBuffer();
- if (db instanceof DataBufferInt) {
- int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
- byte newI[] = new byte[intI.length * 4];
- for (int i = 0; i < intI.length; i++) {
- byte b[] = intToByteArray(intI[i]);
- int newIndex = i * 4;
- newI[newIndex] = b[1];
- newI[newIndex + 1] = b[2];
- newI[newIndex + 2] = b[3];
- newI[newIndex + 3] = b[0];
- }
- byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
- } else {
- byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
- }
- byteBuffer.flip();
- int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA;
- IntBuffer textureId = BufferUtils.createIntBuffer(1);
- ;
- GL11.glGenTextures(textureId);
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
- GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
- GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL11.GL_UNSIGNED_BYTE, byteBuffer.order(ByteOrder.nativeOrder()));
- return textureId.get(0);
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(-1);
- }
- return -1;
- }
- public static boolean isSupported(String fontname) {
- Font font[] = getFonts();
- for (int i = font.length - 1; i >= 0; i--) {
- if (font[i].getName().equalsIgnoreCase(fontname)) {
- return true;
- }
- }
- return false;
- }
- public static Font[] getFonts() {
- return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
- }
- public static byte[] intToByteArray(int value) {
- return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
- }
- public void destroy() {
- IntBuffer scratch = BufferUtils.createIntBuffer(1);
- scratch.put(0, fontTextureID);
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
- GL11.glDeleteTextures(scratch);
- }
- @AllArgsConstructor
- private class QuadObject {
- private float drawX;
- private float drawY;
- private float drawX2;
- private float drawY2;
- private float srcX;
- private float srcY;
- private float srcX2;
- private float srcY2;
- private float z;
- }
- }
- import com.displee.render.font.TrueTypeFont;
- import org.lwjgl.LWJGLException;
- import org.lwjgl.input.Mouse;
- import org.lwjgl.opengl.Display;
- import org.lwjgl.opengl.DisplayMode;
- import org.lwjgl.util.vector.Vector3f;
- import java.awt.*;
- import static org.lwjgl.opengl.GL11.*;
- import static org.lwjgl.util.glu.GLU.gluPerspective;
- public class Test3DFont {
- private static final int WIDTH = 800;
- private static final int HEIGHT = 600;
- private static final float FOV = 45f;
- private static final float NEAR = 0.1f;
- private static final float FAR = 1000f;
- private static boolean mousePressed;
- private static Vector3f mousePressedVector = new Vector3f();
- private static float scale = 0.05f;
- private static TrueTypeFont font;
- private static boolean running = true;
- public static void main(String[] args) throws Exception {
- initializeDisplay();
- font = new TrueTypeFont(new Font("serif", Font.PLAIN, 30), true);
- initializeGL();
- while(running) {
- glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- handleMouse();
- loadDefaultRotation();
- drawGrid();
- font.drawString(0, 0, 0, "Test", 0.1f, 0.1f);
- Display.sync(60);
- Display.update();
- }
- Display.destroy();
- }
- private static void initializeDisplay() throws LWJGLException {
- Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
- Display.create();
- setViewport();
- }
- private static void setViewport() {
- glViewport(0, 0, WIDTH, HEIGHT);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(FOV, (float) WIDTH / (float) HEIGHT, NEAR, FAR);
- glMatrixMode(GL_MODELVIEW);
- }
- private static void initializeGL() {
- glShadeModel(GL_SMOOTH);
- glEnable(GL_NORMALIZE);
- glEnable(GL_BLEND);
- glCullFace(GL_BACK);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- private static void handleMouse() {
- scale += Mouse.getDWheel() > 0 ? 0.005f : Mouse.getDWheel() < 0 ? -0.005f : 0;
- int x = Mouse.getY();
- int y = Mouse.getX();
- if (!mousePressed) {
- mousePressed = Mouse.isButtonDown(0);
- if (mousePressed) {
- mousePressedVector.x = x;
- mousePressedVector.y = y;
- }
- } else if (!Mouse.isButtonDown(0)) {
- mousePressed = false;
- }
- if (!mousePressed) {
- return;
- }
- float xDifference = x - mousePressedVector.x;
- float yDifference = y - mousePressedVector.y;
- mousePressedVector.x += xDifference;
- mousePressedVector.y += yDifference;
- }
- private static void loadDefaultRotation() {
- glLoadIdentity();
- Vector3f cameraPosition = new Vector3f();
- glTranslatef(cameraPosition.x, cameraPosition.y, -10);
- glRotatef(mousePressedVector.x, 1.0F, 0.0F, 0.0F);
- glRotatef(mousePressedVector.y, 0.0F, 1.0F, 0.0F);
- glRotatef(mousePressedVector.z, 0.0F, 0.0F, 1.0F);
- glScalef(scale, scale, scale);
- }
- private static void drawGrid() {
- glColor4f(0.7176471f, 0.7176471f, 0.7176471f, 1.0f);
- glBegin(GL_LINES);
- float size = 50;
- float step = 10;
- for (float i = -size; i <= size; i += step) {
- glVertex3f(i, 0, size);
- glVertex3f(i, 0, -size);
- glVertex3f(size, 0, i);
- glVertex3f(-size, 0, i);
- }
- glEnd();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement