/*
* Copyright (c) 2015 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/

package com.snowplowanalytics.snowplow.tracker
{
	import com.snowplowanalytics.snowplow.tracker.util.UUID;

	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;

	import mx.utils.Base64Encoder;

	public class Util
	{
		public static function isNullOrEmpty(str:*):Boolean
		{
			return str == null || (str is String && (str as String).length == 0);
		}

		public static function padZeroes (value:*, places:int = 2):String
		{
			var str:String = value.toString();
			var zeroes:int = places - str.length;
			if (zeroes > 0)
			{
				for (var i:int=0;i<zeroes;i++)
				{
					str = "0" + str;
				}
			}
			return str;
		}

		private static function callCallback (dataFormat:String, loader:URLLoader, callback:Function):void
		{
			var result:*;

			switch (dataFormat)
			{
				case URLLoaderDataFormat.TEXT:
				case URLLoaderDataFormat.VARIABLES:
					result = loader.data;
					break;
				case URLLoaderDataFormat.BINARY:
				default:
					result = ByteArray(loader.data);
					break;
			}

			callback(result);
		}

		public static function getResponse	(
				url:String,
				callback:Function,
				errorCallback:Function,
				method:String = "get",
				postData:String = null,
				dataFormat:String = "text"
			):void
		{
			var loader:URLLoader = new URLLoader();
			var request:URLRequest = new URLRequest(url);
			request.method = method;

			if (postData != null && method == URLRequestMethod.POST)
			{
				request.data = postData;
				request.contentType = "application/json; charset=utf-8";
			}

			loader.dataFormat = dataFormat;

			loader.addEventListener
				(
					Event.COMPLETE,
					function (event:Event):void
					{
						if (callback != null)
						{
							callCallback(dataFormat, loader, callback);
						}
					}
				);

			loader.addEventListener
				(
					IOErrorEvent.IO_ERROR,
					function (event:IOErrorEvent):void
					{
						if (event.type == "201")
						{
							if (callback != null)
							{
								callCallback(dataFormat, loader, callback);
							}
						}
						else
						{
							if (errorCallback != null)
							{
								errorCallback(event);
							}
						}
					}
				);

			loader.addEventListener
				(
					SecurityErrorEvent.SECURITY_ERROR,
					function (event:SecurityErrorEvent):void
					{
						if (errorCallback != null)
						{
							errorCallback(event);
						}
					}
				);

			loader.load(request);
		}

		public static function getEventId():String
		{
			return UUID.generateGuid();
		}

		public static function getTimestamp():String {
			var date:Date = new Date();
			return date.time.toString();
		}

		public static function copyObject (object:Object, returnEmptyObjectIfNull:Boolean = false):Object
		{
			if (object == null)
			{
				if (returnEmptyObjectIfNull)
					return {}
				else
					return null;
			}

			var newObject:Object = {};

			for (var key:String in object) {
				newObject[key] = object[key];
			}

			return newObject;
		}

		/* Addition functions
		*  Used to add different sources of key=>value pairs to a map.
		*  Map is then used to build "Associative array for getter function.
		*  Some use Base64 encoding
		*/
		public static function base64Encode(str:String):String {
			try {
				var encoder:Base64Encoder = new Base64Encoder();
				encoder.encode(str);
				return encoder.flush();
			} catch (e:Error) {
				trace(e.getStackTrace());
			}
			return null;
		}

		public static function getTransactionId():int
		{
			return Math.round(Math.random() * 1000000);
	    }

		public static function clearArray (a:Array):void
		{
			a.splice(0, a.length);
		}

		public static function findFirstItemInArray (array:Array, prop:String, val:*):*
		{
			for each(var item:* in array)
			{
				if (item[prop] == val)
				{
					return item;
				}
			}

			return null;
		}

		/**
		* Return value from name-value pair in querystring
		*/
		private static function fromQuerystring(field:String, url:String):String {
			var match:RegExp = new RegExp('^[^#]*[?&]' + field + '=([^&#]*)').exec(url);
			if (!match) {
				return null;
			}
			return decodeURIComponent(match[1].replace(/\+/g, ' '));
		};

		/**
		* Extract parameter from URL
		*/
		private static function getParameter(url:String, name:String):String {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e:RegExp = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+))([?][^#]+)');
			var	matches:* = e.exec(url);
			var	result:String = fromQuerystring(name, matches[1]);

			return result;
		}

		/**
		* Extract hostname from URL
		*/
		private static function getHostName(url:String):String {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e:RegExp = new RegExp('^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)');
			var	matches:* = e.exec(url);

			return matches ? matches[1] : url;
		};

		/**
		* Test whether a string is an IP address
		*/
		private static function isIpAddress(str:String):Boolean {
			var IPRegExp:RegExp = new RegExp('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$');
			return IPRegExp.test(str);
		}

		/**
		* If the hostname is an IP address, look for text indicating
		* that the page is cached by Yahoo
		*/
		private static function isYahooCachedPage(hostName:String):Boolean
		{
			return false;
			var	initialDivText:String;
			var cachedIndicator:String;

			if (isIpAddress(hostName)) {
				try {
					initialDivText = ExternalInterface.call("function getInitialDivText() { return document.body.children[0].children[0].children[0].children[0].children[0].children[0].innerHTML; }");
					cachedIndicator = 'You have reached the cached page for';
					return initialDivText.slice(0, cachedIndicator.length) === cachedIndicator;
				} catch (e:Error) {
					return false;
				}
			} else {
				return false;
			}
		}

		/**
		* Fix-up domain
		*/
		public static function fixupDomain(domain:String):String {
			var dl:int = domain.length;

			// remove trailing '.'
			if (domain.charAt(--dl) === '.') {
				domain = domain.slice(0, dl);
			}
			// remove leading '*'
			if (domain.slice(0, 2) === '*.') {
				domain = domain.slice(1);
			}
			return domain;
		};

		/**
		 * Fix-up URL when page rendered from search engine cache or translated page.
		 * TODO: it would be nice to generalise this and/or move into the ETL phase.
		 */
		public static function fixupUrl(hostName:String, href:String, referrer:String):Array {

			if (hostName === 'translate.googleusercontent.com') {       // Google
				if (referrer === '') {
					referrer = href;
				}
				href = getParameter(href, 'u');
				hostName = getHostName(href);
			} else if (hostName === 'cc.bingj.com' ||                   // Bing
		  			   hostName === 'webcache.googleusercontent.com' ||            // Google
				       isYahooCachedPage(hostName)) {                         // Yahoo (via Inktomi 74.6.0.0/16)
				try {
					href = ExternalInterface.call("function getLinkHref() { return document.links[0].href; }");
				} catch (e:Error) {
					href = '';
				}
				hostName = getHostName(href);
			}
			return [hostName, href, referrer];
		};

		public static var scriptAccessAllowed:int = -1; //-1 = not set. 0 = false. 1 = true.

		public static function isScriptAccessAllowed ():Boolean
		{
			if (scriptAccessAllowed != -1)
			{
				return scriptAccessAllowed == 1;
			}

			if (!ExternalInterface.available)
			{
				scriptAccessAllowed = 0;
				return false;
			}

			try
			{
				ExternalInterface.call("function isScriptAccessAllowed(){return true;}");
				scriptAccessAllowed = 1;
			}
			catch (error:Error)
			{
				if (error is SecurityError)
				{
					scriptAccessAllowed = 0;
				}
			}

			return scriptAccessAllowed == 1;
		}

		/**
		 * AS Implementation of MurmurHash3
		 *
		 * @param {string} key ASCII only
		 * @param {number} seed Positive integer only
		 * @return {number} 32-bit positive integer hash
		 */
		public static function murmurhash3_32_gc(key:String, seed:Number):Number {
			var remainder:Number;
			var bytes:Number;
			var h1:Number;
			var h1b:Number;
			var c1:Number;
			var c1b:Number;
			var c2:Number;
			var c2b:Number;
			var k1:Number;
			var i:Number;

			remainder = key.length & 3; // key.length % 4
			bytes = key.length - remainder;
			h1 = seed;
			c1 = 0xcc9e2d51;
			c2 = 0x1b873593;
			i = 0;

			while (i < bytes) {
				k1 =
					((key.charCodeAt(i) & 0xff)) |
					((key.charCodeAt(++i) & 0xff) << 8) |
					((key.charCodeAt(++i) & 0xff) << 16) |
					((key.charCodeAt(++i) & 0xff) << 24);
				++i;

				k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
				k1 = (k1 << 15) | (k1 >>> 17);
				k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;

				h1 ^= k1;
				h1 = (h1 << 13) | (h1 >>> 19);
				h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
				h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
			}

			k1 = 0;

			switch (remainder) {
				case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
				case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
				case 1: k1 ^= (key.charCodeAt(i) & 0xff);

					k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
					k1 = (k1 << 15) | (k1 >>> 17);
					k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
					h1 ^= k1;
			}

			h1 ^= key.length;

			h1 ^= h1 >>> 16;
			h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
			h1 ^= h1 >>> 13;
			h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
			h1 ^= h1 >>> 16;

			return h1 >>> 0;
		}
	}
}

