All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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