2013-03-23 18:16:05 -07:00

282 lines
8.1 KiB
Java

package mods.tinker.tconstruct.client;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.Tessellator;
import org.lwjgl.opengl.GL11;
/**
*
* @author TheObliterator
*
* A class to create and draw true type
* fonts onto the Minecraft game engine.
*/
public class CustomFont
{
private int texID;
private int[] xPos;
private int[] yPos;
private int startChar;
private int endChar;
private FontMetrics metrics;
/**
* Instantiates the font, filling in default start
* and end character parameters.
*
* 'new CustomFont(ModLoader.getMinecraftInstance(),
* "Arial", 12);
*
* @param mc The Minecraft instance for the font to be bound to.
* @param fontName The name of the font to be drawn.
* @param size The size of the font to be drawn.
*/
public CustomFont(Minecraft mc, Object font, int size)
{
this(mc, font, size, 0, 4000);
}
/**
* Instantiates the font, pre-rendering a sprite
* font image by using a true type font on a
* bitmap. Then allocating that bitmap to the
* Minecraft rendering engine for later use.
*
* 'new CustomFont(ModLoader.getMinecraftInstance(),
* "Arial", 12, 32, 126);'
*
* @param mc The Minecraft instance for the font to be bound to.
* @param fontName The name of the font to be drawn.
* @param size The size of the font to be drawn.
* @param startChar The starting ASCII character id to be drawable. (Default 32)
* @param endChar The ending ASCII character id to be drawable. (Default 126)
*/
public CustomFont(Minecraft mc, Object font, int size, int startChar, int endChar)
{
this.startChar = startChar;
this.endChar = endChar;
xPos = new int[endChar - startChar];
yPos = new int[endChar - startChar];
// Create a bitmap and fill it with a transparent color as well
// as obtain a Graphics instance which can be drawn on.
// NOTE: It is CRUICIAL that the size of the image is 256x256, if
// it is not the Minecraft engine will not draw it properly.
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
try
{
if (font instanceof String)
{
String fontName = (String) font;
if (fontName.contains("/"))
g.setFont(Font.createFont(Font.TRUETYPE_FONT, new File(fontName)).deriveFont((float) size));
else
g.setFont(new Font(fontName, 0, size));
}
else if (font instanceof InputStream)
{
g.setFont(Font.createFont(Font.TRUETYPE_FONT, (InputStream) font).deriveFont((float) size));
}
else if (font instanceof File)
{
g.setFont(Font.createFont(Font.TRUETYPE_FONT, (File) font).deriveFont((float) size));
}
}
catch (Exception e)
{
e.printStackTrace();
}
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0, 0, 256, 256);
g.setColor(Color.white);
metrics = g.getFontMetrics();
// Draw the specified range of characters onto
// the new bitmap, spacing according to the font
// widths. Also allocating positions of characters
// on the bitmap to two arrays which will be used
// later when drawing.
int x = 2;
int y = 2;
for (int i = startChar; i < endChar; i++)
{
g.drawString("" + ((char) i), x, y + g.getFontMetrics().getAscent());
xPos[i - startChar] = x;
yPos[i - startChar] = y - metrics.getMaxDescent();
x += metrics.stringWidth("" + (char) i) + 2;
if (x >= 250 - metrics.getMaxAdvance())
{
x = 2;
y += metrics.getMaxAscent() + metrics.getMaxDescent() + size / 2;
}
}
// Render the finished bitmap into the Minecraft
// graphics engine.
texID = mc.renderEngine.allocateAndSetupTexture(img);
}
/**
* Draws a given string with an automatically
* calculated shadow below it.
* @param gui The gui/subclass to be drawn on
* @param text The string to be drawn
* @param x The x position to start drawing
* @param y The y position to start drawing
* @param color The color of the non-shadowed text (Hex)
*/
public void drawStringS (Gui gui, String text, int x, int y, int color)
{
int l = color & 0xff000000;
int shade = (color & 0xfcfcfc) >> 2;
shade += l;
drawString(gui, text, x + 1, y + 1, shade);
drawString(gui, text, x, y, color);
}
/**
* Draws a given string onto a gui/subclass.
* @param gui The gui/subclass to be drawn on
* @param text The string to be drawn
* @param x The x position to start drawing
* @param y The y position to start drawing
* @param color The color of the non-shadowed text (Hex)
*/
public void drawString (Gui gui, String text, int x, int y, int color)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glEnable(3553 /*GL_TEXTURE_2D*/);
GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/, texID);
float red = (float) (color >> 16 & 0xff) / 255F;
float green = (float) (color >> 8 & 0xff) / 255F;
float blue = (float) (color & 0xff) / 255F;
float alpha = (float) (color >> 24 & 0xff) / 255F;
GL11.glColor4f(red, green, blue, alpha);
int startX = x;
for (int i = 0; i < text.length(); i++)
{
char c = text.charAt(i);
if (c == '\\')
{
char type = text.charAt(i + 1);
if (type == 'n')
{
y += metrics.getAscent() + 2;
x = startX;
}
i++;
continue;
}
drawChar(gui, c, x, y);
x += metrics.getStringBounds("" + c, null).getWidth();
}
}
/**
* Returns the created FontMetrics
* which is used to retrive various
* information about the True Type Font
* @return FontMetrics of the created font.
*/
public FontMetrics getMetrics ()
{
return metrics;
}
/**
* Gets the drawing width of a given
* string of string.
* @param text The string to be measured
* @return The width of the given string.
*/
public int getStringWidth (String text)
{
return (int) getBounds(text).getWidth();
}
/**
* Gets the drawing height of a given
* string of string.
* @param text The string to be measured
* @return The height of the given string.
*/
public int getStringHeight (String text)
{
return (int) getBounds(text).getHeight();
}
/**
* A method that returns a Rectangle that
* contains the width and height demensions
* of the given string.
* @param text The string to be measured
* @return Rectangle containing width and height that
* the text will consume when drawn.
*/
private Rectangle getBounds (String text)
{
int w = 0;
int h = 0;
int tw = 0;
for (int i = 0; i < text.length(); i++)
{
char c = text.charAt(i);
if (c == '\\')
{
char type = text.charAt(i + 1);
if (type == 'n')
{
h += metrics.getAscent() + 2;
if (tw > w)
w = tw;
tw = 0;
}
i++;
continue;
}
tw += metrics.stringWidth("" + c);
}
if (tw > w)
w = tw;
h += metrics.getAscent();
return new Rectangle(0, 0, w, h);
}
/**
* Private drawing method used within other
* drawing methods.
*/
private void drawChar (Gui gui, char c, int x, int y)
{
Rectangle2D bounds = metrics.getStringBounds("" + c, null);
drawTexturedModalRect(x, y, xPos[(byte) c - startChar], yPos[(byte) c - startChar], (int) bounds.getWidth(), (int) bounds.getHeight() + metrics.getMaxDescent());
}
public void drawTexturedModalRect(int x, int y, int u, int v, int width, int height)
{
float offsetWidth = 0.00390625F;
float offsetHeight = 0.00390625F;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((x + 0), (y + height), 0, ((u + 0) * offsetWidth), ((v + height) * offsetHeight));
tessellator.addVertexWithUV((x + width), (y + height), 0, ((u + width) * offsetWidth), ((v + height) * offsetHeight));
tessellator.addVertexWithUV((x + width), (y + 0), 0, ((u + width) * offsetWidth), ((v + 0) * offsetHeight));
tessellator.addVertexWithUV((x + 0), (y + 0), 0, ((u + 0) * offsetWidth), ((v + 0) * offsetHeight));
tessellator.draw();
}
}