package Packer {
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldType;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormatAlign;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.*;
import flash.display.MovieClip;
import flash.text.AntiAliasType;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.text.TextLineMetrics;
import djarts.core.*;
public class BitmapFont
{
public var CodepointData:Array = new Array();
public var IndexByCodepoint = {};
public var Name = "";
public var Size;
public var Bold;
public var AsBackupOnly = false;
private var backupFont:BitmapFont = null;
private var useBackupCodepoints = {};
private var useDeviceFontIfNeccessary = true;
private var fontFaceName;
public function BitmapFont(font:String, size:int, bold, backupFont:BitmapFont = null, useBackupCodepoints:String = null, asBackupOnly = false, useDeviceFontIfNeccessary = true)
{
this.fontFaceName = font;
this.Name = font + size + (bold ? "Bold" : "");
this.Size = size;
this.Bold = bold;
this.backupFont = backupFont;
if (useBackupCodepoints != null)
{
for (var i = 0; i < useBackupCodepoints.length; i++)
{
this.useBackupCodepoints[useBackupCodepoints.charCodeAt(i)] = true;
}
}
this.useDeviceFontIfNeccessary = useDeviceFontIfNeccessary;
this.AsBackupOnly = asBackupOnly;
var additionalChars = "";
/*
for (var i = 1024; i < 1280; i++)
{
additionalChars += String.fromCharCode(i);
}
*/
CreateFrames(font, size, bold, additionalChars /*"δΎ§"*/);
}
private function AddCodepoint(data:FontCodepointData)
{
IndexByCodepoint[data.Codepoint] = CodepointData.length;
CodepointData.push(data);
}
private var lineHeight = 10;
public function CreateFrames(font:String, size:int, bold, additionalCodepoints:String)
{
var base:String = "";
for (var i = 32; i < 256; i++)
{
base += String.fromCharCode(i);
}
var text:String = base + additionalCodepoints;
var t:TextField = new TextField();
var f:TextFormat = new TextFormat();
f.font = font;
f.color = 0xFFFFFF;
f.size = size;
f.bold = bold;
t.type = TextFieldType.DYNAMIC;
t.defaultTextFormat = f;
t.selectable = false;
t.autoSize = TextFieldAutoSize.LEFT;
t.embedFonts = true;
t.antiAliasType = AntiAliasType.ADVANCED;
var tDevice:TextField = new TextField();
tDevice.type = TextFieldType.DYNAMIC;
tDevice.defaultTextFormat = f;
tDevice.selectable = false;
tDevice.autoSize = TextFieldAutoSize.LEFT;
tDevice.embedFonts = false;
tDevice.antiAliasType = AntiAliasType.ADVANCED;
t.text = "Test";
var testMetrics:TextLineMetrics = t.getLineMetrics(0);
lineHeight = testMetrics.height;
for (var i = 0; i < text.length; i++)
{
var codepointStr = text.charAt(i);
var codepoint = text.charCodeAt(i);
var field:TextField = t;
field.text = codepointStr;
var lm:TextLineMetrics = t.getLineMetrics(0);
if ((lm.width == 0 && codepoint != 32) || this.useBackupCodepoints[codepoint])
{
// not sure we need this recursive search, actually
var searchFont = this;
var found = false;
while (searchFont != null)
{
if (searchFont.backupFont != null && searchFont.backupFont.IndexByCodepoint[codepoint] != undefined)
{
// use the backup font's frame
var index = searchFont.backupFont.IndexByCodepoint[codepoint];
if (searchFont.backupFont.CodepointData[index] && searchFont.backupFont.CodepointData[index].CodepointWidth != 0)
{
var data:FontCodepointData = new FontCodepointData(codepoint);
data.InitFromOtherFont(searchFont.backupFont, index);
AddCodepoint(data);
searchFont.backupFont.CodepointData[searchFont.backupFont.IndexByCodepoint[codepoint]].References++;
found = true;
break;
}
}
break;
//searchFont = searchFont.backupFont;
}
if (found) continue;
if (this.useBackupCodepoints[codepoint])
{
// back up font didn't have this character, so skip
continue;
}
if (this.useDeviceFontIfNeccessary)
{
field = tDevice;
tDevice.text = codepointStr;
lm = tDevice.getLineMetrics(0);
}
}
var bounds:Rectangle = CacheManager.Instance().GetAccurateBounds(field);
bounds.left = Math.floor(bounds.left);
bounds.right = Math.ceil(bounds.right);
bounds.top = Math.floor(bounds.top);
bounds.bottom = Math.ceil(bounds.bottom);
if ((bounds.width == 0 || bounds.height == 0) && codepoint != 32) continue;
var offsetX = 0;
var offsetY = 0;
if (fontFaceName == "Grobold" && codepointStr == ".")
{
var tf:TextFormat = field.defaultTextFormat;
tf.size = size + 25;
field.defaultTextFormat = tf;
// is this neccessary to refresh the size???
field.text = field.text;
var newBounds:Rectangle = CacheManager.Instance().GetAccurateBounds(field);
newBounds.left = Math.floor(newBounds.left);
newBounds.right = Math.ceil(newBounds.right);
newBounds.top = Math.floor(newBounds.top);
newBounds.bottom = Math.ceil(newBounds.bottom);
offsetY -= (newBounds.bottom - bounds.bottom);
bounds.left = newBounds.left;
bounds.right = newBounds.right;
bounds.top = Math.min(bounds.top, newBounds.top + offsetY);
lm = t.getLineMetrics(0);
}
if (fontFaceName == "Grobold" && (codepointStr == "!" || codepointStr == "%"))
{
var adjust = Math.floor(bounds.left * 0.7);
bounds.x -= adjust;
offsetX -= adjust;
}
var bitmapData:BitmapData = new BitmapData(bounds.width + GraphicPacker.PAD * 2, bounds.height + GraphicPacker.PAD * 2, true, 0x00000000);
bitmapData.draw(field, new Matrix(1, 0, 0, 1, -bounds.left + GraphicPacker.PAD + offsetX, -bounds.top + GraphicPacker.PAD + offsetY));
var data:FontCodepointData = new FontCodepointData(codepoint);
var offset:Point = new Point(-bounds.left + GraphicPacker.PAD, -bounds.top + GraphicPacker.PAD);
var codepointWidth = Math.ceil(lm.width);
if (lm.width > bounds.width && bounds.width != 0)
{
codepointWidth = bounds.width;
}
data.Init(bitmapData, offset, codepointWidth);
AddCodepoint(data);
if (fontFaceName == "Grobold" && codepointStr == ".")
{
var tf:TextFormat = field.defaultTextFormat;
tf.size = size;
field.defaultTextFormat = tf;
}
}
}
public function GetAdditionalData()
{
var codepoints:Array = new Array();
var advances:Array = new Array(); // the width of the character (not the character graphic) is called advance in the client
for (var i = 0; i < CodepointData.length; i++)
{
codepoints.push(CodepointData[i].Codepoint);
advances.push(CodepointData[i].CodepointWidth);
}
return {"codepoints":codepoints,"advances":advances,"line_height":lineHeight};
}
}
}