PageRenderTime 108ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/newcode/src/com/prupe/mcpatcher/hd/FontUtils.java

https://bitbucket.org/SevenBits/mcpatcher
Java | 248 lines | 226 code | 22 blank | 0 comment | 67 complexity | fc935514824db79deb2fe592adaee96c MD5 | raw file
  1. package com.prupe.mcpatcher.hd;
  2. import com.prupe.mcpatcher.*;
  3. import net.minecraft.src.FontRenderer;
  4. import net.minecraft.src.ResourceLocation;
  5. import java.awt.image.BufferedImage;
  6. import java.util.HashSet;
  7. import java.util.Map;
  8. import java.util.Properties;
  9. import java.util.Set;
  10. public class FontUtils {
  11. private static final MCLogger logger = MCLogger.getLogger(MCPatcherUtils.HD_FONT);
  12. private static final boolean enable = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "hdFont", true);
  13. private static final boolean enableNonHD = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "nonHDFontWidth", false);
  14. private static final int ROWS = 16;
  15. private static final int COLS = 16;
  16. public static final char[] AVERAGE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123467890".toCharArray();
  17. public static final int[] SPACERS = new int[]{0x02028bfe, 0x02808080, 0x0dffffff};
  18. private static final boolean showLines = false;
  19. private static final Set<FontRenderer> allRenderers = new HashSet<FontRenderer>();
  20. static {
  21. TexturePackChangeHandler.register(new TexturePackChangeHandler(MCPatcherUtils.HD_FONT, 1) {
  22. @Override
  23. public void initialize() {
  24. }
  25. @Override
  26. public void beforeChange() {
  27. }
  28. @Override
  29. public void afterChange() {
  30. for (FontRenderer renderer : allRenderers) {
  31. renderer.readFontData();
  32. }
  33. }
  34. });
  35. }
  36. static void init() {
  37. }
  38. public static ResourceLocation getFontName(FontRenderer fontRenderer, ResourceLocation font) {
  39. if (fontRenderer.defaultFont == null) {
  40. fontRenderer.defaultFont = font;
  41. }
  42. if (fontRenderer.hdFont == null) {
  43. String namespace = fontRenderer.defaultFont.getNamespace();
  44. String name = fontRenderer.defaultFont.getPath().replaceAll(".*/", "");
  45. fontRenderer.hdFont = new ResourceLocation(namespace, TexturePackAPI.MCPATCHER_SUBDIR + "font/" + name);
  46. }
  47. ResourceLocation newFont;
  48. if (enable && TexturePackAPI.hasResource(fontRenderer.hdFont)) {
  49. logger.fine("using %s instead of %s", fontRenderer.hdFont, fontRenderer.defaultFont);
  50. fontRenderer.isHD = true;
  51. newFont = fontRenderer.hdFont;
  52. } else {
  53. logger.fine("using default %s", fontRenderer.defaultFont);
  54. fontRenderer.isHD = enable && enableNonHD;
  55. newFont = fontRenderer.defaultFont;
  56. }
  57. fontRenderer.fontAdj = fontRenderer.isHD ? 0.0f : 1.0f;
  58. return newFont;
  59. }
  60. public static float[] computeCharWidthsf(FontRenderer fontRenderer, ResourceLocation filename, BufferedImage image, int[] rgb, int[] charWidth, float fontAdj) {
  61. float[] charWidthf = new float[charWidth.length];
  62. if (!fontRenderer.isHD) {
  63. fontRenderer.fontAdj = fontAdj;
  64. for (int i = 0; i < charWidth.length; i++) {
  65. charWidthf[i] = charWidth[i];
  66. }
  67. charWidthf[32] = 4.0f;
  68. return charWidthf;
  69. }
  70. allRenderers.add(fontRenderer);
  71. int width = image.getWidth();
  72. int height = image.getHeight();
  73. int colWidth = width / COLS;
  74. int rowHeight = height / ROWS;
  75. for (int ch = 0; ch < charWidth.length; ch++) {
  76. int row = ch / COLS;
  77. int col = ch % COLS;
  78. outer:
  79. for (int colIdx = colWidth - 1; colIdx >= 0; colIdx--) {
  80. int x = col * colWidth + colIdx;
  81. for (int rowIdx = 0; rowIdx < rowHeight; rowIdx++) {
  82. int y = row * rowHeight + rowIdx;
  83. int pixel = rgb[x + y * width];
  84. if (isOpaque(pixel)) {
  85. if (printThis(ch)) {
  86. logger.finer("'%c' pixel (%d, %d) = %08x, colIdx = %d", (char) ch, x, y, pixel, colIdx);
  87. }
  88. charWidthf[ch] = (128.0f * (float) (colIdx + 1)) / (float) width + 1.0f;
  89. if (showLines) {
  90. for (int i = 0; i < rowHeight; i++) {
  91. y = row * rowHeight + i;
  92. for (int j = 0; j < Math.max(colWidth / 16, 1); j++) {
  93. image.setRGB(x + j, y, (i == rowIdx ? 0xff0000ff : 0xffff0000));
  94. image.setRGB(col * colWidth + j, y, 0xff00ff00);
  95. }
  96. }
  97. }
  98. break outer;
  99. }
  100. }
  101. }
  102. }
  103. for (int ch = 0; ch < charWidthf.length; ch++) {
  104. if (charWidthf[ch] <= 0.0f) {
  105. charWidthf[ch] = 2.0f;
  106. } else if (charWidthf[ch] >= 7.99f) {
  107. charWidthf[ch] = 7.99f;
  108. }
  109. }
  110. boolean[] isOverride = new boolean[charWidth.length];
  111. try {
  112. getCharWidthOverrides(filename, charWidthf, isOverride);
  113. } catch (Throwable e) {
  114. e.printStackTrace();
  115. }
  116. if (!isOverride[32]) {
  117. charWidthf[32] = defaultSpaceWidth(charWidthf);
  118. }
  119. for (int ch = 0; ch < charWidth.length; ch++) {
  120. charWidth[ch] = Math.round(charWidthf[ch]);
  121. if (printThis(ch)) {
  122. logger.finer("charWidth['%c'] = %f", (char) ch, charWidthf[ch]);
  123. }
  124. }
  125. return charWidthf;
  126. }
  127. private static float getCharWidthf(FontRenderer fontRenderer, char ch) {
  128. float width = fontRenderer.getCharWidth(ch);
  129. if (width < 0 || fontRenderer.charWidthf == null || ch >= fontRenderer.charWidthf.length || ch < 0) {
  130. return width;
  131. } else {
  132. return fontRenderer.charWidthf[ch];
  133. }
  134. }
  135. public static float getCharWidthf(FontRenderer fontRenderer, int[] charWidth, int ch) {
  136. return fontRenderer.isHD ? fontRenderer.charWidthf[ch] * fontRenderer.fontHeight / 8.0f : (float) charWidth[ch];
  137. }
  138. public static float getStringWidthf(FontRenderer fontRenderer, String s) {
  139. float totalWidth = 0.0f;
  140. if (s != null) {
  141. boolean isLink = false;
  142. for (int i = 0; i < s.length(); i++) {
  143. char c = s.charAt(i);
  144. float cWidth = getCharWidthf(fontRenderer, c);
  145. if (cWidth < 0.0f && i < s.length() - 1) {
  146. i++;
  147. c = s.charAt(i);
  148. if (c == 'l' || c == 'L') {
  149. isLink = true;
  150. } else if (c == 'r' || c == 'R') {
  151. isLink = false;
  152. }
  153. cWidth = 0.0f;
  154. }
  155. totalWidth += cWidth;
  156. if (isLink) {
  157. totalWidth++;
  158. }
  159. }
  160. }
  161. return totalWidth;
  162. }
  163. public static ResourceLocation getUnicodePage(ResourceLocation resource) {
  164. if (enable && resource != null) {
  165. ResourceLocation newResource = new ResourceLocation(resource.getNamespace(), resource.getPath().replaceFirst("^textures/", "mcpatcher/"));
  166. if (TexturePackAPI.hasResource(newResource)) {
  167. logger.fine("using %s instead of %s", newResource, resource);
  168. return newResource;
  169. }
  170. }
  171. return resource;
  172. }
  173. private static boolean isOpaque(int pixel) {
  174. for (int i : SPACERS) {
  175. if (pixel == i) {
  176. return false;
  177. }
  178. }
  179. return ((pixel >> 24) & 0xf0) > 0;
  180. }
  181. private static boolean printThis(int ch) {
  182. return "ABCDEF abcdef".indexOf(ch) >= 0;
  183. }
  184. private static float defaultSpaceWidth(float[] charWidthf) {
  185. if (TexturePackAPI.isDefaultTexturePack()) {
  186. return 4.0f;
  187. }
  188. float sum = 0.0f;
  189. int n = 0;
  190. for (char ch : AVERAGE_CHARS) {
  191. if (charWidthf[ch] > 0.0f) {
  192. sum += charWidthf[ch];
  193. n++;
  194. }
  195. }
  196. if (n > 0) {
  197. return sum / (float) n * 7.0f / 12.0f;
  198. } else {
  199. return 4.0f;
  200. }
  201. }
  202. private static void getCharWidthOverrides(ResourceLocation font, float[] charWidthf, boolean[] isOverride) {
  203. ResourceLocation textFile = TexturePackAPI.transformResourceLocation(font, ".png", ".properties");
  204. Properties props = TexturePackAPI.getProperties(textFile);
  205. if (props == null) {
  206. return;
  207. }
  208. logger.fine("reading character widths from %s", textFile);
  209. for (Map.Entry entry : props.entrySet()) {
  210. String key = entry.getKey().toString().trim();
  211. String value = entry.getValue().toString().trim();
  212. if (key.matches("^width\\.\\d+$") && !value.equals("")) {
  213. try {
  214. int ch = Integer.parseInt(key.substring(6));
  215. float width = Float.parseFloat(value);
  216. if (ch >= 0 && ch < charWidthf.length) {
  217. logger.finer("setting charWidthf[%d] to %f", ch, width);
  218. charWidthf[ch] = width;
  219. isOverride[ch] = true;
  220. }
  221. } catch (NumberFormatException e) {
  222. }
  223. }
  224. }
  225. }
  226. }