// ================================================================================================= // // Starling Framework // Copyright 2011 Gamua OG. All Rights Reserved. // // This program is free software. You can redistribute and/or modify it // in accordance with the terms of the accompanying license agreement. // // ================================================================================================= package starling.text { import flash.geom.Rectangle; import flash.utils.Dictionary; import starling.display.DisplayObject; import starling.display.Image; import starling.display.Sprite; import starling.textures.Texture; import starling.utils.HAlign; import starling.utils.VAlign; /** The BitmapFont class parses bitmap font files and arranges the glyphs * in the form of a text. * * The class parses the XML format as it is used in the * AngelCode Bitmap Font Generator or * the Glyph Designer. * This is what the file format looks like: * *
 
	 *  <font>
	 *    <info face="BranchingMouse" size="40" />
	 *    <common lineHeight="40" />
	 *    <pages>  <!-- currently, only one page is supported -->
	 *      <page id="0" file="texture.png" />
	 *    </pages>
	 *    <chars>
	 *      <char id="32" x="60" y="29" width="1" height="1" xoffset="0" yoffset="27" xadvance="8" />
	 *      <char id="33" x="155" y="144" width="9" height="21" xoffset="0" yoffset="6" xadvance="9" />
	 *    </chars>
	 *    <kernings> <!-- Kerning is optional -->
	 *      <kerning first="83" second="83" amount="-4"/>
	 *    </kernings>
	 *  </font>
     *  
* * Pass an instance of this class to the method registerBitmapFont of the * TextField class. Then, set the fontName property of the text field to the * name value of the bitmap font. This will make the text field use the bitmap * font. */ public class BitmapFont { /** Use this constant for the fontSize property of the TextField class to * render the bitmap font in exactly the size it was created. */ public static const NATIVE_SIZE:int = -1; private static const CHAR_SPACE:int = 32; private static const CHAR_TAB:int = 9; private static const CHAR_NEWLINE:int = 10; private var mTexture:Texture; private var mChars:Dictionary; private var mName:String; private var mSize:Number; private var mLineHeight:Number; /** Creates a bitmap font by parsing an XML file and uses the specified texture. */ public function BitmapFont(texture:Texture, fontXml:XML=null) { mName = "unknown"; mLineHeight = mSize = 14; mTexture = texture; mChars = new Dictionary(); if (fontXml) parseFontXml(fontXml); } /** Disposes the texture of the bitmap font! */ public function dispose():void { if (mTexture) mTexture.dispose(); } private function parseFontXml(fontXml:XML):void { mName = fontXml.info.attribute("face"); mSize = parseFloat(fontXml.info.attribute("size")); mLineHeight = parseFloat(fontXml.common.attribute("lineHeight")); if (mSize <= 0) { trace("[Starling] Warning: invalid font size in '" + mName + "' font."); mSize = (mSize == 0.0 ? 16.0 : mSize * -1.0); } for each (var charElement:XML in fontXml.chars.char) { var id:int = parseInt(charElement.attribute("id")); var xOffset:Number = parseFloat(charElement.attribute("xoffset")); var yOffset:Number = parseFloat(charElement.attribute("yoffset")); var xAdvance:Number = parseFloat(charElement.attribute("xadvance")); var region:Rectangle = new Rectangle(); region.x = parseFloat(charElement.attribute("x")); region.y = parseFloat(charElement.attribute("y")); region.width = parseFloat(charElement.attribute("width")); region.height = parseFloat(charElement.attribute("height")); var texture:Texture = Texture.fromTexture(mTexture, region); var bitmapChar:BitmapChar = new BitmapChar(id, texture, xOffset, yOffset, xAdvance); addChar(id, bitmapChar); } for each (var kerningElement:XML in fontXml.kernings.kerning) { var first:int = parseInt(kerningElement.attribute("first")); var second:int = parseInt(kerningElement.attribute("second")); var amount:Number = parseFloat(kerningElement.attribute("amount")); getChar(second).addKerning(first, amount); } } /** Returns a single bitmap char with a certain character ID. */ public function getChar(charID:int):BitmapChar { return mChars[charID]; } /** Adds a bitmap char with a certain character ID. */ public function addChar(charID:int, bitmapChar:BitmapChar):void { mChars[charID] = bitmapChar; } /** Creates a display object that contains the given text by arranging individual chars. */ public function createDisplayObject(width:Number, height:Number, text:String, fontSize:Number=-1, color:uint=0xffffff, hAlign:String="center", vAlign:String="center", autoScale:Boolean=true, kerning:Boolean=true):DisplayObject { if (fontSize == NATIVE_SIZE) fontSize = mSize; var lineContainer:Sprite; var finished:Boolean = false; while (!finished) { var scale:Number = fontSize / mSize; lineContainer = new Sprite(); if (mLineHeight * scale <= height) { var containerWidth:Number = width / scale; var containerHeight:Number = height / scale; lineContainer.scaleX = lineContainer.scaleY = scale; var lastWhiteSpace:int = -1; var lastCharID:int = -1; var currentX:Number = 0; var currentLine:Sprite = new Sprite(); var numChars:int = text.length; for (var i:int=0; i containerWidth) { // remove characters and add them again to next line var numCharsToRemove:int = lastWhiteSpace == -1 ? 1 : i - lastWhiteSpace; var removeIndex:int = currentLine.numChildren - numCharsToRemove; for (var r:int=0; r