Archived
0

create FontEngine

This commit is contained in:
2015-09-18 12:41:13 +03:00
parent d2de0b850f
commit 786f90fa98

View File

@@ -0,0 +1,186 @@
package ru.dmitriymx.lwjgl.tools;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.opengl.GL11.*;
public class FontEngine {
private Font font;
private int fontSize;
private Texture glyphTexture;
private int texture_width = 128, texture_height = 128;
private Graphics2D g2d;
private boolean anti_aliasing = false;
private float[] color4f = new float[]{1f, 1f, 1f, 1f};
// int[] = texture_x, // 0
// texture_y, // 1
// visual_width, // 2
// visual_height, // 3
// visual_y, // 4
// visual_x, // 5
// widthChar // 6
private Map<Character, int[]> charMap = new HashMap<>();
private int offset_x = 0, offset_y = 0, max_height = 0;
private Tessellator tess = Tessellator.getInstance();
public static void importFont(InputStream inputStream) throws IOException, FontFormatException {
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(Font.createFont(Font.TRUETYPE_FONT, inputStream));
}
public FontEngine(String fontName, int size) {
this(fontName, size, false);
}
public FontEngine(String fontName, int size, boolean antiAliasing) {
this(new Font(fontName, Font.PLAIN, size), antiAliasing);
}
public FontEngine(Font font) {
this(font, false);
}
public FontEngine(Font font, boolean antiAliasing) {
this.font = font;
this.fontSize = font.getSize();
glyphTexture = new Texture(new BufferedImage(texture_width, texture_height, BufferedImage.TYPE_INT_ARGB));
g2d = glyphTexture.getImage().createGraphics();
if (antiAliasing) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
anti_aliasing = true;
}
g2d.setColor(Color.WHITE);
g2d.setFont(font);
}
public void initializeString(String string) {
char[] chars = string.toCharArray();
for (char chr : chars) {
if (!charMap.containsKey(chr)) {
cache_char(chr, true);
}
}
glyphTexture.updateTexture();
}
public int getFontSize() {
return fontSize;
}
public void setColor(float red, float green, float blue) {
setColor(red, green, blue, 1f);
}
public void setColor(float red, float green, float blue, float alpha) {
this.color4f[0] = red;
this.color4f[1] = green;
this.color4f[2] = blue;
this.color4f[3] = alpha;
}
public void drawString(String string) {
glyphTexture.bind();
char[] chars = string.toCharArray();
int[] data;
float current_x = 0;
for (char ch : chars) {
if (!charMap.containsKey(ch)) data = cache_char(ch);
else data = charMap.get(ch);
current_x -= data[5];
draw_char(data, current_x);
current_x += data[6];
}
}
private int[] cache_char(char chr) {
return cache_char(chr, false);
}
private int[] cache_char(char chr, boolean dontUpdateTexture) {
int[] data = draw_char_in_texture(chr);
if (!dontUpdateTexture) glyphTexture.updateTexture();
offset_x += data[2] + 1;
if (max_height < offset_y + data[3]) {
max_height = offset_y + data[3];
}
charMap.put(chr, data);
return data;
}
private int[] draw_char_in_texture(char chr) {
GlyphVector glyphVector = font.createGlyphVector(g2d.getFontRenderContext(), String.valueOf(chr));
Rectangle visualBounds = glyphVector.getVisualBounds().getBounds();
FontMetrics fontMetrics = g2d.getFontMetrics();
int widthChar = fontMetrics.charWidth(chr) - visualBounds.x;
if (offset_y >= texture_height || (offset_y + visualBounds.height) > texture_height) {
regen_texture();
}
if (offset_x >= texture_width || (offset_x + visualBounds.width) > texture_width) {
offset_y = max_height + 1;
offset_x = 0;
}
g2d.drawGlyphVector(glyphVector, offset_x - visualBounds.x, offset_y - visualBounds.y);
return new int[]{offset_x, offset_y, visualBounds.width, visualBounds.height, ~visualBounds.y + 1, ~visualBounds.x + 1, widthChar};
}
private void regen_texture() {
// удваение размеров текстуры
texture_width *= 2;
texture_height *= 2;
// создание текстуры по новой
BufferedImage img = new BufferedImage(texture_width, texture_height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
if (anti_aliasing) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
}
g2d.setColor(Color.WHITE);
g2d.setFont(font);
// сброс "офсетов"
offset_y = 0;
offset_x = 0;
max_height = 0;
// отрисовка символов по новой
for (char chr : charMap.keySet()) {
cache_char(chr, true);
}
// обновление текстуры
glyphTexture.setImage(img);
glyphTexture.updateTexture();
}
private void draw_char(int[] data, float x) {
float d0 = glyphTexture.floatX(data[0]);
float d1 = glyphTexture.floatX(data[1]);
float d02 = glyphTexture.floatX(data[0] + data[2]);
float d13 = glyphTexture.floatY(data[1] + data[3]);
tess.startDrawingUseVA(GL_QUADS);
tess.setColor(1f,0f,0f).setTexture(d0, d1 ).addVertex(x, data[4], 0);
tess.setColor(0f,1f,0f).setTexture(d02, d1 ).addVertex(x + data[2], data[4], 0);
tess.setColor(0f,0f,1f).setTexture(d02, d13).addVertex(x + data[2], -data[3] + data[4], 0);
tess.setColor(1f,1f,0f).setTexture(d0, d13).addVertex(x, -data[3] + data[4], 0);
tess.drawVA();
}
}