/*
* Copyright (c) 2015 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/

package com.snowplowanalytics.snowplow.tracker
{
	import com.snowplowanalytics.snowplow.tracker.util.UUID;

	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;

	import mx.utils.Base64Encoder;

	public class Util
	{
		public static function isNullOrEmpty(str:*):Boolean
		{
			return str == null || (str is String && (str as String).length == 0);
		}

		public static function padZeroes (value:*, places:int = 2):String
		{
			var str:String = value.toString();
			var zeroes:int = places - str.length;
			if (zeroes > 0)
			{
				for (var i:int=0;i<zeroes;i++)
				{
					str = "0" + str;
				}
			}
			return str;
		}

		private static function callCallback (dataFormat:String, loader:URLLoader, callback:Function):void
		{
			var result:*;

			switch (dataFormat)
			{
				case URLLoaderDataFormat.TEXT:
				case URLLoaderDataFormat.VARIABLES:
					result = loader.data;
					break;
				case URLLoaderDataFormat.BINARY:
				default:
					result = ByteArray(loader.data);
					break;
			}

			callback(result);
		}

		public static function getResponse	(
				url:String,
				callback:Function,
				errorCallback:Function,
				method:String = "get",
				postData:String = null,
				dataFormat:String = "text"
			):void
		{
			var loader:URLLoader = new URLLoader();
			var request:URLRequest = new URLRequest(url);
			request.method = method;

			if (postData != null && method == URLRequestMethod.POST)
			{
				request.data = postData;
				request.contentType = "application/json; charset=utf-8";
			}

			loader.dataFormat = dataFormat;

			loader.addEventListener
				(
					Event.COMPLETE,
					function (event:Event):void
					{
						if (callback != null)
						{
							callCallback(dataFormat, loader, callback);
						}
					}
				);

			loader.addEventListener
				(
					IOErrorEvent.IO_ERROR,
					function (event:IOErrorEvent):void
					{
						if (event.type == "201")
						{
							if (callback != null)
							{
								callCallback(dataFormat, loader, callback);
							}
						}
						else
						{
							if (errorCallback != null)
							{
								errorCallback(event);
							}
						}
					}
				);

			loader.addEventListener
				(
					SecurityErrorEvent.SECURITY_ERROR,
					function (event:SecurityErrorEvent):void
					{
						if (errorCallback != null)
						{
							errorCallback(event);
						}
					}
				);

			loader.load(request);
		}

		public static function getEventId():String
		{
			return UUID.generateGuid();
		}

		public static function getTimestamp():String {
			var date:Date = new Date();
			return date.time.toString();
		}

		public static function copyObject (object:Object, returnEmptyObjectIfNull:Boolean = false):Object
		{
			if (object == null)
			{
				if (returnEmptyObjectIfNull)
					return {}
				else
					return null;
			}

			var newObject:Object = {};

			for (var key:String in object) {
				newObject[key] = object[key];
			}

			return newObject;
		}

		/* Addition functions
		*  Used to add different sources of key=>value pairs to a map.
		*  Map is then used to build "Associative array for getter function.
		*  Some use Base64 encoding
		*/
		public static function base64Encode(str:String):String {
			try {
				var encoder:Base64Encoder = new Base64Encoder();
				encoder.encode(str);
				var base64:String = encoder.flush();

				//make base64 url safe.
				base64 = base64.replace(/\+/g, "-");
				base64 = base64.replace(/\//g, "_");
				base64 = base64.replace(/=/g, "");
				base64 = base64.replace(/\n/g, "");
				base64 = base64.replace(/\r/g, "");
				base64 = base64.replace(/\t/g, "");

				return base64;
			} catch (e:Error) {
				trace(e.getStackTrace());
			}
			return null;
		}

		public static function getTransactionId():int
		{
			return Math.round(Math.random() * 1000000);
	    }

		public static function clearArray (a:Array):void
		{
			a.splice(0, a.length);
		}

		public static function findFirstItemInArray (array:Array, prop:String, val:*):*
		{
			for each(var item:* in array)
			{
				if (item[prop] == val)
				{
					return item;
				}
			}

			return null;
		}

		/**
		* Return value from name-value pair in querystring
		*/
		private static function fromQuerystring(field:String, url:String):String {
			var match:RegExp = new RegExp('^[^#]*[?&]' + field + '=([^&#]*)').exec(url);
			if (!match) {
				return null;
			}
			return decodeURIComponent(match[1].replace(/\+/g, ' '));
		};

		/**
		* Extract parameter from URL
		*/
		private static function getParameter(url:String, name:String):String {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e:RegExp = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+))([?][^#]+)');
			var	matches:* = e.exec(url);
			var	result:String = fromQuerystring(name, matches[1]);

			return result;
		}

		/**
		* Extract hostname from URL
		*/
		private static function getHostName(url:String):String {
			// scheme : // [username [: password] @] hostname [: port] [/ [path] [? query] [# fragment]]
			var e:RegExp = new RegExp('^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)');
			var	matches:* = e.exec(url);

			return matches ? matches[1] : url;
		};

		/**
		* Test whether a string is an IP address
		*/
		private static function isIpAddress(str:String):Boolean {
			var IPRegExp:RegExp = new RegExp('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$');
			return IPRegExp.test(str);
		}

		/**
		* If the hostname is an IP address, look for text indicating
		* that the page is cached by Yahoo
		*/
		private static function isYahooCachedPage(hostName:String):Boolean
		{
			return false;
			var	initialDivText:String;
			var cachedIndicator:String;

			if (isIpAddress(hostName)) {
				try {
					initialDivText = ExternalInterface.call("function getInitialDivText() { return document.body.children[0].children[0].children[0].children[0].children[0].children[0].innerHTML; }");
					cachedIndicator = 'You have reached the cached page for';
					return initialDivText.slice(0, cachedIndicator.length) === cachedIndicator;
				} catch (e:Error) {
					return false;
				}
			} else {
				return false;
			}
		}

		/**
		* Fix-up domain
		*/
		public static function fixupDomain(domain:String):String {
			var dl:int = domain.length;

			// remove trailing '.'
			if (domain.charAt(--dl) === '.') {
				domain = domain.slice(0, dl);
			}
			// remove leading '*'
			if (domain.slice(0, 2) === '*.') {
				domain = domain.slice(1);
			}
			return domain;
		};

		/**
		 * Fix-up URL when page rendered from search engine cache or translated page.
		 * TODO: it would be nice to generalise this and/or move into the ETL phase.
		 */
		public static function fixupUrl(hostName:String, href:String, referrer:String):Array {

			if (hostName === 'translate.googleusercontent.com') {       // Google
				if (referrer === '') {
					referrer = href;
				}
				href = getParameter(href, 'u');
				hostName = getHostName(href);
			} else if (hostName === 'cc.bingj.com' ||                   // Bing
		  			   hostName === 'webcache.googleusercontent.com' ||            // Google
				       isYahooCachedPage(hostName)) {                         // Yahoo (via Inktomi 74.6.0.0/16)
				try {
					href = ExternalInterface.call("function getLinkHref() { return document.links[0].href; }");
				} catch (e:Error) {
					href = '';
				}
				hostName = getHostName(href);
			}
			return [hostName, href, referrer];
		};

		public static var scriptAccessAllowed:int = -1; //-1 = not set. 0 = false. 1 = true.

		public static function isScriptAccessAllowed ():Boolean
		{
			if (scriptAccessAllowed != -1)
			{
				return scriptAccessAllowed == 1;
			}

			if (!ExternalInterface.available)
			{
				scriptAccessAllowed = 0;
				return false;
			}

			try
			{
				ExternalInterface.call("function isScriptAccessAllowed(){return true;}");
				scriptAccessAllowed = 1;
			}
			catch (error:Error)
			{
				if (error is SecurityError)
				{
					scriptAccessAllowed = 0;
				}
			}

			return scriptAccessAllowed == 1;
		}

		/**
		 * AS Implementation of MurmurHash3
		 *
		 * @param {string} key ASCII only
		 * @param {number} seed Positive integer only
		 * @return {number} 32-bit positive integer hash
		 */
		public static function murmurhash3_32_gc(key:String, seed:Number):Number {
			var remainder:Number;
			var bytes:Number;
			var h1:Number;
			var h1b:Number;
			var c1:Number;
			var c1b:Number;
			var c2:Number;
			var c2b:Number;
			var k1:Number;
			var i:Number;

			remainder = key.length & 3; // key.length % 4
			bytes = key.length - remainder;
			h1 = seed;
			c1 = 0xcc9e2d51;
			c2 = 0x1b873593;
			i = 0;

			while (i < bytes) {
				k1 =
					((key.charCodeAt(i) & 0xff)) |
					((key.charCodeAt(++i) & 0xff) << 8) |
					((key.charCodeAt(++i) & 0xff) << 16) |
					((key.charCodeAt(++i) & 0xff) << 24);
				++i;

				k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
				k1 = (k1 << 15) | (k1 >>> 17);
				k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;

				h1 ^= k1;
				h1 = (h1 << 13) | (h1 >>> 19);
				h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
				h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
			}

			k1 = 0;

			switch (remainder) {
				case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
				case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
				case 1: k1 ^= (key.charCodeAt(i) & 0xff);

					k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
					k1 = (k1 << 15) | (k1 >>> 17);
					k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
					h1 ^= k1;
			}

			h1 ^= key.length;

			h1 ^= h1 >>> 16;
			h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
			h1 ^= h1 >>> 13;
			h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
			h1 ^= h1 >>> 16;

			return h1 >>> 0;
		}
	}
}

