package ttftcuts.physis.client.gui; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import ttftcuts.physis.Physis; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; @SideOnly(Side.CLIENT) public class RuneFontRenderer extends FontRenderer { protected static ResourceLocation glyphSheet = new ResourceLocation(Physis.MOD_ID, "textures/font/runes.png"); protected static ResourceLocation unicodeGlyphSheet = new ResourceLocation(Physis.MOD_ID, "textures/font/runesunicode.png"); protected Map<Integer, List<Integer>> unicodeCharsByWidth; protected Map<Integer, List<Integer>> asciiCharsByWidth; protected int remixoffset = 0; public RuneFontRenderer() { super(Minecraft.getMinecraft().gameSettings, glyphSheet, Minecraft.getMinecraft().renderEngine, false); this.calculateUnicodeWidths(); this.calculateAsciiWidths(); } protected static List<Character> forbidden = ImmutableList.of((char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)32, (char)33, (char)34, (char)39, (char)40, (char)41, (char)42, (char)43, (char)44, (char)45, (char)46, (char)47, (char)58, (char)59, (char)60, (char)61, (char)62, (char)63, (char)64, (char)91, (char)92, (char)93, (char)94, (char)95, (char)96, (char)123, (char)124, (char)125, (char)255); protected boolean isCharAllowed(char c, boolean unicode) { if (!unicode) { return !forbidden.contains(c); } return Character.isAlphabetic(c) || Character.isDigit(c); } protected void calculateUnicodeWidths() { this.unicodeFlag = true; unicodeCharsByWidth = new HashMap<Integer, List<Integer>>(); for (int i=0; i<256; i++) { if (!isCharAllowed((char)i, true)) {continue;} int w = this.getCharWidth((char)i); List<Integer> category; if (!unicodeCharsByWidth.containsKey(w)) { category = new ArrayList<Integer>(); unicodeCharsByWidth.put(w, category); }else { category = unicodeCharsByWidth.get(w); } category.add(i); } this.unicodeFlag = false; } protected void calculateAsciiWidths() { asciiCharsByWidth = new HashMap<Integer, List<Integer>>(); for (int i=0; i<256; i++) { if (!isCharAllowed((char)i, false)) {continue;} int w = this.charWidth[i]; List<Integer> category; if (!asciiCharsByWidth.containsKey(w)) { category = new ArrayList<Integer>(); asciiCharsByWidth.put(w, category); }else { category = asciiCharsByWidth.get(w); } category.add(i); } } protected char replaceChar(char c, boolean unicode) { boolean u = this.unicodeFlag; this.unicodeFlag = unicode; int width = this.getCharWidth(c); this.unicodeFlag = u; Map<Integer, List<Integer>> charmap = unicode ? this.unicodeCharsByWidth : this.asciiCharsByWidth; char n = c; List<Integer> chars = charmap.get(width); if (chars != null && isCharAllowed(c, unicode)) { int cnum = (c * (remixoffset+c) + remixoffset + c) % chars.size(); n = (char)(chars.get(cnum).intValue()); remixoffset++; } return n; } @Override protected ResourceLocation getUnicodePageLocation(int page) { return unicodeGlyphSheet; } @Override protected float renderDefaultChar(int c, boolean italic) { char n = replaceChar((char)c, false); return super.renderDefaultChar(n, italic); } @Override protected float renderUnicodeChar(char c, boolean italic) { if (this.glyphWidth[c] == 0) { return 0.0F; } else { char n = replaceChar(c, true); return super.renderUnicodeChar(n, italic); } } @Override protected void renderStringAtPos(String string, boolean shadow) { super.renderStringAtPos(string, shadow); this.remixoffset = 0; } @Override public void onResourceManagerReload(IResourceManager manager) { super.onResourceManagerReload(manager); this.calculateAsciiWidths(); } }