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