resolve #24 - Base64 encoding must be URL-safe, no padding, no wrapping


package aerys.minko.render.resource.texture
{
	import flash.display.BitmapData;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.textures.Texture;
	import flash.display3D.textures.TextureBase;
	import flash.geom.Matrix;
	import flash.utils.ByteArray;

	/**
	 * @inheritdoc
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class TextureResource implements ITextureResource
	{
		private static const MAX_SIZE			: uint		= 2048;
		private static const TMP_MATRIX			: Matrix	= new Matrix();
		private static const FORMAT_BGRA		: String	= Context3DTextureFormat.BGRA
		private static const FORMAT_COMPRESSED	: String	= Context3DTextureFormat.COMPRESSED;

		private var _texture	: Texture		= null;
		private var _mipmap		: Boolean		= false;

		private var _bitmapData	: BitmapData	= null;
		private var _atf		: ByteArray		= null;

		private var _width		: Number		= 0;
		private var _height		: Number		= 0;

		private var _update		: Boolean		= false;
		private var _resize		: Boolean		= false;

		public function get width() : Number
		{
			return _width;
		}

		public function get height() : Number
		{
			return _height;
		}

		public function TextureResource(width : int = 0, height : int = 0)
		{
			if (width != 0 && height != 0)
				setSize(width, height);
		}

		public function setSize(width : uint, height : uint) : void
		{
			//http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
			if (!(width && !(width & (width - 1)))
				|| !(height && !(height & (height - 1))))
			{
				throw new Error(
					'The size must be a power of 2.'
				);
			}

			_width	= width;
			_height	= height;
			_resize = true;
		}

		public function setContentFromBitmapData(bitmapData	: BitmapData,
								   				 mipmap		: Boolean,
												 downSample	: Boolean	= false) : void
		{
			var bitmapWidth		: uint 	= bitmapData.width;
			var bitmapHeight	: uint 	= bitmapData.height;
			var w				: int	= 0;
			var h				: int	= 0;

			if (downSample)
			{
				w = 1 << Math.floor(Math.log(bitmapWidth) * Math.LOG2E);
				h = 1 << Math.floor(Math.log(bitmapHeight) * Math.LOG2E);
			}
			else
			{
				w = 1 << Math.ceil(Math.log(bitmapWidth) * Math.LOG2E);
				h = 1 << Math.ceil(Math.log(bitmapHeight) * Math.LOG2E);
			}

			if (w > MAX_SIZE)
				w = MAX_SIZE;
			if (h > MAX_SIZE)
				h = MAX_SIZE;

			_bitmapData	= new BitmapData(w, h, bitmapData.transparent, 0);

			if (w != bitmapWidth || h != bitmapHeight)
			{
				TMP_MATRIX.identity();
				TMP_MATRIX.scale(w / bitmapWidth, h / bitmapHeight);
				_bitmapData.draw(bitmapData, TMP_MATRIX);
			}
			else
			{
				_bitmapData.draw(bitmapData);
			}

			if (_texture
				&& (mipmap != _mipmap
					|| bitmapData.width != _width
					|| bitmapData.height != _height))
			{
				_texture.dispose();
				_texture = null;
			}

			_width = _bitmapData.width;
			_height = _bitmapData.height;

			_mipmap	= mipmap;
			_update	= true;
		}

		public function setContentFromATF(atf : ByteArray) : void
		{
			_atf = atf;
		}

		public function getNativeTexture(context : Context3D) : TextureBase
		{
			if ((!_texture || _resize) && _width && _height)
			{
				_resize = false;

				if (_texture)
					_texture.dispose();

				_texture = context.createTexture(
					_width,
					_height,
					_atf ? FORMAT_COMPRESSED : FORMAT_BGRA,
					_bitmapData == null && _atf == null
				);

				_update = true;
			}

			if (_update)
			{
				_update = false;

				uploadTextureWithMipMaps();
			}

			_atf = null;
			_bitmapData = null;

			return _texture;
		}

		private function uploadTextureWithMipMaps() : void
		{
			if (_bitmapData)
			{
				if (_mipmap)
				{
					var level 		: int 			= 0;
					var size		: int 			= _width > _height ? _width : _height;
					var transparent	: Boolean		= _bitmapData.transparent;
					var transform 	: Matrix 		= new Matrix();
					var tmp 		: BitmapData 	= new BitmapData(
						size,
						size,
						transparent,
						0
					);

					while (size >= 1)
					{
						tmp.draw(_bitmapData, transform, null, null, null, true);
						_texture.uploadFromBitmapData(tmp, level);

						transform.scale(.5, .5);
						level++;
						size >>= 1;
						if (tmp.transparent)
							tmp.fillRect(tmp.rect, 0);
					}

					tmp.dispose();
				}
				else
				{
					_texture.uploadFromBitmapData(_bitmapData, 0);
				}

				_bitmapData.dispose();
			}
			else if (_atf)
			{
				_texture.uploadCompressedTextureFromByteArray(_atf, 0, false);
			}
		}

		public function dispose() : void
		{
			_texture.dispose();
			_texture = null;
		}
	}
}

package aerys.minko.render.resource.texture
{
	import flash.display.BitmapData;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.textures.Texture;
	import flash.display3D.textures.TextureBase;
	import flash.geom.Matrix;
	import flash.utils.ByteArray;

	/**
	 * @inheritdoc
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class TextureResource implements ITextureResource
	{
		private static const MAX_SIZE			: uint		= 2048;
		private static const TMP_MATRIX			: Matrix	= new Matrix();
		private static const FORMAT_BGRA		: String	= Context3DTextureFormat.BGRA
		private static const FORMAT_COMPRESSED	: String	= Context3DTextureFormat.COMPRESSED;

		private var _texture	: Texture		= null;
		private var _mipmap		: Boolean		= false;

		private var _bitmapData	: BitmapData	= null;
		private var _atf		: ByteArray		= null;
		private var _atfFormat	: uint			= 0;

		private var _width		: Number		= 0;
		private var _height		: Number		= 0;

		private var _update		: Boolean		= false;
		private var _resize		: Boolean		= false;

		public function get width() : Number
		{
			return _width;
		}

		public function get height() : Number
		{
			return _height;
		}

		public function TextureResource(width : int = 0, height : int = 0)
		{
			if (width != 0 && height != 0)
				setSize(width, height);
		}

		public function setSize(width : uint, height : uint) : void
		{
			//http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
			if (!(width && !(width & (width - 1)))
				|| !(height && !(height & (height - 1))))
			{
				throw new Error(
					'The size must be a power of 2.'
				);
			}

			_width	= width;
			_height	= height;
			_resize = true;
		}

		public function setContentFromBitmapData(bitmapData	: BitmapData,
								   				 mipmap		: Boolean,
												 downSample	: Boolean	= false) : void
		{
			var bitmapWidth		: uint 	= bitmapData.width;
			var bitmapHeight	: uint 	= bitmapData.height;
			var w				: int	= 0;
			var h				: int	= 0;

			if (downSample)
			{
				w = 1 << Math.floor(Math.log(bitmapWidth) * Math.LOG2E);
				h = 1 << Math.floor(Math.log(bitmapHeight) * Math.LOG2E);
			}
			else
			{
				w = 1 << Math.ceil(Math.log(bitmapWidth) * Math.LOG2E);
				h = 1 << Math.ceil(Math.log(bitmapHeight) * Math.LOG2E);
			}

			if (w > MAX_SIZE)
				w = MAX_SIZE;
			if (h > MAX_SIZE)
				h = MAX_SIZE;

			_bitmapData	= new BitmapData(w, h, bitmapData.transparent, 0);

			if (w != bitmapWidth || h != bitmapHeight)
			{
				TMP_MATRIX.identity();
				TMP_MATRIX.scale(w / bitmapWidth, h / bitmapHeight);
				_bitmapData.draw(bitmapData, TMP_MATRIX);
			}
			else
			{
				_bitmapData.draw(bitmapData);
			}

			if (_texture
				&& (mipmap != _mipmap
					|| bitmapData.width != _width
					|| bitmapData.height != _height))
			{
				_texture.dispose();
				_texture = null;
			}

			_width = _bitmapData.width;
			_height = _bitmapData.height;

			_mipmap	= mipmap;
			_update	= true;
		}

		public function setContentFromATF(atf : ByteArray) : void
		{
			_atf			= atf;
			_update 		= true;

			atf.position 	= 6;

			_atfFormat 		= atf.readUnsignedByte() & 3;
			_width 			= 1 << atf.readUnsignedByte();
			_height 		= 1 << atf.readUnsignedByte();
			_mipmap 		= atf.readUnsignedByte() > 1;

			atf.position 	= 0;
		}

		public function getNativeTexture(context : Context3D) : TextureBase
		{
			if ((!_texture || _resize) && _width && _height)
			{
				_resize = false;

				if (_texture)
					_texture.dispose();

				_texture = context.createTexture(
					_width,
					_height,
					_atf && _atfFormat == 2 ? FORMAT_COMPRESSED : FORMAT_BGRA,
					_bitmapData == null && _atf == null
				);

				_update = true;
			}

			if (_update)
			{
				_update = false;

				uploadTextureWithMipMaps();
			}

			_atf = null;
			_bitmapData = null;

			return _texture;
		}

		private function uploadTextureWithMipMaps() : void
		{
			if (_bitmapData)
			{
				if (_mipmap)
				{
					var level 		: int 			= 0;
					var size		: int 			= _width > _height ? _width : _height;
					var transparent	: Boolean		= _bitmapData.transparent;
					var transform 	: Matrix 		= new Matrix();
					var tmp 		: BitmapData 	= new BitmapData(
						size,
						size,
						transparent,
						0
					);

					while (size >= 1)
					{
						tmp.draw(_bitmapData, transform, null, null, null, true);
						_texture.uploadFromBitmapData(tmp, level);

						transform.scale(.5, .5);
						level++;
						size >>= 1;
						if (tmp.transparent)
							tmp.fillRect(tmp.rect, 0);
					}

					tmp.dispose();
				}
				else
				{
					_texture.uploadFromBitmapData(_bitmapData, 0);
				}

				_bitmapData.dispose();
			}
			else if (_atf)
			{
				_texture.uploadCompressedTextureFromByteArray(_atf, 0, false);
			}
		}

		public function dispose() : void
		{
			_texture.dispose();
			_texture = null;
		}
	}
}

Fix bugs in ATF texture support: - Proper initialization in setContentFromATF() - Proper texture format


package aerys.minko.render.shader.node.operation.manipulation
{
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractConstant;
	import aerys.minko.render.shader.node.leaf.Constant;
	import aerys.minko.render.shader.node.operation.AbstractOperation;
	import aerys.minko.render.shader.node.operation.builtin.Multiply;

	public class VariadicExtract extends AbstractOperation
	{
		private var _cellSize : uint;

		override public function get instructionName() : String
		{
			throw new Error('This is a virtual operand');
		}

		override public function get opCode() : uint
		{
			throw new Error('This is a virtual operand');
		}

		override public function get size() : uint
		{
			return _cellSize;
		}

		public function VariadicExtract(index		: INode,
										table		: AbstractConstant,
										cellSize	: uint)
		{
			_cellSize	= cellSize;

			var leftOperand : INode = index;
			if (cellSize != 4)
				leftOperand = new Multiply(
					leftOperand,
					new Constant(cellSize / 4)
				);

			var rightOperand : INode = table;

			super(leftOperand, rightOperand);

			if (cellSize % 4 != 0)	throw new Error();
			if (index.size != 1)	throw new Error();
		}

		override public function isSame(node : INode) : Boolean
		{
			var castedNode : VariadicExtract = node as VariadicExtract;

			return castedNode != null &&
				castedNode._arg1.isSame(_arg1) &&
				castedNode._arg2.isSame(_arg2) &&
				castedNode._cellSize == _cellSize;
		}
	}
}

package aerys.minko.render.shader.node.operation.manipulation
{
	import aerys.minko.render.shader.node.Components;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractConstant;
	import aerys.minko.render.shader.node.leaf.Constant;
	import aerys.minko.render.shader.node.operation.AbstractOperation;
	import aerys.minko.render.shader.node.operation.builtin.Multiply;

	public class VariadicExtract extends AbstractOperation
	{
		private var _cellSize : uint;

		override public function get instructionName() : String
		{
			throw new Error('This is a virtual operand');
		}

		override public function get opCode() : uint
		{
			throw new Error('This is a virtual operand');
		}

		override public function get size() : uint
		{
			return _cellSize;
		}

		public function VariadicExtract(index		: INode,
										table		: AbstractConstant,
										cellSize	: uint)
		{
			_cellSize	= cellSize;

			var leftOperand : INode = index;
			if (cellSize != 4)
			{
				leftOperand = new Multiply(leftOperand, new Constant(cellSize / 4));

				// the following is a patch to adobe's agal validator.
				// we have to fill a complete register for the index to work
				leftOperand = new RootWrapper(new Extract(leftOperand, Components.XXXX));
			}

			var rightOperand : INode = table;

			super(leftOperand, rightOperand);

			if (cellSize % 4 != 0)	throw new Error();
			if (index.size != 1)	throw new Error();
		}

		override public function isSame(node : INode) : Boolean
		{
			var castedNode : VariadicExtract = node as VariadicExtract;

			return castedNode != null &&
				castedNode._arg1.isSame(_arg1) &&
				castedNode._arg2.isSame(_arg2) &&
				castedNode._cellSize == _cellSize;
		}
	}
}

add a workaround for a bug from adobe during shader validation to do vc[ft0.x], ft0.yzw must be set, which makes no sense...


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.Effect;
	import aerys.minko.render.Viewport;
	import aerys.minko.scene.controller.scene.RenderingController;
	import aerys.minko.scene.node.camera.AbstractCamera;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.loader.AssetsLibrary;

	import flash.display.BitmapData;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * Scene objects are the root of any 3D scene.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class Scene extends Group
	{
		use namespace minko_scene;

		minko_scene var _camera		: AbstractCamera;

		private var _renderingCtrl	: RenderingController;

		private var _properties		: DataProvider;
		private var _bindings		: DataBindings;

		private var _numTriangles	: uint;

		private var _enterFrame			: Signal;
		private var _renderingBegin		: Signal;
		private var _renderingEnd		: Signal;
		private var _exitFrame			: Signal;

		private var _assets				: AssetsLibrary;

		public function get assets():AssetsLibrary
		{
			return _assets;
		}

		public function get activeCamera() : AbstractCamera
		{
			return _camera;
		}

		public function get numPasses() : uint
		{
			return _renderingCtrl.numPasses;
		}

		public function get numEnabledPasses() : uint
		{
			return _renderingCtrl.numEnabledPasses;
		}

		public function get numTriangles() : uint
		{
			return _numTriangles;
		}

		public function get postProcessingEffect() : Effect
		{
			return _renderingCtrl.postProcessingEffect;
		}
		public function set postProcessingEffect(value : Effect) : void
		{
			_renderingCtrl.postProcessingEffect = value;
		}

		public function get postProcessingProperties() : DataProvider
		{
			return _renderingCtrl.postProcessingProperties;
		}

		public function get properties() : DataProvider
		{
			return _properties;
		}
		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The signal executed when the viewport is about to start rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who starts rendering the frame

		 *

		 * @return
		 *
		 */
		public function get enterFrame() : Signal
		{
			return _enterFrame;
		}

		/**
		 * The signal executed when the viewport is done rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who just finished rendering the frame

		 *

		 * @return
		 *
		 */
		public function get exitFrame() : Signal
		{
			return _exitFrame;
		}

		public function get renderingBegin() : Signal
		{
			return _renderingBegin;
		}

		public function get renderingEnd() : Signal
		{
			return _renderingEnd;
		}

		public function Scene(...children)
		{
			super(children);
		}

		override protected function initialize() : void
		{
			_bindings 					= new DataBindings(this);
			_assets						= new AssetsLibrary();
			this.properties 			= new DataProvider(DataProviderUsage.EXCLUSIVE);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_enterFrame			= new Signal('Scene.enterFrame');
			_renderingBegin 	= new Signal('Scene.renderingBegin');
			_renderingEnd 		= new Signal('Scene.renderingEnd');
			_exitFrame 			= new Signal('Scene.exitFrame');
		}

		override protected function initializeSignalHandlers() : void
		{
			super.initializeSignalHandlers();

			added.add(addedHandler);
		}

		override protected function initializeContollers() : void
		{
			_renderingCtrl = new RenderingController();
			addController(_renderingCtrl);

			super.initializeContollers();
		}

		public function render(viewport : Viewport, destination : BitmapData = null) : void
		{
			_enterFrame.execute(this, viewport, destination, getTimer());
			if (viewport.ready && viewport.visible)
			{
				_renderingBegin.execute(this, viewport, destination, getTimer());
				_numTriangles = _renderingCtrl.render(viewport, destination);
				_renderingEnd.execute(this, viewport, destination, getTimer());
			}
			_exitFrame.execute(this, viewport, destination, getTimer());
		}

		private function addedHandler(child : ISceneNode, parent : Group) : void
		{
			throw new Error();
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.Effect;
	import aerys.minko.render.Viewport;
	import aerys.minko.scene.controller.scene.RenderingController;
	import aerys.minko.scene.node.camera.AbstractCamera;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.loader.AssetsLibrary;

	import flash.display.BitmapData;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * Scene objects are the root of any 3D scene.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class Scene extends Group
	{
		use namespace minko_scene;

		minko_scene var _camera		: AbstractCamera;

		private var _renderingCtrl	: RenderingController;

		private var _properties		: DataProvider;
		private var _bindings		: DataBindings;

		private var _numTriangles	: uint;

		private var _enterFrame		: Signal;
		private var _renderingBegin	: Signal;
		private var _renderingEnd	: Signal;
		private var _exitFrame		: Signal;

		private var _assets				: AssetsLibrary;

		public function get assets() : AssetsLibrary
		{
			return _assets;
		}

		public function get activeCamera() : AbstractCamera
		{
			return _camera;
		}

		public function get numPasses() : uint
		{
			return _renderingCtrl.numPasses;
		}

		public function get numEnabledPasses() : uint
		{
			return _renderingCtrl.numEnabledPasses;
		}

		public function get numTriangles() : uint
		{
			return _numTriangles;
		}

		public function get postProcessingEffect() : Effect
		{
			return _renderingCtrl.postProcessingEffect;
		}
		public function set postProcessingEffect(value : Effect) : void
		{
			_renderingCtrl.postProcessingEffect = value;
		}

		public function get postProcessingProperties() : DataProvider
		{
			return _renderingCtrl.postProcessingProperties;
		}

		public function get properties() : DataProvider
		{
			return _properties;
		}
		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The signal executed when the viewport is about to start rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who starts rendering the frame

		 *

		 * @return
		 *
		 */
		public function get enterFrame() : Signal
		{
			return _enterFrame;
		}

		/**
		 * The signal executed when the viewport is done rendering a frame.
		 * Callback functions for this signal should accept the following arguments:
		 *

		 *
viewport : Viewport, the viewport who just finished rendering the frame

		 *

		 * @return
		 *
		 */
		public function get exitFrame() : Signal
		{
			return _exitFrame;
		}

		public function get renderingBegin() : Signal
		{
			return _renderingBegin;
		}

		public function get renderingEnd() : Signal
		{
			return _renderingEnd;
		}

		public function Scene(...children)
		{
			super(children);
		}

		override protected function initialize() : void
		{
			_bindings 					= new DataBindings(this);
			_assets						= new AssetsLibrary();
			this.properties 			= new DataProvider(DataProviderUsage.EXCLUSIVE);

			super.initialize();
		}

		override protected function initializeSignals() : void
		{
			super.initializeSignals();

			_enterFrame			= new Signal('Scene.enterFrame');
			_renderingBegin 	= new Signal('Scene.renderingBegin');
			_renderingEnd 		= new Signal('Scene.renderingEnd');
			_exitFrame 			= new Signal('Scene.exitFrame');
		}

		override protected function initializeSignalHandlers() : void
		{
			super.initializeSignalHandlers();

			added.add(addedHandler);
		}

		override protected function initializeContollers() : void
		{
			_renderingCtrl = new RenderingController();
			addController(_renderingCtrl);

			super.initializeContollers();
		}

		public function render(viewport : Viewport, destination : BitmapData = null) : void
		{
			_enterFrame.execute(this, viewport, destination, getTimer());
			if (viewport.ready && viewport.visible)
			{
				_renderingBegin.execute(this, viewport, destination, getTimer());
				_numTriangles = _renderingCtrl.render(viewport, destination);
				_renderingEnd.execute(this, viewport, destination, getTimer());
			}
			_exitFrame.execute(this, viewport, destination, getTimer());
		}

		private function addedHandler(child : ISceneNode, parent : Group) : void
		{
			throw new Error();
		}
	}
}

fix coding style

fix coding style


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IBeadModel;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.geom.Rectangle;
	import org.apache.flex.utils.dbg.DOMPathUtil;
    import org.apache.flex.utils.CSSContainerUtils;

    /**
     *  The HorizontalLayout class is a simple layout
     *  bead.  It takes the set of children and lays them out
     *  horizontally in one row, separating them according to
     *  CSS layout rules for margin and vertical-align styles.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class HorizontalLayout implements IBeadLayout
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function HorizontalLayout()
		{
		}

        // the strand/host container is also an ILayoutChild because
        // can have its size dictated by the host's parent which is
        // important to know for layout optimization
		private var host:ILayoutChild;

        /**
         *  @copy org.apache.flex.core.IBead#strand
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function set strand(value:IStrand):void
		{
			host = value as ILayoutChild;
		}

        /**
         * @copy org.apache.flex.core.IBeadLayout#layout
         */
		public function layout():Boolean
		{
            //trace(DOMPathUtil.getPath(host), event ? event.type : "fixed size");
			var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
			var contentView:IParentIUIBase = layoutParent.contentView;
            var padding:Rectangle = CSSContainerUtils.getPaddingMetrics(host);

			var n:int = contentView.numElements;
            var hostSizedToContent:Boolean = host.isHeightSizedToContent();
            var ilc:ILayoutChild;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			var maxHeight:Number = 0;
            // asking for contentView.width can result in infinite loop if host isn't sized already
            var h:Number = hostSizedToContent ? 0 : contentView.height;
			var verticalMargins:Array = [];

			for (var i:int = 0; i < n; i++)
			{
				var child:IUIBase = contentView.getElementAt(i) as IUIBase;
				if (child == null || !child.visible) continue;
                var top:Number = ValuesManager.valuesImpl.getValue(child, "top");
                var bottom:Number = ValuesManager.valuesImpl.getValue(child, "bottom");
                ilc = child as ILayoutChild;
				margin = ValuesManager.valuesImpl.getValue(child, "margin");
				if (margin is Array)
				{
					if (margin.length == 1)
						marginLeft = marginTop = marginRight = marginBottom = margin[0];
					else if (margin.length <= 3)
					{
						marginLeft = marginRight = margin[1];
						marginTop = marginBottom = margin[0];
					}
					else if (margin.length == 4)
					{
						marginLeft = margin[3];
						marginBottom = margin[2];
						marginRight = margin[1];
						marginTop = margin[0];
					}
				}
				else if (margin == null)
				{
					marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
					marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
					marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
					marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
				}
				else
				{
					marginLeft = marginTop = marginBottom = marginRight = margin;
				}
				var ml:Number;
				var mr:Number;
				var mt:Number;
				var mb:Number;
				var lastmr:Number;
				if (marginLeft == "auto")
					ml = 0;
				else
				{
					ml = Number(marginLeft);
					if (isNaN(ml))
						ml = 0;
				}
				if (marginRight == "auto")
					mr = 0;
				else
				{
					mr = Number(marginRight);
					if (isNaN(mr))
						mr = 0;
				}
				mt = Number(marginTop);
				if (isNaN(mt))
					mt = 0;
				mb = Number(marginBottom);
				if (isNaN(mb))
					mb = 0;
                var xx:Number;
                if (i == 0)
                {
                    if (ilc)
                        ilc.setX(ml + padding.left);
                    else
                        child.x = ml + padding.left;
                }
                else
                {
                    if (ilc)
                        ilc.setX(xx + ml + lastmr);
                    else
                        child.x = xx + ml + lastmr;
                }
                if (ilc)
                {
                    if (!isNaN(ilc.percentWidth))
                        ilc.setWidth(contentView.width * ilc.percentWidth / 100, !isNaN(ilc.percentHeight));
                }
                lastmr = mr;
                var marginObject:Object = {};
                verticalMargins[i] = marginObject;
                if (!hostSizedToContent)
                {
                    // if host is sized by parent,
                    // we can position and size children horizontally now
                    setPositionAndHeight(child, top, mt, padding.top, bottom, mb, padding.bottom, h);
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                }
                else
                {
                    if (!isNaN(top))
                    {
                        mt = top;
                        marginObject.top = mt;
                    }
                    if (!isNaN(bottom))
                    {
                        mb = bottom;
                        marginObject.bottom = mb;
                    }
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                }
				xx = child.x + child.width;
				var valign:* = ValuesManager.valuesImpl.getValue(child, "vertical-align");
				marginObject.valign = valign;
			}
            if (hostSizedToContent)
            {
                ILayoutChild(contentView).setHeight(maxHeight, true);
                if (host.isWidthSizedToContent())
                    ILayoutChild(contentView).setWidth(xx, true);
                for (i = 0; i < n; i++)
                {
                    child = contentView.getElementAt(i) as IUIBase;
                    if (child == null || !child.visible) continue;
                    var obj:Object = verticalMargins[i];
                    setPositionAndHeight(child, obj.top, obj.marginTop, padding.top,
                        obj.bottom, obj.marginBottom, padding.bottom, maxHeight);
                }
            }
			for (i = 0; i < n; i++)
			{
				child = contentView.getElementAt(i) as IUIBase;
                ilc = child as ILayoutChild;
				if (child == null || !child.visible) continue;
                obj = verticalMargins[i];
                if (ilc)
                {
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, !isNaN(ilc.percentHeight));
                }
                if (ilc)
                {
    				if (obj.valign == "top")
                        ilc.setY(obj.marginTop + padding.top);
    				else if (valign == "bottom")
                        ilc.setY(maxHeight - child.height - obj.marginBottom);
    				else // TODO: aharui - baseline
                        ilc.setY((maxHeight - child.height) / 2);
                }
                else
                {
                    if (obj.valign == "top")
                        child.y = obj.marginTop + padding.top;
                    else if (valign == "bottom")
                        child.y = maxHeight - child.height - obj.marginBottom;
                    else // TODO: aharui - baseline
                        child.y = (maxHeight - child.height) / 2;
                }
			}

			// Only return true if the contentView needs to be larger; that new
			// size is stored in the model.
			var sizeChanged:Boolean = true;

			host.dispatchEvent( new Event("layoutComplete") );

			return sizeChanged;
		}

        private function setPositionAndHeight(child:IUIBase, top:Number, mt:Number, pt:Number,
                                             bottom:Number, mb:Number, pb:Number, h:Number):void
        {
            var heightSet:Boolean = false;

            var hh:Number = h;
            var ilc:ILayoutChild = child as ILayoutChild;
            if (!isNaN(top))
            {
                if (ilc)
                    ilc.setY(top + mt);
                else
                    child.y = top + mt;
                hh -= top + mt;
            }
            else
            {
                if (ilc)
                    ilc.setY(mt + pt);
                else
                    child.y = mt + pt;
                hh -= mt + pt;
            }
            if (!isNaN(bottom))
            {
                if (!isNaN(top))
                {
                    if (ilc)
                        ilc.setHeight(hh - bottom - mb, true);
                    else
                    {
                        child.height = hh - bottom - mb;
                        heightSet = true;
                    }
                }
                else
                {
                    if (ilc)
                        ilc.setY(h - bottom - mb - child.height);
                    else
                        child.y = h - bottom - mb - child.height;
                }
            }
            if (ilc)
            {
                if (!isNaN(ilc.percentHeight))
                    ilc.setHeight(h * ilc.percentHeight / 100, true);
            }
            if (!heightSet)
                child.dispatchEvent(new Event("sizeChanged"));
        }
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.html.beads.layouts
{
	import org.apache.flex.core.IBeadLayout;
	import org.apache.flex.core.IBeadModel;
	import org.apache.flex.core.ILayoutChild;
	import org.apache.flex.core.ILayoutParent;
	import org.apache.flex.core.IParentIUIBase;
	import org.apache.flex.core.IStrand;
	import org.apache.flex.core.IUIBase;
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.events.IEventDispatcher;
	import org.apache.flex.geom.Rectangle;
	import org.apache.flex.utils.dbg.DOMPathUtil;
    import org.apache.flex.utils.CSSUtils;
    import org.apache.flex.utils.CSSContainerUtils;

    /**
     *  The HorizontalLayout class is a simple layout
     *  bead.  It takes the set of children and lays them out
     *  horizontally in one row, separating them according to
     *  CSS layout rules for margin and vertical-align styles.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class HorizontalLayout implements IBeadLayout
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function HorizontalLayout()
		{
		}

        // the strand/host container is also an ILayoutChild because
        // can have its size dictated by the host's parent which is
        // important to know for layout optimization
		private var host:ILayoutChild;

        /**
         *  @copy org.apache.flex.core.IBead#strand
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function set strand(value:IStrand):void
		{
			host = value as ILayoutChild;
		}

        /**
         * @copy org.apache.flex.core.IBeadLayout#layout
         */
		public function layout():Boolean
		{
            //trace(DOMPathUtil.getPath(host), event ? event.type : "fixed size");
			var layoutParent:ILayoutParent = host.getBeadByType(ILayoutParent) as ILayoutParent;
			var contentView:IParentIUIBase = layoutParent.contentView;
            var padding:Rectangle = CSSContainerUtils.getPaddingMetrics(host);

			var n:int = contentView.numElements;
            var hostSizedToContent:Boolean = host.isHeightSizedToContent();
            var ilc:ILayoutChild;
			var marginLeft:Object;
			var marginRight:Object;
			var marginTop:Object;
			var marginBottom:Object;
			var margin:Object;
			var maxHeight:Number = 0;
            // asking for contentView.height can result in infinite loop if host isn't sized already
            var h:Number = hostSizedToContent ? 0 : contentView.height;
            var w:Number = contentView.width;
			var verticalMargins:Array = [];

			for (var i:int = 0; i < n; i++)
			{
				var child:IUIBase = contentView.getElementAt(i) as IUIBase;
				if (child == null || !child.visible) continue;
                var top:Number = ValuesManager.valuesImpl.getValue(child, "top");
                var bottom:Number = ValuesManager.valuesImpl.getValue(child, "bottom");
                margin = ValuesManager.valuesImpl.getValue(child, "margin");
                marginLeft = ValuesManager.valuesImpl.getValue(child, "margin-left");
                marginTop = ValuesManager.valuesImpl.getValue(child, "margin-top");
                marginRight = ValuesManager.valuesImpl.getValue(child, "margin-right");
                marginBottom = ValuesManager.valuesImpl.getValue(child, "margin-bottom");
                var ml:Number = CSSUtils.getLeftValue(marginLeft, margin, w);
                var mr:Number = CSSUtils.getRightValue(marginRight, margin, w);
                var mt:Number = CSSUtils.getTopValue(marginTop, margin, h);
                var mb:Number = CSSUtils.getBottomValue(marginBottom, margin, h);

                ilc = child as ILayoutChild;
				var lastmr:Number;
				if (marginLeft == "auto")
					ml = 0;
				if (marginRight == "auto")
					mr = 0;
                var xx:Number;
                if (i == 0)
                {
                    if (ilc)
                        ilc.setX(ml + padding.left);
                    else
                        child.x = ml + padding.left;
                }
                else
                {
                    if (ilc)
                        ilc.setX(xx + ml + lastmr);
                    else
                        child.x = xx + ml + lastmr;
                }
                if (ilc)
                {
                    if (!isNaN(ilc.percentWidth))
                        ilc.setWidth(contentView.width * ilc.percentWidth / 100, !isNaN(ilc.percentHeight));
                }
                lastmr = mr;
                var marginObject:Object = {};
                verticalMargins[i] = marginObject;
                if (!hostSizedToContent)
                {
                    // if host is sized by parent,
                    // we can position and size children horizontally now
                    setPositionAndHeight(child, top, mt, padding.top, bottom, mb, padding.bottom, h);
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                }
                else
                {
                    if (!isNaN(top))
                    {
                        mt = top;
                        marginObject.top = mt;
                    }
                    if (!isNaN(bottom))
                    {
                        mb = bottom;
                        marginObject.bottom = mb;
                    }
                    maxHeight = Math.max(maxHeight, mt + child.height + mb);
                }
				xx = child.x + child.width;
				var valign:* = ValuesManager.valuesImpl.getValue(child, "vertical-align");
				marginObject.valign = valign;
			}
            if (hostSizedToContent)
            {
                ILayoutChild(contentView).setHeight(maxHeight, true);
                if (host.isWidthSizedToContent())
                    ILayoutChild(contentView).setWidth(xx, true);
                for (i = 0; i < n; i++)
                {
                    child = contentView.getElementAt(i) as IUIBase;
                    if (child == null || !child.visible) continue;
                    var obj:Object = verticalMargins[i];
                    setPositionAndHeight(child, obj.top, obj.marginTop, padding.top,
                        obj.bottom, obj.marginBottom, padding.bottom, maxHeight);
                }
            }
			for (i = 0; i < n; i++)
			{
				child = contentView.getElementAt(i) as IUIBase;
                ilc = child as ILayoutChild;
				if (child == null || !child.visible) continue;
                obj = verticalMargins[i];
                if (ilc)
                {
                    if (!isNaN(ilc.percentHeight))
                        ilc.setHeight(contentView.height * ilc.percentHeight / 100, !isNaN(ilc.percentHeight));
                }
                if (ilc)
                {
    				if (obj.valign == "top")
                        ilc.setY(obj.marginTop + padding.top);
    				else if (valign == "bottom")
                        ilc.setY(maxHeight - child.height - obj.marginBottom);
    				else // TODO: aharui - baseline
                        ilc.setY((maxHeight - child.height) / 2);
                }
                else
                {
                    if (obj.valign == "top")
                        child.y = obj.marginTop + padding.top;
                    else if (valign == "bottom")
                        child.y = maxHeight - child.height - obj.marginBottom;
                    else // TODO: aharui - baseline
                        child.y = (maxHeight - child.height) / 2;
                }
			}

			// Only return true if the contentView needs to be larger; that new
			// size is stored in the model.
			var sizeChanged:Boolean = true;

			host.dispatchEvent( new Event("layoutComplete") );

			return sizeChanged;
		}

        private function setPositionAndHeight(child:IUIBase, top:Number, mt:Number, pt:Number,
                                             bottom:Number, mb:Number, pb:Number, h:Number):void
        {
            var heightSet:Boolean = false;

            var hh:Number = h;
            var ilc:ILayoutChild = child as ILayoutChild;
            if (!isNaN(top))
            {
                if (ilc)
                    ilc.setY(top + mt);
                else
                    child.y = top + mt;
                hh -= top + mt;
            }
            else
            {
                if (ilc)
                    ilc.setY(mt + pt);
                else
                    child.y = mt + pt;
                hh -= mt + pt;
            }
            if (!isNaN(bottom))
            {
                if (!isNaN(top))
                {
                    if (ilc)
                        ilc.setHeight(hh - bottom - mb, true);
                    else
                    {
                        child.height = hh - bottom - mb;
                        heightSet = true;
                    }
                }
                else
                {
                    if (ilc)
                        ilc.setY(h - bottom - mb - child.height);
                    else
                        child.y = h - bottom - mb - child.height;
                }
            }
            if (ilc)
            {
                if (!isNaN(ilc.percentHeight))
                    ilc.setHeight(h * ilc.percentHeight / 100, true);
            }
            if (!heightSet)
                child.dispatchEvent(new Event("sizeChanged"));
        }
	}
}

