/** Object PixelFont
 *	creates objects with choosed pixel font runtime
 * -----------------------------------------------------------
 * @author		Andrea Giammarchi
 * @site		www.devpro.it
 * @date		2006-10-20
 * @version		SWF OBJECT 0.1 [should beincluded only for IE
 *			<!--[if IE]><script type="text/javascript" src="PixelFontIE.js"></script><![endif]-->
 * -----------------------------------------------------------
 * Public Static Method
 * - Create
 * 	PixelFont.Create(Element:Mixed, Font:PFObject, style:String, value:Object):HTMLCanvasElement
 * @param	Mixed		String/HTMLGenericElement, should contains one or more strings to create Pixel Font graphic version.
 * 				Every nested element will be replaced and SWF OBJECT with Pixel Font String rappresentation will be append as unique childNode.
 *				Generated Pixel Font string should be multile if element text contains one or more "\n" ("Hello\nWorld\n!!!" 3 lines, Hello, World and !!!)
 * @return	PFObject	Pixel Font dedicated Font Object (read line 36 or view AGFont.js file for an example)
 * @return	String		dedicated SWF OBJECT fillStyle string (#123, #123456, rgb(0, 1, 2), rgba(0, 1, 2, 0.5)) rgba uses alpha too
 * @return	Object		an object with 3 keys and values
 *				space		Int32		pixels between two chars
 *				margin		Int32		pixels between each point
 *				size		Inte32		pixels width and height of each point
 *
 *		PixelFont gives you 3 dedicated style objects, plus default object.
 *			PixelFont.Big		generates a big and pixelated version of the string
 *			PixelFont.Bold		generates a bold string (better with uppercase chars)
 *			PixelFont.Dotted	generates an exploded version of the string
 *
 * Public Static Parameters
 * - Big
 * 	PixelFont.Big		Object		dedicated style to have a big font
 * - Bold
 * 	PixelFont.Bold		Object		dedicated style to have a bold font
 * - Dotted
 * 	PixelFont.Dotted	Object		dedicated style to have an "exploded" font
 * -----------------------------------------------------------
 * What is a cell string ?
 *
 * Every Font should contain different key/value parameters.
 * Each key will be respective char code of a single char.
 * For example, zero char '0' char code is 48 then to draw this char
 * Pixel Font should have a UInt32 48 key with respective string coordinates value.
 *
 *	// table object example with only char "0"
 * 	var	GenericFont = {
 *			height:4,		// font height
 *			48:"301235689ab"	// zero char "0"
 *		};
 * 
 * Every string contains markable cells after first width value.
 * In this example 3 is the cell width, then font is a generic 3x4 pixel font.
 * Every other char is a base 36 rappresentation of each markable cells.
 * In this example, zero char coordinates are these:
 * 	------
 *	|0|1|2|
 *	|3| |5|
 *	|6| |8|
 *	|9|a|b|
 *	------
 * that will be a cell with these empty points:
 * 	***
 *	* *
 *	* *
 *	***
 * Maximum pixel font area is 36 (6*6) because
 * Pixel Font is compatible only with Base 36 integers.
 */
PixelFont = new function(){
	
	// static public method to create a pixel font
	this.Create = function(id, Font, style, value){
		function get(id, get){
			return value ? integer(value[id], get) : get;
		};
		function integer(integer, value){
			return integer === undefined ? value : parseInt(integer);
		};
		var	Element = id.constructor === String ? document.getElementById(id) : id,
			Render = new PixelFont.Render(
				Element,
				new PixelFont.Font(Font),
				get("space", 1),
				get("margin", 0),
				get("size", 1)
			);
		return Render.Create(Element.firstChild, Font, Render.Canvas.content, style);
	};

	// static public pixel font dedicated styles
	this.Big = {space:2, margin:0, size:2};
	this.Bold = {space:-1, margin:3, size:-2};
	this.Dotted = {space:1, margin:1, size:1};

	// static "private" methods to render canvas, manages font and creates values
	this.Canvas = function(Element, Font, space, margin, size){
		this.get = function(){
			return Canvas;
		};
		this.content = "";
		function Create(self, Canvas){
			var	id = null,
				content = nodeValue(Element).replace(/(^\s+|\s+$)/, "").replace(/\n|\r|\r\n|\n\r/g, "\n"),
				string = content.split("\n"),
				rows = string.length,
				subheight = (Font.height * size) + (Font.height * margin + margin) + space,
				c = 0,
				row = 0,
				cell = 0,
				width = 0,
				height = 0,
				length = 0,
				sublength = 0,
				max = Math.max,
				random = Math.random;
			while(row < rows) {
				c = 0;
				sublength = 0;
				length = string[row].length;
				while(c < length){
					cell = parseInt(Font.get(string[row].charAt(c++)).charAt(0), 36);
					sublength += (cell * size) + (cell * margin + margin) + space;
				};
				width = max(width, sublength);
				height += subheight;
				++row;
			};
			do{id = "canvas-".concat(random() * 1234567890)}while(document.getElementById(id));
			width -= space;
			height -= space;
			Element.innerHTML = [
				'<object',
					'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"',
					'width="' + width + '"',
					'height="' + height + '"',
					'id="' + id + '"',
				'>',
					'<param name="movie" value="canvas.swf" />',
					'<param name="quality" value="best" />',
					'<param name="wmode" value="transparent" />',
					'<embed',
							'swliveconnect="true"',
							'width="' + width + '"',
							'height="' + height + '"',
							'name="' + id + '"',
							'src="canvas.swf"',
							'quality="best"',
							'wmode="transparent"',
							'type="application/x-shockwave-flash"',
							'pluginspage="http://www.macromedia.com/go/getflashplayer"',
					'>',
				'</object>'
			].join(' ');
			Canvas = document[id];	
			self.content = Canvas.content = content;
			return Canvas;
		};
		function nodeValue(Element){
			var	i = Element.childNodes.length,
				result = [];
			if(Element.nodeType == 3)
				result.push(Element.nodeValue);
			else {
				while(i--) {
					result.push(nodeValue(Element.childNodes[i]));
					Element.removeChild(Element.childNodes[i]);
				};
				result.reverse();
			};
			return result.join("");
		};
		var	Canvas = Create(this, null);
	};
	this.Font = function(Font){
		this.get = function(c){
			return Font[c.charCodeAt(0)] || Font[0];
		};
		this.height = Font.height;
	};
	this.Render = function(Element, Font, space, margin, size){
		this.Create = function(Canvas, Font, content, style){
			var	i, tmp = [];
			for(i in Font) {
				if(i != "height")
					tmp.push(i, Font[i]);
			};
			if(style)
				Canvas.SetVariable('c', style);
			Canvas.SetVariable('toeval', size + "|" + margin + "|" + space + "|" + Font.height + "|" + tmp.join("|"));
			Canvas.SetVariable('str', content);
			Canvas.TCallLabel('_root', 'render');
			return Canvas;
		};
		this.get = function(){
			return this.Canvas.get();
		};
		this.Canvas = new PixelFont.Canvas(Element, Font, space, margin, size);
	};
	this.init = function(){
		var	self = this,
			onload = window.onload;
		window.onload = function(){
			var	img = document.createElement("IMG");
			img.onerror = function(){document.body.removeChild(img); self.init = function(){}};
			document.body.appendChild(img);
			img.src = "canvas.swf";
			if(onload)
				onload();
		};
	};
};
// SWF caching
PixelFont.init();