PageRenderTime 95ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

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

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