fix margin handling

fix margin handling


package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;

    public class swfcat extends Sprite
    {
        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };

        private var output_text:TextField;

        // Socket to facilitator.
        private var s_f:Socket;

        private var fac_addr:Object;

        public function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;
            var tor_spec:String;

            puts("Parameters loaded.");
            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (!fac_spec) {
                puts("Error: no \"facilitator\" specification provided.");
                return;
            }
            puts("Facilitator spec: \"" + fac_spec + "\"");
            fac_addr = parse_addr_spec(fac_spec);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            go();
        }

        private function go():void
        {
            s_f = new Socket();

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\"");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;

    public class swfcat extends Sprite
    {
        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };

        private var output_text:TextField;

        // Socket to facilitator.
        private var s_f:Socket;

        private var fac_addr:Object;

        public function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;
            var tor_spec:String;

            puts("Parameters loaded.");
            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (!fac_spec) {
                puts("Error: no \"facilitator\" specification provided.");
                return;
            }
            puts("Facilitator spec: \"" + fac_spec + "\"");
            fac_addr = parse_addr_spec(fac_spec);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            main();
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function main():void
        {
            s_f = new Socket();

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\"");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

Change the name of function "go" to "main".


package aerys.minko.render.material.realistic
{
	import aerys.minko.render.Effect;
	import aerys.minko.render.material.environment.EnvironmentMappingProperties;
	import aerys.minko.render.material.phong.PhongMaterial;
	import aerys.minko.render.resource.texture.ITextureResource;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.type.binding.IDataProvider;

	import flash.utils.Dictionary;

	public class RealisticMaterial extends PhongMaterial
	{
		private static const DEFAULT_NAME		: String		= 'RealisticMaterial';
		private static const SCENE_TO_EFFECT	: Dictionary	= new Dictionary(true);

		public function get environmentMap() : ITextureResource
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP) as ITextureResource;
		}
		public function set environmentMap(value : ITextureResource) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP, value);
		}

		public function get reflectivity() : Number
		{
			return getProperty(EnvironmentMappingProperties.REFLECTIVITY) as Number;
		}
		public function set reflectivity(value : Number) : void
		{
			setProperty(EnvironmentMappingProperties.REFLECTIVITY, value);
		}

		public function get environmentMappingType() : uint
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE) as uint;
		}
		public function set environmentMappingType(value : uint) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE, value);
		}

		public function get environmentBlending() : uint
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING) as uint;
		}
		public function set environmentBlending(value : uint) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING, value);
		}

		public function RealisticMaterial(scene			: Scene,
										  properties	: Object	= null,
										  effect		: Effect	= null,
										  name			: String	= DEFAULT_NAME)
		{
			effect ||= SCENE_TO_EFFECT[scene] || (SCENE_TO_EFFECT[scene] = new RealisticEffect(scene));

			super(scene, properties, effect, name);
		}

        override public function clone() : IDataProvider
        {
            return new RealisticMaterial((effect as RealisticEffect).scene, this, effect, name);
        }
	}
}

