parent
f5929f23b1
commit
da67300522
@ -1,20 +0,0 @@ |
|||||||
package mightypork.rogue.fonts; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Alignment |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public class Align { |
|
||||||
|
|
||||||
public static final int LEFT = -1; |
|
||||||
public static final int RIGHT = 1; |
|
||||||
public static final int TOP = 1; |
|
||||||
public static final int BOTTOM = -1; |
|
||||||
public static final int UP = 1; |
|
||||||
public static final int DOWN = -1; |
|
||||||
public static final int CENTER = 0; |
|
||||||
public static final int MIDDLE = 0; |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,216 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.FontFormatException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
|
||||||
|
import mightypork.rogue.loading.DeferredResource; |
||||||
|
import mightypork.rogue.loading.MustLoadInMainThread; |
||||||
|
import mightypork.utils.files.FileUtils; |
||||||
|
import mightypork.utils.math.color.RGB; |
||||||
|
import mightypork.utils.math.coord.Coord; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Font obtained from a resource file (TTF). |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class DeferredFont extends DeferredResource implements MustLoadInMainThread, GLFont { |
||||||
|
|
||||||
|
public static enum FontStyle |
||||||
|
{ |
||||||
|
PLAIN(Font.PLAIN), BOLD(Font.BOLD), ITALIC(Font.ITALIC), BOLD_ITALIC(Font.BOLD + Font.ITALIC); |
||||||
|
|
||||||
|
int numeric; |
||||||
|
|
||||||
|
|
||||||
|
private FontStyle(int style) { |
||||||
|
this.numeric = style; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private SlickFont font = null; |
||||||
|
private final double size; |
||||||
|
private final FontStyle style; |
||||||
|
private final boolean antiAlias; |
||||||
|
private final String extraChars; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font from resource |
||||||
|
* |
||||||
|
* @param resourcePath resource to load |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
*/ |
||||||
|
public DeferredFont(String resourcePath, String extraChars, double size) { |
||||||
|
this(resourcePath, extraChars, size, FontStyle.PLAIN, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font from resource |
||||||
|
* |
||||||
|
* @param resourcePath resource to load |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
* @param style font style |
||||||
|
*/ |
||||||
|
public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style) { |
||||||
|
this(resourcePath, extraChars, size, style, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font from resource |
||||||
|
* |
||||||
|
* @param resourcePath resource to load |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
* @param style font style |
||||||
|
* @param antialias use antialiasing |
||||||
|
*/ |
||||||
|
public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style, boolean antialias) { |
||||||
|
super(resourcePath); |
||||||
|
this.size = size; |
||||||
|
this.style = style; |
||||||
|
this.antiAlias = antialias; |
||||||
|
this.extraChars = extraChars; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected final void loadResource(String path) throws FontFormatException, IOException |
||||||
|
{ |
||||||
|
Font awtFont = getAwtFont(path, (float) size, style.numeric); |
||||||
|
|
||||||
|
font = new SlickFont(awtFont, antiAlias, extraChars); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get a font for a resource path / name |
||||||
|
* |
||||||
|
* @param resource resource to load |
||||||
|
* @param size font size (pt) |
||||||
|
* @param style font style |
||||||
|
* @return the {@link Font} |
||||||
|
* @throws FontFormatException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException |
||||||
|
{ |
||||||
|
InputStream in = null; |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
in = FileUtils.getResource(resource); |
||||||
|
|
||||||
|
Font awtFont = Font.createFont(Font.TRUETYPE_FONT, in); |
||||||
|
|
||||||
|
awtFont = awtFont.deriveFont(size); |
||||||
|
awtFont = awtFont.deriveFont(style); |
||||||
|
|
||||||
|
return awtFont; |
||||||
|
|
||||||
|
} finally { |
||||||
|
try { |
||||||
|
if (in != null) in.close(); |
||||||
|
} catch (IOException e) { |
||||||
|
//pass
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
* @param color draw color |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color) |
||||||
|
{ |
||||||
|
if (!ensureLoaded()) return; |
||||||
|
|
||||||
|
font.draw(str, color); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string at 0,0 |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
* @param color draw color |
||||||
|
* @param startIndex first drawn character index |
||||||
|
* @param endIndex last drawn character index |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color, int startIndex, int endIndex) |
||||||
|
{ |
||||||
|
if (!ensureLoaded()) return; |
||||||
|
|
||||||
|
font.draw(str, color, startIndex, endIndex); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string 0,0 |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str) |
||||||
|
{ |
||||||
|
if (!ensureLoaded()) return; |
||||||
|
|
||||||
|
font.draw(str); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get size needed to render give string |
||||||
|
* |
||||||
|
* @param text string to check |
||||||
|
* @return coord (width, height) |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public Coord getNeededSpace(String text) |
||||||
|
{ |
||||||
|
if (!ensureLoaded()) return Coord.zero(); |
||||||
|
|
||||||
|
return font.getNeededSpace(text); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @return font height |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public int getHeight() |
||||||
|
{ |
||||||
|
if (!ensureLoaded()) return 0; |
||||||
|
|
||||||
|
return font.getHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getWidth(String text) |
||||||
|
{ |
||||||
|
return font.getWidth(text); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void destroy() |
||||||
|
{ |
||||||
|
// this will have to suffice
|
||||||
|
font = null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.FontFormatException; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Font obtained from the OS |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class DeferredFontNative extends DeferredFont { |
||||||
|
|
||||||
|
/** |
||||||
|
* A font from OS, found by name |
||||||
|
* |
||||||
|
* @param fontName font family name |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
*/ |
||||||
|
public DeferredFontNative(String fontName, String extraChars, double size) { |
||||||
|
super(fontName, extraChars, size); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font from OS, found by name |
||||||
|
* |
||||||
|
* @param fontName font family name |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
* @param style font style |
||||||
|
*/ |
||||||
|
public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style) { |
||||||
|
super(fontName, extraChars, size, style); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font from OS, found by name |
||||||
|
* |
||||||
|
* @param fontName font family name |
||||||
|
* @param extraChars extra chars (0-255 loaded by default) |
||||||
|
* @param size size (pt) |
||||||
|
* @param style font style |
||||||
|
* @param antialias use antialiasing |
||||||
|
*/ |
||||||
|
public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style, boolean antialias) { |
||||||
|
super(fontName, extraChars, size, style, antialias); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException |
||||||
|
{ |
||||||
|
return new Font(resource, style, (int) size); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
import mightypork.rogue.AppAccess; |
||||||
|
import mightypork.rogue.AppAdapter; |
||||||
|
import mightypork.rogue.bus.events.ResourceLoadRequest; |
||||||
|
import mightypork.utils.logging.Log; |
||||||
|
|
||||||
|
import org.newdawn.slick.opengl.Texture; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Font loader and registry |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class FontBank extends AppAdapter { |
||||||
|
|
||||||
|
private static final GLFont NULL_FONT = new NullFont(); |
||||||
|
|
||||||
|
|
||||||
|
public FontBank(AppAccess app) { |
||||||
|
super(app); |
||||||
|
} |
||||||
|
|
||||||
|
private final HashMap<String, GLFont> fonts = new HashMap<String, GLFont>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Load a {@link DeferredFont} |
||||||
|
* |
||||||
|
* @param key font key |
||||||
|
* @param font font instance |
||||||
|
*/ |
||||||
|
public void loadFont(String key, DeferredFont font) |
||||||
|
{ |
||||||
|
bus().queue(new ResourceLoadRequest(font)); |
||||||
|
|
||||||
|
fonts.put(key, font); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add a {@link GLFont} to the bank. |
||||||
|
* |
||||||
|
* @param key font key |
||||||
|
* @param font font instance |
||||||
|
*/ |
||||||
|
public void addFont(String key, GLFont font) |
||||||
|
{ |
||||||
|
fonts.put(key, font); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get a loaded {@link Texture} |
||||||
|
* |
||||||
|
* @param key texture key |
||||||
|
* @return the texture |
||||||
|
*/ |
||||||
|
public GLFont getFont(String key) |
||||||
|
{ |
||||||
|
GLFont f = fonts.get(key); |
||||||
|
|
||||||
|
if (f == null) { |
||||||
|
Log.w("There's no font called " + key + "!"); |
||||||
|
return NULL_FONT; |
||||||
|
} |
||||||
|
|
||||||
|
return f; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,60 +0,0 @@ |
|||||||
package mightypork.rogue.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import static mightypork.rogue.fonts.FontManager.Style.*; |
|
||||||
import mightypork.rogue.fonts.FontManager.Glyphs; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Global font preloader |
|
||||||
* |
|
||||||
* @author Rapus |
|
||||||
*/ |
|
||||||
public class Fonts { |
|
||||||
|
|
||||||
public static LoadedFont splash_info; |
|
||||||
|
|
||||||
public static LoadedFont tooltip; |
|
||||||
public static LoadedFont gui; |
|
||||||
public static LoadedFont gui_title; |
|
||||||
public static LoadedFont program_number; |
|
||||||
public static LoadedFont menu_button; |
|
||||||
public static LoadedFont menu_title; |
|
||||||
public static LoadedFont tiny; |
|
||||||
|
|
||||||
|
|
||||||
private static void registerFileNames() |
|
||||||
{ |
|
||||||
FontManager.registerFile("res/fonts/4feb.ttf", "4feb", NORMAL); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Load fonts needed for splash. |
|
||||||
*/ |
|
||||||
public static void loadForSplash() |
|
||||||
{ |
|
||||||
registerFileNames(); |
|
||||||
|
|
||||||
gui = FontManager.loadFont("4feb", 24, NORMAL, Glyphs.basic).setCorrection(8, 7); |
|
||||||
splash_info = FontManager.loadFont("4feb", 42, NORMAL, "Loading."); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Preload all fonts we will use in the game |
|
||||||
*/ |
|
||||||
public static void load() |
|
||||||
{ |
|
||||||
tooltip = FontManager.loadFont("4feb", 24, NORMAL, Glyphs.basic_text).setCorrection(8, 7); |
|
||||||
gui_title = FontManager.loadFont("4feb", 30, NORMAL, Glyphs.basic_text); |
|
||||||
menu_button = FontManager.loadFont("4feb", 36, NORMAL, Glyphs.basic_text); |
|
||||||
menu_title = FontManager.loadFont("4feb", 34, NORMAL, Glyphs.basic_text); |
|
||||||
program_number = FontManager.loadFont("4feb", 28, NORMAL, Glyphs.numbers); |
|
||||||
tiny = FontManager.loadFont("4feb", 20, NORMAL, Glyphs.basic_text); |
|
||||||
|
|
||||||
Log.i("Fonts loaded = " + FontManager.loadedFontCounter); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,59 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.utils.math.color.RGB; |
||||||
|
import mightypork.utils.math.coord.Coord; |
||||||
|
|
||||||
|
|
||||||
|
public interface GLFont { |
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string at position |
||||||
|
* |
||||||
|
* @param text string to draw |
||||||
|
* @param color draw color |
||||||
|
*/ |
||||||
|
abstract void draw(String text, RGB color); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string at position |
||||||
|
* |
||||||
|
* @param text string to draw |
||||||
|
* @param color draw color |
||||||
|
* @param startIndex first drawn character index |
||||||
|
* @param endIndex last drawn character index |
||||||
|
*/ |
||||||
|
abstract void draw(String text, RGB color, int startIndex, int endIndex); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw string at position |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
*/ |
||||||
|
abstract void draw(String str); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get suize needed to render give string |
||||||
|
* |
||||||
|
* @param text string to check |
||||||
|
* @return coord (width, height) |
||||||
|
*/ |
||||||
|
abstract Coord getNeededSpace(String text); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @return font height |
||||||
|
*/ |
||||||
|
abstract int getHeight(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @param text texted text |
||||||
|
* @return space needed |
||||||
|
*/ |
||||||
|
abstract int getWidth(String text); |
||||||
|
|
||||||
|
} |
@ -1,639 +0,0 @@ |
|||||||
package mightypork.rogue.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import static mightypork.rogue.fonts.Align.*; |
|
||||||
import static 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.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import mightypork.rogue.Config; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
import mightypork.utils.math.color.RGB; |
|
||||||
import mightypork.utils.math.coord.Coord; |
|
||||||
|
|
||||||
import org.lwjgl.BufferUtils; |
|
||||||
import org.lwjgl.opengl.GL11; |
|
||||||
import org.lwjgl.util.glu.GLU; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 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) |
|
||||||
* @new version edited by MightyPork |
|
||||||
*/ |
|
||||||
public class LoadedFont { |
|
||||||
|
|
||||||
private static final boolean DEBUG = Config.LOG_FONTS; |
|
||||||
|
|
||||||
/** Map of user defined font characters (Character <-> IntObject) */ |
|
||||||
private Map<Character, CharStorageEntry> chars = new HashMap<Character, CharStorageEntry>(100); |
|
||||||
|
|
||||||
/** 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 = 2048; |
|
||||||
|
|
||||||
/** Default font texture height */ |
|
||||||
private int textureHeight = 2048; |
|
||||||
|
|
||||||
/** 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 double defScaleX = 1, defScaleY = 1; |
|
||||||
private double clipVerticalT = 0; |
|
||||||
private double clipVerticalB = 0; |
|
||||||
|
|
||||||
private class CharStorageEntry { |
|
||||||
|
|
||||||
/** Character's width */ |
|
||||||
public int width; |
|
||||||
|
|
||||||
/** Character's height */ |
|
||||||
public int height; |
|
||||||
|
|
||||||
/** Character's stored x position */ |
|
||||||
public int texPosX; |
|
||||||
|
|
||||||
/** Character's stored y position */ |
|
||||||
public int texPosY; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LoadedFont(Font font, boolean antiAlias, String charsNeeded) { |
|
||||||
this.font = font; |
|
||||||
this.fontSize = font.getSize() + 3; |
|
||||||
this.antiAlias = antiAlias; |
|
||||||
|
|
||||||
createSet(charsNeeded.toCharArray()); |
|
||||||
|
|
||||||
fontHeight -= 1; |
|
||||||
if (fontHeight <= 0) fontHeight = 1; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setCorrection(boolean on) |
|
||||||
{ |
|
||||||
if (on) { |
|
||||||
correctL = 9;// 2
|
|
||||||
correctR = 8;// 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()); |
|
||||||
|
|
||||||
return fontImage; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void createSet(char[] charsToLoad) |
|
||||||
{ |
|
||||||
try { |
|
||||||
class LoadedGlyph { |
|
||||||
|
|
||||||
public char c; |
|
||||||
public BufferedImage image; |
|
||||||
public int width; |
|
||||||
public int height; |
|
||||||
|
|
||||||
|
|
||||||
public LoadedGlyph(char c, BufferedImage image) { |
|
||||||
this.image = image; |
|
||||||
this.c = c; |
|
||||||
this.width = image.getWidth(); |
|
||||||
this.height = image.getHeight(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
List<LoadedGlyph> glyphs = new ArrayList<LoadedGlyph>(); |
|
||||||
List<Character> loaded = new ArrayList<Character>(); |
|
||||||
for (char ch : charsToLoad) { |
|
||||||
if (!loaded.contains(ch)) { |
|
||||||
glyphs.add(new LoadedGlyph(ch, getFontImage(ch))); |
|
||||||
loaded.add(ch); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Coord canvas = new Coord(128, 128); |
|
||||||
double lineHeight = 0; |
|
||||||
Coord begin = new Coord(0, 0); |
|
||||||
boolean needsLarger = false; |
|
||||||
|
|
||||||
while (true) { |
|
||||||
needsLarger = false; |
|
||||||
|
|
||||||
for (LoadedGlyph glyph : glyphs) { |
|
||||||
if (begin.x + glyph.width > canvas.x) { |
|
||||||
begin.y += lineHeight; |
|
||||||
lineHeight = 0; |
|
||||||
begin.x = 0; |
|
||||||
} |
|
||||||
|
|
||||||
if (lineHeight < glyph.height) { |
|
||||||
lineHeight = glyph.height; |
|
||||||
} |
|
||||||
|
|
||||||
if (begin.y + lineHeight > canvas.y) { |
|
||||||
needsLarger = true; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// draw.
|
|
||||||
begin.x += glyph.width; |
|
||||||
} |
|
||||||
|
|
||||||
if (needsLarger) { |
|
||||||
canvas.x *= 2; |
|
||||||
canvas.y *= 2; |
|
||||||
begin.setTo(0, 0); |
|
||||||
lineHeight = 0; |
|
||||||
} else { |
|
||||||
if (DEBUG) Log.f3("Preparing texture " + canvas.x + "x" + canvas.y); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
textureWidth = (int) canvas.x; |
|
||||||
textureHeight = (int) canvas.y; |
|
||||||
|
|
||||||
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; |
|
||||||
|
|
||||||
for (LoadedGlyph glyph : glyphs) { |
|
||||||
CharStorageEntry storedChar = new CharStorageEntry(); |
|
||||||
|
|
||||||
storedChar.width = glyph.width; |
|
||||||
storedChar.height = glyph.height; |
|
||||||
|
|
||||||
if (positionX + storedChar.width >= textureWidth) { |
|
||||||
positionX = 0; |
|
||||||
positionY += rowHeight; |
|
||||||
rowHeight = 0; |
|
||||||
} |
|
||||||
|
|
||||||
storedChar.texPosX = positionX; |
|
||||||
storedChar.texPosY = positionY; |
|
||||||
|
|
||||||
if (storedChar.height > fontHeight) { |
|
||||||
fontHeight = storedChar.height; |
|
||||||
} |
|
||||||
|
|
||||||
if (storedChar.height > rowHeight) { |
|
||||||
rowHeight = storedChar.height; |
|
||||||
} |
|
||||||
|
|
||||||
// Draw it here
|
|
||||||
g.drawImage(glyph.image, positionX, positionY, null); |
|
||||||
|
|
||||||
positionX += storedChar.width; |
|
||||||
|
|
||||||
chars.put(glyph.c, storedChar); |
|
||||||
} |
|
||||||
|
|
||||||
fontTextureID = loadImage(imgTemp); |
|
||||||
|
|
||||||
imgTemp = null; |
|
||||||
|
|
||||||
} catch (Exception e) { |
|
||||||
System.err.println("Failed to create font."); |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void drawQuad(double drawX, double drawY, double drawX2, double drawY2, CharStorageEntry charObj) |
|
||||||
{ |
|
||||||
double srcX = charObj.texPosX + charObj.width; |
|
||||||
double srcY = charObj.texPosY + charObj.height; |
|
||||||
double srcX2 = charObj.texPosX; |
|
||||||
double srcY2 = charObj.texPosY; |
|
||||||
double DrawWidth = drawX2 - drawX; |
|
||||||
double DrawHeight = drawY2 - drawY; |
|
||||||
double TextureSrcX = srcX / textureWidth; |
|
||||||
double TextureSrcY = srcY / textureHeight; |
|
||||||
double SrcWidth = srcX2 - srcX; |
|
||||||
double SrcHeight = srcY2 - srcY; |
|
||||||
double RenderWidth = (SrcWidth / textureWidth); |
|
||||||
double RenderHeight = (SrcHeight / textureHeight); |
|
||||||
|
|
||||||
drawY -= DrawHeight * clipVerticalB; |
|
||||||
|
|
||||||
GL11.glTexCoord2d(TextureSrcX, TextureSrcY); |
|
||||||
GL11.glVertex2d(drawX, drawY); |
|
||||||
GL11.glTexCoord2d(TextureSrcX, TextureSrcY + RenderHeight); |
|
||||||
GL11.glVertex2d(drawX, drawY + DrawHeight); |
|
||||||
GL11.glTexCoord2d(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight); |
|
||||||
GL11.glVertex2d(drawX + DrawWidth, drawY + DrawHeight); |
|
||||||
GL11.glTexCoord2d(TextureSrcX + RenderWidth, TextureSrcY); |
|
||||||
GL11.glVertex2d(drawX + DrawWidth, drawY); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public int getWidth(String whatchars) |
|
||||||
{ |
|
||||||
if (whatchars == null) whatchars = ""; |
|
||||||
int totalwidth = 0; |
|
||||||
CharStorageEntry charStorage = null; |
|
||||||
char currentChar = 0; |
|
||||||
for (int i = 0; i < whatchars.length(); i++) { |
|
||||||
currentChar = whatchars.charAt(i); |
|
||||||
|
|
||||||
charStorage = chars.get(currentChar); |
|
||||||
|
|
||||||
if (charStorage != null) { |
|
||||||
totalwidth += charStorage.width - correctL; |
|
||||||
} |
|
||||||
} |
|
||||||
return (int) (totalwidth * defScaleX); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public int getHeight() |
|
||||||
{ |
|
||||||
return (int) (fontHeight * defScaleY * (1 - clipVerticalT - clipVerticalB)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public int getLineHeight() |
|
||||||
{ |
|
||||||
return getHeight(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void drawString(double x, double y, String text, double scaleX, double scaleY, RGB color) |
|
||||||
{ |
|
||||||
drawString(x, y, text, 0, text.length() - 1, scaleX, scaleY, color, LEFT); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void drawString(double x, double y, String text, double scaleX, double scaleY, RGB color, int align) |
|
||||||
{ |
|
||||||
drawString(x, y, text, 0, text.length() - 1, scaleX, scaleY, color, align); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void drawString(double x, double y, String text, int startIndex, int endIndex, double scaleX, double scaleY, RGB color, int align) |
|
||||||
{ |
|
||||||
x = Math.round(x); |
|
||||||
y = Math.round(y); |
|
||||||
|
|
||||||
scaleX *= defScaleX; |
|
||||||
scaleY *= defScaleY; |
|
||||||
|
|
||||||
CharStorageEntry charStorage = null; |
|
||||||
int charCurrent; |
|
||||||
|
|
||||||
int totalwidth = 0; |
|
||||||
int i = startIndex, d = 1, c = correctL; |
|
||||||
float startY = 0; |
|
||||||
|
|
||||||
switch (align) { |
|
||||||
case RIGHT: { |
|
||||||
d = -1; |
|
||||||
c = correctR; |
|
||||||
|
|
||||||
while (i < endIndex) { |
|
||||||
if (text.charAt(i) == '\n') startY -= getHeight(); |
|
||||||
i++; |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
case CENTER: { |
|
||||||
for (int l = startIndex; l <= endIndex; l++) { |
|
||||||
charCurrent = text.charAt(l); |
|
||||||
if (charCurrent == '\n') break; |
|
||||||
|
|
||||||
charStorage = chars.get((char) charCurrent); |
|
||||||
if (charStorage != null) { |
|
||||||
totalwidth += charStorage.width - correctL; |
|
||||||
} |
|
||||||
} |
|
||||||
totalwidth /= -2; |
|
||||||
break; |
|
||||||
} |
|
||||||
case LEFT: |
|
||||||
default: { |
|
||||||
d = 1; |
|
||||||
c = correctL; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
GL11.glPushAttrib(GL_ENABLE_BIT); |
|
||||||
GL11.glEnable(GL11.GL_TEXTURE_2D); |
|
||||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID); |
|
||||||
GL11.glColor4d(color.r, color.g, color.b, color.a); |
|
||||||
GL11.glBegin(GL11.GL_QUADS); |
|
||||||
|
|
||||||
while (i >= startIndex && i <= endIndex) { |
|
||||||
charCurrent = text.charAt(i); |
|
||||||
|
|
||||||
charStorage = chars.get(new Character((char) charCurrent)); |
|
||||||
|
|
||||||
if (charStorage != null) { |
|
||||||
if (d < 0) totalwidth += (charStorage.width - c) * d; |
|
||||||
if (charCurrent == '\n') { |
|
||||||
startY -= getHeight() * d; |
|
||||||
totalwidth = 0; |
|
||||||
if (align == CENTER) { |
|
||||||
for (int l = i + 1; l <= endIndex; l++) { |
|
||||||
charCurrent = text.charAt(l); |
|
||||||
if (charCurrent == '\n') break; |
|
||||||
|
|
||||||
charStorage = chars.get((char) charCurrent); |
|
||||||
|
|
||||||
totalwidth += charStorage.width - correctL; |
|
||||||
} |
|
||||||
totalwidth /= -2; |
|
||||||
} |
|
||||||
// if center get next lines total width/2;
|
|
||||||
} else { |
|
||||||
//@formatter:off
|
|
||||||
drawQuad( |
|
||||||
(totalwidth + charStorage.width) * scaleX + x, |
|
||||||
startY * scaleY + y, totalwidth * scaleX + x, |
|
||||||
(startY + charStorage.height) * scaleY + y, |
|
||||||
charStorage |
|
||||||
); |
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
if (d > 0) totalwidth += (charStorage.width - c) * d; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
i += d; |
|
||||||
} |
|
||||||
GL11.glEnd(); |
|
||||||
GL11.glPopAttrib(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
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); |
|
||||||
|
|
||||||
GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, internalFormat, width, height, format, GL11.GL_UNSIGNED_BYTE, byteBuffer); |
|
||||||
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 Font getFont(String fontname, int style, float size) |
|
||||||
{ |
|
||||||
Font result = null; |
|
||||||
GraphicsEnvironment graphicsenvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); |
|
||||||
for (Font font : graphicsenvironment.getAllFonts()) { |
|
||||||
if (font.getName().equalsIgnoreCase(fontname)) { |
|
||||||
result = font.deriveFont(style, size); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LoadedFont setScale(double x, double y) |
|
||||||
{ |
|
||||||
defScaleX = x; |
|
||||||
defScaleY = y; |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LoadedFont setClip(double clipRatioTop, double clipRatioBottom) |
|
||||||
{ |
|
||||||
clipVerticalT = clipRatioTop; |
|
||||||
clipVerticalB = clipRatioBottom; |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LoadedFont setCorrection(int correctionLeft, int correctionRight) |
|
||||||
{ |
|
||||||
correctL = correctionLeft; |
|
||||||
correctR = correctionRight; |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw string with font. |
|
||||||
* |
|
||||||
* @param x x coord |
|
||||||
* @param y y coord |
|
||||||
* @param text text to draw |
|
||||||
* @param color render color |
|
||||||
* @param align (-1,0,1) |
|
||||||
*/ |
|
||||||
public void draw(double x, double y, String text, RGB color, int align) |
|
||||||
{ |
|
||||||
drawString(x, y, text, 1, 1, color, align); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw string with font. |
|
||||||
* |
|
||||||
* @param pos coord |
|
||||||
* @param text text to draw |
|
||||||
* @param color render color |
|
||||||
* @param align (-1,0,1) |
|
||||||
*/ |
|
||||||
public void draw(Coord pos, String text, RGB color, int align) |
|
||||||
{ |
|
||||||
drawString(pos.x, pos.y, text, 1, 1, color, align); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void drawFuzzy(Coord pos, String text, int align, RGB textColor, RGB blurColor, int blurSize) |
|
||||||
{ |
|
||||||
drawFuzzy(pos, text, align, textColor, blurColor, blurSize, true); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void drawFuzzy(Coord pos, String text, int align, RGB textColor, RGB blurColor, int blurSize, boolean smooth) |
|
||||||
{ |
|
||||||
glPushMatrix(); |
|
||||||
|
|
||||||
glTranslated(pos.x, pos.y, pos.z); |
|
||||||
|
|
||||||
// shadow
|
|
||||||
int sh = blurSize; |
|
||||||
|
|
||||||
int l = glGenLists(1); |
|
||||||
|
|
||||||
glNewList(l, GL_COMPILE); |
|
||||||
draw(0, 0, text, blurColor, align); |
|
||||||
glEndList(); |
|
||||||
|
|
||||||
for (int xx = -sh; xx <= sh; xx += (smooth ? 1 : sh)) { |
|
||||||
for (int yy = -sh; yy <= sh; yy += (smooth ? 1 : sh)) { |
|
||||||
if (xx == 0 && yy == 0) continue; |
|
||||||
glPushMatrix(); |
|
||||||
glTranslated(xx, yy, 0); |
|
||||||
glCallList(l); |
|
||||||
glPopMatrix(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
glDeleteLists(l, 1); |
|
||||||
|
|
||||||
draw(0, 0, text, textColor, align); |
|
||||||
|
|
||||||
glPopMatrix(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,56 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.utils.math.color.RGB; |
||||||
|
import mightypork.utils.math.coord.Coord; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Null font used where real resource could not be loaded. |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class NullFont implements GLFont { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color) |
||||||
|
{ |
||||||
|
// nope
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color, int startIndex, int endIndex) |
||||||
|
{ |
||||||
|
// nope
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void draw(String str) |
||||||
|
{ |
||||||
|
// nope
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Coord getNeededSpace(String str) |
||||||
|
{ |
||||||
|
return Coord.zero(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getHeight() |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getWidth(String text) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,130 @@ |
|||||||
|
package mightypork.rogue.fonts; |
||||||
|
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*; |
||||||
|
|
||||||
|
import java.awt.Font; |
||||||
|
|
||||||
|
import mightypork.utils.math.color.RGB; |
||||||
|
import mightypork.utils.math.coord.Coord; |
||||||
|
|
||||||
|
import org.newdawn.slick.Color; |
||||||
|
import org.newdawn.slick.TrueTypeFont; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Wrapper for slick font |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class SlickFont implements GLFont { |
||||||
|
|
||||||
|
private final TrueTypeFont ttf; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A font with ASCII and extra chars |
||||||
|
* |
||||||
|
* @param font font to load |
||||||
|
* @param antiAlias antialiasing |
||||||
|
* @param extraChars extra chars to load |
||||||
|
*/ |
||||||
|
public SlickFont(Font font, boolean antiAlias, String extraChars) { |
||||||
|
|
||||||
|
ttf = new TrueTypeFont(font, antiAlias, stripASCII(extraChars)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static char[] stripASCII(String chars) |
||||||
|
{ |
||||||
|
if (chars == null) return null; |
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (char c : chars.toCharArray()) { |
||||||
|
if (c <= 255) continue; // already included in default set
|
||||||
|
sb.append(c); |
||||||
|
} |
||||||
|
|
||||||
|
return sb.toString().toCharArray(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static void prepareForRender() |
||||||
|
{ |
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); |
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); |
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw in color |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
* @param color text color |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color) |
||||||
|
{ |
||||||
|
prepareForRender(); |
||||||
|
ttf.drawString(0, 0, str, rgbToSlickColor(color)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw substring in color |
||||||
|
* |
||||||
|
* @param str string to draw |
||||||
|
* @param color text color |
||||||
|
* @param startIndex first char to draw |
||||||
|
* @param endIndex last char to draw (INCLUDING!) |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str, RGB color, int startIndex, int endIndex) |
||||||
|
{ |
||||||
|
prepareForRender(); |
||||||
|
ttf.drawString(0, 0, str, rgbToSlickColor(color), startIndex, endIndex); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Draw in white |
||||||
|
* |
||||||
|
* @param str chars to draw |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void draw(String str) |
||||||
|
{ |
||||||
|
prepareForRender(); |
||||||
|
ttf.drawString(0, 0, str); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static Color rgbToSlickColor(RGB rgb) |
||||||
|
{ |
||||||
|
return new Color((float) rgb.r, (float) rgb.g, (float) rgb.b, (float) rgb.a); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Coord getNeededSpace(String text) |
||||||
|
{ |
||||||
|
return new Coord(getWidth(text), getHeight()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getHeight() |
||||||
|
{ |
||||||
|
return ttf.getHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int getWidth(String text) |
||||||
|
{ |
||||||
|
return ttf.getWidth(text); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
package mightypork.rogue.gui.screens.test_font; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.AppAccess; |
||||||
|
import mightypork.rogue.Res; |
||||||
|
import mightypork.rogue.fonts.GLFont; |
||||||
|
import mightypork.rogue.gui.Screen; |
||||||
|
import mightypork.rogue.render.Render; |
||||||
|
import mightypork.utils.math.coord.Coord; |
||||||
|
|
||||||
|
|
||||||
|
public class ScreenTestFont extends Screen { |
||||||
|
|
||||||
|
public ScreenTestFont(AppAccess app) { |
||||||
|
super(app); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void deinitScreen() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onScreenEnter() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onScreenLeave() |
||||||
|
{ |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void renderScreen() |
||||||
|
{ |
||||||
|
GLFont font = Res.getFont("PolygonPixel_16"); |
||||||
|
|
||||||
|
String s = "It works!"; |
||||||
|
double scale = getRect().height() / 50D; |
||||||
|
Render.pushState(); |
||||||
|
Render.translate(getRect().getCenter().sub(font.getNeededSpace(s).mul(scale).half())); |
||||||
|
Render.scale(new Coord(scale)); |
||||||
|
font.draw("It works!"); |
||||||
|
Render.popState(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String getId() |
||||||
|
{ |
||||||
|
return "test.font"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,127 @@ |
|||||||
|
package mightypork.rogue.loading; |
||||||
|
|
||||||
|
|
||||||
|
import mightypork.utils.control.interf.Destroyable; |
||||||
|
import mightypork.utils.logging.Log; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Deferred resource abstraction.<br> |
||||||
|
* Resources implementing {@link NullResource} will be treated as fake and not |
||||||
|
* attempted to load. |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public abstract class DeferredResource implements Deferred, Destroyable { |
||||||
|
|
||||||
|
private String resource; |
||||||
|
private boolean loadFailed = false; |
||||||
|
private boolean loadAttempted = false; |
||||||
|
|
||||||
|
|
||||||
|
public DeferredResource(String resource) { |
||||||
|
this.resource = resource; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public synchronized final void load() |
||||||
|
{ |
||||||
|
|
||||||
|
if (loadAttempted) return; |
||||||
|
|
||||||
|
loadAttempted = true; |
||||||
|
loadFailed = false; |
||||||
|
|
||||||
|
if (isNull()) return; |
||||||
|
try { |
||||||
|
if (resource == null) throw new NullPointerException("Resource string cannot be null for non-null resource."); |
||||||
|
|
||||||
|
Log.f3("Loading resource " + this); |
||||||
|
loadResource(resource); |
||||||
|
Log.f3("Resource " + this + " loaded."); |
||||||
|
} catch (Exception e) { |
||||||
|
loadFailed = true; |
||||||
|
Log.e("Failed to load resource \"" + resource + "\"", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public synchronized final boolean isLoaded() |
||||||
|
{ |
||||||
|
if (isNull()) return false; |
||||||
|
|
||||||
|
return loadAttempted && !loadFailed; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Check if the resource is loaded; if not, try to do so. |
||||||
|
* |
||||||
|
* @return true if it's loaded now. |
||||||
|
*/ |
||||||
|
public synchronized final boolean ensureLoaded() |
||||||
|
{ |
||||||
|
if (isNull()) return false; |
||||||
|
|
||||||
|
if (isLoaded()) { |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
load(); |
||||||
|
} |
||||||
|
|
||||||
|
return isLoaded(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Load the resource. Called from load() - once only. |
||||||
|
* |
||||||
|
* @param resource the path / name of a resource |
||||||
|
* @throws Exception when some problem prevented the resource from being |
||||||
|
* loaded. |
||||||
|
*/ |
||||||
|
protected abstract void loadResource(String resource) throws Exception; |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public abstract void destroy(); |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() |
||||||
|
{ |
||||||
|
return Log.str(getClass()) + "(\"" + resource + "\")"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() |
||||||
|
{ |
||||||
|
final int prime = 31; |
||||||
|
int result = 1; |
||||||
|
result = prime * result + ((resource == null) ? 0 : resource.hashCode()); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) |
||||||
|
{ |
||||||
|
if (this == obj) return true; |
||||||
|
if (obj == null) return false; |
||||||
|
if (!(obj instanceof DeferredResource)) return false; |
||||||
|
DeferredResource other = (DeferredResource) obj; |
||||||
|
if (resource == null) { |
||||||
|
if (other.resource != null) return false; |
||||||
|
} else if (!resource.equals(other.resource)) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private boolean isNull() |
||||||
|
{ |
||||||
|
return this instanceof NullResource; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package mightypork.rogue.loading; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Resource that is texture-based and therefore needs to be loaded in the main |
||||||
|
* thread (ie. main loop). |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public interface MustLoadInMainThread { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package mightypork.rogue.loading; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Resource that is used as a placeholder instead of an actual resource; this |
||||||
|
* resource should not be attempted to be loaded. |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public interface NullResource { |
||||||
|
|
||||||
|
} |
@ -1,30 +1,18 @@ |
|||||||
package mightypork.rogue.sound; |
package mightypork.rogue.sound; |
||||||
|
|
||||||
|
|
||||||
public class NullAudio extends DeferredAudio { |
import mightypork.rogue.loading.NullResource; |
||||||
|
|
||||||
public NullAudio() { |
|
||||||
super(""); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void load() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
/** |
||||||
|
* Placeholder for cases where no matching audio is found and |
||||||
|
* {@link NullPointerException} has to be avoided. |
||||||
|
* |
||||||
|
* @author MightyPork |
||||||
|
*/ |
||||||
|
public class NullAudio extends DeferredAudio implements NullResource { |
||||||
|
|
||||||
@Override |
public NullAudio() { |
||||||
public boolean isLoaded() |
super(null); |
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected boolean ensureLoaded() |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
@ -0,0 +1,56 @@ |
|||||||
|
package mightypork.rogue.texture; |
||||||
|
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11; |
||||||
|
import org.newdawn.slick.opengl.Texture; |
||||||
|
|
||||||
|
|
||||||
|
public interface FilteredTexture extends Texture { |
||||||
|
|
||||||
|
public static enum Filter |
||||||
|
{ |
||||||
|
LINEAR(GL11.GL_LINEAR), NEAREST(GL11.GL_NEAREST); |
||||||
|
|
||||||
|
public final int num; |
||||||
|
|
||||||
|
|
||||||
|
private Filter(int gl) { |
||||||
|
this.num = gl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static enum Wrap |
||||||
|
{ |
||||||
|
CLAMP(GL11.GL_CLAMP), REPEAT(GL11.GL_REPEAT); |
||||||
|
|
||||||
|
public final int num; |
||||||
|
|
||||||
|
|
||||||
|
private Wrap(int gl) { |
||||||
|
this.num = gl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set filter for scaling |
||||||
|
* |
||||||
|
* @param filterMin downscale filter |
||||||
|
* @param filterMag upscale filter |
||||||
|
*/ |
||||||
|
public void setFilter(Filter filterMin, Filter filterMag); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set filter for scaling (both up and down) |
||||||
|
* |
||||||
|
* @param filter filter |
||||||
|
*/ |
||||||
|
public void setFilter(Filter filter); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @param wrapping wrap mode |
||||||
|
*/ |
||||||
|
public void setWrap(Wrap wrapping); |
||||||
|
} |
Loading…
Reference in new issue