package mightypork.rogue.fonts; import java.awt.Font; import java.io.InputStream; import java.util.HashMap; import mightypork.rogue.Config; import mightypork.utils.logging.Log; import mightypork.utils.math.coord.Coord; import org.newdawn.slick.util.ResourceLoader; /** * Remade universal font manager for Sector. * * @author MightyPork */ public class FontManager { private static final boolean DEBUG = Config.LOG_FONTS; /** * Glyph tables. * * @author MightyPork */ public static class Glyphs { //@formatter:off /** all glyphs */ public static final String all = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]" + "^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤" + "¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäå" + "æçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; /** letters and numbers, sufficient for basic messages etc. NO SPACE */ public static final String alnum_nospace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; /** letters and numbers, sufficient for basic messages etc. */ public static final String alnum = " "+alnum_nospace; /** letters and numbers with the most basic punctuation signs */ public static final String basic_text = " .-,.?!:;_"+alnum_nospace; /** letters */ public static final String alpha = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; /** numbers */ public static final String numbers = " 0123456789.-,:"; /** non-standard variants of alnum */ public static final String alnum_extra = " ŒÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜŸÝßàáâãäåæçèéêëìíîïðñòóôõöøùúû" + "üýþÿĚŠČŘŽŤŇĎŮěščřžťňďůŁłđ"; /** signs and punctuation */ public static final String signs = " !\"#$%&§'()*+,-./:;<=>?@[\\]^_{|}~"; /** extra signs and punctuation */ public static final String signs_extra = " ¥€£¢`ƒ„…†‡ˆ‰‹‘’“”•›¡¤¦¨ª«¬­¯°±²³´µ¶·¸¹º»¼½¾¿÷™©­®→↓←↑"; /** basic character set. */ public static final String basic = alnum + signs; //@formatter:on } /** * Font style * * @author MightyPork */ public static enum Style { /** Normal */ NORMAL, /** Italic */ ITALIC, /** Stronger italic to left. */ LEFT, /** Stronger italic to right */ RIGHT, /** Monospace type */ MONO, /** Bold */ BOLD, /** Bold & Italic */ BOLD_I, /** Bold & Left */ BOLD_L, /** Bold & Right */ BOLD_R, /** Heavy style, stronger than bold. */ HEAVY, /** Light (lighter than normal) */ LIGHT, /** narrow style, similar to Light */ NARROW, /** Wide style, like Bold but with thinner lines */ WIDE, /** Outline variant of normal */ OUTLINE; } // /** // * Preloaded font identifier [name, size, style] // * // * @author MightyPork // */ // public static class FontId { // // /** font size (pt) */ // public float size = 24; // /** font name, registered with registerFile */ // public String name = ""; // /** font style. The given style must be in a file. */ // public Style style; // // /** Set of glyphs in this ID */ // public String glyphs = ""; // // /** Index for faster comparision of glyph ids. */ // public int glyphset_id = 0; // // // /** // * Preloaded font identifier // * // * @param name font name (registerFile) // * @param size font size (pt) // * @param style font style // * @param glyphs glyphs to load // */ // public FontId(String name, double size, Style style, String glyphs) { // this.name = name; // this.size = (float) size; // this.style = style; // // if (glyphs.equals(Glyphs.basic)) { // glyphset_id = 1; // } else if (glyphs.equals(Glyphs.alnum)) { // glyphset_id = 2; // } else if (glyphs.equals(Glyphs.basic_text)) { // glyphset_id = 3; // } else if (glyphs.equals(Glyphs.numbers)) { // glyphset_id = 4; // } else if (glyphs.equals(Glyphs.alpha)) { // glyphset_id = 5; // } else if (glyphs.equals(Glyphs.all)) { // glyphset_id = 6; // } else if (glyphs.equals(Glyphs.alnum_extra)) { // glyphset_id = 7; // } else if (glyphs.equals(Glyphs.signs)) { // glyphset_id = 8; // } else if (glyphs.equals(Glyphs.signs_extra)) { // glyphset_id = 9; // } else { // this.glyphs = glyphs; // } // } // // // @Override // public boolean equals(Object obj) // { // if (obj == null) return false; // if (!(obj.getClass().isAssignableFrom(getClass()))) return false; // if (obj instanceof FontId) { // if (obj == this) return true; // FontId id2 = ((FontId) obj); // boolean flag = true; // flag &= id2.size == size; // flag &= id2.name.equals(name); // flag &= id2.style == style; // flag &= ((id2.glyphset_id != -1 && id2.glyphset_id == glyphset_id) || // id2.glyphs.equals(glyphs)); // return flag; // } // return false; // } // // // @Override // public int hashCode() // { // return (new Float(size).hashCode()) ^ name.hashCode() ^ style.hashCode() // ^ glyphset_id; // } // // // @Override // public String toString() // { // return "[" + name + ", " + size + ", " + style + (glyphset_id > 0 ? // ", g=" + glyphset_id : ", g=custom") + "]"; // } // } /** * Group of styles of one font. * * @author MightyPork */ public static class FontFamily extends HashMap { } /** * Table of font files. name → {style:file,style:file,style:file...} */ private static HashMap fontFiles = new HashMap(); /** * Register font file. * * @param path * resource path (res/fonts/...) * @param name * font name (for binding) * @param style * font style in this file */ public static void registerFile(String path, String name, Style style) { if (fontFiles.containsKey(name)) { if (fontFiles.get(name) != null) { fontFiles.get(name).put(style, path); return; } } // insert new table of styles to font name. FontFamily family = new FontFamily(); family.put(style, path); fontFiles.put(name, family); } /** Counter of loaded fonts */ public static int loadedFontCounter = 0; /** * Preload font if needed, get preloaded font.
* If needed file is not available, throws runtime exception. * * @param name * font name (registerFile) * @param size * font size (pt) * @param style * font style * @param glyphs * glyphs needed * @return the loaded font. */ public static LoadedFont loadFont(String name, double size, Style style, String glyphs) { return loadFont(name, size, style, glyphs, 9, 8, Coord.one(), 0, 0); } /** * Preload font if needed, get preloaded font.
* If needed file is not available, throws runtime exception. * * @param name * font name (registerFile) * @param size * font size (pt) * @param style * font style * @param glyphs * glyphs needed * @param correctLeft * left horizontal correction * @param correctRight * right horizontal correction * @param scale * font scale (changing aspect ratio) * @param clipTop * top clip (0-1) - top part of the font to be cut off * @param clipBottom * bottom clip (0-1) - bottom part of the font to be cut off * @return the loaded font. */ public static LoadedFont loadFont(String name, double size, Style style, String glyphs, int correctLeft, int correctRight, Coord scale, double clipTop, double clipBottom) { String resourcePath; try { resourcePath = fontFiles.get(name).get(style); if (resourcePath == null) { Log.w("Font [" + name + "] does not have variant " + style + ".\nUsing NORMAL instead."); resourcePath = fontFiles.get(name).get(Style.NORMAL); if (resourcePath == null) { throw new NullPointerException(); } } } catch (NullPointerException npe) { throw new RuntimeException("Font loading failed: no font file registered for name \"" + name + "\"."); } InputStream in = ResourceLoader.getResourceAsStream(resourcePath); Font awtFont; try { awtFont = Font.createFont(Font.TRUETYPE_FONT, in); } catch (Exception e) { Log.e("Loading of font " + resourcePath + " failed.", e); throw new RuntimeException(e); } awtFont = awtFont.deriveFont((float) size); // set font size LoadedFont font = new LoadedFont(awtFont, true, glyphs); font.setCorrection(correctLeft, correctRight); font.setClip(clipTop, clipBottom); font.setScale(scale.x, scale.y); loadedFontCounter++; if (DEBUG) Log.f3("Font from file \"" + resourcePath + "\" preloaded."); return font; } }