package aerys.minko.render.material.realistic
{
	import aerys.minko.render.Effect;
	import aerys.minko.render.material.environment.EnvironmentMappingProperties;
	import aerys.minko.render.material.phong.PhongMaterial;
	import aerys.minko.render.resource.texture.ITextureResource;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.type.binding.IDataProvider;

	import flash.utils.Dictionary;

	public class RealisticMaterial extends PhongMaterial
	{
		private static const DEFAULT_NAME		: String		= 'RealisticMaterial';
		private static const SCENE_TO_EFFECT	: Dictionary	= new Dictionary(true);

		public function get environmentMap() : ITextureResource
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP) as ITextureResource;
		}
		public function set environmentMap(value : ITextureResource) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP, value);
		}

        public function get environmentMapFiltering() : uint
        {
            return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FILTERING);
        }
        public function set environmentMapFiltering(value : uint) : void
        {
            setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FILTERING, value);
        }

        public function get environmentMapMipMapping() : uint
        {
            return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_MIPMAPPING);
        }
        public function set environmentMapMipMapping(value : uint) : void
        {
            setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_MIPMAPPING, value);
        }

        public function get environmentMapWrapping() : uint
        {
            return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_WRAPPING);
        }
        public function set environmentMapWrapping(value : uint) : void
        {
            setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_WRAPPING, value);
        }

        public function get environmentMapFormat() : uint
        {
            return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FORMAT);
        }
        public function set environmentMapFormat(value : uint) : void
        {
            setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FORMAT, value);
        }

		public function get reflectivity() : Number
		{
			return getProperty(EnvironmentMappingProperties.REFLECTIVITY) as Number;
		}
		public function set reflectivity(value : Number) : void
		{
			setProperty(EnvironmentMappingProperties.REFLECTIVITY, value);
		}

		public function get environmentMappingType() : uint
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE) as uint;
		}
		public function set environmentMappingType(value : uint) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE, value);
		}

		public function get environmentBlending() : uint
		{
			return getProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING) as uint;
		}
		public function set environmentBlending(value : uint) : void
		{
			setProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING, value);
		}

		public function RealisticMaterial(scene			: Scene,
										  properties	: Object	= null,
										  effect		: Effect	= null,
										  name			: String	= DEFAULT_NAME)
		{
			effect ||= SCENE_TO_EFFECT[scene] || (SCENE_TO_EFFECT[scene] = new RealisticEffect(scene));

			super(scene, properties, effect, name);
		}

        override public function clone() : IDataProvider
        {
            return new RealisticMaterial((effect as RealisticEffect).scene, this, effect, name);
        }
	}
}

