org.gwtwidgets.fontcreator.BitmapFontCreator Maven / Gradle / Ivy
package org.gwtwidgets.fontcreator;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.font.LineMetrics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
public class BitmapFontCreator {
private int standardOffsetX = 2;
private int standardOffsetY = 1;
private String prefix="";
private int offsetTop;
private int offsetLeft;
private int imageWidth;
private int imageHeight;
private int oldChar = -1;
private StringBuilder sb = new StringBuilder();
private static void printUsage() {
System.out.println("Parameters: canvasFontName systemFontName outputPath ranges\n" + "\n"
+ "canvasFontName: name of the generated font files\n"
+ "systemFontName: name and size of font to render\n"
+ "outputPath: path to write bitmap and font information file to\n"
+ "ranges: character index ranges\n" + "\n" + "Example:\n"
+ "BitmapFontCreator arial12 Arial-12-Plain /home/me/ 12-128,225-320,330-407\n");
}
private static List getRanges(String arg) {
List ranges = new ArrayList();
String[] intervals = arg.split(",");
for (String interval : intervals) {
String[] bounds = interval.split("-");
if (bounds.length != 2) {
System.out.println("Interval " + interval + " should be in the form X-Y");
System.exit(3);
}
int lower = Integer.parseInt(bounds[0]);
int upper = Integer.parseInt(bounds[1]);
if (upper < lower) {
System.out.println(interval + " should note first the lower and then the upper bound");
System.exit(4);
}
Integer[] iBounds = new Integer[] { lower, upper };
ranges.add(iBounds);
}
return ranges;
}
private BufferedImage createImage(int width, int height) {
return new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
}
private boolean canDisplay(Font font, FontMetrics metrics, char c){
return font.canDisplay((char)c) && metrics.charWidth((char) c) > 0;
}
private String encodeInt(int value){
return Integer.toString(value, 26);
}
private void appendInt(int value){
sb.append(prefix).append(encodeInt(value));
prefix=",";
}
private void newRecord(int advanceBy){
offsetTop+=advanceBy;
prefix="";
sb.append("\n");
appendInt(advanceBy);
}
public void dumpFont(String fontName, String systemFontName, File path, List ranges) {
Font font = Font.decode(systemFontName);
BufferedImage image = createImage(500, 500);
Graphics2D g = image.createGraphics();
FontMetrics metrics = g.getFontMetrics(font);
int blockHeight = metrics.getHeight();
int blockWidth = 0;
int charNum = 0;
for (Integer[] interval : ranges) {
int lower = interval[0];
int higher = interval[1];
for (int c = lower; c <= higher; c++) {
if (!canDisplay(font, metrics, (char)c))
continue;
int width = metrics.charWidth((char) c);
blockWidth = Math.max(blockWidth, width);
charNum++;
}
}
g.dispose();
// IE produces ugly artifacts when scaling image portions which are near to the border.
// This is why a blank border is placed around the image.
imageWidth = (int)Math.round(Math.sqrt(charNum)+1)*blockWidth + 2*standardOffsetX;
imageHeight = (int)Math.round(Math.sqrt(charNum)+1)*blockHeight + 2*standardOffsetY;
image = createImage(imageWidth, imageHeight);
g = image.createGraphics();
g.setColor(Color.black);
appendInt(blockWidth);
appendInt(blockHeight);
appendInt(imageWidth);
appendInt(imageHeight);
offsetTop = 0;
offsetLeft = standardOffsetX;
oldChar = -1;
newRecord(standardOffsetY);
for (Integer[] interval : ranges) {
int lower = interval[0];
int higher = interval[1];
for (int c = lower; c <= higher; c++) {
if (!canDisplay(font, metrics, (char)c))
continue;
LineMetrics lineMetrics = metrics.getLineMetrics(""+(char)c, g);
int width = metrics.charWidth((char) c);
if (c!=oldChar+1)
appendInt(-c);
appendInt(width);
appendInt(offsetLeft);
oldChar = c;
g.drawString("" + (char) c, offsetLeft, offsetTop+lineMetrics.getLeading()+lineMetrics.getAscent());
offsetLeft+=blockWidth;
if (offsetLeft>imageWidth-blockWidth-standardOffsetX){
offsetLeft = standardOffsetX;
newRecord(blockHeight);
}
}
}
g.dispose();
File fImage = new File(path, fontName + ".png");
File fLookup = new File(path, fontName + ".txt");
try {
ImageIO.write(image, "png", fImage);
FileWriter fw = new FileWriter(fLookup);
fw.write(sb.toString());
fw.flush();
fw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String... args) throws Exception {
if (args.length != 4) {
printUsage();
System.exit(1);
return;
}
BitmapFontCreator fontCreator = new BitmapFontCreator();
File path = new File(args[2]);
if (!path.exists()) {
System.out.println(path + " does not exist.");
System.exit(2);
}
List ranges = getRanges(args[3]);
fontCreator.dumpFont(args[0], args[1], path, ranges);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy