/** * Filename: DataSet.java * Version: $Version$ * Copyright(c) Ubiquity Software Corporation * http://www.ubiquitysoftware.com */ package org.newdawn.slick.tools.hiero; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * The data set generated from the font rendering * * @author kevin */ public class DataSet { /** The character information */ private ArrayList chars = new ArrayList(); /** The kerning information */ private ArrayList kerning = new ArrayList(); /** The name fo the font face */ private String fontName; /** The height of generated texture */ private int height; /** The width of generated texture */ private int width; /** The name of the set */ private String setName; /** The name of the image */ private String imageName; /** The font size */ private int size; /** The global line height */ private int lineHeight; /** * Create a new data set * * @param fontName The name of the font generated * @param size The size of the font generated * @param lineHeight The height of a line of text * @param width The width of the texture generated * @param height The height of the texture generated * @param setName The name of the set * @param imageName The name of the image */ public DataSet(String fontName, int size, int lineHeight, int width, int height, String setName, String imageName) { this.fontName = fontName; this.height = height; this.width = width; this.setName = setName; this.imageName = imageName; this.size = size; this.lineHeight = lineHeight; } /** * Clear the kerning data */ public void clearKerning() { kerning.clear(); } /** * Dump statistics on this set */ public void dumpStats() { System.out.println("Kerning Count: "+kerning.size()); } /** * Output this data set as an angel code data file * * @param imageName The name of the image to reference * @param out The output stream to write to */ public void toAngelCodeText(PrintStream out, String imageName) { out.println("info face=\""+fontName+"\" size="+size+" bold=0 italic=0 charset=\""+setName+"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1"); out.println("common lineHeight="+lineHeight+" base=26 scaleW="+width+" scaleH="+height+" pages=1 packed=0"); out.println("page id=0 file=\""+imageName+"\""); out.println("chars count="+chars.size()); for (int i=0;i<chars.size();i++) { CharData c = (CharData) chars.get(i); out.println("char id="+c.getID()+" x="+c.getX()+" y="+c.getY()+" width="+c.getWidth()+" height="+c.getHeight()+" xoffset=0 yoffset="+c.getYOffset()+" xadvance="+c.getXAdvance()+" page=0 chnl=0 "); } out.println("kernings count="+kerning.size()); for (int i=0;i<kerning.size();i++) { KerningData k = (KerningData) kerning.get(i); out.println("kerning first="+k.first+" second="+k.second+" amount="+k.offset); } } /** * Output this data set as an angle code XML data file * * @param out The output stream to write to * @param imageName The name of the image * @throws IOException Indicates a failure to build the XML */ public void toAngelCodeXML(PrintStream out, String imageName) throws IOException { try { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = builder.newDocument(); Element root = document.createElement("font"); document.appendChild(root); Element info = document.createElement("info"); info.setAttribute("face",fontName); info.setAttribute("size",""+size); info.setAttribute("bold","0"); info.setAttribute("italic","0"); info.setAttribute("charSet",setName); info.setAttribute("unicode",""+0); info.setAttribute("stretchH",""+100); info.setAttribute("smooth",""+0); info.setAttribute("aa",""+0); info.setAttribute("padding","0,0,0,0"); info.setAttribute("spacing","0,0"); root.appendChild(info); Element common = document.createElement("common"); common.setAttribute("lineHeight",""+lineHeight); common.setAttribute("base","0"); common.setAttribute("scaleW",""+width); common.setAttribute("scaleH",""+height); common.setAttribute("pages","1"); common.setAttribute("packed","0"); root.appendChild(common); Element pages = document.createElement("pages"); Element page = document.createElement("page"); page.setAttribute("id","0"); page.setAttribute("file",imageName); root.appendChild(pages); pages.appendChild(page); Element charsElement = document.createElement("chars"); charsElement.setAttribute("count",""+chars.size()); root.appendChild(charsElement); for (int i=0;i<chars.size();i++) { CharData c = (CharData) chars.get(i); Element charElement = document.createElement("char"); charElement.setAttribute("id", ""+c.getID()); charElement.setAttribute("x", ""+c.getX()); charElement.setAttribute("y", ""+c.getY()); charElement.setAttribute("width", ""+c.getWidth()); charElement.setAttribute("height", ""+c.getHeight()); charElement.setAttribute("xoffset", "0"); charElement.setAttribute("yoffset", ""+c.getYOffset()); charElement.setAttribute("xadvance", ""+c.getXAdvance()); charElement.setAttribute("page", "0"); charElement.setAttribute("chnl", "0"); charsElement.appendChild(charElement); } Element kernsElement = document.createElement("kernings"); kernsElement.setAttribute("count",""+kerning.size()); root.appendChild(kernsElement); for (int i=0;i<kerning.size();i++) { KerningData k = (KerningData) kerning.get(i); Element kernElement = document.createElement("kerning"); kernElement.setAttribute("first", ""+k.first); kernElement.setAttribute("second", ""+k.second); kernElement.setAttribute("amount", ""+k.offset); kernsElement.appendChild(kernElement); } Result result = new StreamResult(new OutputStreamWriter(out, "utf-8")); DOMSource source = new DOMSource(document); TransformerFactory factory = TransformerFactory.newInstance(); factory.setAttribute("indent-number", new Integer(2)); Transformer xformer = factory.newTransformer(); xformer.setOutputProperty(OutputKeys.INDENT, "yes"); xformer.transform(source, result); } catch (Exception e) { e.printStackTrace(); IOException x = new IOException(); x.initCause(e); throw x; } } /** * Add a character to the data set * * @param code The character code * @param xadvance The advance on the x axis after writing this character * @param x The x position on the sheet of the character * @param y The y position on the sheet of the character * @param width The width of the character on the sheet * @param height The height of the character on the sheet * @param yoffset The offset on the y axis when drawing the character */ public void addCharacter(int code, int xadvance, int x, int y, int width, int height,int yoffset) { chars.add(new CharData(code, xadvance, x, y, width, height,size + yoffset)); } /** * Add some kerning data * * @param first The first character * @param second The second character * @param offset The kerning offset to apply */ public void addKerning(int first, int second, int offset) { kerning.add(new KerningData(first, second, offset)); } /** * Info about a single character * * @author kevin */ public class CharData { /** The character code */ private int id; /** The advance on the x axis after writing this character */ private int xadvance; /** The x position on the sheet of the character */ private int x; /** The y position on the sheet of the character */ private int y; /** The width of the character on the sheet */ private int width; /** The height of the character on the sheet */ private int height; /** The offset on the y axis when drawing the character */ private int yoffset; /** * Create a new set of character data * * @param id * The character code * @param xadvance * The advance on the x axis after writing this character * @param x * The x position on the sheet of the character * @param y * The y position on the sheet of the character * @param width * The width of the character on the sheet * @param height * The height of the character on the sheet * @param yoffset * The offset on the y axis when drawing the character */ public CharData(int id, int xadvance, int x, int y, int width, int height, int yoffset) { this.id = id; this.xadvance = xadvance; this.x = x; this.y = y; this.width = width; this.height = height; this.yoffset = yoffset; } /** * Get the character code * * @return The character code */ public int getID() { return id; } /** * Get the advance on the X axis * * @return The advance on the X axis */ public int getXAdvance() { return xadvance; } /** * Get the x position of the character on the sheet * * @return The x position of the character on the sheet */ public int getX() { return x; } /** * Get the y position of the character on the sheet * * @return The y position of the character on the sheet */ public int getY() { return y; } /** * Get the width of the character on the sheet * * @return The width of the character on the sheet */ public int getWidth() { return width; } /** * Get the height of the character on the sheet * * @return The height of the character on the sheet */ public int getHeight() { return height; } /** * The offset on the y axis when drawing the character * * @return The offset on the y axis when drawing the character */ public int getYOffset() { return yoffset; } } /** * Kerning data for a particular character pair * * @author kevin */ public class KerningData { /** The first character */ private int first; /** The second character */ private int second; /** The kerning offset */ private int offset; /** * Create a new kerning pair * * @param first The first character * @param second The second character * @param offset The kerning offset to apply */ public KerningData(int first, int second, int offset) { this.first = first; this.second = second; this.offset = offset; } } }