add filtering, mipMapping, wrapping and format properties for the environment map to RealisticMaterial


package aerys.minko.scene.controller.debug
{
	import aerys.minko.render.geometry.primitive.CubeGeometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.skinning.SkinningController;
	import aerys.minko.scene.node.Group;
	import aerys.minko.scene.node.Mesh;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.math.Vector4;

	import flash.utils.Dictionary;

	public final class BonesDebugController extends AbstractController
	{
		private var _bonesThickness		: Number;
		private var _material   		: Material;
		private var _targetToBonesMesh	: Dictionary = new Dictionary();

		public function BonesDebugController(bonesThickness	: Number	= 0.02,
											 bonesMaterial 	: Material 	= null)
		{
			super(Mesh);

			initialize(bonesThickness, bonesMaterial);
		}

		private function initialize(bonesThickness : Number, bonesMaterial : Material) : void
		{
			_bonesThickness = bonesThickness;
			_material = bonesMaterial;

			if (!_material)
			{
				var bonesBasicMaterial : BasicMaterial = new BasicMaterial();

				bonesBasicMaterial.diffuseColor = 0x00ff00ff;
				bonesBasicMaterial.depthWriteEnabled = false;
				bonesBasicMaterial.depthTest = DepthTest.ALWAYS;
				_material = bonesBasicMaterial;
			}

			targetAdded.add(targetAddedHandler);
			targetRemoved.add(targetRemovedHandler);
		}

		private function targetAddedHandler(ctrl	: AbstractController,
											target	: Mesh) : void
		{
			var skinningCtrl : SkinningController = target.getControllersByType(SkinningController)[0]
				as SkinningController;

			_targetToBonesMesh[target] = [];

			for each (var joint : Group in skinningCtrl.joints)
				addBonesMeshes(joint, target);
		}

		private function targetRemovedHandler(ctrl 		: AbstractController,
											  target	: Mesh) : void
		{
			var skinningCtrl : SkinningController = target.getControllersByType(SkinningController)[0]
				as SkinningController;

			for each (var boneMesh : Mesh in _targetToBonesMesh[target])
				boneMesh.parent = null;

			delete _targetToBonesMesh[target];
		}

		private function addBonesMeshes(joint 	: Group,
										target 	: Mesh) : void
		{
			if (joint.getChildByName('__bone__'))
				return ;

			var numChildren : uint = joint.numChildren;

			for (var i : uint = 0; i < numChildren; ++i)
			{
				var child : Group = joint.getChildAt(i) as Group;

				if (child != null)
				{
					var nextJointPosition 	: Vector4 	= child.transform.transformVector(
						Vector4.ZERO
					);
					var boneLength 			: Number 	= nextJointPosition.length;

					if (boneLength != 0.)
					{
						var boneMesh : Mesh = new Mesh(
							CubeGeometry.cubeGeometry, _material, '__bone__'
						);

						boneMesh.transform
							.lookAt(nextJointPosition)
							.prependTranslation(0, 0, boneLength * .5)
							.prependScale(_bonesThickness, _bonesThickness, boneLength);

						joint.addChild(boneMesh);
						_targetToBonesMesh[target].push(boneMesh);
					}
				}
			}
		}
	}
}

package aerys.minko.scene.controller.debug
{
	import flash.utils.Dictionary;

	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.Effect;
	import aerys.minko.render.geometry.primitive.CubeGeometry;
	import aerys.minko.render.geometry.primitive.LineGeometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.render.material.line.LineMaterial;
	import aerys.minko.render.material.line.LineShader;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.skinning.SkinningController;
	import aerys.minko.scene.node.Group;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.scene.node.Mesh;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.enum.TriangleCulling;
	import aerys.minko.type.math.Vector4;

	public final class BonesDebugController extends AbstractController
	{
		private var _bonesThickness		: Number;
		private var _material   		: LineMaterial;
		private var _targetToBonesMesh	: Dictionary = new Dictionary();
		private var _numExtraDescendant	: uint 		 = 0;

		public function BonesDebugController(bonesThickness		: Number		= 0.02,
											 bonesMaterial 		: LineMaterial 	= null,
											 numExtraDescendant	: uint 			= 0)
		{
			super(Mesh);

			_numExtraDescendant = numExtraDescendant;
			initialize(bonesThickness, bonesMaterial);
		}

		private function initialize(bonesThickness : Number, bonesMaterial : LineMaterial) : void
		{
			_bonesThickness = bonesThickness;
			_material = bonesMaterial;

			if (!_material)
			{
				var bonesBasicMaterial : LineMaterial = new LineMaterial();

				bonesBasicMaterial.effect = new Effect(new LineShader(null, -Number.MAX_VALUE));
				bonesBasicMaterial.diffuseColor = 0xffe400ff;
				bonesBasicMaterial.setProperty('depthWriteEnabled', false);
				bonesBasicMaterial.setProperty('depthTest', DepthTest.ALWAYS);
				bonesBasicMaterial.setProperty('triangleCulling', TriangleCulling.NONE);
				_material = bonesBasicMaterial;
			}

			targetAdded.add(targetAddedHandler);
			targetRemoved.add(targetRemovedHandler);
		}

		private function targetAddedHandler(ctrl	: AbstractController,
											target	: Mesh) : void
		{
			var skinningCtrl : SkinningController = target.getControllersByType(SkinningController)[0]
				as SkinningController;

			_targetToBonesMesh[target] = [];

			for each (var joint : Group in skinningCtrl.joints)
				addBonesMeshes(joint, target);
		}

		private function targetRemovedHandler(ctrl 		: AbstractController,
											  target	: Mesh) : void
		{
			var skinningCtrl : SkinningController = target.getControllersByType(SkinningController)[0]
				as SkinningController;

			for each (var boneMesh : Mesh in _targetToBonesMesh[target])
				boneMesh.parent = null;

			delete _targetToBonesMesh[target];
		}

		private function addBonesMeshes(joint 	: Group,
										target 	: Mesh) : void
		{
			if (joint.getChildByName('__bone__'))
				return ;

			var numChildren : uint = joint.numChildren;

			for (var i : uint = 0; i < numChildren; ++i)
			{
				var child : ISceneNode = joint.getChildAt(i);

				if (child != null)
				{
					for (var extraDescendantCount : uint = 0; extraDescendantCount < _numExtraDescendant && child is Group; ++extraDescendantCount)
						child = Group(child).minko_scene::_children[0] as ISceneNode;

					var nextJointPosition 	: Vector4 	= child.transform.transformVector(
						Vector4.ZERO
					);
					var boneLength 			: Number 	= nextJointPosition.length;

					if (boneLength != 0.)
					{
						var lineGeometry : LineGeometry = new LineGeometry();
						var boneMesh : Mesh = new Mesh(
							lineGeometry, _material, '__bone__'
						);

//						boneMesh.transform
//							.lookAt(nextJointPosition)
//							.prependTranslation(0, 0, boneLength * .5)
//							.prependScale(_bonesThickness, _bonesThickness, boneLength);
//
						lineGeometry.moveTo(0, 0, 0).lineTo(nextJointPosition.x, nextJointPosition.y, nextJointPosition.z);
						joint.addChild(boneMesh);
						_targetToBonesMesh[target].push(boneMesh);
					}
				}
			}
		}
	}
}

Use LineShader to display bones

Use LineShader to display bones